From 129d9ad045d57c59db87515e9fd785575f9b1a73 Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Sun, 29 Oct 2023 13:19:31 -0600 Subject: [PATCH 001/125] Bump up version to 8.3.0 Change-Id: I46eab9d7076fefa7fcb162ef023327b73eb3ee5d --- CHANGES | 3 +++ .../templates/custom/partials/class.header.tmpl.partial | 2 +- EFCore/Directory.Build.targets | 6 +++--- EntityFramework/src/MySql.Data.EntityFramework.csproj | 2 +- .../MySql.EntityFramework.Basic.Tests.csproj | 2 +- .../MySql.EntityFramework.CodeFirst.Tests.csproj | 2 +- .../MySql.EntityFramework.Migrations.Tests.csproj | 2 +- .../src/MySQL.Data.OpenTelemetry.csproj | 2 +- MySQL.Data/src/MySql.Data.csproj | 4 ++-- MySQL.Data/src/Properties/VersionInfo.cs | 4 ++-- MySQL.Data/tests/MySql.Data.Tests/MySql.Data.Tests.csproj | 2 +- MySQL.Data/tests/MySqlX.Data.Tests/MySqlX.Data.Tests.csproj | 2 +- MySql.Web/src/MySql.Web.csproj | 2 +- MySql.Web/tests/MySql.Web.Tests.csproj | 2 +- 14 files changed, 20 insertions(+), 17 deletions(-) diff --git a/CHANGES b/CHANGES index cf700e975..7775ba662 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,6 @@ +8.3.0 + + 8.2.0 - Migrated installer to Wix 4.0 (WL15847). - Fixed bug Opening two MySqlConnections simultaneously can crash (Oracle Bug #35307501). diff --git a/Documentation/templates/custom/partials/class.header.tmpl.partial b/Documentation/templates/custom/partials/class.header.tmpl.partial index 9a663a1e5..362f24e4a 100644 --- a/Documentation/templates/custom/partials/class.header.tmpl.partial +++ b/Documentation/templates/custom/partials/class.header.tmpl.partial @@ -25,7 +25,7 @@ {{/implements.0}}
{{__global.namespace}}: {{{namespace.specName.0.value}}}
{{__global.assembly}}: {{assemblies.0}}.dll
-
Version: 8.2.0
+
Version: 8.3.0
{{__global.syntax}}
{{syntax.content.0.value}}
diff --git a/EFCore/Directory.Build.targets b/EFCore/Directory.Build.targets index 08bf7e756..dd451dfa5 100644 --- a/EFCore/Directory.Build.targets +++ b/EFCore/Directory.Build.targets @@ -1,16 +1,16 @@ Copyright (c) 2021, 2023, Oracle and/or its affiliates. - 6.0.21+MySQL8.2.0 + 6.0.21+MySQL8.3.0 Copyright (c) 2022, 2023, Oracle and/or its affiliates. - 7.0.10+MySQL8.2.0 + 7.0.10+MySQL8.3.0 Copyright (c) 2023, Oracle and/or its affiliates. - 8.0.0-preview+MySQL8.2.0 + 8.0.0-preview+MySQL8.3.0 \ No newline at end of file diff --git a/EntityFramework/src/MySql.Data.EntityFramework.csproj b/EntityFramework/src/MySql.Data.EntityFramework.csproj index 3ad54520c..14ebe116f 100644 --- a/EntityFramework/src/MySql.Data.EntityFramework.csproj +++ b/EntityFramework/src/MySql.Data.EntityFramework.csproj @@ -4,7 +4,7 @@ MySql.Data.EntityFramework Copyright (c) 2016, 2023, Oracle and/or its affiliates. en-US - 8.2.0 + 8.3.0 Oracle net462;netstandard2.1; $(NoWarn);CS1591 diff --git a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/MySql.EntityFramework.Basic.Tests.csproj b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/MySql.EntityFramework.Basic.Tests.csproj index fa40e0500..1d1574764 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/MySql.EntityFramework.Basic.Tests.csproj +++ b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/MySql.EntityFramework.Basic.Tests.csproj @@ -4,7 +4,7 @@ MySql.Data.EntityFramework.CodeFirTests Copyright (c) 2016, 2023, Oracle and/or its affiliates. en-US - 8.2.0 + 8.3.0 Oracle net7.0 MySql.EntityFramework.Basic.Tests diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/MySql.EntityFramework.CodeFirst.Tests.csproj b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/MySql.EntityFramework.CodeFirst.Tests.csproj index 394433997..7f7c1c2be 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/MySql.EntityFramework.CodeFirst.Tests.csproj +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/MySql.EntityFramework.CodeFirst.Tests.csproj @@ -4,7 +4,7 @@ MySql.Data.EntityFramework.CodeFirst.Tests Copyright (c) 2016, 2023, Oracle and/or its affiliates. en-US - 8.2.0 + 8.3.0 Oracle net7.0 MySql.EntityFramework.CodeFirst.Tests diff --git a/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/MySql.EntityFramework.Migrations.Tests.csproj b/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/MySql.EntityFramework.Migrations.Tests.csproj index 8be578e10..8912bf929 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/MySql.EntityFramework.Migrations.Tests.csproj +++ b/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/MySql.EntityFramework.Migrations.Tests.csproj @@ -4,7 +4,7 @@ MySql.Data.EntityFramework.Migrations.Tests Copyright (c) 2016, 2023, Oracle and/or its affiliates. en-US - 8.2.0 + 8.3.0 Oracle net7.0 MySql.EntityFramework.Migrations.Tests diff --git a/MySQL.Data.OpenTelemetry/src/MySQL.Data.OpenTelemetry.csproj b/MySQL.Data.OpenTelemetry/src/MySQL.Data.OpenTelemetry.csproj index 1d144fae4..1536f4d84 100644 --- a/MySQL.Data.OpenTelemetry/src/MySQL.Data.OpenTelemetry.csproj +++ b/MySQL.Data.OpenTelemetry/src/MySQL.Data.OpenTelemetry.csproj @@ -4,7 +4,7 @@ MySql.Data.OpenTelemetry Copyright (c) 2023, Oracle and/or its affiliates. en-US - 8.2.0 + 8.3.0 Oracle netstandard2.0 MySql.Data.OpenTelemetry diff --git a/MySQL.Data/src/MySql.Data.csproj b/MySQL.Data/src/MySql.Data.csproj index 26d1d1652..9101458a8 100644 --- a/MySQL.Data/src/MySql.Data.csproj +++ b/MySQL.Data/src/MySql.Data.csproj @@ -1,11 +1,11 @@ - + MySql.Data.MySqlClient .Net Core Class Library Copyright (c) 2016, 2023, Oracle and/or its affiliates. en-US - 8.2.0 + 8.3.0 Oracle MySql.Data net462;net48;netstandard2.0;netstandard2.1;net6.0;net7.0;net8.0; diff --git a/MySQL.Data/src/Properties/VersionInfo.cs b/MySQL.Data/src/Properties/VersionInfo.cs index 05a18cd26..fd8a0e834 100644 --- a/MySQL.Data/src/Properties/VersionInfo.cs +++ b/MySQL.Data/src/Properties/VersionInfo.cs @@ -40,6 +40,6 @@ // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("8.2.0")] -[assembly: AssemblyInformationalVersion("8.2.0")] +[assembly: AssemblyVersion("8.3.0")] +[assembly: AssemblyInformationalVersion("8.3.0")] [assembly: NeutralResourcesLanguage("en-US")] \ No newline at end of file diff --git a/MySQL.Data/tests/MySql.Data.Tests/MySql.Data.Tests.csproj b/MySQL.Data/tests/MySql.Data.Tests/MySql.Data.Tests.csproj index 2b21049c2..bcc0455d3 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/MySql.Data.Tests.csproj +++ b/MySQL.Data/tests/MySql.Data.Tests/MySql.Data.Tests.csproj @@ -4,7 +4,7 @@ MySql.Data.Tests MySql.Data.Tests Class Library Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved. - 8.2.0 + 8.3.0 Oracle Oracle MySql.Data.Tests diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/MySqlX.Data.Tests.csproj b/MySQL.Data/tests/MySqlX.Data.Tests/MySqlX.Data.Tests.csproj index e4f19faa7..388524ac9 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/MySqlX.Data.Tests.csproj +++ b/MySQL.Data/tests/MySqlX.Data.Tests/MySqlX.Data.Tests.csproj @@ -4,7 +4,7 @@ MySql.Data.Tests MySql.Data.Tests Class Library Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved. - 8.2.0 + 8.3.0 Oracle Oracle MySql.Data.Tests diff --git a/MySql.Web/src/MySql.Web.csproj b/MySql.Web/src/MySql.Web.csproj index 46a3075e6..03c2bfe22 100644 --- a/MySql.Web/src/MySql.Web.csproj +++ b/MySql.Web/src/MySql.Web.csproj @@ -4,7 +4,7 @@ MySql.Web Copyright (c) 2016, 2023, Oracle and/or its affiliates. en-US - 8.2.0 + 8.3.0 Oracle net462;net48; $(NoWarn);CS1591 diff --git a/MySql.Web/tests/MySql.Web.Tests.csproj b/MySql.Web/tests/MySql.Web.Tests.csproj index 78995b8cb..b6495a7f5 100644 --- a/MySql.Web/tests/MySql.Web.Tests.csproj +++ b/MySql.Web/tests/MySql.Web.Tests.csproj @@ -4,7 +4,7 @@ MySql.Web.Tests Copyright (c) 2016, 2023, Oracle and/or its affiliates. en-US - 8.2.0 + 8.3.0 Oracle net462;net48; MySql.Web.Tests From 1acc02c5d992da92fec71984eb97f3ab0807e1d6 Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Sun, 29 Oct 2023 13:23:59 -0600 Subject: [PATCH 002/125] WL#15798 [Add support for build traversal] Added support for Microsoft.Build.Traversal in order to be able to build all projects in the repository at once using the dirs.proj file. Change-Id: I27481bb5c878fd2e21f0a7f87899891f05b023de --- CHANGES | 2 +- global.json | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 global.json diff --git a/CHANGES b/CHANGES index 7775ba662..6df1e8061 100644 --- a/CHANGES +++ b/CHANGES @@ -1,5 +1,5 @@ 8.3.0 - +- Added support for build traversal (WL15798). 8.2.0 - Migrated installer to Wix 4.0 (WL15847). diff --git a/global.json b/global.json new file mode 100644 index 000000000..f17298ca8 --- /dev/null +++ b/global.json @@ -0,0 +1,5 @@ +{ + "msbuild-sdks": { + "Microsoft.Build.Traversal": "4.1.0" + } +} \ No newline at end of file From 830f69675cf4c5daa2d2cf0716196186f6bf777d Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Sun, 29 Oct 2023 15:39:21 -0600 Subject: [PATCH 003/125] Bug#35957212 [Missing AssemblyInfo file por MySQL.Data.OpenTelemetry project] Added AssemblyInfo file to MySQL.Data.OpenTelemetry project. Change-Id: I4e0555aa8e7a0a599b288a5fa02be9684630c1f8 --- CHANGES | 1 + .../src/MySQL.Data.OpenTelemetry.csproj | 13 +++++++++++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/CHANGES b/CHANGES index 6df1e8061..a48ac5597 100644 --- a/CHANGES +++ b/CHANGES @@ -1,5 +1,6 @@ 8.3.0 - Added support for build traversal (WL15798). +- Added AssemblyInfo file to MySQL.Data.OpenTelemetry (Oracle Bug #35957212). 8.2.0 - Migrated installer to Wix 4.0 (WL15847). diff --git a/MySQL.Data.OpenTelemetry/src/MySQL.Data.OpenTelemetry.csproj b/MySQL.Data.OpenTelemetry/src/MySQL.Data.OpenTelemetry.csproj index 1536f4d84..082937ecb 100644 --- a/MySQL.Data.OpenTelemetry/src/MySQL.Data.OpenTelemetry.csproj +++ b/MySQL.Data.OpenTelemetry/src/MySQL.Data.OpenTelemetry.csproj @@ -1,4 +1,4 @@ - + MySql.Data.OpenTelemetry @@ -18,7 +18,16 @@ True ..\..\ConnectorNetPublicKey.snk True - MySql.Data.OpenTelemetry + MySql.Data.OpenTelemetry + false + false + false + false + false + false + false + false + false From 73baf89e58599e04b4e9491530731ce717ca7b05 Mon Sep 17 00:00:00 2001 From: Reggie Burnett Date: Mon, 30 Oct 2023 15:56:40 -0500 Subject: [PATCH 004/125] WL #15972 [Fix broken .GetString() behavior on reader] Change-Id: I833ebdf470c6a2b7a5a00b4a0c426e34001aeb78 --- CHANGES | 1 + .../src/MySqlConnectionStringBuilder.cs | 14 ++++++ MySQL.Data/src/MySqlDataReader.cs | 4 ++ .../tests/MySql.Data.Tests/BlobTests.cs | 2 - .../tests/MySql.Data.Tests/DataTypeTests.cs | 45 +++++++++++++++---- .../netstandard2_0/GetSchemaTests.cs | 18 ++++---- 6 files changed, 65 insertions(+), 19 deletions(-) diff --git a/CHANGES b/CHANGES index a48ac5597..159587498 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,7 @@ 8.3.0 - Added support for build traversal (WL15798). - Added AssemblyInfo file to MySQL.Data.OpenTelemetry (Oracle Bug #35957212). +- Fix broken .GetString() behavior on MySqlDataReader (WL15972). 8.2.0 - Migrated installer to Wix 4.0 (WL15847). diff --git a/MySQL.Data/src/MySqlConnectionStringBuilder.cs b/MySQL.Data/src/MySqlConnectionStringBuilder.cs index f790cfb45..8f6245f6d 100644 --- a/MySQL.Data/src/MySqlConnectionStringBuilder.cs +++ b/MySQL.Data/src/MySqlConnectionStringBuilder.cs @@ -241,6 +241,9 @@ static MySqlConnectionStringBuilder() (msb, sender, value) => { msb.SetValue("blobasutf8excludepattern", value); }, (msb, sender) => msb.BlobAsUTF8ExcludePattern)); #endregion + + Options.Add(new MySqlConnectionStringOption("oldgetstringbehavior", null, typeof(bool), false, true, + (msb, sender, value) => { msb.SetValue("oldgetstringbehavior", value); }, (msb, sender) => msb.OldGetStringBehavior)); } /// @@ -1014,6 +1017,17 @@ public bool UseDefaultCommandTimeoutForEF } #endregion + [DisplayName("Use the old GetString behavior for readers")] + [Category("Backwards Compatibility")] + [Description("When true, MySqlDataReader.GetString will return a string version of every possible data type")] + [DefaultValue(false)] + [Obsolete("This property is only used to provide old behavior. This option and the old behavior will be removed in 9.0")] + public bool OldGetStringBehavior + { + get { return (bool)values["oldgetstringbehavior"]; } + set { SetValue("oldgetstringbehavior", value); } + } + /// /// Gets or sets a connection option. /// diff --git a/MySQL.Data/src/MySqlDataReader.cs b/MySQL.Data/src/MySqlDataReader.cs index 37198d7da..3626cddfc 100644 --- a/MySQL.Data/src/MySqlDataReader.cs +++ b/MySQL.Data/src/MySqlDataReader.cs @@ -915,6 +915,10 @@ public override String GetString(int i) { IMySqlValue val = GetFieldValue(i, true); + if (!_connection.Settings.OldGetStringBehavior) + return (string)val.Value; + + if (val is MySqlBinary) { byte[] v = ((MySqlBinary)val).Value; diff --git a/MySQL.Data/tests/MySql.Data.Tests/BlobTests.cs b/MySQL.Data/tests/MySql.Data.Tests/BlobTests.cs index a18f82a1a..edc0f4cd0 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/BlobTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/BlobTests.cs @@ -217,14 +217,12 @@ private void InternalInsertText(bool prepare) Assert.True(reader.Read()); - Assert.AreEqual("This is my blob data", reader.GetString(1)); string s = reader.GetString(2); Assert.True(s.Length == 1024, "Checking length returned "); Assert.True(s.Substring(0, 9) == "ABCDEFGHI", "Checking first few chars of string"); Assert.True(reader.Read()); Assert.AreEqual(DBNull.Value, reader.GetValue(2)); - Assert.AreEqual("This is my text value", reader.GetString(1)); } } diff --git a/MySQL.Data/tests/MySql.Data.Tests/DataTypeTests.cs b/MySQL.Data/tests/MySql.Data.Tests/DataTypeTests.cs index 3aefc8284..b5f2f8b76 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/DataTypeTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/DataTypeTests.cs @@ -459,8 +459,6 @@ public void BinaryAndVarBinary() Assert.AreEqual('o', (char)buffer[1]); Assert.AreEqual(2, read); - string s = reader.GetString(0); - Assert.AreEqual("something", s); } } @@ -777,12 +775,10 @@ public void CanSaveSridValueOnGeometry() "SELECT ST_SRID(v) FROM Test" : "SELECT SRID(v) FROM Test"; - using (MySqlDataReader reader = cmd.ExecuteReader()) - { - reader.Read(); - var val = reader.GetString(0); - Assert.AreEqual("101", val); - } + using var reader = cmd.ExecuteReader(); + reader.Read(); + var val = reader.GetInt32(0); + Assert.AreEqual(101, val); } [Test] @@ -1663,5 +1659,38 @@ public void GetIntForTinyInt(bool treatAsBool, bool isPrepared) Assert.AreEqual(treatAsBool ? 1 : -2, reader.GetFieldValue(0)); Assert.AreEqual(treatAsBool ? 1 : -2, reader.GetFieldValue(0)); } + + [Test] + public void OldGetStringBehaviorOff() + { + ExecuteSQL(@"CREATE TABLE Test (value1 int, value2 DATETIME); INSERT INTO Test VALUES (1, '2023-10-30');"); + + using var cmd = new MySqlCommand(); + cmd.Connection = Connection; + cmd.CommandText = "SELECT * FROM Test"; + using var reader = cmd.ExecuteReader(); + reader.Read(); + Assert.Throws(() => reader.GetString(0)); + Assert.Throws(() => reader.GetString(1)); + } + + [Test] + public void OldGetStringBehaviorOn() + { + ExecuteSQL(@"CREATE TABLE Test (value1 int, value2 DECIMAL(10,2)); INSERT INTO Test VALUES (1, 20.4);"); + + string connString = Connection.ConnectionString + $";oldgetstringbehavior=true;"; + using var conn = new MySqlConnection(connString); + conn.Open(); + + using var cmd = new MySqlCommand(); + cmd.Connection = conn; + cmd.CommandText = "SELECT * FROM Test"; + using var reader = cmd.ExecuteReader(); + reader.Read(); + Assert.AreEqual("1", reader.GetString(0)); + Assert.AreEqual("20.40", reader.GetString(1)); + } + } } \ No newline at end of file diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/GetSchemaTests.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/GetSchemaTests.cs index 79501e17a..1f77a4d05 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/GetSchemaTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/GetSchemaTests.cs @@ -745,7 +745,10 @@ public void GeneratedColumnsVariations() using (var conn = new MySqlConnection(Settings.ConnectionString)) { conn.Open(); - var cmd = new MySqlCommand("create table Test(c1 int, c2 double GENERATED ALWAYS AS(c1 * 101 / 102) Stored COMMENT 'First Gen Col', c3 Json GENERATED ALWAYS AS(concat('{\"F1\":', c1, '}')) VIRTUAL COMMENT 'Second Gen /**/Col', c4 bigint GENERATED ALWAYS as (c1*10000) VIRTUAL UNIQUE KEY Comment '3rd Col' NOT NULL)", conn); + var cmd = new MySqlCommand( + @"create table Test(c1 int, + c2 double GENERATED ALWAYS AS(c1 * 101 / 102) Stored COMMENT 'First Gen Col', + c3 bigint GENERATED ALWAYS as (c1*10000) VIRTUAL UNIQUE KEY Comment '3rd Col' NOT NULL)", conn); cmd.ExecuteNonQuery(); cmd = new MySqlCommand("insert into Test(c1) values(1000)", conn); @@ -757,24 +760,21 @@ public void GeneratedColumnsVariations() using (var reader = cmd.ExecuteReader()) { Assert.True(reader.Read(), "Matching the values"); - Assert.True(reader.GetString(0).Equals("1000", StringComparison.CurrentCulture), "Matching the values"); - Assert.True(reader.GetString(1).Equals("990.196078431", StringComparison.CurrentCulture), "Matching the values"); - Assert.True(reader.GetString(2).Equals("{\"F1\": 1000}", StringComparison.CurrentCulture), "Matching the values"); - Assert.True(reader.GetString(3).Equals("10000000", StringComparison.CurrentCulture), "Matching the values"); + Assert.True(reader.GetInt32(0).Equals(1000), "Matching the values"); + Assert.True(reader.GetDouble(1).Equals(990.196078431), "Matching the values"); + Assert.True(reader.GetInt64(2).Equals(10000000), "Matching the values"); } var dt = conn.GetSchema("Columns", new[] { null, null, "Test", null }); - Assert.AreEqual(4, dt.Rows.Count, "Matching the values"); + Assert.AreEqual(3, dt.Rows.Count, "Matching the values"); Assert.AreEqual("Columns", dt.TableName, "Matching the values"); Assert.AreEqual("int", dt.Rows[0]["DATA_TYPE"].ToString(), "Matching the values"); Assert.AreEqual("double", dt.Rows[1]["DATA_TYPE"].ToString(), "Matching the values"); - Assert.AreEqual("json", dt.Rows[2]["DATA_TYPE"].ToString(), "Matching the values"); - Assert.AreEqual("bigint", dt.Rows[3]["DATA_TYPE"].ToString(), "Matching the values"); + Assert.AreEqual("bigint", dt.Rows[2]["DATA_TYPE"].ToString(), "Matching the values"); Assert.AreEqual("", dt.Rows[0]["GENERATION_EXPRESSION"].ToString(), "Matching the values"); Assert.AreEqual("", dt.Rows[0]["EXTRA"].ToString(), "Matching the values"); Assert.AreEqual("STORED GENERATED", dt.Rows[1]["EXTRA"].ToString(), "Matching the values"); Assert.AreEqual("VIRTUAL GENERATED", dt.Rows[2]["EXTRA"].ToString(), "Matching the values"); - Assert.AreEqual("VIRTUAL GENERATED", dt.Rows[3]["EXTRA"].ToString(), "Matching the values"); } } From 6f8b4871b000f9f877f7e058179001cb4656220d Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Sun, 5 Nov 2023 18:30:48 -0700 Subject: [PATCH 005/125] Bug#35731216 [Pool exhaustion after timeouts in transactions] Fixed a bug that prevented a connection from being removed from the in use connection pool after an exception has been thrown. Change-Id: I4f91820b9b59e7fcdd71d55511e994bea44a237a --- CHANGES | 2 ++ MySQL.Data/src/MySqlConnection.cs | 3 +- .../tests/MySql.Data.Tests/ConnectionTests.cs | 34 +++++++++++++++++++ 3 files changed, 37 insertions(+), 2 deletions(-) diff --git a/CHANGES b/CHANGES index 159587498..36588870a 100644 --- a/CHANGES +++ b/CHANGES @@ -2,6 +2,8 @@ - Added support for build traversal (WL15798). - Added AssemblyInfo file to MySQL.Data.OpenTelemetry (Oracle Bug #35957212). - Fix broken .GetString() behavior on MySqlDataReader (WL15972). +- Fixed a bug that prevented a connection from being removed from the in use connection pool. (MySQL Bug #112123, Oracle Bug #35731216). + 8.2.0 - Migrated installer to Wix 4.0 (WL15847). diff --git a/MySQL.Data/src/MySqlConnection.cs b/MySQL.Data/src/MySqlConnection.cs index f5cbee54e..31a0f43b4 100644 --- a/MySQL.Data/src/MySqlConnection.cs +++ b/MySQL.Data/src/MySqlConnection.cs @@ -743,8 +743,6 @@ internal async Task AbortAsync(bool execAsync, CancellationToken cancellationTok driver.currentTransaction.Connection = newConn; } } - - await driver.CloseAsync(execAsync).ConfigureAwait(false); } catch (Exception ex) { @@ -752,6 +750,7 @@ internal async Task AbortAsync(bool execAsync, CancellationToken cancellationTok } finally { + await driver.CloseAsync(execAsync).ConfigureAwait(false); this.IsInUse = false; } SetState(ConnectionState.Closed, true); diff --git a/MySQL.Data/tests/MySql.Data.Tests/ConnectionTests.cs b/MySQL.Data/tests/MySql.Data.Tests/ConnectionTests.cs index 5aaf85f4a..7a06c2e24 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/ConnectionTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/ConnectionTests.cs @@ -98,6 +98,40 @@ public void ChangeDatabase() } } + /// + /// Bug#35731216 Pool exhaustion after timeouts in transactions. + /// + [Test] + public void ConnectionPoolExhaustion() + { + for (var i = 0; i <= 11; i++) + { + var ex = Assert.Catch(() => CreateCommandTimeoutException()); + //Prior to the fix the exception thrown was 'error connecting: Timeout expired. The timeout period elapsed prior to obtaining a connection from the pool. This may have occurred because all pooled connections were in use and max pool size was reached.' after the 10th execution. + Assert.AreEqual("Fatal error encountered during command execution.", ex.Message); + } + } + + private void CreateCommandTimeoutException() + { + MySqlConnectionStringBuilder settings = new MySqlConnectionStringBuilder(Connection.ConnectionString); + settings.Pooling = true; + settings.MaximumPoolSize = 10; + using (var conn = new MySqlConnection(settings.GetConnectionString(true))) + { + conn.Open(); + using (var tran = conn.BeginTransaction()) + { + using (var cmd = conn.CreateCommand()) + { + cmd.CommandText = "DO SLEEP(5);"; + cmd.CommandTimeout = 1; + cmd.ExecuteNonQuery(); + } + } + } + } + [Test] public void ConnectingAsUTF8() { From 69c439c5f75c60eda072be562ef2043f35183037 Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Sun, 5 Nov 2023 21:57:26 -0700 Subject: [PATCH 006/125] Bug#35968775 [EFCore NuGet packages have missing target frameworks] Added the missing target frameworks for the EFCore project NuGet packages. Change-Id: Iff05dbca083471f1a05f64ab5a98507bbd0914a4 --- CHANGES | 1 + EFCore/Directory.Build.targets | 16 ---------------- 2 files changed, 1 insertion(+), 16 deletions(-) delete mode 100644 EFCore/Directory.Build.targets diff --git a/CHANGES b/CHANGES index 36588870a..588fa493e 100644 --- a/CHANGES +++ b/CHANGES @@ -3,6 +3,7 @@ - Added AssemblyInfo file to MySQL.Data.OpenTelemetry (Oracle Bug #35957212). - Fix broken .GetString() behavior on MySqlDataReader (WL15972). - Fixed a bug that prevented a connection from being removed from the in use connection pool. (MySQL Bug #112123, Oracle Bug #35731216). +- Added missing target frameworks to EFCore nuget packages (Oracle Bug #35968775). 8.2.0 diff --git a/EFCore/Directory.Build.targets b/EFCore/Directory.Build.targets deleted file mode 100644 index dd451dfa5..000000000 --- a/EFCore/Directory.Build.targets +++ /dev/null @@ -1,16 +0,0 @@ - - - Copyright (c) 2021, 2023, Oracle and/or its affiliates. - 6.0.21+MySQL8.3.0 - - - - Copyright (c) 2022, 2023, Oracle and/or its affiliates. - 7.0.10+MySQL8.3.0 - - - - Copyright (c) 2023, Oracle and/or its affiliates. - 8.0.0-preview+MySQL8.3.0 - - \ No newline at end of file From 476152a32f7730919398251e083bf890b41898a7 Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Tue, 21 Nov 2023 17:40:49 -0700 Subject: [PATCH 007/125] WL#16041 [Add readme files to Connector/NET NuGet Packages] Added missing README files to Nuget packages and replaced the deprecated PackageIconURL property with PackageIcon. Change-Id: I817af04f7405750266c8af33dd354d6f17df22e9 --- CHANGES | 1 + EntityFramework/src/MySql.Data.EntityFramework.csproj | 11 ++++++++++- .../src/MySQL.Data.OpenTelemetry.csproj | 11 ++++++++++- MySQL.Data/src/MySql.Data.csproj | 7 ++++++- MySql.Web/src/MySql.Web.csproj | 11 ++++++++++- 5 files changed, 37 insertions(+), 4 deletions(-) diff --git a/CHANGES b/CHANGES index 588fa493e..de21eb30f 100644 --- a/CHANGES +++ b/CHANGES @@ -4,6 +4,7 @@ - Fix broken .GetString() behavior on MySqlDataReader (WL15972). - Fixed a bug that prevented a connection from being removed from the in use connection pool. (MySQL Bug #112123, Oracle Bug #35731216). - Added missing target frameworks to EFCore nuget packages (Oracle Bug #35968775). +- Added missing README files to Nuget packages (WL16041). 8.2.0 diff --git a/EntityFramework/src/MySql.Data.EntityFramework.csproj b/EntityFramework/src/MySql.Data.EntityFramework.csproj index 14ebe116f..fb8a66f20 100644 --- a/EntityFramework/src/MySql.Data.EntityFramework.csproj +++ b/EntityFramework/src/MySql.Data.EntityFramework.csproj @@ -11,7 +11,8 @@ MySql.Data.EntityFramework MySql.Data.EntityFramework MySql;.NET Connector;MySql Connector/NET - http://www.mysql.com/common/logos/logo-mysql-170x115.png + logo-mysql-170x115.png + README.md https://dev.mysql.com/downloads/ GPL-2.0-only true @@ -23,6 +24,14 @@ false + + + + + + + + diff --git a/MySQL.Data.OpenTelemetry/src/MySQL.Data.OpenTelemetry.csproj b/MySQL.Data.OpenTelemetry/src/MySQL.Data.OpenTelemetry.csproj index 082937ecb..8e68c0f18 100644 --- a/MySQL.Data.OpenTelemetry/src/MySQL.Data.OpenTelemetry.csproj +++ b/MySQL.Data.OpenTelemetry/src/MySQL.Data.OpenTelemetry.csproj @@ -10,7 +10,8 @@ MySql.Data.OpenTelemetry MySql.Data.OpenTelemetry MySql;.NET Connector;MySql Connector/NET;ado;ado.net;database;sql;opentelemetry;tracing;diagnostics;instrumentation - http://www.mysql.com/common/logos/logo-mysql-170x115.png + logo-mysql-170x115.png + README.md https://dev.mysql.com/downloads/ GPL-2.0-only true @@ -30,6 +31,14 @@ false + + + + + + + + ..\..\Dependencies\OpenTelemetry.Api\OpenTelemetry.Api.dll diff --git a/MySQL.Data/src/MySql.Data.csproj b/MySQL.Data/src/MySql.Data.csproj index 9101458a8..7e3b0c513 100644 --- a/MySQL.Data/src/MySql.Data.csproj +++ b/MySQL.Data/src/MySql.Data.csproj @@ -13,6 +13,7 @@ MySql;.NET Connector;MySql Connector/NET;netcore;.Net Core;MySql Conector/Net Core;coreclr;C/NET;C/Net Core Review ReleaseNotes.txt for details. logo-mysql-170x115.png + README.md https://dev.mysql.com/downloads/ GPL-2.0-only true @@ -34,7 +35,11 @@ - + + + + + diff --git a/MySql.Web/src/MySql.Web.csproj b/MySql.Web/src/MySql.Web.csproj index 03c2bfe22..5b03391f1 100644 --- a/MySql.Web/src/MySql.Web.csproj +++ b/MySql.Web/src/MySql.Web.csproj @@ -11,7 +11,8 @@ MySql.Web MySql.Web MySql;.NET Connector;MySql Connector/NET - http://www.mysql.com/common/logos/logo-mysql-170x115.png + logo-mysql-170x115.png + README.md https://dev.mysql.com/downloads/ GPL-2.0-only true @@ -27,6 +28,14 @@ ..\..\ConnectorNetPublicKey.snk + + + + + + + + From 4ce528ec14a0bedbba56c19e0bf339f83671e597 Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Sat, 25 Nov 2023 15:44:32 -0700 Subject: [PATCH 008/125] WL#16075 [Upgrade Google.Protobuf dependency to 3.25.1] Change-Id: I9b8c558acbbd2eaee582b20d1aa5055dd4ec7b43 --- CHANGES | 1 + MySQL.Data/src/MySql.Data.csproj | 4 +- .../src/X/Protocol/X/Protobuf/Mysqlx.cs | 579 +-- .../X/Protocol/X/Protobuf/MysqlxConnection.cs | 830 ++-- .../src/X/Protocol/X/Protobuf/MysqlxCrud.cs | 3352 ++++++++++------- .../src/X/Protocol/X/Protobuf/MysqlxCursor.cs | 655 ++-- .../X/Protocol/X/Protobuf/MysqlxDatatypes.cs | 1285 ++++--- .../src/X/Protocol/X/Protobuf/MysqlxExpect.cs | 459 ++- .../src/X/Protocol/X/Protobuf/MysqlxExpr.cs | 1617 +++++--- .../src/X/Protocol/X/Protobuf/MysqlxNotice.cs | 977 +++-- .../X/Protocol/X/Protobuf/MysqlxPrepare.cs | 767 ++-- .../X/Protocol/X/Protobuf/MysqlxResultset.cs | 984 +++-- .../X/Protocol/X/Protobuf/MysqlxSession.cs | 678 ++-- .../src/X/Protocol/X/Protobuf/MysqlxSql.cs | 312 +- 14 files changed, 7810 insertions(+), 4690 deletions(-) diff --git a/CHANGES b/CHANGES index de21eb30f..a48c54622 100644 --- a/CHANGES +++ b/CHANGES @@ -5,6 +5,7 @@ - Fixed a bug that prevented a connection from being removed from the in use connection pool. (MySQL Bug #112123, Oracle Bug #35731216). - Added missing target frameworks to EFCore nuget packages (Oracle Bug #35968775). - Added missing README files to Nuget packages (WL16041). +- Upgraded the Google.Protobuf dependency to version 3.25.1 (WL16075). 8.2.0 diff --git a/MySQL.Data/src/MySql.Data.csproj b/MySQL.Data/src/MySql.Data.csproj index 7e3b0c513..9b54e2055 100644 --- a/MySQL.Data/src/MySql.Data.csproj +++ b/MySQL.Data/src/MySql.Data.csproj @@ -1,4 +1,4 @@ - + @@ -48,7 +48,7 @@ - + diff --git a/MySQL.Data/src/X/Protocol/X/Protobuf/Mysqlx.cs b/MySQL.Data/src/X/Protocol/X/Protobuf/Mysqlx.cs index 09240017d..c5c48b4fd 100644 --- a/MySQL.Data/src/X/Protocol/X/Protobuf/Mysqlx.cs +++ b/MySQL.Data/src/X/Protocol/X/Protobuf/Mysqlx.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2022, 2023, Oracle and/or its affiliates. +// Copyright (c) 2023, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as @@ -7,7 +7,7 @@ // This program is also distributed with certain software (including // but not limited to OpenSSL) that is licensed under separate terms, // as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an +// documentation. The authors of MySQL hereby grant you an // additional permission to link the program and your derivative works // with the separately licensed software that they have included with // MySQL. @@ -37,19 +37,23 @@ using pbc = global::Google.Protobuf.Collections; using pbr = global::Google.Protobuf.Reflection; using scg = global::System.Collections.Generic; -namespace Mysqlx { +namespace Mysqlx +{ /// Holder for reflection information generated from mysqlx.proto - internal static partial class MysqlxReflection { + public static partial class MysqlxReflection + { #region Descriptor /// File descriptor for mysqlx.proto - public static pbr::FileDescriptor Descriptor { + public static pbr::FileDescriptor Descriptor + { get { return descriptor; } } private static pbr::FileDescriptor descriptor; - static MysqlxReflection() { + static MysqlxReflection() + { byte[] descriptorData = global::System.Convert.FromBase64String( string.Concat( "CgxteXNxbHgucHJvdG8SBk15c3FseBogZ29vZ2xlL3Byb3RvYnVmL2Rlc2Ny", @@ -95,11 +99,12 @@ static MysqlxReflection() { } /// Holder for extension identifiers generated from the top level of mysqlx.proto - internal static partial class MysqlxExtensions { + public static partial class MysqlxExtensions + { public static readonly pb::Extension ClientMessageId = - new pb::Extension(100001, pb::FieldCodec.ForEnum(800008, x => (int) x, x => (global::Mysqlx.ClientMessages.Types.Type) x, global::Mysqlx.ClientMessages.Types.Type.ConCapabilitiesGet)); + new pb::Extension(100001, pb::FieldCodec.ForEnum(800008, x => (int)x, x => (global::Mysqlx.ClientMessages.Types.Type)x, global::Mysqlx.ClientMessages.Types.Type.ConCapabilitiesGet)); public static readonly pb::Extension ServerMessageId = - new pb::Extension(100002, pb::FieldCodec.ForEnum(800016, x => (int) x, x => (global::Mysqlx.ServerMessages.Types.Type) x, global::Mysqlx.ServerMessages.Types.Type.Ok)); + new pb::Extension(100002, pb::FieldCodec.ForEnum(800016, x => (int)x, x => (global::Mysqlx.ServerMessages.Types.Type)x, global::Mysqlx.ServerMessages.Types.Type.Ok)); } #region Messages @@ -112,10 +117,11 @@ internal static partial class MysqlxExtensions { ///- generate constants ///- check for uniqueness /// - internal sealed partial class ClientMessages : pb::IMessage - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] + public sealed partial class ClientMessages : pb::IMessage +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE , pb::IBufferMessage - #endif +#endif { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ClientMessages()); private pb::UnknownFieldSet _unknownFields; @@ -125,19 +131,22 @@ internal sealed partial class ClientMessages : pb::IMessage [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static pbr::MessageDescriptor Descriptor { + public static pbr::MessageDescriptor Descriptor + { get { return global::Mysqlx.MysqlxReflection.Descriptor.MessageTypes[0]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - pbr::MessageDescriptor pb::IMessage.Descriptor { + pbr::MessageDescriptor pb::IMessage.Descriptor + { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public ClientMessages() { + public ClientMessages() + { OnConstruction(); } @@ -145,29 +154,35 @@ public ClientMessages() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public ClientMessages(ClientMessages other) : this() { + public ClientMessages(ClientMessages other) : this() + { _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public ClientMessages Clone() { + public ClientMessages Clone() + { return new ClientMessages(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override bool Equals(object other) { + public override bool Equals(object other) + { return Equals(other as ClientMessages); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool Equals(ClientMessages other) { - if (ReferenceEquals(other, null)) { + public bool Equals(ClientMessages other) + { + if (ReferenceEquals(other, null)) + { return false; } - if (ReferenceEquals(other, this)) { + if (ReferenceEquals(other, this)) + { return true; } return Equals(_unknownFields, other._unknownFields); @@ -175,9 +190,11 @@ public bool Equals(ClientMessages other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override int GetHashCode() { + public override int GetHashCode() + { int hash = 1; - if (_unknownFields != null) { + if (_unknownFields != null) + { hash ^= _unknownFields.GetHashCode(); } return hash; @@ -185,37 +202,43 @@ public override int GetHashCode() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override string ToString() { + public override string ToString() + { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void WriteTo(pb::CodedOutputStream output) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void WriteTo(pb::CodedOutputStream output) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE output.WriteRawMessage(this); - #else +#else if (_unknownFields != null) { _unknownFields.WriteTo(output); } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { - if (_unknownFields != null) { + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) + { + if (_unknownFields != null) + { _unknownFields.WriteTo(ref output); } } - #endif +#endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public int CalculateSize() { + public int CalculateSize() + { int size = 0; - if (_unknownFields != null) { + if (_unknownFields != null) + { size += _unknownFields.CalculateSize(); } return size; @@ -223,8 +246,10 @@ public int CalculateSize() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(ClientMessages other) { - if (other == null) { + public void MergeFrom(ClientMessages other) + { + if (other == null) + { return; } _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); @@ -232,10 +257,11 @@ public void MergeFrom(ClientMessages other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(pb::CodedInputStream input) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void MergeFrom(pb::CodedInputStream input) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE input.ReadRawMessage(this); - #else +#else uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { @@ -244,30 +270,35 @@ public void MergeFrom(pb::CodedInputStream input) { break; } } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) + { uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { + while ((tag = input.ReadTag()) != 0) + { + switch (tag) + { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; } } } - #endif +#endif #region Nested types /// Container for nested types declared in the ClientMessages message type. [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static partial class Types { - public enum Type { + public static partial class Types + { + public enum Type + { [pbr::OriginalName("CON_CAPABILITIES_GET")] ConCapabilitiesGet = 1, [pbr::OriginalName("CON_CAPABILITIES_SET")] ConCapabilitiesSet = 2, [pbr::OriginalName("CON_CLOSE")] ConClose = 3, @@ -308,10 +339,11 @@ public enum Type { ///- generate constants ///- check for uniqueness /// - internal sealed partial class ServerMessages : pb::IMessage - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] + public sealed partial class ServerMessages : pb::IMessage +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE , pb::IBufferMessage - #endif +#endif { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ServerMessages()); private pb::UnknownFieldSet _unknownFields; @@ -321,19 +353,22 @@ internal sealed partial class ServerMessages : pb::IMessage [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static pbr::MessageDescriptor Descriptor { + public static pbr::MessageDescriptor Descriptor + { get { return global::Mysqlx.MysqlxReflection.Descriptor.MessageTypes[1]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - pbr::MessageDescriptor pb::IMessage.Descriptor { + pbr::MessageDescriptor pb::IMessage.Descriptor + { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public ServerMessages() { + public ServerMessages() + { OnConstruction(); } @@ -341,29 +376,35 @@ public ServerMessages() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public ServerMessages(ServerMessages other) : this() { + public ServerMessages(ServerMessages other) : this() + { _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public ServerMessages Clone() { + public ServerMessages Clone() + { return new ServerMessages(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override bool Equals(object other) { + public override bool Equals(object other) + { return Equals(other as ServerMessages); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool Equals(ServerMessages other) { - if (ReferenceEquals(other, null)) { + public bool Equals(ServerMessages other) + { + if (ReferenceEquals(other, null)) + { return false; } - if (ReferenceEquals(other, this)) { + if (ReferenceEquals(other, this)) + { return true; } return Equals(_unknownFields, other._unknownFields); @@ -371,9 +412,11 @@ public bool Equals(ServerMessages other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override int GetHashCode() { + public override int GetHashCode() + { int hash = 1; - if (_unknownFields != null) { + if (_unknownFields != null) + { hash ^= _unknownFields.GetHashCode(); } return hash; @@ -381,37 +424,43 @@ public override int GetHashCode() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override string ToString() { + public override string ToString() + { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void WriteTo(pb::CodedOutputStream output) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void WriteTo(pb::CodedOutputStream output) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE output.WriteRawMessage(this); - #else +#else if (_unknownFields != null) { _unknownFields.WriteTo(output); } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { - if (_unknownFields != null) { + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) + { + if (_unknownFields != null) + { _unknownFields.WriteTo(ref output); } } - #endif +#endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public int CalculateSize() { + public int CalculateSize() + { int size = 0; - if (_unknownFields != null) { + if (_unknownFields != null) + { size += _unknownFields.CalculateSize(); } return size; @@ -419,8 +468,10 @@ public int CalculateSize() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(ServerMessages other) { - if (other == null) { + public void MergeFrom(ServerMessages other) + { + if (other == null) + { return; } _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); @@ -428,10 +479,11 @@ public void MergeFrom(ServerMessages other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(pb::CodedInputStream input) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void MergeFrom(pb::CodedInputStream input) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE input.ReadRawMessage(this); - #else +#else uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { @@ -440,30 +492,35 @@ public void MergeFrom(pb::CodedInputStream input) { break; } } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) + { uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { + while ((tag = input.ReadTag()) != 0) + { + switch (tag) + { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; } } } - #endif +#endif #region Nested types /// Container for nested types declared in the ServerMessages message type. [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static partial class Types { - public enum Type { + public static partial class Types + { + public enum Type + { [pbr::OriginalName("OK")] Ok = 0, [pbr::OriginalName("ERROR")] Error = 1, [pbr::OriginalName("CONN_CAPABILITIES")] ConnCapabilities = 2, @@ -488,10 +545,11 @@ public enum Type { } - internal sealed partial class Ok : pb::IMessage - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] + public sealed partial class Ok : pb::IMessage +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE , pb::IBufferMessage - #endif +#endif { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Ok()); private pb::UnknownFieldSet _unknownFields; @@ -501,19 +559,22 @@ internal sealed partial class Ok : pb::IMessage [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static pbr::MessageDescriptor Descriptor { + public static pbr::MessageDescriptor Descriptor + { get { return global::Mysqlx.MysqlxReflection.Descriptor.MessageTypes[2]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - pbr::MessageDescriptor pb::IMessage.Descriptor { + pbr::MessageDescriptor pb::IMessage.Descriptor + { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Ok() { + public Ok() + { OnConstruction(); } @@ -521,14 +582,16 @@ public Ok() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Ok(Ok other) : this() { + public Ok(Ok other) : this() + { msg_ = other.msg_; _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Ok Clone() { + public Ok Clone() + { return new Ok(this); } @@ -539,38 +602,46 @@ public Ok Clone() { private string msg_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public string Msg { + public string Msg + { get { return msg_ ?? MsgDefaultValue; } - set { + set + { msg_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } /// Gets whether the "msg" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasMsg { + public bool HasMsg + { get { return msg_ != null; } } /// Clears the value of the "msg" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearMsg() { + public void ClearMsg() + { msg_ = null; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override bool Equals(object other) { + public override bool Equals(object other) + { return Equals(other as Ok); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool Equals(Ok other) { - if (ReferenceEquals(other, null)) { + public bool Equals(Ok other) + { + if (ReferenceEquals(other, null)) + { return false; } - if (ReferenceEquals(other, this)) { + if (ReferenceEquals(other, this)) + { return true; } if (Msg != other.Msg) return false; @@ -579,10 +650,12 @@ public bool Equals(Ok other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override int GetHashCode() { + public override int GetHashCode() + { int hash = 1; if (HasMsg) hash ^= Msg.GetHashCode(); - if (_unknownFields != null) { + if (_unknownFields != null) + { hash ^= _unknownFields.GetHashCode(); } return hash; @@ -590,16 +663,18 @@ public override int GetHashCode() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override string ToString() { + public override string ToString() + { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void WriteTo(pb::CodedOutputStream output) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void WriteTo(pb::CodedOutputStream output) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE output.WriteRawMessage(this); - #else +#else if (HasMsg) { output.WriteRawTag(10); output.WriteString(Msg); @@ -607,31 +682,37 @@ public void WriteTo(pb::CodedOutputStream output) { if (_unknownFields != null) { _unknownFields.WriteTo(output); } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { - if (HasMsg) { + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) + { + if (HasMsg) + { output.WriteRawTag(10); output.WriteString(Msg); } - if (_unknownFields != null) { + if (_unknownFields != null) + { _unknownFields.WriteTo(ref output); } } - #endif +#endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public int CalculateSize() { + public int CalculateSize() + { int size = 0; - if (HasMsg) { + if (HasMsg) + { size += 1 + pb::CodedOutputStream.ComputeStringSize(Msg); } - if (_unknownFields != null) { + if (_unknownFields != null) + { size += _unknownFields.CalculateSize(); } return size; @@ -639,11 +720,14 @@ public int CalculateSize() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(Ok other) { - if (other == null) { + public void MergeFrom(Ok other) + { + if (other == null) + { return; } - if (other.HasMsg) { + if (other.HasMsg) + { Msg = other.Msg; } _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); @@ -651,10 +735,11 @@ public void MergeFrom(Ok other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(pb::CodedInputStream input) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void MergeFrom(pb::CodedInputStream input) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE input.ReadRawMessage(this); - #else +#else uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { @@ -667,34 +752,39 @@ public void MergeFrom(pb::CodedInputStream input) { } } } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) + { uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { + while ((tag = input.ReadTag()) != 0) + { + switch (tag) + { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; - case 10: { - Msg = input.ReadString(); - break; - } + case 10: + { + Msg = input.ReadString(); + break; + } } } } - #endif +#endif } - internal sealed partial class Error : pb::IMessage - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] + public sealed partial class Error : pb::IMessage +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE , pb::IBufferMessage - #endif +#endif { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Error()); private pb::UnknownFieldSet _unknownFields; @@ -705,19 +795,22 @@ internal sealed partial class Error : pb::IMessage [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static pbr::MessageDescriptor Descriptor { + public static pbr::MessageDescriptor Descriptor + { get { return global::Mysqlx.MysqlxReflection.Descriptor.MessageTypes[3]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - pbr::MessageDescriptor pb::IMessage.Descriptor { + pbr::MessageDescriptor pb::IMessage.Descriptor + { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Error() { + public Error() + { OnConstruction(); } @@ -725,7 +818,8 @@ public Error() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Error(Error other) : this() { + public Error(Error other) : this() + { _hasBits0 = other._hasBits0; severity_ = other.severity_; code_ = other.code_; @@ -736,7 +830,8 @@ public Error(Error other) : this() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Error Clone() { + public Error Clone() + { return new Error(this); } @@ -750,9 +845,11 @@ public Error Clone() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public global::Mysqlx.Error.Types.Severity Severity { + public global::Mysqlx.Error.Types.Severity Severity + { get { if ((_hasBits0 & 1) != 0) { return severity_; } else { return SeverityDefaultValue; } } - set { + set + { _hasBits0 |= 1; severity_ = value; } @@ -760,13 +857,15 @@ public Error Clone() { /// Gets whether the "severity" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasSeverity { + public bool HasSeverity + { get { return (_hasBits0 & 1) != 0; } } /// Clears the value of the "severity" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearSeverity() { + public void ClearSeverity() + { _hasBits0 &= ~1; } @@ -780,9 +879,11 @@ public void ClearSeverity() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public uint Code { + public uint Code + { get { if ((_hasBits0 & 2) != 0) { return code_; } else { return CodeDefaultValue; } } - set { + set + { _hasBits0 |= 2; code_ = value; } @@ -790,13 +891,15 @@ public uint Code { /// Gets whether the "code" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasCode { + public bool HasCode + { get { return (_hasBits0 & 2) != 0; } } /// Clears the value of the "code" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearCode() { + public void ClearCode() + { _hasBits0 &= ~2; } @@ -810,22 +913,26 @@ public void ClearCode() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public string SqlState { + public string SqlState + { get { return sqlState_ ?? SqlStateDefaultValue; } - set { + set + { sqlState_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } /// Gets whether the "sql_state" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasSqlState { + public bool HasSqlState + { get { return sqlState_ != null; } } /// Clears the value of the "sql_state" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearSqlState() { + public void ClearSqlState() + { sqlState_ = null; } @@ -839,38 +946,46 @@ public void ClearSqlState() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public string Msg { + public string Msg + { get { return msg_ ?? MsgDefaultValue; } - set { + set + { msg_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } /// Gets whether the "msg" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasMsg { + public bool HasMsg + { get { return msg_ != null; } } /// Clears the value of the "msg" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearMsg() { + public void ClearMsg() + { msg_ = null; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override bool Equals(object other) { + public override bool Equals(object other) + { return Equals(other as Error); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool Equals(Error other) { - if (ReferenceEquals(other, null)) { + public bool Equals(Error other) + { + if (ReferenceEquals(other, null)) + { return false; } - if (ReferenceEquals(other, this)) { + if (ReferenceEquals(other, this)) + { return true; } if (Severity != other.Severity) return false; @@ -882,13 +997,15 @@ public bool Equals(Error other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override int GetHashCode() { + public override int GetHashCode() + { int hash = 1; if (HasSeverity) hash ^= Severity.GetHashCode(); if (HasCode) hash ^= Code.GetHashCode(); if (HasSqlState) hash ^= SqlState.GetHashCode(); if (HasMsg) hash ^= Msg.GetHashCode(); - if (_unknownFields != null) { + if (_unknownFields != null) + { hash ^= _unknownFields.GetHashCode(); } return hash; @@ -896,16 +1013,18 @@ public override int GetHashCode() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override string ToString() { + public override string ToString() + { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void WriteTo(pb::CodedOutputStream output) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void WriteTo(pb::CodedOutputStream output) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE output.WriteRawMessage(this); - #else +#else if (HasSeverity) { output.WriteRawTag(8); output.WriteEnum((int) Severity); @@ -925,52 +1044,64 @@ public void WriteTo(pb::CodedOutputStream output) { if (_unknownFields != null) { _unknownFields.WriteTo(output); } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { - if (HasSeverity) { + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) + { + if (HasSeverity) + { output.WriteRawTag(8); - output.WriteEnum((int) Severity); + output.WriteEnum((int)Severity); } - if (HasCode) { + if (HasCode) + { output.WriteRawTag(16); output.WriteUInt32(Code); } - if (HasMsg) { + if (HasMsg) + { output.WriteRawTag(26); output.WriteString(Msg); } - if (HasSqlState) { + if (HasSqlState) + { output.WriteRawTag(34); output.WriteString(SqlState); } - if (_unknownFields != null) { + if (_unknownFields != null) + { _unknownFields.WriteTo(ref output); } } - #endif +#endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public int CalculateSize() { + public int CalculateSize() + { int size = 0; - if (HasSeverity) { - size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Severity); + if (HasSeverity) + { + size += 1 + pb::CodedOutputStream.ComputeEnumSize((int)Severity); } - if (HasCode) { + if (HasCode) + { size += 1 + pb::CodedOutputStream.ComputeUInt32Size(Code); } - if (HasSqlState) { + if (HasSqlState) + { size += 1 + pb::CodedOutputStream.ComputeStringSize(SqlState); } - if (HasMsg) { + if (HasMsg) + { size += 1 + pb::CodedOutputStream.ComputeStringSize(Msg); } - if (_unknownFields != null) { + if (_unknownFields != null) + { size += _unknownFields.CalculateSize(); } return size; @@ -978,20 +1109,26 @@ public int CalculateSize() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(Error other) { - if (other == null) { + public void MergeFrom(Error other) + { + if (other == null) + { return; } - if (other.HasSeverity) { + if (other.HasSeverity) + { Severity = other.Severity; } - if (other.HasCode) { + if (other.HasCode) + { Code = other.Code; } - if (other.HasSqlState) { + if (other.HasSqlState) + { SqlState = other.SqlState; } - if (other.HasMsg) { + if (other.HasMsg) + { Msg = other.Msg; } _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); @@ -999,10 +1136,11 @@ public void MergeFrom(Error other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(pb::CodedInputStream input) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void MergeFrom(pb::CodedInputStream input) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE input.ReadRawMessage(this); - #else +#else uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { @@ -1027,46 +1165,55 @@ public void MergeFrom(pb::CodedInputStream input) { } } } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) + { uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { + while ((tag = input.ReadTag()) != 0) + { + switch (tag) + { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; - case 8: { - Severity = (global::Mysqlx.Error.Types.Severity) input.ReadEnum(); - break; - } - case 16: { - Code = input.ReadUInt32(); - break; - } - case 26: { - Msg = input.ReadString(); - break; - } - case 34: { - SqlState = input.ReadString(); - break; - } + case 8: + { + Severity = (global::Mysqlx.Error.Types.Severity)input.ReadEnum(); + break; + } + case 16: + { + Code = input.ReadUInt32(); + break; + } + case 26: + { + Msg = input.ReadString(); + break; + } + case 34: + { + SqlState = input.ReadString(); + break; + } } } } - #endif +#endif #region Nested types /// Container for nested types declared in the Error message type. [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static partial class Types { - public enum Severity { + public static partial class Types + { + public enum Severity + { [pbr::OriginalName("ERROR")] Error = 0, [pbr::OriginalName("FATAL")] Fatal = 1, } diff --git a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxConnection.cs b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxConnection.cs index 56fa65d62..73e4f7769 100644 --- a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxConnection.cs +++ b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxConnection.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2022, 2023, Oracle and/or its affiliates. +// Copyright (c) 2023, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as @@ -7,7 +7,7 @@ // This program is also distributed with certain software (including // but not limited to OpenSSL) that is licensed under separate terms, // as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an +// documentation. The authors of MySQL hereby grant you an // additional permission to link the program and your derivative works // with the separately licensed software that they have included with // MySQL. @@ -37,19 +37,23 @@ using pbc = global::Google.Protobuf.Collections; using pbr = global::Google.Protobuf.Reflection; using scg = global::System.Collections.Generic; -namespace Mysqlx.Connection { +namespace Mysqlx.Connection +{ /// Holder for reflection information generated from mysqlx_connection.proto - internal static partial class MysqlxConnectionReflection { + public static partial class MysqlxConnectionReflection + { #region Descriptor /// File descriptor for mysqlx_connection.proto - public static pbr::FileDescriptor Descriptor { + public static pbr::FileDescriptor Descriptor + { get { return descriptor; } } private static pbr::FileDescriptor descriptor; - static MysqlxConnectionReflection() { + static MysqlxConnectionReflection() + { byte[] descriptorData = global::System.Convert.FromBase64String( string.Concat( "ChdteXNxbHhfY29ubmVjdGlvbi5wcm90bxIRTXlzcWx4LkNvbm5lY3Rpb24a", @@ -63,7 +67,7 @@ static MysqlxConnectionReflection() { "GQoRdW5jb21wcmVzc2VkX3NpemUYASABKAQSNAoPc2VydmVyX21lc3NhZ2Vz", "GAIgASgOMhsuTXlzcWx4LlNlcnZlck1lc3NhZ2VzLlR5cGUSNAoPY2xpZW50", "X21lc3NhZ2VzGAMgASgOMhsuTXlzcWx4LkNsaWVudE1lc3NhZ2VzLlR5cGUS", - "DwoHcGF5bG9hZBgEIAIoDDoIkOowE4jqMC5CGQoXY29tLm15c3FsLmNqLngu", + "DwoHcGF5bG9hZBgEIAIoDDoIiOowLpDqMBNCGQoXY29tLm15c3FsLmNqLngu", "cHJvdG9idWY=")); descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { global::Mysqlx.Datatypes.MysqlxDatatypesReflection.Descriptor, global::Mysqlx.MysqlxReflection.Descriptor, }, @@ -86,10 +90,11 @@ static MysqlxConnectionReflection() { /// ///A tuple of a ``name`` and a @ref Mysqlx::Datatypes::Any /// - internal sealed partial class Capability : pb::IMessage - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] + public sealed partial class Capability : pb::IMessage +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE , pb::IBufferMessage - #endif +#endif { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Capability()); private pb::UnknownFieldSet _unknownFields; @@ -99,19 +104,22 @@ internal sealed partial class Capability : pb::IMessage [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static pbr::MessageDescriptor Descriptor { + public static pbr::MessageDescriptor Descriptor + { get { return global::Mysqlx.Connection.MysqlxConnectionReflection.Descriptor.MessageTypes[0]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - pbr::MessageDescriptor pb::IMessage.Descriptor { + pbr::MessageDescriptor pb::IMessage.Descriptor + { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Capability() { + public Capability() + { OnConstruction(); } @@ -119,7 +127,8 @@ public Capability() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Capability(Capability other) : this() { + public Capability(Capability other) : this() + { name_ = other.name_; value_ = other.value_ != null ? other.value_.Clone() : null; _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); @@ -127,7 +136,8 @@ public Capability(Capability other) : this() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Capability Clone() { + public Capability Clone() + { return new Capability(this); } @@ -138,22 +148,26 @@ public Capability Clone() { private string name_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public string Name { + public string Name + { get { return name_ ?? NameDefaultValue; } - set { + set + { name_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } /// Gets whether the "name" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasName { + public bool HasName + { get { return name_ != null; } } /// Clears the value of the "name" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearName() { + public void ClearName() + { name_ = null; } @@ -162,26 +176,32 @@ public void ClearName() { private global::Mysqlx.Datatypes.Any value_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public global::Mysqlx.Datatypes.Any Value { + public global::Mysqlx.Datatypes.Any Value + { get { return value_; } - set { + set + { value_ = value; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override bool Equals(object other) { + public override bool Equals(object other) + { return Equals(other as Capability); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool Equals(Capability other) { - if (ReferenceEquals(other, null)) { + public bool Equals(Capability other) + { + if (ReferenceEquals(other, null)) + { return false; } - if (ReferenceEquals(other, this)) { + if (ReferenceEquals(other, this)) + { return true; } if (Name != other.Name) return false; @@ -191,11 +211,13 @@ public bool Equals(Capability other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override int GetHashCode() { + public override int GetHashCode() + { int hash = 1; if (HasName) hash ^= Name.GetHashCode(); if (value_ != null) hash ^= Value.GetHashCode(); - if (_unknownFields != null) { + if (_unknownFields != null) + { hash ^= _unknownFields.GetHashCode(); } return hash; @@ -203,16 +225,18 @@ public override int GetHashCode() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override string ToString() { + public override string ToString() + { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void WriteTo(pb::CodedOutputStream output) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void WriteTo(pb::CodedOutputStream output) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE output.WriteRawMessage(this); - #else +#else if (HasName) { output.WriteRawTag(10); output.WriteString(Name); @@ -224,38 +248,46 @@ public void WriteTo(pb::CodedOutputStream output) { if (_unknownFields != null) { _unknownFields.WriteTo(output); } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { - if (HasName) { + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) + { + if (HasName) + { output.WriteRawTag(10); output.WriteString(Name); } - if (value_ != null) { + if (value_ != null) + { output.WriteRawTag(18); output.WriteMessage(Value); } - if (_unknownFields != null) { + if (_unknownFields != null) + { _unknownFields.WriteTo(ref output); } } - #endif +#endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public int CalculateSize() { + public int CalculateSize() + { int size = 0; - if (HasName) { + if (HasName) + { size += 1 + pb::CodedOutputStream.ComputeStringSize(Name); } - if (value_ != null) { + if (value_ != null) + { size += 1 + pb::CodedOutputStream.ComputeMessageSize(Value); } - if (_unknownFields != null) { + if (_unknownFields != null) + { size += _unknownFields.CalculateSize(); } return size; @@ -263,15 +295,20 @@ public int CalculateSize() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(Capability other) { - if (other == null) { + public void MergeFrom(Capability other) + { + if (other == null) + { return; } - if (other.HasName) { + if (other.HasName) + { Name = other.Name; } - if (other.value_ != null) { - if (value_ == null) { + if (other.value_ != null) + { + if (value_ == null) + { Value = new global::Mysqlx.Datatypes.Any(); } Value.MergeFrom(other.Value); @@ -281,10 +318,11 @@ public void MergeFrom(Capability other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(pb::CodedInputStream input) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void MergeFrom(pb::CodedInputStream input) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE input.ReadRawMessage(this); - #else +#else uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { @@ -304,34 +342,40 @@ public void MergeFrom(pb::CodedInputStream input) { } } } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) + { uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { + while ((tag = input.ReadTag()) != 0) + { + switch (tag) + { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; - case 10: { - Name = input.ReadString(); - break; - } - case 18: { - if (value_ == null) { - Value = new global::Mysqlx.Datatypes.Any(); + case 10: + { + Name = input.ReadString(); + break; + } + case 18: + { + if (value_ == null) + { + Value = new global::Mysqlx.Datatypes.Any(); + } + input.ReadMessage(Value); + break; } - input.ReadMessage(Value); - break; - } } } } - #endif +#endif } @@ -341,10 +385,11 @@ public void MergeFrom(pb::CodedInputStream input) { /// ///list of Capability /// - internal sealed partial class Capabilities : pb::IMessage - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] + public sealed partial class Capabilities : pb::IMessage +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE , pb::IBufferMessage - #endif +#endif { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Capabilities()); private pb::UnknownFieldSet _unknownFields; @@ -354,19 +399,22 @@ internal sealed partial class Capabilities : pb::IMessage [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static pbr::MessageDescriptor Descriptor { + public static pbr::MessageDescriptor Descriptor + { get { return global::Mysqlx.Connection.MysqlxConnectionReflection.Descriptor.MessageTypes[1]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - pbr::MessageDescriptor pb::IMessage.Descriptor { + pbr::MessageDescriptor pb::IMessage.Descriptor + { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Capabilities() { + public Capabilities() + { OnConstruction(); } @@ -374,14 +422,16 @@ public Capabilities() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Capabilities(Capabilities other) : this() { + public Capabilities(Capabilities other) : this() + { capabilities_ = other.capabilities_.Clone(); _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Capabilities Clone() { + public Capabilities Clone() + { return new Capabilities(this); } @@ -392,35 +442,42 @@ public Capabilities Clone() { private readonly pbc::RepeatedField capabilities_ = new pbc::RepeatedField(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public pbc::RepeatedField Capabilities_ { + public pbc::RepeatedField Capabilities_ + { get { return capabilities_; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override bool Equals(object other) { + public override bool Equals(object other) + { return Equals(other as Capabilities); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool Equals(Capabilities other) { - if (ReferenceEquals(other, null)) { + public bool Equals(Capabilities other) + { + if (ReferenceEquals(other, null)) + { return false; } - if (ReferenceEquals(other, this)) { + if (ReferenceEquals(other, this)) + { return true; } - if(!capabilities_.Equals(other.capabilities_)) return false; + if (!capabilities_.Equals(other.capabilities_)) return false; return Equals(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override int GetHashCode() { + public override int GetHashCode() + { int hash = 1; hash ^= capabilities_.GetHashCode(); - if (_unknownFields != null) { + if (_unknownFields != null) + { hash ^= _unknownFields.GetHashCode(); } return hash; @@ -428,40 +485,46 @@ public override int GetHashCode() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override string ToString() { + public override string ToString() + { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void WriteTo(pb::CodedOutputStream output) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void WriteTo(pb::CodedOutputStream output) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE output.WriteRawMessage(this); - #else +#else capabilities_.WriteTo(output, _repeated_capabilities_codec); if (_unknownFields != null) { _unknownFields.WriteTo(output); } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) + { capabilities_.WriteTo(ref output, _repeated_capabilities_codec); - if (_unknownFields != null) { + if (_unknownFields != null) + { _unknownFields.WriteTo(ref output); } } - #endif +#endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public int CalculateSize() { + public int CalculateSize() + { int size = 0; size += capabilities_.CalculateSize(_repeated_capabilities_codec); - if (_unknownFields != null) { + if (_unknownFields != null) + { size += _unknownFields.CalculateSize(); } return size; @@ -469,8 +532,10 @@ public int CalculateSize() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(Capabilities other) { - if (other == null) { + public void MergeFrom(Capabilities other) + { + if (other == null) + { return; } capabilities_.Add(other.capabilities_); @@ -479,10 +544,11 @@ public void MergeFrom(Capabilities other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(pb::CodedInputStream input) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void MergeFrom(pb::CodedInputStream input) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE input.ReadRawMessage(this); - #else +#else uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { @@ -495,27 +561,31 @@ public void MergeFrom(pb::CodedInputStream input) { } } } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) + { uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { + while ((tag = input.ReadTag()) != 0) + { + switch (tag) + { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; - case 10: { - capabilities_.AddEntriesFrom(ref input, _repeated_capabilities_codec); - break; - } + case 10: + { + capabilities_.AddEntriesFrom(ref input, _repeated_capabilities_codec); + break; + } } } } - #endif +#endif } @@ -525,10 +595,11 @@ public void MergeFrom(pb::CodedInputStream input) { /// ///@returns @ref Mysqlx::Connection::Capabilities or @ref Mysqlx::Error /// - internal sealed partial class CapabilitiesGet : pb::IMessage - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] + public sealed partial class CapabilitiesGet : pb::IMessage +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE , pb::IBufferMessage - #endif +#endif { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new CapabilitiesGet()); private pb::UnknownFieldSet _unknownFields; @@ -538,19 +609,22 @@ internal sealed partial class CapabilitiesGet : pb::IMessage [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static pbr::MessageDescriptor Descriptor { + public static pbr::MessageDescriptor Descriptor + { get { return global::Mysqlx.Connection.MysqlxConnectionReflection.Descriptor.MessageTypes[2]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - pbr::MessageDescriptor pb::IMessage.Descriptor { + pbr::MessageDescriptor pb::IMessage.Descriptor + { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public CapabilitiesGet() { + public CapabilitiesGet() + { OnConstruction(); } @@ -558,29 +632,35 @@ public CapabilitiesGet() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public CapabilitiesGet(CapabilitiesGet other) : this() { + public CapabilitiesGet(CapabilitiesGet other) : this() + { _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public CapabilitiesGet Clone() { + public CapabilitiesGet Clone() + { return new CapabilitiesGet(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override bool Equals(object other) { + public override bool Equals(object other) + { return Equals(other as CapabilitiesGet); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool Equals(CapabilitiesGet other) { - if (ReferenceEquals(other, null)) { + public bool Equals(CapabilitiesGet other) + { + if (ReferenceEquals(other, null)) + { return false; } - if (ReferenceEquals(other, this)) { + if (ReferenceEquals(other, this)) + { return true; } return Equals(_unknownFields, other._unknownFields); @@ -588,9 +668,11 @@ public bool Equals(CapabilitiesGet other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override int GetHashCode() { + public override int GetHashCode() + { int hash = 1; - if (_unknownFields != null) { + if (_unknownFields != null) + { hash ^= _unknownFields.GetHashCode(); } return hash; @@ -598,37 +680,43 @@ public override int GetHashCode() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override string ToString() { + public override string ToString() + { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void WriteTo(pb::CodedOutputStream output) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void WriteTo(pb::CodedOutputStream output) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE output.WriteRawMessage(this); - #else +#else if (_unknownFields != null) { _unknownFields.WriteTo(output); } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { - if (_unknownFields != null) { + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) + { + if (_unknownFields != null) + { _unknownFields.WriteTo(ref output); } } - #endif +#endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public int CalculateSize() { + public int CalculateSize() + { int size = 0; - if (_unknownFields != null) { + if (_unknownFields != null) + { size += _unknownFields.CalculateSize(); } return size; @@ -636,8 +724,10 @@ public int CalculateSize() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(CapabilitiesGet other) { - if (other == null) { + public void MergeFrom(CapabilitiesGet other) + { + if (other == null) + { return; } _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); @@ -645,10 +735,11 @@ public void MergeFrom(CapabilitiesGet other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(pb::CodedInputStream input) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void MergeFrom(pb::CodedInputStream input) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE input.ReadRawMessage(this); - #else +#else uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { @@ -657,23 +748,26 @@ public void MergeFrom(pb::CodedInputStream input) { break; } } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) + { uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { + while ((tag = input.ReadTag()) != 0) + { + switch (tag) + { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; } } } - #endif +#endif } @@ -688,10 +782,11 @@ public void MergeFrom(pb::CodedInputStream input) { /// ///@returns @ref Mysqlx::Ok or @ref Mysqlx::Error /// - internal sealed partial class CapabilitiesSet : pb::IMessage - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] + public sealed partial class CapabilitiesSet : pb::IMessage +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE , pb::IBufferMessage - #endif +#endif { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new CapabilitiesSet()); private pb::UnknownFieldSet _unknownFields; @@ -701,19 +796,22 @@ internal sealed partial class CapabilitiesSet : pb::IMessage [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static pbr::MessageDescriptor Descriptor { + public static pbr::MessageDescriptor Descriptor + { get { return global::Mysqlx.Connection.MysqlxConnectionReflection.Descriptor.MessageTypes[3]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - pbr::MessageDescriptor pb::IMessage.Descriptor { + pbr::MessageDescriptor pb::IMessage.Descriptor + { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public CapabilitiesSet() { + public CapabilitiesSet() + { OnConstruction(); } @@ -721,14 +819,16 @@ public CapabilitiesSet() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public CapabilitiesSet(CapabilitiesSet other) : this() { + public CapabilitiesSet(CapabilitiesSet other) : this() + { capabilities_ = other.capabilities_ != null ? other.capabilities_.Clone() : null; _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public CapabilitiesSet Clone() { + public CapabilitiesSet Clone() + { return new CapabilitiesSet(this); } @@ -737,26 +837,32 @@ public CapabilitiesSet Clone() { private global::Mysqlx.Connection.Capabilities capabilities_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public global::Mysqlx.Connection.Capabilities Capabilities { + public global::Mysqlx.Connection.Capabilities Capabilities + { get { return capabilities_; } - set { + set + { capabilities_ = value; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override bool Equals(object other) { + public override bool Equals(object other) + { return Equals(other as CapabilitiesSet); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool Equals(CapabilitiesSet other) { - if (ReferenceEquals(other, null)) { + public bool Equals(CapabilitiesSet other) + { + if (ReferenceEquals(other, null)) + { return false; } - if (ReferenceEquals(other, this)) { + if (ReferenceEquals(other, this)) + { return true; } if (!object.Equals(Capabilities, other.Capabilities)) return false; @@ -765,10 +871,12 @@ public bool Equals(CapabilitiesSet other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override int GetHashCode() { + public override int GetHashCode() + { int hash = 1; if (capabilities_ != null) hash ^= Capabilities.GetHashCode(); - if (_unknownFields != null) { + if (_unknownFields != null) + { hash ^= _unknownFields.GetHashCode(); } return hash; @@ -776,16 +884,18 @@ public override int GetHashCode() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override string ToString() { + public override string ToString() + { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void WriteTo(pb::CodedOutputStream output) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void WriteTo(pb::CodedOutputStream output) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE output.WriteRawMessage(this); - #else +#else if (capabilities_ != null) { output.WriteRawTag(10); output.WriteMessage(Capabilities); @@ -793,31 +903,37 @@ public void WriteTo(pb::CodedOutputStream output) { if (_unknownFields != null) { _unknownFields.WriteTo(output); } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { - if (capabilities_ != null) { + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) + { + if (capabilities_ != null) + { output.WriteRawTag(10); output.WriteMessage(Capabilities); } - if (_unknownFields != null) { + if (_unknownFields != null) + { _unknownFields.WriteTo(ref output); } } - #endif +#endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public int CalculateSize() { + public int CalculateSize() + { int size = 0; - if (capabilities_ != null) { + if (capabilities_ != null) + { size += 1 + pb::CodedOutputStream.ComputeMessageSize(Capabilities); } - if (_unknownFields != null) { + if (_unknownFields != null) + { size += _unknownFields.CalculateSize(); } return size; @@ -825,12 +941,16 @@ public int CalculateSize() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(CapabilitiesSet other) { - if (other == null) { + public void MergeFrom(CapabilitiesSet other) + { + if (other == null) + { return; } - if (other.capabilities_ != null) { - if (capabilities_ == null) { + if (other.capabilities_ != null) + { + if (capabilities_ == null) + { Capabilities = new global::Mysqlx.Connection.Capabilities(); } Capabilities.MergeFrom(other.Capabilities); @@ -840,10 +960,11 @@ public void MergeFrom(CapabilitiesSet other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(pb::CodedInputStream input) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void MergeFrom(pb::CodedInputStream input) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE input.ReadRawMessage(this); - #else +#else uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { @@ -859,30 +980,35 @@ public void MergeFrom(pb::CodedInputStream input) { } } } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) + { uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { + while ((tag = input.ReadTag()) != 0) + { + switch (tag) + { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; - case 10: { - if (capabilities_ == null) { - Capabilities = new global::Mysqlx.Connection.Capabilities(); + case 10: + { + if (capabilities_ == null) + { + Capabilities = new global::Mysqlx.Connection.Capabilities(); + } + input.ReadMessage(Capabilities); + break; } - input.ReadMessage(Capabilities); - break; - } } } } - #endif +#endif } @@ -894,10 +1020,11 @@ public void MergeFrom(pb::CodedInputStream input) { /// ///@returns @ref Mysqlx::Ok /// - internal sealed partial class Close : pb::IMessage - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] + public sealed partial class Close : pb::IMessage +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE , pb::IBufferMessage - #endif +#endif { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Close()); private pb::UnknownFieldSet _unknownFields; @@ -907,19 +1034,22 @@ internal sealed partial class Close : pb::IMessage [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static pbr::MessageDescriptor Descriptor { + public static pbr::MessageDescriptor Descriptor + { get { return global::Mysqlx.Connection.MysqlxConnectionReflection.Descriptor.MessageTypes[4]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - pbr::MessageDescriptor pb::IMessage.Descriptor { + pbr::MessageDescriptor pb::IMessage.Descriptor + { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Close() { + public Close() + { OnConstruction(); } @@ -927,29 +1057,35 @@ public Close() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Close(Close other) : this() { + public Close(Close other) : this() + { _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Close Clone() { + public Close Clone() + { return new Close(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override bool Equals(object other) { + public override bool Equals(object other) + { return Equals(other as Close); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool Equals(Close other) { - if (ReferenceEquals(other, null)) { + public bool Equals(Close other) + { + if (ReferenceEquals(other, null)) + { return false; } - if (ReferenceEquals(other, this)) { + if (ReferenceEquals(other, this)) + { return true; } return Equals(_unknownFields, other._unknownFields); @@ -957,9 +1093,11 @@ public bool Equals(Close other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override int GetHashCode() { + public override int GetHashCode() + { int hash = 1; - if (_unknownFields != null) { + if (_unknownFields != null) + { hash ^= _unknownFields.GetHashCode(); } return hash; @@ -967,37 +1105,43 @@ public override int GetHashCode() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override string ToString() { + public override string ToString() + { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void WriteTo(pb::CodedOutputStream output) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void WriteTo(pb::CodedOutputStream output) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE output.WriteRawMessage(this); - #else +#else if (_unknownFields != null) { _unknownFields.WriteTo(output); } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { - if (_unknownFields != null) { + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) + { + if (_unknownFields != null) + { _unknownFields.WriteTo(ref output); } } - #endif +#endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public int CalculateSize() { + public int CalculateSize() + { int size = 0; - if (_unknownFields != null) { + if (_unknownFields != null) + { size += _unknownFields.CalculateSize(); } return size; @@ -1005,8 +1149,10 @@ public int CalculateSize() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(Close other) { - if (other == null) { + public void MergeFrom(Close other) + { + if (other == null) + { return; } _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); @@ -1014,10 +1160,11 @@ public void MergeFrom(Close other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(pb::CodedInputStream input) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void MergeFrom(pb::CodedInputStream input) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE input.ReadRawMessage(this); - #else +#else uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { @@ -1026,30 +1173,34 @@ public void MergeFrom(pb::CodedInputStream input) { break; } } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) + { uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { + while ((tag = input.ReadTag()) != 0) + { + switch (tag) + { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; } } } - #endif +#endif } - internal sealed partial class Compression : pb::IMessage - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] + public sealed partial class Compression : pb::IMessage +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE , pb::IBufferMessage - #endif +#endif { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Compression()); private pb::UnknownFieldSet _unknownFields; @@ -1060,19 +1211,22 @@ internal sealed partial class Compression : pb::IMessage [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static pbr::MessageDescriptor Descriptor { + public static pbr::MessageDescriptor Descriptor + { get { return global::Mysqlx.Connection.MysqlxConnectionReflection.Descriptor.MessageTypes[5]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - pbr::MessageDescriptor pb::IMessage.Descriptor { + pbr::MessageDescriptor pb::IMessage.Descriptor + { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Compression() { + public Compression() + { OnConstruction(); } @@ -1080,7 +1234,8 @@ public Compression() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Compression(Compression other) : this() { + public Compression(Compression other) : this() + { _hasBits0 = other._hasBits0; uncompressedSize_ = other.uncompressedSize_; serverMessages_ = other.serverMessages_; @@ -1091,7 +1246,8 @@ public Compression(Compression other) : this() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Compression Clone() { + public Compression Clone() + { return new Compression(this); } @@ -1102,9 +1258,11 @@ public Compression Clone() { private ulong uncompressedSize_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public ulong UncompressedSize { + public ulong UncompressedSize + { get { if ((_hasBits0 & 1) != 0) { return uncompressedSize_; } else { return UncompressedSizeDefaultValue; } } - set { + set + { _hasBits0 |= 1; uncompressedSize_ = value; } @@ -1112,13 +1270,15 @@ public ulong UncompressedSize { /// Gets whether the "uncompressed_size" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasUncompressedSize { + public bool HasUncompressedSize + { get { return (_hasBits0 & 1) != 0; } } /// Clears the value of the "uncompressed_size" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearUncompressedSize() { + public void ClearUncompressedSize() + { _hasBits0 &= ~1; } @@ -1129,9 +1289,11 @@ public void ClearUncompressedSize() { private global::Mysqlx.ServerMessages.Types.Type serverMessages_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public global::Mysqlx.ServerMessages.Types.Type ServerMessages { + public global::Mysqlx.ServerMessages.Types.Type ServerMessages + { get { if ((_hasBits0 & 2) != 0) { return serverMessages_; } else { return ServerMessagesDefaultValue; } } - set { + set + { _hasBits0 |= 2; serverMessages_ = value; } @@ -1139,13 +1301,15 @@ public void ClearUncompressedSize() { /// Gets whether the "server_messages" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasServerMessages { + public bool HasServerMessages + { get { return (_hasBits0 & 2) != 0; } } /// Clears the value of the "server_messages" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearServerMessages() { + public void ClearServerMessages() + { _hasBits0 &= ~2; } @@ -1156,9 +1320,11 @@ public void ClearServerMessages() { private global::Mysqlx.ClientMessages.Types.Type clientMessages_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public global::Mysqlx.ClientMessages.Types.Type ClientMessages { + public global::Mysqlx.ClientMessages.Types.Type ClientMessages + { get { if ((_hasBits0 & 4) != 0) { return clientMessages_; } else { return ClientMessagesDefaultValue; } } - set { + set + { _hasBits0 |= 4; clientMessages_ = value; } @@ -1166,13 +1332,15 @@ public void ClearServerMessages() { /// Gets whether the "client_messages" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasClientMessages { + public bool HasClientMessages + { get { return (_hasBits0 & 4) != 0; } } /// Clears the value of the "client_messages" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearClientMessages() { + public void ClearClientMessages() + { _hasBits0 &= ~4; } @@ -1183,38 +1351,46 @@ public void ClearClientMessages() { private pb::ByteString payload_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public pb::ByteString Payload { + public pb::ByteString Payload + { get { return payload_ ?? PayloadDefaultValue; } - set { + set + { payload_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } /// Gets whether the "payload" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasPayload { + public bool HasPayload + { get { return payload_ != null; } } /// Clears the value of the "payload" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearPayload() { + public void ClearPayload() + { payload_ = null; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override bool Equals(object other) { + public override bool Equals(object other) + { return Equals(other as Compression); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool Equals(Compression other) { - if (ReferenceEquals(other, null)) { + public bool Equals(Compression other) + { + if (ReferenceEquals(other, null)) + { return false; } - if (ReferenceEquals(other, this)) { + if (ReferenceEquals(other, this)) + { return true; } if (UncompressedSize != other.UncompressedSize) return false; @@ -1226,13 +1402,15 @@ public bool Equals(Compression other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override int GetHashCode() { + public override int GetHashCode() + { int hash = 1; if (HasUncompressedSize) hash ^= UncompressedSize.GetHashCode(); if (HasServerMessages) hash ^= ServerMessages.GetHashCode(); if (HasClientMessages) hash ^= ClientMessages.GetHashCode(); if (HasPayload) hash ^= Payload.GetHashCode(); - if (_unknownFields != null) { + if (_unknownFields != null) + { hash ^= _unknownFields.GetHashCode(); } return hash; @@ -1240,16 +1418,18 @@ public override int GetHashCode() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override string ToString() { + public override string ToString() + { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void WriteTo(pb::CodedOutputStream output) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void WriteTo(pb::CodedOutputStream output) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE output.WriteRawMessage(this); - #else +#else if (HasUncompressedSize) { output.WriteRawTag(8); output.WriteUInt64(UncompressedSize); @@ -1269,52 +1449,64 @@ public void WriteTo(pb::CodedOutputStream output) { if (_unknownFields != null) { _unknownFields.WriteTo(output); } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { - if (HasUncompressedSize) { + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) + { + if (HasUncompressedSize) + { output.WriteRawTag(8); output.WriteUInt64(UncompressedSize); } - if (HasServerMessages) { + if (HasServerMessages) + { output.WriteRawTag(16); - output.WriteEnum((int) ServerMessages); + output.WriteEnum((int)ServerMessages); } - if (HasClientMessages) { + if (HasClientMessages) + { output.WriteRawTag(24); - output.WriteEnum((int) ClientMessages); + output.WriteEnum((int)ClientMessages); } - if (HasPayload) { + if (HasPayload) + { output.WriteRawTag(34); output.WriteBytes(Payload); } - if (_unknownFields != null) { + if (_unknownFields != null) + { _unknownFields.WriteTo(ref output); } } - #endif +#endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public int CalculateSize() { + public int CalculateSize() + { int size = 0; - if (HasUncompressedSize) { + if (HasUncompressedSize) + { size += 1 + pb::CodedOutputStream.ComputeUInt64Size(UncompressedSize); } - if (HasServerMessages) { - size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) ServerMessages); + if (HasServerMessages) + { + size += 1 + pb::CodedOutputStream.ComputeEnumSize((int)ServerMessages); } - if (HasClientMessages) { - size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) ClientMessages); + if (HasClientMessages) + { + size += 1 + pb::CodedOutputStream.ComputeEnumSize((int)ClientMessages); } - if (HasPayload) { + if (HasPayload) + { size += 1 + pb::CodedOutputStream.ComputeBytesSize(Payload); } - if (_unknownFields != null) { + if (_unknownFields != null) + { size += _unknownFields.CalculateSize(); } return size; @@ -1322,20 +1514,26 @@ public int CalculateSize() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(Compression other) { - if (other == null) { + public void MergeFrom(Compression other) + { + if (other == null) + { return; } - if (other.HasUncompressedSize) { + if (other.HasUncompressedSize) + { UncompressedSize = other.UncompressedSize; } - if (other.HasServerMessages) { + if (other.HasServerMessages) + { ServerMessages = other.ServerMessages; } - if (other.HasClientMessages) { + if (other.HasClientMessages) + { ClientMessages = other.ClientMessages; } - if (other.HasPayload) { + if (other.HasPayload) + { Payload = other.Payload; } _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); @@ -1343,10 +1541,11 @@ public void MergeFrom(Compression other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(pb::CodedInputStream input) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void MergeFrom(pb::CodedInputStream input) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE input.ReadRawMessage(this); - #else +#else uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { @@ -1371,39 +1570,46 @@ public void MergeFrom(pb::CodedInputStream input) { } } } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) + { uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { + while ((tag = input.ReadTag()) != 0) + { + switch (tag) + { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; - case 8: { - UncompressedSize = input.ReadUInt64(); - break; - } - case 16: { - ServerMessages = (global::Mysqlx.ServerMessages.Types.Type) input.ReadEnum(); - break; - } - case 24: { - ClientMessages = (global::Mysqlx.ClientMessages.Types.Type) input.ReadEnum(); - break; - } - case 34: { - Payload = input.ReadBytes(); - break; - } + case 8: + { + UncompressedSize = input.ReadUInt64(); + break; + } + case 16: + { + ServerMessages = (global::Mysqlx.ServerMessages.Types.Type)input.ReadEnum(); + break; + } + case 24: + { + ClientMessages = (global::Mysqlx.ClientMessages.Types.Type)input.ReadEnum(); + break; + } + case 34: + { + Payload = input.ReadBytes(); + break; + } } } } - #endif +#endif } diff --git a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxCrud.cs b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxCrud.cs index bef4f3ff2..bd891ca50 100644 --- a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxCrud.cs +++ b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxCrud.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2022, 2023, Oracle and/or its affiliates. +// Copyright (c) 2023, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as @@ -7,7 +7,7 @@ // This program is also distributed with certain software (including // but not limited to OpenSSL) that is licensed under separate terms, // as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an +// documentation. The authors of MySQL hereby grant you an // additional permission to link the program and your derivative works // with the separately licensed software that they have included with // MySQL. @@ -37,19 +37,23 @@ using pbc = global::Google.Protobuf.Collections; using pbr = global::Google.Protobuf.Reflection; using scg = global::System.Collections.Generic; -namespace Mysqlx.Crud { +namespace Mysqlx.Crud +{ /// Holder for reflection information generated from mysqlx_crud.proto - internal static partial class MysqlxCrudReflection { + public static partial class MysqlxCrudReflection + { #region Descriptor /// File descriptor for mysqlx_crud.proto - public static pbr::FileDescriptor Descriptor { + public static pbr::FileDescriptor Descriptor + { get { return descriptor; } } private static pbr::FileDescriptor descriptor; - static MysqlxCrudReflection() { + static MysqlxCrudReflection() + { byte[] descriptorData = global::System.Convert.FromBase64String( string.Concat( "ChFteXNxbHhfY3J1ZC5wcm90bxILTXlzcWx4LkNydWQaDG15c3FseC5wcm90", @@ -128,7 +132,7 @@ static MysqlxCrudReflection() { "QhkKF2NvbS5teXNxbC5jai54LnByb3RvYnVm")); descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { global::Mysqlx.MysqlxReflection.Descriptor, global::Mysqlx.Expr.MysqlxExprReflection.Descriptor, global::Mysqlx.Datatypes.MysqlxDatatypesReflection.Descriptor, }, - new pbr::GeneratedClrTypeInfo(new[] {typeof(global::Mysqlx.Crud.DataModel), typeof(global::Mysqlx.Crud.ViewAlgorithm), typeof(global::Mysqlx.Crud.ViewSqlSecurity), typeof(global::Mysqlx.Crud.ViewCheckOption), }, null, new pbr::GeneratedClrTypeInfo[] { + new pbr::GeneratedClrTypeInfo(new[] { typeof(global::Mysqlx.Crud.DataModel), typeof(global::Mysqlx.Crud.ViewAlgorithm), typeof(global::Mysqlx.Crud.ViewSqlSecurity), typeof(global::Mysqlx.Crud.ViewCheckOption), }, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Mysqlx.Crud.Column), global::Mysqlx.Crud.Column.Parser, new[]{ "Name", "Alias", "DocumentPath" }, null, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Mysqlx.Crud.Projection), global::Mysqlx.Crud.Projection.Parser, new[]{ "Source", "Alias" }, null, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Mysqlx.Crud.Collection), global::Mysqlx.Crud.Collection.Parser, new[]{ "Name", "Schema" }, null, null, null, null), @@ -153,7 +157,8 @@ static MysqlxCrudReflection() { ///* ///DataModel to use for filters, names, ... /// - internal enum DataModel { + public enum DataModel + { [pbr::OriginalName("DOCUMENT")] Document = 1, [pbr::OriginalName("TABLE")] Table = 2, } @@ -162,7 +167,8 @@ internal enum DataModel { ///* ///ViewAlgorithm defines how MySQL Server processes the view /// - internal enum ViewAlgorithm { + public enum ViewAlgorithm + { /// ///* MySQL chooses which algorithm to use /// @@ -184,7 +190,8 @@ internal enum ViewAlgorithm { ///executed; this means that VIEW can be executed with current user permissions or ///with permissions of the user who defined the VIEW /// - internal enum ViewSqlSecurity { + public enum ViewSqlSecurity + { /// ///* use current user permissions /// @@ -200,7 +207,8 @@ internal enum ViewSqlSecurity { ///ViewCheckOption limits the write operations done on a `VIEW` ///(`INSERT`, `UPDATE`, `DELETE`) to rows in which the `WHERE` clause is `TRUE` /// - internal enum ViewCheckOption { + public enum ViewCheckOption + { /// ///* the view WHERE clause is checked, but no underlying views are checked /// @@ -215,10 +223,11 @@ internal enum ViewCheckOption { #endregion #region Messages - internal sealed partial class Column : pb::IMessage - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] + public sealed partial class Column : pb::IMessage +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE , pb::IBufferMessage - #endif +#endif { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Column()); private pb::UnknownFieldSet _unknownFields; @@ -228,19 +237,22 @@ internal sealed partial class Column : pb::IMessage [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static pbr::MessageDescriptor Descriptor { + public static pbr::MessageDescriptor Descriptor + { get { return global::Mysqlx.Crud.MysqlxCrudReflection.Descriptor.MessageTypes[0]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - pbr::MessageDescriptor pb::IMessage.Descriptor { + pbr::MessageDescriptor pb::IMessage.Descriptor + { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Column() { + public Column() + { OnConstruction(); } @@ -248,7 +260,8 @@ public Column() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Column(Column other) : this() { + public Column(Column other) : this() + { name_ = other.name_; alias_ = other.alias_; documentPath_ = other.documentPath_.Clone(); @@ -257,7 +270,8 @@ public Column(Column other) : this() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Column Clone() { + public Column Clone() + { return new Column(this); } @@ -268,22 +282,26 @@ public Column Clone() { private string name_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public string Name { + public string Name + { get { return name_ ?? NameDefaultValue; } - set { + set + { name_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } /// Gets whether the "name" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasName { + public bool HasName + { get { return name_ != null; } } /// Clears the value of the "name" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearName() { + public void ClearName() + { name_ = null; } @@ -294,22 +312,26 @@ public void ClearName() { private string alias_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public string Alias { + public string Alias + { get { return alias_ ?? AliasDefaultValue; } - set { + set + { alias_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } /// Gets whether the "alias" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasAlias { + public bool HasAlias + { get { return alias_ != null; } } /// Clears the value of the "alias" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearAlias() { + public void ClearAlias() + { alias_ = null; } @@ -320,39 +342,46 @@ public void ClearAlias() { private readonly pbc::RepeatedField documentPath_ = new pbc::RepeatedField(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public pbc::RepeatedField DocumentPath { + public pbc::RepeatedField DocumentPath + { get { return documentPath_; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override bool Equals(object other) { + public override bool Equals(object other) + { return Equals(other as Column); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool Equals(Column other) { - if (ReferenceEquals(other, null)) { + public bool Equals(Column other) + { + if (ReferenceEquals(other, null)) + { return false; } - if (ReferenceEquals(other, this)) { + if (ReferenceEquals(other, this)) + { return true; } if (Name != other.Name) return false; if (Alias != other.Alias) return false; - if(!documentPath_.Equals(other.documentPath_)) return false; + if (!documentPath_.Equals(other.documentPath_)) return false; return Equals(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override int GetHashCode() { + public override int GetHashCode() + { int hash = 1; if (HasName) hash ^= Name.GetHashCode(); if (HasAlias) hash ^= Alias.GetHashCode(); hash ^= documentPath_.GetHashCode(); - if (_unknownFields != null) { + if (_unknownFields != null) + { hash ^= _unknownFields.GetHashCode(); } return hash; @@ -360,16 +389,18 @@ public override int GetHashCode() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override string ToString() { + public override string ToString() + { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void WriteTo(pb::CodedOutputStream output) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void WriteTo(pb::CodedOutputStream output) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE output.WriteRawMessage(this); - #else +#else if (HasName) { output.WriteRawTag(10); output.WriteString(Name); @@ -382,40 +413,48 @@ public void WriteTo(pb::CodedOutputStream output) { if (_unknownFields != null) { _unknownFields.WriteTo(output); } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { - if (HasName) { + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) + { + if (HasName) + { output.WriteRawTag(10); output.WriteString(Name); } - if (HasAlias) { + if (HasAlias) + { output.WriteRawTag(18); output.WriteString(Alias); } documentPath_.WriteTo(ref output, _repeated_documentPath_codec); - if (_unknownFields != null) { + if (_unknownFields != null) + { _unknownFields.WriteTo(ref output); } } - #endif +#endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public int CalculateSize() { + public int CalculateSize() + { int size = 0; - if (HasName) { + if (HasName) + { size += 1 + pb::CodedOutputStream.ComputeStringSize(Name); } - if (HasAlias) { + if (HasAlias) + { size += 1 + pb::CodedOutputStream.ComputeStringSize(Alias); } size += documentPath_.CalculateSize(_repeated_documentPath_codec); - if (_unknownFields != null) { + if (_unknownFields != null) + { size += _unknownFields.CalculateSize(); } return size; @@ -423,14 +462,18 @@ public int CalculateSize() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(Column other) { - if (other == null) { + public void MergeFrom(Column other) + { + if (other == null) + { return; } - if (other.HasName) { + if (other.HasName) + { Name = other.Name; } - if (other.HasAlias) { + if (other.HasAlias) + { Alias = other.Alias; } documentPath_.Add(other.documentPath_); @@ -439,10 +482,11 @@ public void MergeFrom(Column other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(pb::CodedInputStream input) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void MergeFrom(pb::CodedInputStream input) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE input.ReadRawMessage(this); - #else +#else uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { @@ -463,42 +507,49 @@ public void MergeFrom(pb::CodedInputStream input) { } } } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) + { uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { + while ((tag = input.ReadTag()) != 0) + { + switch (tag) + { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; - case 10: { - Name = input.ReadString(); - break; - } - case 18: { - Alias = input.ReadString(); - break; - } - case 26: { - documentPath_.AddEntriesFrom(ref input, _repeated_documentPath_codec); - break; - } + case 10: + { + Name = input.ReadString(); + break; + } + case 18: + { + Alias = input.ReadString(); + break; + } + case 26: + { + documentPath_.AddEntriesFrom(ref input, _repeated_documentPath_codec); + break; + } } } } - #endif +#endif } - internal sealed partial class Projection : pb::IMessage - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] + public sealed partial class Projection : pb::IMessage +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE , pb::IBufferMessage - #endif +#endif { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Projection()); private pb::UnknownFieldSet _unknownFields; @@ -508,19 +559,22 @@ internal sealed partial class Projection : pb::IMessage [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static pbr::MessageDescriptor Descriptor { + public static pbr::MessageDescriptor Descriptor + { get { return global::Mysqlx.Crud.MysqlxCrudReflection.Descriptor.MessageTypes[1]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - pbr::MessageDescriptor pb::IMessage.Descriptor { + pbr::MessageDescriptor pb::IMessage.Descriptor + { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Projection() { + public Projection() + { OnConstruction(); } @@ -528,7 +582,8 @@ public Projection() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Projection(Projection other) : this() { + public Projection(Projection other) : this() + { source_ = other.source_ != null ? other.source_.Clone() : null; alias_ = other.alias_; _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); @@ -536,7 +591,8 @@ public Projection(Projection other) : this() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Projection Clone() { + public Projection Clone() + { return new Projection(this); } @@ -549,9 +605,11 @@ public Projection Clone() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public global::Mysqlx.Expr.Expr Source { + public global::Mysqlx.Expr.Expr Source + { get { return source_; } - set { + set + { source_ = value; } } @@ -567,38 +625,46 @@ public Projection Clone() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public string Alias { + public string Alias + { get { return alias_ ?? AliasDefaultValue; } - set { + set + { alias_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } /// Gets whether the "alias" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasAlias { + public bool HasAlias + { get { return alias_ != null; } } /// Clears the value of the "alias" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearAlias() { + public void ClearAlias() + { alias_ = null; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override bool Equals(object other) { + public override bool Equals(object other) + { return Equals(other as Projection); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool Equals(Projection other) { - if (ReferenceEquals(other, null)) { + public bool Equals(Projection other) + { + if (ReferenceEquals(other, null)) + { return false; } - if (ReferenceEquals(other, this)) { + if (ReferenceEquals(other, this)) + { return true; } if (!object.Equals(Source, other.Source)) return false; @@ -608,11 +674,13 @@ public bool Equals(Projection other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override int GetHashCode() { + public override int GetHashCode() + { int hash = 1; if (source_ != null) hash ^= Source.GetHashCode(); if (HasAlias) hash ^= Alias.GetHashCode(); - if (_unknownFields != null) { + if (_unknownFields != null) + { hash ^= _unknownFields.GetHashCode(); } return hash; @@ -620,16 +688,18 @@ public override int GetHashCode() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override string ToString() { + public override string ToString() + { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void WriteTo(pb::CodedOutputStream output) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void WriteTo(pb::CodedOutputStream output) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE output.WriteRawMessage(this); - #else +#else if (source_ != null) { output.WriteRawTag(10); output.WriteMessage(Source); @@ -641,38 +711,46 @@ public void WriteTo(pb::CodedOutputStream output) { if (_unknownFields != null) { _unknownFields.WriteTo(output); } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { - if (source_ != null) { + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) + { + if (source_ != null) + { output.WriteRawTag(10); output.WriteMessage(Source); } - if (HasAlias) { + if (HasAlias) + { output.WriteRawTag(18); output.WriteString(Alias); } - if (_unknownFields != null) { + if (_unknownFields != null) + { _unknownFields.WriteTo(ref output); } } - #endif +#endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public int CalculateSize() { + public int CalculateSize() + { int size = 0; - if (source_ != null) { + if (source_ != null) + { size += 1 + pb::CodedOutputStream.ComputeMessageSize(Source); } - if (HasAlias) { + if (HasAlias) + { size += 1 + pb::CodedOutputStream.ComputeStringSize(Alias); } - if (_unknownFields != null) { + if (_unknownFields != null) + { size += _unknownFields.CalculateSize(); } return size; @@ -680,17 +758,22 @@ public int CalculateSize() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(Projection other) { - if (other == null) { + public void MergeFrom(Projection other) + { + if (other == null) + { return; } - if (other.source_ != null) { - if (source_ == null) { + if (other.source_ != null) + { + if (source_ == null) + { Source = new global::Mysqlx.Expr.Expr(); } Source.MergeFrom(other.Source); } - if (other.HasAlias) { + if (other.HasAlias) + { Alias = other.Alias; } _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); @@ -698,10 +781,11 @@ public void MergeFrom(Projection other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(pb::CodedInputStream input) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void MergeFrom(pb::CodedInputStream input) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE input.ReadRawMessage(this); - #else +#else uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { @@ -721,41 +805,48 @@ public void MergeFrom(pb::CodedInputStream input) { } } } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) + { uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { + while ((tag = input.ReadTag()) != 0) + { + switch (tag) + { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; - case 10: { - if (source_ == null) { - Source = new global::Mysqlx.Expr.Expr(); + case 10: + { + if (source_ == null) + { + Source = new global::Mysqlx.Expr.Expr(); + } + input.ReadMessage(Source); + break; + } + case 18: + { + Alias = input.ReadString(); + break; } - input.ReadMessage(Source); - break; - } - case 18: { - Alias = input.ReadString(); - break; - } } } } - #endif +#endif } - internal sealed partial class Collection : pb::IMessage - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] + public sealed partial class Collection : pb::IMessage +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE , pb::IBufferMessage - #endif +#endif { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Collection()); private pb::UnknownFieldSet _unknownFields; @@ -765,19 +856,22 @@ internal sealed partial class Collection : pb::IMessage [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static pbr::MessageDescriptor Descriptor { + public static pbr::MessageDescriptor Descriptor + { get { return global::Mysqlx.Crud.MysqlxCrudReflection.Descriptor.MessageTypes[2]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - pbr::MessageDescriptor pb::IMessage.Descriptor { + pbr::MessageDescriptor pb::IMessage.Descriptor + { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Collection() { + public Collection() + { OnConstruction(); } @@ -785,7 +879,8 @@ public Collection() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Collection(Collection other) : this() { + public Collection(Collection other) : this() + { name_ = other.name_; schema_ = other.schema_; _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); @@ -793,7 +888,8 @@ public Collection(Collection other) : this() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Collection Clone() { + public Collection Clone() + { return new Collection(this); } @@ -804,22 +900,26 @@ public Collection Clone() { private string name_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public string Name { + public string Name + { get { return name_ ?? NameDefaultValue; } - set { + set + { name_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } /// Gets whether the "name" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasName { + public bool HasName + { get { return name_ != null; } } /// Clears the value of the "name" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearName() { + public void ClearName() + { name_ = null; } @@ -830,38 +930,46 @@ public void ClearName() { private string schema_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public string Schema { + public string Schema + { get { return schema_ ?? SchemaDefaultValue; } - set { + set + { schema_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } /// Gets whether the "schema" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasSchema { + public bool HasSchema + { get { return schema_ != null; } } /// Clears the value of the "schema" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearSchema() { + public void ClearSchema() + { schema_ = null; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override bool Equals(object other) { + public override bool Equals(object other) + { return Equals(other as Collection); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool Equals(Collection other) { - if (ReferenceEquals(other, null)) { + public bool Equals(Collection other) + { + if (ReferenceEquals(other, null)) + { return false; } - if (ReferenceEquals(other, this)) { + if (ReferenceEquals(other, this)) + { return true; } if (Name != other.Name) return false; @@ -871,11 +979,13 @@ public bool Equals(Collection other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override int GetHashCode() { + public override int GetHashCode() + { int hash = 1; if (HasName) hash ^= Name.GetHashCode(); if (HasSchema) hash ^= Schema.GetHashCode(); - if (_unknownFields != null) { + if (_unknownFields != null) + { hash ^= _unknownFields.GetHashCode(); } return hash; @@ -883,16 +993,18 @@ public override int GetHashCode() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override string ToString() { + public override string ToString() + { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void WriteTo(pb::CodedOutputStream output) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void WriteTo(pb::CodedOutputStream output) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE output.WriteRawMessage(this); - #else +#else if (HasName) { output.WriteRawTag(10); output.WriteString(Name); @@ -904,38 +1016,46 @@ public void WriteTo(pb::CodedOutputStream output) { if (_unknownFields != null) { _unknownFields.WriteTo(output); } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { - if (HasName) { + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) + { + if (HasName) + { output.WriteRawTag(10); output.WriteString(Name); } - if (HasSchema) { + if (HasSchema) + { output.WriteRawTag(18); output.WriteString(Schema); } - if (_unknownFields != null) { + if (_unknownFields != null) + { _unknownFields.WriteTo(ref output); } } - #endif +#endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public int CalculateSize() { + public int CalculateSize() + { int size = 0; - if (HasName) { + if (HasName) + { size += 1 + pb::CodedOutputStream.ComputeStringSize(Name); } - if (HasSchema) { + if (HasSchema) + { size += 1 + pb::CodedOutputStream.ComputeStringSize(Schema); } - if (_unknownFields != null) { + if (_unknownFields != null) + { size += _unknownFields.CalculateSize(); } return size; @@ -943,14 +1063,18 @@ public int CalculateSize() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(Collection other) { - if (other == null) { + public void MergeFrom(Collection other) + { + if (other == null) + { return; } - if (other.HasName) { + if (other.HasName) + { Name = other.Name; } - if (other.HasSchema) { + if (other.HasSchema) + { Schema = other.Schema; } _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); @@ -958,10 +1082,11 @@ public void MergeFrom(Collection other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(pb::CodedInputStream input) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void MergeFrom(pb::CodedInputStream input) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE input.ReadRawMessage(this); - #else +#else uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { @@ -978,38 +1103,44 @@ public void MergeFrom(pb::CodedInputStream input) { } } } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) + { uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { + while ((tag = input.ReadTag()) != 0) + { + switch (tag) + { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; - case 10: { - Name = input.ReadString(); - break; - } - case 18: { - Schema = input.ReadString(); - break; - } + case 10: + { + Name = input.ReadString(); + break; + } + case 18: + { + Schema = input.ReadString(); + break; + } } } } - #endif +#endif } - internal sealed partial class Limit : pb::IMessage - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] + public sealed partial class Limit : pb::IMessage +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE , pb::IBufferMessage - #endif +#endif { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Limit()); private pb::UnknownFieldSet _unknownFields; @@ -1020,19 +1151,22 @@ internal sealed partial class Limit : pb::IMessage [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static pbr::MessageDescriptor Descriptor { + public static pbr::MessageDescriptor Descriptor + { get { return global::Mysqlx.Crud.MysqlxCrudReflection.Descriptor.MessageTypes[3]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - pbr::MessageDescriptor pb::IMessage.Descriptor { + pbr::MessageDescriptor pb::IMessage.Descriptor + { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Limit() { + public Limit() + { OnConstruction(); } @@ -1040,7 +1174,8 @@ public Limit() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Limit(Limit other) : this() { + public Limit(Limit other) : this() + { _hasBits0 = other._hasBits0; rowCount_ = other.rowCount_; offset_ = other.offset_; @@ -1049,7 +1184,8 @@ public Limit(Limit other) : this() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Limit Clone() { + public Limit Clone() + { return new Limit(this); } @@ -1063,9 +1199,11 @@ public Limit Clone() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public ulong RowCount { + public ulong RowCount + { get { if ((_hasBits0 & 1) != 0) { return rowCount_; } else { return RowCountDefaultValue; } } - set { + set + { _hasBits0 |= 1; rowCount_ = value; } @@ -1073,13 +1211,15 @@ public ulong RowCount { /// Gets whether the "row_count" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasRowCount { + public bool HasRowCount + { get { return (_hasBits0 & 1) != 0; } } /// Clears the value of the "row_count" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearRowCount() { + public void ClearRowCount() + { _hasBits0 &= ~1; } @@ -1093,9 +1233,11 @@ public void ClearRowCount() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public ulong Offset { + public ulong Offset + { get { if ((_hasBits0 & 2) != 0) { return offset_; } else { return OffsetDefaultValue; } } - set { + set + { _hasBits0 |= 2; offset_ = value; } @@ -1103,29 +1245,35 @@ public ulong Offset { /// Gets whether the "offset" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasOffset { + public bool HasOffset + { get { return (_hasBits0 & 2) != 0; } } /// Clears the value of the "offset" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearOffset() { + public void ClearOffset() + { _hasBits0 &= ~2; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override bool Equals(object other) { + public override bool Equals(object other) + { return Equals(other as Limit); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool Equals(Limit other) { - if (ReferenceEquals(other, null)) { + public bool Equals(Limit other) + { + if (ReferenceEquals(other, null)) + { return false; } - if (ReferenceEquals(other, this)) { + if (ReferenceEquals(other, this)) + { return true; } if (RowCount != other.RowCount) return false; @@ -1135,11 +1283,13 @@ public bool Equals(Limit other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override int GetHashCode() { + public override int GetHashCode() + { int hash = 1; if (HasRowCount) hash ^= RowCount.GetHashCode(); if (HasOffset) hash ^= Offset.GetHashCode(); - if (_unknownFields != null) { + if (_unknownFields != null) + { hash ^= _unknownFields.GetHashCode(); } return hash; @@ -1147,16 +1297,18 @@ public override int GetHashCode() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override string ToString() { + public override string ToString() + { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void WriteTo(pb::CodedOutputStream output) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void WriteTo(pb::CodedOutputStream output) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE output.WriteRawMessage(this); - #else +#else if (HasRowCount) { output.WriteRawTag(8); output.WriteUInt64(RowCount); @@ -1168,38 +1320,46 @@ public void WriteTo(pb::CodedOutputStream output) { if (_unknownFields != null) { _unknownFields.WriteTo(output); } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { - if (HasRowCount) { + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) + { + if (HasRowCount) + { output.WriteRawTag(8); output.WriteUInt64(RowCount); } - if (HasOffset) { + if (HasOffset) + { output.WriteRawTag(16); output.WriteUInt64(Offset); } - if (_unknownFields != null) { + if (_unknownFields != null) + { _unknownFields.WriteTo(ref output); } } - #endif +#endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public int CalculateSize() { + public int CalculateSize() + { int size = 0; - if (HasRowCount) { + if (HasRowCount) + { size += 1 + pb::CodedOutputStream.ComputeUInt64Size(RowCount); } - if (HasOffset) { + if (HasOffset) + { size += 1 + pb::CodedOutputStream.ComputeUInt64Size(Offset); } - if (_unknownFields != null) { + if (_unknownFields != null) + { size += _unknownFields.CalculateSize(); } return size; @@ -1207,14 +1367,18 @@ public int CalculateSize() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(Limit other) { - if (other == null) { + public void MergeFrom(Limit other) + { + if (other == null) + { return; } - if (other.HasRowCount) { + if (other.HasRowCount) + { RowCount = other.RowCount; } - if (other.HasOffset) { + if (other.HasOffset) + { Offset = other.Offset; } _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); @@ -1222,10 +1386,11 @@ public void MergeFrom(Limit other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(pb::CodedInputStream input) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void MergeFrom(pb::CodedInputStream input) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE input.ReadRawMessage(this); - #else +#else uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { @@ -1242,31 +1407,36 @@ public void MergeFrom(pb::CodedInputStream input) { } } } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) + { uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { + while ((tag = input.ReadTag()) != 0) + { + switch (tag) + { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; - case 8: { - RowCount = input.ReadUInt64(); - break; - } - case 16: { - Offset = input.ReadUInt64(); - break; - } + case 8: + { + RowCount = input.ReadUInt64(); + break; + } + case 16: + { + Offset = input.ReadUInt64(); + break; + } } } } - #endif +#endif } @@ -1277,10 +1447,11 @@ public void MergeFrom(pb::CodedInputStream input) { ///This message support expressions of following types Expr/literal/UINT, ///Expr/PLACEHOLDER. /// - internal sealed partial class LimitExpr : pb::IMessage - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] + public sealed partial class LimitExpr : pb::IMessage +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE , pb::IBufferMessage - #endif +#endif { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new LimitExpr()); private pb::UnknownFieldSet _unknownFields; @@ -1290,19 +1461,22 @@ internal sealed partial class LimitExpr : pb::IMessage [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static pbr::MessageDescriptor Descriptor { + public static pbr::MessageDescriptor Descriptor + { get { return global::Mysqlx.Crud.MysqlxCrudReflection.Descriptor.MessageTypes[4]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - pbr::MessageDescriptor pb::IMessage.Descriptor { + pbr::MessageDescriptor pb::IMessage.Descriptor + { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public LimitExpr() { + public LimitExpr() + { OnConstruction(); } @@ -1310,7 +1484,8 @@ public LimitExpr() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public LimitExpr(LimitExpr other) : this() { + public LimitExpr(LimitExpr other) : this() + { rowCount_ = other.rowCount_ != null ? other.rowCount_.Clone() : null; offset_ = other.offset_ != null ? other.offset_.Clone() : null; _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); @@ -1318,7 +1493,8 @@ public LimitExpr(LimitExpr other) : this() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public LimitExpr Clone() { + public LimitExpr Clone() + { return new LimitExpr(this); } @@ -1330,9 +1506,11 @@ public LimitExpr Clone() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public global::Mysqlx.Expr.Expr RowCount { + public global::Mysqlx.Expr.Expr RowCount + { get { return rowCount_; } - set { + set + { rowCount_ = value; } } @@ -1345,26 +1523,32 @@ public LimitExpr Clone() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public global::Mysqlx.Expr.Expr Offset { + public global::Mysqlx.Expr.Expr Offset + { get { return offset_; } - set { + set + { offset_ = value; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override bool Equals(object other) { + public override bool Equals(object other) + { return Equals(other as LimitExpr); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool Equals(LimitExpr other) { - if (ReferenceEquals(other, null)) { + public bool Equals(LimitExpr other) + { + if (ReferenceEquals(other, null)) + { return false; } - if (ReferenceEquals(other, this)) { + if (ReferenceEquals(other, this)) + { return true; } if (!object.Equals(RowCount, other.RowCount)) return false; @@ -1374,11 +1558,13 @@ public bool Equals(LimitExpr other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override int GetHashCode() { + public override int GetHashCode() + { int hash = 1; if (rowCount_ != null) hash ^= RowCount.GetHashCode(); if (offset_ != null) hash ^= Offset.GetHashCode(); - if (_unknownFields != null) { + if (_unknownFields != null) + { hash ^= _unknownFields.GetHashCode(); } return hash; @@ -1386,16 +1572,18 @@ public override int GetHashCode() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override string ToString() { + public override string ToString() + { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void WriteTo(pb::CodedOutputStream output) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void WriteTo(pb::CodedOutputStream output) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE output.WriteRawMessage(this); - #else +#else if (rowCount_ != null) { output.WriteRawTag(10); output.WriteMessage(RowCount); @@ -1407,38 +1595,46 @@ public void WriteTo(pb::CodedOutputStream output) { if (_unknownFields != null) { _unknownFields.WriteTo(output); } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { - if (rowCount_ != null) { + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) + { + if (rowCount_ != null) + { output.WriteRawTag(10); output.WriteMessage(RowCount); } - if (offset_ != null) { + if (offset_ != null) + { output.WriteRawTag(18); output.WriteMessage(Offset); } - if (_unknownFields != null) { + if (_unknownFields != null) + { _unknownFields.WriteTo(ref output); } } - #endif +#endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public int CalculateSize() { + public int CalculateSize() + { int size = 0; - if (rowCount_ != null) { + if (rowCount_ != null) + { size += 1 + pb::CodedOutputStream.ComputeMessageSize(RowCount); } - if (offset_ != null) { + if (offset_ != null) + { size += 1 + pb::CodedOutputStream.ComputeMessageSize(Offset); } - if (_unknownFields != null) { + if (_unknownFields != null) + { size += _unknownFields.CalculateSize(); } return size; @@ -1446,18 +1642,24 @@ public int CalculateSize() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(LimitExpr other) { - if (other == null) { + public void MergeFrom(LimitExpr other) + { + if (other == null) + { return; } - if (other.rowCount_ != null) { - if (rowCount_ == null) { + if (other.rowCount_ != null) + { + if (rowCount_ == null) + { RowCount = new global::Mysqlx.Expr.Expr(); } RowCount.MergeFrom(other.RowCount); } - if (other.offset_ != null) { - if (offset_ == null) { + if (other.offset_ != null) + { + if (offset_ == null) + { Offset = new global::Mysqlx.Expr.Expr(); } Offset.MergeFrom(other.Offset); @@ -1467,10 +1669,11 @@ public void MergeFrom(LimitExpr other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(pb::CodedInputStream input) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void MergeFrom(pb::CodedInputStream input) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE input.ReadRawMessage(this); - #else +#else uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { @@ -1493,37 +1696,44 @@ public void MergeFrom(pb::CodedInputStream input) { } } } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) + { uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { + while ((tag = input.ReadTag()) != 0) + { + switch (tag) + { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; - case 10: { - if (rowCount_ == null) { - RowCount = new global::Mysqlx.Expr.Expr(); + case 10: + { + if (rowCount_ == null) + { + RowCount = new global::Mysqlx.Expr.Expr(); + } + input.ReadMessage(RowCount); + break; } - input.ReadMessage(RowCount); - break; - } - case 18: { - if (offset_ == null) { - Offset = new global::Mysqlx.Expr.Expr(); + case 18: + { + if (offset_ == null) + { + Offset = new global::Mysqlx.Expr.Expr(); + } + input.ReadMessage(Offset); + break; } - input.ReadMessage(Offset); - break; - } } } } - #endif +#endif } @@ -1531,10 +1741,11 @@ public void MergeFrom(pb::CodedInputStream input) { ///* ///Sort order /// - internal sealed partial class Order : pb::IMessage - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] + public sealed partial class Order : pb::IMessage +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE , pb::IBufferMessage - #endif +#endif { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Order()); private pb::UnknownFieldSet _unknownFields; @@ -1545,19 +1756,22 @@ internal sealed partial class Order : pb::IMessage [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static pbr::MessageDescriptor Descriptor { + public static pbr::MessageDescriptor Descriptor + { get { return global::Mysqlx.Crud.MysqlxCrudReflection.Descriptor.MessageTypes[5]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - pbr::MessageDescriptor pb::IMessage.Descriptor { + pbr::MessageDescriptor pb::IMessage.Descriptor + { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Order() { + public Order() + { OnConstruction(); } @@ -1565,7 +1779,8 @@ public Order() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Order(Order other) : this() { + public Order(Order other) : this() + { _hasBits0 = other._hasBits0; expr_ = other.expr_ != null ? other.expr_.Clone() : null; direction_ = other.direction_; @@ -1574,7 +1789,8 @@ public Order(Order other) : this() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Order Clone() { + public Order Clone() + { return new Order(this); } @@ -1583,9 +1799,11 @@ public Order Clone() { private global::Mysqlx.Expr.Expr expr_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public global::Mysqlx.Expr.Expr Expr { + public global::Mysqlx.Expr.Expr Expr + { get { return expr_; } - set { + set + { expr_ = value; } } @@ -1597,9 +1815,11 @@ public Order Clone() { private global::Mysqlx.Crud.Order.Types.Direction direction_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public global::Mysqlx.Crud.Order.Types.Direction Direction { + public global::Mysqlx.Crud.Order.Types.Direction Direction + { get { if ((_hasBits0 & 1) != 0) { return direction_; } else { return DirectionDefaultValue; } } - set { + set + { _hasBits0 |= 1; direction_ = value; } @@ -1607,29 +1827,35 @@ public Order Clone() { /// Gets whether the "direction" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasDirection { + public bool HasDirection + { get { return (_hasBits0 & 1) != 0; } } /// Clears the value of the "direction" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearDirection() { + public void ClearDirection() + { _hasBits0 &= ~1; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override bool Equals(object other) { + public override bool Equals(object other) + { return Equals(other as Order); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool Equals(Order other) { - if (ReferenceEquals(other, null)) { + public bool Equals(Order other) + { + if (ReferenceEquals(other, null)) + { return false; } - if (ReferenceEquals(other, this)) { + if (ReferenceEquals(other, this)) + { return true; } if (!object.Equals(Expr, other.Expr)) return false; @@ -1639,11 +1865,13 @@ public bool Equals(Order other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override int GetHashCode() { + public override int GetHashCode() + { int hash = 1; if (expr_ != null) hash ^= Expr.GetHashCode(); if (HasDirection) hash ^= Direction.GetHashCode(); - if (_unknownFields != null) { + if (_unknownFields != null) + { hash ^= _unknownFields.GetHashCode(); } return hash; @@ -1651,16 +1879,18 @@ public override int GetHashCode() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override string ToString() { + public override string ToString() + { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void WriteTo(pb::CodedOutputStream output) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void WriteTo(pb::CodedOutputStream output) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE output.WriteRawMessage(this); - #else +#else if (expr_ != null) { output.WriteRawTag(10); output.WriteMessage(Expr); @@ -1672,38 +1902,46 @@ public void WriteTo(pb::CodedOutputStream output) { if (_unknownFields != null) { _unknownFields.WriteTo(output); } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { - if (expr_ != null) { + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) + { + if (expr_ != null) + { output.WriteRawTag(10); output.WriteMessage(Expr); } - if (HasDirection) { + if (HasDirection) + { output.WriteRawTag(16); - output.WriteEnum((int) Direction); + output.WriteEnum((int)Direction); } - if (_unknownFields != null) { + if (_unknownFields != null) + { _unknownFields.WriteTo(ref output); } } - #endif +#endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public int CalculateSize() { + public int CalculateSize() + { int size = 0; - if (expr_ != null) { + if (expr_ != null) + { size += 1 + pb::CodedOutputStream.ComputeMessageSize(Expr); } - if (HasDirection) { - size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Direction); + if (HasDirection) + { + size += 1 + pb::CodedOutputStream.ComputeEnumSize((int)Direction); } - if (_unknownFields != null) { + if (_unknownFields != null) + { size += _unknownFields.CalculateSize(); } return size; @@ -1711,17 +1949,22 @@ public int CalculateSize() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(Order other) { - if (other == null) { + public void MergeFrom(Order other) + { + if (other == null) + { return; } - if (other.expr_ != null) { - if (expr_ == null) { + if (other.expr_ != null) + { + if (expr_ == null) + { Expr = new global::Mysqlx.Expr.Expr(); } Expr.MergeFrom(other.Expr); } - if (other.HasDirection) { + if (other.HasDirection) + { Direction = other.Direction; } _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); @@ -1729,10 +1972,11 @@ public void MergeFrom(Order other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(pb::CodedInputStream input) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void MergeFrom(pb::CodedInputStream input) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE input.ReadRawMessage(this); - #else +#else uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { @@ -1752,41 +1996,49 @@ public void MergeFrom(pb::CodedInputStream input) { } } } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) + { uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { + while ((tag = input.ReadTag()) != 0) + { + switch (tag) + { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; - case 10: { - if (expr_ == null) { - Expr = new global::Mysqlx.Expr.Expr(); + case 10: + { + if (expr_ == null) + { + Expr = new global::Mysqlx.Expr.Expr(); + } + input.ReadMessage(Expr); + break; + } + case 16: + { + Direction = (global::Mysqlx.Crud.Order.Types.Direction)input.ReadEnum(); + break; } - input.ReadMessage(Expr); - break; - } - case 16: { - Direction = (global::Mysqlx.Crud.Order.Types.Direction) input.ReadEnum(); - break; - } } } } - #endif +#endif #region Nested types /// Container for nested types declared in the Order message type. [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static partial class Types { - public enum Direction { + public static partial class Types + { + public enum Direction + { [pbr::OriginalName("ASC")] Asc = 1, [pbr::OriginalName("DESC")] Desc = 2, } @@ -1796,10 +2048,11 @@ public enum Direction { } - internal sealed partial class UpdateOperation : pb::IMessage - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] + public sealed partial class UpdateOperation : pb::IMessage +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE , pb::IBufferMessage - #endif +#endif { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new UpdateOperation()); private pb::UnknownFieldSet _unknownFields; @@ -1810,19 +2063,22 @@ internal sealed partial class UpdateOperation : pb::IMessage [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static pbr::MessageDescriptor Descriptor { + public static pbr::MessageDescriptor Descriptor + { get { return global::Mysqlx.Crud.MysqlxCrudReflection.Descriptor.MessageTypes[6]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - pbr::MessageDescriptor pb::IMessage.Descriptor { + pbr::MessageDescriptor pb::IMessage.Descriptor + { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public UpdateOperation() { + public UpdateOperation() + { OnConstruction(); } @@ -1830,7 +2086,8 @@ public UpdateOperation() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public UpdateOperation(UpdateOperation other) : this() { + public UpdateOperation(UpdateOperation other) : this() + { _hasBits0 = other._hasBits0; source_ = other.source_ != null ? other.source_.Clone() : null; operation_ = other.operation_; @@ -1840,7 +2097,8 @@ public UpdateOperation(UpdateOperation other) : this() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public UpdateOperation Clone() { + public UpdateOperation Clone() + { return new UpdateOperation(this); } @@ -1857,9 +2115,11 @@ public UpdateOperation Clone() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public global::Mysqlx.Expr.ColumnIdentifier Source { + public global::Mysqlx.Expr.ColumnIdentifier Source + { get { return source_; } - set { + set + { source_ = value; } } @@ -1874,9 +2134,11 @@ public UpdateOperation Clone() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public global::Mysqlx.Crud.UpdateOperation.Types.UpdateType Operation { + public global::Mysqlx.Crud.UpdateOperation.Types.UpdateType Operation + { get { if ((_hasBits0 & 1) != 0) { return operation_; } else { return OperationDefaultValue; } } - set { + set + { _hasBits0 |= 1; operation_ = value; } @@ -1884,13 +2146,15 @@ public UpdateOperation Clone() { /// Gets whether the "operation" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasOperation { + public bool HasOperation + { get { return (_hasBits0 & 1) != 0; } } /// Clears the value of the "operation" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearOperation() { + public void ClearOperation() + { _hasBits0 &= ~1; } @@ -1902,26 +2166,32 @@ public void ClearOperation() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public global::Mysqlx.Expr.Expr Value { + public global::Mysqlx.Expr.Expr Value + { get { return value_; } - set { + set + { value_ = value; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override bool Equals(object other) { + public override bool Equals(object other) + { return Equals(other as UpdateOperation); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool Equals(UpdateOperation other) { - if (ReferenceEquals(other, null)) { + public bool Equals(UpdateOperation other) + { + if (ReferenceEquals(other, null)) + { return false; } - if (ReferenceEquals(other, this)) { + if (ReferenceEquals(other, this)) + { return true; } if (!object.Equals(Source, other.Source)) return false; @@ -1932,12 +2202,14 @@ public bool Equals(UpdateOperation other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override int GetHashCode() { + public override int GetHashCode() + { int hash = 1; if (source_ != null) hash ^= Source.GetHashCode(); if (HasOperation) hash ^= Operation.GetHashCode(); if (value_ != null) hash ^= Value.GetHashCode(); - if (_unknownFields != null) { + if (_unknownFields != null) + { hash ^= _unknownFields.GetHashCode(); } return hash; @@ -1945,16 +2217,18 @@ public override int GetHashCode() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override string ToString() { + public override string ToString() + { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void WriteTo(pb::CodedOutputStream output) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void WriteTo(pb::CodedOutputStream output) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE output.WriteRawMessage(this); - #else +#else if (source_ != null) { output.WriteRawTag(10); output.WriteMessage(Source); @@ -1970,45 +2244,55 @@ public void WriteTo(pb::CodedOutputStream output) { if (_unknownFields != null) { _unknownFields.WriteTo(output); } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { - if (source_ != null) { + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) + { + if (source_ != null) + { output.WriteRawTag(10); output.WriteMessage(Source); } - if (HasOperation) { + if (HasOperation) + { output.WriteRawTag(16); - output.WriteEnum((int) Operation); + output.WriteEnum((int)Operation); } - if (value_ != null) { + if (value_ != null) + { output.WriteRawTag(26); output.WriteMessage(Value); } - if (_unknownFields != null) { + if (_unknownFields != null) + { _unknownFields.WriteTo(ref output); } } - #endif +#endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public int CalculateSize() { + public int CalculateSize() + { int size = 0; - if (source_ != null) { + if (source_ != null) + { size += 1 + pb::CodedOutputStream.ComputeMessageSize(Source); } - if (HasOperation) { - size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Operation); + if (HasOperation) + { + size += 1 + pb::CodedOutputStream.ComputeEnumSize((int)Operation); } - if (value_ != null) { + if (value_ != null) + { size += 1 + pb::CodedOutputStream.ComputeMessageSize(Value); } - if (_unknownFields != null) { + if (_unknownFields != null) + { size += _unknownFields.CalculateSize(); } return size; @@ -2016,21 +2300,28 @@ public int CalculateSize() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(UpdateOperation other) { - if (other == null) { + public void MergeFrom(UpdateOperation other) + { + if (other == null) + { return; } - if (other.source_ != null) { - if (source_ == null) { + if (other.source_ != null) + { + if (source_ == null) + { Source = new global::Mysqlx.Expr.ColumnIdentifier(); } Source.MergeFrom(other.Source); } - if (other.HasOperation) { + if (other.HasOperation) + { Operation = other.Operation; } - if (other.value_ != null) { - if (value_ == null) { + if (other.value_ != null) + { + if (value_ == null) + { Value = new global::Mysqlx.Expr.Expr(); } Value.MergeFrom(other.Value); @@ -2040,10 +2331,11 @@ public void MergeFrom(UpdateOperation other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(pb::CodedInputStream input) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void MergeFrom(pb::CodedInputStream input) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE input.ReadRawMessage(this); - #else +#else uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { @@ -2070,48 +2362,58 @@ public void MergeFrom(pb::CodedInputStream input) { } } } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) + { uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { + while ((tag = input.ReadTag()) != 0) + { + switch (tag) + { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; - case 10: { - if (source_ == null) { - Source = new global::Mysqlx.Expr.ColumnIdentifier(); + case 10: + { + if (source_ == null) + { + Source = new global::Mysqlx.Expr.ColumnIdentifier(); + } + input.ReadMessage(Source); + break; } - input.ReadMessage(Source); - break; - } - case 16: { - Operation = (global::Mysqlx.Crud.UpdateOperation.Types.UpdateType) input.ReadEnum(); - break; - } - case 26: { - if (value_ == null) { - Value = new global::Mysqlx.Expr.Expr(); + case 16: + { + Operation = (global::Mysqlx.Crud.UpdateOperation.Types.UpdateType)input.ReadEnum(); + break; + } + case 26: + { + if (value_ == null) + { + Value = new global::Mysqlx.Expr.Expr(); + } + input.ReadMessage(Value); + break; } - input.ReadMessage(Value); - break; - } } } } - #endif +#endif #region Nested types /// Container for nested types declared in the UpdateOperation message type. [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static partial class Types { - public enum UpdateType { + public static partial class Types + { + public enum UpdateType + { /// ///* only allowed for TABLE /// @@ -2162,10 +2464,11 @@ public enum UpdateType { /// ///@returns @ref Mysqlx::Resultset /// - internal sealed partial class Find : pb::IMessage - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] + public sealed partial class Find : pb::IMessage +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE , pb::IBufferMessage - #endif +#endif { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Find()); private pb::UnknownFieldSet _unknownFields; @@ -2176,19 +2479,22 @@ internal sealed partial class Find : pb::IMessage [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static pbr::MessageDescriptor Descriptor { + public static pbr::MessageDescriptor Descriptor + { get { return global::Mysqlx.Crud.MysqlxCrudReflection.Descriptor.MessageTypes[7]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - pbr::MessageDescriptor pb::IMessage.Descriptor { + pbr::MessageDescriptor pb::IMessage.Descriptor + { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Find() { + public Find() + { OnConstruction(); } @@ -2196,7 +2502,8 @@ public Find() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Find(Find other) : this() { + public Find(Find other) : this() + { _hasBits0 = other._hasBits0; collection_ = other.collection_ != null ? other.collection_.Clone() : null; dataModel_ = other.dataModel_; @@ -2215,7 +2522,8 @@ public Find(Find other) : this() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Find Clone() { + public Find Clone() + { return new Find(this); } @@ -2227,9 +2535,11 @@ public Find Clone() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public global::Mysqlx.Crud.Collection Collection { + public global::Mysqlx.Crud.Collection Collection + { get { return collection_; } - set { + set + { collection_ = value; } } @@ -2244,9 +2554,11 @@ public Find Clone() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public global::Mysqlx.Crud.DataModel DataModel { + public global::Mysqlx.Crud.DataModel DataModel + { get { if ((_hasBits0 & 1) != 0) { return dataModel_; } else { return DataModelDefaultValue; } } - set { + set + { _hasBits0 |= 1; dataModel_ = value; } @@ -2254,13 +2566,15 @@ public Find Clone() { /// Gets whether the "data_model" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasDataModel { + public bool HasDataModel + { get { return (_hasBits0 & 1) != 0; } } /// Clears the value of the "data_model" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearDataModel() { + public void ClearDataModel() + { _hasBits0 &= ~1; } @@ -2274,7 +2588,8 @@ public void ClearDataModel() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public pbc::RepeatedField Projection { + public pbc::RepeatedField Projection + { get { return projection_; } } @@ -2288,7 +2603,8 @@ public void ClearDataModel() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public pbc::RepeatedField Args { + public pbc::RepeatedField Args + { get { return args_; } } @@ -2300,9 +2616,11 @@ public void ClearDataModel() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public global::Mysqlx.Expr.Expr Criteria { + public global::Mysqlx.Expr.Expr Criteria + { get { return criteria_; } - set { + set + { criteria_ = value; } } @@ -2316,9 +2634,11 @@ public void ClearDataModel() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public global::Mysqlx.Crud.Limit Limit { + public global::Mysqlx.Crud.Limit Limit + { get { return limit_; } - set { + set + { limit_ = value; } } @@ -2333,7 +2653,8 @@ public void ClearDataModel() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public pbc::RepeatedField Order { + public pbc::RepeatedField Order + { get { return order_; } } @@ -2347,7 +2668,8 @@ public void ClearDataModel() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public pbc::RepeatedField Grouping { + public pbc::RepeatedField Grouping + { get { return grouping_; } } @@ -2359,9 +2681,11 @@ public void ClearDataModel() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public global::Mysqlx.Expr.Expr GroupingCriteria { + public global::Mysqlx.Expr.Expr GroupingCriteria + { get { return groupingCriteria_; } - set { + set + { groupingCriteria_ = value; } } @@ -2376,9 +2700,11 @@ public void ClearDataModel() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public global::Mysqlx.Crud.Find.Types.RowLock Locking { + public global::Mysqlx.Crud.Find.Types.RowLock Locking + { get { if ((_hasBits0 & 2) != 0) { return locking_; } else { return LockingDefaultValue; } } - set { + set + { _hasBits0 |= 2; locking_ = value; } @@ -2386,13 +2712,15 @@ public void ClearDataModel() { /// Gets whether the "locking" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasLocking { + public bool HasLocking + { get { return (_hasBits0 & 2) != 0; } } /// Clears the value of the "locking" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearLocking() { + public void ClearLocking() + { _hasBits0 &= ~2; } @@ -2406,9 +2734,11 @@ public void ClearLocking() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public global::Mysqlx.Crud.Find.Types.RowLockOptions LockingOptions { + public global::Mysqlx.Crud.Find.Types.RowLockOptions LockingOptions + { get { if ((_hasBits0 & 4) != 0) { return lockingOptions_; } else { return LockingOptionsDefaultValue; } } - set { + set + { _hasBits0 |= 4; lockingOptions_ = value; } @@ -2416,13 +2746,15 @@ public void ClearLocking() { /// Gets whether the "locking_options" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasLockingOptions { + public bool HasLockingOptions + { get { return (_hasBits0 & 4) != 0; } } /// Clears the value of the "locking_options" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearLockingOptions() { + public void ClearLockingOptions() + { _hasBits0 &= ~4; } @@ -2435,36 +2767,42 @@ public void ClearLockingOptions() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public global::Mysqlx.Crud.LimitExpr LimitExpr { + public global::Mysqlx.Crud.LimitExpr LimitExpr + { get { return limitExpr_; } - set { + set + { limitExpr_ = value; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override bool Equals(object other) { + public override bool Equals(object other) + { return Equals(other as Find); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool Equals(Find other) { - if (ReferenceEquals(other, null)) { + public bool Equals(Find other) + { + if (ReferenceEquals(other, null)) + { return false; } - if (ReferenceEquals(other, this)) { + if (ReferenceEquals(other, this)) + { return true; } if (!object.Equals(Collection, other.Collection)) return false; if (DataModel != other.DataModel) return false; - if(!projection_.Equals(other.projection_)) return false; - if(!args_.Equals(other.args_)) return false; + if (!projection_.Equals(other.projection_)) return false; + if (!args_.Equals(other.args_)) return false; if (!object.Equals(Criteria, other.Criteria)) return false; if (!object.Equals(Limit, other.Limit)) return false; - if(!order_.Equals(other.order_)) return false; - if(!grouping_.Equals(other.grouping_)) return false; + if (!order_.Equals(other.order_)) return false; + if (!grouping_.Equals(other.grouping_)) return false; if (!object.Equals(GroupingCriteria, other.GroupingCriteria)) return false; if (Locking != other.Locking) return false; if (LockingOptions != other.LockingOptions) return false; @@ -2474,7 +2812,8 @@ public bool Equals(Find other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override int GetHashCode() { + public override int GetHashCode() + { int hash = 1; if (collection_ != null) hash ^= Collection.GetHashCode(); if (HasDataModel) hash ^= DataModel.GetHashCode(); @@ -2488,7 +2827,8 @@ public override int GetHashCode() { if (HasLocking) hash ^= Locking.GetHashCode(); if (HasLockingOptions) hash ^= LockingOptions.GetHashCode(); if (limitExpr_ != null) hash ^= LimitExpr.GetHashCode(); - if (_unknownFields != null) { + if (_unknownFields != null) + { hash ^= _unknownFields.GetHashCode(); } return hash; @@ -2496,16 +2836,18 @@ public override int GetHashCode() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override string ToString() { + public override string ToString() + { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void WriteTo(pb::CodedOutputStream output) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void WriteTo(pb::CodedOutputStream output) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE output.WriteRawMessage(this); - #else +#else if (collection_ != null) { output.WriteRawTag(18); output.WriteMessage(Collection); @@ -2545,88 +2887,108 @@ public void WriteTo(pb::CodedOutputStream output) { if (_unknownFields != null) { _unknownFields.WriteTo(output); } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { - if (collection_ != null) { + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) + { + if (collection_ != null) + { output.WriteRawTag(18); output.WriteMessage(Collection); } - if (HasDataModel) { + if (HasDataModel) + { output.WriteRawTag(24); - output.WriteEnum((int) DataModel); + output.WriteEnum((int)DataModel); } projection_.WriteTo(ref output, _repeated_projection_codec); - if (criteria_ != null) { + if (criteria_ != null) + { output.WriteRawTag(42); output.WriteMessage(Criteria); } - if (limit_ != null) { + if (limit_ != null) + { output.WriteRawTag(50); output.WriteMessage(Limit); } order_.WriteTo(ref output, _repeated_order_codec); grouping_.WriteTo(ref output, _repeated_grouping_codec); - if (groupingCriteria_ != null) { + if (groupingCriteria_ != null) + { output.WriteRawTag(74); output.WriteMessage(GroupingCriteria); } args_.WriteTo(ref output, _repeated_args_codec); - if (HasLocking) { + if (HasLocking) + { output.WriteRawTag(96); - output.WriteEnum((int) Locking); + output.WriteEnum((int)Locking); } - if (HasLockingOptions) { + if (HasLockingOptions) + { output.WriteRawTag(104); - output.WriteEnum((int) LockingOptions); + output.WriteEnum((int)LockingOptions); } - if (limitExpr_ != null) { + if (limitExpr_ != null) + { output.WriteRawTag(114); output.WriteMessage(LimitExpr); } - if (_unknownFields != null) { + if (_unknownFields != null) + { _unknownFields.WriteTo(ref output); } } - #endif +#endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public int CalculateSize() { + public int CalculateSize() + { int size = 0; - if (collection_ != null) { + if (collection_ != null) + { size += 1 + pb::CodedOutputStream.ComputeMessageSize(Collection); } - if (HasDataModel) { - size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) DataModel); + if (HasDataModel) + { + size += 1 + pb::CodedOutputStream.ComputeEnumSize((int)DataModel); } size += projection_.CalculateSize(_repeated_projection_codec); size += args_.CalculateSize(_repeated_args_codec); - if (criteria_ != null) { + if (criteria_ != null) + { size += 1 + pb::CodedOutputStream.ComputeMessageSize(Criteria); } - if (limit_ != null) { + if (limit_ != null) + { size += 1 + pb::CodedOutputStream.ComputeMessageSize(Limit); } size += order_.CalculateSize(_repeated_order_codec); size += grouping_.CalculateSize(_repeated_grouping_codec); - if (groupingCriteria_ != null) { + if (groupingCriteria_ != null) + { size += 1 + pb::CodedOutputStream.ComputeMessageSize(GroupingCriteria); } - if (HasLocking) { - size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Locking); + if (HasLocking) + { + size += 1 + pb::CodedOutputStream.ComputeEnumSize((int)Locking); } - if (HasLockingOptions) { - size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) LockingOptions); + if (HasLockingOptions) + { + size += 1 + pb::CodedOutputStream.ComputeEnumSize((int)LockingOptions); } - if (limitExpr_ != null) { + if (limitExpr_ != null) + { size += 1 + pb::CodedOutputStream.ComputeMessageSize(LimitExpr); } - if (_unknownFields != null) { + if (_unknownFields != null) + { size += _unknownFields.CalculateSize(); } return size; @@ -2634,49 +2996,64 @@ public int CalculateSize() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(Find other) { - if (other == null) { + public void MergeFrom(Find other) + { + if (other == null) + { return; } - if (other.collection_ != null) { - if (collection_ == null) { + if (other.collection_ != null) + { + if (collection_ == null) + { Collection = new global::Mysqlx.Crud.Collection(); } Collection.MergeFrom(other.Collection); } - if (other.HasDataModel) { + if (other.HasDataModel) + { DataModel = other.DataModel; } projection_.Add(other.projection_); args_.Add(other.args_); - if (other.criteria_ != null) { - if (criteria_ == null) { + if (other.criteria_ != null) + { + if (criteria_ == null) + { Criteria = new global::Mysqlx.Expr.Expr(); } Criteria.MergeFrom(other.Criteria); } - if (other.limit_ != null) { - if (limit_ == null) { + if (other.limit_ != null) + { + if (limit_ == null) + { Limit = new global::Mysqlx.Crud.Limit(); } Limit.MergeFrom(other.Limit); } order_.Add(other.order_); grouping_.Add(other.grouping_); - if (other.groupingCriteria_ != null) { - if (groupingCriteria_ == null) { + if (other.groupingCriteria_ != null) + { + if (groupingCriteria_ == null) + { GroupingCriteria = new global::Mysqlx.Expr.Expr(); } GroupingCriteria.MergeFrom(other.GroupingCriteria); } - if (other.HasLocking) { + if (other.HasLocking) + { Locking = other.Locking; } - if (other.HasLockingOptions) { + if (other.HasLockingOptions) + { LockingOptions = other.LockingOptions; } - if (other.limitExpr_ != null) { - if (limitExpr_ == null) { + if (other.limitExpr_ != null) + { + if (limitExpr_ == null) + { LimitExpr = new global::Mysqlx.Crud.LimitExpr(); } LimitExpr.MergeFrom(other.LimitExpr); @@ -2686,10 +3063,11 @@ public void MergeFrom(Find other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(pb::CodedInputStream input) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void MergeFrom(pb::CodedInputStream input) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE input.ReadRawMessage(this); - #else +#else uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { @@ -2761,93 +3139,115 @@ public void MergeFrom(pb::CodedInputStream input) { } } } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) + { uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { + while ((tag = input.ReadTag()) != 0) + { + switch (tag) + { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; - case 18: { - if (collection_ == null) { - Collection = new global::Mysqlx.Crud.Collection(); + case 18: + { + if (collection_ == null) + { + Collection = new global::Mysqlx.Crud.Collection(); + } + input.ReadMessage(Collection); + break; } - input.ReadMessage(Collection); - break; - } - case 24: { - DataModel = (global::Mysqlx.Crud.DataModel) input.ReadEnum(); - break; - } - case 34: { - projection_.AddEntriesFrom(ref input, _repeated_projection_codec); - break; - } - case 42: { - if (criteria_ == null) { - Criteria = new global::Mysqlx.Expr.Expr(); + case 24: + { + DataModel = (global::Mysqlx.Crud.DataModel)input.ReadEnum(); + break; } - input.ReadMessage(Criteria); - break; - } - case 50: { - if (limit_ == null) { - Limit = new global::Mysqlx.Crud.Limit(); + case 34: + { + projection_.AddEntriesFrom(ref input, _repeated_projection_codec); + break; } - input.ReadMessage(Limit); - break; - } - case 58: { - order_.AddEntriesFrom(ref input, _repeated_order_codec); - break; - } - case 66: { - grouping_.AddEntriesFrom(ref input, _repeated_grouping_codec); - break; - } - case 74: { - if (groupingCriteria_ == null) { - GroupingCriteria = new global::Mysqlx.Expr.Expr(); + case 42: + { + if (criteria_ == null) + { + Criteria = new global::Mysqlx.Expr.Expr(); + } + input.ReadMessage(Criteria); + break; } - input.ReadMessage(GroupingCriteria); - break; - } - case 90: { - args_.AddEntriesFrom(ref input, _repeated_args_codec); - break; - } - case 96: { - Locking = (global::Mysqlx.Crud.Find.Types.RowLock) input.ReadEnum(); - break; - } - case 104: { - LockingOptions = (global::Mysqlx.Crud.Find.Types.RowLockOptions) input.ReadEnum(); - break; - } - case 114: { - if (limitExpr_ == null) { - LimitExpr = new global::Mysqlx.Crud.LimitExpr(); + case 50: + { + if (limit_ == null) + { + Limit = new global::Mysqlx.Crud.Limit(); + } + input.ReadMessage(Limit); + break; + } + case 58: + { + order_.AddEntriesFrom(ref input, _repeated_order_codec); + break; + } + case 66: + { + grouping_.AddEntriesFrom(ref input, _repeated_grouping_codec); + break; + } + case 74: + { + if (groupingCriteria_ == null) + { + GroupingCriteria = new global::Mysqlx.Expr.Expr(); + } + input.ReadMessage(GroupingCriteria); + break; + } + case 90: + { + args_.AddEntriesFrom(ref input, _repeated_args_codec); + break; + } + case 96: + { + Locking = (global::Mysqlx.Crud.Find.Types.RowLock)input.ReadEnum(); + break; + } + case 104: + { + LockingOptions = (global::Mysqlx.Crud.Find.Types.RowLockOptions)input.ReadEnum(); + break; + } + case 114: + { + if (limitExpr_ == null) + { + LimitExpr = new global::Mysqlx.Crud.LimitExpr(); + } + input.ReadMessage(LimitExpr); + break; } - input.ReadMessage(LimitExpr); - break; - } } } } - #endif +#endif #region Nested types /// Container for nested types declared in the Find message type. [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static partial class Types { - public enum RowLock { + public static partial class Types + { + public enum RowLock + { /// ///* Lock matching rows against updates /// @@ -2858,7 +3258,8 @@ public enum RowLock { [pbr::OriginalName("EXCLUSIVE_LOCK")] ExclusiveLock = 2, } - public enum RowLockOptions { + public enum RowLockOptions + { /// ///* Do not wait to acquire row lock, fail with an error ///if a requested row is locked @@ -2882,10 +3283,11 @@ public enum RowLockOptions { /// ///@returns @ref Mysqlx::Resultset /// - internal sealed partial class Insert : pb::IMessage - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] + public sealed partial class Insert : pb::IMessage +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE , pb::IBufferMessage - #endif +#endif { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Insert()); private pb::UnknownFieldSet _unknownFields; @@ -2896,19 +3298,22 @@ internal sealed partial class Insert : pb::IMessage [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static pbr::MessageDescriptor Descriptor { + public static pbr::MessageDescriptor Descriptor + { get { return global::Mysqlx.Crud.MysqlxCrudReflection.Descriptor.MessageTypes[8]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - pbr::MessageDescriptor pb::IMessage.Descriptor { + pbr::MessageDescriptor pb::IMessage.Descriptor + { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Insert() { + public Insert() + { OnConstruction(); } @@ -2916,7 +3321,8 @@ public Insert() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Insert(Insert other) : this() { + public Insert(Insert other) : this() + { _hasBits0 = other._hasBits0; collection_ = other.collection_ != null ? other.collection_.Clone() : null; dataModel_ = other.dataModel_; @@ -2929,7 +3335,8 @@ public Insert(Insert other) : this() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Insert Clone() { + public Insert Clone() + { return new Insert(this); } @@ -2941,9 +3348,11 @@ public Insert Clone() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public global::Mysqlx.Crud.Collection Collection { + public global::Mysqlx.Crud.Collection Collection + { get { return collection_; } - set { + set + { collection_ = value; } } @@ -2958,9 +3367,11 @@ public Insert Clone() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public global::Mysqlx.Crud.DataModel DataModel { + public global::Mysqlx.Crud.DataModel DataModel + { get { if ((_hasBits0 & 1) != 0) { return dataModel_; } else { return DataModelDefaultValue; } } - set { + set + { _hasBits0 |= 1; dataModel_ = value; } @@ -2968,13 +3379,15 @@ public Insert Clone() { /// Gets whether the "data_model" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasDataModel { + public bool HasDataModel + { get { return (_hasBits0 & 1) != 0; } } /// Clears the value of the "data_model" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearDataModel() { + public void ClearDataModel() + { _hasBits0 &= ~1; } @@ -2989,7 +3402,8 @@ public void ClearDataModel() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public pbc::RepeatedField Projection { + public pbc::RepeatedField Projection + { get { return projection_; } } @@ -3004,7 +3418,8 @@ public void ClearDataModel() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public pbc::RepeatedField Row { + public pbc::RepeatedField Row + { get { return row_; } } @@ -3018,7 +3433,8 @@ public void ClearDataModel() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public pbc::RepeatedField Args { + public pbc::RepeatedField Args + { get { return args_; } } @@ -3033,9 +3449,11 @@ public void ClearDataModel() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool Upsert { + public bool Upsert + { get { if ((_hasBits0 & 2) != 0) { return upsert_; } else { return UpsertDefaultValue; } } - set { + set + { _hasBits0 |= 2; upsert_ = value; } @@ -3043,43 +3461,50 @@ public bool Upsert { /// Gets whether the "upsert" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasUpsert { + public bool HasUpsert + { get { return (_hasBits0 & 2) != 0; } } /// Clears the value of the "upsert" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearUpsert() { + public void ClearUpsert() + { _hasBits0 &= ~2; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override bool Equals(object other) { + public override bool Equals(object other) + { return Equals(other as Insert); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool Equals(Insert other) { - if (ReferenceEquals(other, null)) { + public bool Equals(Insert other) + { + if (ReferenceEquals(other, null)) + { return false; } - if (ReferenceEquals(other, this)) { + if (ReferenceEquals(other, this)) + { return true; } if (!object.Equals(Collection, other.Collection)) return false; if (DataModel != other.DataModel) return false; - if(!projection_.Equals(other.projection_)) return false; - if(!row_.Equals(other.row_)) return false; - if(!args_.Equals(other.args_)) return false; + if (!projection_.Equals(other.projection_)) return false; + if (!row_.Equals(other.row_)) return false; + if (!args_.Equals(other.args_)) return false; if (Upsert != other.Upsert) return false; return Equals(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override int GetHashCode() { + public override int GetHashCode() + { int hash = 1; if (collection_ != null) hash ^= Collection.GetHashCode(); if (HasDataModel) hash ^= DataModel.GetHashCode(); @@ -3087,7 +3512,8 @@ public override int GetHashCode() { hash ^= row_.GetHashCode(); hash ^= args_.GetHashCode(); if (HasUpsert) hash ^= Upsert.GetHashCode(); - if (_unknownFields != null) { + if (_unknownFields != null) + { hash ^= _unknownFields.GetHashCode(); } return hash; @@ -3095,16 +3521,18 @@ public override int GetHashCode() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override string ToString() { + public override string ToString() + { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void WriteTo(pb::CodedOutputStream output) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void WriteTo(pb::CodedOutputStream output) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE output.WriteRawMessage(this); - #else +#else if (collection_ != null) { output.WriteRawTag(10); output.WriteMessage(Collection); @@ -3123,51 +3551,61 @@ public void WriteTo(pb::CodedOutputStream output) { if (_unknownFields != null) { _unknownFields.WriteTo(output); } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { - if (collection_ != null) { + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) + { + if (collection_ != null) + { output.WriteRawTag(10); output.WriteMessage(Collection); } - if (HasDataModel) { + if (HasDataModel) + { output.WriteRawTag(16); - output.WriteEnum((int) DataModel); + output.WriteEnum((int)DataModel); } projection_.WriteTo(ref output, _repeated_projection_codec); row_.WriteTo(ref output, _repeated_row_codec); args_.WriteTo(ref output, _repeated_args_codec); - if (HasUpsert) { + if (HasUpsert) + { output.WriteRawTag(48); output.WriteBool(Upsert); } - if (_unknownFields != null) { + if (_unknownFields != null) + { _unknownFields.WriteTo(ref output); } } - #endif +#endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public int CalculateSize() { + public int CalculateSize() + { int size = 0; - if (collection_ != null) { + if (collection_ != null) + { size += 1 + pb::CodedOutputStream.ComputeMessageSize(Collection); } - if (HasDataModel) { - size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) DataModel); + if (HasDataModel) + { + size += 1 + pb::CodedOutputStream.ComputeEnumSize((int)DataModel); } size += projection_.CalculateSize(_repeated_projection_codec); size += row_.CalculateSize(_repeated_row_codec); size += args_.CalculateSize(_repeated_args_codec); - if (HasUpsert) { + if (HasUpsert) + { size += 1 + 1; } - if (_unknownFields != null) { + if (_unknownFields != null) + { size += _unknownFields.CalculateSize(); } return size; @@ -3175,23 +3613,29 @@ public int CalculateSize() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(Insert other) { - if (other == null) { + public void MergeFrom(Insert other) + { + if (other == null) + { return; } - if (other.collection_ != null) { - if (collection_ == null) { + if (other.collection_ != null) + { + if (collection_ == null) + { Collection = new global::Mysqlx.Crud.Collection(); } Collection.MergeFrom(other.Collection); } - if (other.HasDataModel) { + if (other.HasDataModel) + { DataModel = other.DataModel; } projection_.Add(other.projection_); row_.Add(other.row_); args_.Add(other.args_); - if (other.HasUpsert) { + if (other.HasUpsert) + { Upsert = other.Upsert; } _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); @@ -3199,10 +3643,11 @@ public void MergeFrom(Insert other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(pb::CodedInputStream input) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void MergeFrom(pb::CodedInputStream input) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE input.ReadRawMessage(this); - #else +#else uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { @@ -3238,63 +3683,75 @@ public void MergeFrom(pb::CodedInputStream input) { } } } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) + { uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { + while ((tag = input.ReadTag()) != 0) + { + switch (tag) + { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; - case 10: { - if (collection_ == null) { - Collection = new global::Mysqlx.Crud.Collection(); + case 10: + { + if (collection_ == null) + { + Collection = new global::Mysqlx.Crud.Collection(); + } + input.ReadMessage(Collection); + break; + } + case 16: + { + DataModel = (global::Mysqlx.Crud.DataModel)input.ReadEnum(); + break; + } + case 26: + { + projection_.AddEntriesFrom(ref input, _repeated_projection_codec); + break; + } + case 34: + { + row_.AddEntriesFrom(ref input, _repeated_row_codec); + break; + } + case 42: + { + args_.AddEntriesFrom(ref input, _repeated_args_codec); + break; + } + case 48: + { + Upsert = input.ReadBool(); + break; } - input.ReadMessage(Collection); - break; - } - case 16: { - DataModel = (global::Mysqlx.Crud.DataModel) input.ReadEnum(); - break; - } - case 26: { - projection_.AddEntriesFrom(ref input, _repeated_projection_codec); - break; - } - case 34: { - row_.AddEntriesFrom(ref input, _repeated_row_codec); - break; - } - case 42: { - args_.AddEntriesFrom(ref input, _repeated_args_codec); - break; - } - case 48: { - Upsert = input.ReadBool(); - break; - } } } } - #endif +#endif #region Nested types /// Container for nested types declared in the Insert message type. [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static partial class Types { + public static partial class Types + { /// ///* set of fields to insert as a one row /// + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] public sealed partial class TypedRow : pb::IMessage - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE , pb::IBufferMessage - #endif +#endif { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TypedRow()); private pb::UnknownFieldSet _unknownFields; @@ -3304,19 +3761,22 @@ public sealed partial class TypedRow : pb::IMessage [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static pbr::MessageDescriptor Descriptor { + public static pbr::MessageDescriptor Descriptor + { get { return global::Mysqlx.Crud.Insert.Descriptor.NestedTypes[0]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - pbr::MessageDescriptor pb::IMessage.Descriptor { + pbr::MessageDescriptor pb::IMessage.Descriptor + { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public TypedRow() { + public TypedRow() + { OnConstruction(); } @@ -3324,14 +3784,16 @@ public TypedRow() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public TypedRow(TypedRow other) : this() { + public TypedRow(TypedRow other) : this() + { field_ = other.field_.Clone(); _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public TypedRow Clone() { + public TypedRow Clone() + { return new TypedRow(this); } @@ -3342,35 +3804,42 @@ public TypedRow Clone() { private readonly pbc::RepeatedField field_ = new pbc::RepeatedField(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public pbc::RepeatedField Field { + public pbc::RepeatedField Field + { get { return field_; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override bool Equals(object other) { + public override bool Equals(object other) + { return Equals(other as TypedRow); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool Equals(TypedRow other) { - if (ReferenceEquals(other, null)) { + public bool Equals(TypedRow other) + { + if (ReferenceEquals(other, null)) + { return false; } - if (ReferenceEquals(other, this)) { + if (ReferenceEquals(other, this)) + { return true; } - if(!field_.Equals(other.field_)) return false; + if (!field_.Equals(other.field_)) return false; return Equals(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override int GetHashCode() { + public override int GetHashCode() + { int hash = 1; hash ^= field_.GetHashCode(); - if (_unknownFields != null) { + if (_unknownFields != null) + { hash ^= _unknownFields.GetHashCode(); } return hash; @@ -3378,40 +3847,46 @@ public override int GetHashCode() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override string ToString() { + public override string ToString() + { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void WriteTo(pb::CodedOutputStream output) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void WriteTo(pb::CodedOutputStream output) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE output.WriteRawMessage(this); - #else +#else field_.WriteTo(output, _repeated_field_codec); if (_unknownFields != null) { _unknownFields.WriteTo(output); } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) + { field_.WriteTo(ref output, _repeated_field_codec); - if (_unknownFields != null) { + if (_unknownFields != null) + { _unknownFields.WriteTo(ref output); } } - #endif +#endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public int CalculateSize() { + public int CalculateSize() + { int size = 0; size += field_.CalculateSize(_repeated_field_codec); - if (_unknownFields != null) { + if (_unknownFields != null) + { size += _unknownFields.CalculateSize(); } return size; @@ -3419,8 +3894,10 @@ public int CalculateSize() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(TypedRow other) { - if (other == null) { + public void MergeFrom(TypedRow other) + { + if (other == null) + { return; } field_.Add(other.field_); @@ -3429,10 +3906,11 @@ public void MergeFrom(TypedRow other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(pb::CodedInputStream input) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void MergeFrom(pb::CodedInputStream input) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE input.ReadRawMessage(this); - #else +#else uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { @@ -3445,27 +3923,31 @@ public void MergeFrom(pb::CodedInputStream input) { } } } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) + { uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { + while ((tag = input.ReadTag()) != 0) + { + switch (tag) + { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; - case 10: { - field_.AddEntriesFrom(ref input, _repeated_field_codec); - break; - } + case 10: + { + field_.AddEntriesFrom(ref input, _repeated_field_codec); + break; + } } } } - #endif +#endif } @@ -3480,10 +3962,11 @@ public void MergeFrom(pb::CodedInputStream input) { /// ///@returns @ref Mysqlx::Resultset /// - internal sealed partial class Update : pb::IMessage - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] + public sealed partial class Update : pb::IMessage +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE , pb::IBufferMessage - #endif +#endif { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Update()); private pb::UnknownFieldSet _unknownFields; @@ -3494,19 +3977,22 @@ internal sealed partial class Update : pb::IMessage [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static pbr::MessageDescriptor Descriptor { + public static pbr::MessageDescriptor Descriptor + { get { return global::Mysqlx.Crud.MysqlxCrudReflection.Descriptor.MessageTypes[9]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - pbr::MessageDescriptor pb::IMessage.Descriptor { + pbr::MessageDescriptor pb::IMessage.Descriptor + { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Update() { + public Update() + { OnConstruction(); } @@ -3514,7 +4000,8 @@ public Update() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Update(Update other) : this() { + public Update(Update other) : this() + { _hasBits0 = other._hasBits0; collection_ = other.collection_ != null ? other.collection_.Clone() : null; dataModel_ = other.dataModel_; @@ -3529,7 +4016,8 @@ public Update(Update other) : this() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Update Clone() { + public Update Clone() + { return new Update(this); } @@ -3541,9 +4029,11 @@ public Update Clone() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public global::Mysqlx.Crud.Collection Collection { + public global::Mysqlx.Crud.Collection Collection + { get { return collection_; } - set { + set + { collection_ = value; } } @@ -3558,9 +4048,11 @@ public Update Clone() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public global::Mysqlx.Crud.DataModel DataModel { + public global::Mysqlx.Crud.DataModel DataModel + { get { if ((_hasBits0 & 1) != 0) { return dataModel_; } else { return DataModelDefaultValue; } } - set { + set + { _hasBits0 |= 1; dataModel_ = value; } @@ -3568,13 +4060,15 @@ public Update Clone() { /// Gets whether the "data_model" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasDataModel { + public bool HasDataModel + { get { return (_hasBits0 & 1) != 0; } } /// Clears the value of the "data_model" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearDataModel() { + public void ClearDataModel() + { _hasBits0 &= ~1; } @@ -3586,9 +4080,11 @@ public void ClearDataModel() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public global::Mysqlx.Expr.Expr Criteria { + public global::Mysqlx.Expr.Expr Criteria + { get { return criteria_; } - set { + set + { criteria_ = value; } } @@ -3602,9 +4098,11 @@ public void ClearDataModel() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public global::Mysqlx.Crud.Limit Limit { + public global::Mysqlx.Crud.Limit Limit + { get { return limit_; } - set { + set + { limit_ = value; } } @@ -3619,7 +4117,8 @@ public void ClearDataModel() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public pbc::RepeatedField Order { + public pbc::RepeatedField Order + { get { return order_; } } @@ -3634,7 +4133,8 @@ public void ClearDataModel() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public pbc::RepeatedField Operation { + public pbc::RepeatedField Operation + { get { return operation_; } } @@ -3648,7 +4148,8 @@ public void ClearDataModel() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public pbc::RepeatedField Args { + public pbc::RepeatedField Args + { get { return args_; } } @@ -3661,42 +4162,49 @@ public void ClearDataModel() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public global::Mysqlx.Crud.LimitExpr LimitExpr { + public global::Mysqlx.Crud.LimitExpr LimitExpr + { get { return limitExpr_; } - set { + set + { limitExpr_ = value; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override bool Equals(object other) { + public override bool Equals(object other) + { return Equals(other as Update); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool Equals(Update other) { - if (ReferenceEquals(other, null)) { + public bool Equals(Update other) + { + if (ReferenceEquals(other, null)) + { return false; } - if (ReferenceEquals(other, this)) { + if (ReferenceEquals(other, this)) + { return true; } if (!object.Equals(Collection, other.Collection)) return false; if (DataModel != other.DataModel) return false; if (!object.Equals(Criteria, other.Criteria)) return false; if (!object.Equals(Limit, other.Limit)) return false; - if(!order_.Equals(other.order_)) return false; - if(!operation_.Equals(other.operation_)) return false; - if(!args_.Equals(other.args_)) return false; + if (!order_.Equals(other.order_)) return false; + if (!operation_.Equals(other.operation_)) return false; + if (!args_.Equals(other.args_)) return false; if (!object.Equals(LimitExpr, other.LimitExpr)) return false; return Equals(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override int GetHashCode() { + public override int GetHashCode() + { int hash = 1; if (collection_ != null) hash ^= Collection.GetHashCode(); if (HasDataModel) hash ^= DataModel.GetHashCode(); @@ -3706,7 +4214,8 @@ public override int GetHashCode() { hash ^= operation_.GetHashCode(); hash ^= args_.GetHashCode(); if (limitExpr_ != null) hash ^= LimitExpr.GetHashCode(); - if (_unknownFields != null) { + if (_unknownFields != null) + { hash ^= _unknownFields.GetHashCode(); } return hash; @@ -3714,16 +4223,18 @@ public override int GetHashCode() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override string ToString() { + public override string ToString() + { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void WriteTo(pb::CodedOutputStream output) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void WriteTo(pb::CodedOutputStream output) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE output.WriteRawMessage(this); - #else +#else if (collection_ != null) { output.WriteRawTag(18); output.WriteMessage(Collection); @@ -3750,65 +4261,79 @@ public void WriteTo(pb::CodedOutputStream output) { if (_unknownFields != null) { _unknownFields.WriteTo(output); } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { - if (collection_ != null) { + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) + { + if (collection_ != null) + { output.WriteRawTag(18); output.WriteMessage(Collection); } - if (HasDataModel) { + if (HasDataModel) + { output.WriteRawTag(24); - output.WriteEnum((int) DataModel); + output.WriteEnum((int)DataModel); } - if (criteria_ != null) { + if (criteria_ != null) + { output.WriteRawTag(34); output.WriteMessage(Criteria); } - if (limit_ != null) { + if (limit_ != null) + { output.WriteRawTag(42); output.WriteMessage(Limit); } order_.WriteTo(ref output, _repeated_order_codec); operation_.WriteTo(ref output, _repeated_operation_codec); args_.WriteTo(ref output, _repeated_args_codec); - if (limitExpr_ != null) { + if (limitExpr_ != null) + { output.WriteRawTag(74); output.WriteMessage(LimitExpr); } - if (_unknownFields != null) { + if (_unknownFields != null) + { _unknownFields.WriteTo(ref output); } } - #endif +#endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public int CalculateSize() { + public int CalculateSize() + { int size = 0; - if (collection_ != null) { + if (collection_ != null) + { size += 1 + pb::CodedOutputStream.ComputeMessageSize(Collection); } - if (HasDataModel) { - size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) DataModel); + if (HasDataModel) + { + size += 1 + pb::CodedOutputStream.ComputeEnumSize((int)DataModel); } - if (criteria_ != null) { + if (criteria_ != null) + { size += 1 + pb::CodedOutputStream.ComputeMessageSize(Criteria); } - if (limit_ != null) { + if (limit_ != null) + { size += 1 + pb::CodedOutputStream.ComputeMessageSize(Limit); } size += order_.CalculateSize(_repeated_order_codec); size += operation_.CalculateSize(_repeated_operation_codec); size += args_.CalculateSize(_repeated_args_codec); - if (limitExpr_ != null) { + if (limitExpr_ != null) + { size += 1 + pb::CodedOutputStream.ComputeMessageSize(LimitExpr); } - if (_unknownFields != null) { + if (_unknownFields != null) + { size += _unknownFields.CalculateSize(); } return size; @@ -3816,27 +4341,36 @@ public int CalculateSize() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(Update other) { - if (other == null) { + public void MergeFrom(Update other) + { + if (other == null) + { return; } - if (other.collection_ != null) { - if (collection_ == null) { + if (other.collection_ != null) + { + if (collection_ == null) + { Collection = new global::Mysqlx.Crud.Collection(); } Collection.MergeFrom(other.Collection); } - if (other.HasDataModel) { + if (other.HasDataModel) + { DataModel = other.DataModel; } - if (other.criteria_ != null) { - if (criteria_ == null) { + if (other.criteria_ != null) + { + if (criteria_ == null) + { Criteria = new global::Mysqlx.Expr.Expr(); } Criteria.MergeFrom(other.Criteria); } - if (other.limit_ != null) { - if (limit_ == null) { + if (other.limit_ != null) + { + if (limit_ == null) + { Limit = new global::Mysqlx.Crud.Limit(); } Limit.MergeFrom(other.Limit); @@ -3844,8 +4378,10 @@ public void MergeFrom(Update other) { order_.Add(other.order_); operation_.Add(other.operation_); args_.Add(other.args_); - if (other.limitExpr_ != null) { - if (limitExpr_ == null) { + if (other.limitExpr_ != null) + { + if (limitExpr_ == null) + { LimitExpr = new global::Mysqlx.Crud.LimitExpr(); } LimitExpr.MergeFrom(other.LimitExpr); @@ -3855,10 +4391,11 @@ public void MergeFrom(Update other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(pb::CodedInputStream input) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void MergeFrom(pb::CodedInputStream input) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE input.ReadRawMessage(this); - #else +#else uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { @@ -3911,67 +4448,82 @@ public void MergeFrom(pb::CodedInputStream input) { } } } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) + { uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { + while ((tag = input.ReadTag()) != 0) + { + switch (tag) + { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; - case 18: { - if (collection_ == null) { - Collection = new global::Mysqlx.Crud.Collection(); + case 18: + { + if (collection_ == null) + { + Collection = new global::Mysqlx.Crud.Collection(); + } + input.ReadMessage(Collection); + break; } - input.ReadMessage(Collection); - break; - } - case 24: { - DataModel = (global::Mysqlx.Crud.DataModel) input.ReadEnum(); - break; - } - case 34: { - if (criteria_ == null) { - Criteria = new global::Mysqlx.Expr.Expr(); + case 24: + { + DataModel = (global::Mysqlx.Crud.DataModel)input.ReadEnum(); + break; } - input.ReadMessage(Criteria); - break; - } - case 42: { - if (limit_ == null) { - Limit = new global::Mysqlx.Crud.Limit(); + case 34: + { + if (criteria_ == null) + { + Criteria = new global::Mysqlx.Expr.Expr(); + } + input.ReadMessage(Criteria); + break; } - input.ReadMessage(Limit); - break; - } - case 50: { - order_.AddEntriesFrom(ref input, _repeated_order_codec); - break; - } - case 58: { - operation_.AddEntriesFrom(ref input, _repeated_operation_codec); - break; - } - case 66: { - args_.AddEntriesFrom(ref input, _repeated_args_codec); - break; - } - case 74: { - if (limitExpr_ == null) { - LimitExpr = new global::Mysqlx.Crud.LimitExpr(); + case 42: + { + if (limit_ == null) + { + Limit = new global::Mysqlx.Crud.Limit(); + } + input.ReadMessage(Limit); + break; + } + case 50: + { + order_.AddEntriesFrom(ref input, _repeated_order_codec); + break; + } + case 58: + { + operation_.AddEntriesFrom(ref input, _repeated_operation_codec); + break; + } + case 66: + { + args_.AddEntriesFrom(ref input, _repeated_args_codec); + break; + } + case 74: + { + if (limitExpr_ == null) + { + LimitExpr = new global::Mysqlx.Crud.LimitExpr(); + } + input.ReadMessage(LimitExpr); + break; } - input.ReadMessage(LimitExpr); - break; - } } } } - #endif +#endif } @@ -3981,10 +4533,11 @@ public void MergeFrom(pb::CodedInputStream input) { /// ///@returns @ref Mysqlx::Resultset /// - internal sealed partial class Delete : pb::IMessage - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] + public sealed partial class Delete : pb::IMessage +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE , pb::IBufferMessage - #endif +#endif { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Delete()); private pb::UnknownFieldSet _unknownFields; @@ -3995,19 +4548,22 @@ internal sealed partial class Delete : pb::IMessage [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static pbr::MessageDescriptor Descriptor { + public static pbr::MessageDescriptor Descriptor + { get { return global::Mysqlx.Crud.MysqlxCrudReflection.Descriptor.MessageTypes[10]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - pbr::MessageDescriptor pb::IMessage.Descriptor { + pbr::MessageDescriptor pb::IMessage.Descriptor + { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Delete() { + public Delete() + { OnConstruction(); } @@ -4015,7 +4571,8 @@ public Delete() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Delete(Delete other) : this() { + public Delete(Delete other) : this() + { _hasBits0 = other._hasBits0; collection_ = other.collection_ != null ? other.collection_.Clone() : null; dataModel_ = other.dataModel_; @@ -4029,7 +4586,8 @@ public Delete(Delete other) : this() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Delete Clone() { + public Delete Clone() + { return new Delete(this); } @@ -4041,9 +4599,11 @@ public Delete Clone() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public global::Mysqlx.Crud.Collection Collection { + public global::Mysqlx.Crud.Collection Collection + { get { return collection_; } - set { + set + { collection_ = value; } } @@ -4058,9 +4618,11 @@ public Delete Clone() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public global::Mysqlx.Crud.DataModel DataModel { + public global::Mysqlx.Crud.DataModel DataModel + { get { if ((_hasBits0 & 1) != 0) { return dataModel_; } else { return DataModelDefaultValue; } } - set { + set + { _hasBits0 |= 1; dataModel_ = value; } @@ -4068,13 +4630,15 @@ public Delete Clone() { /// Gets whether the "data_model" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasDataModel { + public bool HasDataModel + { get { return (_hasBits0 & 1) != 0; } } /// Clears the value of the "data_model" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearDataModel() { + public void ClearDataModel() + { _hasBits0 &= ~1; } @@ -4086,9 +4650,11 @@ public void ClearDataModel() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public global::Mysqlx.Expr.Expr Criteria { + public global::Mysqlx.Expr.Expr Criteria + { get { return criteria_; } - set { + set + { criteria_ = value; } } @@ -4102,9 +4668,11 @@ public void ClearDataModel() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public global::Mysqlx.Crud.Limit Limit { + public global::Mysqlx.Crud.Limit Limit + { get { return limit_; } - set { + set + { limit_ = value; } } @@ -4119,7 +4687,8 @@ public void ClearDataModel() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public pbc::RepeatedField Order { + public pbc::RepeatedField Order + { get { return order_; } } @@ -4133,7 +4702,8 @@ public void ClearDataModel() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public pbc::RepeatedField Args { + public pbc::RepeatedField Args + { get { return args_; } } @@ -4146,41 +4716,48 @@ public void ClearDataModel() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public global::Mysqlx.Crud.LimitExpr LimitExpr { + public global::Mysqlx.Crud.LimitExpr LimitExpr + { get { return limitExpr_; } - set { + set + { limitExpr_ = value; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override bool Equals(object other) { + public override bool Equals(object other) + { return Equals(other as Delete); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool Equals(Delete other) { - if (ReferenceEquals(other, null)) { + public bool Equals(Delete other) + { + if (ReferenceEquals(other, null)) + { return false; } - if (ReferenceEquals(other, this)) { + if (ReferenceEquals(other, this)) + { return true; } if (!object.Equals(Collection, other.Collection)) return false; if (DataModel != other.DataModel) return false; if (!object.Equals(Criteria, other.Criteria)) return false; if (!object.Equals(Limit, other.Limit)) return false; - if(!order_.Equals(other.order_)) return false; - if(!args_.Equals(other.args_)) return false; + if (!order_.Equals(other.order_)) return false; + if (!args_.Equals(other.args_)) return false; if (!object.Equals(LimitExpr, other.LimitExpr)) return false; return Equals(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override int GetHashCode() { + public override int GetHashCode() + { int hash = 1; if (collection_ != null) hash ^= Collection.GetHashCode(); if (HasDataModel) hash ^= DataModel.GetHashCode(); @@ -4189,7 +4766,8 @@ public override int GetHashCode() { hash ^= order_.GetHashCode(); hash ^= args_.GetHashCode(); if (limitExpr_ != null) hash ^= LimitExpr.GetHashCode(); - if (_unknownFields != null) { + if (_unknownFields != null) + { hash ^= _unknownFields.GetHashCode(); } return hash; @@ -4197,16 +4775,18 @@ public override int GetHashCode() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override string ToString() { + public override string ToString() + { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void WriteTo(pb::CodedOutputStream output) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void WriteTo(pb::CodedOutputStream output) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE output.WriteRawMessage(this); - #else +#else if (collection_ != null) { output.WriteRawTag(10); output.WriteMessage(Collection); @@ -4232,63 +4812,77 @@ public void WriteTo(pb::CodedOutputStream output) { if (_unknownFields != null) { _unknownFields.WriteTo(output); } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { - if (collection_ != null) { + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) + { + if (collection_ != null) + { output.WriteRawTag(10); output.WriteMessage(Collection); } - if (HasDataModel) { + if (HasDataModel) + { output.WriteRawTag(16); - output.WriteEnum((int) DataModel); + output.WriteEnum((int)DataModel); } - if (criteria_ != null) { + if (criteria_ != null) + { output.WriteRawTag(26); output.WriteMessage(Criteria); } - if (limit_ != null) { + if (limit_ != null) + { output.WriteRawTag(34); output.WriteMessage(Limit); } order_.WriteTo(ref output, _repeated_order_codec); args_.WriteTo(ref output, _repeated_args_codec); - if (limitExpr_ != null) { + if (limitExpr_ != null) + { output.WriteRawTag(58); output.WriteMessage(LimitExpr); } - if (_unknownFields != null) { + if (_unknownFields != null) + { _unknownFields.WriteTo(ref output); } } - #endif +#endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public int CalculateSize() { + public int CalculateSize() + { int size = 0; - if (collection_ != null) { + if (collection_ != null) + { size += 1 + pb::CodedOutputStream.ComputeMessageSize(Collection); } - if (HasDataModel) { - size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) DataModel); + if (HasDataModel) + { + size += 1 + pb::CodedOutputStream.ComputeEnumSize((int)DataModel); } - if (criteria_ != null) { + if (criteria_ != null) + { size += 1 + pb::CodedOutputStream.ComputeMessageSize(Criteria); } - if (limit_ != null) { + if (limit_ != null) + { size += 1 + pb::CodedOutputStream.ComputeMessageSize(Limit); } size += order_.CalculateSize(_repeated_order_codec); size += args_.CalculateSize(_repeated_args_codec); - if (limitExpr_ != null) { + if (limitExpr_ != null) + { size += 1 + pb::CodedOutputStream.ComputeMessageSize(LimitExpr); } - if (_unknownFields != null) { + if (_unknownFields != null) + { size += _unknownFields.CalculateSize(); } return size; @@ -4296,35 +4890,46 @@ public int CalculateSize() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(Delete other) { - if (other == null) { + public void MergeFrom(Delete other) + { + if (other == null) + { return; } - if (other.collection_ != null) { - if (collection_ == null) { + if (other.collection_ != null) + { + if (collection_ == null) + { Collection = new global::Mysqlx.Crud.Collection(); } Collection.MergeFrom(other.Collection); } - if (other.HasDataModel) { + if (other.HasDataModel) + { DataModel = other.DataModel; } - if (other.criteria_ != null) { - if (criteria_ == null) { + if (other.criteria_ != null) + { + if (criteria_ == null) + { Criteria = new global::Mysqlx.Expr.Expr(); } Criteria.MergeFrom(other.Criteria); } - if (other.limit_ != null) { - if (limit_ == null) { + if (other.limit_ != null) + { + if (limit_ == null) + { Limit = new global::Mysqlx.Crud.Limit(); } Limit.MergeFrom(other.Limit); } order_.Add(other.order_); args_.Add(other.args_); - if (other.limitExpr_ != null) { - if (limitExpr_ == null) { + if (other.limitExpr_ != null) + { + if (limitExpr_ == null) + { LimitExpr = new global::Mysqlx.Crud.LimitExpr(); } LimitExpr.MergeFrom(other.LimitExpr); @@ -4334,10 +4939,11 @@ public void MergeFrom(Delete other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(pb::CodedInputStream input) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void MergeFrom(pb::CodedInputStream input) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE input.ReadRawMessage(this); - #else +#else uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { @@ -4386,63 +4992,77 @@ public void MergeFrom(pb::CodedInputStream input) { } } } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) + { uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { + while ((tag = input.ReadTag()) != 0) + { + switch (tag) + { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; - case 10: { - if (collection_ == null) { - Collection = new global::Mysqlx.Crud.Collection(); + case 10: + { + if (collection_ == null) + { + Collection = new global::Mysqlx.Crud.Collection(); + } + input.ReadMessage(Collection); + break; } - input.ReadMessage(Collection); - break; - } - case 16: { - DataModel = (global::Mysqlx.Crud.DataModel) input.ReadEnum(); - break; - } - case 26: { - if (criteria_ == null) { - Criteria = new global::Mysqlx.Expr.Expr(); + case 16: + { + DataModel = (global::Mysqlx.Crud.DataModel)input.ReadEnum(); + break; } - input.ReadMessage(Criteria); - break; - } - case 34: { - if (limit_ == null) { - Limit = new global::Mysqlx.Crud.Limit(); + case 26: + { + if (criteria_ == null) + { + Criteria = new global::Mysqlx.Expr.Expr(); + } + input.ReadMessage(Criteria); + break; } - input.ReadMessage(Limit); - break; - } - case 42: { - order_.AddEntriesFrom(ref input, _repeated_order_codec); - break; - } - case 50: { - args_.AddEntriesFrom(ref input, _repeated_args_codec); - break; - } - case 58: { - if (limitExpr_ == null) { - LimitExpr = new global::Mysqlx.Crud.LimitExpr(); + case 34: + { + if (limit_ == null) + { + Limit = new global::Mysqlx.Crud.Limit(); + } + input.ReadMessage(Limit); + break; + } + case 42: + { + order_.AddEntriesFrom(ref input, _repeated_order_codec); + break; + } + case 50: + { + args_.AddEntriesFrom(ref input, _repeated_args_codec); + break; + } + case 58: + { + if (limitExpr_ == null) + { + LimitExpr = new global::Mysqlx.Crud.LimitExpr(); + } + input.ReadMessage(LimitExpr); + break; } - input.ReadMessage(LimitExpr); - break; - } } } } - #endif +#endif } @@ -4450,10 +5070,11 @@ public void MergeFrom(pb::CodedInputStream input) { ///* ///CreateView create view based on indicated @ref Mysqlx::Crud::Find message /// - internal sealed partial class CreateView : pb::IMessage - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] + public sealed partial class CreateView : pb::IMessage +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE , pb::IBufferMessage - #endif +#endif { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new CreateView()); private pb::UnknownFieldSet _unknownFields; @@ -4464,19 +5085,22 @@ internal sealed partial class CreateView : pb::IMessage [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static pbr::MessageDescriptor Descriptor { + public static pbr::MessageDescriptor Descriptor + { get { return global::Mysqlx.Crud.MysqlxCrudReflection.Descriptor.MessageTypes[11]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - pbr::MessageDescriptor pb::IMessage.Descriptor { + pbr::MessageDescriptor pb::IMessage.Descriptor + { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public CreateView() { + public CreateView() + { OnConstruction(); } @@ -4484,7 +5108,8 @@ public CreateView() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public CreateView(CreateView other) : this() { + public CreateView(CreateView other) : this() + { _hasBits0 = other._hasBits0; collection_ = other.collection_ != null ? other.collection_.Clone() : null; definer_ = other.definer_; @@ -4499,7 +5124,8 @@ public CreateView(CreateView other) : this() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public CreateView Clone() { + public CreateView Clone() + { return new CreateView(this); } @@ -4511,9 +5137,11 @@ public CreateView Clone() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public global::Mysqlx.Crud.Collection Collection { + public global::Mysqlx.Crud.Collection Collection + { get { return collection_; } - set { + set + { collection_ = value; } } @@ -4529,22 +5157,26 @@ public CreateView Clone() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public string Definer { + public string Definer + { get { return definer_ ?? DefinerDefaultValue; } - set { + set + { definer_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } /// Gets whether the "definer" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasDefiner { + public bool HasDefiner + { get { return definer_ != null; } } /// Clears the value of the "definer" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearDefiner() { + public void ClearDefiner() + { definer_ = null; } @@ -4558,9 +5190,11 @@ public void ClearDefiner() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public global::Mysqlx.Crud.ViewAlgorithm Algorithm { + public global::Mysqlx.Crud.ViewAlgorithm Algorithm + { get { if ((_hasBits0 & 1) != 0) { return algorithm_; } else { return AlgorithmDefaultValue; } } - set { + set + { _hasBits0 |= 1; algorithm_ = value; } @@ -4568,13 +5202,15 @@ public void ClearDefiner() { /// Gets whether the "algorithm" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasAlgorithm { + public bool HasAlgorithm + { get { return (_hasBits0 & 1) != 0; } } /// Clears the value of the "algorithm" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearAlgorithm() { + public void ClearAlgorithm() + { _hasBits0 &= ~1; } @@ -4588,9 +5224,11 @@ public void ClearAlgorithm() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public global::Mysqlx.Crud.ViewSqlSecurity Security { + public global::Mysqlx.Crud.ViewSqlSecurity Security + { get { if ((_hasBits0 & 2) != 0) { return security_; } else { return SecurityDefaultValue; } } - set { + set + { _hasBits0 |= 2; security_ = value; } @@ -4598,13 +5236,15 @@ public void ClearAlgorithm() { /// Gets whether the "security" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasSecurity { + public bool HasSecurity + { get { return (_hasBits0 & 2) != 0; } } /// Clears the value of the "security" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearSecurity() { + public void ClearSecurity() + { _hasBits0 &= ~2; } @@ -4618,9 +5258,11 @@ public void ClearSecurity() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public global::Mysqlx.Crud.ViewCheckOption Check { + public global::Mysqlx.Crud.ViewCheckOption Check + { get { if ((_hasBits0 & 4) != 0) { return check_; } else { return CheckDefaultValue; } } - set { + set + { _hasBits0 |= 4; check_ = value; } @@ -4628,13 +5270,15 @@ public void ClearSecurity() { /// Gets whether the "check" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasCheck { + public bool HasCheck + { get { return (_hasBits0 & 4) != 0; } } /// Clears the value of the "check" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearCheck() { + public void ClearCheck() + { _hasBits0 &= ~4; } @@ -4648,7 +5292,8 @@ public void ClearCheck() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public pbc::RepeatedField Column { + public pbc::RepeatedField Column + { get { return column_; } } @@ -4661,9 +5306,11 @@ public void ClearCheck() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public global::Mysqlx.Crud.Find Stmt { + public global::Mysqlx.Crud.Find Stmt + { get { return stmt_; } - set { + set + { stmt_ = value; } } @@ -4679,9 +5326,11 @@ public void ClearCheck() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool ReplaceExisting { + public bool ReplaceExisting + { get { if ((_hasBits0 & 8) != 0) { return replaceExisting_; } else { return ReplaceExistingDefaultValue; } } - set { + set + { _hasBits0 |= 8; replaceExisting_ = value; } @@ -4689,29 +5338,35 @@ public bool ReplaceExisting { /// Gets whether the "replace_existing" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasReplaceExisting { + public bool HasReplaceExisting + { get { return (_hasBits0 & 8) != 0; } } /// Clears the value of the "replace_existing" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearReplaceExisting() { + public void ClearReplaceExisting() + { _hasBits0 &= ~8; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override bool Equals(object other) { + public override bool Equals(object other) + { return Equals(other as CreateView); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool Equals(CreateView other) { - if (ReferenceEquals(other, null)) { + public bool Equals(CreateView other) + { + if (ReferenceEquals(other, null)) + { return false; } - if (ReferenceEquals(other, this)) { + if (ReferenceEquals(other, this)) + { return true; } if (!object.Equals(Collection, other.Collection)) return false; @@ -4719,7 +5374,7 @@ public bool Equals(CreateView other) { if (Algorithm != other.Algorithm) return false; if (Security != other.Security) return false; if (Check != other.Check) return false; - if(!column_.Equals(other.column_)) return false; + if (!column_.Equals(other.column_)) return false; if (!object.Equals(Stmt, other.Stmt)) return false; if (ReplaceExisting != other.ReplaceExisting) return false; return Equals(_unknownFields, other._unknownFields); @@ -4727,7 +5382,8 @@ public bool Equals(CreateView other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override int GetHashCode() { + public override int GetHashCode() + { int hash = 1; if (collection_ != null) hash ^= Collection.GetHashCode(); if (HasDefiner) hash ^= Definer.GetHashCode(); @@ -4737,7 +5393,8 @@ public override int GetHashCode() { hash ^= column_.GetHashCode(); if (stmt_ != null) hash ^= Stmt.GetHashCode(); if (HasReplaceExisting) hash ^= ReplaceExisting.GetHashCode(); - if (_unknownFields != null) { + if (_unknownFields != null) + { hash ^= _unknownFields.GetHashCode(); } return hash; @@ -4745,16 +5402,18 @@ public override int GetHashCode() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override string ToString() { + public override string ToString() + { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void WriteTo(pb::CodedOutputStream output) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void WriteTo(pb::CodedOutputStream output) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE output.WriteRawMessage(this); - #else +#else if (collection_ != null) { output.WriteRawTag(10); output.WriteMessage(Collection); @@ -4787,75 +5446,93 @@ public void WriteTo(pb::CodedOutputStream output) { if (_unknownFields != null) { _unknownFields.WriteTo(output); } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { - if (collection_ != null) { + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) + { + if (collection_ != null) + { output.WriteRawTag(10); output.WriteMessage(Collection); } - if (HasDefiner) { + if (HasDefiner) + { output.WriteRawTag(18); output.WriteString(Definer); } - if (HasAlgorithm) { + if (HasAlgorithm) + { output.WriteRawTag(24); - output.WriteEnum((int) Algorithm); + output.WriteEnum((int)Algorithm); } - if (HasSecurity) { + if (HasSecurity) + { output.WriteRawTag(32); - output.WriteEnum((int) Security); + output.WriteEnum((int)Security); } - if (HasCheck) { + if (HasCheck) + { output.WriteRawTag(40); - output.WriteEnum((int) Check); + output.WriteEnum((int)Check); } column_.WriteTo(ref output, _repeated_column_codec); - if (stmt_ != null) { + if (stmt_ != null) + { output.WriteRawTag(58); output.WriteMessage(Stmt); } - if (HasReplaceExisting) { + if (HasReplaceExisting) + { output.WriteRawTag(64); output.WriteBool(ReplaceExisting); } - if (_unknownFields != null) { + if (_unknownFields != null) + { _unknownFields.WriteTo(ref output); } } - #endif +#endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public int CalculateSize() { + public int CalculateSize() + { int size = 0; - if (collection_ != null) { + if (collection_ != null) + { size += 1 + pb::CodedOutputStream.ComputeMessageSize(Collection); } - if (HasDefiner) { + if (HasDefiner) + { size += 1 + pb::CodedOutputStream.ComputeStringSize(Definer); } - if (HasAlgorithm) { - size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Algorithm); + if (HasAlgorithm) + { + size += 1 + pb::CodedOutputStream.ComputeEnumSize((int)Algorithm); } - if (HasSecurity) { - size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Security); + if (HasSecurity) + { + size += 1 + pb::CodedOutputStream.ComputeEnumSize((int)Security); } - if (HasCheck) { - size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Check); + if (HasCheck) + { + size += 1 + pb::CodedOutputStream.ComputeEnumSize((int)Check); } size += column_.CalculateSize(_repeated_column_codec); - if (stmt_ != null) { + if (stmt_ != null) + { size += 1 + pb::CodedOutputStream.ComputeMessageSize(Stmt); } - if (HasReplaceExisting) { + if (HasReplaceExisting) + { size += 1 + 1; } - if (_unknownFields != null) { + if (_unknownFields != null) + { size += _unknownFields.CalculateSize(); } return size; @@ -4863,36 +5540,47 @@ public int CalculateSize() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(CreateView other) { - if (other == null) { + public void MergeFrom(CreateView other) + { + if (other == null) + { return; } - if (other.collection_ != null) { - if (collection_ == null) { + if (other.collection_ != null) + { + if (collection_ == null) + { Collection = new global::Mysqlx.Crud.Collection(); } Collection.MergeFrom(other.Collection); } - if (other.HasDefiner) { + if (other.HasDefiner) + { Definer = other.Definer; } - if (other.HasAlgorithm) { + if (other.HasAlgorithm) + { Algorithm = other.Algorithm; } - if (other.HasSecurity) { + if (other.HasSecurity) + { Security = other.Security; } - if (other.HasCheck) { + if (other.HasCheck) + { Check = other.Check; } column_.Add(other.column_); - if (other.stmt_ != null) { - if (stmt_ == null) { + if (other.stmt_ != null) + { + if (stmt_ == null) + { Stmt = new global::Mysqlx.Crud.Find(); } Stmt.MergeFrom(other.Stmt); } - if (other.HasReplaceExisting) { + if (other.HasReplaceExisting) + { ReplaceExisting = other.ReplaceExisting; } _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); @@ -4900,10 +5588,11 @@ public void MergeFrom(CreateView other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(pb::CodedInputStream input) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void MergeFrom(pb::CodedInputStream input) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE input.ReadRawMessage(this); - #else +#else uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { @@ -4950,61 +5639,74 @@ public void MergeFrom(pb::CodedInputStream input) { } } } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) + { uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { + while ((tag = input.ReadTag()) != 0) + { + switch (tag) + { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; - case 10: { - if (collection_ == null) { - Collection = new global::Mysqlx.Crud.Collection(); + case 10: + { + if (collection_ == null) + { + Collection = new global::Mysqlx.Crud.Collection(); + } + input.ReadMessage(Collection); + break; } - input.ReadMessage(Collection); - break; - } - case 18: { - Definer = input.ReadString(); - break; - } - case 24: { - Algorithm = (global::Mysqlx.Crud.ViewAlgorithm) input.ReadEnum(); - break; - } - case 32: { - Security = (global::Mysqlx.Crud.ViewSqlSecurity) input.ReadEnum(); - break; - } - case 40: { - Check = (global::Mysqlx.Crud.ViewCheckOption) input.ReadEnum(); - break; - } - case 50: { - column_.AddEntriesFrom(ref input, _repeated_column_codec); - break; - } - case 58: { - if (stmt_ == null) { - Stmt = new global::Mysqlx.Crud.Find(); + case 18: + { + Definer = input.ReadString(); + break; + } + case 24: + { + Algorithm = (global::Mysqlx.Crud.ViewAlgorithm)input.ReadEnum(); + break; + } + case 32: + { + Security = (global::Mysqlx.Crud.ViewSqlSecurity)input.ReadEnum(); + break; + } + case 40: + { + Check = (global::Mysqlx.Crud.ViewCheckOption)input.ReadEnum(); + break; + } + case 50: + { + column_.AddEntriesFrom(ref input, _repeated_column_codec); + break; + } + case 58: + { + if (stmt_ == null) + { + Stmt = new global::Mysqlx.Crud.Find(); + } + input.ReadMessage(Stmt); + break; + } + case 64: + { + ReplaceExisting = input.ReadBool(); + break; } - input.ReadMessage(Stmt); - break; - } - case 64: { - ReplaceExisting = input.ReadBool(); - break; - } } } } - #endif +#endif } @@ -5013,10 +5715,11 @@ public void MergeFrom(pb::CodedInputStream input) { ///ModifyView modify existing view based on indicated ///@ref Mysqlx::Crud::Find message /// - internal sealed partial class ModifyView : pb::IMessage - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] + public sealed partial class ModifyView : pb::IMessage +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE , pb::IBufferMessage - #endif +#endif { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ModifyView()); private pb::UnknownFieldSet _unknownFields; @@ -5027,19 +5730,22 @@ internal sealed partial class ModifyView : pb::IMessage [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static pbr::MessageDescriptor Descriptor { + public static pbr::MessageDescriptor Descriptor + { get { return global::Mysqlx.Crud.MysqlxCrudReflection.Descriptor.MessageTypes[12]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - pbr::MessageDescriptor pb::IMessage.Descriptor { + pbr::MessageDescriptor pb::IMessage.Descriptor + { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public ModifyView() { + public ModifyView() + { OnConstruction(); } @@ -5047,7 +5753,8 @@ public ModifyView() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public ModifyView(ModifyView other) : this() { + public ModifyView(ModifyView other) : this() + { _hasBits0 = other._hasBits0; collection_ = other.collection_ != null ? other.collection_.Clone() : null; definer_ = other.definer_; @@ -5061,7 +5768,8 @@ public ModifyView(ModifyView other) : this() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public ModifyView Clone() { + public ModifyView Clone() + { return new ModifyView(this); } @@ -5073,9 +5781,11 @@ public ModifyView Clone() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public global::Mysqlx.Crud.Collection Collection { + public global::Mysqlx.Crud.Collection Collection + { get { return collection_; } - set { + set + { collection_ = value; } } @@ -5091,22 +5801,26 @@ public ModifyView Clone() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public string Definer { + public string Definer + { get { return definer_ ?? DefinerDefaultValue; } - set { + set + { definer_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } /// Gets whether the "definer" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasDefiner { + public bool HasDefiner + { get { return definer_ != null; } } /// Clears the value of the "definer" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearDefiner() { + public void ClearDefiner() + { definer_ = null; } @@ -5120,9 +5834,11 @@ public void ClearDefiner() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public global::Mysqlx.Crud.ViewAlgorithm Algorithm { + public global::Mysqlx.Crud.ViewAlgorithm Algorithm + { get { if ((_hasBits0 & 1) != 0) { return algorithm_; } else { return AlgorithmDefaultValue; } } - set { + set + { _hasBits0 |= 1; algorithm_ = value; } @@ -5130,13 +5846,15 @@ public void ClearDefiner() { /// Gets whether the "algorithm" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasAlgorithm { + public bool HasAlgorithm + { get { return (_hasBits0 & 1) != 0; } } /// Clears the value of the "algorithm" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearAlgorithm() { + public void ClearAlgorithm() + { _hasBits0 &= ~1; } @@ -5150,9 +5868,11 @@ public void ClearAlgorithm() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public global::Mysqlx.Crud.ViewSqlSecurity Security { + public global::Mysqlx.Crud.ViewSqlSecurity Security + { get { if ((_hasBits0 & 2) != 0) { return security_; } else { return SecurityDefaultValue; } } - set { + set + { _hasBits0 |= 2; security_ = value; } @@ -5160,13 +5880,15 @@ public void ClearAlgorithm() { /// Gets whether the "security" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasSecurity { + public bool HasSecurity + { get { return (_hasBits0 & 2) != 0; } } /// Clears the value of the "security" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearSecurity() { + public void ClearSecurity() + { _hasBits0 &= ~2; } @@ -5180,9 +5902,11 @@ public void ClearSecurity() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public global::Mysqlx.Crud.ViewCheckOption Check { + public global::Mysqlx.Crud.ViewCheckOption Check + { get { if ((_hasBits0 & 4) != 0) { return check_; } else { return CheckDefaultValue; } } - set { + set + { _hasBits0 |= 4; check_ = value; } @@ -5190,13 +5914,15 @@ public void ClearSecurity() { /// Gets whether the "check" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasCheck { + public bool HasCheck + { get { return (_hasBits0 & 4) != 0; } } /// Clears the value of the "check" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearCheck() { + public void ClearCheck() + { _hasBits0 &= ~4; } @@ -5210,7 +5936,8 @@ public void ClearCheck() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public pbc::RepeatedField Column { + public pbc::RepeatedField Column + { get { return column_; } } @@ -5223,26 +5950,32 @@ public void ClearCheck() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public global::Mysqlx.Crud.Find Stmt { + public global::Mysqlx.Crud.Find Stmt + { get { return stmt_; } - set { + set + { stmt_ = value; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override bool Equals(object other) { + public override bool Equals(object other) + { return Equals(other as ModifyView); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool Equals(ModifyView other) { - if (ReferenceEquals(other, null)) { + public bool Equals(ModifyView other) + { + if (ReferenceEquals(other, null)) + { return false; } - if (ReferenceEquals(other, this)) { + if (ReferenceEquals(other, this)) + { return true; } if (!object.Equals(Collection, other.Collection)) return false; @@ -5250,14 +5983,15 @@ public bool Equals(ModifyView other) { if (Algorithm != other.Algorithm) return false; if (Security != other.Security) return false; if (Check != other.Check) return false; - if(!column_.Equals(other.column_)) return false; + if (!column_.Equals(other.column_)) return false; if (!object.Equals(Stmt, other.Stmt)) return false; return Equals(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override int GetHashCode() { + public override int GetHashCode() + { int hash = 1; if (collection_ != null) hash ^= Collection.GetHashCode(); if (HasDefiner) hash ^= Definer.GetHashCode(); @@ -5266,7 +6000,8 @@ public override int GetHashCode() { if (HasCheck) hash ^= Check.GetHashCode(); hash ^= column_.GetHashCode(); if (stmt_ != null) hash ^= Stmt.GetHashCode(); - if (_unknownFields != null) { + if (_unknownFields != null) + { hash ^= _unknownFields.GetHashCode(); } return hash; @@ -5274,16 +6009,18 @@ public override int GetHashCode() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override string ToString() { + public override string ToString() + { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void WriteTo(pb::CodedOutputStream output) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void WriteTo(pb::CodedOutputStream output) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE output.WriteRawMessage(this); - #else +#else if (collection_ != null) { output.WriteRawTag(10); output.WriteMessage(Collection); @@ -5312,68 +6049,84 @@ public void WriteTo(pb::CodedOutputStream output) { if (_unknownFields != null) { _unknownFields.WriteTo(output); } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { - if (collection_ != null) { + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) + { + if (collection_ != null) + { output.WriteRawTag(10); output.WriteMessage(Collection); } - if (HasDefiner) { + if (HasDefiner) + { output.WriteRawTag(18); output.WriteString(Definer); } - if (HasAlgorithm) { + if (HasAlgorithm) + { output.WriteRawTag(24); - output.WriteEnum((int) Algorithm); + output.WriteEnum((int)Algorithm); } - if (HasSecurity) { + if (HasSecurity) + { output.WriteRawTag(32); - output.WriteEnum((int) Security); + output.WriteEnum((int)Security); } - if (HasCheck) { + if (HasCheck) + { output.WriteRawTag(40); - output.WriteEnum((int) Check); + output.WriteEnum((int)Check); } column_.WriteTo(ref output, _repeated_column_codec); - if (stmt_ != null) { + if (stmt_ != null) + { output.WriteRawTag(58); output.WriteMessage(Stmt); } - if (_unknownFields != null) { + if (_unknownFields != null) + { _unknownFields.WriteTo(ref output); } } - #endif +#endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public int CalculateSize() { + public int CalculateSize() + { int size = 0; - if (collection_ != null) { + if (collection_ != null) + { size += 1 + pb::CodedOutputStream.ComputeMessageSize(Collection); } - if (HasDefiner) { + if (HasDefiner) + { size += 1 + pb::CodedOutputStream.ComputeStringSize(Definer); } - if (HasAlgorithm) { - size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Algorithm); + if (HasAlgorithm) + { + size += 1 + pb::CodedOutputStream.ComputeEnumSize((int)Algorithm); } - if (HasSecurity) { - size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Security); + if (HasSecurity) + { + size += 1 + pb::CodedOutputStream.ComputeEnumSize((int)Security); } - if (HasCheck) { - size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Check); + if (HasCheck) + { + size += 1 + pb::CodedOutputStream.ComputeEnumSize((int)Check); } size += column_.CalculateSize(_repeated_column_codec); - if (stmt_ != null) { + if (stmt_ != null) + { size += 1 + pb::CodedOutputStream.ComputeMessageSize(Stmt); } - if (_unknownFields != null) { + if (_unknownFields != null) + { size += _unknownFields.CalculateSize(); } return size; @@ -5381,31 +6134,41 @@ public int CalculateSize() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(ModifyView other) { - if (other == null) { + public void MergeFrom(ModifyView other) + { + if (other == null) + { return; } - if (other.collection_ != null) { - if (collection_ == null) { + if (other.collection_ != null) + { + if (collection_ == null) + { Collection = new global::Mysqlx.Crud.Collection(); } Collection.MergeFrom(other.Collection); } - if (other.HasDefiner) { + if (other.HasDefiner) + { Definer = other.Definer; } - if (other.HasAlgorithm) { + if (other.HasAlgorithm) + { Algorithm = other.Algorithm; } - if (other.HasSecurity) { + if (other.HasSecurity) + { Security = other.Security; } - if (other.HasCheck) { + if (other.HasCheck) + { Check = other.Check; } column_.Add(other.column_); - if (other.stmt_ != null) { - if (stmt_ == null) { + if (other.stmt_ != null) + { + if (stmt_ == null) + { Stmt = new global::Mysqlx.Crud.Find(); } Stmt.MergeFrom(other.Stmt); @@ -5415,10 +6178,11 @@ public void MergeFrom(ModifyView other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(pb::CodedInputStream input) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void MergeFrom(pb::CodedInputStream input) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE input.ReadRawMessage(this); - #else +#else uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { @@ -5461,57 +6225,69 @@ public void MergeFrom(pb::CodedInputStream input) { } } } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) + { uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { + while ((tag = input.ReadTag()) != 0) + { + switch (tag) + { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; - case 10: { - if (collection_ == null) { - Collection = new global::Mysqlx.Crud.Collection(); + case 10: + { + if (collection_ == null) + { + Collection = new global::Mysqlx.Crud.Collection(); + } + input.ReadMessage(Collection); + break; } - input.ReadMessage(Collection); - break; - } - case 18: { - Definer = input.ReadString(); - break; - } - case 24: { - Algorithm = (global::Mysqlx.Crud.ViewAlgorithm) input.ReadEnum(); - break; - } - case 32: { - Security = (global::Mysqlx.Crud.ViewSqlSecurity) input.ReadEnum(); - break; - } - case 40: { - Check = (global::Mysqlx.Crud.ViewCheckOption) input.ReadEnum(); - break; - } - case 50: { - column_.AddEntriesFrom(ref input, _repeated_column_codec); - break; - } - case 58: { - if (stmt_ == null) { - Stmt = new global::Mysqlx.Crud.Find(); + case 18: + { + Definer = input.ReadString(); + break; + } + case 24: + { + Algorithm = (global::Mysqlx.Crud.ViewAlgorithm)input.ReadEnum(); + break; + } + case 32: + { + Security = (global::Mysqlx.Crud.ViewSqlSecurity)input.ReadEnum(); + break; + } + case 40: + { + Check = (global::Mysqlx.Crud.ViewCheckOption)input.ReadEnum(); + break; + } + case 50: + { + column_.AddEntriesFrom(ref input, _repeated_column_codec); + break; + } + case 58: + { + if (stmt_ == null) + { + Stmt = new global::Mysqlx.Crud.Find(); + } + input.ReadMessage(Stmt); + break; } - input.ReadMessage(Stmt); - break; - } } } } - #endif +#endif } @@ -5519,10 +6295,11 @@ public void MergeFrom(pb::CodedInputStream input) { ///* ///DropView removing existing view /// - internal sealed partial class DropView : pb::IMessage - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] + public sealed partial class DropView : pb::IMessage +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE , pb::IBufferMessage - #endif +#endif { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new DropView()); private pb::UnknownFieldSet _unknownFields; @@ -5533,19 +6310,22 @@ internal sealed partial class DropView : pb::IMessage [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static pbr::MessageDescriptor Descriptor { + public static pbr::MessageDescriptor Descriptor + { get { return global::Mysqlx.Crud.MysqlxCrudReflection.Descriptor.MessageTypes[13]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - pbr::MessageDescriptor pb::IMessage.Descriptor { + pbr::MessageDescriptor pb::IMessage.Descriptor + { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public DropView() { + public DropView() + { OnConstruction(); } @@ -5553,7 +6333,8 @@ public DropView() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public DropView(DropView other) : this() { + public DropView(DropView other) : this() + { _hasBits0 = other._hasBits0; collection_ = other.collection_ != null ? other.collection_.Clone() : null; ifExists_ = other.ifExists_; @@ -5562,7 +6343,8 @@ public DropView(DropView other) : this() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public DropView Clone() { + public DropView Clone() + { return new DropView(this); } @@ -5574,9 +6356,11 @@ public DropView Clone() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public global::Mysqlx.Crud.Collection Collection { + public global::Mysqlx.Crud.Collection Collection + { get { return collection_; } - set { + set + { collection_ = value; } } @@ -5591,9 +6375,11 @@ public DropView Clone() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool IfExists { + public bool IfExists + { get { if ((_hasBits0 & 1) != 0) { return ifExists_; } else { return IfExistsDefaultValue; } } - set { + set + { _hasBits0 |= 1; ifExists_ = value; } @@ -5601,29 +6387,35 @@ public bool IfExists { /// Gets whether the "if_exists" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasIfExists { + public bool HasIfExists + { get { return (_hasBits0 & 1) != 0; } } /// Clears the value of the "if_exists" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearIfExists() { + public void ClearIfExists() + { _hasBits0 &= ~1; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override bool Equals(object other) { + public override bool Equals(object other) + { return Equals(other as DropView); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool Equals(DropView other) { - if (ReferenceEquals(other, null)) { + public bool Equals(DropView other) + { + if (ReferenceEquals(other, null)) + { return false; } - if (ReferenceEquals(other, this)) { + if (ReferenceEquals(other, this)) + { return true; } if (!object.Equals(Collection, other.Collection)) return false; @@ -5633,11 +6425,13 @@ public bool Equals(DropView other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override int GetHashCode() { + public override int GetHashCode() + { int hash = 1; if (collection_ != null) hash ^= Collection.GetHashCode(); if (HasIfExists) hash ^= IfExists.GetHashCode(); - if (_unknownFields != null) { + if (_unknownFields != null) + { hash ^= _unknownFields.GetHashCode(); } return hash; @@ -5645,16 +6439,18 @@ public override int GetHashCode() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override string ToString() { + public override string ToString() + { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void WriteTo(pb::CodedOutputStream output) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void WriteTo(pb::CodedOutputStream output) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE output.WriteRawMessage(this); - #else +#else if (collection_ != null) { output.WriteRawTag(10); output.WriteMessage(Collection); @@ -5666,38 +6462,46 @@ public void WriteTo(pb::CodedOutputStream output) { if (_unknownFields != null) { _unknownFields.WriteTo(output); } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { - if (collection_ != null) { + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) + { + if (collection_ != null) + { output.WriteRawTag(10); output.WriteMessage(Collection); } - if (HasIfExists) { + if (HasIfExists) + { output.WriteRawTag(16); output.WriteBool(IfExists); } - if (_unknownFields != null) { + if (_unknownFields != null) + { _unknownFields.WriteTo(ref output); } } - #endif +#endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public int CalculateSize() { + public int CalculateSize() + { int size = 0; - if (collection_ != null) { + if (collection_ != null) + { size += 1 + pb::CodedOutputStream.ComputeMessageSize(Collection); } - if (HasIfExists) { + if (HasIfExists) + { size += 1 + 1; } - if (_unknownFields != null) { + if (_unknownFields != null) + { size += _unknownFields.CalculateSize(); } return size; @@ -5705,17 +6509,22 @@ public int CalculateSize() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(DropView other) { - if (other == null) { + public void MergeFrom(DropView other) + { + if (other == null) + { return; } - if (other.collection_ != null) { - if (collection_ == null) { + if (other.collection_ != null) + { + if (collection_ == null) + { Collection = new global::Mysqlx.Crud.Collection(); } Collection.MergeFrom(other.Collection); } - if (other.HasIfExists) { + if (other.HasIfExists) + { IfExists = other.IfExists; } _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); @@ -5723,10 +6532,11 @@ public void MergeFrom(DropView other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(pb::CodedInputStream input) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void MergeFrom(pb::CodedInputStream input) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE input.ReadRawMessage(this); - #else +#else uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { @@ -5746,34 +6556,40 @@ public void MergeFrom(pb::CodedInputStream input) { } } } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) + { uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { + while ((tag = input.ReadTag()) != 0) + { + switch (tag) + { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; - case 10: { - if (collection_ == null) { - Collection = new global::Mysqlx.Crud.Collection(); + case 10: + { + if (collection_ == null) + { + Collection = new global::Mysqlx.Crud.Collection(); + } + input.ReadMessage(Collection); + break; + } + case 16: + { + IfExists = input.ReadBool(); + break; } - input.ReadMessage(Collection); - break; - } - case 16: { - IfExists = input.ReadBool(); - break; - } } } } - #endif +#endif } diff --git a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxCursor.cs b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxCursor.cs index 2faf288d0..a6afe056b 100644 --- a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxCursor.cs +++ b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxCursor.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2022, 2023, Oracle and/or its affiliates. +// Copyright (c) 2023, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as @@ -7,7 +7,7 @@ // This program is also distributed with certain software (including // but not limited to OpenSSL) that is licensed under separate terms, // as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an +// documentation. The authors of MySQL hereby grant you an // additional permission to link the program and your derivative works // with the separately licensed software that they have included with // MySQL. @@ -37,19 +37,23 @@ using pbc = global::Google.Protobuf.Collections; using pbr = global::Google.Protobuf.Reflection; using scg = global::System.Collections.Generic; -namespace Mysqlx.Cursor { +namespace Mysqlx.Cursor +{ /// Holder for reflection information generated from mysqlx_cursor.proto - internal static partial class MysqlxCursorReflection { + public static partial class MysqlxCursorReflection + { #region Descriptor /// File descriptor for mysqlx_cursor.proto - public static pbr::FileDescriptor Descriptor { + public static pbr::FileDescriptor Descriptor + { get { return descriptor; } } private static pbr::FileDescriptor descriptor; - static MysqlxCursorReflection() { + static MysqlxCursorReflection() + { byte[] descriptorData = global::System.Convert.FromBase64String( string.Concat( "ChNteXNxbHhfY3Vyc29yLnByb3RvEg1NeXNxbHguQ3Vyc29yGgxteXNxbHgu", @@ -90,10 +94,11 @@ static MysqlxCursorReflection() { /// ///@returns @ref Mysqlx::Ok /// - internal sealed partial class Open : pb::IMessage - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] + public sealed partial class Open : pb::IMessage +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE , pb::IBufferMessage - #endif +#endif { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Open()); private pb::UnknownFieldSet _unknownFields; @@ -104,19 +109,22 @@ internal sealed partial class Open : pb::IMessage [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static pbr::MessageDescriptor Descriptor { + public static pbr::MessageDescriptor Descriptor + { get { return global::Mysqlx.Cursor.MysqlxCursorReflection.Descriptor.MessageTypes[0]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - pbr::MessageDescriptor pb::IMessage.Descriptor { + pbr::MessageDescriptor pb::IMessage.Descriptor + { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Open() { + public Open() + { OnConstruction(); } @@ -124,7 +132,8 @@ public Open() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Open(Open other) : this() { + public Open(Open other) : this() + { _hasBits0 = other._hasBits0; cursorId_ = other.cursorId_; stmt_ = other.stmt_ != null ? other.stmt_.Clone() : null; @@ -134,7 +143,8 @@ public Open(Open other) : this() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Open Clone() { + public Open Clone() + { return new Open(this); } @@ -149,9 +159,11 @@ public Open Clone() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public uint CursorId { + public uint CursorId + { get { if ((_hasBits0 & 1) != 0) { return cursorId_; } else { return CursorIdDefaultValue; } } - set { + set + { _hasBits0 |= 1; cursorId_ = value; } @@ -159,13 +171,15 @@ public uint CursorId { /// Gets whether the "cursor_id" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasCursorId { + public bool HasCursorId + { get { return (_hasBits0 & 1) != 0; } } /// Clears the value of the "cursor_id" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearCursorId() { + public void ClearCursorId() + { _hasBits0 &= ~1; } @@ -177,9 +191,11 @@ public void ClearCursorId() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public global::Mysqlx.Cursor.Open.Types.OneOfMessage Stmt { + public global::Mysqlx.Cursor.Open.Types.OneOfMessage Stmt + { get { return stmt_; } - set { + set + { stmt_ = value; } } @@ -194,9 +210,11 @@ public void ClearCursorId() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public ulong FetchRows { + public ulong FetchRows + { get { if ((_hasBits0 & 2) != 0) { return fetchRows_; } else { return FetchRowsDefaultValue; } } - set { + set + { _hasBits0 |= 2; fetchRows_ = value; } @@ -204,29 +222,35 @@ public ulong FetchRows { /// Gets whether the "fetch_rows" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasFetchRows { + public bool HasFetchRows + { get { return (_hasBits0 & 2) != 0; } } /// Clears the value of the "fetch_rows" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearFetchRows() { + public void ClearFetchRows() + { _hasBits0 &= ~2; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override bool Equals(object other) { + public override bool Equals(object other) + { return Equals(other as Open); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool Equals(Open other) { - if (ReferenceEquals(other, null)) { + public bool Equals(Open other) + { + if (ReferenceEquals(other, null)) + { return false; } - if (ReferenceEquals(other, this)) { + if (ReferenceEquals(other, this)) + { return true; } if (CursorId != other.CursorId) return false; @@ -237,12 +261,14 @@ public bool Equals(Open other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override int GetHashCode() { + public override int GetHashCode() + { int hash = 1; if (HasCursorId) hash ^= CursorId.GetHashCode(); if (stmt_ != null) hash ^= Stmt.GetHashCode(); if (HasFetchRows) hash ^= FetchRows.GetHashCode(); - if (_unknownFields != null) { + if (_unknownFields != null) + { hash ^= _unknownFields.GetHashCode(); } return hash; @@ -250,16 +276,18 @@ public override int GetHashCode() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override string ToString() { + public override string ToString() + { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void WriteTo(pb::CodedOutputStream output) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void WriteTo(pb::CodedOutputStream output) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE output.WriteRawMessage(this); - #else +#else if (HasCursorId) { output.WriteRawTag(8); output.WriteUInt32(CursorId); @@ -275,45 +303,55 @@ public void WriteTo(pb::CodedOutputStream output) { if (_unknownFields != null) { _unknownFields.WriteTo(output); } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { - if (HasCursorId) { + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) + { + if (HasCursorId) + { output.WriteRawTag(8); output.WriteUInt32(CursorId); } - if (stmt_ != null) { + if (stmt_ != null) + { output.WriteRawTag(34); output.WriteMessage(Stmt); } - if (HasFetchRows) { + if (HasFetchRows) + { output.WriteRawTag(40); output.WriteUInt64(FetchRows); } - if (_unknownFields != null) { + if (_unknownFields != null) + { _unknownFields.WriteTo(ref output); } } - #endif +#endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public int CalculateSize() { + public int CalculateSize() + { int size = 0; - if (HasCursorId) { + if (HasCursorId) + { size += 1 + pb::CodedOutputStream.ComputeUInt32Size(CursorId); } - if (stmt_ != null) { + if (stmt_ != null) + { size += 1 + pb::CodedOutputStream.ComputeMessageSize(Stmt); } - if (HasFetchRows) { + if (HasFetchRows) + { size += 1 + pb::CodedOutputStream.ComputeUInt64Size(FetchRows); } - if (_unknownFields != null) { + if (_unknownFields != null) + { size += _unknownFields.CalculateSize(); } return size; @@ -321,20 +359,26 @@ public int CalculateSize() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(Open other) { - if (other == null) { + public void MergeFrom(Open other) + { + if (other == null) + { return; } - if (other.HasCursorId) { + if (other.HasCursorId) + { CursorId = other.CursorId; } - if (other.stmt_ != null) { - if (stmt_ == null) { + if (other.stmt_ != null) + { + if (stmt_ == null) + { Stmt = new global::Mysqlx.Cursor.Open.Types.OneOfMessage(); } Stmt.MergeFrom(other.Stmt); } - if (other.HasFetchRows) { + if (other.HasFetchRows) + { FetchRows = other.FetchRows; } _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); @@ -342,10 +386,11 @@ public void MergeFrom(Open other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(pb::CodedInputStream input) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void MergeFrom(pb::CodedInputStream input) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE input.ReadRawMessage(this); - #else +#else uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { @@ -369,48 +414,57 @@ public void MergeFrom(pb::CodedInputStream input) { } } } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) + { uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { + while ((tag = input.ReadTag()) != 0) + { + switch (tag) + { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; - case 8: { - CursorId = input.ReadUInt32(); - break; - } - case 34: { - if (stmt_ == null) { - Stmt = new global::Mysqlx.Cursor.Open.Types.OneOfMessage(); + case 8: + { + CursorId = input.ReadUInt32(); + break; + } + case 34: + { + if (stmt_ == null) + { + Stmt = new global::Mysqlx.Cursor.Open.Types.OneOfMessage(); + } + input.ReadMessage(Stmt); + break; + } + case 40: + { + FetchRows = input.ReadUInt64(); + break; } - input.ReadMessage(Stmt); - break; - } - case 40: { - FetchRows = input.ReadUInt64(); - break; - } } } } - #endif +#endif #region Nested types /// Container for nested types declared in the Open message type. [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static partial class Types { + public static partial class Types + { + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] public sealed partial class OneOfMessage : pb::IMessage - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE , pb::IBufferMessage - #endif +#endif { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new OneOfMessage()); private pb::UnknownFieldSet _unknownFields; @@ -421,19 +475,22 @@ public sealed partial class OneOfMessage : pb::IMessage [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static pbr::MessageDescriptor Descriptor { + public static pbr::MessageDescriptor Descriptor + { get { return global::Mysqlx.Cursor.Open.Descriptor.NestedTypes[0]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - pbr::MessageDescriptor pb::IMessage.Descriptor { + pbr::MessageDescriptor pb::IMessage.Descriptor + { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public OneOfMessage() { + public OneOfMessage() + { OnConstruction(); } @@ -441,7 +498,8 @@ public OneOfMessage() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public OneOfMessage(OneOfMessage other) : this() { + public OneOfMessage(OneOfMessage other) : this() + { _hasBits0 = other._hasBits0; type_ = other.type_; prepareExecute_ = other.prepareExecute_ != null ? other.prepareExecute_.Clone() : null; @@ -450,7 +508,8 @@ public OneOfMessage(OneOfMessage other) : this() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public OneOfMessage Clone() { + public OneOfMessage Clone() + { return new OneOfMessage(this); } @@ -461,9 +520,11 @@ public OneOfMessage Clone() { private global::Mysqlx.Cursor.Open.Types.OneOfMessage.Types.Type type_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public global::Mysqlx.Cursor.Open.Types.OneOfMessage.Types.Type Type { + public global::Mysqlx.Cursor.Open.Types.OneOfMessage.Types.Type Type + { get { if ((_hasBits0 & 1) != 0) { return type_; } else { return TypeDefaultValue; } } - set { + set + { _hasBits0 |= 1; type_ = value; } @@ -471,13 +532,15 @@ public OneOfMessage Clone() { /// Gets whether the "type" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasType { + public bool HasType + { get { return (_hasBits0 & 1) != 0; } } /// Clears the value of the "type" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearType() { + public void ClearType() + { _hasBits0 &= ~1; } @@ -486,26 +549,32 @@ public void ClearType() { private global::Mysqlx.Prepare.Execute prepareExecute_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public global::Mysqlx.Prepare.Execute PrepareExecute { + public global::Mysqlx.Prepare.Execute PrepareExecute + { get { return prepareExecute_; } - set { + set + { prepareExecute_ = value; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override bool Equals(object other) { + public override bool Equals(object other) + { return Equals(other as OneOfMessage); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool Equals(OneOfMessage other) { - if (ReferenceEquals(other, null)) { + public bool Equals(OneOfMessage other) + { + if (ReferenceEquals(other, null)) + { return false; } - if (ReferenceEquals(other, this)) { + if (ReferenceEquals(other, this)) + { return true; } if (Type != other.Type) return false; @@ -515,11 +584,13 @@ public bool Equals(OneOfMessage other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override int GetHashCode() { + public override int GetHashCode() + { int hash = 1; if (HasType) hash ^= Type.GetHashCode(); if (prepareExecute_ != null) hash ^= PrepareExecute.GetHashCode(); - if (_unknownFields != null) { + if (_unknownFields != null) + { hash ^= _unknownFields.GetHashCode(); } return hash; @@ -527,16 +598,18 @@ public override int GetHashCode() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override string ToString() { + public override string ToString() + { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void WriteTo(pb::CodedOutputStream output) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void WriteTo(pb::CodedOutputStream output) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE output.WriteRawMessage(this); - #else +#else if (HasType) { output.WriteRawTag(8); output.WriteEnum((int) Type); @@ -548,38 +621,46 @@ public void WriteTo(pb::CodedOutputStream output) { if (_unknownFields != null) { _unknownFields.WriteTo(output); } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { - if (HasType) { + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) + { + if (HasType) + { output.WriteRawTag(8); - output.WriteEnum((int) Type); + output.WriteEnum((int)Type); } - if (prepareExecute_ != null) { + if (prepareExecute_ != null) + { output.WriteRawTag(18); output.WriteMessage(PrepareExecute); } - if (_unknownFields != null) { + if (_unknownFields != null) + { _unknownFields.WriteTo(ref output); } } - #endif +#endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public int CalculateSize() { + public int CalculateSize() + { int size = 0; - if (HasType) { - size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Type); + if (HasType) + { + size += 1 + pb::CodedOutputStream.ComputeEnumSize((int)Type); } - if (prepareExecute_ != null) { + if (prepareExecute_ != null) + { size += 1 + pb::CodedOutputStream.ComputeMessageSize(PrepareExecute); } - if (_unknownFields != null) { + if (_unknownFields != null) + { size += _unknownFields.CalculateSize(); } return size; @@ -587,15 +668,20 @@ public int CalculateSize() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(OneOfMessage other) { - if (other == null) { + public void MergeFrom(OneOfMessage other) + { + if (other == null) + { return; } - if (other.HasType) { + if (other.HasType) + { Type = other.Type; } - if (other.prepareExecute_ != null) { - if (prepareExecute_ == null) { + if (other.prepareExecute_ != null) + { + if (prepareExecute_ == null) + { PrepareExecute = new global::Mysqlx.Prepare.Execute(); } PrepareExecute.MergeFrom(other.PrepareExecute); @@ -605,10 +691,11 @@ public void MergeFrom(OneOfMessage other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(pb::CodedInputStream input) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void MergeFrom(pb::CodedInputStream input) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE input.ReadRawMessage(this); - #else +#else uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { @@ -628,41 +715,49 @@ public void MergeFrom(pb::CodedInputStream input) { } } } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) + { uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { + while ((tag = input.ReadTag()) != 0) + { + switch (tag) + { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; - case 8: { - Type = (global::Mysqlx.Cursor.Open.Types.OneOfMessage.Types.Type) input.ReadEnum(); - break; - } - case 18: { - if (prepareExecute_ == null) { - PrepareExecute = new global::Mysqlx.Prepare.Execute(); + case 8: + { + Type = (global::Mysqlx.Cursor.Open.Types.OneOfMessage.Types.Type)input.ReadEnum(); + break; + } + case 18: + { + if (prepareExecute_ == null) + { + PrepareExecute = new global::Mysqlx.Prepare.Execute(); + } + input.ReadMessage(PrepareExecute); + break; } - input.ReadMessage(PrepareExecute); - break; - } } } } - #endif +#endif #region Nested types /// Container for nested types declared in the OneOfMessage message type. [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static partial class Types { - public enum Type { + public static partial class Types + { + public enum Type + { [pbr::OriginalName("PREPARE_EXECUTE")] PrepareExecute = 0, } @@ -690,10 +785,11 @@ public enum Type { ///end ///@enduml /// - internal sealed partial class Fetch : pb::IMessage - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] + public sealed partial class Fetch : pb::IMessage +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE , pb::IBufferMessage - #endif +#endif { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Fetch()); private pb::UnknownFieldSet _unknownFields; @@ -704,19 +800,22 @@ internal sealed partial class Fetch : pb::IMessage [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static pbr::MessageDescriptor Descriptor { + public static pbr::MessageDescriptor Descriptor + { get { return global::Mysqlx.Cursor.MysqlxCursorReflection.Descriptor.MessageTypes[1]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - pbr::MessageDescriptor pb::IMessage.Descriptor { + pbr::MessageDescriptor pb::IMessage.Descriptor + { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Fetch() { + public Fetch() + { OnConstruction(); } @@ -724,7 +823,8 @@ public Fetch() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Fetch(Fetch other) : this() { + public Fetch(Fetch other) : this() + { _hasBits0 = other._hasBits0; cursorId_ = other.cursorId_; fetchRows_ = other.fetchRows_; @@ -733,7 +833,8 @@ public Fetch(Fetch other) : this() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Fetch Clone() { + public Fetch Clone() + { return new Fetch(this); } @@ -747,9 +848,11 @@ public Fetch Clone() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public uint CursorId { + public uint CursorId + { get { if ((_hasBits0 & 1) != 0) { return cursorId_; } else { return CursorIdDefaultValue; } } - set { + set + { _hasBits0 |= 1; cursorId_ = value; } @@ -757,13 +860,15 @@ public uint CursorId { /// Gets whether the "cursor_id" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasCursorId { + public bool HasCursorId + { get { return (_hasBits0 & 1) != 0; } } /// Clears the value of the "cursor_id" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearCursorId() { + public void ClearCursorId() + { _hasBits0 &= ~1; } @@ -777,9 +882,11 @@ public void ClearCursorId() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public ulong FetchRows { + public ulong FetchRows + { get { if ((_hasBits0 & 2) != 0) { return fetchRows_; } else { return FetchRowsDefaultValue; } } - set { + set + { _hasBits0 |= 2; fetchRows_ = value; } @@ -787,29 +894,35 @@ public ulong FetchRows { /// Gets whether the "fetch_rows" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasFetchRows { + public bool HasFetchRows + { get { return (_hasBits0 & 2) != 0; } } /// Clears the value of the "fetch_rows" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearFetchRows() { + public void ClearFetchRows() + { _hasBits0 &= ~2; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override bool Equals(object other) { + public override bool Equals(object other) + { return Equals(other as Fetch); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool Equals(Fetch other) { - if (ReferenceEquals(other, null)) { + public bool Equals(Fetch other) + { + if (ReferenceEquals(other, null)) + { return false; } - if (ReferenceEquals(other, this)) { + if (ReferenceEquals(other, this)) + { return true; } if (CursorId != other.CursorId) return false; @@ -819,11 +932,13 @@ public bool Equals(Fetch other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override int GetHashCode() { + public override int GetHashCode() + { int hash = 1; if (HasCursorId) hash ^= CursorId.GetHashCode(); if (HasFetchRows) hash ^= FetchRows.GetHashCode(); - if (_unknownFields != null) { + if (_unknownFields != null) + { hash ^= _unknownFields.GetHashCode(); } return hash; @@ -831,16 +946,18 @@ public override int GetHashCode() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override string ToString() { + public override string ToString() + { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void WriteTo(pb::CodedOutputStream output) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void WriteTo(pb::CodedOutputStream output) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE output.WriteRawMessage(this); - #else +#else if (HasCursorId) { output.WriteRawTag(8); output.WriteUInt32(CursorId); @@ -852,38 +969,46 @@ public void WriteTo(pb::CodedOutputStream output) { if (_unknownFields != null) { _unknownFields.WriteTo(output); } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { - if (HasCursorId) { + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) + { + if (HasCursorId) + { output.WriteRawTag(8); output.WriteUInt32(CursorId); } - if (HasFetchRows) { + if (HasFetchRows) + { output.WriteRawTag(40); output.WriteUInt64(FetchRows); } - if (_unknownFields != null) { + if (_unknownFields != null) + { _unknownFields.WriteTo(ref output); } } - #endif +#endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public int CalculateSize() { + public int CalculateSize() + { int size = 0; - if (HasCursorId) { + if (HasCursorId) + { size += 1 + pb::CodedOutputStream.ComputeUInt32Size(CursorId); } - if (HasFetchRows) { + if (HasFetchRows) + { size += 1 + pb::CodedOutputStream.ComputeUInt64Size(FetchRows); } - if (_unknownFields != null) { + if (_unknownFields != null) + { size += _unknownFields.CalculateSize(); } return size; @@ -891,14 +1016,18 @@ public int CalculateSize() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(Fetch other) { - if (other == null) { + public void MergeFrom(Fetch other) + { + if (other == null) + { return; } - if (other.HasCursorId) { + if (other.HasCursorId) + { CursorId = other.CursorId; } - if (other.HasFetchRows) { + if (other.HasFetchRows) + { FetchRows = other.FetchRows; } _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); @@ -906,10 +1035,11 @@ public void MergeFrom(Fetch other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(pb::CodedInputStream input) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void MergeFrom(pb::CodedInputStream input) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE input.ReadRawMessage(this); - #else +#else uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { @@ -926,31 +1056,36 @@ public void MergeFrom(pb::CodedInputStream input) { } } } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) + { uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { + while ((tag = input.ReadTag()) != 0) + { + switch (tag) + { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; - case 8: { - CursorId = input.ReadUInt32(); - break; - } - case 40: { - FetchRows = input.ReadUInt64(); - break; - } + case 8: + { + CursorId = input.ReadUInt32(); + break; + } + case 40: + { + FetchRows = input.ReadUInt64(); + break; + } } } } - #endif +#endif } @@ -969,10 +1104,11 @@ public void MergeFrom(pb::CodedInputStream input) { /// ///@returns @ref Mysqlx::Ok or @ref Mysqlx::Error /// - internal sealed partial class Close : pb::IMessage - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] + public sealed partial class Close : pb::IMessage +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE , pb::IBufferMessage - #endif +#endif { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Close()); private pb::UnknownFieldSet _unknownFields; @@ -983,19 +1119,22 @@ internal sealed partial class Close : pb::IMessage [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static pbr::MessageDescriptor Descriptor { + public static pbr::MessageDescriptor Descriptor + { get { return global::Mysqlx.Cursor.MysqlxCursorReflection.Descriptor.MessageTypes[2]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - pbr::MessageDescriptor pb::IMessage.Descriptor { + pbr::MessageDescriptor pb::IMessage.Descriptor + { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Close() { + public Close() + { OnConstruction(); } @@ -1003,7 +1142,8 @@ public Close() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Close(Close other) : this() { + public Close(Close other) : this() + { _hasBits0 = other._hasBits0; cursorId_ = other.cursorId_; _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); @@ -1011,7 +1151,8 @@ public Close(Close other) : this() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Close Clone() { + public Close Clone() + { return new Close(this); } @@ -1025,9 +1166,11 @@ public Close Clone() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public uint CursorId { + public uint CursorId + { get { if ((_hasBits0 & 1) != 0) { return cursorId_; } else { return CursorIdDefaultValue; } } - set { + set + { _hasBits0 |= 1; cursorId_ = value; } @@ -1035,29 +1178,35 @@ public uint CursorId { /// Gets whether the "cursor_id" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasCursorId { + public bool HasCursorId + { get { return (_hasBits0 & 1) != 0; } } /// Clears the value of the "cursor_id" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearCursorId() { + public void ClearCursorId() + { _hasBits0 &= ~1; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override bool Equals(object other) { + public override bool Equals(object other) + { return Equals(other as Close); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool Equals(Close other) { - if (ReferenceEquals(other, null)) { + public bool Equals(Close other) + { + if (ReferenceEquals(other, null)) + { return false; } - if (ReferenceEquals(other, this)) { + if (ReferenceEquals(other, this)) + { return true; } if (CursorId != other.CursorId) return false; @@ -1066,10 +1215,12 @@ public bool Equals(Close other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override int GetHashCode() { + public override int GetHashCode() + { int hash = 1; if (HasCursorId) hash ^= CursorId.GetHashCode(); - if (_unknownFields != null) { + if (_unknownFields != null) + { hash ^= _unknownFields.GetHashCode(); } return hash; @@ -1077,16 +1228,18 @@ public override int GetHashCode() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override string ToString() { + public override string ToString() + { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void WriteTo(pb::CodedOutputStream output) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void WriteTo(pb::CodedOutputStream output) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE output.WriteRawMessage(this); - #else +#else if (HasCursorId) { output.WriteRawTag(8); output.WriteUInt32(CursorId); @@ -1094,31 +1247,37 @@ public void WriteTo(pb::CodedOutputStream output) { if (_unknownFields != null) { _unknownFields.WriteTo(output); } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { - if (HasCursorId) { + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) + { + if (HasCursorId) + { output.WriteRawTag(8); output.WriteUInt32(CursorId); } - if (_unknownFields != null) { + if (_unknownFields != null) + { _unknownFields.WriteTo(ref output); } } - #endif +#endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public int CalculateSize() { + public int CalculateSize() + { int size = 0; - if (HasCursorId) { + if (HasCursorId) + { size += 1 + pb::CodedOutputStream.ComputeUInt32Size(CursorId); } - if (_unknownFields != null) { + if (_unknownFields != null) + { size += _unknownFields.CalculateSize(); } return size; @@ -1126,11 +1285,14 @@ public int CalculateSize() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(Close other) { - if (other == null) { + public void MergeFrom(Close other) + { + if (other == null) + { return; } - if (other.HasCursorId) { + if (other.HasCursorId) + { CursorId = other.CursorId; } _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); @@ -1138,10 +1300,11 @@ public void MergeFrom(Close other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(pb::CodedInputStream input) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void MergeFrom(pb::CodedInputStream input) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE input.ReadRawMessage(this); - #else +#else uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { @@ -1154,27 +1317,31 @@ public void MergeFrom(pb::CodedInputStream input) { } } } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) + { uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { + while ((tag = input.ReadTag()) != 0) + { + switch (tag) + { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; - case 8: { - CursorId = input.ReadUInt32(); - break; - } + case 8: + { + CursorId = input.ReadUInt32(); + break; + } } } } - #endif +#endif } diff --git a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxDatatypes.cs b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxDatatypes.cs index 75d44e306..42027d377 100644 --- a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxDatatypes.cs +++ b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxDatatypes.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2022, 2023, Oracle and/or its affiliates. +// Copyright (c) 2023, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as @@ -7,7 +7,7 @@ // This program is also distributed with certain software (including // but not limited to OpenSSL) that is licensed under separate terms, // as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an +// documentation. The authors of MySQL hereby grant you an // additional permission to link the program and your derivative works // with the separately licensed software that they have included with // MySQL. @@ -37,19 +37,23 @@ using pbc = global::Google.Protobuf.Collections; using pbr = global::Google.Protobuf.Reflection; using scg = global::System.Collections.Generic; -namespace Mysqlx.Datatypes { +namespace Mysqlx.Datatypes +{ /// Holder for reflection information generated from mysqlx_datatypes.proto - internal static partial class MysqlxDatatypesReflection { + public static partial class MysqlxDatatypesReflection + { #region Descriptor /// File descriptor for mysqlx_datatypes.proto - internal static pbr::FileDescriptor Descriptor { + public static pbr::FileDescriptor Descriptor + { get { return descriptor; } } private static pbr::FileDescriptor descriptor; - static MysqlxDatatypesReflection() { + static MysqlxDatatypesReflection() + { byte[] descriptorData = global::System.Convert.FromBase64String( string.Concat( "ChZteXNxbHhfZGF0YXR5cGVzLnByb3RvEhBNeXNxbHguRGF0YXR5cGVzIsYD", @@ -90,10 +94,11 @@ static MysqlxDatatypesReflection() { /// /// a scalar /// - internal sealed partial class Scalar : pb::IMessage - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] + public sealed partial class Scalar : pb::IMessage +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE , pb::IBufferMessage - #endif +#endif { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Scalar()); private pb::UnknownFieldSet _unknownFields; @@ -104,19 +109,22 @@ internal sealed partial class Scalar : pb::IMessage [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static pbr::MessageDescriptor Descriptor { + public static pbr::MessageDescriptor Descriptor + { get { return global::Mysqlx.Datatypes.MysqlxDatatypesReflection.Descriptor.MessageTypes[0]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - pbr::MessageDescriptor pb::IMessage.Descriptor { + pbr::MessageDescriptor pb::IMessage.Descriptor + { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Scalar() { + public Scalar() + { OnConstruction(); } @@ -124,7 +132,8 @@ public Scalar() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Scalar(Scalar other) : this() { + public Scalar(Scalar other) : this() + { _hasBits0 = other._hasBits0; type_ = other.type_; vSignedInt_ = other.vSignedInt_; @@ -139,7 +148,8 @@ public Scalar(Scalar other) : this() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Scalar Clone() { + public Scalar Clone() + { return new Scalar(this); } @@ -150,9 +160,11 @@ public Scalar Clone() { private global::Mysqlx.Datatypes.Scalar.Types.Type type_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public global::Mysqlx.Datatypes.Scalar.Types.Type Type { + public global::Mysqlx.Datatypes.Scalar.Types.Type Type + { get { if ((_hasBits0 & 1) != 0) { return type_; } else { return TypeDefaultValue; } } - set { + set + { _hasBits0 |= 1; type_ = value; } @@ -160,13 +172,15 @@ public Scalar Clone() { /// Gets whether the "type" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasType { + public bool HasType + { get { return (_hasBits0 & 1) != 0; } } /// Clears the value of the "type" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearType() { + public void ClearType() + { _hasBits0 &= ~1; } @@ -177,9 +191,11 @@ public void ClearType() { private long vSignedInt_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public long VSignedInt { + public long VSignedInt + { get { if ((_hasBits0 & 2) != 0) { return vSignedInt_; } else { return VSignedIntDefaultValue; } } - set { + set + { _hasBits0 |= 2; vSignedInt_ = value; } @@ -187,13 +203,15 @@ public long VSignedInt { /// Gets whether the "v_signed_int" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasVSignedInt { + public bool HasVSignedInt + { get { return (_hasBits0 & 2) != 0; } } /// Clears the value of the "v_signed_int" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearVSignedInt() { + public void ClearVSignedInt() + { _hasBits0 &= ~2; } @@ -204,9 +222,11 @@ public void ClearVSignedInt() { private ulong vUnsignedInt_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public ulong VUnsignedInt { + public ulong VUnsignedInt + { get { if ((_hasBits0 & 4) != 0) { return vUnsignedInt_; } else { return VUnsignedIntDefaultValue; } } - set { + set + { _hasBits0 |= 4; vUnsignedInt_ = value; } @@ -214,13 +234,15 @@ public ulong VUnsignedInt { /// Gets whether the "v_unsigned_int" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasVUnsignedInt { + public bool HasVUnsignedInt + { get { return (_hasBits0 & 4) != 0; } } /// Clears the value of the "v_unsigned_int" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearVUnsignedInt() { + public void ClearVUnsignedInt() + { _hasBits0 &= ~4; } @@ -232,9 +254,11 @@ public void ClearVUnsignedInt() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public global::Mysqlx.Datatypes.Scalar.Types.Octets VOctets { + public global::Mysqlx.Datatypes.Scalar.Types.Octets VOctets + { get { return vOctets_; } - set { + set + { vOctets_ = value; } } @@ -246,9 +270,11 @@ public void ClearVUnsignedInt() { private double vDouble_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public double VDouble { + public double VDouble + { get { if ((_hasBits0 & 8) != 0) { return vDouble_; } else { return VDoubleDefaultValue; } } - set { + set + { _hasBits0 |= 8; vDouble_ = value; } @@ -256,13 +282,15 @@ public double VDouble { /// Gets whether the "v_double" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasVDouble { + public bool HasVDouble + { get { return (_hasBits0 & 8) != 0; } } /// Clears the value of the "v_double" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearVDouble() { + public void ClearVDouble() + { _hasBits0 &= ~8; } @@ -273,9 +301,11 @@ public void ClearVDouble() { private float vFloat_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public float VFloat { + public float VFloat + { get { if ((_hasBits0 & 16) != 0) { return vFloat_; } else { return VFloatDefaultValue; } } - set { + set + { _hasBits0 |= 16; vFloat_ = value; } @@ -283,13 +313,15 @@ public float VFloat { /// Gets whether the "v_float" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasVFloat { + public bool HasVFloat + { get { return (_hasBits0 & 16) != 0; } } /// Clears the value of the "v_float" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearVFloat() { + public void ClearVFloat() + { _hasBits0 &= ~16; } @@ -300,9 +332,11 @@ public void ClearVFloat() { private bool vBool_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool VBool { + public bool VBool + { get { if ((_hasBits0 & 32) != 0) { return vBool_; } else { return VBoolDefaultValue; } } - set { + set + { _hasBits0 |= 32; vBool_ = value; } @@ -310,13 +344,15 @@ public bool VBool { /// Gets whether the "v_bool" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasVBool { + public bool HasVBool + { get { return (_hasBits0 & 32) != 0; } } /// Clears the value of the "v_bool" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearVBool() { + public void ClearVBool() + { _hasBits0 &= ~32; } @@ -325,26 +361,32 @@ public void ClearVBool() { private global::Mysqlx.Datatypes.Scalar.Types.String vString_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public global::Mysqlx.Datatypes.Scalar.Types.String VString { + public global::Mysqlx.Datatypes.Scalar.Types.String VString + { get { return vString_; } - set { + set + { vString_ = value; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override bool Equals(object other) { + public override bool Equals(object other) + { return Equals(other as Scalar); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool Equals(Scalar other) { - if (ReferenceEquals(other, null)) { + public bool Equals(Scalar other) + { + if (ReferenceEquals(other, null)) + { return false; } - if (ReferenceEquals(other, this)) { + if (ReferenceEquals(other, this)) + { return true; } if (Type != other.Type) return false; @@ -360,7 +402,8 @@ public bool Equals(Scalar other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override int GetHashCode() { + public override int GetHashCode() + { int hash = 1; if (HasType) hash ^= Type.GetHashCode(); if (HasVSignedInt) hash ^= VSignedInt.GetHashCode(); @@ -370,7 +413,8 @@ public override int GetHashCode() { if (HasVFloat) hash ^= pbc::ProtobufEqualityComparers.BitwiseSingleEqualityComparer.GetHashCode(VFloat); if (HasVBool) hash ^= VBool.GetHashCode(); if (vString_ != null) hash ^= VString.GetHashCode(); - if (_unknownFields != null) { + if (_unknownFields != null) + { hash ^= _unknownFields.GetHashCode(); } return hash; @@ -378,16 +422,18 @@ public override int GetHashCode() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override string ToString() { + public override string ToString() + { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void WriteTo(pb::CodedOutputStream output) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void WriteTo(pb::CodedOutputStream output) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE output.WriteRawMessage(this); - #else +#else if (HasType) { output.WriteRawTag(8); output.WriteEnum((int) Type); @@ -423,80 +469,100 @@ public void WriteTo(pb::CodedOutputStream output) { if (_unknownFields != null) { _unknownFields.WriteTo(output); } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { - if (HasType) { + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) + { + if (HasType) + { output.WriteRawTag(8); - output.WriteEnum((int) Type); + output.WriteEnum((int)Type); } - if (HasVSignedInt) { + if (HasVSignedInt) + { output.WriteRawTag(16); output.WriteSInt64(VSignedInt); } - if (HasVUnsignedInt) { + if (HasVUnsignedInt) + { output.WriteRawTag(24); output.WriteUInt64(VUnsignedInt); } - if (vOctets_ != null) { + if (vOctets_ != null) + { output.WriteRawTag(42); output.WriteMessage(VOctets); } - if (HasVDouble) { + if (HasVDouble) + { output.WriteRawTag(49); output.WriteDouble(VDouble); } - if (HasVFloat) { + if (HasVFloat) + { output.WriteRawTag(61); output.WriteFloat(VFloat); } - if (HasVBool) { + if (HasVBool) + { output.WriteRawTag(64); output.WriteBool(VBool); } - if (vString_ != null) { + if (vString_ != null) + { output.WriteRawTag(74); output.WriteMessage(VString); } - if (_unknownFields != null) { + if (_unknownFields != null) + { _unknownFields.WriteTo(ref output); } } - #endif +#endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public int CalculateSize() { + public int CalculateSize() + { int size = 0; - if (HasType) { - size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Type); + if (HasType) + { + size += 1 + pb::CodedOutputStream.ComputeEnumSize((int)Type); } - if (HasVSignedInt) { + if (HasVSignedInt) + { size += 1 + pb::CodedOutputStream.ComputeSInt64Size(VSignedInt); } - if (HasVUnsignedInt) { + if (HasVUnsignedInt) + { size += 1 + pb::CodedOutputStream.ComputeUInt64Size(VUnsignedInt); } - if (vOctets_ != null) { + if (vOctets_ != null) + { size += 1 + pb::CodedOutputStream.ComputeMessageSize(VOctets); } - if (HasVDouble) { + if (HasVDouble) + { size += 1 + 8; } - if (HasVFloat) { + if (HasVFloat) + { size += 1 + 4; } - if (HasVBool) { + if (HasVBool) + { size += 1 + 1; } - if (vString_ != null) { + if (vString_ != null) + { size += 1 + pb::CodedOutputStream.ComputeMessageSize(VString); } - if (_unknownFields != null) { + if (_unknownFields != null) + { size += _unknownFields.CalculateSize(); } return size; @@ -504,36 +570,48 @@ public int CalculateSize() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(Scalar other) { - if (other == null) { + public void MergeFrom(Scalar other) + { + if (other == null) + { return; } - if (other.HasType) { + if (other.HasType) + { Type = other.Type; } - if (other.HasVSignedInt) { + if (other.HasVSignedInt) + { VSignedInt = other.VSignedInt; } - if (other.HasVUnsignedInt) { + if (other.HasVUnsignedInt) + { VUnsignedInt = other.VUnsignedInt; } - if (other.vOctets_ != null) { - if (vOctets_ == null) { + if (other.vOctets_ != null) + { + if (vOctets_ == null) + { VOctets = new global::Mysqlx.Datatypes.Scalar.Types.Octets(); } VOctets.MergeFrom(other.VOctets); } - if (other.HasVDouble) { + if (other.HasVDouble) + { VDouble = other.VDouble; } - if (other.HasVFloat) { + if (other.HasVFloat) + { VFloat = other.VFloat; } - if (other.HasVBool) { + if (other.HasVBool) + { VBool = other.VBool; } - if (other.vString_ != null) { - if (vString_ == null) { + if (other.vString_ != null) + { + if (vString_ == null) + { VString = new global::Mysqlx.Datatypes.Scalar.Types.String(); } VString.MergeFrom(other.VString); @@ -543,10 +621,11 @@ public void MergeFrom(Scalar other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(pb::CodedInputStream input) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void MergeFrom(pb::CodedInputStream input) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE input.ReadRawMessage(this); - #else +#else uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { @@ -593,68 +672,83 @@ public void MergeFrom(pb::CodedInputStream input) { } } } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) + { uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { + while ((tag = input.ReadTag()) != 0) + { + switch (tag) + { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; - case 8: { - Type = (global::Mysqlx.Datatypes.Scalar.Types.Type) input.ReadEnum(); - break; - } - case 16: { - VSignedInt = input.ReadSInt64(); - break; - } - case 24: { - VUnsignedInt = input.ReadUInt64(); - break; - } - case 42: { - if (vOctets_ == null) { - VOctets = new global::Mysqlx.Datatypes.Scalar.Types.Octets(); + case 8: + { + Type = (global::Mysqlx.Datatypes.Scalar.Types.Type)input.ReadEnum(); + break; } - input.ReadMessage(VOctets); - break; - } - case 49: { - VDouble = input.ReadDouble(); - break; - } - case 61: { - VFloat = input.ReadFloat(); - break; - } - case 64: { - VBool = input.ReadBool(); - break; - } - case 74: { - if (vString_ == null) { - VString = new global::Mysqlx.Datatypes.Scalar.Types.String(); + case 16: + { + VSignedInt = input.ReadSInt64(); + break; + } + case 24: + { + VUnsignedInt = input.ReadUInt64(); + break; + } + case 42: + { + if (vOctets_ == null) + { + VOctets = new global::Mysqlx.Datatypes.Scalar.Types.Octets(); + } + input.ReadMessage(VOctets); + break; + } + case 49: + { + VDouble = input.ReadDouble(); + break; + } + case 61: + { + VFloat = input.ReadFloat(); + break; + } + case 64: + { + VBool = input.ReadBool(); + break; + } + case 74: + { + if (vString_ == null) + { + VString = new global::Mysqlx.Datatypes.Scalar.Types.String(); + } + input.ReadMessage(VString); + break; } - input.ReadMessage(VString); - break; - } } } } - #endif +#endif #region Nested types /// Container for nested types declared in the Scalar message type. [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static partial class Types { - public enum Type { + public static partial class Types + { + public enum Type + { [pbr::OriginalName("V_SINT")] VSint = 1, [pbr::OriginalName("V_UINT")] VUint = 2, [pbr::OriginalName("V_NULL")] VNull = 3, @@ -668,10 +762,11 @@ public enum Type { /// ///* a string with a charset/collation /// + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] public sealed partial class String : pb::IMessage - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE , pb::IBufferMessage - #endif +#endif { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new String()); private pb::UnknownFieldSet _unknownFields; @@ -682,19 +777,22 @@ public sealed partial class String : pb::IMessage [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static pbr::MessageDescriptor Descriptor { + public static pbr::MessageDescriptor Descriptor + { get { return global::Mysqlx.Datatypes.Scalar.Descriptor.NestedTypes[0]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - pbr::MessageDescriptor pb::IMessage.Descriptor { + pbr::MessageDescriptor pb::IMessage.Descriptor + { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public String() { + public String() + { OnConstruction(); } @@ -702,7 +800,8 @@ public String() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public String(String other) : this() { + public String(String other) : this() + { _hasBits0 = other._hasBits0; value_ = other.value_; collation_ = other.collation_; @@ -711,7 +810,8 @@ public String(String other) : this() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public String Clone() { + public String Clone() + { return new String(this); } @@ -722,22 +822,26 @@ public String Clone() { private pb::ByteString value_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public pb::ByteString Value { + public pb::ByteString Value + { get { return value_ ?? ValueDefaultValue; } - set { + set + { value_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } /// Gets whether the "value" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasValue { + public bool HasValue + { get { return value_ != null; } } /// Clears the value of the "value" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearValue() { + public void ClearValue() + { value_ = null; } @@ -748,9 +852,11 @@ public void ClearValue() { private ulong collation_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public ulong Collation { + public ulong Collation + { get { if ((_hasBits0 & 1) != 0) { return collation_; } else { return CollationDefaultValue; } } - set { + set + { _hasBits0 |= 1; collation_ = value; } @@ -758,29 +864,35 @@ public ulong Collation { /// Gets whether the "collation" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasCollation { + public bool HasCollation + { get { return (_hasBits0 & 1) != 0; } } /// Clears the value of the "collation" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearCollation() { + public void ClearCollation() + { _hasBits0 &= ~1; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override bool Equals(object other) { + public override bool Equals(object other) + { return Equals(other as String); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool Equals(String other) { - if (ReferenceEquals(other, null)) { + public bool Equals(String other) + { + if (ReferenceEquals(other, null)) + { return false; } - if (ReferenceEquals(other, this)) { + if (ReferenceEquals(other, this)) + { return true; } if (Value != other.Value) return false; @@ -790,11 +902,13 @@ public bool Equals(String other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override int GetHashCode() { + public override int GetHashCode() + { int hash = 1; if (HasValue) hash ^= Value.GetHashCode(); if (HasCollation) hash ^= Collation.GetHashCode(); - if (_unknownFields != null) { + if (_unknownFields != null) + { hash ^= _unknownFields.GetHashCode(); } return hash; @@ -802,16 +916,18 @@ public override int GetHashCode() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override string ToString() { + public override string ToString() + { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void WriteTo(pb::CodedOutputStream output) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void WriteTo(pb::CodedOutputStream output) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE output.WriteRawMessage(this); - #else +#else if (HasValue) { output.WriteRawTag(10); output.WriteBytes(Value); @@ -823,38 +939,46 @@ public void WriteTo(pb::CodedOutputStream output) { if (_unknownFields != null) { _unknownFields.WriteTo(output); } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { - if (HasValue) { + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) + { + if (HasValue) + { output.WriteRawTag(10); output.WriteBytes(Value); } - if (HasCollation) { + if (HasCollation) + { output.WriteRawTag(16); output.WriteUInt64(Collation); } - if (_unknownFields != null) { + if (_unknownFields != null) + { _unknownFields.WriteTo(ref output); } } - #endif +#endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public int CalculateSize() { + public int CalculateSize() + { int size = 0; - if (HasValue) { + if (HasValue) + { size += 1 + pb::CodedOutputStream.ComputeBytesSize(Value); } - if (HasCollation) { + if (HasCollation) + { size += 1 + pb::CodedOutputStream.ComputeUInt64Size(Collation); } - if (_unknownFields != null) { + if (_unknownFields != null) + { size += _unknownFields.CalculateSize(); } return size; @@ -862,14 +986,18 @@ public int CalculateSize() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(String other) { - if (other == null) { + public void MergeFrom(String other) + { + if (other == null) + { return; } - if (other.HasValue) { + if (other.HasValue) + { Value = other.Value; } - if (other.HasCollation) { + if (other.HasCollation) + { Collation = other.Collation; } _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); @@ -877,10 +1005,11 @@ public void MergeFrom(String other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(pb::CodedInputStream input) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void MergeFrom(pb::CodedInputStream input) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE input.ReadRawMessage(this); - #else +#else uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { @@ -897,31 +1026,36 @@ public void MergeFrom(pb::CodedInputStream input) { } } } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) + { uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { + while ((tag = input.ReadTag()) != 0) + { + switch (tag) + { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; - case 10: { - Value = input.ReadBytes(); - break; - } - case 16: { - Collation = input.ReadUInt64(); - break; - } + case 10: + { + Value = input.ReadBytes(); + break; + } + case 16: + { + Collation = input.ReadUInt64(); + break; + } } } } - #endif +#endif } @@ -929,10 +1063,11 @@ public void MergeFrom(pb::CodedInputStream input) { ///* an opaque octet sequence, with an optional content_type ///See @ref Mysqlx::Resultset::ContentType_BYTES for list of known values. /// + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] public sealed partial class Octets : pb::IMessage - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE , pb::IBufferMessage - #endif +#endif { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Octets()); private pb::UnknownFieldSet _unknownFields; @@ -943,19 +1078,22 @@ public sealed partial class Octets : pb::IMessage [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static pbr::MessageDescriptor Descriptor { + public static pbr::MessageDescriptor Descriptor + { get { return global::Mysqlx.Datatypes.Scalar.Descriptor.NestedTypes[1]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - pbr::MessageDescriptor pb::IMessage.Descriptor { + pbr::MessageDescriptor pb::IMessage.Descriptor + { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Octets() { + public Octets() + { OnConstruction(); } @@ -963,7 +1101,8 @@ public Octets() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Octets(Octets other) : this() { + public Octets(Octets other) : this() + { _hasBits0 = other._hasBits0; value_ = other.value_; contentType_ = other.contentType_; @@ -972,7 +1111,8 @@ public Octets(Octets other) : this() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Octets Clone() { + public Octets Clone() + { return new Octets(this); } @@ -983,22 +1123,26 @@ public Octets Clone() { private pb::ByteString value_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public pb::ByteString Value { + public pb::ByteString Value + { get { return value_ ?? ValueDefaultValue; } - set { + set + { value_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } /// Gets whether the "value" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasValue { + public bool HasValue + { get { return value_ != null; } } /// Clears the value of the "value" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearValue() { + public void ClearValue() + { value_ = null; } @@ -1009,9 +1153,11 @@ public void ClearValue() { private uint contentType_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public uint ContentType { + public uint ContentType + { get { if ((_hasBits0 & 1) != 0) { return contentType_; } else { return ContentTypeDefaultValue; } } - set { + set + { _hasBits0 |= 1; contentType_ = value; } @@ -1019,29 +1165,35 @@ public uint ContentType { /// Gets whether the "content_type" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasContentType { + public bool HasContentType + { get { return (_hasBits0 & 1) != 0; } } /// Clears the value of the "content_type" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearContentType() { + public void ClearContentType() + { _hasBits0 &= ~1; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override bool Equals(object other) { + public override bool Equals(object other) + { return Equals(other as Octets); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool Equals(Octets other) { - if (ReferenceEquals(other, null)) { + public bool Equals(Octets other) + { + if (ReferenceEquals(other, null)) + { return false; } - if (ReferenceEquals(other, this)) { + if (ReferenceEquals(other, this)) + { return true; } if (Value != other.Value) return false; @@ -1051,11 +1203,13 @@ public bool Equals(Octets other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override int GetHashCode() { + public override int GetHashCode() + { int hash = 1; if (HasValue) hash ^= Value.GetHashCode(); if (HasContentType) hash ^= ContentType.GetHashCode(); - if (_unknownFields != null) { + if (_unknownFields != null) + { hash ^= _unknownFields.GetHashCode(); } return hash; @@ -1063,16 +1217,18 @@ public override int GetHashCode() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override string ToString() { + public override string ToString() + { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void WriteTo(pb::CodedOutputStream output) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void WriteTo(pb::CodedOutputStream output) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE output.WriteRawMessage(this); - #else +#else if (HasValue) { output.WriteRawTag(10); output.WriteBytes(Value); @@ -1084,38 +1240,46 @@ public void WriteTo(pb::CodedOutputStream output) { if (_unknownFields != null) { _unknownFields.WriteTo(output); } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { - if (HasValue) { + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) + { + if (HasValue) + { output.WriteRawTag(10); output.WriteBytes(Value); } - if (HasContentType) { + if (HasContentType) + { output.WriteRawTag(16); output.WriteUInt32(ContentType); } - if (_unknownFields != null) { + if (_unknownFields != null) + { _unknownFields.WriteTo(ref output); } } - #endif +#endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public int CalculateSize() { + public int CalculateSize() + { int size = 0; - if (HasValue) { + if (HasValue) + { size += 1 + pb::CodedOutputStream.ComputeBytesSize(Value); } - if (HasContentType) { + if (HasContentType) + { size += 1 + pb::CodedOutputStream.ComputeUInt32Size(ContentType); } - if (_unknownFields != null) { + if (_unknownFields != null) + { size += _unknownFields.CalculateSize(); } return size; @@ -1123,14 +1287,18 @@ public int CalculateSize() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(Octets other) { - if (other == null) { + public void MergeFrom(Octets other) + { + if (other == null) + { return; } - if (other.HasValue) { + if (other.HasValue) + { Value = other.Value; } - if (other.HasContentType) { + if (other.HasContentType) + { ContentType = other.ContentType; } _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); @@ -1138,10 +1306,11 @@ public void MergeFrom(Octets other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(pb::CodedInputStream input) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void MergeFrom(pb::CodedInputStream input) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE input.ReadRawMessage(this); - #else +#else uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { @@ -1158,31 +1327,36 @@ public void MergeFrom(pb::CodedInputStream input) { } } } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) + { uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { + while ((tag = input.ReadTag()) != 0) + { + switch (tag) + { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; - case 10: { - Value = input.ReadBytes(); - break; - } - case 16: { - ContentType = input.ReadUInt32(); - break; - } + case 10: + { + Value = input.ReadBytes(); + break; + } + case 16: + { + ContentType = input.ReadUInt32(); + break; + } } } } - #endif +#endif } @@ -1195,10 +1369,11 @@ public void MergeFrom(pb::CodedInputStream input) { ///* ///An object /// - internal sealed partial class Object : pb::IMessage - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] + public sealed partial class Object : pb::IMessage +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE , pb::IBufferMessage - #endif +#endif { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Object()); private pb::UnknownFieldSet _unknownFields; @@ -1208,19 +1383,22 @@ internal sealed partial class Object : pb::IMessage [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static pbr::MessageDescriptor Descriptor { + public static pbr::MessageDescriptor Descriptor + { get { return global::Mysqlx.Datatypes.MysqlxDatatypesReflection.Descriptor.MessageTypes[1]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - pbr::MessageDescriptor pb::IMessage.Descriptor { + pbr::MessageDescriptor pb::IMessage.Descriptor + { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Object() { + public Object() + { OnConstruction(); } @@ -1228,14 +1406,16 @@ public Object() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Object(Object other) : this() { + public Object(Object other) : this() + { fld_ = other.fld_.Clone(); _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Object Clone() { + public Object Clone() + { return new Object(this); } @@ -1246,35 +1426,42 @@ public Object Clone() { private readonly pbc::RepeatedField fld_ = new pbc::RepeatedField(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public pbc::RepeatedField Fld { + public pbc::RepeatedField Fld + { get { return fld_; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override bool Equals(object other) { + public override bool Equals(object other) + { return Equals(other as Object); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool Equals(Object other) { - if (ReferenceEquals(other, null)) { + public bool Equals(Object other) + { + if (ReferenceEquals(other, null)) + { return false; } - if (ReferenceEquals(other, this)) { + if (ReferenceEquals(other, this)) + { return true; } - if(!fld_.Equals(other.fld_)) return false; + if (!fld_.Equals(other.fld_)) return false; return Equals(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override int GetHashCode() { + public override int GetHashCode() + { int hash = 1; hash ^= fld_.GetHashCode(); - if (_unknownFields != null) { + if (_unknownFields != null) + { hash ^= _unknownFields.GetHashCode(); } return hash; @@ -1282,40 +1469,46 @@ public override int GetHashCode() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override string ToString() { + public override string ToString() + { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void WriteTo(pb::CodedOutputStream output) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void WriteTo(pb::CodedOutputStream output) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE output.WriteRawMessage(this); - #else +#else fld_.WriteTo(output, _repeated_fld_codec); if (_unknownFields != null) { _unknownFields.WriteTo(output); } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) + { fld_.WriteTo(ref output, _repeated_fld_codec); - if (_unknownFields != null) { + if (_unknownFields != null) + { _unknownFields.WriteTo(ref output); } } - #endif +#endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public int CalculateSize() { + public int CalculateSize() + { int size = 0; size += fld_.CalculateSize(_repeated_fld_codec); - if (_unknownFields != null) { + if (_unknownFields != null) + { size += _unknownFields.CalculateSize(); } return size; @@ -1323,8 +1516,10 @@ public int CalculateSize() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(Object other) { - if (other == null) { + public void MergeFrom(Object other) + { + if (other == null) + { return; } fld_.Add(other.fld_); @@ -1333,10 +1528,11 @@ public void MergeFrom(Object other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(pb::CodedInputStream input) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void MergeFrom(pb::CodedInputStream input) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE input.ReadRawMessage(this); - #else +#else uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { @@ -1349,37 +1545,43 @@ public void MergeFrom(pb::CodedInputStream input) { } } } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) + { uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { + while ((tag = input.ReadTag()) != 0) + { + switch (tag) + { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; - case 10: { - fld_.AddEntriesFrom(ref input, _repeated_fld_codec); - break; - } + case 10: + { + fld_.AddEntriesFrom(ref input, _repeated_fld_codec); + break; + } } } } - #endif +#endif #region Nested types /// Container for nested types declared in the Object message type. [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static partial class Types { + public static partial class Types + { + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] public sealed partial class ObjectField : pb::IMessage - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE , pb::IBufferMessage - #endif +#endif { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ObjectField()); private pb::UnknownFieldSet _unknownFields; @@ -1389,19 +1591,22 @@ public sealed partial class ObjectField : pb::IMessage [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static pbr::MessageDescriptor Descriptor { + public static pbr::MessageDescriptor Descriptor + { get { return global::Mysqlx.Datatypes.Object.Descriptor.NestedTypes[0]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - pbr::MessageDescriptor pb::IMessage.Descriptor { + pbr::MessageDescriptor pb::IMessage.Descriptor + { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public ObjectField() { + public ObjectField() + { OnConstruction(); } @@ -1409,7 +1614,8 @@ public ObjectField() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public ObjectField(ObjectField other) : this() { + public ObjectField(ObjectField other) : this() + { key_ = other.key_; value_ = other.value_ != null ? other.value_.Clone() : null; _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); @@ -1417,7 +1623,8 @@ public ObjectField(ObjectField other) : this() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public ObjectField Clone() { + public ObjectField Clone() + { return new ObjectField(this); } @@ -1428,22 +1635,26 @@ public ObjectField Clone() { private string key_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public string Key { + public string Key + { get { return key_ ?? KeyDefaultValue; } - set { + set + { key_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } /// Gets whether the "key" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasKey { + public bool HasKey + { get { return key_ != null; } } /// Clears the value of the "key" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearKey() { + public void ClearKey() + { key_ = null; } @@ -1452,26 +1663,32 @@ public void ClearKey() { private global::Mysqlx.Datatypes.Any value_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public global::Mysqlx.Datatypes.Any Value { + public global::Mysqlx.Datatypes.Any Value + { get { return value_; } - set { + set + { value_ = value; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override bool Equals(object other) { + public override bool Equals(object other) + { return Equals(other as ObjectField); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool Equals(ObjectField other) { - if (ReferenceEquals(other, null)) { + public bool Equals(ObjectField other) + { + if (ReferenceEquals(other, null)) + { return false; } - if (ReferenceEquals(other, this)) { + if (ReferenceEquals(other, this)) + { return true; } if (Key != other.Key) return false; @@ -1481,11 +1698,13 @@ public bool Equals(ObjectField other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override int GetHashCode() { + public override int GetHashCode() + { int hash = 1; if (HasKey) hash ^= Key.GetHashCode(); if (value_ != null) hash ^= Value.GetHashCode(); - if (_unknownFields != null) { + if (_unknownFields != null) + { hash ^= _unknownFields.GetHashCode(); } return hash; @@ -1493,16 +1712,18 @@ public override int GetHashCode() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override string ToString() { + public override string ToString() + { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void WriteTo(pb::CodedOutputStream output) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void WriteTo(pb::CodedOutputStream output) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE output.WriteRawMessage(this); - #else +#else if (HasKey) { output.WriteRawTag(10); output.WriteString(Key); @@ -1514,38 +1735,46 @@ public void WriteTo(pb::CodedOutputStream output) { if (_unknownFields != null) { _unknownFields.WriteTo(output); } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { - if (HasKey) { + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) + { + if (HasKey) + { output.WriteRawTag(10); output.WriteString(Key); } - if (value_ != null) { + if (value_ != null) + { output.WriteRawTag(18); output.WriteMessage(Value); } - if (_unknownFields != null) { + if (_unknownFields != null) + { _unknownFields.WriteTo(ref output); } } - #endif +#endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public int CalculateSize() { + public int CalculateSize() + { int size = 0; - if (HasKey) { + if (HasKey) + { size += 1 + pb::CodedOutputStream.ComputeStringSize(Key); } - if (value_ != null) { + if (value_ != null) + { size += 1 + pb::CodedOutputStream.ComputeMessageSize(Value); } - if (_unknownFields != null) { + if (_unknownFields != null) + { size += _unknownFields.CalculateSize(); } return size; @@ -1553,15 +1782,20 @@ public int CalculateSize() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(ObjectField other) { - if (other == null) { + public void MergeFrom(ObjectField other) + { + if (other == null) + { return; } - if (other.HasKey) { + if (other.HasKey) + { Key = other.Key; } - if (other.value_ != null) { - if (value_ == null) { + if (other.value_ != null) + { + if (value_ == null) + { Value = new global::Mysqlx.Datatypes.Any(); } Value.MergeFrom(other.Value); @@ -1571,10 +1805,11 @@ public void MergeFrom(ObjectField other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(pb::CodedInputStream input) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void MergeFrom(pb::CodedInputStream input) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE input.ReadRawMessage(this); - #else +#else uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { @@ -1594,34 +1829,40 @@ public void MergeFrom(pb::CodedInputStream input) { } } } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) + { uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { + while ((tag = input.ReadTag()) != 0) + { + switch (tag) + { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; - case 10: { - Key = input.ReadString(); - break; - } - case 18: { - if (value_ == null) { - Value = new global::Mysqlx.Datatypes.Any(); + case 10: + { + Key = input.ReadString(); + break; + } + case 18: + { + if (value_ == null) + { + Value = new global::Mysqlx.Datatypes.Any(); + } + input.ReadMessage(Value); + break; } - input.ReadMessage(Value); - break; - } } } } - #endif +#endif } @@ -1634,10 +1875,11 @@ public void MergeFrom(pb::CodedInputStream input) { ///* ///An Array /// - internal sealed partial class Array : pb::IMessage - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] + public sealed partial class Array : pb::IMessage +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE , pb::IBufferMessage - #endif +#endif { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Array()); private pb::UnknownFieldSet _unknownFields; @@ -1647,19 +1889,22 @@ internal sealed partial class Array : pb::IMessage [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static pbr::MessageDescriptor Descriptor { + public static pbr::MessageDescriptor Descriptor + { get { return global::Mysqlx.Datatypes.MysqlxDatatypesReflection.Descriptor.MessageTypes[2]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - pbr::MessageDescriptor pb::IMessage.Descriptor { + pbr::MessageDescriptor pb::IMessage.Descriptor + { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Array() { + public Array() + { OnConstruction(); } @@ -1667,14 +1912,16 @@ public Array() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Array(Array other) : this() { + public Array(Array other) : this() + { value_ = other.value_.Clone(); _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Array Clone() { + public Array Clone() + { return new Array(this); } @@ -1685,35 +1932,42 @@ public Array Clone() { private readonly pbc::RepeatedField value_ = new pbc::RepeatedField(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public pbc::RepeatedField Value { + public pbc::RepeatedField Value + { get { return value_; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override bool Equals(object other) { + public override bool Equals(object other) + { return Equals(other as Array); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool Equals(Array other) { - if (ReferenceEquals(other, null)) { + public bool Equals(Array other) + { + if (ReferenceEquals(other, null)) + { return false; } - if (ReferenceEquals(other, this)) { + if (ReferenceEquals(other, this)) + { return true; } - if(!value_.Equals(other.value_)) return false; + if (!value_.Equals(other.value_)) return false; return Equals(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override int GetHashCode() { + public override int GetHashCode() + { int hash = 1; hash ^= value_.GetHashCode(); - if (_unknownFields != null) { + if (_unknownFields != null) + { hash ^= _unknownFields.GetHashCode(); } return hash; @@ -1721,40 +1975,46 @@ public override int GetHashCode() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override string ToString() { + public override string ToString() + { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void WriteTo(pb::CodedOutputStream output) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void WriteTo(pb::CodedOutputStream output) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE output.WriteRawMessage(this); - #else +#else value_.WriteTo(output, _repeated_value_codec); if (_unknownFields != null) { _unknownFields.WriteTo(output); } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) + { value_.WriteTo(ref output, _repeated_value_codec); - if (_unknownFields != null) { + if (_unknownFields != null) + { _unknownFields.WriteTo(ref output); } } - #endif +#endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public int CalculateSize() { + public int CalculateSize() + { int size = 0; size += value_.CalculateSize(_repeated_value_codec); - if (_unknownFields != null) { + if (_unknownFields != null) + { size += _unknownFields.CalculateSize(); } return size; @@ -1762,8 +2022,10 @@ public int CalculateSize() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(Array other) { - if (other == null) { + public void MergeFrom(Array other) + { + if (other == null) + { return; } value_.Add(other.value_); @@ -1772,10 +2034,11 @@ public void MergeFrom(Array other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(pb::CodedInputStream input) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void MergeFrom(pb::CodedInputStream input) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE input.ReadRawMessage(this); - #else +#else uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { @@ -1788,27 +2051,31 @@ public void MergeFrom(pb::CodedInputStream input) { } } } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) + { uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { + while ((tag = input.ReadTag()) != 0) + { + switch (tag) + { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; - case 10: { - value_.AddEntriesFrom(ref input, _repeated_value_codec); - break; - } + case 10: + { + value_.AddEntriesFrom(ref input, _repeated_value_codec); + break; + } } } } - #endif +#endif } @@ -1816,10 +2083,11 @@ public void MergeFrom(pb::CodedInputStream input) { ///* ///A helper to allow all field types /// - internal sealed partial class Any : pb::IMessage - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] + public sealed partial class Any : pb::IMessage +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE , pb::IBufferMessage - #endif +#endif { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Any()); private pb::UnknownFieldSet _unknownFields; @@ -1830,19 +2098,22 @@ internal sealed partial class Any : pb::IMessage [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static pbr::MessageDescriptor Descriptor { + public static pbr::MessageDescriptor Descriptor + { get { return global::Mysqlx.Datatypes.MysqlxDatatypesReflection.Descriptor.MessageTypes[3]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - pbr::MessageDescriptor pb::IMessage.Descriptor { + pbr::MessageDescriptor pb::IMessage.Descriptor + { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Any() { + public Any() + { OnConstruction(); } @@ -1850,7 +2121,8 @@ public Any() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Any(Any other) : this() { + public Any(Any other) : this() + { _hasBits0 = other._hasBits0; type_ = other.type_; scalar_ = other.scalar_ != null ? other.scalar_.Clone() : null; @@ -1861,7 +2133,8 @@ public Any(Any other) : this() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Any Clone() { + public Any Clone() + { return new Any(this); } @@ -1872,9 +2145,11 @@ public Any Clone() { private global::Mysqlx.Datatypes.Any.Types.Type type_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public global::Mysqlx.Datatypes.Any.Types.Type Type { + public global::Mysqlx.Datatypes.Any.Types.Type Type + { get { if ((_hasBits0 & 1) != 0) { return type_; } else { return TypeDefaultValue; } } - set { + set + { _hasBits0 |= 1; type_ = value; } @@ -1882,13 +2157,15 @@ public Any Clone() { /// Gets whether the "type" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasType { + public bool HasType + { get { return (_hasBits0 & 1) != 0; } } /// Clears the value of the "type" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearType() { + public void ClearType() + { _hasBits0 &= ~1; } @@ -1897,9 +2174,11 @@ public void ClearType() { private global::Mysqlx.Datatypes.Scalar scalar_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public global::Mysqlx.Datatypes.Scalar Scalar { + public global::Mysqlx.Datatypes.Scalar Scalar + { get { return scalar_; } - set { + set + { scalar_ = value; } } @@ -1909,9 +2188,11 @@ public void ClearType() { private global::Mysqlx.Datatypes.Object obj_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public global::Mysqlx.Datatypes.Object Obj { + public global::Mysqlx.Datatypes.Object Obj + { get { return obj_; } - set { + set + { obj_ = value; } } @@ -1921,26 +2202,32 @@ public void ClearType() { private global::Mysqlx.Datatypes.Array array_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public global::Mysqlx.Datatypes.Array Array { + public global::Mysqlx.Datatypes.Array Array + { get { return array_; } - set { + set + { array_ = value; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override bool Equals(object other) { + public override bool Equals(object other) + { return Equals(other as Any); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool Equals(Any other) { - if (ReferenceEquals(other, null)) { + public bool Equals(Any other) + { + if (ReferenceEquals(other, null)) + { return false; } - if (ReferenceEquals(other, this)) { + if (ReferenceEquals(other, this)) + { return true; } if (Type != other.Type) return false; @@ -1952,13 +2239,15 @@ public bool Equals(Any other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override int GetHashCode() { + public override int GetHashCode() + { int hash = 1; if (HasType) hash ^= Type.GetHashCode(); if (scalar_ != null) hash ^= Scalar.GetHashCode(); if (obj_ != null) hash ^= Obj.GetHashCode(); if (array_ != null) hash ^= Array.GetHashCode(); - if (_unknownFields != null) { + if (_unknownFields != null) + { hash ^= _unknownFields.GetHashCode(); } return hash; @@ -1966,16 +2255,18 @@ public override int GetHashCode() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override string ToString() { + public override string ToString() + { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void WriteTo(pb::CodedOutputStream output) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void WriteTo(pb::CodedOutputStream output) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE output.WriteRawMessage(this); - #else +#else if (HasType) { output.WriteRawTag(8); output.WriteEnum((int) Type); @@ -1995,52 +2286,64 @@ public void WriteTo(pb::CodedOutputStream output) { if (_unknownFields != null) { _unknownFields.WriteTo(output); } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { - if (HasType) { + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) + { + if (HasType) + { output.WriteRawTag(8); - output.WriteEnum((int) Type); + output.WriteEnum((int)Type); } - if (scalar_ != null) { + if (scalar_ != null) + { output.WriteRawTag(18); output.WriteMessage(Scalar); } - if (obj_ != null) { + if (obj_ != null) + { output.WriteRawTag(26); output.WriteMessage(Obj); } - if (array_ != null) { + if (array_ != null) + { output.WriteRawTag(34); output.WriteMessage(Array); } - if (_unknownFields != null) { + if (_unknownFields != null) + { _unknownFields.WriteTo(ref output); } } - #endif +#endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public int CalculateSize() { + public int CalculateSize() + { int size = 0; - if (HasType) { - size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Type); + if (HasType) + { + size += 1 + pb::CodedOutputStream.ComputeEnumSize((int)Type); } - if (scalar_ != null) { + if (scalar_ != null) + { size += 1 + pb::CodedOutputStream.ComputeMessageSize(Scalar); } - if (obj_ != null) { + if (obj_ != null) + { size += 1 + pb::CodedOutputStream.ComputeMessageSize(Obj); } - if (array_ != null) { + if (array_ != null) + { size += 1 + pb::CodedOutputStream.ComputeMessageSize(Array); } - if (_unknownFields != null) { + if (_unknownFields != null) + { size += _unknownFields.CalculateSize(); } return size; @@ -2048,27 +2351,36 @@ public int CalculateSize() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(Any other) { - if (other == null) { + public void MergeFrom(Any other) + { + if (other == null) + { return; } - if (other.HasType) { + if (other.HasType) + { Type = other.Type; } - if (other.scalar_ != null) { - if (scalar_ == null) { + if (other.scalar_ != null) + { + if (scalar_ == null) + { Scalar = new global::Mysqlx.Datatypes.Scalar(); } Scalar.MergeFrom(other.Scalar); } - if (other.obj_ != null) { - if (obj_ == null) { + if (other.obj_ != null) + { + if (obj_ == null) + { Obj = new global::Mysqlx.Datatypes.Object(); } Obj.MergeFrom(other.Obj); } - if (other.array_ != null) { - if (array_ == null) { + if (other.array_ != null) + { + if (array_ == null) + { Array = new global::Mysqlx.Datatypes.Array(); } Array.MergeFrom(other.Array); @@ -2078,10 +2390,11 @@ public void MergeFrom(Any other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(pb::CodedInputStream input) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void MergeFrom(pb::CodedInputStream input) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE input.ReadRawMessage(this); - #else +#else uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { @@ -2115,55 +2428,67 @@ public void MergeFrom(pb::CodedInputStream input) { } } } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) + { uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { + while ((tag = input.ReadTag()) != 0) + { + switch (tag) + { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; - case 8: { - Type = (global::Mysqlx.Datatypes.Any.Types.Type) input.ReadEnum(); - break; - } - case 18: { - if (scalar_ == null) { - Scalar = new global::Mysqlx.Datatypes.Scalar(); + case 8: + { + Type = (global::Mysqlx.Datatypes.Any.Types.Type)input.ReadEnum(); + break; } - input.ReadMessage(Scalar); - break; - } - case 26: { - if (obj_ == null) { - Obj = new global::Mysqlx.Datatypes.Object(); + case 18: + { + if (scalar_ == null) + { + Scalar = new global::Mysqlx.Datatypes.Scalar(); + } + input.ReadMessage(Scalar); + break; } - input.ReadMessage(Obj); - break; - } - case 34: { - if (array_ == null) { - Array = new global::Mysqlx.Datatypes.Array(); + case 26: + { + if (obj_ == null) + { + Obj = new global::Mysqlx.Datatypes.Object(); + } + input.ReadMessage(Obj); + break; + } + case 34: + { + if (array_ == null) + { + Array = new global::Mysqlx.Datatypes.Array(); + } + input.ReadMessage(Array); + break; } - input.ReadMessage(Array); - break; - } } } } - #endif +#endif #region Nested types /// Container for nested types declared in the Any message type. [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static partial class Types { - public enum Type { + public static partial class Types + { + public enum Type + { [pbr::OriginalName("SCALAR")] Scalar = 1, [pbr::OriginalName("OBJECT")] Object = 2, [pbr::OriginalName("ARRAY")] Array = 3, diff --git a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxExpect.cs b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxExpect.cs index 4e994c039..f5278dbe2 100644 --- a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxExpect.cs +++ b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxExpect.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2022, 2023, Oracle and/or its affiliates. +// Copyright (c) 2023, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as @@ -7,7 +7,7 @@ // This program is also distributed with certain software (including // but not limited to OpenSSL) that is licensed under separate terms, // as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an +// documentation. The authors of MySQL hereby grant you an // additional permission to link the program and your derivative works // with the separately licensed software that they have included with // MySQL. @@ -37,19 +37,23 @@ using pbc = global::Google.Protobuf.Collections; using pbr = global::Google.Protobuf.Reflection; using scg = global::System.Collections.Generic; -namespace Mysqlx.Expect { +namespace Mysqlx.Expect +{ /// Holder for reflection information generated from mysqlx_expect.proto - internal static partial class MysqlxExpectReflection { + public static partial class MysqlxExpectReflection + { #region Descriptor /// File descriptor for mysqlx_expect.proto - internal static pbr::FileDescriptor Descriptor { + public static pbr::FileDescriptor Descriptor + { get { return descriptor; } } private static pbr::FileDescriptor descriptor; - static MysqlxExpectReflection() { + static MysqlxExpectReflection() + { byte[] descriptorData = global::System.Convert.FromBase64String( string.Concat( "ChNteXNxbHhfZXhwZWN0LnByb3RvEg1NeXNxbHguRXhwZWN0GgxteXNxbHgu", @@ -86,10 +90,11 @@ static MysqlxExpectReflection() { /// ///@returns @ref Mysqlx::Ok on success, @ref Mysqlx::Error on error /// - internal sealed partial class Open : pb::IMessage - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] + public sealed partial class Open : pb::IMessage +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE , pb::IBufferMessage - #endif +#endif { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Open()); private pb::UnknownFieldSet _unknownFields; @@ -100,19 +105,22 @@ internal sealed partial class Open : pb::IMessage [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static pbr::MessageDescriptor Descriptor { + public static pbr::MessageDescriptor Descriptor + { get { return global::Mysqlx.Expect.MysqlxExpectReflection.Descriptor.MessageTypes[0]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - pbr::MessageDescriptor pb::IMessage.Descriptor { + pbr::MessageDescriptor pb::IMessage.Descriptor + { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Open() { + public Open() + { OnConstruction(); } @@ -120,7 +128,8 @@ public Open() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Open(Open other) : this() { + public Open(Open other) : this() + { _hasBits0 = other._hasBits0; op_ = other.op_; cond_ = other.cond_.Clone(); @@ -129,7 +138,8 @@ public Open(Open other) : this() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Open Clone() { + public Open Clone() + { return new Open(this); } @@ -140,9 +150,11 @@ public Open Clone() { private global::Mysqlx.Expect.Open.Types.CtxOperation op_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public global::Mysqlx.Expect.Open.Types.CtxOperation Op { + public global::Mysqlx.Expect.Open.Types.CtxOperation Op + { get { if ((_hasBits0 & 1) != 0) { return op_; } else { return OpDefaultValue; } } - set { + set + { _hasBits0 |= 1; op_ = value; } @@ -150,13 +162,15 @@ public Open Clone() { /// Gets whether the "op" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasOp { + public bool HasOp + { get { return (_hasBits0 & 1) != 0; } } /// Clears the value of the "op" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearOp() { + public void ClearOp() + { _hasBits0 &= ~1; } @@ -167,37 +181,44 @@ public void ClearOp() { private readonly pbc::RepeatedField cond_ = new pbc::RepeatedField(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public pbc::RepeatedField Cond { + public pbc::RepeatedField Cond + { get { return cond_; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override bool Equals(object other) { + public override bool Equals(object other) + { return Equals(other as Open); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool Equals(Open other) { - if (ReferenceEquals(other, null)) { + public bool Equals(Open other) + { + if (ReferenceEquals(other, null)) + { return false; } - if (ReferenceEquals(other, this)) { + if (ReferenceEquals(other, this)) + { return true; } if (Op != other.Op) return false; - if(!cond_.Equals(other.cond_)) return false; + if (!cond_.Equals(other.cond_)) return false; return Equals(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override int GetHashCode() { + public override int GetHashCode() + { int hash = 1; if (HasOp) hash ^= Op.GetHashCode(); hash ^= cond_.GetHashCode(); - if (_unknownFields != null) { + if (_unknownFields != null) + { hash ^= _unknownFields.GetHashCode(); } return hash; @@ -205,16 +226,18 @@ public override int GetHashCode() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override string ToString() { + public override string ToString() + { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void WriteTo(pb::CodedOutputStream output) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void WriteTo(pb::CodedOutputStream output) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE output.WriteRawMessage(this); - #else +#else if (HasOp) { output.WriteRawTag(8); output.WriteEnum((int) Op); @@ -223,33 +246,39 @@ public void WriteTo(pb::CodedOutputStream output) { if (_unknownFields != null) { _unknownFields.WriteTo(output); } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { - if (HasOp) { + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) + { + if (HasOp) + { output.WriteRawTag(8); - output.WriteEnum((int) Op); + output.WriteEnum((int)Op); } cond_.WriteTo(ref output, _repeated_cond_codec); - if (_unknownFields != null) { + if (_unknownFields != null) + { _unknownFields.WriteTo(ref output); } } - #endif +#endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public int CalculateSize() { + public int CalculateSize() + { int size = 0; - if (HasOp) { - size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Op); + if (HasOp) + { + size += 1 + pb::CodedOutputStream.ComputeEnumSize((int)Op); } size += cond_.CalculateSize(_repeated_cond_codec); - if (_unknownFields != null) { + if (_unknownFields != null) + { size += _unknownFields.CalculateSize(); } return size; @@ -257,11 +286,14 @@ public int CalculateSize() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(Open other) { - if (other == null) { + public void MergeFrom(Open other) + { + if (other == null) + { return; } - if (other.HasOp) { + if (other.HasOp) + { Op = other.Op; } cond_.Add(other.cond_); @@ -270,10 +302,11 @@ public void MergeFrom(Open other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(pb::CodedInputStream input) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void MergeFrom(pb::CodedInputStream input) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE input.ReadRawMessage(this); - #else +#else uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { @@ -290,38 +323,45 @@ public void MergeFrom(pb::CodedInputStream input) { } } } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) + { uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { + while ((tag = input.ReadTag()) != 0) + { + switch (tag) + { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; - case 8: { - Op = (global::Mysqlx.Expect.Open.Types.CtxOperation) input.ReadEnum(); - break; - } - case 18: { - cond_.AddEntriesFrom(ref input, _repeated_cond_codec); - break; - } + case 8: + { + Op = (global::Mysqlx.Expect.Open.Types.CtxOperation)input.ReadEnum(); + break; + } + case 18: + { + cond_.AddEntriesFrom(ref input, _repeated_cond_codec); + break; + } } } } - #endif +#endif #region Nested types /// Container for nested types declared in the Open message type. [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static partial class Types { - public enum CtxOperation { + public static partial class Types + { + public enum CtxOperation + { /// ///* copy the operations from the parent Expect-block /// @@ -332,10 +372,11 @@ public enum CtxOperation { [pbr::OriginalName("EXPECT_CTX_EMPTY")] ExpectCtxEmpty = 1, } + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] public sealed partial class Condition : pb::IMessage - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE , pb::IBufferMessage - #endif +#endif { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Condition()); private pb::UnknownFieldSet _unknownFields; @@ -346,19 +387,22 @@ public sealed partial class Condition : pb::IMessage [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static pbr::MessageDescriptor Descriptor { + public static pbr::MessageDescriptor Descriptor + { get { return global::Mysqlx.Expect.Open.Descriptor.NestedTypes[0]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - pbr::MessageDescriptor pb::IMessage.Descriptor { + pbr::MessageDescriptor pb::IMessage.Descriptor + { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Condition() { + public Condition() + { OnConstruction(); } @@ -366,7 +410,8 @@ public Condition() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Condition(Condition other) : this() { + public Condition(Condition other) : this() + { _hasBits0 = other._hasBits0; conditionKey_ = other.conditionKey_; conditionValue_ = other.conditionValue_; @@ -376,7 +421,8 @@ public Condition(Condition other) : this() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Condition Clone() { + public Condition Clone() + { return new Condition(this); } @@ -387,9 +433,11 @@ public Condition Clone() { private uint conditionKey_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public uint ConditionKey { + public uint ConditionKey + { get { if ((_hasBits0 & 1) != 0) { return conditionKey_; } else { return ConditionKeyDefaultValue; } } - set { + set + { _hasBits0 |= 1; conditionKey_ = value; } @@ -397,13 +445,15 @@ public uint ConditionKey { /// Gets whether the "condition_key" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasConditionKey { + public bool HasConditionKey + { get { return (_hasBits0 & 1) != 0; } } /// Clears the value of the "condition_key" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearConditionKey() { + public void ClearConditionKey() + { _hasBits0 &= ~1; } @@ -414,22 +464,26 @@ public void ClearConditionKey() { private pb::ByteString conditionValue_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public pb::ByteString ConditionValue { + public pb::ByteString ConditionValue + { get { return conditionValue_ ?? ConditionValueDefaultValue; } - set { + set + { conditionValue_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } /// Gets whether the "condition_value" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasConditionValue { + public bool HasConditionValue + { get { return conditionValue_ != null; } } /// Clears the value of the "condition_value" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearConditionValue() { + public void ClearConditionValue() + { conditionValue_ = null; } @@ -440,9 +494,11 @@ public void ClearConditionValue() { private global::Mysqlx.Expect.Open.Types.Condition.Types.ConditionOperation op_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public global::Mysqlx.Expect.Open.Types.Condition.Types.ConditionOperation Op { + public global::Mysqlx.Expect.Open.Types.Condition.Types.ConditionOperation Op + { get { if ((_hasBits0 & 2) != 0) { return op_; } else { return OpDefaultValue; } } - set { + set + { _hasBits0 |= 2; op_ = value; } @@ -450,29 +506,35 @@ public void ClearConditionValue() { /// Gets whether the "op" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasOp { + public bool HasOp + { get { return (_hasBits0 & 2) != 0; } } /// Clears the value of the "op" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearOp() { + public void ClearOp() + { _hasBits0 &= ~2; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override bool Equals(object other) { + public override bool Equals(object other) + { return Equals(other as Condition); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool Equals(Condition other) { - if (ReferenceEquals(other, null)) { + public bool Equals(Condition other) + { + if (ReferenceEquals(other, null)) + { return false; } - if (ReferenceEquals(other, this)) { + if (ReferenceEquals(other, this)) + { return true; } if (ConditionKey != other.ConditionKey) return false; @@ -483,12 +545,14 @@ public bool Equals(Condition other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override int GetHashCode() { + public override int GetHashCode() + { int hash = 1; if (HasConditionKey) hash ^= ConditionKey.GetHashCode(); if (HasConditionValue) hash ^= ConditionValue.GetHashCode(); if (HasOp) hash ^= Op.GetHashCode(); - if (_unknownFields != null) { + if (_unknownFields != null) + { hash ^= _unknownFields.GetHashCode(); } return hash; @@ -496,16 +560,18 @@ public override int GetHashCode() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override string ToString() { + public override string ToString() + { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void WriteTo(pb::CodedOutputStream output) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void WriteTo(pb::CodedOutputStream output) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE output.WriteRawMessage(this); - #else +#else if (HasConditionKey) { output.WriteRawTag(8); output.WriteUInt32(ConditionKey); @@ -521,45 +587,55 @@ public void WriteTo(pb::CodedOutputStream output) { if (_unknownFields != null) { _unknownFields.WriteTo(output); } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { - if (HasConditionKey) { + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) + { + if (HasConditionKey) + { output.WriteRawTag(8); output.WriteUInt32(ConditionKey); } - if (HasConditionValue) { + if (HasConditionValue) + { output.WriteRawTag(18); output.WriteBytes(ConditionValue); } - if (HasOp) { + if (HasOp) + { output.WriteRawTag(24); - output.WriteEnum((int) Op); + output.WriteEnum((int)Op); } - if (_unknownFields != null) { + if (_unknownFields != null) + { _unknownFields.WriteTo(ref output); } } - #endif +#endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public int CalculateSize() { + public int CalculateSize() + { int size = 0; - if (HasConditionKey) { + if (HasConditionKey) + { size += 1 + pb::CodedOutputStream.ComputeUInt32Size(ConditionKey); } - if (HasConditionValue) { + if (HasConditionValue) + { size += 1 + pb::CodedOutputStream.ComputeBytesSize(ConditionValue); } - if (HasOp) { - size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Op); + if (HasOp) + { + size += 1 + pb::CodedOutputStream.ComputeEnumSize((int)Op); } - if (_unknownFields != null) { + if (_unknownFields != null) + { size += _unknownFields.CalculateSize(); } return size; @@ -567,17 +643,22 @@ public int CalculateSize() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(Condition other) { - if (other == null) { + public void MergeFrom(Condition other) + { + if (other == null) + { return; } - if (other.HasConditionKey) { + if (other.HasConditionKey) + { ConditionKey = other.ConditionKey; } - if (other.HasConditionValue) { + if (other.HasConditionValue) + { ConditionValue = other.ConditionValue; } - if (other.HasOp) { + if (other.HasOp) + { Op = other.Op; } _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); @@ -585,10 +666,11 @@ public void MergeFrom(Condition other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(pb::CodedInputStream input) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void MergeFrom(pb::CodedInputStream input) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE input.ReadRawMessage(this); - #else +#else uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { @@ -609,42 +691,50 @@ public void MergeFrom(pb::CodedInputStream input) { } } } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) + { uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { + while ((tag = input.ReadTag()) != 0) + { + switch (tag) + { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; - case 8: { - ConditionKey = input.ReadUInt32(); - break; - } - case 18: { - ConditionValue = input.ReadBytes(); - break; - } - case 24: { - Op = (global::Mysqlx.Expect.Open.Types.Condition.Types.ConditionOperation) input.ReadEnum(); - break; - } + case 8: + { + ConditionKey = input.ReadUInt32(); + break; + } + case 18: + { + ConditionValue = input.ReadBytes(); + break; + } + case 24: + { + Op = (global::Mysqlx.Expect.Open.Types.Condition.Types.ConditionOperation)input.ReadEnum(); + break; + } } } } - #endif +#endif #region Nested types /// Container for nested types declared in the Condition message type. [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static partial class Types { - public enum Key { + public static partial class Types + { + public enum Key + { /// ///* Change error propagation behaviour /// @@ -659,7 +749,8 @@ public enum Key { [pbr::OriginalName("EXPECT_DOCID_GENERATED")] ExpectDocidGenerated = 3, } - public enum ConditionOperation { + public enum ConditionOperation + { /// ///* set the condition; set, if not set; overwrite, if set /// @@ -689,10 +780,11 @@ public enum ConditionOperation { /// ///@returns @ref Mysqlx::Ok on success, @ref Mysqlx::Error on error /// - internal sealed partial class Close : pb::IMessage - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] + public sealed partial class Close : pb::IMessage +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE , pb::IBufferMessage - #endif +#endif { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Close()); private pb::UnknownFieldSet _unknownFields; @@ -702,19 +794,22 @@ internal sealed partial class Close : pb::IMessage [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static pbr::MessageDescriptor Descriptor { + public static pbr::MessageDescriptor Descriptor + { get { return global::Mysqlx.Expect.MysqlxExpectReflection.Descriptor.MessageTypes[1]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - pbr::MessageDescriptor pb::IMessage.Descriptor { + pbr::MessageDescriptor pb::IMessage.Descriptor + { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Close() { + public Close() + { OnConstruction(); } @@ -722,29 +817,35 @@ public Close() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Close(Close other) : this() { + public Close(Close other) : this() + { _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Close Clone() { + public Close Clone() + { return new Close(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override bool Equals(object other) { + public override bool Equals(object other) + { return Equals(other as Close); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool Equals(Close other) { - if (ReferenceEquals(other, null)) { + public bool Equals(Close other) + { + if (ReferenceEquals(other, null)) + { return false; } - if (ReferenceEquals(other, this)) { + if (ReferenceEquals(other, this)) + { return true; } return Equals(_unknownFields, other._unknownFields); @@ -752,9 +853,11 @@ public bool Equals(Close other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override int GetHashCode() { + public override int GetHashCode() + { int hash = 1; - if (_unknownFields != null) { + if (_unknownFields != null) + { hash ^= _unknownFields.GetHashCode(); } return hash; @@ -762,37 +865,43 @@ public override int GetHashCode() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override string ToString() { + public override string ToString() + { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void WriteTo(pb::CodedOutputStream output) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void WriteTo(pb::CodedOutputStream output) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE output.WriteRawMessage(this); - #else +#else if (_unknownFields != null) { _unknownFields.WriteTo(output); } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { - if (_unknownFields != null) { + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) + { + if (_unknownFields != null) + { _unknownFields.WriteTo(ref output); } } - #endif +#endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public int CalculateSize() { + public int CalculateSize() + { int size = 0; - if (_unknownFields != null) { + if (_unknownFields != null) + { size += _unknownFields.CalculateSize(); } return size; @@ -800,8 +909,10 @@ public int CalculateSize() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(Close other) { - if (other == null) { + public void MergeFrom(Close other) + { + if (other == null) + { return; } _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); @@ -809,10 +920,11 @@ public void MergeFrom(Close other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(pb::CodedInputStream input) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void MergeFrom(pb::CodedInputStream input) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE input.ReadRawMessage(this); - #else +#else uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { @@ -821,23 +933,26 @@ public void MergeFrom(pb::CodedInputStream input) { break; } } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) + { uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { + while ((tag = input.ReadTag()) != 0) + { + switch (tag) + { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; } } } - #endif +#endif } diff --git a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxExpr.cs b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxExpr.cs index 3714a77d2..56f669b41 100644 --- a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxExpr.cs +++ b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxExpr.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2022, 2023, Oracle and/or its affiliates. +// Copyright (c) 2023, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as @@ -7,7 +7,7 @@ // This program is also distributed with certain software (including // but not limited to OpenSSL) that is licensed under separate terms, // as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an +// documentation. The authors of MySQL hereby grant you an // additional permission to link the program and your derivative works // with the separately licensed software that they have included with // MySQL. @@ -37,19 +37,23 @@ using pbc = global::Google.Protobuf.Collections; using pbr = global::Google.Protobuf.Reflection; using scg = global::System.Collections.Generic; -namespace Mysqlx.Expr { +namespace Mysqlx.Expr +{ /// Holder for reflection information generated from mysqlx_expr.proto - internal static partial class MysqlxExprReflection { + public static partial class MysqlxExprReflection + { #region Descriptor /// File descriptor for mysqlx_expr.proto - internal static pbr::FileDescriptor Descriptor { + public static pbr::FileDescriptor Descriptor + { get { return descriptor; } } private static pbr::FileDescriptor descriptor; - static MysqlxExprReflection() { + static MysqlxExprReflection() + { byte[] descriptorData = global::System.Convert.FromBase64String( string.Concat( "ChFteXNxbHhfZXhwci5wcm90bxILTXlzcWx4LkV4cHIaFm15c3FseF9kYXRh", @@ -119,10 +123,11 @@ static MysqlxExprReflection() { ///: placeholder ///@endcode /// - internal sealed partial class Expr : pb::IMessage - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] + public sealed partial class Expr : pb::IMessage +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE , pb::IBufferMessage - #endif +#endif { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Expr()); private pb::UnknownFieldSet _unknownFields; @@ -133,19 +138,22 @@ internal sealed partial class Expr : pb::IMessage [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static pbr::MessageDescriptor Descriptor { + public static pbr::MessageDescriptor Descriptor + { get { return global::Mysqlx.Expr.MysqlxExprReflection.Descriptor.MessageTypes[0]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - pbr::MessageDescriptor pb::IMessage.Descriptor { + pbr::MessageDescriptor pb::IMessage.Descriptor + { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Expr() { + public Expr() + { OnConstruction(); } @@ -153,7 +161,8 @@ public Expr() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Expr(Expr other) : this() { + public Expr(Expr other) : this() + { _hasBits0 = other._hasBits0; type_ = other.type_; identifier_ = other.identifier_ != null ? other.identifier_.Clone() : null; @@ -169,7 +178,8 @@ public Expr(Expr other) : this() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Expr Clone() { + public Expr Clone() + { return new Expr(this); } @@ -180,9 +190,11 @@ public Expr Clone() { private global::Mysqlx.Expr.Expr.Types.Type type_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public global::Mysqlx.Expr.Expr.Types.Type Type { + public global::Mysqlx.Expr.Expr.Types.Type Type + { get { if ((_hasBits0 & 1) != 0) { return type_; } else { return TypeDefaultValue; } } - set { + set + { _hasBits0 |= 1; type_ = value; } @@ -190,13 +202,15 @@ public Expr Clone() { /// Gets whether the "type" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasType { + public bool HasType + { get { return (_hasBits0 & 1) != 0; } } /// Clears the value of the "type" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearType() { + public void ClearType() + { _hasBits0 &= ~1; } @@ -205,9 +219,11 @@ public void ClearType() { private global::Mysqlx.Expr.ColumnIdentifier identifier_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public global::Mysqlx.Expr.ColumnIdentifier Identifier { + public global::Mysqlx.Expr.ColumnIdentifier Identifier + { get { return identifier_; } - set { + set + { identifier_ = value; } } @@ -219,22 +235,26 @@ public void ClearType() { private string variable_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public string Variable { + public string Variable + { get { return variable_ ?? VariableDefaultValue; } - set { + set + { variable_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } /// Gets whether the "variable" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasVariable { + public bool HasVariable + { get { return variable_ != null; } } /// Clears the value of the "variable" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearVariable() { + public void ClearVariable() + { variable_ = null; } @@ -243,9 +263,11 @@ public void ClearVariable() { private global::Mysqlx.Datatypes.Scalar literal_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public global::Mysqlx.Datatypes.Scalar Literal { + public global::Mysqlx.Datatypes.Scalar Literal + { get { return literal_; } - set { + set + { literal_ = value; } } @@ -255,9 +277,11 @@ public void ClearVariable() { private global::Mysqlx.Expr.FunctionCall functionCall_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public global::Mysqlx.Expr.FunctionCall FunctionCall { + public global::Mysqlx.Expr.FunctionCall FunctionCall + { get { return functionCall_; } - set { + set + { functionCall_ = value; } } @@ -267,9 +291,11 @@ public void ClearVariable() { private global::Mysqlx.Expr.Operator operator_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public global::Mysqlx.Expr.Operator Operator { + public global::Mysqlx.Expr.Operator Operator + { get { return operator_; } - set { + set + { operator_ = value; } } @@ -281,9 +307,11 @@ public void ClearVariable() { private uint position_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public uint Position { + public uint Position + { get { if ((_hasBits0 & 2) != 0) { return position_; } else { return PositionDefaultValue; } } - set { + set + { _hasBits0 |= 2; position_ = value; } @@ -291,13 +319,15 @@ public uint Position { /// Gets whether the "position" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasPosition { + public bool HasPosition + { get { return (_hasBits0 & 2) != 0; } } /// Clears the value of the "position" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearPosition() { + public void ClearPosition() + { _hasBits0 &= ~2; } @@ -306,9 +336,11 @@ public void ClearPosition() { private global::Mysqlx.Expr.Object object_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public global::Mysqlx.Expr.Object Object { + public global::Mysqlx.Expr.Object Object + { get { return object_; } - set { + set + { object_ = value; } } @@ -318,26 +350,32 @@ public void ClearPosition() { private global::Mysqlx.Expr.Array array_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public global::Mysqlx.Expr.Array Array { + public global::Mysqlx.Expr.Array Array + { get { return array_; } - set { + set + { array_ = value; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override bool Equals(object other) { + public override bool Equals(object other) + { return Equals(other as Expr); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool Equals(Expr other) { - if (ReferenceEquals(other, null)) { + public bool Equals(Expr other) + { + if (ReferenceEquals(other, null)) + { return false; } - if (ReferenceEquals(other, this)) { + if (ReferenceEquals(other, this)) + { return true; } if (Type != other.Type) return false; @@ -354,7 +392,8 @@ public bool Equals(Expr other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override int GetHashCode() { + public override int GetHashCode() + { int hash = 1; if (HasType) hash ^= Type.GetHashCode(); if (identifier_ != null) hash ^= Identifier.GetHashCode(); @@ -365,7 +404,8 @@ public override int GetHashCode() { if (HasPosition) hash ^= Position.GetHashCode(); if (object_ != null) hash ^= Object.GetHashCode(); if (array_ != null) hash ^= Array.GetHashCode(); - if (_unknownFields != null) { + if (_unknownFields != null) + { hash ^= _unknownFields.GetHashCode(); } return hash; @@ -373,16 +413,18 @@ public override int GetHashCode() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override string ToString() { + public override string ToString() + { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void WriteTo(pb::CodedOutputStream output) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void WriteTo(pb::CodedOutputStream output) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE output.WriteRawMessage(this); - #else +#else if (HasType) { output.WriteRawTag(8); output.WriteEnum((int) Type); @@ -422,87 +464,109 @@ public void WriteTo(pb::CodedOutputStream output) { if (_unknownFields != null) { _unknownFields.WriteTo(output); } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { - if (HasType) { + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) + { + if (HasType) + { output.WriteRawTag(8); - output.WriteEnum((int) Type); + output.WriteEnum((int)Type); } - if (identifier_ != null) { + if (identifier_ != null) + { output.WriteRawTag(18); output.WriteMessage(Identifier); } - if (HasVariable) { + if (HasVariable) + { output.WriteRawTag(26); output.WriteString(Variable); } - if (literal_ != null) { + if (literal_ != null) + { output.WriteRawTag(34); output.WriteMessage(Literal); } - if (functionCall_ != null) { + if (functionCall_ != null) + { output.WriteRawTag(42); output.WriteMessage(FunctionCall); } - if (operator_ != null) { + if (operator_ != null) + { output.WriteRawTag(50); output.WriteMessage(Operator); } - if (HasPosition) { + if (HasPosition) + { output.WriteRawTag(56); output.WriteUInt32(Position); } - if (object_ != null) { + if (object_ != null) + { output.WriteRawTag(66); output.WriteMessage(Object); } - if (array_ != null) { + if (array_ != null) + { output.WriteRawTag(74); output.WriteMessage(Array); } - if (_unknownFields != null) { + if (_unknownFields != null) + { _unknownFields.WriteTo(ref output); } } - #endif +#endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public int CalculateSize() { + public int CalculateSize() + { int size = 0; - if (HasType) { - size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Type); + if (HasType) + { + size += 1 + pb::CodedOutputStream.ComputeEnumSize((int)Type); } - if (identifier_ != null) { + if (identifier_ != null) + { size += 1 + pb::CodedOutputStream.ComputeMessageSize(Identifier); } - if (HasVariable) { + if (HasVariable) + { size += 1 + pb::CodedOutputStream.ComputeStringSize(Variable); } - if (literal_ != null) { + if (literal_ != null) + { size += 1 + pb::CodedOutputStream.ComputeMessageSize(Literal); } - if (functionCall_ != null) { + if (functionCall_ != null) + { size += 1 + pb::CodedOutputStream.ComputeMessageSize(FunctionCall); } - if (operator_ != null) { + if (operator_ != null) + { size += 1 + pb::CodedOutputStream.ComputeMessageSize(Operator); } - if (HasPosition) { + if (HasPosition) + { size += 1 + pb::CodedOutputStream.ComputeUInt32Size(Position); } - if (object_ != null) { + if (object_ != null) + { size += 1 + pb::CodedOutputStream.ComputeMessageSize(Object); } - if (array_ != null) { + if (array_ != null) + { size += 1 + pb::CodedOutputStream.ComputeMessageSize(Array); } - if (_unknownFields != null) { + if (_unknownFields != null) + { size += _unknownFields.CalculateSize(); } return size; @@ -510,51 +574,68 @@ public int CalculateSize() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(Expr other) { - if (other == null) { + public void MergeFrom(Expr other) + { + if (other == null) + { return; } - if (other.HasType) { + if (other.HasType) + { Type = other.Type; } - if (other.identifier_ != null) { - if (identifier_ == null) { + if (other.identifier_ != null) + { + if (identifier_ == null) + { Identifier = new global::Mysqlx.Expr.ColumnIdentifier(); } Identifier.MergeFrom(other.Identifier); } - if (other.HasVariable) { + if (other.HasVariable) + { Variable = other.Variable; } - if (other.literal_ != null) { - if (literal_ == null) { + if (other.literal_ != null) + { + if (literal_ == null) + { Literal = new global::Mysqlx.Datatypes.Scalar(); } Literal.MergeFrom(other.Literal); } - if (other.functionCall_ != null) { - if (functionCall_ == null) { + if (other.functionCall_ != null) + { + if (functionCall_ == null) + { FunctionCall = new global::Mysqlx.Expr.FunctionCall(); } FunctionCall.MergeFrom(other.FunctionCall); } - if (other.operator_ != null) { - if (operator_ == null) { + if (other.operator_ != null) + { + if (operator_ == null) + { Operator = new global::Mysqlx.Expr.Operator(); } Operator.MergeFrom(other.Operator); } - if (other.HasPosition) { + if (other.HasPosition) + { Position = other.Position; } - if (other.object_ != null) { - if (object_ == null) { + if (other.object_ != null) + { + if (object_ == null) + { Object = new global::Mysqlx.Expr.Object(); } Object.MergeFrom(other.Object); } - if (other.array_ != null) { - if (array_ == null) { + if (other.array_ != null) + { + if (array_ == null) + { Array = new global::Mysqlx.Expr.Array(); } Array.MergeFrom(other.Array); @@ -564,10 +645,11 @@ public void MergeFrom(Expr other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(pb::CodedInputStream input) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void MergeFrom(pb::CodedInputStream input) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE input.ReadRawMessage(this); - #else +#else uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { @@ -630,84 +712,104 @@ public void MergeFrom(pb::CodedInputStream input) { } } } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) + { uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { + while ((tag = input.ReadTag()) != 0) + { + switch (tag) + { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; - case 8: { - Type = (global::Mysqlx.Expr.Expr.Types.Type) input.ReadEnum(); - break; - } - case 18: { - if (identifier_ == null) { - Identifier = new global::Mysqlx.Expr.ColumnIdentifier(); + case 8: + { + Type = (global::Mysqlx.Expr.Expr.Types.Type)input.ReadEnum(); + break; } - input.ReadMessage(Identifier); - break; - } - case 26: { - Variable = input.ReadString(); - break; - } - case 34: { - if (literal_ == null) { - Literal = new global::Mysqlx.Datatypes.Scalar(); + case 18: + { + if (identifier_ == null) + { + Identifier = new global::Mysqlx.Expr.ColumnIdentifier(); + } + input.ReadMessage(Identifier); + break; } - input.ReadMessage(Literal); - break; - } - case 42: { - if (functionCall_ == null) { - FunctionCall = new global::Mysqlx.Expr.FunctionCall(); + case 26: + { + Variable = input.ReadString(); + break; } - input.ReadMessage(FunctionCall); - break; - } - case 50: { - if (operator_ == null) { - Operator = new global::Mysqlx.Expr.Operator(); + case 34: + { + if (literal_ == null) + { + Literal = new global::Mysqlx.Datatypes.Scalar(); + } + input.ReadMessage(Literal); + break; } - input.ReadMessage(Operator); - break; - } - case 56: { - Position = input.ReadUInt32(); - break; - } - case 66: { - if (object_ == null) { - Object = new global::Mysqlx.Expr.Object(); + case 42: + { + if (functionCall_ == null) + { + FunctionCall = new global::Mysqlx.Expr.FunctionCall(); + } + input.ReadMessage(FunctionCall); + break; } - input.ReadMessage(Object); - break; - } - case 74: { - if (array_ == null) { - Array = new global::Mysqlx.Expr.Array(); + case 50: + { + if (operator_ == null) + { + Operator = new global::Mysqlx.Expr.Operator(); + } + input.ReadMessage(Operator); + break; + } + case 56: + { + Position = input.ReadUInt32(); + break; + } + case 66: + { + if (object_ == null) + { + Object = new global::Mysqlx.Expr.Object(); + } + input.ReadMessage(Object); + break; + } + case 74: + { + if (array_ == null) + { + Array = new global::Mysqlx.Expr.Array(); + } + input.ReadMessage(Array); + break; } - input.ReadMessage(Array); - break; - } } } } - #endif +#endif #region Nested types /// Container for nested types declared in the Expr message type. [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static partial class Types { - public enum Type { + public static partial class Types + { + public enum Type + { [pbr::OriginalName("IDENT")] Ident = 1, [pbr::OriginalName("LITERAL")] Literal = 2, [pbr::OriginalName("VARIABLE")] Variable = 3, @@ -733,10 +835,11 @@ public enum Type { ///: string ///@endcode /// - internal sealed partial class Identifier : pb::IMessage - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] + public sealed partial class Identifier : pb::IMessage +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE , pb::IBufferMessage - #endif +#endif { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Identifier()); private pb::UnknownFieldSet _unknownFields; @@ -746,19 +849,22 @@ internal sealed partial class Identifier : pb::IMessage [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static pbr::MessageDescriptor Descriptor { + public static pbr::MessageDescriptor Descriptor + { get { return global::Mysqlx.Expr.MysqlxExprReflection.Descriptor.MessageTypes[1]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - pbr::MessageDescriptor pb::IMessage.Descriptor { + pbr::MessageDescriptor pb::IMessage.Descriptor + { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Identifier() { + public Identifier() + { OnConstruction(); } @@ -766,7 +872,8 @@ public Identifier() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Identifier(Identifier other) : this() { + public Identifier(Identifier other) : this() + { name_ = other.name_; schemaName_ = other.schemaName_; _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); @@ -774,7 +881,8 @@ public Identifier(Identifier other) : this() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Identifier Clone() { + public Identifier Clone() + { return new Identifier(this); } @@ -785,22 +893,26 @@ public Identifier Clone() { private string name_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public string Name { + public string Name + { get { return name_ ?? NameDefaultValue; } - set { + set + { name_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } /// Gets whether the "name" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasName { + public bool HasName + { get { return name_ != null; } } /// Clears the value of the "name" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearName() { + public void ClearName() + { name_ = null; } @@ -811,38 +923,46 @@ public void ClearName() { private string schemaName_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public string SchemaName { + public string SchemaName + { get { return schemaName_ ?? SchemaNameDefaultValue; } - set { + set + { schemaName_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } /// Gets whether the "schema_name" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasSchemaName { + public bool HasSchemaName + { get { return schemaName_ != null; } } /// Clears the value of the "schema_name" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearSchemaName() { + public void ClearSchemaName() + { schemaName_ = null; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override bool Equals(object other) { + public override bool Equals(object other) + { return Equals(other as Identifier); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool Equals(Identifier other) { - if (ReferenceEquals(other, null)) { + public bool Equals(Identifier other) + { + if (ReferenceEquals(other, null)) + { return false; } - if (ReferenceEquals(other, this)) { + if (ReferenceEquals(other, this)) + { return true; } if (Name != other.Name) return false; @@ -852,11 +972,13 @@ public bool Equals(Identifier other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override int GetHashCode() { + public override int GetHashCode() + { int hash = 1; if (HasName) hash ^= Name.GetHashCode(); if (HasSchemaName) hash ^= SchemaName.GetHashCode(); - if (_unknownFields != null) { + if (_unknownFields != null) + { hash ^= _unknownFields.GetHashCode(); } return hash; @@ -864,16 +986,18 @@ public override int GetHashCode() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override string ToString() { + public override string ToString() + { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void WriteTo(pb::CodedOutputStream output) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void WriteTo(pb::CodedOutputStream output) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE output.WriteRawMessage(this); - #else +#else if (HasName) { output.WriteRawTag(10); output.WriteString(Name); @@ -885,38 +1009,46 @@ public void WriteTo(pb::CodedOutputStream output) { if (_unknownFields != null) { _unknownFields.WriteTo(output); } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { - if (HasName) { + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) + { + if (HasName) + { output.WriteRawTag(10); output.WriteString(Name); } - if (HasSchemaName) { + if (HasSchemaName) + { output.WriteRawTag(18); output.WriteString(SchemaName); } - if (_unknownFields != null) { + if (_unknownFields != null) + { _unknownFields.WriteTo(ref output); } } - #endif +#endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public int CalculateSize() { + public int CalculateSize() + { int size = 0; - if (HasName) { + if (HasName) + { size += 1 + pb::CodedOutputStream.ComputeStringSize(Name); } - if (HasSchemaName) { + if (HasSchemaName) + { size += 1 + pb::CodedOutputStream.ComputeStringSize(SchemaName); } - if (_unknownFields != null) { + if (_unknownFields != null) + { size += _unknownFields.CalculateSize(); } return size; @@ -924,14 +1056,18 @@ public int CalculateSize() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(Identifier other) { - if (other == null) { + public void MergeFrom(Identifier other) + { + if (other == null) + { return; } - if (other.HasName) { + if (other.HasName) + { Name = other.Name; } - if (other.HasSchemaName) { + if (other.HasSchemaName) + { SchemaName = other.SchemaName; } _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); @@ -939,10 +1075,11 @@ public void MergeFrom(Identifier other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(pb::CodedInputStream input) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void MergeFrom(pb::CodedInputStream input) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE input.ReadRawMessage(this); - #else +#else uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { @@ -959,31 +1096,36 @@ public void MergeFrom(pb::CodedInputStream input) { } } } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) + { uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { + while ((tag = input.ReadTag()) != 0) + { + switch (tag) + { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; - case 10: { - Name = input.ReadString(); - break; - } - case 18: { - SchemaName = input.ReadString(); - break; - } + case 10: + { + Name = input.ReadString(); + break; + } + case 18: + { + SchemaName = input.ReadString(); + break; + } } } } - #endif +#endif } @@ -999,10 +1141,11 @@ public void MergeFrom(pb::CodedInputStream input) { ///array_index : "[" number "]" | "[" "*" "]" ///@endcode /// - internal sealed partial class DocumentPathItem : pb::IMessage - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] + public sealed partial class DocumentPathItem : pb::IMessage +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE , pb::IBufferMessage - #endif +#endif { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new DocumentPathItem()); private pb::UnknownFieldSet _unknownFields; @@ -1013,19 +1156,22 @@ internal sealed partial class DocumentPathItem : pb::IMessage [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static pbr::MessageDescriptor Descriptor { + public static pbr::MessageDescriptor Descriptor + { get { return global::Mysqlx.Expr.MysqlxExprReflection.Descriptor.MessageTypes[2]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - pbr::MessageDescriptor pb::IMessage.Descriptor { + pbr::MessageDescriptor pb::IMessage.Descriptor + { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public DocumentPathItem() { + public DocumentPathItem() + { OnConstruction(); } @@ -1033,7 +1179,8 @@ public DocumentPathItem() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public DocumentPathItem(DocumentPathItem other) : this() { + public DocumentPathItem(DocumentPathItem other) : this() + { _hasBits0 = other._hasBits0; type_ = other.type_; value_ = other.value_; @@ -1043,7 +1190,8 @@ public DocumentPathItem(DocumentPathItem other) : this() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public DocumentPathItem Clone() { + public DocumentPathItem Clone() + { return new DocumentPathItem(this); } @@ -1054,9 +1202,11 @@ public DocumentPathItem Clone() { private global::Mysqlx.Expr.DocumentPathItem.Types.Type type_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public global::Mysqlx.Expr.DocumentPathItem.Types.Type Type { + public global::Mysqlx.Expr.DocumentPathItem.Types.Type Type + { get { if ((_hasBits0 & 1) != 0) { return type_; } else { return TypeDefaultValue; } } - set { + set + { _hasBits0 |= 1; type_ = value; } @@ -1064,13 +1214,15 @@ public DocumentPathItem Clone() { /// Gets whether the "type" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasType { + public bool HasType + { get { return (_hasBits0 & 1) != 0; } } /// Clears the value of the "type" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearType() { + public void ClearType() + { _hasBits0 &= ~1; } @@ -1081,22 +1233,26 @@ public void ClearType() { private string value_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public string Value { + public string Value + { get { return value_ ?? ValueDefaultValue; } - set { + set + { value_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } /// Gets whether the "value" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasValue { + public bool HasValue + { get { return value_ != null; } } /// Clears the value of the "value" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearValue() { + public void ClearValue() + { value_ = null; } @@ -1110,9 +1266,11 @@ public void ClearValue() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public uint Index { + public uint Index + { get { if ((_hasBits0 & 2) != 0) { return index_; } else { return IndexDefaultValue; } } - set { + set + { _hasBits0 |= 2; index_ = value; } @@ -1120,29 +1278,35 @@ public uint Index { /// Gets whether the "index" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasIndex { + public bool HasIndex + { get { return (_hasBits0 & 2) != 0; } } /// Clears the value of the "index" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearIndex() { + public void ClearIndex() + { _hasBits0 &= ~2; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override bool Equals(object other) { + public override bool Equals(object other) + { return Equals(other as DocumentPathItem); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool Equals(DocumentPathItem other) { - if (ReferenceEquals(other, null)) { + public bool Equals(DocumentPathItem other) + { + if (ReferenceEquals(other, null)) + { return false; } - if (ReferenceEquals(other, this)) { + if (ReferenceEquals(other, this)) + { return true; } if (Type != other.Type) return false; @@ -1153,12 +1317,14 @@ public bool Equals(DocumentPathItem other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override int GetHashCode() { + public override int GetHashCode() + { int hash = 1; if (HasType) hash ^= Type.GetHashCode(); if (HasValue) hash ^= Value.GetHashCode(); if (HasIndex) hash ^= Index.GetHashCode(); - if (_unknownFields != null) { + if (_unknownFields != null) + { hash ^= _unknownFields.GetHashCode(); } return hash; @@ -1166,16 +1332,18 @@ public override int GetHashCode() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override string ToString() { + public override string ToString() + { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void WriteTo(pb::CodedOutputStream output) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void WriteTo(pb::CodedOutputStream output) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE output.WriteRawMessage(this); - #else +#else if (HasType) { output.WriteRawTag(8); output.WriteEnum((int) Type); @@ -1191,45 +1359,55 @@ public void WriteTo(pb::CodedOutputStream output) { if (_unknownFields != null) { _unknownFields.WriteTo(output); } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { - if (HasType) { + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) + { + if (HasType) + { output.WriteRawTag(8); - output.WriteEnum((int) Type); + output.WriteEnum((int)Type); } - if (HasValue) { + if (HasValue) + { output.WriteRawTag(18); output.WriteString(Value); } - if (HasIndex) { + if (HasIndex) + { output.WriteRawTag(24); output.WriteUInt32(Index); } - if (_unknownFields != null) { + if (_unknownFields != null) + { _unknownFields.WriteTo(ref output); } } - #endif +#endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public int CalculateSize() { + public int CalculateSize() + { int size = 0; - if (HasType) { - size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Type); + if (HasType) + { + size += 1 + pb::CodedOutputStream.ComputeEnumSize((int)Type); } - if (HasValue) { + if (HasValue) + { size += 1 + pb::CodedOutputStream.ComputeStringSize(Value); } - if (HasIndex) { + if (HasIndex) + { size += 1 + pb::CodedOutputStream.ComputeUInt32Size(Index); } - if (_unknownFields != null) { + if (_unknownFields != null) + { size += _unknownFields.CalculateSize(); } return size; @@ -1237,17 +1415,22 @@ public int CalculateSize() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(DocumentPathItem other) { - if (other == null) { + public void MergeFrom(DocumentPathItem other) + { + if (other == null) + { return; } - if (other.HasType) { + if (other.HasType) + { Type = other.Type; } - if (other.HasValue) { + if (other.HasValue) + { Value = other.Value; } - if (other.HasIndex) { + if (other.HasIndex) + { Index = other.Index; } _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); @@ -1255,10 +1438,11 @@ public void MergeFrom(DocumentPathItem other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(pb::CodedInputStream input) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void MergeFrom(pb::CodedInputStream input) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE input.ReadRawMessage(this); - #else +#else uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { @@ -1279,42 +1463,50 @@ public void MergeFrom(pb::CodedInputStream input) { } } } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) + { uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { + while ((tag = input.ReadTag()) != 0) + { + switch (tag) + { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; - case 8: { - Type = (global::Mysqlx.Expr.DocumentPathItem.Types.Type) input.ReadEnum(); - break; - } - case 18: { - Value = input.ReadString(); - break; - } - case 24: { - Index = input.ReadUInt32(); - break; - } + case 8: + { + Type = (global::Mysqlx.Expr.DocumentPathItem.Types.Type)input.ReadEnum(); + break; + } + case 18: + { + Value = input.ReadString(); + break; + } + case 24: + { + Index = input.ReadUInt32(); + break; + } } } } - #endif +#endif #region Nested types /// Container for nested types declared in the DocumentPathItem message type. [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static partial class Types { - public enum Type { + public static partial class Types + { + public enum Type + { /// ///* .member /// @@ -1364,10 +1556,11 @@ public enum Type { ///doubleAsterisk = "**" ///@endcode /// - internal sealed partial class ColumnIdentifier : pb::IMessage - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] + public sealed partial class ColumnIdentifier : pb::IMessage +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE , pb::IBufferMessage - #endif +#endif { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ColumnIdentifier()); private pb::UnknownFieldSet _unknownFields; @@ -1377,19 +1570,22 @@ internal sealed partial class ColumnIdentifier : pb::IMessage [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static pbr::MessageDescriptor Descriptor { + public static pbr::MessageDescriptor Descriptor + { get { return global::Mysqlx.Expr.MysqlxExprReflection.Descriptor.MessageTypes[3]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - pbr::MessageDescriptor pb::IMessage.Descriptor { + pbr::MessageDescriptor pb::IMessage.Descriptor + { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public ColumnIdentifier() { + public ColumnIdentifier() + { OnConstruction(); } @@ -1397,7 +1593,8 @@ public ColumnIdentifier() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public ColumnIdentifier(ColumnIdentifier other) : this() { + public ColumnIdentifier(ColumnIdentifier other) : this() + { documentPath_ = other.documentPath_.Clone(); name_ = other.name_; tableName_ = other.tableName_; @@ -1407,7 +1604,8 @@ public ColumnIdentifier(ColumnIdentifier other) : this() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public ColumnIdentifier Clone() { + public ColumnIdentifier Clone() + { return new ColumnIdentifier(this); } @@ -1421,7 +1619,8 @@ public ColumnIdentifier Clone() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public pbc::RepeatedField DocumentPath { + public pbc::RepeatedField DocumentPath + { get { return documentPath_; } } @@ -1435,22 +1634,26 @@ public ColumnIdentifier Clone() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public string Name { + public string Name + { get { return name_ ?? NameDefaultValue; } - set { + set + { name_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } /// Gets whether the "name" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasName { + public bool HasName + { get { return name_ != null; } } /// Clears the value of the "name" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearName() { + public void ClearName() + { name_ = null; } @@ -1464,22 +1667,26 @@ public void ClearName() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public string TableName { + public string TableName + { get { return tableName_ ?? TableNameDefaultValue; } - set { + set + { tableName_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } /// Gets whether the "table_name" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasTableName { + public bool HasTableName + { get { return tableName_ != null; } } /// Clears the value of the "table_name" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearTableName() { + public void ClearTableName() + { tableName_ = null; } @@ -1493,41 +1700,49 @@ public void ClearTableName() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public string SchemaName { + public string SchemaName + { get { return schemaName_ ?? SchemaNameDefaultValue; } - set { + set + { schemaName_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } /// Gets whether the "schema_name" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasSchemaName { + public bool HasSchemaName + { get { return schemaName_ != null; } } /// Clears the value of the "schema_name" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearSchemaName() { + public void ClearSchemaName() + { schemaName_ = null; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override bool Equals(object other) { + public override bool Equals(object other) + { return Equals(other as ColumnIdentifier); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool Equals(ColumnIdentifier other) { - if (ReferenceEquals(other, null)) { + public bool Equals(ColumnIdentifier other) + { + if (ReferenceEquals(other, null)) + { return false; } - if (ReferenceEquals(other, this)) { + if (ReferenceEquals(other, this)) + { return true; } - if(!documentPath_.Equals(other.documentPath_)) return false; + if (!documentPath_.Equals(other.documentPath_)) return false; if (Name != other.Name) return false; if (TableName != other.TableName) return false; if (SchemaName != other.SchemaName) return false; @@ -1536,13 +1751,15 @@ public bool Equals(ColumnIdentifier other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override int GetHashCode() { + public override int GetHashCode() + { int hash = 1; hash ^= documentPath_.GetHashCode(); if (HasName) hash ^= Name.GetHashCode(); if (HasTableName) hash ^= TableName.GetHashCode(); if (HasSchemaName) hash ^= SchemaName.GetHashCode(); - if (_unknownFields != null) { + if (_unknownFields != null) + { hash ^= _unknownFields.GetHashCode(); } return hash; @@ -1550,16 +1767,18 @@ public override int GetHashCode() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override string ToString() { + public override string ToString() + { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void WriteTo(pb::CodedOutputStream output) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void WriteTo(pb::CodedOutputStream output) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE output.WriteRawMessage(this); - #else +#else documentPath_.WriteTo(output, _repeated_documentPath_codec); if (HasName) { output.WriteRawTag(18); @@ -1576,47 +1795,57 @@ public void WriteTo(pb::CodedOutputStream output) { if (_unknownFields != null) { _unknownFields.WriteTo(output); } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) + { documentPath_.WriteTo(ref output, _repeated_documentPath_codec); - if (HasName) { + if (HasName) + { output.WriteRawTag(18); output.WriteString(Name); } - if (HasTableName) { + if (HasTableName) + { output.WriteRawTag(26); output.WriteString(TableName); } - if (HasSchemaName) { + if (HasSchemaName) + { output.WriteRawTag(34); output.WriteString(SchemaName); } - if (_unknownFields != null) { + if (_unknownFields != null) + { _unknownFields.WriteTo(ref output); } } - #endif +#endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public int CalculateSize() { + public int CalculateSize() + { int size = 0; size += documentPath_.CalculateSize(_repeated_documentPath_codec); - if (HasName) { + if (HasName) + { size += 1 + pb::CodedOutputStream.ComputeStringSize(Name); } - if (HasTableName) { + if (HasTableName) + { size += 1 + pb::CodedOutputStream.ComputeStringSize(TableName); } - if (HasSchemaName) { + if (HasSchemaName) + { size += 1 + pb::CodedOutputStream.ComputeStringSize(SchemaName); } - if (_unknownFields != null) { + if (_unknownFields != null) + { size += _unknownFields.CalculateSize(); } return size; @@ -1624,18 +1853,23 @@ public int CalculateSize() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(ColumnIdentifier other) { - if (other == null) { + public void MergeFrom(ColumnIdentifier other) + { + if (other == null) + { return; } documentPath_.Add(other.documentPath_); - if (other.HasName) { + if (other.HasName) + { Name = other.Name; } - if (other.HasTableName) { + if (other.HasTableName) + { TableName = other.TableName; } - if (other.HasSchemaName) { + if (other.HasSchemaName) + { SchemaName = other.SchemaName; } _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); @@ -1643,10 +1877,11 @@ public void MergeFrom(ColumnIdentifier other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(pb::CodedInputStream input) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void MergeFrom(pb::CodedInputStream input) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE input.ReadRawMessage(this); - #else +#else uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { @@ -1671,39 +1906,46 @@ public void MergeFrom(pb::CodedInputStream input) { } } } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) + { uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { + while ((tag = input.ReadTag()) != 0) + { + switch (tag) + { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; - case 10: { - documentPath_.AddEntriesFrom(ref input, _repeated_documentPath_codec); - break; - } - case 18: { - Name = input.ReadString(); - break; - } - case 26: { - TableName = input.ReadString(); - break; - } - case 34: { - SchemaName = input.ReadString(); - break; - } + case 10: + { + documentPath_.AddEntriesFrom(ref input, _repeated_documentPath_codec); + break; + } + case 18: + { + Name = input.ReadString(); + break; + } + case 26: + { + TableName = input.ReadString(); + break; + } + case 34: + { + SchemaName = input.ReadString(); + break; + } } } } - #endif +#endif } @@ -1716,10 +1958,11 @@ public void MergeFrom(pb::CodedInputStream input) { ///function_call: `identifier` "(" [ `expr` ["," `expr` ]* ] ")" ///@endcode /// - internal sealed partial class FunctionCall : pb::IMessage - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] + public sealed partial class FunctionCall : pb::IMessage +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE , pb::IBufferMessage - #endif +#endif { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new FunctionCall()); private pb::UnknownFieldSet _unknownFields; @@ -1729,19 +1972,22 @@ internal sealed partial class FunctionCall : pb::IMessage [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static pbr::MessageDescriptor Descriptor { + public static pbr::MessageDescriptor Descriptor + { get { return global::Mysqlx.Expr.MysqlxExprReflection.Descriptor.MessageTypes[4]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - pbr::MessageDescriptor pb::IMessage.Descriptor { + pbr::MessageDescriptor pb::IMessage.Descriptor + { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public FunctionCall() { + public FunctionCall() + { OnConstruction(); } @@ -1749,7 +1995,8 @@ public FunctionCall() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public FunctionCall(FunctionCall other) : this() { + public FunctionCall(FunctionCall other) : this() + { name_ = other.name_ != null ? other.name_.Clone() : null; param_ = other.param_.Clone(); _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); @@ -1757,7 +2004,8 @@ public FunctionCall(FunctionCall other) : this() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public FunctionCall Clone() { + public FunctionCall Clone() + { return new FunctionCall(this); } @@ -1769,9 +2017,11 @@ public FunctionCall Clone() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public global::Mysqlx.Expr.Identifier Name { + public global::Mysqlx.Expr.Identifier Name + { get { return name_; } - set { + set + { name_ = value; } } @@ -1786,37 +2036,44 @@ public FunctionCall Clone() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public pbc::RepeatedField Param { + public pbc::RepeatedField Param + { get { return param_; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override bool Equals(object other) { + public override bool Equals(object other) + { return Equals(other as FunctionCall); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool Equals(FunctionCall other) { - if (ReferenceEquals(other, null)) { + public bool Equals(FunctionCall other) + { + if (ReferenceEquals(other, null)) + { return false; } - if (ReferenceEquals(other, this)) { + if (ReferenceEquals(other, this)) + { return true; } if (!object.Equals(Name, other.Name)) return false; - if(!param_.Equals(other.param_)) return false; + if (!param_.Equals(other.param_)) return false; return Equals(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override int GetHashCode() { + public override int GetHashCode() + { int hash = 1; if (name_ != null) hash ^= Name.GetHashCode(); hash ^= param_.GetHashCode(); - if (_unknownFields != null) { + if (_unknownFields != null) + { hash ^= _unknownFields.GetHashCode(); } return hash; @@ -1824,16 +2081,18 @@ public override int GetHashCode() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override string ToString() { + public override string ToString() + { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void WriteTo(pb::CodedOutputStream output) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void WriteTo(pb::CodedOutputStream output) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE output.WriteRawMessage(this); - #else +#else if (name_ != null) { output.WriteRawTag(10); output.WriteMessage(Name); @@ -1842,33 +2101,39 @@ public void WriteTo(pb::CodedOutputStream output) { if (_unknownFields != null) { _unknownFields.WriteTo(output); } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { - if (name_ != null) { + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) + { + if (name_ != null) + { output.WriteRawTag(10); output.WriteMessage(Name); } param_.WriteTo(ref output, _repeated_param_codec); - if (_unknownFields != null) { + if (_unknownFields != null) + { _unknownFields.WriteTo(ref output); } } - #endif +#endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public int CalculateSize() { + public int CalculateSize() + { int size = 0; - if (name_ != null) { + if (name_ != null) + { size += 1 + pb::CodedOutputStream.ComputeMessageSize(Name); } size += param_.CalculateSize(_repeated_param_codec); - if (_unknownFields != null) { + if (_unknownFields != null) + { size += _unknownFields.CalculateSize(); } return size; @@ -1876,12 +2141,16 @@ public int CalculateSize() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(FunctionCall other) { - if (other == null) { + public void MergeFrom(FunctionCall other) + { + if (other == null) + { return; } - if (other.name_ != null) { - if (name_ == null) { + if (other.name_ != null) + { + if (name_ == null) + { Name = new global::Mysqlx.Expr.Identifier(); } Name.MergeFrom(other.Name); @@ -1892,10 +2161,11 @@ public void MergeFrom(FunctionCall other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(pb::CodedInputStream input) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void MergeFrom(pb::CodedInputStream input) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE input.ReadRawMessage(this); - #else +#else uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { @@ -1915,41 +2185,48 @@ public void MergeFrom(pb::CodedInputStream input) { } } } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) + { uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { + while ((tag = input.ReadTag()) != 0) + { + switch (tag) + { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; - case 10: { - if (name_ == null) { - Name = new global::Mysqlx.Expr.Identifier(); + case 10: + { + if (name_ == null) + { + Name = new global::Mysqlx.Expr.Identifier(); + } + input.ReadMessage(Name); + break; + } + case 18: + { + param_.AddEntriesFrom(ref input, _repeated_param_codec); + break; } - input.ReadMessage(Name); - break; - } - case 18: { - param_.AddEntriesFrom(ref input, _repeated_param_codec); - break; - } } } } - #endif +#endif } - internal sealed partial class Operator : pb::IMessage - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] + public sealed partial class Operator : pb::IMessage +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE , pb::IBufferMessage - #endif +#endif { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Operator()); private pb::UnknownFieldSet _unknownFields; @@ -1959,19 +2236,22 @@ internal sealed partial class Operator : pb::IMessage [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static pbr::MessageDescriptor Descriptor { + public static pbr::MessageDescriptor Descriptor + { get { return global::Mysqlx.Expr.MysqlxExprReflection.Descriptor.MessageTypes[5]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - pbr::MessageDescriptor pb::IMessage.Descriptor { + pbr::MessageDescriptor pb::IMessage.Descriptor + { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Operator() { + public Operator() + { OnConstruction(); } @@ -1979,7 +2259,8 @@ public Operator() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Operator(Operator other) : this() { + public Operator(Operator other) : this() + { name_ = other.name_; param_ = other.param_.Clone(); _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); @@ -1987,7 +2268,8 @@ public Operator(Operator other) : this() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Operator Clone() { + public Operator Clone() + { return new Operator(this); } @@ -2001,22 +2283,26 @@ public Operator Clone() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public string Name { + public string Name + { get { return name_ ?? NameDefaultValue; } - set { + set + { name_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } /// Gets whether the "name" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasName { + public bool HasName + { get { return name_ != null; } } /// Clears the value of the "name" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearName() { + public void ClearName() + { name_ = null; } @@ -2030,37 +2316,44 @@ public void ClearName() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public pbc::RepeatedField Param { + public pbc::RepeatedField Param + { get { return param_; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override bool Equals(object other) { + public override bool Equals(object other) + { return Equals(other as Operator); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool Equals(Operator other) { - if (ReferenceEquals(other, null)) { + public bool Equals(Operator other) + { + if (ReferenceEquals(other, null)) + { return false; } - if (ReferenceEquals(other, this)) { + if (ReferenceEquals(other, this)) + { return true; } if (Name != other.Name) return false; - if(!param_.Equals(other.param_)) return false; + if (!param_.Equals(other.param_)) return false; return Equals(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override int GetHashCode() { + public override int GetHashCode() + { int hash = 1; if (HasName) hash ^= Name.GetHashCode(); hash ^= param_.GetHashCode(); - if (_unknownFields != null) { + if (_unknownFields != null) + { hash ^= _unknownFields.GetHashCode(); } return hash; @@ -2068,16 +2361,18 @@ public override int GetHashCode() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override string ToString() { + public override string ToString() + { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void WriteTo(pb::CodedOutputStream output) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void WriteTo(pb::CodedOutputStream output) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE output.WriteRawMessage(this); - #else +#else if (HasName) { output.WriteRawTag(10); output.WriteString(Name); @@ -2086,33 +2381,39 @@ public void WriteTo(pb::CodedOutputStream output) { if (_unknownFields != null) { _unknownFields.WriteTo(output); } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { - if (HasName) { + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) + { + if (HasName) + { output.WriteRawTag(10); output.WriteString(Name); } param_.WriteTo(ref output, _repeated_param_codec); - if (_unknownFields != null) { + if (_unknownFields != null) + { _unknownFields.WriteTo(ref output); } } - #endif +#endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public int CalculateSize() { + public int CalculateSize() + { int size = 0; - if (HasName) { + if (HasName) + { size += 1 + pb::CodedOutputStream.ComputeStringSize(Name); } size += param_.CalculateSize(_repeated_param_codec); - if (_unknownFields != null) { + if (_unknownFields != null) + { size += _unknownFields.CalculateSize(); } return size; @@ -2120,11 +2421,14 @@ public int CalculateSize() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(Operator other) { - if (other == null) { + public void MergeFrom(Operator other) + { + if (other == null) + { return; } - if (other.HasName) { + if (other.HasName) + { Name = other.Name; } param_.Add(other.param_); @@ -2133,10 +2437,11 @@ public void MergeFrom(Operator other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(pb::CodedInputStream input) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void MergeFrom(pb::CodedInputStream input) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE input.ReadRawMessage(this); - #else +#else uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { @@ -2153,31 +2458,36 @@ public void MergeFrom(pb::CodedInputStream input) { } } } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) + { uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { + while ((tag = input.ReadTag()) != 0) + { + switch (tag) + { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; - case 10: { - Name = input.ReadString(); - break; - } - case 18: { - param_.AddEntriesFrom(ref input, _repeated_param_codec); - break; - } + case 10: + { + Name = input.ReadString(); + break; + } + case 18: + { + param_.AddEntriesFrom(ref input, _repeated_param_codec); + break; + } } } } - #endif +#endif } @@ -2185,10 +2495,11 @@ public void MergeFrom(pb::CodedInputStream input) { ///* ///An object (with expression values) /// - internal sealed partial class Object : pb::IMessage - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] + public sealed partial class Object : pb::IMessage +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE , pb::IBufferMessage - #endif +#endif { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Object()); private pb::UnknownFieldSet _unknownFields; @@ -2198,19 +2509,22 @@ internal sealed partial class Object : pb::IMessage [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static pbr::MessageDescriptor Descriptor { + public static pbr::MessageDescriptor Descriptor + { get { return global::Mysqlx.Expr.MysqlxExprReflection.Descriptor.MessageTypes[6]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - pbr::MessageDescriptor pb::IMessage.Descriptor { + pbr::MessageDescriptor pb::IMessage.Descriptor + { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Object() { + public Object() + { OnConstruction(); } @@ -2218,14 +2532,16 @@ public Object() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Object(Object other) : this() { + public Object(Object other) : this() + { fld_ = other.fld_.Clone(); _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Object Clone() { + public Object Clone() + { return new Object(this); } @@ -2239,35 +2555,42 @@ public Object Clone() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public pbc::RepeatedField Fld { + public pbc::RepeatedField Fld + { get { return fld_; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override bool Equals(object other) { + public override bool Equals(object other) + { return Equals(other as Object); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool Equals(Object other) { - if (ReferenceEquals(other, null)) { + public bool Equals(Object other) + { + if (ReferenceEquals(other, null)) + { return false; } - if (ReferenceEquals(other, this)) { + if (ReferenceEquals(other, this)) + { return true; } - if(!fld_.Equals(other.fld_)) return false; + if (!fld_.Equals(other.fld_)) return false; return Equals(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override int GetHashCode() { + public override int GetHashCode() + { int hash = 1; hash ^= fld_.GetHashCode(); - if (_unknownFields != null) { + if (_unknownFields != null) + { hash ^= _unknownFields.GetHashCode(); } return hash; @@ -2275,40 +2598,46 @@ public override int GetHashCode() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override string ToString() { + public override string ToString() + { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void WriteTo(pb::CodedOutputStream output) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void WriteTo(pb::CodedOutputStream output) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE output.WriteRawMessage(this); - #else +#else fld_.WriteTo(output, _repeated_fld_codec); if (_unknownFields != null) { _unknownFields.WriteTo(output); } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) + { fld_.WriteTo(ref output, _repeated_fld_codec); - if (_unknownFields != null) { + if (_unknownFields != null) + { _unknownFields.WriteTo(ref output); } } - #endif +#endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public int CalculateSize() { + public int CalculateSize() + { int size = 0; size += fld_.CalculateSize(_repeated_fld_codec); - if (_unknownFields != null) { + if (_unknownFields != null) + { size += _unknownFields.CalculateSize(); } return size; @@ -2316,8 +2645,10 @@ public int CalculateSize() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(Object other) { - if (other == null) { + public void MergeFrom(Object other) + { + if (other == null) + { return; } fld_.Add(other.fld_); @@ -2326,10 +2657,11 @@ public void MergeFrom(Object other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(pb::CodedInputStream input) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void MergeFrom(pb::CodedInputStream input) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE input.ReadRawMessage(this); - #else +#else uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { @@ -2342,37 +2674,43 @@ public void MergeFrom(pb::CodedInputStream input) { } } } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) + { uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { + while ((tag = input.ReadTag()) != 0) + { + switch (tag) + { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; - case 10: { - fld_.AddEntriesFrom(ref input, _repeated_fld_codec); - break; - } + case 10: + { + fld_.AddEntriesFrom(ref input, _repeated_fld_codec); + break; + } } } } - #endif +#endif #region Nested types /// Container for nested types declared in the Object message type. [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static partial class Types { + public static partial class Types + { + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] public sealed partial class ObjectField : pb::IMessage - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE , pb::IBufferMessage - #endif +#endif { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ObjectField()); private pb::UnknownFieldSet _unknownFields; @@ -2382,19 +2720,22 @@ public sealed partial class ObjectField : pb::IMessage [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static pbr::MessageDescriptor Descriptor { + public static pbr::MessageDescriptor Descriptor + { get { return global::Mysqlx.Expr.Object.Descriptor.NestedTypes[0]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - pbr::MessageDescriptor pb::IMessage.Descriptor { + pbr::MessageDescriptor pb::IMessage.Descriptor + { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public ObjectField() { + public ObjectField() + { OnConstruction(); } @@ -2402,7 +2743,8 @@ public ObjectField() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public ObjectField(ObjectField other) : this() { + public ObjectField(ObjectField other) : this() + { key_ = other.key_; value_ = other.value_ != null ? other.value_.Clone() : null; _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); @@ -2410,7 +2752,8 @@ public ObjectField(ObjectField other) : this() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public ObjectField Clone() { + public ObjectField Clone() + { return new ObjectField(this); } @@ -2424,22 +2767,26 @@ public ObjectField Clone() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public string Key { + public string Key + { get { return key_ ?? KeyDefaultValue; } - set { + set + { key_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } /// Gets whether the "key" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasKey { + public bool HasKey + { get { return key_ != null; } } /// Clears the value of the "key" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearKey() { + public void ClearKey() + { key_ = null; } @@ -2451,26 +2798,32 @@ public void ClearKey() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public global::Mysqlx.Expr.Expr Value { + public global::Mysqlx.Expr.Expr Value + { get { return value_; } - set { + set + { value_ = value; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override bool Equals(object other) { + public override bool Equals(object other) + { return Equals(other as ObjectField); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool Equals(ObjectField other) { - if (ReferenceEquals(other, null)) { + public bool Equals(ObjectField other) + { + if (ReferenceEquals(other, null)) + { return false; } - if (ReferenceEquals(other, this)) { + if (ReferenceEquals(other, this)) + { return true; } if (Key != other.Key) return false; @@ -2480,11 +2833,13 @@ public bool Equals(ObjectField other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override int GetHashCode() { + public override int GetHashCode() + { int hash = 1; if (HasKey) hash ^= Key.GetHashCode(); if (value_ != null) hash ^= Value.GetHashCode(); - if (_unknownFields != null) { + if (_unknownFields != null) + { hash ^= _unknownFields.GetHashCode(); } return hash; @@ -2492,16 +2847,18 @@ public override int GetHashCode() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override string ToString() { + public override string ToString() + { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void WriteTo(pb::CodedOutputStream output) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void WriteTo(pb::CodedOutputStream output) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE output.WriteRawMessage(this); - #else +#else if (HasKey) { output.WriteRawTag(10); output.WriteString(Key); @@ -2513,38 +2870,46 @@ public void WriteTo(pb::CodedOutputStream output) { if (_unknownFields != null) { _unknownFields.WriteTo(output); } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { - if (HasKey) { + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) + { + if (HasKey) + { output.WriteRawTag(10); output.WriteString(Key); } - if (value_ != null) { + if (value_ != null) + { output.WriteRawTag(18); output.WriteMessage(Value); } - if (_unknownFields != null) { + if (_unknownFields != null) + { _unknownFields.WriteTo(ref output); } } - #endif +#endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public int CalculateSize() { + public int CalculateSize() + { int size = 0; - if (HasKey) { + if (HasKey) + { size += 1 + pb::CodedOutputStream.ComputeStringSize(Key); } - if (value_ != null) { + if (value_ != null) + { size += 1 + pb::CodedOutputStream.ComputeMessageSize(Value); } - if (_unknownFields != null) { + if (_unknownFields != null) + { size += _unknownFields.CalculateSize(); } return size; @@ -2552,15 +2917,20 @@ public int CalculateSize() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(ObjectField other) { - if (other == null) { + public void MergeFrom(ObjectField other) + { + if (other == null) + { return; } - if (other.HasKey) { + if (other.HasKey) + { Key = other.Key; } - if (other.value_ != null) { - if (value_ == null) { + if (other.value_ != null) + { + if (value_ == null) + { Value = new global::Mysqlx.Expr.Expr(); } Value.MergeFrom(other.Value); @@ -2570,10 +2940,11 @@ public void MergeFrom(ObjectField other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(pb::CodedInputStream input) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void MergeFrom(pb::CodedInputStream input) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE input.ReadRawMessage(this); - #else +#else uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { @@ -2593,34 +2964,40 @@ public void MergeFrom(pb::CodedInputStream input) { } } } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) + { uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { + while ((tag = input.ReadTag()) != 0) + { + switch (tag) + { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; - case 10: { - Key = input.ReadString(); - break; - } - case 18: { - if (value_ == null) { - Value = new global::Mysqlx.Expr.Expr(); + case 10: + { + Key = input.ReadString(); + break; + } + case 18: + { + if (value_ == null) + { + Value = new global::Mysqlx.Expr.Expr(); + } + input.ReadMessage(Value); + break; } - input.ReadMessage(Value); - break; - } } } } - #endif +#endif } @@ -2633,10 +3010,11 @@ public void MergeFrom(pb::CodedInputStream input) { ///* ///An array of expressions /// - internal sealed partial class Array : pb::IMessage - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] + public sealed partial class Array : pb::IMessage +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE , pb::IBufferMessage - #endif +#endif { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Array()); private pb::UnknownFieldSet _unknownFields; @@ -2646,19 +3024,22 @@ internal sealed partial class Array : pb::IMessage [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static pbr::MessageDescriptor Descriptor { + public static pbr::MessageDescriptor Descriptor + { get { return global::Mysqlx.Expr.MysqlxExprReflection.Descriptor.MessageTypes[7]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - pbr::MessageDescriptor pb::IMessage.Descriptor { + pbr::MessageDescriptor pb::IMessage.Descriptor + { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Array() { + public Array() + { OnConstruction(); } @@ -2666,14 +3047,16 @@ public Array() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Array(Array other) : this() { + public Array(Array other) : this() + { value_ = other.value_.Clone(); _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Array Clone() { + public Array Clone() + { return new Array(this); } @@ -2687,35 +3070,42 @@ public Array Clone() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public pbc::RepeatedField Value { + public pbc::RepeatedField Value + { get { return value_; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override bool Equals(object other) { + public override bool Equals(object other) + { return Equals(other as Array); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool Equals(Array other) { - if (ReferenceEquals(other, null)) { + public bool Equals(Array other) + { + if (ReferenceEquals(other, null)) + { return false; } - if (ReferenceEquals(other, this)) { + if (ReferenceEquals(other, this)) + { return true; } - if(!value_.Equals(other.value_)) return false; + if (!value_.Equals(other.value_)) return false; return Equals(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override int GetHashCode() { + public override int GetHashCode() + { int hash = 1; hash ^= value_.GetHashCode(); - if (_unknownFields != null) { + if (_unknownFields != null) + { hash ^= _unknownFields.GetHashCode(); } return hash; @@ -2723,40 +3113,46 @@ public override int GetHashCode() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override string ToString() { + public override string ToString() + { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void WriteTo(pb::CodedOutputStream output) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void WriteTo(pb::CodedOutputStream output) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE output.WriteRawMessage(this); - #else +#else value_.WriteTo(output, _repeated_value_codec); if (_unknownFields != null) { _unknownFields.WriteTo(output); } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) + { value_.WriteTo(ref output, _repeated_value_codec); - if (_unknownFields != null) { + if (_unknownFields != null) + { _unknownFields.WriteTo(ref output); } } - #endif +#endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public int CalculateSize() { + public int CalculateSize() + { int size = 0; size += value_.CalculateSize(_repeated_value_codec); - if (_unknownFields != null) { + if (_unknownFields != null) + { size += _unknownFields.CalculateSize(); } return size; @@ -2764,8 +3160,10 @@ public int CalculateSize() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(Array other) { - if (other == null) { + public void MergeFrom(Array other) + { + if (other == null) + { return; } value_.Add(other.value_); @@ -2774,10 +3172,11 @@ public void MergeFrom(Array other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(pb::CodedInputStream input) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void MergeFrom(pb::CodedInputStream input) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE input.ReadRawMessage(this); - #else +#else uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { @@ -2790,27 +3189,31 @@ public void MergeFrom(pb::CodedInputStream input) { } } } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) + { uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { + while ((tag = input.ReadTag()) != 0) + { + switch (tag) + { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; - case 10: { - value_.AddEntriesFrom(ref input, _repeated_value_codec); - break; - } + case 10: + { + value_.AddEntriesFrom(ref input, _repeated_value_codec); + break; + } } } } - #endif +#endif } diff --git a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxNotice.cs b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxNotice.cs index 7333d2701..f431ab8ac 100644 --- a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxNotice.cs +++ b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxNotice.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2022, 2023, Oracle and/or its affiliates. +// Copyright (c) 2023, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as @@ -7,7 +7,7 @@ // This program is also distributed with certain software (including // but not limited to OpenSSL) that is licensed under separate terms, // as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an +// documentation. The authors of MySQL hereby grant you an // additional permission to link the program and your derivative works // with the separately licensed software that they have included with // MySQL. @@ -37,19 +37,23 @@ using pbc = global::Google.Protobuf.Collections; using pbr = global::Google.Protobuf.Reflection; using scg = global::System.Collections.Generic; -namespace Mysqlx.Notice { +namespace Mysqlx.Notice +{ /// Holder for reflection information generated from mysqlx_notice.proto - internal static partial class MysqlxNoticeReflection { + public static partial class MysqlxNoticeReflection + { #region Descriptor /// File descriptor for mysqlx_notice.proto - public static pbr::FileDescriptor Descriptor { + public static pbr::FileDescriptor Descriptor + { get { return descriptor; } } private static pbr::FileDescriptor descriptor; - static MysqlxNoticeReflection() { + static MysqlxNoticeReflection() + { byte[] descriptorData = global::System.Convert.FromBase64String( string.Concat( "ChNteXNxbHhfbm90aWNlLnByb3RvEg1NeXNxbHguTm90aWNlGgxteXNxbHgu", @@ -105,10 +109,11 @@ static MysqlxNoticeReflection() { ///| @ref Mysqlx::Notice::GroupReplicationStateChanged | 4 | ///| @ref Mysqlx::Notice::ServerHello | 5 | /// - internal sealed partial class Frame : pb::IMessage - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] + public sealed partial class Frame : pb::IMessage +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE , pb::IBufferMessage - #endif +#endif { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Frame()); private pb::UnknownFieldSet _unknownFields; @@ -119,19 +124,22 @@ internal sealed partial class Frame : pb::IMessage [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static pbr::MessageDescriptor Descriptor { + public static pbr::MessageDescriptor Descriptor + { get { return global::Mysqlx.Notice.MysqlxNoticeReflection.Descriptor.MessageTypes[0]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - pbr::MessageDescriptor pb::IMessage.Descriptor { + pbr::MessageDescriptor pb::IMessage.Descriptor + { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Frame() { + public Frame() + { OnConstruction(); } @@ -139,7 +147,8 @@ public Frame() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Frame(Frame other) : this() { + public Frame(Frame other) : this() + { _hasBits0 = other._hasBits0; type_ = other.type_; scope_ = other.scope_; @@ -149,7 +158,8 @@ public Frame(Frame other) : this() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Frame Clone() { + public Frame Clone() + { return new Frame(this); } @@ -163,9 +173,11 @@ public Frame Clone() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public uint Type { + public uint Type + { get { if ((_hasBits0 & 1) != 0) { return type_; } else { return TypeDefaultValue; } } - set { + set + { _hasBits0 |= 1; type_ = value; } @@ -173,13 +185,15 @@ public uint Type { /// Gets whether the "type" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasType { + public bool HasType + { get { return (_hasBits0 & 1) != 0; } } /// Clears the value of the "type" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearType() { + public void ClearType() + { _hasBits0 &= ~1; } @@ -193,9 +207,11 @@ public void ClearType() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public global::Mysqlx.Notice.Frame.Types.Scope Scope { + public global::Mysqlx.Notice.Frame.Types.Scope Scope + { get { if ((_hasBits0 & 2) != 0) { return scope_; } else { return ScopeDefaultValue; } } - set { + set + { _hasBits0 |= 2; scope_ = value; } @@ -203,13 +219,15 @@ public void ClearType() { /// Gets whether the "scope" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasScope { + public bool HasScope + { get { return (_hasBits0 & 2) != 0; } } /// Clears the value of the "scope" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearScope() { + public void ClearScope() + { _hasBits0 &= ~2; } @@ -223,38 +241,46 @@ public void ClearScope() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public pb::ByteString Payload { + public pb::ByteString Payload + { get { return payload_ ?? PayloadDefaultValue; } - set { + set + { payload_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } /// Gets whether the "payload" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasPayload { + public bool HasPayload + { get { return payload_ != null; } } /// Clears the value of the "payload" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearPayload() { + public void ClearPayload() + { payload_ = null; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override bool Equals(object other) { + public override bool Equals(object other) + { return Equals(other as Frame); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool Equals(Frame other) { - if (ReferenceEquals(other, null)) { + public bool Equals(Frame other) + { + if (ReferenceEquals(other, null)) + { return false; } - if (ReferenceEquals(other, this)) { + if (ReferenceEquals(other, this)) + { return true; } if (Type != other.Type) return false; @@ -265,12 +291,14 @@ public bool Equals(Frame other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override int GetHashCode() { + public override int GetHashCode() + { int hash = 1; if (HasType) hash ^= Type.GetHashCode(); if (HasScope) hash ^= Scope.GetHashCode(); if (HasPayload) hash ^= Payload.GetHashCode(); - if (_unknownFields != null) { + if (_unknownFields != null) + { hash ^= _unknownFields.GetHashCode(); } return hash; @@ -278,16 +306,18 @@ public override int GetHashCode() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override string ToString() { + public override string ToString() + { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void WriteTo(pb::CodedOutputStream output) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void WriteTo(pb::CodedOutputStream output) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE output.WriteRawMessage(this); - #else +#else if (HasType) { output.WriteRawTag(8); output.WriteUInt32(Type); @@ -303,45 +333,55 @@ public void WriteTo(pb::CodedOutputStream output) { if (_unknownFields != null) { _unknownFields.WriteTo(output); } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { - if (HasType) { + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) + { + if (HasType) + { output.WriteRawTag(8); output.WriteUInt32(Type); } - if (HasScope) { + if (HasScope) + { output.WriteRawTag(16); - output.WriteEnum((int) Scope); + output.WriteEnum((int)Scope); } - if (HasPayload) { + if (HasPayload) + { output.WriteRawTag(26); output.WriteBytes(Payload); } - if (_unknownFields != null) { + if (_unknownFields != null) + { _unknownFields.WriteTo(ref output); } } - #endif +#endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public int CalculateSize() { + public int CalculateSize() + { int size = 0; - if (HasType) { + if (HasType) + { size += 1 + pb::CodedOutputStream.ComputeUInt32Size(Type); } - if (HasScope) { - size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Scope); + if (HasScope) + { + size += 1 + pb::CodedOutputStream.ComputeEnumSize((int)Scope); } - if (HasPayload) { + if (HasPayload) + { size += 1 + pb::CodedOutputStream.ComputeBytesSize(Payload); } - if (_unknownFields != null) { + if (_unknownFields != null) + { size += _unknownFields.CalculateSize(); } return size; @@ -349,17 +389,22 @@ public int CalculateSize() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(Frame other) { - if (other == null) { + public void MergeFrom(Frame other) + { + if (other == null) + { return; } - if (other.HasType) { + if (other.HasType) + { Type = other.Type; } - if (other.HasScope) { + if (other.HasScope) + { Scope = other.Scope; } - if (other.HasPayload) { + if (other.HasPayload) + { Payload = other.Payload; } _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); @@ -367,10 +412,11 @@ public void MergeFrom(Frame other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(pb::CodedInputStream input) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void MergeFrom(pb::CodedInputStream input) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE input.ReadRawMessage(this); - #else +#else uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { @@ -391,45 +437,53 @@ public void MergeFrom(pb::CodedInputStream input) { } } } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) + { uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { + while ((tag = input.ReadTag()) != 0) + { + switch (tag) + { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; - case 8: { - Type = input.ReadUInt32(); - break; - } - case 16: { - Scope = (global::Mysqlx.Notice.Frame.Types.Scope) input.ReadEnum(); - break; - } - case 26: { - Payload = input.ReadBytes(); - break; - } + case 8: + { + Type = input.ReadUInt32(); + break; + } + case 16: + { + Scope = (global::Mysqlx.Notice.Frame.Types.Scope)input.ReadEnum(); + break; + } + case 26: + { + Payload = input.ReadBytes(); + break; + } } } } - #endif +#endif #region Nested types /// Container for nested types declared in the Frame message type. [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static partial class Types { + public static partial class Types + { /// ///* scope of notice /// - public enum Scope { + public enum Scope + { [pbr::OriginalName("GLOBAL")] Global = 1, [pbr::OriginalName("LOCAL")] Local = 2, } @@ -437,7 +491,8 @@ public enum Scope { /// ///* type of notice payload /// - public enum Type { + public enum Type + { [pbr::OriginalName("WARNING")] Warning = 1, [pbr::OriginalName("SESSION_VARIABLE_CHANGED")] SessionVariableChanged = 2, [pbr::OriginalName("SESSION_STATE_CHANGED")] SessionStateChanged = 3, @@ -471,10 +526,11 @@ public enum Type { ///| ``.type`` | 1 | ///| ``.scope`` | ``local`` or ``global`` | /// - internal sealed partial class Warning : pb::IMessage - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] + public sealed partial class Warning : pb::IMessage +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE , pb::IBufferMessage - #endif +#endif { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Warning()); private pb::UnknownFieldSet _unknownFields; @@ -485,19 +541,22 @@ internal sealed partial class Warning : pb::IMessage [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static pbr::MessageDescriptor Descriptor { + public static pbr::MessageDescriptor Descriptor + { get { return global::Mysqlx.Notice.MysqlxNoticeReflection.Descriptor.MessageTypes[1]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - pbr::MessageDescriptor pb::IMessage.Descriptor { + pbr::MessageDescriptor pb::IMessage.Descriptor + { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Warning() { + public Warning() + { OnConstruction(); } @@ -505,7 +564,8 @@ public Warning() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Warning(Warning other) : this() { + public Warning(Warning other) : this() + { _hasBits0 = other._hasBits0; level_ = other.level_; code_ = other.code_; @@ -515,7 +575,8 @@ public Warning(Warning other) : this() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Warning Clone() { + public Warning Clone() + { return new Warning(this); } @@ -529,9 +590,11 @@ public Warning Clone() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public global::Mysqlx.Notice.Warning.Types.Level Level { + public global::Mysqlx.Notice.Warning.Types.Level Level + { get { if ((_hasBits0 & 1) != 0) { return level_; } else { return LevelDefaultValue; } } - set { + set + { _hasBits0 |= 1; level_ = value; } @@ -539,13 +602,15 @@ public Warning Clone() { /// Gets whether the "level" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasLevel { + public bool HasLevel + { get { return (_hasBits0 & 1) != 0; } } /// Clears the value of the "level" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearLevel() { + public void ClearLevel() + { _hasBits0 &= ~1; } @@ -559,9 +624,11 @@ public void ClearLevel() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public uint Code { + public uint Code + { get { if ((_hasBits0 & 2) != 0) { return code_; } else { return CodeDefaultValue; } } - set { + set + { _hasBits0 |= 2; code_ = value; } @@ -569,13 +636,15 @@ public uint Code { /// Gets whether the "code" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasCode { + public bool HasCode + { get { return (_hasBits0 & 2) != 0; } } /// Clears the value of the "code" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearCode() { + public void ClearCode() + { _hasBits0 &= ~2; } @@ -589,38 +658,46 @@ public void ClearCode() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public string Msg { + public string Msg + { get { return msg_ ?? MsgDefaultValue; } - set { + set + { msg_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } /// Gets whether the "msg" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasMsg { + public bool HasMsg + { get { return msg_ != null; } } /// Clears the value of the "msg" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearMsg() { + public void ClearMsg() + { msg_ = null; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override bool Equals(object other) { + public override bool Equals(object other) + { return Equals(other as Warning); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool Equals(Warning other) { - if (ReferenceEquals(other, null)) { + public bool Equals(Warning other) + { + if (ReferenceEquals(other, null)) + { return false; } - if (ReferenceEquals(other, this)) { + if (ReferenceEquals(other, this)) + { return true; } if (Level != other.Level) return false; @@ -631,12 +708,14 @@ public bool Equals(Warning other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override int GetHashCode() { + public override int GetHashCode() + { int hash = 1; if (HasLevel) hash ^= Level.GetHashCode(); if (HasCode) hash ^= Code.GetHashCode(); if (HasMsg) hash ^= Msg.GetHashCode(); - if (_unknownFields != null) { + if (_unknownFields != null) + { hash ^= _unknownFields.GetHashCode(); } return hash; @@ -644,16 +723,18 @@ public override int GetHashCode() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override string ToString() { + public override string ToString() + { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void WriteTo(pb::CodedOutputStream output) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void WriteTo(pb::CodedOutputStream output) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE output.WriteRawMessage(this); - #else +#else if (HasLevel) { output.WriteRawTag(8); output.WriteEnum((int) Level); @@ -669,45 +750,55 @@ public void WriteTo(pb::CodedOutputStream output) { if (_unknownFields != null) { _unknownFields.WriteTo(output); } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { - if (HasLevel) { + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) + { + if (HasLevel) + { output.WriteRawTag(8); - output.WriteEnum((int) Level); + output.WriteEnum((int)Level); } - if (HasCode) { + if (HasCode) + { output.WriteRawTag(16); output.WriteUInt32(Code); } - if (HasMsg) { + if (HasMsg) + { output.WriteRawTag(26); output.WriteString(Msg); } - if (_unknownFields != null) { + if (_unknownFields != null) + { _unknownFields.WriteTo(ref output); } } - #endif +#endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public int CalculateSize() { + public int CalculateSize() + { int size = 0; - if (HasLevel) { - size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Level); + if (HasLevel) + { + size += 1 + pb::CodedOutputStream.ComputeEnumSize((int)Level); } - if (HasCode) { + if (HasCode) + { size += 1 + pb::CodedOutputStream.ComputeUInt32Size(Code); } - if (HasMsg) { + if (HasMsg) + { size += 1 + pb::CodedOutputStream.ComputeStringSize(Msg); } - if (_unknownFields != null) { + if (_unknownFields != null) + { size += _unknownFields.CalculateSize(); } return size; @@ -715,17 +806,22 @@ public int CalculateSize() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(Warning other) { - if (other == null) { + public void MergeFrom(Warning other) + { + if (other == null) + { return; } - if (other.HasLevel) { + if (other.HasLevel) + { Level = other.Level; } - if (other.HasCode) { + if (other.HasCode) + { Code = other.Code; } - if (other.HasMsg) { + if (other.HasMsg) + { Msg = other.Msg; } _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); @@ -733,10 +829,11 @@ public void MergeFrom(Warning other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(pb::CodedInputStream input) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void MergeFrom(pb::CodedInputStream input) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE input.ReadRawMessage(this); - #else +#else uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { @@ -757,42 +854,50 @@ public void MergeFrom(pb::CodedInputStream input) { } } } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) + { uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { + while ((tag = input.ReadTag()) != 0) + { + switch (tag) + { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; - case 8: { - Level = (global::Mysqlx.Notice.Warning.Types.Level) input.ReadEnum(); - break; - } - case 16: { - Code = input.ReadUInt32(); - break; - } - case 26: { - Msg = input.ReadString(); - break; - } + case 8: + { + Level = (global::Mysqlx.Notice.Warning.Types.Level)input.ReadEnum(); + break; + } + case 16: + { + Code = input.ReadUInt32(); + break; + } + case 26: + { + Msg = input.ReadString(); + break; + } } } } - #endif +#endif #region Nested types /// Container for nested types declared in the Warning message type. [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static partial class Types { - public enum Level { + public static partial class Types + { + public enum Level + { [pbr::OriginalName("NOTE")] Note = 1, [pbr::OriginalName("WARNING")] Warning = 2, [pbr::OriginalName("ERROR")] Error = 3, @@ -818,10 +923,11 @@ public enum Level { ///| ``.type`` | 2 | ///| ``.scope`` | ``local``| /// - internal sealed partial class SessionVariableChanged : pb::IMessage - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] + public sealed partial class SessionVariableChanged : pb::IMessage +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE , pb::IBufferMessage - #endif +#endif { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new SessionVariableChanged()); private pb::UnknownFieldSet _unknownFields; @@ -831,19 +937,22 @@ internal sealed partial class SessionVariableChanged : pb::IMessage [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public string Param { + public string Param + { get { return param_ ?? ParamDefaultValue; } - set { + set + { param_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } /// Gets whether the "param" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasParam { + public bool HasParam + { get { return param_ != null; } } /// Clears the value of the "param" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearParam() { + public void ClearParam() + { param_ = null; } @@ -900,26 +1015,32 @@ public void ClearParam() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public global::Mysqlx.Datatypes.Scalar Value { + public global::Mysqlx.Datatypes.Scalar Value + { get { return value_; } - set { + set + { value_ = value; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override bool Equals(object other) { + public override bool Equals(object other) + { return Equals(other as SessionVariableChanged); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool Equals(SessionVariableChanged other) { - if (ReferenceEquals(other, null)) { + public bool Equals(SessionVariableChanged other) + { + if (ReferenceEquals(other, null)) + { return false; } - if (ReferenceEquals(other, this)) { + if (ReferenceEquals(other, this)) + { return true; } if (Param != other.Param) return false; @@ -929,11 +1050,13 @@ public bool Equals(SessionVariableChanged other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override int GetHashCode() { + public override int GetHashCode() + { int hash = 1; if (HasParam) hash ^= Param.GetHashCode(); if (value_ != null) hash ^= Value.GetHashCode(); - if (_unknownFields != null) { + if (_unknownFields != null) + { hash ^= _unknownFields.GetHashCode(); } return hash; @@ -941,16 +1064,18 @@ public override int GetHashCode() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override string ToString() { + public override string ToString() + { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void WriteTo(pb::CodedOutputStream output) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void WriteTo(pb::CodedOutputStream output) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE output.WriteRawMessage(this); - #else +#else if (HasParam) { output.WriteRawTag(10); output.WriteString(Param); @@ -962,38 +1087,46 @@ public void WriteTo(pb::CodedOutputStream output) { if (_unknownFields != null) { _unknownFields.WriteTo(output); } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { - if (HasParam) { + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) + { + if (HasParam) + { output.WriteRawTag(10); output.WriteString(Param); } - if (value_ != null) { + if (value_ != null) + { output.WriteRawTag(18); output.WriteMessage(Value); } - if (_unknownFields != null) { + if (_unknownFields != null) + { _unknownFields.WriteTo(ref output); } } - #endif +#endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public int CalculateSize() { + public int CalculateSize() + { int size = 0; - if (HasParam) { + if (HasParam) + { size += 1 + pb::CodedOutputStream.ComputeStringSize(Param); } - if (value_ != null) { + if (value_ != null) + { size += 1 + pb::CodedOutputStream.ComputeMessageSize(Value); } - if (_unknownFields != null) { + if (_unknownFields != null) + { size += _unknownFields.CalculateSize(); } return size; @@ -1001,15 +1134,20 @@ public int CalculateSize() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(SessionVariableChanged other) { - if (other == null) { + public void MergeFrom(SessionVariableChanged other) + { + if (other == null) + { return; } - if (other.HasParam) { + if (other.HasParam) + { Param = other.Param; } - if (other.value_ != null) { - if (value_ == null) { + if (other.value_ != null) + { + if (value_ == null) + { Value = new global::Mysqlx.Datatypes.Scalar(); } Value.MergeFrom(other.Value); @@ -1019,10 +1157,11 @@ public void MergeFrom(SessionVariableChanged other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(pb::CodedInputStream input) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void MergeFrom(pb::CodedInputStream input) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE input.ReadRawMessage(this); - #else +#else uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { @@ -1042,41 +1181,48 @@ public void MergeFrom(pb::CodedInputStream input) { } } } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) + { uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { + while ((tag = input.ReadTag()) != 0) + { + switch (tag) + { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; - case 10: { - Param = input.ReadString(); - break; - } - case 18: { - if (value_ == null) { - Value = new global::Mysqlx.Datatypes.Scalar(); + case 10: + { + Param = input.ReadString(); + break; + } + case 18: + { + if (value_ == null) + { + Value = new global::Mysqlx.Datatypes.Scalar(); + } + input.ReadMessage(Value); + break; } - input.ReadMessage(Value); - break; - } } } } - #endif +#endif } - internal sealed partial class SessionStateChanged : pb::IMessage - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] + public sealed partial class SessionStateChanged : pb::IMessage +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE , pb::IBufferMessage - #endif +#endif { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new SessionStateChanged()); private pb::UnknownFieldSet _unknownFields; @@ -1087,19 +1233,22 @@ internal sealed partial class SessionStateChanged : pb::IMessage [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public global::Mysqlx.Notice.SessionStateChanged.Types.Parameter Param { + public global::Mysqlx.Notice.SessionStateChanged.Types.Parameter Param + { get { if ((_hasBits0 & 1) != 0) { return param_; } else { return ParamDefaultValue; } } - set { + set + { _hasBits0 |= 1; param_ = value; } @@ -1140,13 +1293,15 @@ public SessionStateChanged Clone() { /// Gets whether the "param" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasParam { + public bool HasParam + { get { return (_hasBits0 & 1) != 0; } } /// Clears the value of the "param" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearParam() { + public void ClearParam() + { _hasBits0 &= ~1; } @@ -1160,37 +1315,44 @@ public void ClearParam() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public pbc::RepeatedField Value { + public pbc::RepeatedField Value + { get { return value_; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override bool Equals(object other) { + public override bool Equals(object other) + { return Equals(other as SessionStateChanged); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool Equals(SessionStateChanged other) { - if (ReferenceEquals(other, null)) { + public bool Equals(SessionStateChanged other) + { + if (ReferenceEquals(other, null)) + { return false; } - if (ReferenceEquals(other, this)) { + if (ReferenceEquals(other, this)) + { return true; } if (Param != other.Param) return false; - if(!value_.Equals(other.value_)) return false; + if (!value_.Equals(other.value_)) return false; return Equals(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override int GetHashCode() { + public override int GetHashCode() + { int hash = 1; if (HasParam) hash ^= Param.GetHashCode(); hash ^= value_.GetHashCode(); - if (_unknownFields != null) { + if (_unknownFields != null) + { hash ^= _unknownFields.GetHashCode(); } return hash; @@ -1198,16 +1360,18 @@ public override int GetHashCode() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override string ToString() { + public override string ToString() + { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void WriteTo(pb::CodedOutputStream output) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void WriteTo(pb::CodedOutputStream output) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE output.WriteRawMessage(this); - #else +#else if (HasParam) { output.WriteRawTag(8); output.WriteEnum((int) Param); @@ -1216,33 +1380,39 @@ public void WriteTo(pb::CodedOutputStream output) { if (_unknownFields != null) { _unknownFields.WriteTo(output); } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { - if (HasParam) { + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) + { + if (HasParam) + { output.WriteRawTag(8); - output.WriteEnum((int) Param); + output.WriteEnum((int)Param); } value_.WriteTo(ref output, _repeated_value_codec); - if (_unknownFields != null) { + if (_unknownFields != null) + { _unknownFields.WriteTo(ref output); } } - #endif +#endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public int CalculateSize() { + public int CalculateSize() + { int size = 0; - if (HasParam) { - size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Param); + if (HasParam) + { + size += 1 + pb::CodedOutputStream.ComputeEnumSize((int)Param); } size += value_.CalculateSize(_repeated_value_codec); - if (_unknownFields != null) { + if (_unknownFields != null) + { size += _unknownFields.CalculateSize(); } return size; @@ -1250,11 +1420,14 @@ public int CalculateSize() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(SessionStateChanged other) { - if (other == null) { + public void MergeFrom(SessionStateChanged other) + { + if (other == null) + { return; } - if (other.HasParam) { + if (other.HasParam) + { Param = other.Param; } value_.Add(other.value_); @@ -1263,10 +1436,11 @@ public void MergeFrom(SessionStateChanged other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(pb::CodedInputStream input) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void MergeFrom(pb::CodedInputStream input) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE input.ReadRawMessage(this); - #else +#else uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { @@ -1283,38 +1457,45 @@ public void MergeFrom(pb::CodedInputStream input) { } } } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) + { uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { + while ((tag = input.ReadTag()) != 0) + { + switch (tag) + { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; - case 8: { - Param = (global::Mysqlx.Notice.SessionStateChanged.Types.Parameter) input.ReadEnum(); - break; - } - case 18: { - value_.AddEntriesFrom(ref input, _repeated_value_codec); - break; - } + case 8: + { + Param = (global::Mysqlx.Notice.SessionStateChanged.Types.Parameter)input.ReadEnum(); + break; + } + case 18: + { + value_.AddEntriesFrom(ref input, _repeated_value_codec); + break; + } } } } - #endif +#endif #region Nested types /// Container for nested types declared in the SessionStateChanged message type. [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static partial class Types { - public enum Parameter { + public static partial class Types + { + public enum Parameter + { [pbr::OriginalName("CURRENT_SCHEMA")] CurrentSchema = 1, [pbr::OriginalName("ACCOUNT_EXPIRED")] AccountExpired = 2, [pbr::OriginalName("GENERATED_INSERT_ID")] GeneratedInsertId = 3, @@ -1345,10 +1526,11 @@ public enum Parameter { ///|``.type`` | 4 | ///|``.scope`` | ``global`` | /// - internal sealed partial class GroupReplicationStateChanged : pb::IMessage - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] + public sealed partial class GroupReplicationStateChanged : pb::IMessage +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE , pb::IBufferMessage - #endif +#endif { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new GroupReplicationStateChanged()); private pb::UnknownFieldSet _unknownFields; @@ -1359,19 +1541,22 @@ internal sealed partial class GroupReplicationStateChanged : pb::IMessage [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public uint Type { + public uint Type + { get { if ((_hasBits0 & 1) != 0) { return type_; } else { return TypeDefaultValue; } } - set { + set + { _hasBits0 |= 1; type_ = value; } @@ -1412,13 +1601,15 @@ public uint Type { /// Gets whether the "type" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasType { + public bool HasType + { get { return (_hasBits0 & 1) != 0; } } /// Clears the value of the "type" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearType() { + public void ClearType() + { _hasBits0 &= ~1; } @@ -1432,38 +1623,46 @@ public void ClearType() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public string ViewId { + public string ViewId + { get { return viewId_ ?? ViewIdDefaultValue; } - set { + set + { viewId_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } /// Gets whether the "view_id" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasViewId { + public bool HasViewId + { get { return viewId_ != null; } } /// Clears the value of the "view_id" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearViewId() { + public void ClearViewId() + { viewId_ = null; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override bool Equals(object other) { + public override bool Equals(object other) + { return Equals(other as GroupReplicationStateChanged); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool Equals(GroupReplicationStateChanged other) { - if (ReferenceEquals(other, null)) { + public bool Equals(GroupReplicationStateChanged other) + { + if (ReferenceEquals(other, null)) + { return false; } - if (ReferenceEquals(other, this)) { + if (ReferenceEquals(other, this)) + { return true; } if (Type != other.Type) return false; @@ -1473,11 +1672,13 @@ public bool Equals(GroupReplicationStateChanged other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override int GetHashCode() { + public override int GetHashCode() + { int hash = 1; if (HasType) hash ^= Type.GetHashCode(); if (HasViewId) hash ^= ViewId.GetHashCode(); - if (_unknownFields != null) { + if (_unknownFields != null) + { hash ^= _unknownFields.GetHashCode(); } return hash; @@ -1485,16 +1686,18 @@ public override int GetHashCode() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override string ToString() { + public override string ToString() + { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void WriteTo(pb::CodedOutputStream output) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void WriteTo(pb::CodedOutputStream output) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE output.WriteRawMessage(this); - #else +#else if (HasType) { output.WriteRawTag(8); output.WriteUInt32(Type); @@ -1506,38 +1709,46 @@ public void WriteTo(pb::CodedOutputStream output) { if (_unknownFields != null) { _unknownFields.WriteTo(output); } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { - if (HasType) { + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) + { + if (HasType) + { output.WriteRawTag(8); output.WriteUInt32(Type); } - if (HasViewId) { + if (HasViewId) + { output.WriteRawTag(18); output.WriteString(ViewId); } - if (_unknownFields != null) { + if (_unknownFields != null) + { _unknownFields.WriteTo(ref output); } } - #endif +#endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public int CalculateSize() { + public int CalculateSize() + { int size = 0; - if (HasType) { + if (HasType) + { size += 1 + pb::CodedOutputStream.ComputeUInt32Size(Type); } - if (HasViewId) { + if (HasViewId) + { size += 1 + pb::CodedOutputStream.ComputeStringSize(ViewId); } - if (_unknownFields != null) { + if (_unknownFields != null) + { size += _unknownFields.CalculateSize(); } return size; @@ -1545,14 +1756,18 @@ public int CalculateSize() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(GroupReplicationStateChanged other) { - if (other == null) { + public void MergeFrom(GroupReplicationStateChanged other) + { + if (other == null) + { return; } - if (other.HasType) { + if (other.HasType) + { Type = other.Type; } - if (other.HasViewId) { + if (other.HasViewId) + { ViewId = other.ViewId; } _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); @@ -1560,10 +1775,11 @@ public void MergeFrom(GroupReplicationStateChanged other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(pb::CodedInputStream input) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void MergeFrom(pb::CodedInputStream input) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE input.ReadRawMessage(this); - #else +#else uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { @@ -1580,38 +1796,45 @@ public void MergeFrom(pb::CodedInputStream input) { } } } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) + { uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { + while ((tag = input.ReadTag()) != 0) + { + switch (tag) + { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; - case 8: { - Type = input.ReadUInt32(); - break; - } - case 18: { - ViewId = input.ReadString(); - break; - } + case 8: + { + Type = input.ReadUInt32(); + break; + } + case 18: + { + ViewId = input.ReadString(); + break; + } } } } - #endif +#endif #region Nested types /// Container for nested types declared in the GroupReplicationStateChanged message type. [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static partial class Types { - public enum Type { + public static partial class Types + { + public enum Type + { [pbr::OriginalName("MEMBERSHIP_QUORUM_LOSS")] MembershipQuorumLoss = 1, [pbr::OriginalName("MEMBERSHIP_VIEW_CHANGE")] MembershipViewChange = 2, [pbr::OriginalName("MEMBER_ROLE_CHANGE")] MemberRoleChange = 3, @@ -1632,10 +1855,11 @@ public enum Type { ///|``.type`` | 5 | ///|``.scope`` | ``global`` | /// - internal sealed partial class ServerHello : pb::IMessage - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] + public sealed partial class ServerHello : pb::IMessage +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE , pb::IBufferMessage - #endif +#endif { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ServerHello()); private pb::UnknownFieldSet _unknownFields; @@ -1645,19 +1869,22 @@ internal sealed partial class ServerHello : pb::IMessage [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static pbr::MessageDescriptor Descriptor { + public static pbr::MessageDescriptor Descriptor + { get { return global::Mysqlx.Notice.MysqlxNoticeReflection.Descriptor.MessageTypes[5]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - pbr::MessageDescriptor pb::IMessage.Descriptor { + pbr::MessageDescriptor pb::IMessage.Descriptor + { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public ServerHello() { + public ServerHello() + { OnConstruction(); } @@ -1665,29 +1892,35 @@ public ServerHello() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public ServerHello(ServerHello other) : this() { + public ServerHello(ServerHello other) : this() + { _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public ServerHello Clone() { + public ServerHello Clone() + { return new ServerHello(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override bool Equals(object other) { + public override bool Equals(object other) + { return Equals(other as ServerHello); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool Equals(ServerHello other) { - if (ReferenceEquals(other, null)) { + public bool Equals(ServerHello other) + { + if (ReferenceEquals(other, null)) + { return false; } - if (ReferenceEquals(other, this)) { + if (ReferenceEquals(other, this)) + { return true; } return Equals(_unknownFields, other._unknownFields); @@ -1695,9 +1928,11 @@ public bool Equals(ServerHello other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override int GetHashCode() { + public override int GetHashCode() + { int hash = 1; - if (_unknownFields != null) { + if (_unknownFields != null) + { hash ^= _unknownFields.GetHashCode(); } return hash; @@ -1705,37 +1940,43 @@ public override int GetHashCode() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override string ToString() { + public override string ToString() + { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void WriteTo(pb::CodedOutputStream output) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void WriteTo(pb::CodedOutputStream output) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE output.WriteRawMessage(this); - #else +#else if (_unknownFields != null) { _unknownFields.WriteTo(output); } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { - if (_unknownFields != null) { + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) + { + if (_unknownFields != null) + { _unknownFields.WriteTo(ref output); } } - #endif +#endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public int CalculateSize() { + public int CalculateSize() + { int size = 0; - if (_unknownFields != null) { + if (_unknownFields != null) + { size += _unknownFields.CalculateSize(); } return size; @@ -1743,8 +1984,10 @@ public int CalculateSize() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(ServerHello other) { - if (other == null) { + public void MergeFrom(ServerHello other) + { + if (other == null) + { return; } _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); @@ -1752,10 +1995,11 @@ public void MergeFrom(ServerHello other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(pb::CodedInputStream input) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void MergeFrom(pb::CodedInputStream input) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE input.ReadRawMessage(this); - #else +#else uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { @@ -1764,23 +2008,26 @@ public void MergeFrom(pb::CodedInputStream input) { break; } } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) + { uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { + while ((tag = input.ReadTag()) != 0) + { + switch (tag) + { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; } } } - #endif +#endif } diff --git a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxPrepare.cs b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxPrepare.cs index 45bfa77ba..bcf88607b 100644 --- a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxPrepare.cs +++ b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxPrepare.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2022, 2023, Oracle and/or its affiliates. +// Copyright (c) 2023, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as @@ -7,7 +7,7 @@ // This program is also distributed with certain software (including // but not limited to OpenSSL) that is licensed under separate terms, // as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an +// documentation. The authors of MySQL hereby grant you an // additional permission to link the program and your derivative works // with the separately licensed software that they have included with // MySQL. @@ -37,19 +37,23 @@ using pbc = global::Google.Protobuf.Collections; using pbr = global::Google.Protobuf.Reflection; using scg = global::System.Collections.Generic; -namespace Mysqlx.Prepare { +namespace Mysqlx.Prepare +{ /// Holder for reflection information generated from mysqlx_prepare.proto - internal static partial class MysqlxPrepareReflection { + public static partial class MysqlxPrepareReflection + { #region Descriptor /// File descriptor for mysqlx_prepare.proto - internal static pbr::FileDescriptor Descriptor { + public static pbr::FileDescriptor Descriptor + { get { return descriptor; } } private static pbr::FileDescriptor descriptor; - static MysqlxPrepareReflection() { + static MysqlxPrepareReflection() + { byte[] descriptorData = global::System.Convert.FromBase64String( string.Concat( "ChRteXNxbHhfcHJlcGFyZS5wcm90bxIOTXlzcWx4LlByZXBhcmUaDG15c3Fs", @@ -95,10 +99,11 @@ static MysqlxPrepareReflection() { /// ///@returns @ref Mysqlx::Ok or @ref Mysqlx::Error /// - internal sealed partial class Prepare : pb::IMessage - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] + public sealed partial class Prepare : pb::IMessage +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE , pb::IBufferMessage - #endif +#endif { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Prepare()); private pb::UnknownFieldSet _unknownFields; @@ -109,19 +114,22 @@ internal sealed partial class Prepare : pb::IMessage [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static pbr::MessageDescriptor Descriptor { + public static pbr::MessageDescriptor Descriptor + { get { return global::Mysqlx.Prepare.MysqlxPrepareReflection.Descriptor.MessageTypes[0]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - pbr::MessageDescriptor pb::IMessage.Descriptor { + pbr::MessageDescriptor pb::IMessage.Descriptor + { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Prepare() { + public Prepare() + { OnConstruction(); } @@ -129,7 +137,8 @@ public Prepare() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Prepare(Prepare other) : this() { + public Prepare(Prepare other) : this() + { _hasBits0 = other._hasBits0; stmtId_ = other.stmtId_; stmt_ = other.stmt_ != null ? other.stmt_.Clone() : null; @@ -138,7 +147,8 @@ public Prepare(Prepare other) : this() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Prepare Clone() { + public Prepare Clone() + { return new Prepare(this); } @@ -153,9 +163,11 @@ public Prepare Clone() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public uint StmtId { + public uint StmtId + { get { if ((_hasBits0 & 1) != 0) { return stmtId_; } else { return StmtIdDefaultValue; } } - set { + set + { _hasBits0 |= 1; stmtId_ = value; } @@ -163,13 +175,15 @@ public uint StmtId { /// Gets whether the "stmt_id" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasStmtId { + public bool HasStmtId + { get { return (_hasBits0 & 1) != 0; } } /// Clears the value of the "stmt_id" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearStmtId() { + public void ClearStmtId() + { _hasBits0 &= ~1; } @@ -182,26 +196,32 @@ public void ClearStmtId() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public global::Mysqlx.Prepare.Prepare.Types.OneOfMessage Stmt { + public global::Mysqlx.Prepare.Prepare.Types.OneOfMessage Stmt + { get { return stmt_; } - set { + set + { stmt_ = value; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override bool Equals(object other) { + public override bool Equals(object other) + { return Equals(other as Prepare); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool Equals(Prepare other) { - if (ReferenceEquals(other, null)) { + public bool Equals(Prepare other) + { + if (ReferenceEquals(other, null)) + { return false; } - if (ReferenceEquals(other, this)) { + if (ReferenceEquals(other, this)) + { return true; } if (StmtId != other.StmtId) return false; @@ -211,11 +231,13 @@ public bool Equals(Prepare other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override int GetHashCode() { + public override int GetHashCode() + { int hash = 1; if (HasStmtId) hash ^= StmtId.GetHashCode(); if (stmt_ != null) hash ^= Stmt.GetHashCode(); - if (_unknownFields != null) { + if (_unknownFields != null) + { hash ^= _unknownFields.GetHashCode(); } return hash; @@ -223,16 +245,18 @@ public override int GetHashCode() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override string ToString() { + public override string ToString() + { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void WriteTo(pb::CodedOutputStream output) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void WriteTo(pb::CodedOutputStream output) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE output.WriteRawMessage(this); - #else +#else if (HasStmtId) { output.WriteRawTag(8); output.WriteUInt32(StmtId); @@ -244,38 +268,46 @@ public void WriteTo(pb::CodedOutputStream output) { if (_unknownFields != null) { _unknownFields.WriteTo(output); } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { - if (HasStmtId) { + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) + { + if (HasStmtId) + { output.WriteRawTag(8); output.WriteUInt32(StmtId); } - if (stmt_ != null) { + if (stmt_ != null) + { output.WriteRawTag(18); output.WriteMessage(Stmt); } - if (_unknownFields != null) { + if (_unknownFields != null) + { _unknownFields.WriteTo(ref output); } } - #endif +#endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public int CalculateSize() { + public int CalculateSize() + { int size = 0; - if (HasStmtId) { + if (HasStmtId) + { size += 1 + pb::CodedOutputStream.ComputeUInt32Size(StmtId); } - if (stmt_ != null) { + if (stmt_ != null) + { size += 1 + pb::CodedOutputStream.ComputeMessageSize(Stmt); } - if (_unknownFields != null) { + if (_unknownFields != null) + { size += _unknownFields.CalculateSize(); } return size; @@ -283,15 +315,20 @@ public int CalculateSize() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(Prepare other) { - if (other == null) { + public void MergeFrom(Prepare other) + { + if (other == null) + { return; } - if (other.HasStmtId) { + if (other.HasStmtId) + { StmtId = other.StmtId; } - if (other.stmt_ != null) { - if (stmt_ == null) { + if (other.stmt_ != null) + { + if (stmt_ == null) + { Stmt = new global::Mysqlx.Prepare.Prepare.Types.OneOfMessage(); } Stmt.MergeFrom(other.Stmt); @@ -301,10 +338,11 @@ public void MergeFrom(Prepare other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(pb::CodedInputStream input) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void MergeFrom(pb::CodedInputStream input) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE input.ReadRawMessage(this); - #else +#else uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { @@ -324,44 +362,52 @@ public void MergeFrom(pb::CodedInputStream input) { } } } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) + { uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { + while ((tag = input.ReadTag()) != 0) + { + switch (tag) + { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; - case 8: { - StmtId = input.ReadUInt32(); - break; - } - case 18: { - if (stmt_ == null) { - Stmt = new global::Mysqlx.Prepare.Prepare.Types.OneOfMessage(); + case 8: + { + StmtId = input.ReadUInt32(); + break; + } + case 18: + { + if (stmt_ == null) + { + Stmt = new global::Mysqlx.Prepare.Prepare.Types.OneOfMessage(); + } + input.ReadMessage(Stmt); + break; } - input.ReadMessage(Stmt); - break; - } } } } - #endif +#endif #region Nested types /// Container for nested types declared in the Prepare message type. [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static partial class Types { + public static partial class Types + { + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] public sealed partial class OneOfMessage : pb::IMessage - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE , pb::IBufferMessage - #endif +#endif { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new OneOfMessage()); private pb::UnknownFieldSet _unknownFields; @@ -372,19 +418,22 @@ public sealed partial class OneOfMessage : pb::IMessage [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static pbr::MessageDescriptor Descriptor { + public static pbr::MessageDescriptor Descriptor + { get { return global::Mysqlx.Prepare.Prepare.Descriptor.NestedTypes[0]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - pbr::MessageDescriptor pb::IMessage.Descriptor { + pbr::MessageDescriptor pb::IMessage.Descriptor + { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public OneOfMessage() { + public OneOfMessage() + { OnConstruction(); } @@ -392,7 +441,8 @@ public OneOfMessage() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public OneOfMessage(OneOfMessage other) : this() { + public OneOfMessage(OneOfMessage other) : this() + { _hasBits0 = other._hasBits0; type_ = other.type_; find_ = other.find_ != null ? other.find_.Clone() : null; @@ -405,7 +455,8 @@ public OneOfMessage(OneOfMessage other) : this() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public OneOfMessage Clone() { + public OneOfMessage Clone() + { return new OneOfMessage(this); } @@ -416,9 +467,11 @@ public OneOfMessage Clone() { private global::Mysqlx.Prepare.Prepare.Types.OneOfMessage.Types.Type type_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public global::Mysqlx.Prepare.Prepare.Types.OneOfMessage.Types.Type Type { + public global::Mysqlx.Prepare.Prepare.Types.OneOfMessage.Types.Type Type + { get { if ((_hasBits0 & 1) != 0) { return type_; } else { return TypeDefaultValue; } } - set { + set + { _hasBits0 |= 1; type_ = value; } @@ -426,13 +479,15 @@ public OneOfMessage Clone() { /// Gets whether the "type" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasType { + public bool HasType + { get { return (_hasBits0 & 1) != 0; } } /// Clears the value of the "type" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearType() { + public void ClearType() + { _hasBits0 &= ~1; } @@ -441,9 +496,11 @@ public void ClearType() { private global::Mysqlx.Crud.Find find_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public global::Mysqlx.Crud.Find Find { + public global::Mysqlx.Crud.Find Find + { get { return find_; } - set { + set + { find_ = value; } } @@ -453,9 +510,11 @@ public void ClearType() { private global::Mysqlx.Crud.Insert insert_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public global::Mysqlx.Crud.Insert Insert { + public global::Mysqlx.Crud.Insert Insert + { get { return insert_; } - set { + set + { insert_ = value; } } @@ -465,9 +524,11 @@ public void ClearType() { private global::Mysqlx.Crud.Update update_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public global::Mysqlx.Crud.Update Update { + public global::Mysqlx.Crud.Update Update + { get { return update_; } - set { + set + { update_ = value; } } @@ -477,9 +538,11 @@ public void ClearType() { private global::Mysqlx.Crud.Delete delete_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public global::Mysqlx.Crud.Delete Delete { + public global::Mysqlx.Crud.Delete Delete + { get { return delete_; } - set { + set + { delete_ = value; } } @@ -489,26 +552,32 @@ public void ClearType() { private global::Mysqlx.Sql.StmtExecute stmtExecute_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public global::Mysqlx.Sql.StmtExecute StmtExecute { + public global::Mysqlx.Sql.StmtExecute StmtExecute + { get { return stmtExecute_; } - set { + set + { stmtExecute_ = value; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override bool Equals(object other) { + public override bool Equals(object other) + { return Equals(other as OneOfMessage); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool Equals(OneOfMessage other) { - if (ReferenceEquals(other, null)) { + public bool Equals(OneOfMessage other) + { + if (ReferenceEquals(other, null)) + { return false; } - if (ReferenceEquals(other, this)) { + if (ReferenceEquals(other, this)) + { return true; } if (Type != other.Type) return false; @@ -522,7 +591,8 @@ public bool Equals(OneOfMessage other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override int GetHashCode() { + public override int GetHashCode() + { int hash = 1; if (HasType) hash ^= Type.GetHashCode(); if (find_ != null) hash ^= Find.GetHashCode(); @@ -530,7 +600,8 @@ public override int GetHashCode() { if (update_ != null) hash ^= Update.GetHashCode(); if (delete_ != null) hash ^= Delete.GetHashCode(); if (stmtExecute_ != null) hash ^= StmtExecute.GetHashCode(); - if (_unknownFields != null) { + if (_unknownFields != null) + { hash ^= _unknownFields.GetHashCode(); } return hash; @@ -538,16 +609,18 @@ public override int GetHashCode() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override string ToString() { + public override string ToString() + { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void WriteTo(pb::CodedOutputStream output) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void WriteTo(pb::CodedOutputStream output) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE output.WriteRawMessage(this); - #else +#else if (HasType) { output.WriteRawTag(8); output.WriteEnum((int) Type); @@ -575,66 +648,82 @@ public void WriteTo(pb::CodedOutputStream output) { if (_unknownFields != null) { _unknownFields.WriteTo(output); } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { - if (HasType) { + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) + { + if (HasType) + { output.WriteRawTag(8); - output.WriteEnum((int) Type); + output.WriteEnum((int)Type); } - if (find_ != null) { + if (find_ != null) + { output.WriteRawTag(18); output.WriteMessage(Find); } - if (insert_ != null) { + if (insert_ != null) + { output.WriteRawTag(26); output.WriteMessage(Insert); } - if (update_ != null) { + if (update_ != null) + { output.WriteRawTag(34); output.WriteMessage(Update); } - if (delete_ != null) { + if (delete_ != null) + { output.WriteRawTag(42); output.WriteMessage(Delete); } - if (stmtExecute_ != null) { + if (stmtExecute_ != null) + { output.WriteRawTag(50); output.WriteMessage(StmtExecute); } - if (_unknownFields != null) { + if (_unknownFields != null) + { _unknownFields.WriteTo(ref output); } } - #endif +#endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public int CalculateSize() { + public int CalculateSize() + { int size = 0; - if (HasType) { - size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Type); + if (HasType) + { + size += 1 + pb::CodedOutputStream.ComputeEnumSize((int)Type); } - if (find_ != null) { + if (find_ != null) + { size += 1 + pb::CodedOutputStream.ComputeMessageSize(Find); } - if (insert_ != null) { + if (insert_ != null) + { size += 1 + pb::CodedOutputStream.ComputeMessageSize(Insert); } - if (update_ != null) { + if (update_ != null) + { size += 1 + pb::CodedOutputStream.ComputeMessageSize(Update); } - if (delete_ != null) { + if (delete_ != null) + { size += 1 + pb::CodedOutputStream.ComputeMessageSize(Delete); } - if (stmtExecute_ != null) { + if (stmtExecute_ != null) + { size += 1 + pb::CodedOutputStream.ComputeMessageSize(StmtExecute); } - if (_unknownFields != null) { + if (_unknownFields != null) + { size += _unknownFields.CalculateSize(); } return size; @@ -642,39 +731,52 @@ public int CalculateSize() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(OneOfMessage other) { - if (other == null) { + public void MergeFrom(OneOfMessage other) + { + if (other == null) + { return; } - if (other.HasType) { + if (other.HasType) + { Type = other.Type; } - if (other.find_ != null) { - if (find_ == null) { + if (other.find_ != null) + { + if (find_ == null) + { Find = new global::Mysqlx.Crud.Find(); } Find.MergeFrom(other.Find); } - if (other.insert_ != null) { - if (insert_ == null) { + if (other.insert_ != null) + { + if (insert_ == null) + { Insert = new global::Mysqlx.Crud.Insert(); } Insert.MergeFrom(other.Insert); } - if (other.update_ != null) { - if (update_ == null) { + if (other.update_ != null) + { + if (update_ == null) + { Update = new global::Mysqlx.Crud.Update(); } Update.MergeFrom(other.Update); } - if (other.delete_ != null) { - if (delete_ == null) { + if (other.delete_ != null) + { + if (delete_ == null) + { Delete = new global::Mysqlx.Crud.Delete(); } Delete.MergeFrom(other.Delete); } - if (other.stmtExecute_ != null) { - if (stmtExecute_ == null) { + if (other.stmtExecute_ != null) + { + if (stmtExecute_ == null) + { StmtExecute = new global::Mysqlx.Sql.StmtExecute(); } StmtExecute.MergeFrom(other.StmtExecute); @@ -684,10 +786,11 @@ public void MergeFrom(OneOfMessage other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(pb::CodedInputStream input) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void MergeFrom(pb::CodedInputStream input) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE input.ReadRawMessage(this); - #else +#else uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { @@ -735,73 +838,89 @@ public void MergeFrom(pb::CodedInputStream input) { } } } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) + { uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { + while ((tag = input.ReadTag()) != 0) + { + switch (tag) + { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; - case 8: { - Type = (global::Mysqlx.Prepare.Prepare.Types.OneOfMessage.Types.Type) input.ReadEnum(); - break; - } - case 18: { - if (find_ == null) { - Find = new global::Mysqlx.Crud.Find(); + case 8: + { + Type = (global::Mysqlx.Prepare.Prepare.Types.OneOfMessage.Types.Type)input.ReadEnum(); + break; } - input.ReadMessage(Find); - break; - } - case 26: { - if (insert_ == null) { - Insert = new global::Mysqlx.Crud.Insert(); + case 18: + { + if (find_ == null) + { + Find = new global::Mysqlx.Crud.Find(); + } + input.ReadMessage(Find); + break; } - input.ReadMessage(Insert); - break; - } - case 34: { - if (update_ == null) { - Update = new global::Mysqlx.Crud.Update(); + case 26: + { + if (insert_ == null) + { + Insert = new global::Mysqlx.Crud.Insert(); + } + input.ReadMessage(Insert); + break; } - input.ReadMessage(Update); - break; - } - case 42: { - if (delete_ == null) { - Delete = new global::Mysqlx.Crud.Delete(); + case 34: + { + if (update_ == null) + { + Update = new global::Mysqlx.Crud.Update(); + } + input.ReadMessage(Update); + break; } - input.ReadMessage(Delete); - break; - } - case 50: { - if (stmtExecute_ == null) { - StmtExecute = new global::Mysqlx.Sql.StmtExecute(); + case 42: + { + if (delete_ == null) + { + Delete = new global::Mysqlx.Crud.Delete(); + } + input.ReadMessage(Delete); + break; + } + case 50: + { + if (stmtExecute_ == null) + { + StmtExecute = new global::Mysqlx.Sql.StmtExecute(); + } + input.ReadMessage(StmtExecute); + break; } - input.ReadMessage(StmtExecute); - break; - } } } } - #endif +#endif #region Nested types /// Container for nested types declared in the OneOfMessage message type. [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static partial class Types { + public static partial class Types + { /// /// Determine which of optional fields was set by the client /// (Workaround for missing "oneof" keyword in pb2.5) /// - public enum Type { + public enum Type + { [pbr::OriginalName("FIND")] Find = 0, [pbr::OriginalName("INSERT")] Insert = 1, [pbr::OriginalName("UPDATE")] Update = 2, @@ -835,10 +954,11 @@ public enum Type { ///@enduml ///@returns @ref Mysqlx::Ok /// - internal sealed partial class Execute : pb::IMessage - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] + public sealed partial class Execute : pb::IMessage +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE , pb::IBufferMessage - #endif +#endif { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Execute()); private pb::UnknownFieldSet _unknownFields; @@ -849,19 +969,22 @@ internal sealed partial class Execute : pb::IMessage [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static pbr::MessageDescriptor Descriptor { + public static pbr::MessageDescriptor Descriptor + { get { return global::Mysqlx.Prepare.MysqlxPrepareReflection.Descriptor.MessageTypes[1]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - pbr::MessageDescriptor pb::IMessage.Descriptor { + pbr::MessageDescriptor pb::IMessage.Descriptor + { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Execute() { + public Execute() + { OnConstruction(); } @@ -869,7 +992,8 @@ public Execute() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Execute(Execute other) : this() { + public Execute(Execute other) : this() + { _hasBits0 = other._hasBits0; stmtId_ = other.stmtId_; args_ = other.args_.Clone(); @@ -879,7 +1003,8 @@ public Execute(Execute other) : this() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Execute Clone() { + public Execute Clone() + { return new Execute(this); } @@ -893,9 +1018,11 @@ public Execute Clone() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public uint StmtId { + public uint StmtId + { get { if ((_hasBits0 & 1) != 0) { return stmtId_; } else { return StmtIdDefaultValue; } } - set { + set + { _hasBits0 |= 1; stmtId_ = value; } @@ -903,13 +1030,15 @@ public uint StmtId { /// Gets whether the "stmt_id" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasStmtId { + public bool HasStmtId + { get { return (_hasBits0 & 1) != 0; } } /// Clears the value of the "stmt_id" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearStmtId() { + public void ClearStmtId() + { _hasBits0 &= ~1; } @@ -923,7 +1052,8 @@ public void ClearStmtId() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public pbc::RepeatedField Args { + public pbc::RepeatedField Args + { get { return args_; } } @@ -938,9 +1068,11 @@ public void ClearStmtId() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool CompactMetadata { + public bool CompactMetadata + { get { if ((_hasBits0 & 2) != 0) { return compactMetadata_; } else { return CompactMetadataDefaultValue; } } - set { + set + { _hasBits0 |= 2; compactMetadata_ = value; } @@ -948,45 +1080,53 @@ public bool CompactMetadata { /// Gets whether the "compact_metadata" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasCompactMetadata { + public bool HasCompactMetadata + { get { return (_hasBits0 & 2) != 0; } } /// Clears the value of the "compact_metadata" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearCompactMetadata() { + public void ClearCompactMetadata() + { _hasBits0 &= ~2; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override bool Equals(object other) { + public override bool Equals(object other) + { return Equals(other as Execute); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool Equals(Execute other) { - if (ReferenceEquals(other, null)) { + public bool Equals(Execute other) + { + if (ReferenceEquals(other, null)) + { return false; } - if (ReferenceEquals(other, this)) { + if (ReferenceEquals(other, this)) + { return true; } if (StmtId != other.StmtId) return false; - if(!args_.Equals(other.args_)) return false; + if (!args_.Equals(other.args_)) return false; if (CompactMetadata != other.CompactMetadata) return false; return Equals(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override int GetHashCode() { + public override int GetHashCode() + { int hash = 1; if (HasStmtId) hash ^= StmtId.GetHashCode(); hash ^= args_.GetHashCode(); if (HasCompactMetadata) hash ^= CompactMetadata.GetHashCode(); - if (_unknownFields != null) { + if (_unknownFields != null) + { hash ^= _unknownFields.GetHashCode(); } return hash; @@ -994,16 +1134,18 @@ public override int GetHashCode() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override string ToString() { + public override string ToString() + { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void WriteTo(pb::CodedOutputStream output) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void WriteTo(pb::CodedOutputStream output) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE output.WriteRawMessage(this); - #else +#else if (HasStmtId) { output.WriteRawTag(8); output.WriteUInt32(StmtId); @@ -1016,40 +1158,48 @@ public void WriteTo(pb::CodedOutputStream output) { if (_unknownFields != null) { _unknownFields.WriteTo(output); } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { - if (HasStmtId) { + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) + { + if (HasStmtId) + { output.WriteRawTag(8); output.WriteUInt32(StmtId); } args_.WriteTo(ref output, _repeated_args_codec); - if (HasCompactMetadata) { + if (HasCompactMetadata) + { output.WriteRawTag(24); output.WriteBool(CompactMetadata); } - if (_unknownFields != null) { + if (_unknownFields != null) + { _unknownFields.WriteTo(ref output); } } - #endif +#endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public int CalculateSize() { + public int CalculateSize() + { int size = 0; - if (HasStmtId) { + if (HasStmtId) + { size += 1 + pb::CodedOutputStream.ComputeUInt32Size(StmtId); } size += args_.CalculateSize(_repeated_args_codec); - if (HasCompactMetadata) { + if (HasCompactMetadata) + { size += 1 + 1; } - if (_unknownFields != null) { + if (_unknownFields != null) + { size += _unknownFields.CalculateSize(); } return size; @@ -1057,15 +1207,19 @@ public int CalculateSize() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(Execute other) { - if (other == null) { + public void MergeFrom(Execute other) + { + if (other == null) + { return; } - if (other.HasStmtId) { + if (other.HasStmtId) + { StmtId = other.StmtId; } args_.Add(other.args_); - if (other.HasCompactMetadata) { + if (other.HasCompactMetadata) + { CompactMetadata = other.CompactMetadata; } _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); @@ -1073,10 +1227,11 @@ public void MergeFrom(Execute other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(pb::CodedInputStream input) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void MergeFrom(pb::CodedInputStream input) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE input.ReadRawMessage(this); - #else +#else uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { @@ -1097,35 +1252,41 @@ public void MergeFrom(pb::CodedInputStream input) { } } } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) + { uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { + while ((tag = input.ReadTag()) != 0) + { + switch (tag) + { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; - case 8: { - StmtId = input.ReadUInt32(); - break; - } - case 18: { - args_.AddEntriesFrom(ref input, _repeated_args_codec); - break; - } - case 24: { - CompactMetadata = input.ReadBool(); - break; - } + case 8: + { + StmtId = input.ReadUInt32(); + break; + } + case 18: + { + args_.AddEntriesFrom(ref input, _repeated_args_codec); + break; + } + case 24: + { + CompactMetadata = input.ReadBool(); + break; + } } } } - #endif +#endif } @@ -1144,10 +1305,11 @@ public void MergeFrom(pb::CodedInputStream input) { /// ///@returns @ref Mysqlx::Ok or @ref Mysqlx::Error /// - internal sealed partial class Deallocate : pb::IMessage - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] + public sealed partial class Deallocate : pb::IMessage +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE , pb::IBufferMessage - #endif +#endif { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Deallocate()); private pb::UnknownFieldSet _unknownFields; @@ -1158,19 +1320,22 @@ internal sealed partial class Deallocate : pb::IMessage [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static pbr::MessageDescriptor Descriptor { + public static pbr::MessageDescriptor Descriptor + { get { return global::Mysqlx.Prepare.MysqlxPrepareReflection.Descriptor.MessageTypes[2]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - pbr::MessageDescriptor pb::IMessage.Descriptor { + pbr::MessageDescriptor pb::IMessage.Descriptor + { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Deallocate() { + public Deallocate() + { OnConstruction(); } @@ -1178,7 +1343,8 @@ public Deallocate() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Deallocate(Deallocate other) : this() { + public Deallocate(Deallocate other) : this() + { _hasBits0 = other._hasBits0; stmtId_ = other.stmtId_; _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); @@ -1186,7 +1352,8 @@ public Deallocate(Deallocate other) : this() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Deallocate Clone() { + public Deallocate Clone() + { return new Deallocate(this); } @@ -1200,9 +1367,11 @@ public Deallocate Clone() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public uint StmtId { + public uint StmtId + { get { if ((_hasBits0 & 1) != 0) { return stmtId_; } else { return StmtIdDefaultValue; } } - set { + set + { _hasBits0 |= 1; stmtId_ = value; } @@ -1210,29 +1379,35 @@ public uint StmtId { /// Gets whether the "stmt_id" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasStmtId { + public bool HasStmtId + { get { return (_hasBits0 & 1) != 0; } } /// Clears the value of the "stmt_id" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearStmtId() { + public void ClearStmtId() + { _hasBits0 &= ~1; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override bool Equals(object other) { + public override bool Equals(object other) + { return Equals(other as Deallocate); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool Equals(Deallocate other) { - if (ReferenceEquals(other, null)) { + public bool Equals(Deallocate other) + { + if (ReferenceEquals(other, null)) + { return false; } - if (ReferenceEquals(other, this)) { + if (ReferenceEquals(other, this)) + { return true; } if (StmtId != other.StmtId) return false; @@ -1241,10 +1416,12 @@ public bool Equals(Deallocate other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override int GetHashCode() { + public override int GetHashCode() + { int hash = 1; if (HasStmtId) hash ^= StmtId.GetHashCode(); - if (_unknownFields != null) { + if (_unknownFields != null) + { hash ^= _unknownFields.GetHashCode(); } return hash; @@ -1252,16 +1429,18 @@ public override int GetHashCode() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override string ToString() { + public override string ToString() + { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void WriteTo(pb::CodedOutputStream output) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void WriteTo(pb::CodedOutputStream output) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE output.WriteRawMessage(this); - #else +#else if (HasStmtId) { output.WriteRawTag(8); output.WriteUInt32(StmtId); @@ -1269,31 +1448,37 @@ public void WriteTo(pb::CodedOutputStream output) { if (_unknownFields != null) { _unknownFields.WriteTo(output); } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { - if (HasStmtId) { + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) + { + if (HasStmtId) + { output.WriteRawTag(8); output.WriteUInt32(StmtId); } - if (_unknownFields != null) { + if (_unknownFields != null) + { _unknownFields.WriteTo(ref output); } } - #endif +#endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public int CalculateSize() { + public int CalculateSize() + { int size = 0; - if (HasStmtId) { + if (HasStmtId) + { size += 1 + pb::CodedOutputStream.ComputeUInt32Size(StmtId); } - if (_unknownFields != null) { + if (_unknownFields != null) + { size += _unknownFields.CalculateSize(); } return size; @@ -1301,11 +1486,14 @@ public int CalculateSize() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(Deallocate other) { - if (other == null) { + public void MergeFrom(Deallocate other) + { + if (other == null) + { return; } - if (other.HasStmtId) { + if (other.HasStmtId) + { StmtId = other.StmtId; } _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); @@ -1313,10 +1501,11 @@ public void MergeFrom(Deallocate other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(pb::CodedInputStream input) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void MergeFrom(pb::CodedInputStream input) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE input.ReadRawMessage(this); - #else +#else uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { @@ -1329,27 +1518,31 @@ public void MergeFrom(pb::CodedInputStream input) { } } } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) + { uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { + while ((tag = input.ReadTag()) != 0) + { + switch (tag) + { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; - case 8: { - StmtId = input.ReadUInt32(); - break; - } + case 8: + { + StmtId = input.ReadUInt32(); + break; + } } } } - #endif +#endif } diff --git a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxResultset.cs b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxResultset.cs index c80e9d959..bcbd7bd38 100644 --- a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxResultset.cs +++ b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxResultset.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2022, 2023, Oracle and/or its affiliates. +// Copyright (c) 2023, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as @@ -7,7 +7,7 @@ // This program is also distributed with certain software (including // but not limited to OpenSSL) that is licensed under separate terms, // as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an +// documentation. The authors of MySQL hereby grant you an // additional permission to link the program and your derivative works // with the separately licensed software that they have included with // MySQL. @@ -37,19 +37,23 @@ using pbc = global::Google.Protobuf.Collections; using pbr = global::Google.Protobuf.Reflection; using scg = global::System.Collections.Generic; -namespace Mysqlx.Resultset { +namespace Mysqlx.Resultset +{ /// Holder for reflection information generated from mysqlx_resultset.proto - internal static partial class MysqlxResultsetReflection { + public static partial class MysqlxResultsetReflection + { #region Descriptor /// File descriptor for mysqlx_resultset.proto - public static pbr::FileDescriptor Descriptor { + public static pbr::FileDescriptor Descriptor + { get { return descriptor; } } private static pbr::FileDescriptor descriptor; - static MysqlxResultsetReflection() { + static MysqlxResultsetReflection() + { byte[] descriptorData = global::System.Convert.FromBase64String( string.Concat( "ChZteXNxbHhfcmVzdWx0c2V0LnByb3RvEhBNeXNxbHguUmVzdWx0c2V0Ggxt", @@ -71,7 +75,7 @@ static MysqlxResultsetReflection() { "Chdjb20ubXlzcWwuY2oueC5wcm90b2J1Zg==")); descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { global::Mysqlx.MysqlxReflection.Descriptor, }, - new pbr::GeneratedClrTypeInfo(new[] {typeof(global::Mysqlx.Resultset.ContentType_BYTES), typeof(global::Mysqlx.Resultset.ContentType_DATETIME), }, null, new pbr::GeneratedClrTypeInfo[] { + new pbr::GeneratedClrTypeInfo(new[] { typeof(global::Mysqlx.Resultset.ContentType_BYTES), typeof(global::Mysqlx.Resultset.ContentType_DATETIME), }, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Mysqlx.Resultset.FetchDoneMoreOutParams), global::Mysqlx.Resultset.FetchDoneMoreOutParams.Parser, null, null, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Mysqlx.Resultset.FetchDoneMoreResultsets), global::Mysqlx.Resultset.FetchDoneMoreResultsets.Parser, null, null, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Mysqlx.Resultset.FetchDone), global::Mysqlx.Resultset.FetchDone.Parser, null, null, null, null, null), @@ -101,7 +105,8 @@ static MysqlxResultsetReflection() { ///like image manipulation, seeking into complex types in BLOBs, ... more ///types will be added. /// - internal enum ContentType_BYTES { + public enum ContentType_BYTES + { [pbr::OriginalName("GEOMETRY")] Geometry = 1, [pbr::OriginalName("JSON")] Json = 2, [pbr::OriginalName("XML")] Xml = 3, @@ -116,7 +121,8 @@ internal enum ContentType_BYTES { ///|DATE |0x0001 |DATETIME contains only date part | ///|DATETIME |0x0002 |DATETIME contains both date and time parts | /// - internal enum ContentType_DATETIME { + public enum ContentType_DATETIME + { [pbr::OriginalName("DATE")] Date = 1, [pbr::OriginalName("DATETIME")] Datetime = 2, } @@ -128,10 +134,11 @@ internal enum ContentType_DATETIME { ///* ///Resultsets are finished, OUT paramset is next: /// - internal sealed partial class FetchDoneMoreOutParams : pb::IMessage - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] + public sealed partial class FetchDoneMoreOutParams : pb::IMessage +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE , pb::IBufferMessage - #endif +#endif { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new FetchDoneMoreOutParams()); private pb::UnknownFieldSet _unknownFields; @@ -141,19 +148,22 @@ internal sealed partial class FetchDoneMoreOutParams : pb::IMessage - internal sealed partial class FetchDoneMoreResultsets : pb::IMessage - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] + public sealed partial class FetchDoneMoreResultsets : pb::IMessage +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE , pb::IBufferMessage - #endif +#endif { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new FetchDoneMoreResultsets()); private pb::UnknownFieldSet _unknownFields; @@ -297,19 +328,22 @@ internal sealed partial class FetchDoneMoreResultsets : pb::IMessage - internal sealed partial class FetchDone : pb::IMessage - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] + public sealed partial class FetchDone : pb::IMessage +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE , pb::IBufferMessage - #endif +#endif { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new FetchDone()); private pb::UnknownFieldSet _unknownFields; @@ -453,19 +508,22 @@ internal sealed partial class FetchDone : pb::IMessage [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static pbr::MessageDescriptor Descriptor { + public static pbr::MessageDescriptor Descriptor + { get { return global::Mysqlx.Resultset.MysqlxResultsetReflection.Descriptor.MessageTypes[2]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - pbr::MessageDescriptor pb::IMessage.Descriptor { + pbr::MessageDescriptor pb::IMessage.Descriptor + { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public FetchDone() { + public FetchDone() + { OnConstruction(); } @@ -473,29 +531,35 @@ public FetchDone() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public FetchDone(FetchDone other) : this() { + public FetchDone(FetchDone other) : this() + { _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public FetchDone Clone() { + public FetchDone Clone() + { return new FetchDone(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override bool Equals(object other) { + public override bool Equals(object other) + { return Equals(other as FetchDone); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool Equals(FetchDone other) { - if (ReferenceEquals(other, null)) { + public bool Equals(FetchDone other) + { + if (ReferenceEquals(other, null)) + { return false; } - if (ReferenceEquals(other, this)) { + if (ReferenceEquals(other, this)) + { return true; } return Equals(_unknownFields, other._unknownFields); @@ -503,9 +567,11 @@ public bool Equals(FetchDone other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override int GetHashCode() { + public override int GetHashCode() + { int hash = 1; - if (_unknownFields != null) { + if (_unknownFields != null) + { hash ^= _unknownFields.GetHashCode(); } return hash; @@ -513,37 +579,43 @@ public override int GetHashCode() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override string ToString() { + public override string ToString() + { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void WriteTo(pb::CodedOutputStream output) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void WriteTo(pb::CodedOutputStream output) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE output.WriteRawMessage(this); - #else +#else if (_unknownFields != null) { _unknownFields.WriteTo(output); } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { - if (_unknownFields != null) { + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) + { + if (_unknownFields != null) + { _unknownFields.WriteTo(ref output); } } - #endif +#endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public int CalculateSize() { + public int CalculateSize() + { int size = 0; - if (_unknownFields != null) { + if (_unknownFields != null) + { size += _unknownFields.CalculateSize(); } return size; @@ -551,8 +623,10 @@ public int CalculateSize() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(FetchDone other) { - if (other == null) { + public void MergeFrom(FetchDone other) + { + if (other == null) + { return; } _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); @@ -560,10 +634,11 @@ public void MergeFrom(FetchDone other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(pb::CodedInputStream input) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void MergeFrom(pb::CodedInputStream input) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE input.ReadRawMessage(this); - #else +#else uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { @@ -572,23 +647,26 @@ public void MergeFrom(pb::CodedInputStream input) { break; } } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) + { uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { + while ((tag = input.ReadTag()) != 0) + { + switch (tag) + { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; } } } - #endif +#endif } @@ -596,10 +674,11 @@ public void MergeFrom(pb::CodedInputStream input) { ///* ///Cursor is opened; still, the execution of PrepFetch or PrepExecute ended /// - internal sealed partial class FetchSuspended : pb::IMessage - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] + public sealed partial class FetchSuspended : pb::IMessage +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE , pb::IBufferMessage - #endif +#endif { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new FetchSuspended()); private pb::UnknownFieldSet _unknownFields; @@ -609,19 +688,22 @@ internal sealed partial class FetchSuspended : pb::IMessage [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static pbr::MessageDescriptor Descriptor { + public static pbr::MessageDescriptor Descriptor + { get { return global::Mysqlx.Resultset.MysqlxResultsetReflection.Descriptor.MessageTypes[3]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - pbr::MessageDescriptor pb::IMessage.Descriptor { + pbr::MessageDescriptor pb::IMessage.Descriptor + { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public FetchSuspended() { + public FetchSuspended() + { OnConstruction(); } @@ -629,29 +711,35 @@ public FetchSuspended() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public FetchSuspended(FetchSuspended other) : this() { + public FetchSuspended(FetchSuspended other) : this() + { _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public FetchSuspended Clone() { + public FetchSuspended Clone() + { return new FetchSuspended(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override bool Equals(object other) { + public override bool Equals(object other) + { return Equals(other as FetchSuspended); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool Equals(FetchSuspended other) { - if (ReferenceEquals(other, null)) { + public bool Equals(FetchSuspended other) + { + if (ReferenceEquals(other, null)) + { return false; } - if (ReferenceEquals(other, this)) { + if (ReferenceEquals(other, this)) + { return true; } return Equals(_unknownFields, other._unknownFields); @@ -659,9 +747,11 @@ public bool Equals(FetchSuspended other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override int GetHashCode() { + public override int GetHashCode() + { int hash = 1; - if (_unknownFields != null) { + if (_unknownFields != null) + { hash ^= _unknownFields.GetHashCode(); } return hash; @@ -669,37 +759,43 @@ public override int GetHashCode() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override string ToString() { + public override string ToString() + { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void WriteTo(pb::CodedOutputStream output) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void WriteTo(pb::CodedOutputStream output) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE output.WriteRawMessage(this); - #else +#else if (_unknownFields != null) { _unknownFields.WriteTo(output); } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { - if (_unknownFields != null) { + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) + { + if (_unknownFields != null) + { _unknownFields.WriteTo(ref output); } } - #endif +#endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public int CalculateSize() { + public int CalculateSize() + { int size = 0; - if (_unknownFields != null) { + if (_unknownFields != null) + { size += _unknownFields.CalculateSize(); } return size; @@ -707,8 +803,10 @@ public int CalculateSize() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(FetchSuspended other) { - if (other == null) { + public void MergeFrom(FetchSuspended other) + { + if (other == null) + { return; } _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); @@ -716,10 +814,11 @@ public void MergeFrom(FetchSuspended other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(pb::CodedInputStream input) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void MergeFrom(pb::CodedInputStream input) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE input.ReadRawMessage(this); - #else +#else uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { @@ -728,23 +827,26 @@ public void MergeFrom(pb::CodedInputStream input) { break; } } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) + { uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { + while ((tag = input.ReadTag()) != 0) + { + switch (tag) + { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; } } } - #endif +#endif } @@ -1075,10 +1177,11 @@ public void MergeFrom(pb::CodedInputStream input) { /// ///- ``[8] 0x03 F O O 0x03 B A R`` - a set with 2 items: FOO,BAR /// - internal sealed partial class ColumnMetaData : pb::IMessage - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] + public sealed partial class ColumnMetaData : pb::IMessage +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE , pb::IBufferMessage - #endif +#endif { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ColumnMetaData()); private pb::UnknownFieldSet _unknownFields; @@ -1089,19 +1192,22 @@ internal sealed partial class ColumnMetaData : pb::IMessage [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static pbr::MessageDescriptor Descriptor { + public static pbr::MessageDescriptor Descriptor + { get { return global::Mysqlx.Resultset.MysqlxResultsetReflection.Descriptor.MessageTypes[4]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - pbr::MessageDescriptor pb::IMessage.Descriptor { + pbr::MessageDescriptor pb::IMessage.Descriptor + { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public ColumnMetaData() { + public ColumnMetaData() + { OnConstruction(); } @@ -1109,7 +1215,8 @@ public ColumnMetaData() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public ColumnMetaData(ColumnMetaData other) : this() { + public ColumnMetaData(ColumnMetaData other) : this() + { _hasBits0 = other._hasBits0; type_ = other.type_; name_ = other.name_; @@ -1128,7 +1235,8 @@ public ColumnMetaData(ColumnMetaData other) : this() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public ColumnMetaData Clone() { + public ColumnMetaData Clone() + { return new ColumnMetaData(this); } @@ -1142,9 +1250,11 @@ public ColumnMetaData Clone() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public global::Mysqlx.Resultset.ColumnMetaData.Types.FieldType Type { + public global::Mysqlx.Resultset.ColumnMetaData.Types.FieldType Type + { get { if ((_hasBits0 & 1) != 0) { return type_; } else { return TypeDefaultValue; } } - set { + set + { _hasBits0 |= 1; type_ = value; } @@ -1152,13 +1262,15 @@ public ColumnMetaData Clone() { /// Gets whether the "type" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasType { + public bool HasType + { get { return (_hasBits0 & 1) != 0; } } /// Clears the value of the "type" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearType() { + public void ClearType() + { _hasBits0 &= ~1; } @@ -1172,22 +1284,26 @@ public void ClearType() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public pb::ByteString Name { + public pb::ByteString Name + { get { return name_ ?? NameDefaultValue; } - set { + set + { name_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } /// Gets whether the "name" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasName { + public bool HasName + { get { return name_ != null; } } /// Clears the value of the "name" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearName() { + public void ClearName() + { name_ = null; } @@ -1201,22 +1317,26 @@ public void ClearName() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public pb::ByteString OriginalName { + public pb::ByteString OriginalName + { get { return originalName_ ?? OriginalNameDefaultValue; } - set { + set + { originalName_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } /// Gets whether the "original_name" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasOriginalName { + public bool HasOriginalName + { get { return originalName_ != null; } } /// Clears the value of the "original_name" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearOriginalName() { + public void ClearOriginalName() + { originalName_ = null; } @@ -1230,22 +1350,26 @@ public void ClearOriginalName() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public pb::ByteString Table { + public pb::ByteString Table + { get { return table_ ?? TableDefaultValue; } - set { + set + { table_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } /// Gets whether the "table" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasTable { + public bool HasTable + { get { return table_ != null; } } /// Clears the value of the "table" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearTable() { + public void ClearTable() + { table_ = null; } @@ -1259,22 +1383,26 @@ public void ClearTable() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public pb::ByteString OriginalTable { + public pb::ByteString OriginalTable + { get { return originalTable_ ?? OriginalTableDefaultValue; } - set { + set + { originalTable_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } /// Gets whether the "original_table" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasOriginalTable { + public bool HasOriginalTable + { get { return originalTable_ != null; } } /// Clears the value of the "original_table" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearOriginalTable() { + public void ClearOriginalTable() + { originalTable_ = null; } @@ -1288,22 +1416,26 @@ public void ClearOriginalTable() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public pb::ByteString Schema { + public pb::ByteString Schema + { get { return schema_ ?? SchemaDefaultValue; } - set { + set + { schema_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } /// Gets whether the "schema" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasSchema { + public bool HasSchema + { get { return schema_ != null; } } /// Clears the value of the "schema" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearSchema() { + public void ClearSchema() + { schema_ = null; } @@ -1321,22 +1453,26 @@ public void ClearSchema() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public pb::ByteString Catalog { + public pb::ByteString Catalog + { get { return catalog_ ?? CatalogDefaultValue; } - set { + set + { catalog_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } /// Gets whether the "catalog" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasCatalog { + public bool HasCatalog + { get { return catalog_ != null; } } /// Clears the value of the "catalog" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearCatalog() { + public void ClearCatalog() + { catalog_ = null; } @@ -1347,9 +1483,11 @@ public void ClearCatalog() { private ulong collation_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public ulong Collation { + public ulong Collation + { get { if ((_hasBits0 & 2) != 0) { return collation_; } else { return CollationDefaultValue; } } - set { + set + { _hasBits0 |= 2; collation_ = value; } @@ -1357,13 +1495,15 @@ public ulong Collation { /// Gets whether the "collation" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasCollation { + public bool HasCollation + { get { return (_hasBits0 & 2) != 0; } } /// Clears the value of the "collation" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearCollation() { + public void ClearCollation() + { _hasBits0 &= ~2; } @@ -1378,9 +1518,11 @@ public void ClearCollation() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public uint FractionalDigits { + public uint FractionalDigits + { get { if ((_hasBits0 & 4) != 0) { return fractionalDigits_; } else { return FractionalDigitsDefaultValue; } } - set { + set + { _hasBits0 |= 4; fractionalDigits_ = value; } @@ -1388,13 +1530,15 @@ public uint FractionalDigits { /// Gets whether the "fractional_digits" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasFractionalDigits { + public bool HasFractionalDigits + { get { return (_hasBits0 & 4) != 0; } } /// Clears the value of the "fractional_digits" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearFractionalDigits() { + public void ClearFractionalDigits() + { _hasBits0 &= ~4; } @@ -1408,9 +1552,11 @@ public void ClearFractionalDigits() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public uint Length { + public uint Length + { get { if ((_hasBits0 & 8) != 0) { return length_; } else { return LengthDefaultValue; } } - set { + set + { _hasBits0 |= 8; length_ = value; } @@ -1418,13 +1564,15 @@ public uint Length { /// Gets whether the "length" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasLength { + public bool HasLength + { get { return (_hasBits0 & 8) != 0; } } /// Clears the value of the "length" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearLength() { + public void ClearLength() + { _hasBits0 &= ~8; } @@ -1455,9 +1603,11 @@ public void ClearLength() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public uint Flags { + public uint Flags + { get { if ((_hasBits0 & 16) != 0) { return flags_; } else { return FlagsDefaultValue; } } - set { + set + { _hasBits0 |= 16; flags_ = value; } @@ -1465,13 +1615,15 @@ public uint Flags { /// Gets whether the "flags" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasFlags { + public bool HasFlags + { get { return (_hasBits0 & 16) != 0; } } /// Clears the value of the "flags" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearFlags() { + public void ClearFlags() + { _hasBits0 &= ~16; } @@ -1497,9 +1649,11 @@ public void ClearFlags() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public uint ContentType { + public uint ContentType + { get { if ((_hasBits0 & 32) != 0) { return contentType_; } else { return ContentTypeDefaultValue; } } - set { + set + { _hasBits0 |= 32; contentType_ = value; } @@ -1507,29 +1661,35 @@ public uint ContentType { /// Gets whether the "content_type" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasContentType { + public bool HasContentType + { get { return (_hasBits0 & 32) != 0; } } /// Clears the value of the "content_type" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearContentType() { + public void ClearContentType() + { _hasBits0 &= ~32; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override bool Equals(object other) { + public override bool Equals(object other) + { return Equals(other as ColumnMetaData); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool Equals(ColumnMetaData other) { - if (ReferenceEquals(other, null)) { + public bool Equals(ColumnMetaData other) + { + if (ReferenceEquals(other, null)) + { return false; } - if (ReferenceEquals(other, this)) { + if (ReferenceEquals(other, this)) + { return true; } if (Type != other.Type) return false; @@ -1549,7 +1709,8 @@ public bool Equals(ColumnMetaData other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override int GetHashCode() { + public override int GetHashCode() + { int hash = 1; if (HasType) hash ^= Type.GetHashCode(); if (HasName) hash ^= Name.GetHashCode(); @@ -1563,7 +1724,8 @@ public override int GetHashCode() { if (HasLength) hash ^= Length.GetHashCode(); if (HasFlags) hash ^= Flags.GetHashCode(); if (HasContentType) hash ^= ContentType.GetHashCode(); - if (_unknownFields != null) { + if (_unknownFields != null) + { hash ^= _unknownFields.GetHashCode(); } return hash; @@ -1571,16 +1733,18 @@ public override int GetHashCode() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override string ToString() { + public override string ToString() + { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void WriteTo(pb::CodedOutputStream output) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void WriteTo(pb::CodedOutputStream output) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE output.WriteRawMessage(this); - #else +#else if (HasType) { output.WriteRawTag(8); output.WriteEnum((int) Type); @@ -1632,108 +1796,136 @@ public void WriteTo(pb::CodedOutputStream output) { if (_unknownFields != null) { _unknownFields.WriteTo(output); } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { - if (HasType) { + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) + { + if (HasType) + { output.WriteRawTag(8); - output.WriteEnum((int) Type); + output.WriteEnum((int)Type); } - if (HasName) { + if (HasName) + { output.WriteRawTag(18); output.WriteBytes(Name); } - if (HasOriginalName) { + if (HasOriginalName) + { output.WriteRawTag(26); output.WriteBytes(OriginalName); } - if (HasTable) { + if (HasTable) + { output.WriteRawTag(34); output.WriteBytes(Table); } - if (HasOriginalTable) { + if (HasOriginalTable) + { output.WriteRawTag(42); output.WriteBytes(OriginalTable); } - if (HasSchema) { + if (HasSchema) + { output.WriteRawTag(50); output.WriteBytes(Schema); } - if (HasCatalog) { + if (HasCatalog) + { output.WriteRawTag(58); output.WriteBytes(Catalog); } - if (HasCollation) { + if (HasCollation) + { output.WriteRawTag(64); output.WriteUInt64(Collation); } - if (HasFractionalDigits) { + if (HasFractionalDigits) + { output.WriteRawTag(72); output.WriteUInt32(FractionalDigits); } - if (HasLength) { + if (HasLength) + { output.WriteRawTag(80); output.WriteUInt32(Length); } - if (HasFlags) { + if (HasFlags) + { output.WriteRawTag(88); output.WriteUInt32(Flags); } - if (HasContentType) { + if (HasContentType) + { output.WriteRawTag(96); output.WriteUInt32(ContentType); } - if (_unknownFields != null) { + if (_unknownFields != null) + { _unknownFields.WriteTo(ref output); } } - #endif +#endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public int CalculateSize() { + public int CalculateSize() + { int size = 0; - if (HasType) { - size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Type); + if (HasType) + { + size += 1 + pb::CodedOutputStream.ComputeEnumSize((int)Type); } - if (HasName) { + if (HasName) + { size += 1 + pb::CodedOutputStream.ComputeBytesSize(Name); } - if (HasOriginalName) { + if (HasOriginalName) + { size += 1 + pb::CodedOutputStream.ComputeBytesSize(OriginalName); } - if (HasTable) { + if (HasTable) + { size += 1 + pb::CodedOutputStream.ComputeBytesSize(Table); } - if (HasOriginalTable) { + if (HasOriginalTable) + { size += 1 + pb::CodedOutputStream.ComputeBytesSize(OriginalTable); } - if (HasSchema) { + if (HasSchema) + { size += 1 + pb::CodedOutputStream.ComputeBytesSize(Schema); } - if (HasCatalog) { + if (HasCatalog) + { size += 1 + pb::CodedOutputStream.ComputeBytesSize(Catalog); } - if (HasCollation) { + if (HasCollation) + { size += 1 + pb::CodedOutputStream.ComputeUInt64Size(Collation); } - if (HasFractionalDigits) { + if (HasFractionalDigits) + { size += 1 + pb::CodedOutputStream.ComputeUInt32Size(FractionalDigits); } - if (HasLength) { + if (HasLength) + { size += 1 + pb::CodedOutputStream.ComputeUInt32Size(Length); } - if (HasFlags) { + if (HasFlags) + { size += 1 + pb::CodedOutputStream.ComputeUInt32Size(Flags); } - if (HasContentType) { + if (HasContentType) + { size += 1 + pb::CodedOutputStream.ComputeUInt32Size(ContentType); } - if (_unknownFields != null) { + if (_unknownFields != null) + { size += _unknownFields.CalculateSize(); } return size; @@ -1741,44 +1933,58 @@ public int CalculateSize() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(ColumnMetaData other) { - if (other == null) { + public void MergeFrom(ColumnMetaData other) + { + if (other == null) + { return; } - if (other.HasType) { + if (other.HasType) + { Type = other.Type; } - if (other.HasName) { + if (other.HasName) + { Name = other.Name; } - if (other.HasOriginalName) { + if (other.HasOriginalName) + { OriginalName = other.OriginalName; } - if (other.HasTable) { + if (other.HasTable) + { Table = other.Table; } - if (other.HasOriginalTable) { + if (other.HasOriginalTable) + { OriginalTable = other.OriginalTable; } - if (other.HasSchema) { + if (other.HasSchema) + { Schema = other.Schema; } - if (other.HasCatalog) { + if (other.HasCatalog) + { Catalog = other.Catalog; } - if (other.HasCollation) { + if (other.HasCollation) + { Collation = other.Collation; } - if (other.HasFractionalDigits) { + if (other.HasFractionalDigits) + { FractionalDigits = other.FractionalDigits; } - if (other.HasLength) { + if (other.HasLength) + { Length = other.Length; } - if (other.HasFlags) { + if (other.HasFlags) + { Flags = other.Flags; } - if (other.HasContentType) { + if (other.HasContentType) + { ContentType = other.ContentType; } _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); @@ -1786,10 +1992,11 @@ public void MergeFrom(ColumnMetaData other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(pb::CodedInputStream input) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void MergeFrom(pb::CodedInputStream input) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE input.ReadRawMessage(this); - #else +#else uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { @@ -1846,78 +2053,95 @@ public void MergeFrom(pb::CodedInputStream input) { } } } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) + { uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { + while ((tag = input.ReadTag()) != 0) + { + switch (tag) + { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; - case 8: { - Type = (global::Mysqlx.Resultset.ColumnMetaData.Types.FieldType) input.ReadEnum(); - break; - } - case 18: { - Name = input.ReadBytes(); - break; - } - case 26: { - OriginalName = input.ReadBytes(); - break; - } - case 34: { - Table = input.ReadBytes(); - break; - } - case 42: { - OriginalTable = input.ReadBytes(); - break; - } - case 50: { - Schema = input.ReadBytes(); - break; - } - case 58: { - Catalog = input.ReadBytes(); - break; - } - case 64: { - Collation = input.ReadUInt64(); - break; - } - case 72: { - FractionalDigits = input.ReadUInt32(); - break; - } - case 80: { - Length = input.ReadUInt32(); - break; - } - case 88: { - Flags = input.ReadUInt32(); - break; - } - case 96: { - ContentType = input.ReadUInt32(); - break; - } + case 8: + { + Type = (global::Mysqlx.Resultset.ColumnMetaData.Types.FieldType)input.ReadEnum(); + break; + } + case 18: + { + Name = input.ReadBytes(); + break; + } + case 26: + { + OriginalName = input.ReadBytes(); + break; + } + case 34: + { + Table = input.ReadBytes(); + break; + } + case 42: + { + OriginalTable = input.ReadBytes(); + break; + } + case 50: + { + Schema = input.ReadBytes(); + break; + } + case 58: + { + Catalog = input.ReadBytes(); + break; + } + case 64: + { + Collation = input.ReadUInt64(); + break; + } + case 72: + { + FractionalDigits = input.ReadUInt32(); + break; + } + case 80: + { + Length = input.ReadUInt32(); + break; + } + case 88: + { + Flags = input.ReadUInt32(); + break; + } + case 96: + { + ContentType = input.ReadUInt32(); + break; + } } } } - #endif +#endif #region Nested types /// Container for nested types declared in the ColumnMetaData message type. [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static partial class Types { - public enum FieldType { + public static partial class Types + { + public enum FieldType + { [pbr::OriginalName("SINT")] Sint = 1, [pbr::OriginalName("UINT")] Uint = 2, [pbr::OriginalName("DOUBLE")] Double = 5, @@ -1946,10 +2170,11 @@ public enum FieldType { ///``ColumnMetadata``, as specified in the @ref Mysqlx::Resultset::ColumnMetaData ///description. /// - internal sealed partial class Row : pb::IMessage - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] + public sealed partial class Row : pb::IMessage +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE , pb::IBufferMessage - #endif +#endif { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Row()); private pb::UnknownFieldSet _unknownFields; @@ -1959,19 +2184,22 @@ internal sealed partial class Row : pb::IMessage [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static pbr::MessageDescriptor Descriptor { + public static pbr::MessageDescriptor Descriptor + { get { return global::Mysqlx.Resultset.MysqlxResultsetReflection.Descriptor.MessageTypes[5]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - pbr::MessageDescriptor pb::IMessage.Descriptor { + pbr::MessageDescriptor pb::IMessage.Descriptor + { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Row() { + public Row() + { OnConstruction(); } @@ -1979,14 +2207,16 @@ public Row() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Row(Row other) : this() { + public Row(Row other) : this() + { field_ = other.field_.Clone(); _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Row Clone() { + public Row Clone() + { return new Row(this); } @@ -1997,35 +2227,42 @@ public Row Clone() { private readonly pbc::RepeatedField field_ = new pbc::RepeatedField(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public pbc::RepeatedField Field { + public pbc::RepeatedField Field + { get { return field_; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override bool Equals(object other) { + public override bool Equals(object other) + { return Equals(other as Row); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool Equals(Row other) { - if (ReferenceEquals(other, null)) { + public bool Equals(Row other) + { + if (ReferenceEquals(other, null)) + { return false; } - if (ReferenceEquals(other, this)) { + if (ReferenceEquals(other, this)) + { return true; } - if(!field_.Equals(other.field_)) return false; + if (!field_.Equals(other.field_)) return false; return Equals(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override int GetHashCode() { + public override int GetHashCode() + { int hash = 1; hash ^= field_.GetHashCode(); - if (_unknownFields != null) { + if (_unknownFields != null) + { hash ^= _unknownFields.GetHashCode(); } return hash; @@ -2033,40 +2270,46 @@ public override int GetHashCode() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override string ToString() { + public override string ToString() + { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void WriteTo(pb::CodedOutputStream output) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void WriteTo(pb::CodedOutputStream output) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE output.WriteRawMessage(this); - #else +#else field_.WriteTo(output, _repeated_field_codec); if (_unknownFields != null) { _unknownFields.WriteTo(output); } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) + { field_.WriteTo(ref output, _repeated_field_codec); - if (_unknownFields != null) { + if (_unknownFields != null) + { _unknownFields.WriteTo(ref output); } } - #endif +#endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public int CalculateSize() { + public int CalculateSize() + { int size = 0; size += field_.CalculateSize(_repeated_field_codec); - if (_unknownFields != null) { + if (_unknownFields != null) + { size += _unknownFields.CalculateSize(); } return size; @@ -2074,8 +2317,10 @@ public int CalculateSize() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(Row other) { - if (other == null) { + public void MergeFrom(Row other) + { + if (other == null) + { return; } field_.Add(other.field_); @@ -2084,10 +2329,11 @@ public void MergeFrom(Row other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(pb::CodedInputStream input) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void MergeFrom(pb::CodedInputStream input) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE input.ReadRawMessage(this); - #else +#else uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { @@ -2100,27 +2346,31 @@ public void MergeFrom(pb::CodedInputStream input) { } } } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) + { uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { + while ((tag = input.ReadTag()) != 0) + { + switch (tag) + { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; - case 10: { - field_.AddEntriesFrom(ref input, _repeated_field_codec); - break; - } + case 10: + { + field_.AddEntriesFrom(ref input, _repeated_field_codec); + break; + } } } } - #endif +#endif } diff --git a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxSession.cs b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxSession.cs index 5ef3192e6..5226f524b 100644 --- a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxSession.cs +++ b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxSession.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2022, 2023, Oracle and/or its affiliates. +// Copyright (c) 2023, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as @@ -7,7 +7,7 @@ // This program is also distributed with certain software (including // but not limited to OpenSSL) that is licensed under separate terms, // as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an +// documentation. The authors of MySQL hereby grant you an // additional permission to link the program and your derivative works // with the separately licensed software that they have included with // MySQL. @@ -37,26 +37,30 @@ using pbc = global::Google.Protobuf.Collections; using pbr = global::Google.Protobuf.Reflection; using scg = global::System.Collections.Generic; -namespace Mysqlx.Session { +namespace Mysqlx.Session +{ /// Holder for reflection information generated from mysqlx_session.proto - internal static partial class MysqlxSessionReflection { + public static partial class MysqlxSessionReflection + { #region Descriptor /// File descriptor for mysqlx_session.proto - public static pbr::FileDescriptor Descriptor { + public static pbr::FileDescriptor Descriptor + { get { return descriptor; } } private static pbr::FileDescriptor descriptor; - static MysqlxSessionReflection() { + static MysqlxSessionReflection() + { byte[] descriptorData = global::System.Convert.FromBase64String( string.Concat( "ChRteXNxbHhfc2Vzc2lvbi5wcm90bxIOTXlzcWx4LlNlc3Npb24aDG15c3Fs", "eC5wcm90byJZChFBdXRoZW50aWNhdGVTdGFydBIRCgltZWNoX25hbWUYASAC", "KAkSEQoJYXV0aF9kYXRhGAIgASgMEhgKEGluaXRpYWxfcmVzcG9uc2UYAyAB", "KAw6BIjqMAQiMwoUQXV0aGVudGljYXRlQ29udGludWUSEQoJYXV0aF9kYXRh", - "GAEgAigMOgiQ6jADiOowBSIpCg5BdXRoZW50aWNhdGVPaxIRCglhdXRoX2Rh", + "GAEgAigMOgiI6jAFkOowAyIpCg5BdXRoZW50aWNhdGVPaxIRCglhdXRoX2Rh", "dGEYASABKAw6BJDqMAQiJwoFUmVzZXQSGAoJa2VlcF9vcGVuGAEgASgIOgVm", "YWxzZToEiOowBiINCgVDbG9zZToEiOowB0IZChdjb20ubXlzcWwuY2oueC5w", "cm90b2J1Zg==")); @@ -81,10 +85,11 @@ static MysqlxSessionReflection() { /// ///@returns @ref Mysqlx::Session::AuthenticateContinue /// - internal sealed partial class AuthenticateStart : pb::IMessage - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] + public sealed partial class AuthenticateStart : pb::IMessage +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE , pb::IBufferMessage - #endif +#endif { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new AuthenticateStart()); private pb::UnknownFieldSet _unknownFields; @@ -94,19 +99,22 @@ internal sealed partial class AuthenticateStart : pb::IMessage [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public string MechName { + public string MechName + { get { return mechName_ ?? MechNameDefaultValue; } - set { + set + { mechName_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } /// Gets whether the "mech_name" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasMechName { + public bool HasMechName + { get { return mechName_ != null; } } /// Clears the value of the "mech_name" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearMechName() { + public void ClearMechName() + { mechName_ = null; } @@ -166,22 +180,26 @@ public void ClearMechName() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public pb::ByteString AuthData { + public pb::ByteString AuthData + { get { return authData_ ?? AuthDataDefaultValue; } - set { + set + { authData_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } /// Gets whether the "auth_data" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasAuthData { + public bool HasAuthData + { get { return authData_ != null; } } /// Clears the value of the "auth_data" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearAuthData() { + public void ClearAuthData() + { authData_ = null; } @@ -195,38 +213,46 @@ public void ClearAuthData() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public pb::ByteString InitialResponse { + public pb::ByteString InitialResponse + { get { return initialResponse_ ?? InitialResponseDefaultValue; } - set { + set + { initialResponse_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } /// Gets whether the "initial_response" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasInitialResponse { + public bool HasInitialResponse + { get { return initialResponse_ != null; } } /// Clears the value of the "initial_response" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearInitialResponse() { + public void ClearInitialResponse() + { initialResponse_ = null; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override bool Equals(object other) { + public override bool Equals(object other) + { return Equals(other as AuthenticateStart); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool Equals(AuthenticateStart other) { - if (ReferenceEquals(other, null)) { + public bool Equals(AuthenticateStart other) + { + if (ReferenceEquals(other, null)) + { return false; } - if (ReferenceEquals(other, this)) { + if (ReferenceEquals(other, this)) + { return true; } if (MechName != other.MechName) return false; @@ -237,12 +263,14 @@ public bool Equals(AuthenticateStart other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override int GetHashCode() { + public override int GetHashCode() + { int hash = 1; if (HasMechName) hash ^= MechName.GetHashCode(); if (HasAuthData) hash ^= AuthData.GetHashCode(); if (HasInitialResponse) hash ^= InitialResponse.GetHashCode(); - if (_unknownFields != null) { + if (_unknownFields != null) + { hash ^= _unknownFields.GetHashCode(); } return hash; @@ -250,16 +278,18 @@ public override int GetHashCode() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override string ToString() { + public override string ToString() + { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void WriteTo(pb::CodedOutputStream output) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void WriteTo(pb::CodedOutputStream output) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE output.WriteRawMessage(this); - #else +#else if (HasMechName) { output.WriteRawTag(10); output.WriteString(MechName); @@ -275,45 +305,55 @@ public void WriteTo(pb::CodedOutputStream output) { if (_unknownFields != null) { _unknownFields.WriteTo(output); } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { - if (HasMechName) { + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) + { + if (HasMechName) + { output.WriteRawTag(10); output.WriteString(MechName); } - if (HasAuthData) { + if (HasAuthData) + { output.WriteRawTag(18); output.WriteBytes(AuthData); } - if (HasInitialResponse) { + if (HasInitialResponse) + { output.WriteRawTag(26); output.WriteBytes(InitialResponse); } - if (_unknownFields != null) { + if (_unknownFields != null) + { _unknownFields.WriteTo(ref output); } } - #endif +#endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public int CalculateSize() { + public int CalculateSize() + { int size = 0; - if (HasMechName) { + if (HasMechName) + { size += 1 + pb::CodedOutputStream.ComputeStringSize(MechName); } - if (HasAuthData) { + if (HasAuthData) + { size += 1 + pb::CodedOutputStream.ComputeBytesSize(AuthData); } - if (HasInitialResponse) { + if (HasInitialResponse) + { size += 1 + pb::CodedOutputStream.ComputeBytesSize(InitialResponse); } - if (_unknownFields != null) { + if (_unknownFields != null) + { size += _unknownFields.CalculateSize(); } return size; @@ -321,17 +361,22 @@ public int CalculateSize() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(AuthenticateStart other) { - if (other == null) { + public void MergeFrom(AuthenticateStart other) + { + if (other == null) + { return; } - if (other.HasMechName) { + if (other.HasMechName) + { MechName = other.MechName; } - if (other.HasAuthData) { + if (other.HasAuthData) + { AuthData = other.AuthData; } - if (other.HasInitialResponse) { + if (other.HasInitialResponse) + { InitialResponse = other.InitialResponse; } _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); @@ -339,10 +384,11 @@ public void MergeFrom(AuthenticateStart other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(pb::CodedInputStream input) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void MergeFrom(pb::CodedInputStream input) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE input.ReadRawMessage(this); - #else +#else uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { @@ -363,35 +409,41 @@ public void MergeFrom(pb::CodedInputStream input) { } } } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) + { uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { + while ((tag = input.ReadTag()) != 0) + { + switch (tag) + { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; - case 10: { - MechName = input.ReadString(); - break; - } - case 18: { - AuthData = input.ReadBytes(); - break; - } - case 26: { - InitialResponse = input.ReadBytes(); - break; - } + case 10: + { + MechName = input.ReadString(); + break; + } + case 18: + { + AuthData = input.ReadBytes(); + break; + } + case 26: + { + InitialResponse = input.ReadBytes(); + break; + } } } } - #endif +#endif } @@ -402,10 +454,11 @@ public void MergeFrom(pb::CodedInputStream input) { /// ///@returns Mysqlx::Session::AuthenticateContinue /// - internal sealed partial class AuthenticateContinue : pb::IMessage - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] + public sealed partial class AuthenticateContinue : pb::IMessage +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE , pb::IBufferMessage - #endif +#endif { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new AuthenticateContinue()); private pb::UnknownFieldSet _unknownFields; @@ -415,19 +468,22 @@ internal sealed partial class AuthenticateContinue : pb::IMessage [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public pb::ByteString AuthData { + public pb::ByteString AuthData + { get { return authData_ ?? AuthDataDefaultValue; } - set { + set + { authData_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } /// Gets whether the "auth_data" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasAuthData { + public bool HasAuthData + { get { return authData_ != null; } } /// Clears the value of the "auth_data" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearAuthData() { + public void ClearAuthData() + { authData_ = null; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override bool Equals(object other) { + public override bool Equals(object other) + { return Equals(other as AuthenticateContinue); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool Equals(AuthenticateContinue other) { - if (ReferenceEquals(other, null)) { + public bool Equals(AuthenticateContinue other) + { + if (ReferenceEquals(other, null)) + { return false; } - if (ReferenceEquals(other, this)) { + if (ReferenceEquals(other, this)) + { return true; } if (AuthData != other.AuthData) return false; @@ -496,10 +562,12 @@ public bool Equals(AuthenticateContinue other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override int GetHashCode() { + public override int GetHashCode() + { int hash = 1; if (HasAuthData) hash ^= AuthData.GetHashCode(); - if (_unknownFields != null) { + if (_unknownFields != null) + { hash ^= _unknownFields.GetHashCode(); } return hash; @@ -507,16 +575,18 @@ public override int GetHashCode() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override string ToString() { + public override string ToString() + { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void WriteTo(pb::CodedOutputStream output) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void WriteTo(pb::CodedOutputStream output) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE output.WriteRawMessage(this); - #else +#else if (HasAuthData) { output.WriteRawTag(10); output.WriteBytes(AuthData); @@ -524,31 +594,37 @@ public void WriteTo(pb::CodedOutputStream output) { if (_unknownFields != null) { _unknownFields.WriteTo(output); } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { - if (HasAuthData) { + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) + { + if (HasAuthData) + { output.WriteRawTag(10); output.WriteBytes(AuthData); } - if (_unknownFields != null) { + if (_unknownFields != null) + { _unknownFields.WriteTo(ref output); } } - #endif +#endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public int CalculateSize() { + public int CalculateSize() + { int size = 0; - if (HasAuthData) { + if (HasAuthData) + { size += 1 + pb::CodedOutputStream.ComputeBytesSize(AuthData); } - if (_unknownFields != null) { + if (_unknownFields != null) + { size += _unknownFields.CalculateSize(); } return size; @@ -556,11 +632,14 @@ public int CalculateSize() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(AuthenticateContinue other) { - if (other == null) { + public void MergeFrom(AuthenticateContinue other) + { + if (other == null) + { return; } - if (other.HasAuthData) { + if (other.HasAuthData) + { AuthData = other.AuthData; } _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); @@ -568,10 +647,11 @@ public void MergeFrom(AuthenticateContinue other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(pb::CodedInputStream input) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void MergeFrom(pb::CodedInputStream input) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE input.ReadRawMessage(this); - #else +#else uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { @@ -584,27 +664,31 @@ public void MergeFrom(pb::CodedInputStream input) { } } } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) + { uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { + while ((tag = input.ReadTag()) != 0) + { + switch (tag) + { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; - case 10: { - AuthData = input.ReadBytes(); - break; - } + case 10: + { + AuthData = input.ReadBytes(); + break; + } } } } - #endif +#endif } @@ -612,10 +696,11 @@ public void MergeFrom(pb::CodedInputStream input) { ///* ///Sent by the server after successful authentication. /// - internal sealed partial class AuthenticateOk : pb::IMessage - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] + public sealed partial class AuthenticateOk : pb::IMessage +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE , pb::IBufferMessage - #endif +#endif { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new AuthenticateOk()); private pb::UnknownFieldSet _unknownFields; @@ -625,19 +710,22 @@ internal sealed partial class AuthenticateOk : pb::IMessage [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static pbr::MessageDescriptor Descriptor { + public static pbr::MessageDescriptor Descriptor + { get { return global::Mysqlx.Session.MysqlxSessionReflection.Descriptor.MessageTypes[2]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - pbr::MessageDescriptor pb::IMessage.Descriptor { + pbr::MessageDescriptor pb::IMessage.Descriptor + { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public AuthenticateOk() { + public AuthenticateOk() + { OnConstruction(); } @@ -645,14 +733,16 @@ public AuthenticateOk() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public AuthenticateOk(AuthenticateOk other) : this() { + public AuthenticateOk(AuthenticateOk other) : this() + { authData_ = other.authData_; _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public AuthenticateOk Clone() { + public AuthenticateOk Clone() + { return new AuthenticateOk(this); } @@ -666,38 +756,46 @@ public AuthenticateOk Clone() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public pb::ByteString AuthData { + public pb::ByteString AuthData + { get { return authData_ ?? AuthDataDefaultValue; } - set { + set + { authData_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } /// Gets whether the "auth_data" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasAuthData { + public bool HasAuthData + { get { return authData_ != null; } } /// Clears the value of the "auth_data" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearAuthData() { + public void ClearAuthData() + { authData_ = null; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override bool Equals(object other) { + public override bool Equals(object other) + { return Equals(other as AuthenticateOk); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool Equals(AuthenticateOk other) { - if (ReferenceEquals(other, null)) { + public bool Equals(AuthenticateOk other) + { + if (ReferenceEquals(other, null)) + { return false; } - if (ReferenceEquals(other, this)) { + if (ReferenceEquals(other, this)) + { return true; } if (AuthData != other.AuthData) return false; @@ -706,10 +804,12 @@ public bool Equals(AuthenticateOk other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override int GetHashCode() { + public override int GetHashCode() + { int hash = 1; if (HasAuthData) hash ^= AuthData.GetHashCode(); - if (_unknownFields != null) { + if (_unknownFields != null) + { hash ^= _unknownFields.GetHashCode(); } return hash; @@ -717,16 +817,18 @@ public override int GetHashCode() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override string ToString() { + public override string ToString() + { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void WriteTo(pb::CodedOutputStream output) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void WriteTo(pb::CodedOutputStream output) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE output.WriteRawMessage(this); - #else +#else if (HasAuthData) { output.WriteRawTag(10); output.WriteBytes(AuthData); @@ -734,31 +836,37 @@ public void WriteTo(pb::CodedOutputStream output) { if (_unknownFields != null) { _unknownFields.WriteTo(output); } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { - if (HasAuthData) { + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) + { + if (HasAuthData) + { output.WriteRawTag(10); output.WriteBytes(AuthData); } - if (_unknownFields != null) { + if (_unknownFields != null) + { _unknownFields.WriteTo(ref output); } } - #endif +#endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public int CalculateSize() { + public int CalculateSize() + { int size = 0; - if (HasAuthData) { + if (HasAuthData) + { size += 1 + pb::CodedOutputStream.ComputeBytesSize(AuthData); } - if (_unknownFields != null) { + if (_unknownFields != null) + { size += _unknownFields.CalculateSize(); } return size; @@ -766,11 +874,14 @@ public int CalculateSize() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(AuthenticateOk other) { - if (other == null) { + public void MergeFrom(AuthenticateOk other) + { + if (other == null) + { return; } - if (other.HasAuthData) { + if (other.HasAuthData) + { AuthData = other.AuthData; } _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); @@ -778,10 +889,11 @@ public void MergeFrom(AuthenticateOk other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(pb::CodedInputStream input) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void MergeFrom(pb::CodedInputStream input) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE input.ReadRawMessage(this); - #else +#else uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { @@ -794,27 +906,31 @@ public void MergeFrom(pb::CodedInputStream input) { } } } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) + { uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { + while ((tag = input.ReadTag()) != 0) + { + switch (tag) + { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; - case 10: { - AuthData = input.ReadBytes(); - break; - } + case 10: + { + AuthData = input.ReadBytes(); + break; + } } } } - #endif +#endif } @@ -824,10 +940,11 @@ public void MergeFrom(pb::CodedInputStream input) { /// ///@returns @ref Mysqlx::Ok /// - internal sealed partial class Reset : pb::IMessage - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] + public sealed partial class Reset : pb::IMessage +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE , pb::IBufferMessage - #endif +#endif { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Reset()); private pb::UnknownFieldSet _unknownFields; @@ -838,19 +955,22 @@ internal sealed partial class Reset : pb::IMessage [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static pbr::MessageDescriptor Descriptor { + public static pbr::MessageDescriptor Descriptor + { get { return global::Mysqlx.Session.MysqlxSessionReflection.Descriptor.MessageTypes[3]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - pbr::MessageDescriptor pb::IMessage.Descriptor { + pbr::MessageDescriptor pb::IMessage.Descriptor + { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Reset() { + public Reset() + { OnConstruction(); } @@ -858,7 +978,8 @@ public Reset() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Reset(Reset other) : this() { + public Reset(Reset other) : this() + { _hasBits0 = other._hasBits0; keepOpen_ = other.keepOpen_; _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); @@ -866,7 +987,8 @@ public Reset(Reset other) : this() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Reset Clone() { + public Reset Clone() + { return new Reset(this); } @@ -881,9 +1003,11 @@ public Reset Clone() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool KeepOpen { + public bool KeepOpen + { get { if ((_hasBits0 & 1) != 0) { return keepOpen_; } else { return KeepOpenDefaultValue; } } - set { + set + { _hasBits0 |= 1; keepOpen_ = value; } @@ -891,29 +1015,35 @@ public bool KeepOpen { /// Gets whether the "keep_open" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasKeepOpen { + public bool HasKeepOpen + { get { return (_hasBits0 & 1) != 0; } } /// Clears the value of the "keep_open" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearKeepOpen() { + public void ClearKeepOpen() + { _hasBits0 &= ~1; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override bool Equals(object other) { + public override bool Equals(object other) + { return Equals(other as Reset); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool Equals(Reset other) { - if (ReferenceEquals(other, null)) { + public bool Equals(Reset other) + { + if (ReferenceEquals(other, null)) + { return false; } - if (ReferenceEquals(other, this)) { + if (ReferenceEquals(other, this)) + { return true; } if (KeepOpen != other.KeepOpen) return false; @@ -922,10 +1052,12 @@ public bool Equals(Reset other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override int GetHashCode() { + public override int GetHashCode() + { int hash = 1; if (HasKeepOpen) hash ^= KeepOpen.GetHashCode(); - if (_unknownFields != null) { + if (_unknownFields != null) + { hash ^= _unknownFields.GetHashCode(); } return hash; @@ -933,16 +1065,18 @@ public override int GetHashCode() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override string ToString() { + public override string ToString() + { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void WriteTo(pb::CodedOutputStream output) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void WriteTo(pb::CodedOutputStream output) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE output.WriteRawMessage(this); - #else +#else if (HasKeepOpen) { output.WriteRawTag(8); output.WriteBool(KeepOpen); @@ -950,31 +1084,37 @@ public void WriteTo(pb::CodedOutputStream output) { if (_unknownFields != null) { _unknownFields.WriteTo(output); } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { - if (HasKeepOpen) { + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) + { + if (HasKeepOpen) + { output.WriteRawTag(8); output.WriteBool(KeepOpen); } - if (_unknownFields != null) { + if (_unknownFields != null) + { _unknownFields.WriteTo(ref output); } } - #endif +#endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public int CalculateSize() { + public int CalculateSize() + { int size = 0; - if (HasKeepOpen) { + if (HasKeepOpen) + { size += 1 + 1; } - if (_unknownFields != null) { + if (_unknownFields != null) + { size += _unknownFields.CalculateSize(); } return size; @@ -982,11 +1122,14 @@ public int CalculateSize() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(Reset other) { - if (other == null) { + public void MergeFrom(Reset other) + { + if (other == null) + { return; } - if (other.HasKeepOpen) { + if (other.HasKeepOpen) + { KeepOpen = other.KeepOpen; } _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); @@ -994,10 +1137,11 @@ public void MergeFrom(Reset other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(pb::CodedInputStream input) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void MergeFrom(pb::CodedInputStream input) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE input.ReadRawMessage(this); - #else +#else uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { @@ -1010,27 +1154,31 @@ public void MergeFrom(pb::CodedInputStream input) { } } } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) + { uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { + while ((tag = input.ReadTag()) != 0) + { + switch (tag) + { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; - case 8: { - KeepOpen = input.ReadBool(); - break; - } + case 8: + { + KeepOpen = input.ReadBool(); + break; + } } } } - #endif +#endif } @@ -1040,10 +1188,11 @@ public void MergeFrom(pb::CodedInputStream input) { /// ///@returns @ref Mysqlx::Ok /// - internal sealed partial class Close : pb::IMessage - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] + public sealed partial class Close : pb::IMessage +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE , pb::IBufferMessage - #endif +#endif { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Close()); private pb::UnknownFieldSet _unknownFields; @@ -1053,19 +1202,22 @@ internal sealed partial class Close : pb::IMessage [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static pbr::MessageDescriptor Descriptor { + public static pbr::MessageDescriptor Descriptor + { get { return global::Mysqlx.Session.MysqlxSessionReflection.Descriptor.MessageTypes[4]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - pbr::MessageDescriptor pb::IMessage.Descriptor { + pbr::MessageDescriptor pb::IMessage.Descriptor + { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Close() { + public Close() + { OnConstruction(); } @@ -1073,29 +1225,35 @@ public Close() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Close(Close other) : this() { + public Close(Close other) : this() + { _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Close Clone() { + public Close Clone() + { return new Close(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override bool Equals(object other) { + public override bool Equals(object other) + { return Equals(other as Close); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool Equals(Close other) { - if (ReferenceEquals(other, null)) { + public bool Equals(Close other) + { + if (ReferenceEquals(other, null)) + { return false; } - if (ReferenceEquals(other, this)) { + if (ReferenceEquals(other, this)) + { return true; } return Equals(_unknownFields, other._unknownFields); @@ -1103,9 +1261,11 @@ public bool Equals(Close other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override int GetHashCode() { + public override int GetHashCode() + { int hash = 1; - if (_unknownFields != null) { + if (_unknownFields != null) + { hash ^= _unknownFields.GetHashCode(); } return hash; @@ -1113,37 +1273,43 @@ public override int GetHashCode() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override string ToString() { + public override string ToString() + { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void WriteTo(pb::CodedOutputStream output) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void WriteTo(pb::CodedOutputStream output) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE output.WriteRawMessage(this); - #else +#else if (_unknownFields != null) { _unknownFields.WriteTo(output); } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { - if (_unknownFields != null) { + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) + { + if (_unknownFields != null) + { _unknownFields.WriteTo(ref output); } } - #endif +#endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public int CalculateSize() { + public int CalculateSize() + { int size = 0; - if (_unknownFields != null) { + if (_unknownFields != null) + { size += _unknownFields.CalculateSize(); } return size; @@ -1151,8 +1317,10 @@ public int CalculateSize() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(Close other) { - if (other == null) { + public void MergeFrom(Close other) + { + if (other == null) + { return; } _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); @@ -1160,10 +1328,11 @@ public void MergeFrom(Close other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(pb::CodedInputStream input) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void MergeFrom(pb::CodedInputStream input) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE input.ReadRawMessage(this); - #else +#else uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { @@ -1172,23 +1341,26 @@ public void MergeFrom(pb::CodedInputStream input) { break; } } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) + { uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { + while ((tag = input.ReadTag()) != 0) + { + switch (tag) + { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; } } } - #endif +#endif } diff --git a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxSql.cs b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxSql.cs index 7f8a00342..7540472fc 100644 --- a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxSql.cs +++ b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxSql.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2022, 2023, Oracle and/or its affiliates. +// Copyright (c) 2023, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as @@ -7,7 +7,7 @@ // This program is also distributed with certain software (including // but not limited to OpenSSL) that is licensed under separate terms, // as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an +// documentation. The authors of MySQL hereby grant you an // additional permission to link the program and your derivative works // with the separately licensed software that they have included with // MySQL. @@ -37,19 +37,23 @@ using pbc = global::Google.Protobuf.Collections; using pbr = global::Google.Protobuf.Reflection; using scg = global::System.Collections.Generic; -namespace Mysqlx.Sql { +namespace Mysqlx.Sql +{ /// Holder for reflection information generated from mysqlx_sql.proto - internal static partial class MysqlxSqlReflection { + public static partial class MysqlxSqlReflection + { #region Descriptor /// File descriptor for mysqlx_sql.proto - public static pbr::FileDescriptor Descriptor { + public static pbr::FileDescriptor Descriptor + { get { return descriptor; } } private static pbr::FileDescriptor descriptor; - static MysqlxSqlReflection() { + static MysqlxSqlReflection() + { byte[] descriptorData = global::System.Convert.FromBase64String( string.Concat( "ChBteXNxbHhfc3FsLnByb3RvEgpNeXNxbHguU3FsGgxteXNxbHgucHJvdG8a", @@ -85,10 +89,11 @@ static MysqlxSqlReflection() { /// ///@returns zero or more @ref Mysqlx::Resultset followed by @ref Mysqlx::Sql::StmtExecuteOk /// - internal sealed partial class StmtExecute : pb::IMessage - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] + public sealed partial class StmtExecute : pb::IMessage +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE , pb::IBufferMessage - #endif +#endif { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new StmtExecute()); private pb::UnknownFieldSet _unknownFields; @@ -99,19 +104,22 @@ internal sealed partial class StmtExecute : pb::IMessage [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static pbr::MessageDescriptor Descriptor { + public static pbr::MessageDescriptor Descriptor + { get { return global::Mysqlx.Sql.MysqlxSqlReflection.Descriptor.MessageTypes[0]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - pbr::MessageDescriptor pb::IMessage.Descriptor { + pbr::MessageDescriptor pb::IMessage.Descriptor + { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public StmtExecute() { + public StmtExecute() + { OnConstruction(); } @@ -119,7 +127,8 @@ public StmtExecute() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public StmtExecute(StmtExecute other) : this() { + public StmtExecute(StmtExecute other) : this() + { _hasBits0 = other._hasBits0; namespace_ = other.namespace_; stmt_ = other.stmt_; @@ -130,7 +139,8 @@ public StmtExecute(StmtExecute other) : this() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public StmtExecute Clone() { + public StmtExecute Clone() + { return new StmtExecute(this); } @@ -144,22 +154,26 @@ public StmtExecute Clone() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public string Namespace { + public string Namespace + { get { return namespace_ ?? NamespaceDefaultValue; } - set { + set + { namespace_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } /// Gets whether the "namespace" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasNamespace { + public bool HasNamespace + { get { return namespace_ != null; } } /// Clears the value of the "namespace" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearNamespace() { + public void ClearNamespace() + { namespace_ = null; } @@ -173,22 +187,26 @@ public void ClearNamespace() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public pb::ByteString Stmt { + public pb::ByteString Stmt + { get { return stmt_ ?? StmtDefaultValue; } - set { + set + { stmt_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } /// Gets whether the "stmt" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasStmt { + public bool HasStmt + { get { return stmt_ != null; } } /// Clears the value of the "stmt" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearStmt() { + public void ClearStmt() + { stmt_ = null; } @@ -202,7 +220,8 @@ public void ClearStmt() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public pbc::RepeatedField Args { + public pbc::RepeatedField Args + { get { return args_; } } @@ -217,9 +236,11 @@ public void ClearStmt() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool CompactMetadata { + public bool CompactMetadata + { get { if ((_hasBits0 & 1) != 0) { return compactMetadata_; } else { return CompactMetadataDefaultValue; } } - set { + set + { _hasBits0 |= 1; compactMetadata_ = value; } @@ -227,47 +248,55 @@ public bool CompactMetadata { /// Gets whether the "compact_metadata" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasCompactMetadata { + public bool HasCompactMetadata + { get { return (_hasBits0 & 1) != 0; } } /// Clears the value of the "compact_metadata" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearCompactMetadata() { + public void ClearCompactMetadata() + { _hasBits0 &= ~1; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override bool Equals(object other) { + public override bool Equals(object other) + { return Equals(other as StmtExecute); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool Equals(StmtExecute other) { - if (ReferenceEquals(other, null)) { + public bool Equals(StmtExecute other) + { + if (ReferenceEquals(other, null)) + { return false; } - if (ReferenceEquals(other, this)) { + if (ReferenceEquals(other, this)) + { return true; } if (Namespace != other.Namespace) return false; if (Stmt != other.Stmt) return false; - if(!args_.Equals(other.args_)) return false; + if (!args_.Equals(other.args_)) return false; if (CompactMetadata != other.CompactMetadata) return false; return Equals(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override int GetHashCode() { + public override int GetHashCode() + { int hash = 1; if (HasNamespace) hash ^= Namespace.GetHashCode(); if (HasStmt) hash ^= Stmt.GetHashCode(); hash ^= args_.GetHashCode(); if (HasCompactMetadata) hash ^= CompactMetadata.GetHashCode(); - if (_unknownFields != null) { + if (_unknownFields != null) + { hash ^= _unknownFields.GetHashCode(); } return hash; @@ -275,16 +304,18 @@ public override int GetHashCode() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override string ToString() { + public override string ToString() + { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void WriteTo(pb::CodedOutputStream output) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void WriteTo(pb::CodedOutputStream output) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE output.WriteRawMessage(this); - #else +#else if (HasStmt) { output.WriteRawTag(10); output.WriteBytes(Stmt); @@ -301,47 +332,57 @@ public void WriteTo(pb::CodedOutputStream output) { if (_unknownFields != null) { _unknownFields.WriteTo(output); } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { - if (HasStmt) { + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) + { + if (HasStmt) + { output.WriteRawTag(10); output.WriteBytes(Stmt); } args_.WriteTo(ref output, _repeated_args_codec); - if (HasNamespace) { + if (HasNamespace) + { output.WriteRawTag(26); output.WriteString(Namespace); } - if (HasCompactMetadata) { + if (HasCompactMetadata) + { output.WriteRawTag(32); output.WriteBool(CompactMetadata); } - if (_unknownFields != null) { + if (_unknownFields != null) + { _unknownFields.WriteTo(ref output); } } - #endif +#endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public int CalculateSize() { + public int CalculateSize() + { int size = 0; - if (HasNamespace) { + if (HasNamespace) + { size += 1 + pb::CodedOutputStream.ComputeStringSize(Namespace); } - if (HasStmt) { + if (HasStmt) + { size += 1 + pb::CodedOutputStream.ComputeBytesSize(Stmt); } size += args_.CalculateSize(_repeated_args_codec); - if (HasCompactMetadata) { + if (HasCompactMetadata) + { size += 1 + 1; } - if (_unknownFields != null) { + if (_unknownFields != null) + { size += _unknownFields.CalculateSize(); } return size; @@ -349,18 +390,23 @@ public int CalculateSize() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(StmtExecute other) { - if (other == null) { + public void MergeFrom(StmtExecute other) + { + if (other == null) + { return; } - if (other.HasNamespace) { + if (other.HasNamespace) + { Namespace = other.Namespace; } - if (other.HasStmt) { + if (other.HasStmt) + { Stmt = other.Stmt; } args_.Add(other.args_); - if (other.HasCompactMetadata) { + if (other.HasCompactMetadata) + { CompactMetadata = other.CompactMetadata; } _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); @@ -368,10 +414,11 @@ public void MergeFrom(StmtExecute other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(pb::CodedInputStream input) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void MergeFrom(pb::CodedInputStream input) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE input.ReadRawMessage(this); - #else +#else uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { @@ -396,39 +443,46 @@ public void MergeFrom(pb::CodedInputStream input) { } } } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) + { uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { + while ((tag = input.ReadTag()) != 0) + { + switch (tag) + { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; - case 10: { - Stmt = input.ReadBytes(); - break; - } - case 18: { - args_.AddEntriesFrom(ref input, _repeated_args_codec); - break; - } - case 26: { - Namespace = input.ReadString(); - break; - } - case 32: { - CompactMetadata = input.ReadBool(); - break; - } + case 10: + { + Stmt = input.ReadBytes(); + break; + } + case 18: + { + args_.AddEntriesFrom(ref input, _repeated_args_codec); + break; + } + case 26: + { + Namespace = input.ReadString(); + break; + } + case 32: + { + CompactMetadata = input.ReadBool(); + break; + } } } } - #endif +#endif } @@ -436,10 +490,11 @@ public void MergeFrom(pb::CodedInputStream input) { ///* ///Statement executed successfully /// - internal sealed partial class StmtExecuteOk : pb::IMessage - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] + public sealed partial class StmtExecuteOk : pb::IMessage +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE , pb::IBufferMessage - #endif +#endif { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new StmtExecuteOk()); private pb::UnknownFieldSet _unknownFields; @@ -449,19 +504,22 @@ internal sealed partial class StmtExecuteOk : pb::IMessage [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static pbr::MessageDescriptor Descriptor { + public static pbr::MessageDescriptor Descriptor + { get { return global::Mysqlx.Sql.MysqlxSqlReflection.Descriptor.MessageTypes[1]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - pbr::MessageDescriptor pb::IMessage.Descriptor { + pbr::MessageDescriptor pb::IMessage.Descriptor + { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public StmtExecuteOk() { + public StmtExecuteOk() + { OnConstruction(); } @@ -469,29 +527,35 @@ public StmtExecuteOk() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public StmtExecuteOk(StmtExecuteOk other) : this() { + public StmtExecuteOk(StmtExecuteOk other) : this() + { _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public StmtExecuteOk Clone() { + public StmtExecuteOk Clone() + { return new StmtExecuteOk(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override bool Equals(object other) { + public override bool Equals(object other) + { return Equals(other as StmtExecuteOk); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool Equals(StmtExecuteOk other) { - if (ReferenceEquals(other, null)) { + public bool Equals(StmtExecuteOk other) + { + if (ReferenceEquals(other, null)) + { return false; } - if (ReferenceEquals(other, this)) { + if (ReferenceEquals(other, this)) + { return true; } return Equals(_unknownFields, other._unknownFields); @@ -499,9 +563,11 @@ public bool Equals(StmtExecuteOk other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override int GetHashCode() { + public override int GetHashCode() + { int hash = 1; - if (_unknownFields != null) { + if (_unknownFields != null) + { hash ^= _unknownFields.GetHashCode(); } return hash; @@ -509,37 +575,43 @@ public override int GetHashCode() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override string ToString() { + public override string ToString() + { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void WriteTo(pb::CodedOutputStream output) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void WriteTo(pb::CodedOutputStream output) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE output.WriteRawMessage(this); - #else +#else if (_unknownFields != null) { _unknownFields.WriteTo(output); } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { - if (_unknownFields != null) { + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) + { + if (_unknownFields != null) + { _unknownFields.WriteTo(ref output); } } - #endif +#endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public int CalculateSize() { + public int CalculateSize() + { int size = 0; - if (_unknownFields != null) { + if (_unknownFields != null) + { size += _unknownFields.CalculateSize(); } return size; @@ -547,8 +619,10 @@ public int CalculateSize() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(StmtExecuteOk other) { - if (other == null) { + public void MergeFrom(StmtExecuteOk other) + { + if (other == null) + { return; } _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); @@ -556,10 +630,11 @@ public void MergeFrom(StmtExecuteOk other) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(pb::CodedInputStream input) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + public void MergeFrom(pb::CodedInputStream input) + { +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE input.ReadRawMessage(this); - #else +#else uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { @@ -568,23 +643,26 @@ public void MergeFrom(pb::CodedInputStream input) { break; } } - #endif +#endif } - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE +#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) + { uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { + while ((tag = input.ReadTag()) != 0) + { + switch (tag) + { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; } } } - #endif +#endif } From 0e953148a50169cf8ae498c7436a5afc84e28a25 Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Thu, 23 Nov 2023 19:50:46 -0700 Subject: [PATCH 009/125] WL#16035 [Add Support for .NET 8 GA version] Added suppor for .NET * and EFCore 8 Ga versions. Change-Id: I7b193408ab7efa05dd46d5e528c4b5266fe27d39 --- CHANGES | 1 + .../src/Extensions/MySQLTypeBaseExtensions.cs | 60 +++++++++ .../Conventions/MySQLConventionSetBuilder.cs | 3 +- .../MySqlEntityCharsetAttributeConvention.cs | 27 ++++ ...MySqlEntityCollationAttributeConvention.cs | 27 ++++ .../Internal/MySQLAnnotationProvider.cs | 117 ++++++++++++++++- .../Migrations/MySQLMigrationsSqlGenerator.cs | 5 + EFCore/src/MySql.EntityFrameworkCore.csproj | 4 +- .../MySQLStringComparisonMethodTranslator.cs | 118 +++++++++++++++++- .../Internal/MySQLGeometryTypeMapping.cs | 5 + .../Internal/MySQLTypeMappingSource.cs | 34 +++++ .../Internal/MySQLValueGeneratorSelector.cs | 17 +++ ...Sql.EntityFrameworkCore.Basic.Tests.csproj | 4 +- ...ql.EntityFrameworkCore.Design.Tests.csproj | 4 +- ...ntityFrameworkCore.Migrations.Tests.csproj | 2 +- MySQL.Data/src/MySqlDataReader.cs | 4 + 16 files changed, 418 insertions(+), 14 deletions(-) create mode 100644 EFCore/src/Extensions/MySQLTypeBaseExtensions.cs diff --git a/CHANGES b/CHANGES index a48c54622..8ce957c3d 100644 --- a/CHANGES +++ b/CHANGES @@ -6,6 +6,7 @@ - Added missing target frameworks to EFCore nuget packages (Oracle Bug #35968775). - Added missing README files to Nuget packages (WL16041). - Upgraded the Google.Protobuf dependency to version 3.25.1 (WL16075). +- Added support for .NET 8 and EFCore 8 GA versions (WL16035). 8.2.0 diff --git a/EFCore/src/Extensions/MySQLTypeBaseExtensions.cs b/EFCore/src/Extensions/MySQLTypeBaseExtensions.cs new file mode 100644 index 000000000..59f50fb40 --- /dev/null +++ b/EFCore/src/Extensions/MySQLTypeBaseExtensions.cs @@ -0,0 +1,60 @@ +// Copyright (c) 2023, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is also distributed with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, +// as designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an +// additional permission to link the program and your derivative works +// with the separately licensed software that they have included with +// MySQL. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using Microsoft.EntityFrameworkCore.Metadata; +using MySql.EntityFrameworkCore.Metadata.Internal; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace MySql.EntityFrameworkCore.Extensions +{ + /// + /// MySQL extension methods for type base. + /// + public static class MySQLTypeBaseExtensions + { + /// + /// Gets the MySQL character set for the table associated with this TypeBase. + /// + /// The TypeBase. + /// The name of the character set. + public static string? GetCharSet([NotNull] this IReadOnlyTypeBase typeBase) + => typeBase[MySQLAnnotationNames.Charset] as string; + + /// + /// Gets the MySQL collation for the table associated with this TypeBase. + /// + /// The TypeBase. + /// The name of the collation. + public static string? GetCollation([NotNull] this IReadOnlyTypeBase typeBase) + => typeBase[RelationalAnnotationNames.Collation] as string; + } +} diff --git a/EFCore/src/Metadata/Conventions/MySQLConventionSetBuilder.cs b/EFCore/src/Metadata/Conventions/MySQLConventionSetBuilder.cs index 17aa4d2d7..892e28f7d 100644 --- a/EFCore/src/Metadata/Conventions/MySQLConventionSetBuilder.cs +++ b/EFCore/src/Metadata/Conventions/MySQLConventionSetBuilder.cs @@ -67,9 +67,10 @@ public override ConventionSet CreateConventionSet() conventionSet.PropertyAddedConventions.Add(new MySqlCharsetAttributeConvention(Dependencies)); conventionSet.PropertyAddedConventions.Add(new MySqlCollationAttributeConvention(Dependencies)); + #if !NET8_0 conventionSet.EntityTypeAddedConventions.Add(new MySqlEntityCharsetAttributeConvention(Dependencies)); conventionSet.EntityTypeAddedConventions.Add(new MySqlEntityCollationAttributeConvention(Dependencies)); - + #endif ValueGenerationConvention valueGeneratorConvention = new MySQLValueGenerationConvention(Dependencies, RelationalDependencies); ReplaceConvention(conventionSet.EntityTypeBaseTypeChangedConventions, valueGeneratorConvention); ReplaceConvention(conventionSet.EntityTypePrimaryKeyChangedConventions, valueGeneratorConvention); diff --git a/EFCore/src/Metadata/Conventions/MySqlEntityCharsetAttributeConvention.cs b/EFCore/src/Metadata/Conventions/MySqlEntityCharsetAttributeConvention.cs index 3500e1df3..f12270ef7 100644 --- a/EFCore/src/Metadata/Conventions/MySqlEntityCharsetAttributeConvention.cs +++ b/EFCore/src/Metadata/Conventions/MySqlEntityCharsetAttributeConvention.cs @@ -34,6 +34,7 @@ namespace MySql.EntityFrameworkCore.Metadata.Conventions { +#if !NET8_0 /// /// Represents a character-set attribute for an entity. /// @@ -58,4 +59,30 @@ protected override void ProcessEntityTypeAdded( true); } } +#else + /// + /// Represents a character-set attribute for a Type. + /// + internal class MySqlEntityCharsetAttributeConvention : TypeAttributeConventionBase + { + /// + /// Creates a new instance of . + /// + /// Parameter object containing dependencies for this convention. + public MySqlEntityCharsetAttributeConvention([NotNull] ProviderConventionSetBuilderDependencies dependencies) + : base(dependencies) + { } + + protected override void ProcessEntityTypeAdded( + [NotNull] IConventionEntityTypeBuilder entityTypeBuilder, + [NotNull] MySQLCharsetAttribute attribute, + [NotNull] IConventionContext context) + { + entityTypeBuilder.Metadata.SetAnnotation( + MySQLAnnotationNames.Charset, + attribute.Charset, + true); + } + } +#endif } diff --git a/EFCore/src/Metadata/Conventions/MySqlEntityCollationAttributeConvention.cs b/EFCore/src/Metadata/Conventions/MySqlEntityCollationAttributeConvention.cs index 966e485bc..71abf355f 100644 --- a/EFCore/src/Metadata/Conventions/MySqlEntityCollationAttributeConvention.cs +++ b/EFCore/src/Metadata/Conventions/MySqlEntityCollationAttributeConvention.cs @@ -34,6 +34,7 @@ namespace MySql.EntityFrameworkCore.Metadata.Conventions { +#if !NET8_0 /// /// Represents a collation attribute for an entity. /// @@ -58,4 +59,30 @@ protected override void ProcessEntityTypeAdded( true); } } +#else + /// + /// Represents a collation attribute for an Type. + /// + internal class MySqlEntityCollationAttributeConvention : TypeAttributeConventionBase + { + /// + /// Creates a new instance of . + /// + /// Parameter object containing dependencies for this convention. + internal MySqlEntityCollationAttributeConvention([NotNull] ProviderConventionSetBuilderDependencies dependencies) + : base(dependencies) + { } + + protected override void ProcessEntityTypeAdded( + [NotNull] IConventionEntityTypeBuilder entityTypeBuilder, + [NotNull] MySQLCollationAttribute attribute, + [NotNull] IConventionContext context) + { + entityTypeBuilder.Metadata.SetAnnotation( + MySQLAnnotationNames.Collation, + attribute.Collation, + true); + } + } +#endif } diff --git a/EFCore/src/Metadata/Internal/MySQLAnnotationProvider.cs b/EFCore/src/Metadata/Internal/MySQLAnnotationProvider.cs index f6174f88e..ce5ce583a 100644 --- a/EFCore/src/Metadata/Internal/MySQLAnnotationProvider.cs +++ b/EFCore/src/Metadata/Internal/MySQLAnnotationProvider.cs @@ -29,6 +29,7 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Metadata.Internal; using MySql.EntityFrameworkCore.Extensions; using MySql.EntityFrameworkCore.Infrastructure.Internal; using MySql.EntityFrameworkCore.Storage.Internal; @@ -69,7 +70,7 @@ public override IEnumerable For(ITable table, bool designTime) { yield break; } - +#if !NET8_0 var entityType = table.EntityTypeMappings.First().EntityType; if (GetActualEntityTypeCharSet(entityType) is string charSet) @@ -80,6 +81,18 @@ public override IEnumerable For(ITable table, bool designTime) foreach (var annotation in entityType.GetAnnotations().Where(a => a.Name is MySQLAnnotationNames.StoreOptions)) yield return annotation; +#else + var typeBase = table.EntityTypeMappings.First().TypeBase; + + if (GetActualTypeBaseCharSet(typeBase) is string charSet) + yield return new Annotation(MySQLAnnotationNames.Charset, charSet); + + if (GetActualTypeBaseCollation(typeBase) is string collation) + yield return new Annotation(RelationalAnnotationNames.Collation, collation); + + foreach (var annotation in typeBase.GetAnnotations().Where(a => a.Name is MySQLAnnotationNames.StoreOptions)) + yield return annotation; +#endif } public override IEnumerable For(IUniqueConstraint constraint, bool designTime) @@ -142,7 +155,7 @@ public override IEnumerable For(IColumn column, bool designTime) yield return new Annotation(MySQLAnnotationNames.ValueGenerationStrategy, valueGenerationStrategy); } } -#elif NET7_0 || NET8_0 +#elif NET7_0 public override IEnumerable For(IColumn column, bool designTime) { if (!designTime) @@ -166,6 +179,32 @@ public override IEnumerable For(IColumn column, bool designTime) yield return new Annotation(MySQLAnnotationNames.ValueGenerationStrategy, valueGenerationStrategy); } } + +#elif NET8_0 + +public override IEnumerable For(IColumn column, bool designTime) + { + if (!designTime) + yield break; + + var table = StoreObjectIdentifier.Table(column.Table.Name, column.Table.Schema); + var properties = column.PropertyMappings.Select(m => m.Property).ToArray(); + + if (column.PropertyMappings.Where(m => m.TableMapping.IsSharedTablePrincipal ?? true + && m.TableMapping.TypeBase == m.Property.DeclaringEntityType) + .Select(m => m.Property) + .FirstOrDefault(p => p.GetValueGenerationStrategy(table) == MySQLValueGenerationStrategy.IdentityColumn) is IProperty identityProperty) + { + var valueGenerationStrategy = identityProperty.GetValueGenerationStrategy(table); + yield return new Annotation(MySQLAnnotationNames.ValueGenerationStrategy, valueGenerationStrategy); + } + else if (properties.FirstOrDefault + (p => p.GetValueGenerationStrategy(table) == MySQLValueGenerationStrategy.ComputedColumn) is IProperty computedProperty) + { + var valueGenerationStrategy = computedProperty.GetValueGenerationStrategy(table); + yield return new Annotation(MySQLAnnotationNames.ValueGenerationStrategy, valueGenerationStrategy); + } + } #endif @@ -179,6 +218,8 @@ protected virtual string GetActualModelCollation(IModel model) return model.GetCollation()!; } + +#if !NET8_0 protected virtual string? GetActualEntityTypeCharSet(IEntityType entityType) { var entityTypeCharSet = entityType.GetCharSet(); @@ -248,5 +289,77 @@ protected virtual string GetActualModelCollation(IModel model) : null) .FirstOrDefault(s => s is not null); } +#else + protected virtual string? GetActualTypeBaseCharSet(ITypeBase typeBase) + { + var typeBaseCharSet = typeBase.GetCharSet(); + + if (typeBaseCharSet is not null) + return typeBaseCharSet; + + if (typeBaseCharSet is null) + { + var typeBaseCollation = typeBase.GetCollation(); + var actualModelCharSet = GetActualModelCharSet(typeBase.Model); + + if (typeBaseCollation is not null) + { + return actualModelCharSet is not null && typeBaseCollation.StartsWith(actualModelCharSet, StringComparison.OrdinalIgnoreCase) + ? actualModelCharSet : null; + } + + var actualModelCollation = GetActualModelCollation(typeBase.Model); + + if (actualModelCollation is not null) + { + return actualModelCharSet is not null && actualModelCollation.StartsWith(actualModelCharSet, StringComparison.OrdinalIgnoreCase) + ? actualModelCharSet : null; + } + + return actualModelCharSet; + } + + return null; + } + + protected virtual string? GetActualTypeBaseCollation(ITypeBase typeBase) + { + var typeBaseCollation = typeBase.GetCollation(); + + if (typeBaseCollation is not null) + return typeBaseCollation; + + if (typeBaseCollation is null) + { + var typeBaseCharSet = typeBase.GetCharSet(); + var actualModelCollation = GetActualModelCollation(typeBase.Model); + + if (typeBaseCharSet is not null) + { + return actualModelCollation is not null && actualModelCollation.StartsWith(typeBaseCharSet, StringComparison.OrdinalIgnoreCase) + ? actualModelCollation : null; + } + + return actualModelCollation; + } + + return null; + } + + protected virtual string? GetActualPropertyCharSet(IProperty[] properties) + { + return properties.Select(p => p.GetCharSet()).FirstOrDefault(s => s is not null) ?? + properties.Select( + p => p.FindTypeMapping() is MySQLStringTypeMapping + ? GetActualTypeBaseCharSet(p.DeclaringType) is string charSet && + (p.GetCollation() is not string collation || + collation.StartsWith(charSet, StringComparison.OrdinalIgnoreCase)) + ? charSet + : null + : null) + .FirstOrDefault(s => s is not null); + } +#endif + } } diff --git a/EFCore/src/Migrations/MySQLMigrationsSqlGenerator.cs b/EFCore/src/Migrations/MySQLMigrationsSqlGenerator.cs index 32a7491a5..7a02a8ecd 100644 --- a/EFCore/src/Migrations/MySQLMigrationsSqlGenerator.cs +++ b/EFCore/src/Migrations/MySQLMigrationsSqlGenerator.cs @@ -537,7 +537,12 @@ protected override void Generate( if (model?.GetRelationalModel().FindTable(operation.Name, operation.Schema) != null) { +#if !NET8_0 var entity = model?.GetRelationalModel().FindTable(operation.Name, operation.Schema)!.EntityTypeMappings.FirstOrDefault()!.EntityType; +#else + var entity = model?.GetRelationalModel().FindTable(operation.Name, operation.Schema)!.EntityTypeMappings.FirstOrDefault()!.TypeBase; +#endif + var charset = entity?.FindAnnotation(MySQLAnnotationNames.Charset); if (charset != null) { diff --git a/EFCore/src/MySql.EntityFrameworkCore.csproj b/EFCore/src/MySql.EntityFrameworkCore.csproj index 379b4289a..5df7f82ed 100644 --- a/EFCore/src/MySql.EntityFrameworkCore.csproj +++ b/EFCore/src/MySql.EntityFrameworkCore.csproj @@ -32,8 +32,8 @@ - - + + diff --git a/EFCore/src/Query/Expressions/Internal/MySQLStringComparisonMethodTranslator.cs b/EFCore/src/Query/Expressions/Internal/MySQLStringComparisonMethodTranslator.cs index a9427da6a..174e19ff8 100644 --- a/EFCore/src/Query/Expressions/Internal/MySQLStringComparisonMethodTranslator.cs +++ b/EFCore/src/Query/Expressions/Internal/MySQLStringComparisonMethodTranslator.cs @@ -34,6 +34,7 @@ using MySql.EntityFrameworkCore.Query.Internal; using System; using System.Collections.Generic; +using System.Linq; using System.Reflection; using System.Text; using static MySql.EntityFrameworkCore.Utils.Statics; @@ -165,6 +166,7 @@ public MySQLStringComparisonMethodTranslator(ISqlExpressionFactory sqlExpression } else { + #if !NET8_0 return new CaseExpression( new[] { @@ -183,6 +185,26 @@ public MySQLStringComparisonMethodTranslator(ISqlExpressionFactory sqlExpression Utf8Bin(LCase(rightValue)) ) ); +#else + return new CaseExpression( + new[] + { + new CaseWhenClause( + _sqlExpressionFactory.In(stringComparison,(IReadOnlyList)_caseSensitiveComparisons), + // Case sensitive, accent sensitive + _sqlExpressionFactory.Equal( + leftValue, + Utf8Bin(rightValue) + ) + ) + }, + // Case insensitive, accent sensitive + _sqlExpressionFactory.Equal( + LCase(leftValue), + Utf8Bin(LCase(rightValue)) + ) + ); +#endif } } @@ -210,6 +232,7 @@ public MySQLStringComparisonMethodTranslator(ISqlExpressionFactory sqlExpression } else { +#if !NET8_0 return new CaseExpression( new[] { @@ -229,6 +252,27 @@ public MySQLStringComparisonMethodTranslator(ISqlExpressionFactory sqlExpression Utf8Bin(LCase(prefix)) ) ); +#else + return new CaseExpression( + new[] + { + new CaseWhenClause( + _sqlExpressionFactory.In(stringComparison,(IReadOnlyList) _caseSensitiveComparisons), + // Case sensitive, accent sensitive + MakeStartsWithExpressionImpl( + target, + Utf8Bin(prefix), + originalPrefix: prefix + ) + ) + }, + // Case insensitive, accent sensitive + MakeStartsWithExpressionImpl( + LCase(target), + Utf8Bin(LCase(prefix)) + ) + ); +#endif } } @@ -286,6 +330,7 @@ private SqlBinaryExpression MakeStartsWithExpressionImpl( } else { +#if !NET8_0 return new CaseExpression( new[] { @@ -306,6 +351,28 @@ private SqlBinaryExpression MakeStartsWithExpressionImpl( suffix ) ); +#else + return new CaseExpression( + new[] + { + new CaseWhenClause( + _sqlExpressionFactory.In(stringComparison,(IReadOnlyList) _caseSensitiveComparisons), + // Case sensitive, accent sensitive + MakeEndsWithExpressionImpl( + target, + Utf8Bin(suffix), + suffix + ) + ) + }, + // Case insensitive, accent sensitive + MakeEndsWithExpressionImpl( + LCase(target), + Utf8Bin(LCase(suffix)), + suffix + ) + ); +#endif } } @@ -379,6 +446,7 @@ private SqlExpression MakeEndsWithExpressionImpl( } else { +#if !NET8_0 return new CaseExpression( new[] { @@ -401,6 +469,30 @@ private SqlExpression MakeEndsWithExpressionImpl( e => Utf8Bin(LCase(e)) ) ); +#else + return new CaseExpression( + new[] + { + new CaseWhenClause( + _sqlExpressionFactory.In(stringComparison,(IReadOnlyList) _caseSensitiveComparisons), + // Case sensitive, accent sensitive + MakeContainsExpressionImpl( + target, + e => e, + search, + e => Utf8Bin(e) + ) + ) + }, + // Case insensitive, accent sensitive + MakeContainsExpressionImpl( + target, + e => LCase(e), + search, + e => Utf8Bin(LCase(e)) + ) + ); +#endif } } private SqlExpression MakeContainsExpressionImpl( @@ -473,14 +565,12 @@ private SqlExpression MakeContainsExpressionImpl( e => Utf8Bin(LCase(e)))); } +#if !NET8_0 return _sqlExpressionFactory.Case( new[] { new CaseWhenClause( - _sqlExpressionFactory.In( - stringComparison, - _caseSensitiveComparisons, - false), + _sqlExpressionFactory.In(stringComparison, _caseSensitiveComparisons, false), // Case sensitive, accent sensitive MakeIndexOfExpressionImpl( target, @@ -494,6 +584,26 @@ private SqlExpression MakeContainsExpressionImpl( e => LCase(e), search, e => Utf8Bin(LCase(e)))); +#else + return _sqlExpressionFactory.Case( + new[] + { + new CaseWhenClause( + _sqlExpressionFactory.In(stringComparison, (IReadOnlyList)_caseSensitiveComparisons), + // Case sensitive, accent sensitive + MakeIndexOfExpressionImpl( + target, + e => e, + search, + e => Utf8Bin(e))) + }, + // Case insensitive, accent sensitive + MakeIndexOfExpressionImpl( + target, + e => LCase(e), + search, + e => Utf8Bin(LCase(e)))); +#endif } private SqlExpression MakeIndexOfExpressionImpl( diff --git a/EFCore/src/Storage/Internal/MySQLGeometryTypeMapping.cs b/EFCore/src/Storage/Internal/MySQLGeometryTypeMapping.cs index 73ad2d675..3935f085c 100644 --- a/EFCore/src/Storage/Internal/MySQLGeometryTypeMapping.cs +++ b/EFCore/src/Storage/Internal/MySQLGeometryTypeMapping.cs @@ -43,8 +43,13 @@ protected MySQLGeometryTypeMapping(RelationalTypeMappingParameters parameters) { } +#if NET8_0 + public CoreTypeMapping Clone(ValueConverter? converter) + => new MySQLGeometryTypeMapping(Parameters.WithComposedConverter(converter,null,null,null,null)); +#else public override CoreTypeMapping Clone(ValueConverter? converter) => new MySQLGeometryTypeMapping(Parameters.WithComposedConverter(converter)); +#endif protected override void ConfigureParameter(DbParameter parameter) { diff --git a/EFCore/src/Storage/Internal/MySQLTypeMappingSource.cs b/EFCore/src/Storage/Internal/MySQLTypeMappingSource.cs index 229bf8ab2..273f5617d 100644 --- a/EFCore/src/Storage/Internal/MySQLTypeMappingSource.cs +++ b/EFCore/src/Storage/Internal/MySQLTypeMappingSource.cs @@ -187,12 +187,21 @@ protected void Initialize() { typeof(byte), _utinyint }, { typeof(sbyte), _tinyint }, + #if !NET8_0 // DateTime { typeof(DateTime), _datetime.Clone(6, null) }, { typeof(DateOnly), _dateonly }, { typeof(DateTimeOffset), _datetimeoffset.Clone(6, null) }, { typeof(TimeSpan), _time.Clone(6, null) }, { typeof(TimeOnly), _timeonly }, + #else + // DateTime + { typeof(DateTime), _datetime.WithPrecisionAndScale(6, null) }, + { typeof(DateOnly), _dateonly }, + { typeof(DateTimeOffset), _datetimeoffset.Clone() }, + { typeof(TimeSpan), _time.WithPrecisionAndScale(6, null) }, + { typeof(TimeOnly), _timeonly }, + #endif // decimals { typeof(float), _float }, @@ -243,9 +252,15 @@ protected void Initialize() if (_storeTypeMappings.TryGetValue(storeTypeNameBase!, out mapping)) { +#if !NET8_0 return clrType == null ? mapping[0].Clone(in mappingInfo) : mapping.FirstOrDefault(m => m.ClrType == clrType)?.Clone(in mappingInfo); +#else + return clrType == null + ? mapping[0].WithTypeMappingInfo(mappingInfo) + : mapping.FirstOrDefault(m => m.ClrType == clrType)?.WithTypeMappingInfo(mappingInfo); +#endif } } @@ -259,7 +274,11 @@ protected void Initialize() clrType == typeof(DateTimeOffset) || clrType == typeof(TimeSpan)) { +#if !NET8_0 return mapping.Clone(mappingInfo.Precision.Value, null); +#else + return mapping.WithPrecisionAndScale(mappingInfo.Precision.Value, null); +#endif } } @@ -282,7 +301,11 @@ protected void Initialize() mapping = isFixedLength ? _charUnicode : size == null ? _longtextUnicode : _varcharUnicode; +#if !NET8_0 return size == null ? mapping : mapping.Clone($"{mapping.StoreTypeNameBase}({size})", size); +#else + return size == null ? mapping : mapping.WithStoreTypeAndSize($"{mapping.StoreTypeNameBase}({size})", size); +#endif } else if (clrType == typeof(byte[])) { @@ -297,6 +320,7 @@ protected void Initialize() return null; } +#if !NET8_0 protected override string ParseStoreTypeName(string? storeTypeName, out bool? unicode, out int? size, out int? precision, out int? scale) { var storeTypeBaseName = base.ParseStoreTypeName(storeTypeName, out unicode, out size, out precision, out scale); @@ -305,5 +329,15 @@ protected override string ParseStoreTypeName(string? storeTypeName, out bool? un ? storeTypeBaseName + " unsigned" : storeTypeBaseName!; } +#else + protected string ParseStoreTypeName(string? storeTypeName, ref bool? unicode, ref int? size, ref int? precision, ref int? scale) + { + var storeTypeBaseName = base.ParseStoreTypeName(storeTypeName, ref unicode, ref size, ref precision, ref scale); + + return (storeTypeName?.IndexOf("unsigned", StringComparison.OrdinalIgnoreCase) ?? -1) >= 0 + ? storeTypeBaseName + " unsigned" + : storeTypeBaseName!; + } +#endif } } \ No newline at end of file diff --git a/EFCore/src/ValueGeneration/Internal/MySQLValueGeneratorSelector.cs b/EFCore/src/ValueGeneration/Internal/MySQLValueGeneratorSelector.cs index a991c381d..0f4e52a1e 100644 --- a/EFCore/src/ValueGeneration/Internal/MySQLValueGeneratorSelector.cs +++ b/EFCore/src/ValueGeneration/Internal/MySQLValueGeneratorSelector.cs @@ -52,7 +52,23 @@ public MySQLValueGeneratorSelector( } + #if NET8_0 /// + public ValueGenerator Create(IProperty property, IEntityType entityType) + { + Check.NotNull(property, nameof(property)); + Check.NotNull(entityType, nameof(entityType)); + + var ret = property.ClrType.UnwrapNullableType() == typeof(Guid) + ? property.ValueGenerated == ValueGenerated.Never + || property.GetDefaultValueSql() != null + ? (ValueGenerator)new TemporaryGuidValueGenerator() + : new SequentialGuidValueGenerator() + : base.Create(property, entityType); + return ret; + } +#else + /// public override ValueGenerator Create(IProperty property, IEntityType entityType) { Check.NotNull(property, nameof(property)); @@ -66,5 +82,6 @@ public override ValueGenerator Create(IProperty property, IEntityType entityType : base.Create(property, entityType); return ret; } +#endif } } diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/MySql.EntityFrameworkCore.Basic.Tests.csproj b/EFCore/tests/MySql.EFCore.Basic.Tests/MySql.EntityFrameworkCore.Basic.Tests.csproj index 6fb99961f..895966926 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/MySql.EntityFrameworkCore.Basic.Tests.csproj +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/MySql.EntityFrameworkCore.Basic.Tests.csproj @@ -22,11 +22,11 @@ - + - + diff --git a/EFCore/tests/MySql.EFCore.Design.Tests/MySql.EntityFrameworkCore.Design.Tests.csproj b/EFCore/tests/MySql.EFCore.Design.Tests/MySql.EntityFrameworkCore.Design.Tests.csproj index 7ce9788d5..86eaa62e7 100644 --- a/EFCore/tests/MySql.EFCore.Design.Tests/MySql.EntityFrameworkCore.Design.Tests.csproj +++ b/EFCore/tests/MySql.EFCore.Design.Tests/MySql.EntityFrameworkCore.Design.Tests.csproj @@ -24,8 +24,8 @@ - - + + diff --git a/EFCore/tests/MySql.EFCore.Migrations.Tests/MySql.EntityFrameworkCore.Migrations.Tests.csproj b/EFCore/tests/MySql.EFCore.Migrations.Tests/MySql.EntityFrameworkCore.Migrations.Tests.csproj index 820f237f9..fd2e0ef96 100644 --- a/EFCore/tests/MySql.EFCore.Migrations.Tests/MySql.EntityFrameworkCore.Migrations.Tests.csproj +++ b/EFCore/tests/MySql.EFCore.Migrations.Tests/MySql.EntityFrameworkCore.Migrations.Tests.csproj @@ -14,7 +14,7 @@ - + diff --git a/MySQL.Data/src/MySqlDataReader.cs b/MySQL.Data/src/MySqlDataReader.cs index 3626cddfc..87d122fc6 100644 --- a/MySQL.Data/src/MySqlDataReader.cs +++ b/MySQL.Data/src/MySqlDataReader.cs @@ -336,7 +336,11 @@ public sbyte GetSByte(int i) if (v is MySqlByte) return (sbyte)ChangeType(v, i, typeof(sbyte)); else +#if !NET8_0 return checked(((MySqlByte)v).Value); +#else + return checked((sbyte)((MySqlUByte)v).Value); +#endif } /// From c78d8cc9defa5276119e3066f9d26c56c4fecbfe Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Mon, 4 Dec 2023 00:03:49 -0700 Subject: [PATCH 010/125] Bug#35827809 [Connector/Net allows a connection that has been disposed to be reopened.] Change-Id: I7b2755fbe26e428ca38283033f2cc5cbf568f93e --- CHANGES | 1 + MySQL.Data/src/MySqlConnection.cs | 6 ++++++ .../tests/MySql.Data.Tests/ConnectionTests.cs | 15 +++++++++++++++ 3 files changed, 22 insertions(+) diff --git a/CHANGES b/CHANGES index 8ce957c3d..b8abb2190 100644 --- a/CHANGES +++ b/CHANGES @@ -7,6 +7,7 @@ - Added missing README files to Nuget packages (WL16041). - Upgraded the Google.Protobuf dependency to version 3.25.1 (WL16075). - Added support for .NET 8 and EFCore 8 GA versions (WL16035). +- Fixed a bug that permitted to open a disposed connection (MySQL bug #112399, Oracle bug #35827809). 8.2.0 diff --git a/MySQL.Data/src/MySqlConnection.cs b/MySQL.Data/src/MySqlConnection.cs index 31a0f43b4..2fa3cbb50 100644 --- a/MySQL.Data/src/MySqlConnection.cs +++ b/MySQL.Data/src/MySqlConnection.cs @@ -73,6 +73,7 @@ public sealed class MySqlConnection : DbConnection, ICloneable internal ConnectionState connectionState; internal Driver driver; internal bool hasBeenOpen; + internal bool hasBeenDisposed; private SchemaProvider _schemaProvider; private ExceptionInterceptor _exceptionInterceptor; internal CommandInterceptor commandInterceptor; @@ -115,6 +116,7 @@ public MySqlConnection() //TODO: add event data to StateChange docs Settings = new MySqlConnectionStringBuilder(); _database = String.Empty; + hasBeenDisposed = false; } /// @@ -355,6 +357,7 @@ protected override void Dispose(bool disposing) { if (State == ConnectionState.Open) Close(); + hasBeenDisposed = true; base.Dispose(disposing); } @@ -599,6 +602,9 @@ internal async Task OpenAsync(bool execAsync, CancellationToken cancellationToke if (State != ConnectionState.Closed) Throw(new InvalidOperationException(Resources.ConnectionAlreadyOpen)); + if (hasBeenDisposed) + Throw(new InvalidOperationException("The connection had been disposed.")); + // start up our interceptors _exceptionInterceptor = new ExceptionInterceptor(this); commandInterceptor = new CommandInterceptor(this); diff --git a/MySQL.Data/tests/MySql.Data.Tests/ConnectionTests.cs b/MySQL.Data/tests/MySql.Data.Tests/ConnectionTests.cs index 7a06c2e24..5ceaede9d 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/ConnectionTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/ConnectionTests.cs @@ -132,6 +132,21 @@ private void CreateCommandTimeoutException() } } + /// + /// Bug#35827809 Connector/Net allows a connection that has been disposed to be reopened. + /// + [Test] + public void ReOpenDisposedConnection() + { + using (MySqlConnection c = new MySqlConnection(Connection.ConnectionString)) + { + c.Open(); + c.Close(); + c.Dispose(); + Assert.Throws(() => c.Open()); + } + } + [Test] public void ConnectingAsUTF8() { From 316b7169ca28469e5d0df01efc11eef188a6d5b9 Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Tue, 5 Dec 2023 11:03:47 -0700 Subject: [PATCH 011/125] WL#15792 [Fix broken .GetString() behavior on reader] - fixed broken test cases Change-Id: Ibe58405186e02b4ee63556c6caeaf1660e3ce2f5 --- EFCore/tests/MySql.EFCore.Basic.Tests/ModelingTests.cs | 2 +- MySQL.Data/tests/MySql.Data.Tests/ParameterTests.cs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/ModelingTests.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/ModelingTests.cs index 1f696ae53..3df9fb4a3 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/ModelingTests.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/ModelingTests.cs @@ -189,7 +189,7 @@ public void ConvertToType() ls = context.Actor.OrderBy(a => a.ActorId).Select(b => new ActorTest { Number = Convert.ToInt32(b.ActorId), - Value = Convert.ToString(b.LastUpdate), + Value = b.LastUpdate.ToString(), Text = b.FirstName, }).ToList(); diff --git a/MySQL.Data/tests/MySql.Data.Tests/ParameterTests.cs b/MySQL.Data/tests/MySql.Data.Tests/ParameterTests.cs index fccf44018..50e1bb808 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/ParameterTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/ParameterTests.cs @@ -234,9 +234,9 @@ public void MemoryStreamAsParameterValue() using (MySqlDataReader reader = cmd.ExecuteReader()) { reader.Read(); - Assert.AreEqual("abcd", reader.GetString(0)); - Assert.AreEqual("efgh", reader.GetString(1)); - Assert.AreEqual("5678", reader.GetString(2)); + Assert.AreEqual("abcd", reader.GetTextReader(0).ReadToEnd()); + Assert.AreEqual("efgh", reader.GetTextReader(1).ReadToEnd()); + Assert.AreEqual("5678", reader.GetTextReader(2).ReadToEnd()); } } } From 39564b48d5cf68aa4933df2c2976781b4a678cbe Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Tue, 5 Dec 2023 12:43:34 -0700 Subject: [PATCH 012/125] Updated version number references in documentation. Change-Id: Ie608f26a919f33736b28709b83831f599b155476 --- Documentation/docfx.json | 2 +- Documentation/index.md | 4 ++-- README.md | 2 ++ Release Notes.txt | 9 ++++----- 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/Documentation/docfx.json b/Documentation/docfx.json index 0989b6025..38e1770f7 100644 --- a/Documentation/docfx.json +++ b/Documentation/docfx.json @@ -28,7 +28,7 @@ } ], "dest": "api/efcore_api", - "properties": { "TargetFramework": "net7.0" } + "properties": { "TargetFramework": "net8.0" } }, { "src": [ diff --git a/Documentation/index.md b/Documentation/index.md index ad6cc25d6..00ffbfdfc 100644 --- a/Documentation/index.md +++ b/Documentation/index.md @@ -1,6 +1,6 @@ ## MySQL Connector/NET and X DevAPI -MySQL Connector/NET 8.2 supports X Protocol, which enables you to use X DevAPI with the .NET language of choice to develop applications that communicate with a MySQL server functioning as a document store, relational database, or both. +MySQL Connector/NET 8.3 supports X Protocol, which enables you to use X DevAPI with the .NET language of choice to develop applications that communicate with a MySQL server functioning as a document store, relational database, or both. To get started, review the following main classes: @@ -16,7 +16,7 @@ For an introduction to X DevAPI concepts, see the [X DevAPI User Guide](https:// ## MySQL Connector/NET -MySQL Connector/NET 8.2 also supports the development of .NET, .NET Core and .NET Framework applications that require secure, high-performance data connectivity with MySQL through the classic protocol. It supports ADO.NET, Entity Framework and various web providers. +MySQL Connector/NET 8.3 also supports the development of .NET, .NET Core and .NET Framework applications that require secure, high-performance data connectivity with MySQL through the classic protocol. It supports ADO.NET, Entity Framework and various web providers. To get started, review the following main classes: diff --git a/README.md b/README.md index e3616a5f6..a9bdb7f44 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,8 @@ From MySQL Connector/NET 8.1, the driver contains an implementation of [OpenTele From MySQL Connector/NET 8.2, the driver adds support for [WebAuthn authentication](https://dev.mysql.com/doc/dev/connector-net/latest/api/data_api/MySql.Data.MySqlClient.WebAuthnActionCallback.html), the driver also adds support for [.NET 8](https://learn.microsoft.com/en-us/dotnet/core/whats-new/dotnet-8). +From MySQL Connector/NET 8.3, the driver also adds support for [.NET 8](https://learn.microsoft.com/en-us/dotnet/core/whats-new/dotnet-8) and [EFCore 8](https://learn.microsoft.com/en-us/ef/core/what-is-new/ef-core-8.0/whatsnew) GA versions. + For detailed information please visit the official [MySQL Connector/NET documentation.](https://dev.mysql.com/doc/connector-net/en/) ## Licensing diff --git a/Release Notes.txt b/Release Notes.txt index c581b031e..8d0350ec8 100644 --- a/Release Notes.txt +++ b/Release Notes.txt @@ -1,9 +1,8 @@ -Connector/NET 8.2 Release Notes +Connector/NET 8.3 Release Notes ------------------------------------ -Welcome to the release notes for Connector/NET 8.2 +Welcome to the release notes for Connector/NET 8.3 -What's new in 8.2 +What's new in 8.3 -------------------- -Connector/NET added support for the preview version of .NET 8, if you want know more about .NET 8 see (https://learn.microsoft.com/en-us/dotnet/core/whats-new/dotnet-8). -Connector/NET added support for WebAuthn authentication, if you want to know more about it please visit (https://dev.mysql.com/doc/dev/connector-net/latest/api/data_api/MySql.Data.MySqlClient.WebAuthnActionCallback.html). \ No newline at end of file +Connector/NET added support for the GA version of .NET 8 and EF Core 8, if you want know more about .NET 8 see (https://learn.microsoft.com/en-us/dotnet/core/whats-new/dotnet-8). \ No newline at end of file From 4fd6a45f131bdf43eb80abe4f0db91c265fc7015 Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Tue, 5 Dec 2023 12:46:36 -0700 Subject: [PATCH 013/125] Updated year in copyright notices. Change-Id: I60436b404b5378190f69fe8e394a5125736fcbdf --- Documentation/docfx.json | 2 +- README | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/docfx.json b/Documentation/docfx.json index 38e1770f7..cd6e78456 100644 --- a/Documentation/docfx.json +++ b/Documentation/docfx.json @@ -77,7 +77,7 @@ } ], "globalMetadata": { - "_appFooter": "Copyright © 2021, 2023, Oracle and/or its affiliates.", + "_appFooter": "Copyright © 2021, 2024, Oracle and/or its affiliates.", "_appLogoPath": "/images/logo.svg", "_appFaviconPath": "/images/favicon.ico", "_enableSearch": true diff --git a/README b/README index c8a7f1dcb..4448edd0b 100644 --- a/README +++ b/README @@ -1,4 +1,4 @@ -Copyright (c) 2004, 2023, Oracle and/or its affiliates. +Copyright (c) 2004, 2024, Oracle and/or its affiliates. This is a release of MySQL Connector/NET, Oracle's fully managed ADO .NET Driver for MySQL. From 83acdcea40b6f747bcd0500c3bca2342015d9947 Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Tue, 5 Dec 2023 12:54:02 -0700 Subject: [PATCH 014/125] Updated copyright year in protobuf files. Change-Id: I6cd6a7faf22fa47a5f074082579b56a21cd6a1fc --- MySQL.Data/src/X/Protocol/X/Protobuf/Mysqlx.cs | 2 +- MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxConnection.cs | 2 +- MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxCrud.cs | 2 +- MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxCursor.cs | 2 +- MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxDatatypes.cs | 2 +- MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxExpect.cs | 2 +- MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxExpr.cs | 2 +- MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxNotice.cs | 2 +- MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxPrepare.cs | 2 +- MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxResultset.cs | 2 +- MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxSession.cs | 2 +- MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxSql.cs | 2 +- 12 files changed, 12 insertions(+), 12 deletions(-) diff --git a/MySQL.Data/src/X/Protocol/X/Protobuf/Mysqlx.cs b/MySQL.Data/src/X/Protocol/X/Protobuf/Mysqlx.cs index c5c48b4fd..7231626fb 100644 --- a/MySQL.Data/src/X/Protocol/X/Protobuf/Mysqlx.cs +++ b/MySQL.Data/src/X/Protocol/X/Protobuf/Mysqlx.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2023, Oracle and/or its affiliates. +// Copyright (c) 2022, 2023, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxConnection.cs b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxConnection.cs index 73e4f7769..697f6e772 100644 --- a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxConnection.cs +++ b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxConnection.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2023, Oracle and/or its affiliates. +// Copyright (c) 2022, 2023, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxCrud.cs b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxCrud.cs index bd891ca50..e43d0163b 100644 --- a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxCrud.cs +++ b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxCrud.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2023, Oracle and/or its affiliates. +// Copyright (c) 2022, 2023, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxCursor.cs b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxCursor.cs index a6afe056b..df947e05c 100644 --- a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxCursor.cs +++ b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxCursor.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2023, Oracle and/or its affiliates. +// Copyright (c) 2022, 2023, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxDatatypes.cs b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxDatatypes.cs index 42027d377..6ffd395a8 100644 --- a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxDatatypes.cs +++ b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxDatatypes.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2023, Oracle and/or its affiliates. +// Copyright (c) 2022, 2023, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxExpect.cs b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxExpect.cs index f5278dbe2..5903d8778 100644 --- a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxExpect.cs +++ b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxExpect.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2023, Oracle and/or its affiliates. +// Copyright (c) 2022, 2023, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxExpr.cs b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxExpr.cs index 56f669b41..fb1317250 100644 --- a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxExpr.cs +++ b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxExpr.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2023, Oracle and/or its affiliates. +// Copyright (c) 2022, 2023, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxNotice.cs b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxNotice.cs index f431ab8ac..fba7e1be2 100644 --- a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxNotice.cs +++ b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxNotice.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2023, Oracle and/or its affiliates. +// Copyright (c) 2022, 2023, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxPrepare.cs b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxPrepare.cs index bcf88607b..e0b207234 100644 --- a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxPrepare.cs +++ b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxPrepare.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2023, Oracle and/or its affiliates. +// Copyright (c) 2022, 2023, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxResultset.cs b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxResultset.cs index bcbd7bd38..4a3e37447 100644 --- a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxResultset.cs +++ b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxResultset.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2023, Oracle and/or its affiliates. +// Copyright (c) 2022, 2023, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxSession.cs b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxSession.cs index 5226f524b..917d53581 100644 --- a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxSession.cs +++ b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxSession.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2023, Oracle and/or its affiliates. +// Copyright (c) 2022, 2023, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxSql.cs b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxSql.cs index 7540472fc..52856d584 100644 --- a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxSql.cs +++ b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxSql.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2023, Oracle and/or its affiliates. +// Copyright (c) 2022, 2023, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as From 877534c4a587de2f9544000e4b787bc237e1d60c Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Tue, 5 Dec 2023 15:52:08 -0700 Subject: [PATCH 015/125] Updated EF Core project versions. Change-Id: I023fd2b781c1bf0a299af0d16e2aadce1bb47cf8 --- EFCore/src/MySql.EntityFrameworkCore.csproj | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/EFCore/src/MySql.EntityFrameworkCore.csproj b/EFCore/src/MySql.EntityFrameworkCore.csproj index 5df7f82ed..f0d8c2a31 100644 --- a/EFCore/src/MySql.EntityFrameworkCore.csproj +++ b/EFCore/src/MySql.EntityFrameworkCore.csproj @@ -22,13 +22,13 @@ - - + + - - + + From 94cc3971f3d30adece4d7d72628989cde08a92e5 Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Tue, 5 Dec 2023 15:55:23 -0700 Subject: [PATCH 016/125] Updated LIUMS. Change-Id: I2c58845e86e9574bb51b5af6f57c6df513bc5e47 --- LICENSE | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/LICENSE b/LICENSE index f1204f0e0..48062d95d 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ Licensing Information User Manual -MySQL Connector/NET 8.2.0 Community +MySQL Connector/NET 8.3.0 Community __________________________________________________________________ Introduction @@ -8,18 +8,18 @@ Introduction This License Information User Manual contains Oracle's product license and other licensing information, including licensing information for third-party software which may be included in this distribution of - MySQL Connector/NET 8.2.0 Community. + MySQL Connector/NET 8.3.0 Community. - Last updated: September 2023 + Last updated: November 2023 Licensing Information - This release of MySQL Connector/NET 8.2.0 Community is brought to you + This release of MySQL Connector/NET 8.3.0 Community is brought to you by the MySQL team at Oracle. This software is released under version 2 of the GNU General Public License (GPLv2), as set forth below, with the following additional permissions: - This distribution of MySQL Connector/NET 8.2.0 Community is distributed + This distribution of MySQL Connector/NET 8.3.0 Community is distributed with certain software (including but not limited to OpenSSL) that is licensed under separate terms, as designated in a particular file or component or in the license documentation. Without limiting your rights From 281f27d9feb79cd51196451d71dae6cf35915cad Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Tue, 5 Dec 2023 19:11:11 -0700 Subject: [PATCH 017/125] WL#15792 [Fix broken .GetString() behavior on reader] - fixed test cases Change-Id: Iaf043bd8b394e7ade288c91cd856f24303fbb4c0 --- MySQL.Data/tests/MySql.Data.Tests/ParameterTests.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/MySQL.Data/tests/MySql.Data.Tests/ParameterTests.cs b/MySQL.Data/tests/MySql.Data.Tests/ParameterTests.cs index 50e1bb808..b3badb9b2 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/ParameterTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/ParameterTests.cs @@ -31,6 +31,7 @@ using System.Data; using System.Diagnostics; using System.IO; +using System.Text; namespace MySql.Data.MySqlClient.Tests { @@ -234,9 +235,9 @@ public void MemoryStreamAsParameterValue() using (MySqlDataReader reader = cmd.ExecuteReader()) { reader.Read(); - Assert.AreEqual("abcd", reader.GetTextReader(0).ReadToEnd()); - Assert.AreEqual("efgh", reader.GetTextReader(1).ReadToEnd()); - Assert.AreEqual("5678", reader.GetTextReader(2).ReadToEnd()); + Assert.AreEqual("abcd", Convert.ToString(reader[0])); + Assert.AreEqual("efgh", Encoding.Default.GetString((byte[])reader[1])); + Assert.AreEqual("5678", Convert.ToString(reader[2])); } } } From 0bb0e8c4d9f327138e758b6a31c3d8ebb70a2eae Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Tue, 5 Dec 2023 19:40:36 -0700 Subject: [PATCH 018/125] Bug#35827809 [Connector/Net allows a connection that has been disposed to be reopened.] - fixed relational connection in EFCore Change-Id: Ibaf30bebede11d0f471af5a85abba1d99e0cdde0 --- EFCore/src/Storage/Internal/MySQLRelationalConnection.cs | 4 ++++ MySQL.Data/src/MySqlConnection.cs | 6 ++++++ 2 files changed, 10 insertions(+) diff --git a/EFCore/src/Storage/Internal/MySQLRelationalConnection.cs b/EFCore/src/Storage/Internal/MySQLRelationalConnection.cs index b2f2c0cb2..bdebfdc79 100644 --- a/EFCore/src/Storage/Internal/MySQLRelationalConnection.cs +++ b/EFCore/src/Storage/Internal/MySQLRelationalConnection.cs @@ -83,12 +83,16 @@ public virtual IMySQLRelationalConnection CreateSourceConnection() public override bool Open(bool errorsExpected = false) { + if (DbConnection.IsDisposed) + DbConnection = (MySqlConnection)CreateDbConnection(); var result = base.Open(errorsExpected); return result; } public override async Task OpenAsync(CancellationToken cancellationToken, bool errorsExpected = false) { + if (DbConnection.IsDisposed) + DbConnection = (MySqlConnection)CreateDbConnection(); return await base.OpenAsync(cancellationToken, errorsExpected).ConfigureAwait(false); } } diff --git a/MySQL.Data/src/MySqlConnection.cs b/MySQL.Data/src/MySqlConnection.cs index 2fa3cbb50..f2a7f5851 100644 --- a/MySQL.Data/src/MySqlConnection.cs +++ b/MySQL.Data/src/MySqlConnection.cs @@ -251,6 +251,12 @@ internal bool SoftClosed [Browsable(false)] public override ConnectionState State => connectionState; + [Browsable(true)] + /// + /// Gets a boolean indicating if the current connection had been disposed. + /// + public bool IsDisposed { get { return hasBeenDisposed; } } + /// Gets a string containing the version of the MySQL server to which the client is connected. /// The version of the instance of MySQL. /// The connection is closed. From 6be9b86383701f4d6306590ec33df6475b5d81cd Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Sun, 28 Jan 2024 16:32:00 -0700 Subject: [PATCH 019/125] Bump up version to 8.4.0 Change-Id: Ic8490e909f79365b8147adc96f94e34ff24bb8c5 --- CHANGES | 3 +++ .../templates/custom/partials/class.header.tmpl.partial | 2 +- EntityFramework/src/MySql.Data.EntityFramework.csproj | 4 ++-- .../MySql.EntityFramework.Basic.Tests.csproj | 2 +- .../MySql.EntityFramework.CodeFirst.Tests.csproj | 2 +- .../MySql.EntityFramework.Migrations.Tests.csproj | 2 +- .../src/MySQL.Data.OpenTelemetry.csproj | 6 +++--- MySQL.Data/src/MySql.Data.csproj | 6 +++--- MySQL.Data/src/Properties/VersionInfo.cs | 4 ++-- MySQL.Data/tests/MySql.Data.Tests/MySql.Data.Tests.csproj | 2 +- MySQL.Data/tests/MySqlX.Data.Tests/MySqlX.Data.Tests.csproj | 2 +- MySql.Web/src/MySql.Web.csproj | 4 ++-- MySql.Web/tests/MySql.Web.Tests.csproj | 2 +- 13 files changed, 22 insertions(+), 19 deletions(-) diff --git a/CHANGES b/CHANGES index b8abb2190..068294302 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,6 @@ +8.4.0 + + 8.3.0 - Added support for build traversal (WL15798). - Added AssemblyInfo file to MySQL.Data.OpenTelemetry (Oracle Bug #35957212). diff --git a/Documentation/templates/custom/partials/class.header.tmpl.partial b/Documentation/templates/custom/partials/class.header.tmpl.partial index 362f24e4a..a5e724eed 100644 --- a/Documentation/templates/custom/partials/class.header.tmpl.partial +++ b/Documentation/templates/custom/partials/class.header.tmpl.partial @@ -25,7 +25,7 @@ {{/implements.0}}
{{__global.namespace}}: {{{namespace.specName.0.value}}}
{{__global.assembly}}: {{assemblies.0}}.dll
-
Version: 8.3.0
+
Version: 8.4.0
{{__global.syntax}}
{{syntax.content.0.value}}
diff --git a/EntityFramework/src/MySql.Data.EntityFramework.csproj b/EntityFramework/src/MySql.Data.EntityFramework.csproj index fb8a66f20..42ba730d8 100644 --- a/EntityFramework/src/MySql.Data.EntityFramework.csproj +++ b/EntityFramework/src/MySql.Data.EntityFramework.csproj @@ -4,7 +4,7 @@ MySql.Data.EntityFramework Copyright (c) 2016, 2023, Oracle and/or its affiliates. en-US - 8.3.0 + 8.4.0 Oracle net462;netstandard2.1; $(NoWarn);CS1591 @@ -29,7 +29,7 @@ - + diff --git a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/MySql.EntityFramework.Basic.Tests.csproj b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/MySql.EntityFramework.Basic.Tests.csproj index 1d1574764..548d2bb0c 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/MySql.EntityFramework.Basic.Tests.csproj +++ b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/MySql.EntityFramework.Basic.Tests.csproj @@ -4,7 +4,7 @@ MySql.Data.EntityFramework.CodeFirTests Copyright (c) 2016, 2023, Oracle and/or its affiliates. en-US - 8.3.0 + 8.4.0 Oracle net7.0 MySql.EntityFramework.Basic.Tests diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/MySql.EntityFramework.CodeFirst.Tests.csproj b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/MySql.EntityFramework.CodeFirst.Tests.csproj index 7f7c1c2be..5e91bd5af 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/MySql.EntityFramework.CodeFirst.Tests.csproj +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/MySql.EntityFramework.CodeFirst.Tests.csproj @@ -4,7 +4,7 @@ MySql.Data.EntityFramework.CodeFirst.Tests Copyright (c) 2016, 2023, Oracle and/or its affiliates. en-US - 8.3.0 + 8.4.0 Oracle net7.0 MySql.EntityFramework.CodeFirst.Tests diff --git a/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/MySql.EntityFramework.Migrations.Tests.csproj b/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/MySql.EntityFramework.Migrations.Tests.csproj index 8912bf929..a7ad7c9a2 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/MySql.EntityFramework.Migrations.Tests.csproj +++ b/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/MySql.EntityFramework.Migrations.Tests.csproj @@ -4,7 +4,7 @@ MySql.Data.EntityFramework.Migrations.Tests Copyright (c) 2016, 2023, Oracle and/or its affiliates. en-US - 8.3.0 + 8.4.0 Oracle net7.0 MySql.EntityFramework.Migrations.Tests diff --git a/MySQL.Data.OpenTelemetry/src/MySQL.Data.OpenTelemetry.csproj b/MySQL.Data.OpenTelemetry/src/MySQL.Data.OpenTelemetry.csproj index 8e68c0f18..c9f9cf24d 100644 --- a/MySQL.Data.OpenTelemetry/src/MySQL.Data.OpenTelemetry.csproj +++ b/MySQL.Data.OpenTelemetry/src/MySQL.Data.OpenTelemetry.csproj @@ -1,10 +1,10 @@ - + MySql.Data.OpenTelemetry Copyright (c) 2023, Oracle and/or its affiliates. en-US - 8.3.0 + 8.4.0 Oracle netstandard2.0 MySql.Data.OpenTelemetry @@ -36,7 +36,7 @@ - + diff --git a/MySQL.Data/src/MySql.Data.csproj b/MySQL.Data/src/MySql.Data.csproj index 9b54e2055..1f435c3fc 100644 --- a/MySQL.Data/src/MySql.Data.csproj +++ b/MySQL.Data/src/MySql.Data.csproj @@ -1,11 +1,11 @@ - + MySql.Data.MySqlClient .Net Core Class Library Copyright (c) 2016, 2023, Oracle and/or its affiliates. en-US - 8.3.0 + 8.4.0 Oracle MySql.Data net462;net48;netstandard2.0;netstandard2.1;net6.0;net7.0;net8.0; @@ -39,7 +39,7 @@ - + diff --git a/MySQL.Data/src/Properties/VersionInfo.cs b/MySQL.Data/src/Properties/VersionInfo.cs index fd8a0e834..3316e3581 100644 --- a/MySQL.Data/src/Properties/VersionInfo.cs +++ b/MySQL.Data/src/Properties/VersionInfo.cs @@ -40,6 +40,6 @@ // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("8.3.0")] -[assembly: AssemblyInformationalVersion("8.3.0")] +[assembly: AssemblyVersion("8.4.0")] +[assembly: AssemblyInformationalVersion("8.4.0")] [assembly: NeutralResourcesLanguage("en-US")] \ No newline at end of file diff --git a/MySQL.Data/tests/MySql.Data.Tests/MySql.Data.Tests.csproj b/MySQL.Data/tests/MySql.Data.Tests/MySql.Data.Tests.csproj index bcc0455d3..68baf743f 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/MySql.Data.Tests.csproj +++ b/MySQL.Data/tests/MySql.Data.Tests/MySql.Data.Tests.csproj @@ -4,7 +4,7 @@ MySql.Data.Tests MySql.Data.Tests Class Library Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved. - 8.3.0 + 8.4.0 Oracle Oracle MySql.Data.Tests diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/MySqlX.Data.Tests.csproj b/MySQL.Data/tests/MySqlX.Data.Tests/MySqlX.Data.Tests.csproj index 388524ac9..3e23abe90 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/MySqlX.Data.Tests.csproj +++ b/MySQL.Data/tests/MySqlX.Data.Tests/MySqlX.Data.Tests.csproj @@ -4,7 +4,7 @@ MySql.Data.Tests MySql.Data.Tests Class Library Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved. - 8.3.0 + 8.4.0 Oracle Oracle MySql.Data.Tests diff --git a/MySql.Web/src/MySql.Web.csproj b/MySql.Web/src/MySql.Web.csproj index 5b03391f1..12aa57b06 100644 --- a/MySql.Web/src/MySql.Web.csproj +++ b/MySql.Web/src/MySql.Web.csproj @@ -4,7 +4,7 @@ MySql.Web Copyright (c) 2016, 2023, Oracle and/or its affiliates. en-US - 8.3.0 + 8.4.0 Oracle net462;net48; $(NoWarn);CS1591 @@ -33,7 +33,7 @@ - + diff --git a/MySql.Web/tests/MySql.Web.Tests.csproj b/MySql.Web/tests/MySql.Web.Tests.csproj index b6495a7f5..535a6939f 100644 --- a/MySql.Web/tests/MySql.Web.Tests.csproj +++ b/MySql.Web/tests/MySql.Web.Tests.csproj @@ -4,7 +4,7 @@ MySql.Web.Tests Copyright (c) 2016, 2023, Oracle and/or its affiliates. en-US - 8.3.0 + 8.4.0 Oracle net462;net48; MySql.Web.Tests From da00b0b9d559bac74e31d73eb1ba3d993b43887b Mon Sep 17 00:00:00 2001 From: Reggie Burnett Date: Fri, 9 Feb 2024 15:28:48 -0600 Subject: [PATCH 020/125] Squashed commit of the following: commit 0b2d1a9e1d182354ee558cdfff639934da456267 Author: Reggie Burnett Date: Mon Feb 5 16:31:30 2024 -0600 WL#16197 [GPL License Exception Update] Updated some files that were missed before. Change-Id: I968185d7377c2747dcdc6418133eb33a6cee8dcc Change-Id: Ic3ad63dcb630efcc9a6f5d8fdeff3da20be5f7bb --- CHANGES | 2 +- .../DataAnnotations/MySQLCharsetAttribute.cs | 16 +- .../MySQLCollationAttribute.cs | 16 +- .../Internal/MySQLAnnotationCodeGenerator.cs | 16 +- .../Internal/MySQLDesignTimeServices.cs | 16 +- .../Internal/MySQLLoggingDefinitions.cs | 18 +- EFCore/src/Diagnostics/MySQLEventId.cs | 18 +- .../MySQLDatabaseFacadeExtensions.cs | 16 +- .../MySQLDbContextOptionsExtensions.cs | 18 +- .../src/Extensions/MySQLDbFunctionsEnums.cs | 16 +- .../Extensions/MySQLDbFunctionsExtensions.cs | 16 +- .../MySQLEntityTypeBuilderExtensions.cs | 16 +- .../Extensions/MySQLEntityTypeExtensions.cs | 16 +- EFCore/src/Extensions/MySQLIndexExtensions.cs | 18 +- .../Extensions/MySQLKeyBuilderExtensions.cs | 16 +- EFCore/src/Extensions/MySQLKeyExtensions.cs | 16 +- .../MySQLMigrationBuilderExtensions.cs | 16 +- .../Extensions/MySQLModelBuilderExtensions.cs | 16 +- EFCore/src/Extensions/MySQLModelExtensions.cs | 16 +- .../MySQLPropertyBuilderExtensions.cs | 16 +- .../src/Extensions/MySQLPropertyExtensions.cs | 18 +- .../MySQLServiceCollectionExtensions.cs | 18 +- .../src/Extensions/MySQLTypeBaseExtensions.cs | 16 +- .../Extensions/MySqlIndexBuilderExtensions.cs | 16 +- .../Infrastructure/Internal/IMySQLOptions.cs | 18 +- .../Internal/MySQLOptionsExtension.cs | 18 +- .../MySQLDbContextOptionsBuilder.cs | 16 +- .../src/Infrastructure/MySQLSchemaBehavior.cs | 16 +- EFCore/src/Internal/MySQLModelValidator.cs | 18 +- EFCore/src/Internal/MySQLOptions.cs | 18 +- .../MySQLRetryingExecutionStrategy.cs | 16 +- ...SQLValueGenerationStrategyCompatibility.cs | 16 +- .../Conventions/MySQLConventionSetBuilder.cs | 16 +- .../MySQLValueGenerationConvention.cs | 18 +- .../MySqlCharsetAttributeConvention.cs | 18 +- .../MySqlCollationAttributeConvention.cs | 16 +- .../MySqlEntityCharsetAttributeConvention.cs | 16 +- ...MySqlEntityCollationAttributeConvention.cs | 16 +- .../Metadata/Internal/MySQLAnnotationNames.cs | 16 +- .../Internal/MySQLAnnotationProvider.cs | 16 +- .../Metadata/MySQLValueGenerationStrategy.cs | 16 +- .../Internal/MySQLHistoryRepository.cs | 16 +- .../Internal/MySQLMigrationsModelDiffer.cs | 18 +- .../src/Migrations/Internal/MySQLMigrator.cs | 16 +- .../Migrations/MySQLMigrationsSqlGenerator.cs | 16 +- .../Operations/CreateDatabaseOperation.cs | 16 +- .../Operations/DropDatabaseOperation.cs | 18 +- ...imaryKeyAndRecreateForeignKeysOperation.cs | 16 +- ...nstraintAndRecreateForeignKeysOperation.cs | 16 +- EFCore/src/Properties/AssemblyInfo.cs | 18 +- .../MySQLByteArrayMethodTranslator.cs | 16 +- ...QLDbFunctionsExtensionsMethodTranslator.cs | 16 +- .../Internal/MySQLRegexIsMatchTranslator.cs | 16 +- .../Internal/MySQLStringLengthTranslator.cs | 18 +- .../Internal/MySQLBinaryExpression.cs | 16 +- .../Internal/MySQLCollateExpression.cs | 16 +- .../MySQLColumnAliasReferenceExpression.cs | 16 +- .../MySQLComplexFunctionArgumentExpression.cs | 16 +- .../Internal/MySQLJsonArrayIndexExpression.cs | 16 +- .../Internal/MySQLJsonTraversalExpression.cs | 16 +- .../Internal/MySQLMatchExpression.cs | 16 +- .../Internal/MySQLRegexpExpression.cs | 16 +- .../MySQLStringComparisonMethodTranslator.cs | 16 +- .../src/Query/Internal/MySQLCommandParser.cs | 16 +- .../MySQLCompatibilityExpressionVisitor.cs | 18 +- .../MySQLCompiledQueryCacheKeyGenerator.cs | 16 +- .../Query/Internal/MySQLConvertTranslator.cs | 18 +- .../MySQLDateDiffFunctionsTranslator.cs | 18 +- .../Internal/MySQLDateTimeMemberTranslator.cs | 16 +- .../Internal/MySQLDateTimeMethodTranslator.cs | 18 +- .../MySQLEvaluatableExpressionFilter.cs | 16 +- .../src/Query/Internal/MySQLMathTranslator.cs | 18 +- .../Internal/MySQLMemberTranslatorProvider.cs | 16 +- .../MySQLMethodCallTranslatorProvider.cs | 16 +- .../Query/Internal/MySQLNewGuidTranslator.cs | 18 +- .../Internal/MySQLObjectToStringTranslator.cs | 18 +- .../MySQLParameterBasedSqlProcessor.cs | 16 +- .../MySQLParameterBasedSqlProcessorFactory.cs | 16 +- .../Internal/MySQLQueryCompilationContext.cs | 16 +- .../MySQLQueryCompilationContextFactory.cs | 16 +- .../Query/Internal/MySQLQueryStringFactory.cs | 16 +- .../MySQLQueryTranslationPostprocessor.cs | 18 +- ...SQLQueryTranslationPostprocessorFactory.cs | 16 +- .../Internal/MySQLSqlExpressionFactory.cs | 16 +- .../Internal/MySQLSqlNullabilityProcessor.cs | 16 +- .../MySQLSqlTranslatingExpressionVisitor.cs | 18 +- ...LSqlTranslatingExpressionVisitorFactory.cs | 16 +- .../Internal/MySQLStringMemberTranslator.cs | 16 +- .../Internal/MySQLStringMethodTranslator.cs | 18 +- EFCore/src/Query/MySQLJsonString.cs | 16 +- .../Internal/MySQLQueryGeneratorFactory.cs | 16 +- .../Sql/Internal/MySQLQuerySqlGenerator.cs | 16 +- .../Internal/MySQLCodeGenerator.cs | 18 +- .../Internal/MySQLDataReaderExtension.cs | 16 +- .../Internal/MySQLDatabaseModelFactory.cs | 16 +- .../src/Storage/Internal/ByteArrayComparer.cs | 18 +- .../Internal/BytesToDateTimeConverter.cs | 18 +- .../Internal/IMySQLRelationalConnection.cs | 18 +- .../Storage/Internal/MySQLBoolTypeMapping.cs | 18 +- .../Internal/MySQLByteArrayTypeMapping.cs | 18 +- .../Storage/Internal/MySQLDatabaseCreator.cs | 18 +- .../MySQLDateTimeOffsetTypeMapping.cs | 16 +- .../Storage/Internal/MySQLDateTypeMapping.cs | 16 +- .../Internal/MySQLDatetimeTypeMapping.cs | 18 +- .../Internal/MySQLDecimalTypeMapping.cs | 16 +- .../Internal/MySQLDoubleTypeMapping.cs | 16 +- .../Internal/MySQLExecutionStrategy.cs | 16 +- .../Internal/MySQLExecutionStrategyFactory.cs | 18 +- .../Storage/Internal/MySQLFloatTypeMapping.cs | 16 +- .../Internal/MySQLGeometryTypeMapping.cs | 18 +- .../Storage/Internal/MySQLGuidTypeMapping.cs | 16 +- .../MySQLJsonChangeTrackingOptions.cs | 16 +- .../Storage/Internal/MySQLJsonTypeMapping.cs | 16 +- .../Internal/MySQLRelationalConnection.cs | 18 +- .../MySQLScaffoldingConnectionSettings.cs | 16 +- .../Internal/MySQLSqlGenerationHelper.cs | 16 +- .../Internal/MySQLStringTypeMapping.cs | 16 +- .../Storage/Internal/MySQLTimeSpanMapping.cs | 16 +- .../MySQLTransientExceptionDetector.cs | 18 +- .../src/Storage/Internal/MySQLTypeMapping.cs | 16 +- .../Internal/MySQLTypeMappingSource.cs | 18 +- EFCore/src/Update/IMySQLUpdateSqlGenerator.cs | 16 +- .../Update/MySQLModificationCommandBatch.cs | 16 +- .../MySQLModificationCommandBatchFactory.cs | 16 +- EFCore/src/Update/MySQLUpdateSqlGenerator.cs | 16 +- EFCore/src/Utils/Check.cs | 16 +- EFCore/src/Utils/CodeAnnotations.cs | 16 +- EFCore/src/Utils/CodeAttributes.cs | 18 +- EFCore/src/Utils/SharedTypeExtensions.cs | 18 +- EFCore/src/Utils/Static.cs | 16 +- EFCore/src/Utils/StringBuilderExtensions.cs | 16 +- .../Internal/MySQLValueGeneratorSelector.cs | 16 +- .../BasicGuidTests.cs | 16 +- .../ConcurrencyTests.cs | 16 +- .../ConnectionTests.cs | 16 +- .../MySql.EFCore.Basic.Tests/DataTests.cs | 16 +- .../DbContextClasses/ConventionsContexts.cs | 16 +- .../DbContextClasses/EFFluentAPIContexts.cs | 18 +- .../DbContextClasses/EntitiesClasses.cs | 16 +- .../DbContextClasses/SakilaLiteContext.cs | 16 +- .../DbContextClasses/TestsContexts.cs | 16 +- .../DbFunctionsMySQLTest.cs | 16 +- .../MySql.EFCore.Basic.Tests/EFCoreTests.cs | 16 +- .../FluentAPITests.cs | 16 +- .../FunctionalTests.cs | 16 +- .../LoadingRelatedDataTests.cs | 16 +- .../MySql.EFCore.Basic.Tests/ModelingTests.cs | 18 +- .../MultiSchemaTests.cs | 18 +- .../MySQLDatabaseFacadeTest.cs | 16 +- .../MySQLTypeMapperTests.cs | 16 +- .../Properties/DatabaseSetup.sql | 18 +- .../ShadowPropertiesTests.cs | 16 +- .../Utils/EntityTestsFixtureClass.cs | 16 +- .../Utils/MySqlTestStore.cs | 16 +- .../Utils/TestUtils.cs | 16 +- .../MySql.EFCore.Design.Tests/Extensions.cs | 16 +- .../MySQLAnnotationCodeGeneratorTest.cs | 16 +- .../MySQLCodeGeneratorTest.cs | 16 +- .../MySQLDatabaseModelFactoryTest.cs | 18 +- .../MySQLDatabaseModelFixture.cs | 18 +- .../MySQLDesignTimeProviderServicesTest.cs | 18 +- .../Properties/sakiladb-schema.sql | 16 +- .../Properties/world.sql | 16 +- .../MySQLHistoryRepositoryTests.cs | 16 +- .../MySQLMigrationsTests.cs | 16 +- .../MySqlMigrationsGeneratorTest.cs | 16 +- .../MySqlMigrationsGeneratorTestBase.cs | 16 +- .../Utilities/ContextUtils.cs | 16 +- EntityFramework/src/EFMySqlCommand.cs | 16 +- EntityFramework/src/EFMySqlDataReader.cs | 16 +- .../src/Fragments/InputFragment.cs | 16 +- EntityFramework/src/Fragments/JoinFragment.cs | 16 +- EntityFramework/src/Fragments/SqlFragment.cs | 16 +- .../src/Fragments/TableFragment.cs | 18 +- .../src/Generators/DeleteGenerator.cs | 16 +- .../src/Generators/FunctionGenerator.cs | 16 +- .../src/Generators/FunctionProcessor.cs | 16 +- .../src/Generators/InsertGenerator.cs | 16 +- EntityFramework/src/Generators/Scope.cs | 16 +- .../src/Generators/SelectGenerator.cs | 16 +- .../src/Generators/SqlGenerator.cs | 16 +- .../src/Generators/UpdateGenerator.cs | 16 +- EntityFramework/src/Metadata.cs | 16 +- EntityFramework/src/MySqlConnectionFactory.cs | 18 +- .../src/MySqlDependencyResolver.cs | 16 +- EntityFramework/src/MySqlEFConfiguration.cs | 16 +- EntityFramework/src/MySqlExecutionStrategy.cs | 18 +- EntityFramework/src/MySqlHistoryContext.cs | 16 +- EntityFramework/src/MySqlLogger.cs | 16 +- .../src/MySqlMigrationSqlGenerator.cs | 16 +- EntityFramework/src/MySqlSpatialDataReader.cs | 16 +- EntityFramework/src/MySqlSpatialServices.cs | 16 +- .../src/Properties/AssemblyInfo.cs | 16 +- .../src/Properties/Resources.Designer.cs | 198 +- EntityFramework/src/ProviderManifest.cs | 16 +- EntityFramework/src/ProviderServices.cs | 16 +- .../src/Statements/DeleteStatement.cs | 16 +- .../src/Statements/InsertStatement.cs | 16 +- .../src/Statements/SelectStatement.cs | 16 +- .../src/Statements/UpdateStatement.cs | 16 +- .../AggregateOperators.cs | 16 +- .../CanonicalFunctions.cs | 16 +- .../DataTypeTests.cs | 16 +- .../DatesTypesTests.cs | 16 +- .../DefaultContext.cs | 18 +- .../DefaultFixture.cs | 358 +- .../DeleteTests.cs | 272 +- .../ExpressionTests.cs | 16 +- .../GenericListener.cs | 174 +- .../InsertTests.cs | 18 +- .../JoinTests.cs | 18 +- .../OrderingAndGrouping.cs | 18 +- .../Paging.cs | 208 +- .../ProceduresAndFunctions.cs | 18 +- .../Properties/AssemblyInfo.cs | 110 +- .../ProviderManifestTests.cs | 206 +- .../ProviderServicesTests.cs | 18 +- .../RelationalOperators.cs | 18 +- .../RestrictionOperators.cs | 156 +- .../SchemaInformation.cs | 16 +- .../SetOperators.cs | 18 +- .../SimpleQuery.cs | 18 +- .../UpdateTests.cs | 18 +- .../Wizard.cs | 18 +- .../Blogs.cs | 16 +- .../CodeFirstFixture.cs | 38 +- .../CodeFirstTests.cs | 4508 +++++++-------- .../ContextForNormalFk.cs | 16 +- .../ContextForString.cs | 16 +- .../Dinosauria.cs | 178 +- .../Movie.cs | 352 +- .../MovieContextCodeBasedConfiguration.cs | 18 +- .../PromotionsDB.cs | 178 +- .../Properties/AssemblyInfo.cs | 18 +- .../Properties/SQLSyntax.Designer.cs | 766 +-- .../SakilaModel/SakilaDb.cs | 16 +- .../SakilaModel/actor.cs | 16 +- .../SakilaModel/actor_info.cs | 16 +- .../SakilaModel/address.cs | 16 +- .../SakilaModel/category.cs | 16 +- .../SakilaModel/city.cs | 16 +- .../SakilaModel/country.cs | 16 +- .../SakilaModel/customer.cs | 16 +- .../SakilaModel/customer_list.cs | 16 +- .../SakilaModel/film.cs | 16 +- .../SakilaModel/film_actor.cs | 16 +- .../SakilaModel/film_category.cs | 16 +- .../SakilaModel/film_list.cs | 16 +- .../SakilaModel/film_text.cs | 16 +- .../SakilaModel/inventory.cs | 16 +- .../SakilaModel/language.cs | 16 +- .../SakilaModel/nicer_but_slower_film_list.cs | 16 +- .../SakilaModel/payment.cs | 16 +- .../SakilaModel/rental.cs | 16 +- .../SakilaModel/sales_by_film_category.cs | 16 +- .../SakilaModel/sales_by_store.cs | 16 +- .../SakilaModel/staff.cs | 16 +- .../SakilaModel/staff_list.cs | 16 +- .../SakilaModel/store.cs | 16 +- .../Ship.cs | 198 +- .../SiteDB.cs | 16 +- .../TransactionTests.cs | 16 +- .../Vehicle.cs | 724 +-- .../BlogsModel.cs | 16 +- .../MyConfiguration.cs | 16 +- .../MySqlMigrationsTests.cs | 920 +-- .../Properties/AssemblyInfo.cs | 18 +- .../SetUpMigrationsTests.cs | 230 +- LICENSE | 15 +- .../src/TraceProviderBuilderExtension.cs | 28 + .../MySql.Replication.Tests/BaseTest.cs | 344 +- .../Properties/AssemblyInfo.cs | 110 +- .../Properties/Resources.Designer.cs | 224 +- .../ReplicationTest.cs | 492 +- MySQL.Data/MySql.Replication.Tests/SetUp.cs | 316 +- .../Authentication/AuthenticationManager.cs | 194 +- .../CachingSha2AuthenticationPlugin.cs | 18 +- .../src/Authentication/ClearPasswordPlugin.cs | 16 +- .../src/Authentication/FIDO/FidoAssertion.cs | 16 +- .../src/Authentication/FIDO/FidoDevice.cs | 16 +- .../src/Authentication/FIDO/FidoDeviceInfo.cs | 16 +- .../FIDO/Native/NativeMethods.cs | 16 +- .../src/Authentication/FIDO/Native/Structs.cs | 16 +- .../FIDO/Utility/ConstStringMarshaler.cs | 16 +- .../src/Authentication/FIDO/Utility/Enums.cs | 16 +- .../Authentication/FIDO/Utility/Extensions.cs | 16 +- .../FIDO/Utility/FidoExceptions.cs | 16 +- .../src/Authentication/FIDO/Utility/Init.cs | 16 +- .../FidoAuthenticationPlugin.cs | 16 +- MySQL.Data/src/Authentication/GSSAPI/Const.cs | 16 +- .../src/Authentication/GSSAPI/GssContext.cs | 18 +- .../Authentication/GSSAPI/GssContextFlags.cs | 18 +- .../Authentication/GSSAPI/GssCredentials.cs | 18 +- .../Authentication/GSSAPI/GssapiMechanism.cs | 18 +- .../GSSAPI/Native/GssBufferDescStruct.cs | 18 +- .../GSSAPI/Native/GssOidStruct.cs | 18 +- .../GSSAPI/Native/NativeMethods.cs | 18 +- .../GSSAPI/Native/NativeMethodsLinux.cs | 18 +- .../GSSAPI/Native/NativeMethodsWin64.cs | 18 +- .../GSSAPI/Utility/Disposable.cs | 18 +- .../GSSAPI/Utility/ExceptionMessages.cs | 18 +- .../Authentication/GSSAPI/Utility/GssType.cs | 18 +- .../GSSAPI/Utility/KerberosConfig.cs | 18 +- .../Authentication/GSSAPI/Utility/Pinned.cs | 18 +- .../KerberosAuthenticationPlugin.cs | 18 +- .../MySQLAuthenticationPlugin.cs | 686 +-- .../src/Authentication/MySqlPemReader.cs | 18 +- .../src/Authentication/MySqlSASLPlugin.cs | 18 +- .../Authentication/NativePasswordPlugins.cs | 16 +- .../Authentication/OciAuthenticationPlugin.cs | 16 +- MySQL.Data/src/Authentication/SSPI/Const.cs | 16 +- .../src/Authentication/SSPI/NativeMethods.cs | 16 +- .../Authentication/SSPI/SspiCredentials.cs | 16 +- .../SSPI/SspiSecurityContext.cs | 16 +- MySQL.Data/src/Authentication/SSPI/Structs.cs | 16 +- MySQL.Data/src/Authentication/ScramBase.cs | 18 +- .../src/Authentication/ScramSha1Mechanism.cs | 18 +- .../Authentication/ScramSha256Mechanism.cs | 18 +- .../Sha256AuthenticationPlugin.cs | 252 +- .../Sha256MemoryAuthenticationPlugin.cs | 16 +- .../WebAuthnAuthenticationPlugin.cs | 16 +- .../WindowsAuthenticationPlugin.cs | 16 +- MySQL.Data/src/BulkLoader.cs | 730 +-- MySQL.Data/src/CharSetMap.cs | 460 +- MySQL.Data/src/CompressedStream.cs | 16 +- MySQL.Data/src/Crypt.cs | 18 +- MySQL.Data/src/Driver.cs | 16 +- MySQL.Data/src/Exception.cs | 16 +- MySQL.Data/src/Failover/FailoverGroup.cs | 16 +- MySQL.Data/src/Failover/FailoverManager.cs | 16 +- MySQL.Data/src/Failover/FailoverServer.cs | 16 +- .../src/Failover/RandomFailoverGroup.cs | 18 +- .../src/Failover/SequentialFailoverGroup.cs | 18 +- MySQL.Data/src/Field.cs | 16 +- .../net462/SystemPerformanceMonitor.cs | 18 +- .../netstandard2_0/AuthenticationManager.cs | 18 +- .../netstandard2_0/CommandBuilder.cs | 16 +- .../netstandard2_0/MySqlClientPermission.cs | 204 +- .../MySqlClientPermissionAttribute.cs | 106 +- .../netstandard2_0/MySqlConfiguration.cs | 410 +- .../Framework/netstandard2_0/MySqlHelper.cs | 16 +- .../MySqlPromotableTransaction.cs | 16 +- .../netstandard2_0/MySqlSecurityPermission.cs | 130 +- .../Framework/netstandard2_0/dataadapter.cs | 16 +- MySQL.Data/src/ISSchemaProvider.cs | 794 +-- .../src/Interceptors/CommandInterceptor.cs | 16 +- .../src/Interceptors/ExceptionInterceptor.cs | 16 +- MySQL.Data/src/Interceptors/Interceptor.cs | 128 +- MySQL.Data/src/MySQLActivitySource.cs | 30 +- MySQL.Data/src/MySqlAttribute.cs | 16 +- MySQL.Data/src/MySqlAttributeCollection.cs | 16 +- .../src/MySqlBaseConnectionStringBuilder.cs | 18 +- MySQL.Data/src/MySqlClientFactory.cs | 16 +- MySQL.Data/src/MySqlCommand.cs | 16 +- MySQL.Data/src/MySqlConnection.cs | 16 +- .../src/MySqlConnectionStringBuilder.cs | 16 +- MySQL.Data/src/MySqlDataReader.cs | 16 +- MySQL.Data/src/MySqlError.cs | 4020 ++++++------- MySQL.Data/src/MySqlHelper.cs | 16 +- MySQL.Data/src/MySqlPacket.cs | 16 +- MySQL.Data/src/MySqlParameter.cs | 16 +- MySQL.Data/src/MySqlParameterCollection.cs | 16 +- MySQL.Data/src/MySqlPool.cs | 16 +- MySQL.Data/src/MySqlPoolManager.cs | 18 +- MySQL.Data/src/MySqlScript.cs | 16 +- MySQL.Data/src/MySqlStream.cs | 16 +- MySQL.Data/src/MySqlTrace.cs | 16 +- MySQL.Data/src/MySqlTransaction.cs | 16 +- MySQL.Data/src/MysqlDefs.cs | 16 +- MySQL.Data/src/NativeDriver.cs | 16 +- MySQL.Data/src/OkPacket.cs | 16 +- MySQL.Data/src/PerformanceMonitor.cs | 104 +- MySQL.Data/src/PreparableStatement.cs | 516 +- MySQL.Data/src/ProcedureCache.cs | 460 +- MySQL.Data/src/Properties/AssemblyInfo.cs | 18 +- MySQL.Data/src/Properties/VersionInfo.cs | 90 +- .../Replication/ReplicationConfiguration.cs | 292 +- .../src/Replication/ReplicationManager.cs | 16 +- .../ReplicationRoundRobinServerGroup.cs | 134 +- .../src/Replication/ReplicationServer.cs | 140 +- .../src/Replication/ReplicationServerGroup.cs | 370 +- MySQL.Data/src/ResourcesX.Designer.cs | 1442 ++--- MySQL.Data/src/ResultSet.cs | 678 +-- MySQL.Data/src/Runtime.cs | 112 +- MySQL.Data/src/Schema.cs | 16 +- MySQL.Data/src/SchemaProvider.cs | 16 +- MySQL.Data/src/Statement.cs | 702 +-- MySQL.Data/src/StoredProcedure.cs | 754 +-- MySQL.Data/src/TableCache.cs | 326 +- MySQL.Data/src/TimedStream.cs | 16 +- MySQL.Data/src/TracingDriver.cs | 16 +- MySQL.Data/src/Types/IMySqlValue.cs | 94 +- MySQL.Data/src/Types/MetaData.cs | 18 +- MySQL.Data/src/Types/MySqlBinary.cs | 418 +- MySQL.Data/src/Types/MySqlBit.cs | 248 +- MySQL.Data/src/Types/MySqlByte.cs | 282 +- .../src/Types/MySqlConversionException.cs | 16 +- MySQL.Data/src/Types/MySqlDateTime.cs | 16 +- MySQL.Data/src/Types/MySqlDecimal.cs | 324 +- MySQL.Data/src/Types/MySqlDouble.cs | 290 +- MySQL.Data/src/Types/MySqlGeometry.cs | 790 +-- MySQL.Data/src/Types/MySqlGuid.cs | 418 +- MySQL.Data/src/Types/MySqlInt16.cs | 246 +- MySQL.Data/src/Types/MySqlInt32.cs | 286 +- MySQL.Data/src/Types/MySqlInt64.cs | 250 +- MySQL.Data/src/Types/MySqlSingle.cs | 260 +- MySQL.Data/src/Types/MySqlString.cs | 290 +- MySQL.Data/src/Types/MySqlTime.cs | 436 +- MySQL.Data/src/Types/MySqlUByte.cs | 244 +- MySQL.Data/src/Types/MySqlUInt16.cs | 244 +- MySQL.Data/src/Types/MySqlUInt32.cs | 288 +- MySQL.Data/src/Types/MySqlUInt64.cs | 250 +- MySQL.Data/src/Utils.cs | 16 +- .../ExternalAuthenticationPlugin.cs | 18 +- .../MySQL41AuthenticationPlugin.cs | 18 +- .../PlainAuthenticationPlugin.cs | 18 +- MySQL.Data/src/X/Common/Tools.cs | 16 +- .../src/X/Common/UnmanagedLibraryLoader.cs | 16 +- .../X/Communication/CommunicationPacket.cs | 192 +- .../X/Communication/XCompressionController.cs | 16 +- .../src/X/Communication/XPacketProcessor.cs | 16 +- .../X/Communication/XPacketReaderWriter.cs | 302 +- MySQL.Data/src/X/Data/CollationMap.cs | 684 +-- MySQL.Data/src/X/Data/Enums.cs | 16 +- MySQL.Data/src/X/Protocol/ProtocolBase.cs | 106 +- MySQL.Data/src/X/Protocol/ValueDecoder.cs | 96 +- MySQL.Data/src/X/Protocol/X/BitDecoder.cs | 18 +- MySQL.Data/src/X/Protocol/X/ByteDecoder.cs | 200 +- MySQL.Data/src/X/Protocol/X/DecimalDecoder.cs | 60 +- MySQL.Data/src/X/Protocol/X/Enum.cs | 136 +- MySQL.Data/src/X/Protocol/X/ExpUnparser.cs | 16 +- MySQL.Data/src/X/Protocol/X/ExprParser.cs | 16 +- MySQL.Data/src/X/Protocol/X/ExprUtil.cs | 540 +- MySQL.Data/src/X/Protocol/X/FloatDecoder.cs | 138 +- MySQL.Data/src/X/Protocol/X/IntegerDecoder.cs | 316 +- .../src/X/Protocol/X/Protobuf/Mysqlx.cs | 16 +- .../X/Protocol/X/Protobuf/MysqlxConnection.cs | 16 +- .../src/X/Protocol/X/Protobuf/MysqlxCrud.cs | 16 +- .../src/X/Protocol/X/Protobuf/MysqlxCursor.cs | 16 +- .../X/Protocol/X/Protobuf/MysqlxDatatypes.cs | 16 +- .../src/X/Protocol/X/Protobuf/MysqlxExpect.cs | 16 +- .../src/X/Protocol/X/Protobuf/MysqlxExpr.cs | 16 +- .../src/X/Protocol/X/Protobuf/MysqlxNotice.cs | 16 +- .../X/Protocol/X/Protobuf/MysqlxPrepare.cs | 16 +- .../X/Protocol/X/Protobuf/MysqlxResultset.cs | 16 +- .../X/Protocol/X/Protobuf/MysqlxSession.cs | 16 +- MySQL.Data/src/X/Protocol/X/SetDecoder.cs | 148 +- .../src/X/Protocol/X/XDateTimeDecoder.cs | 154 +- MySQL.Data/src/X/Protocol/X/XProtocol.cs | 1856 +++--- MySQL.Data/src/X/Protocol/X/XTimeDecoder.cs | 132 +- .../src/X/Protocol/X/XValueDecoderFactory.cs | 112 +- .../RoutingServices/DefaultRoutingService.cs | 16 +- .../X/RoutingServices/RoutingServiceBase.cs | 16 +- MySQL.Data/src/X/Serialization/JsonParser.cs | 426 +- MySQL.Data/src/X/Sessions/InternalSession.cs | 16 +- .../src/X/Sessions/QueueTaskScheduler.cs | 16 +- MySQL.Data/src/X/Sessions/XInternalSession.cs | 2112 +++---- MySQL.Data/src/X/XDevAPI/BaseSession.cs | 1668 +++--- MySQL.Data/src/X/XDevAPI/CRUD/AddStatement.cs | 152 +- .../CRUD/CreateCollectionIndexStatement.cs | 16 +- .../src/X/XDevAPI/CRUD/CreateIndexParams.cs | 16 +- .../src/X/XDevAPI/CRUD/CrudStatement.cs | 138 +- MySQL.Data/src/X/XDevAPI/CRUD/DocResult.cs | 148 +- MySQL.Data/src/X/XDevAPI/CRUD/FindParams.cs | 86 +- .../src/X/XDevAPI/CRUD/FindStatement.cs | 344 +- .../src/X/XDevAPI/CRUD/ModifyStatement.cs | 398 +- .../src/X/XDevAPI/CRUD/RemoveStatement.cs | 154 +- MySQL.Data/src/X/XDevAPI/CRUD/UpdateSpec.cs | 218 +- MySQL.Data/src/X/XDevAPI/Client.cs | 16 +- MySQL.Data/src/X/XDevAPI/Collection.cs | 382 +- MySQL.Data/src/X/XDevAPI/Common/BaseResult.cs | 228 +- .../src/X/XDevAPI/Common/BaseStatement.cs | 326 +- .../src/X/XDevAPI/Common/BufferingResult.cs | 484 +- .../src/X/XDevAPI/Common/CollectionOptions.cs | 18 +- MySQL.Data/src/X/XDevAPI/Common/ColumnType.cs | 16 +- MySQL.Data/src/X/XDevAPI/Common/ErrorInfo.cs | 114 +- .../src/X/XDevAPI/Common/FilterParams.cs | 188 +- .../X/XDevAPI/Common/FilterableStatement.cs | 404 +- .../src/X/XDevAPI/Common/QueryStatement.cs | 16 +- MySQL.Data/src/X/XDevAPI/Common/Result.cs | 120 +- .../X/XDevAPI/Common/TargetedBaseStatement.cs | 110 +- .../src/X/XDevAPI/Common/WarningInfo.cs | 124 +- MySQL.Data/src/X/XDevAPI/DatabaseObject.cs | 152 +- MySQL.Data/src/X/XDevAPI/DbDoc.cs | 606 +- MySQL.Data/src/X/XDevAPI/GenericCollection.cs | 602 +- MySQL.Data/src/X/XDevAPI/Iterator.cs | 16 +- MySQL.Data/src/X/XDevAPI/MySqlExpression.cs | 16 +- MySQL.Data/src/X/XDevAPI/MySqlX.cs | 294 +- .../XDevAPI/MySqlXConnectionStringBuilder.cs | 16 +- MySQL.Data/src/X/XDevAPI/Relational/Column.cs | 218 +- .../X/XDevAPI/Relational/InternalRowResult.cs | 280 +- MySQL.Data/src/X/XDevAPI/Relational/Row.cs | 194 +- .../src/X/XDevAPI/Relational/RowResult.cs | 86 +- .../src/X/XDevAPI/Relational/SqlResult.cs | 136 +- .../src/X/XDevAPI/Relational/SqlStatement.cs | 216 +- MySQL.Data/src/X/XDevAPI/Relational/Table.cs | 344 +- .../Relational/TableDeleteStatement.cs | 132 +- .../Relational/TableInsertStatement.cs | 142 +- .../Relational/TableSelectStatement.cs | 282 +- .../Relational/TableUpdateStatement.cs | 16 +- MySQL.Data/src/X/XDevAPI/Schema.cs | 698 +-- MySQL.Data/src/X/XDevAPI/Session.cs | 16 +- MySQL.Data/src/common/Cache.cs | 166 +- MySQL.Data/src/common/ContextString.cs | 342 +- MySQL.Data/src/common/Dns/DnsEnums.cs | 16 +- MySQL.Data/src/common/Dns/DnsQuestion.cs | 16 +- MySQL.Data/src/common/Dns/DnsRecordHeader.cs | 16 +- MySQL.Data/src/common/Dns/DnsRecordReader.cs | 16 +- MySQL.Data/src/common/Dns/DnsRecordUnknown.cs | 16 +- MySQL.Data/src/common/Dns/DnsRequest.cs | 16 +- MySQL.Data/src/common/Dns/DnsResolver.cs | 16 +- .../src/common/Dns/DnsResourceRecord.cs | 16 +- MySQL.Data/src/common/Dns/DnsResponse.cs | 16 +- MySQL.Data/src/common/Dns/DnsSrvRecord.cs | 18 +- MySQL.Data/src/common/DnsSrv.cs | 18 +- .../src/common/LowResolutionStopwatch.cs | 202 +- MySQL.Data/src/common/MyNetworkStream.cs | 18 +- .../src/common/MySqlConnectionStringOption.cs | 16 +- .../MySqlConnectionStringOptionCollection.cs | 16 +- MySQL.Data/src/common/MySqlTokenizer.cs | 576 +- MySQL.Data/src/common/NativeMethods.cs | 16 +- MySQL.Data/src/common/Platform.cs | 16 +- MySQL.Data/src/common/QueryNormalizer.cs | 760 +-- MySQL.Data/src/common/Ssl.cs | 712 +-- .../src/common/SslPemCertificateValidator.cs | 16 +- MySQL.Data/src/common/StreamCreator.cs | 16 +- MySQL.Data/src/common/StringUtility.cs | 90 +- MySQL.Data/src/common/UnixEndPoint.cs | 16 +- MySQL.Data/src/common/Version.cs | 202 +- .../common/netstandard2_0/NamedPipeStream.cs | 16 +- .../netstandard2_0/SharedMemoryStream.cs | 16 +- .../tests/MySql.Data.Tests/AttributeTests.cs | 16 +- .../tests/MySql.Data.Tests/AuthTests.cs | 18 +- .../tests/MySql.Data.Tests/BlobTests.cs | 16 +- .../MySql.Data.Tests/BlobTestsCompressed.cs | 18 +- .../tests/MySql.Data.Tests/CharSetTests.cs | 18 +- .../MySql.Data.Tests/CharSetUTF8Tests.cs | 16 +- .../ClientSideFailoverTests.cs | 18 +- MySQL.Data/tests/MySql.Data.Tests/CmdTests.cs | 18 +- .../MySql.Data.Tests/CmdTestsCompressed.cs | 18 +- .../ConnectionStringBuilderTests.cs | 18 +- .../tests/MySql.Data.Tests/ConnectionTests.cs | 16 +- .../tests/MySql.Data.Tests/DataTypeTests.cs | 18 +- .../tests/MySql.Data.Tests/DateTimeTests.cs | 16 +- .../tests/MySql.Data.Tests/DnsSrvTests.cs | 18 +- .../tests/MySql.Data.Tests/EventTests.cs | 18 +- .../tests/MySql.Data.Tests/ExceptionTests.cs | 16 +- .../Framework/netstandard2_0/BlobTestsPipe.cs | 16 +- .../netstandard2_0/BlobTestsPipeCompressed.cs | 18 +- .../netstandard2_0/BlobTestsSharedMem.cs | 18 +- .../BlobTestsSharedMemCompressed.cs | 18 +- .../Framework/netstandard2_0/CmdTestsPipe.cs | 18 +- .../netstandard2_0/CmdTestsPipeCompressed.cs | 18 +- .../netstandard2_0/CmdTestsSharedMem.cs | 18 +- .../CmdTestsSharedmemCompressed.cs | 18 +- .../Framework/netstandard2_0/CultureTests.cs | 16 +- .../Framework/netstandard2_0/DataTypeTests.cs | 16 +- .../Framework/netstandard2_0/DateTimeTests.cs | 18 +- .../netstandard2_0/GetSchemaTests.cs | 18 +- .../netstandard2_0/InstallerTests.cs | 16 +- .../MediumTrust/MediumTrustDomain.cs | 16 +- .../MediumTrustFixtureAttribute.cs | 16 +- .../MediumTrustTestClassCommand.cs | 16 +- .../MediumTrust/MediumTrustTestCommand.cs | 16 +- .../MediumTrust/MySql.MediumTrustsTests.cs | 16 +- .../MediumTrust/MySqlClientPermissionTests.cs | 16 +- .../netstandard2_0/MySQLHelperTests.cs | 16 +- .../MySqlCommandBuilderTests.cs | 16 +- .../netstandard2_0/MySqlDataAdapterTests.cs | 16 +- .../netstandard2_0/MySqlDataReaderTests.cs | 16 +- .../netstandard2_0/NETCore20Tests.cs | 38 +- .../OutputParametersBatchPrepared.cs | 16 +- .../netstandard2_0/OutputParametersNoBatch.cs | 18 +- .../OutputParametersNoBatchPrepared.cs | 18 +- .../Framework/netstandard2_0/PSPipe.cs | 16 +- .../netstandard2_0/PSPipeCompressed.cs | 16 +- .../netstandard2_0/PSSharedMemory.cs | 16 +- .../PSSharedMemoryCompressed.cs | 16 +- .../netstandard2_0/PartialTrustSandbox.cs | 16 +- .../Framework/netstandard2_0/PerfMonTests.cs | 16 +- .../netstandard2_0/ProcedureParameterTests.cs | 16 +- .../netstandard2_0/ReplicationTests.cs | 16 +- .../netstandard2_0/StressTestsPipe.cs | 16 +- .../StressTestsPipeCompressed.cs | 16 +- .../netstandard2_0/StressTestsSharedMemory.cs | 16 +- .../StressTestsSharedMemoryCompressed.cs | 16 +- .../netstandard2_0/ThreadingTests.cs | 16 +- .../netstandard2_0/TimeoutAndCancel.cs | 16 +- .../TimeoutAndCancelCompressed.cs | 16 +- .../netstandard2_0/TimeoutAndCancelPipe.cs | 16 +- .../TimeoutAndCancelSharedMemory.cs | 16 +- .../Framework/netstandard2_0/TypeTests.cs | 18 +- .../netstandard2_0/UsageAdvisorTests.cs | 18 +- .../tests/MySql.Data.Tests/GenericListener.cs | 16 +- .../tests/MySql.Data.Tests/LoggingTests.cs | 18 +- .../MySql.Data.Tests/MySqlBulkLoaderTests.cs | 18 +- .../MySql.Data.Tests/MySqlDataReaderTests.cs | 16 +- .../MySql.Data.Tests/OutputParametersBatch.cs | 16 +- .../tests/MySql.Data.Tests/ParameterTests.cs | 18 +- .../tests/MySql.Data.Tests/PoolingTests.cs | 16 +- .../PreparedStatementCompressed.cs | 16 +- .../MySql.Data.Tests/PreparedStatements.cs | 16 +- .../Properties/AssemblyInfo.cs | 16 +- .../tests/MySql.Data.Tests/ScriptExecution.cs | 16 +- .../MySql.Data.Tests/SimpleTransactions.cs | 16 +- .../tests/MySql.Data.Tests/SqlServerMode.cs | 18 +- .../tests/MySql.Data.Tests/SqlTokenizer.cs | 16 +- MySQL.Data/tests/MySql.Data.Tests/SslTests.cs | 16 +- .../tests/MySql.Data.Tests/StoredProcedure.cs | 18 +- .../StoredProcedureWithAccess.cs | 16 +- .../tests/MySql.Data.Tests/StressTests.cs | 16 +- .../MySql.Data.Tests/StressTestsCompressed.cs | 18 +- MySQL.Data/tests/MySql.Data.Tests/Syntax.cs | 16 +- MySQL.Data/tests/MySql.Data.Tests/Syntax2.cs | 16 +- .../tests/MySql.Data.Tests/TableCaching.cs | 16 +- MySQL.Data/tests/MySql.Data.Tests/TestBase.cs | 16 +- .../tests/MySql.Data.Tests/Tokenizer.cs | 16 +- .../tests/MySql.Data.Tests/Transactions.cs | 18 +- .../tests/MySql.Data.Tests/UnixSockets.cs | 18 +- MySQL.Data/tests/MySql.Data.Tests/Utils.cs | 18 +- .../Program.cs | 18 +- .../tests/MySqlX.Data.Tests/BaseTest.cs | 564 +- .../tests/MySqlX.Data.Tests/BasicFindTests.cs | 4568 +++++++-------- .../MySqlX.Data.Tests/BasicSelectTests.cs | 294 +- .../CharsetAndCollationTests.cs | 16 +- .../ClientSideFailoverTests.cs | 16 +- .../tests/MySqlX.Data.Tests/ClientTests.cs | 18 +- .../MySqlX.Data.Tests/CloseConnectionTests.cs | 16 +- .../MySqlX.Data.Tests/CollectionAsyncTests.cs | 268 +- .../MySqlX.Data.Tests/CollectionIndexTests.cs | 18 +- .../MySqlX.Data.Tests/CollectionTests.cs | 3478 ++++++------ .../MySqlX.Data.Tests/CompressionTests.cs | 18 +- .../MySqlX.Data.Tests/CrudInsertTests.cs | 5012 ++++++++--------- .../MySqlX.Data.Tests/CrudRemoveTests.cs | 760 +-- .../CrudTests/CrudGCTests.cs | 120 +- .../CrudTests/DocBufferingTests.cs | 122 +- .../MySqlX.Data.Tests/CrudUpdateTests.cs | 2564 ++++----- .../MySqlX.Data.Tests/CustomTypeTests.cs | 16 +- .../tests/MySqlX.Data.Tests/DbDocTests.cs | 16 +- .../tests/MySqlX.Data.Tests/DnsSrvTests.cs | 18 +- .../MySqlX.Data.Tests/ExprParserTests.cs | 16 +- .../MySqlX.Data.Tests/GenericListener.cs | 16 +- .../MySqlX.Data.Tests/JsonParserTests.cs | 16 +- .../tests/MySqlX.Data.Tests/MergePatch.cs | 16 +- .../MySqlX.Data.Tests/PerformanceTests.cs | 16 +- .../PreparedStatementsTests.cs | 16 +- .../Properties/AssemblyInfo.cs | 18 +- .../RelationalTests/ColumnMetadataTests.cs | 16 +- .../RelationalTests/DataTypeTests.cs | 626 +- .../RelationalTests/DateTimeTests.cs | 252 +- .../RelationalTests/RelationalGCTests.cs | 114 +- .../RelationalTests/RowBufferingTests.cs | 112 +- .../RelationalTests/SqlTests.cs | 2130 +++---- .../RelationalTests/TableAsyncTests.cs | 328 +- .../RelationalTests/TableDeleteTests.cs | 232 +- .../RelationalTests/TableInsertTests.cs | 250 +- .../RelationalTests/TableSelectTests.cs | 3508 ++++++------ .../RelationalTests/TableUpdateTests.cs | 734 +-- .../RelationalTests/ViewTests.cs | 16 +- .../tests/MySqlX.Data.Tests/SchemaTests.cs | 594 +- .../tests/MySqlX.Data.Tests/SessionTests.cs | 4778 ++++++++-------- .../tests/MySqlX.Data.Tests/SslTests.cs | 18 +- .../MySqlX.Data.Tests/TransactionTests.cs | 1992 +++---- .../MySqlX.Data.Tests/UnixSocketsTests.cs | 16 +- MySQL.Data/tests/MySqlX.Data.Tests/XAuth.cs | 16 +- .../XConnectionStringBuilderTests.cs | 16 +- MySql.Web/src/Application.cs | 188 +- MySql.Web/src/ConfigUtility.cs | 16 +- MySql.Web/src/MembershipProvider.cs | 3454 ++++++------ MySql.Web/src/MySqlDatabaseWrapper.cs | 416 +- MySql.Web/src/MySqlWebSecurity.cs | 1154 ++-- .../src/PersonalizationConnectionHelper.cs | 172 +- MySql.Web/src/PersonalizationProvider.cs | 1138 ++-- .../src/PersonalizationProviderProcedures.cs | 1396 ++--- MySql.Web/src/ProfileProvider.cs | 1346 ++--- MySql.Web/src/Properties/AssemblyInfo.cs | 16 +- .../src/Properties/Resources.Designer.cs | 1260 ++--- MySql.Web/src/Properties/schema1.sql | 64 +- MySql.Web/src/Properties/schema10.sql | 44 +- MySql.Web/src/Properties/schema2.sql | 12 +- MySql.Web/src/Properties/schema3.sql | 168 +- MySql.Web/src/Properties/schema4.sql | 10 +- MySql.Web/src/Properties/schema5.sql | 60 +- MySql.Web/src/Properties/schema6.sql | 8 +- MySql.Web/src/Properties/schema7.sql | 20 +- MySql.Web/src/Properties/schema8.sql | 10 +- MySql.Web/src/RoleProvider.cs | 1286 ++--- MySql.Web/src/Runtime.cs | 118 +- MySql.Web/src/SchemaManager.cs | 382 +- MySql.Web/src/SessionProvider.cs | 1818 +++--- MySql.Web/src/SimpleMembershipProvider.cs | 2276 ++++---- MySql.Web/src/SimpleRoleProvider.cs | 1068 ++-- MySql.Web/src/SiteMapProvider.cs | 398 +- MySql.Web/tests/PersonalizationTests.cs | 16 +- MySql.Web/tests/ProfileTests.cs | 574 +- MySql.Web/tests/Properties/AssemblyInfo.cs | 98 +- MySql.Web/tests/RoleManagement.cs | 468 +- MySql.Web/tests/SchemaManagerTests.cs | 638 +-- MySql.Web/tests/SchemaTests.cs | 714 +-- MySql.Web/tests/SessionLocking/Global.asax.cs | 16 +- .../SessionLocking/InitSessionLocking.aspx.cs | 96 +- .../InitSessionLocking.aspx.designer.cs | 52 +- MySql.Web/tests/SessionLocking/read.aspx.cs | 104 +- .../SessionLocking/read.aspx.designer.cs | 48 +- MySql.Web/tests/SessionLocking/write.aspx.cs | 108 +- .../SessionLocking/write.aspx.designer.cs | 48 +- MySql.Web/tests/SessionLocking/write2.aspx.cs | 102 +- .../SessionLocking/write2.aspx.designer.cs | 48 +- MySql.Web/tests/SessionTests.cs | 762 +-- MySql.Web/tests/SimpleMembership.cs | 456 +- MySql.Web/tests/SiteMapTests.cs | 236 +- MySql.Web/tests/TestProfile.cs | 134 +- MySql.Web/tests/UserManagement.cs | 1650 +++--- MySql.Web/tests/WebTestBase.cs | 16 +- 714 files changed, 59402 insertions(+), 59333 deletions(-) diff --git a/CHANGES b/CHANGES index 068294302..b54054960 100644 --- a/CHANGES +++ b/CHANGES @@ -1,5 +1,5 @@ 8.4.0 - +- Updated FOSS license text in all source files (WL16197) 8.3.0 - Added support for build traversal (WL15798). diff --git a/EFCore/src/DataAnnotations/MySQLCharsetAttribute.cs b/EFCore/src/DataAnnotations/MySQLCharsetAttribute.cs index 93341796a..72907a16b 100644 --- a/EFCore/src/DataAnnotations/MySQLCharsetAttribute.cs +++ b/EFCore/src/DataAnnotations/MySQLCharsetAttribute.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/src/DataAnnotations/MySQLCollationAttribute.cs b/EFCore/src/DataAnnotations/MySQLCollationAttribute.cs index a5096091c..a1a10b00c 100644 --- a/EFCore/src/DataAnnotations/MySQLCollationAttribute.cs +++ b/EFCore/src/DataAnnotations/MySQLCollationAttribute.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/src/Design/Internal/MySQLAnnotationCodeGenerator.cs b/EFCore/src/Design/Internal/MySQLAnnotationCodeGenerator.cs index c784b531f..3bc26690f 100644 --- a/EFCore/src/Design/Internal/MySQLAnnotationCodeGenerator.cs +++ b/EFCore/src/Design/Internal/MySQLAnnotationCodeGenerator.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/src/Design/Internal/MySQLDesignTimeServices.cs b/EFCore/src/Design/Internal/MySQLDesignTimeServices.cs index 145c197a1..a621f6a8f 100644 --- a/EFCore/src/Design/Internal/MySQLDesignTimeServices.cs +++ b/EFCore/src/Design/Internal/MySQLDesignTimeServices.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/src/Diagnostics/Internal/MySQLLoggingDefinitions.cs b/EFCore/src/Diagnostics/Internal/MySQLLoggingDefinitions.cs index 0eb84c2b6..b95397df1 100644 --- a/EFCore/src/Diagnostics/Internal/MySQLLoggingDefinitions.cs +++ b/EFCore/src/Diagnostics/Internal/MySQLLoggingDefinitions.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -64,4 +64,4 @@ internal class MySQLLoggingDefinitions : RelationalLoggingDefinitions public EventDefinitionBase? LogReflexiveConstraintIgnored; } -} \ No newline at end of file +} diff --git a/EFCore/src/Diagnostics/MySQLEventId.cs b/EFCore/src/Diagnostics/MySQLEventId.cs index 571f75f12..c51b1d6a8 100644 --- a/EFCore/src/Diagnostics/MySQLEventId.cs +++ b/EFCore/src/Diagnostics/MySQLEventId.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -187,4 +187,4 @@ private enum Id ///
public static readonly EventId ReflexiveConstraintIgnored = MakeScaffoldingId(Id.ReflexiveConstraintIgnored); } -} \ No newline at end of file +} diff --git a/EFCore/src/Extensions/MySQLDatabaseFacadeExtensions.cs b/EFCore/src/Extensions/MySQLDatabaseFacadeExtensions.cs index 585b4a51d..4e6b24506 100644 --- a/EFCore/src/Extensions/MySQLDatabaseFacadeExtensions.cs +++ b/EFCore/src/Extensions/MySQLDatabaseFacadeExtensions.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/src/Extensions/MySQLDbContextOptionsExtensions.cs b/EFCore/src/Extensions/MySQLDbContextOptionsExtensions.cs index 50072cf32..02306ebf6 100644 --- a/EFCore/src/Extensions/MySQLDbContextOptionsExtensions.cs +++ b/EFCore/src/Extensions/MySQLDbContextOptionsExtensions.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -201,4 +201,4 @@ var coreOptionsExtension ((IDbContextOptionsBuilderInfrastructure)optionsBuilder).AddOrUpdateExtension(coreOptionsExtension); } } -} \ No newline at end of file +} diff --git a/EFCore/src/Extensions/MySQLDbFunctionsEnums.cs b/EFCore/src/Extensions/MySQLDbFunctionsEnums.cs index cc8e6a5b6..867fac2e9 100644 --- a/EFCore/src/Extensions/MySQLDbFunctionsEnums.cs +++ b/EFCore/src/Extensions/MySQLDbFunctionsEnums.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/src/Extensions/MySQLDbFunctionsExtensions.cs b/EFCore/src/Extensions/MySQLDbFunctionsExtensions.cs index 4e10401c6..fcb9042ae 100644 --- a/EFCore/src/Extensions/MySQLDbFunctionsExtensions.cs +++ b/EFCore/src/Extensions/MySQLDbFunctionsExtensions.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/src/Extensions/MySQLEntityTypeBuilderExtensions.cs b/EFCore/src/Extensions/MySQLEntityTypeBuilderExtensions.cs index cf19851e7..fd8bf9b6a 100644 --- a/EFCore/src/Extensions/MySQLEntityTypeBuilderExtensions.cs +++ b/EFCore/src/Extensions/MySQLEntityTypeBuilderExtensions.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/src/Extensions/MySQLEntityTypeExtensions.cs b/EFCore/src/Extensions/MySQLEntityTypeExtensions.cs index ed70a8753..5465bfc06 100644 --- a/EFCore/src/Extensions/MySQLEntityTypeExtensions.cs +++ b/EFCore/src/Extensions/MySQLEntityTypeExtensions.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/src/Extensions/MySQLIndexExtensions.cs b/EFCore/src/Extensions/MySQLIndexExtensions.cs index b6e6984c6..0759214c0 100644 --- a/EFCore/src/Extensions/MySQLIndexExtensions.cs +++ b/EFCore/src/Extensions/MySQLIndexExtensions.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -194,4 +194,4 @@ public static int[] SetPrefixLength([NotNull] this IConventionIndex index, int[] public static ConfigurationSource? GetPrefixLengthConfigurationSource([NotNull] this IConventionIndex property) => property.FindAnnotation(MySQLAnnotationNames.IndexPrefixLength)?.GetConfigurationSource(); } -} \ No newline at end of file +} diff --git a/EFCore/src/Extensions/MySQLKeyBuilderExtensions.cs b/EFCore/src/Extensions/MySQLKeyBuilderExtensions.cs index e60b9a12d..147d7f03b 100644 --- a/EFCore/src/Extensions/MySQLKeyBuilderExtensions.cs +++ b/EFCore/src/Extensions/MySQLKeyBuilderExtensions.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/src/Extensions/MySQLKeyExtensions.cs b/EFCore/src/Extensions/MySQLKeyExtensions.cs index 5481669a3..71007b148 100644 --- a/EFCore/src/Extensions/MySQLKeyExtensions.cs +++ b/EFCore/src/Extensions/MySQLKeyExtensions.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/src/Extensions/MySQLMigrationBuilderExtensions.cs b/EFCore/src/Extensions/MySQLMigrationBuilderExtensions.cs index ddb6a689d..ff668966f 100644 --- a/EFCore/src/Extensions/MySQLMigrationBuilderExtensions.cs +++ b/EFCore/src/Extensions/MySQLMigrationBuilderExtensions.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/src/Extensions/MySQLModelBuilderExtensions.cs b/EFCore/src/Extensions/MySQLModelBuilderExtensions.cs index e6a07340f..532b9eed3 100644 --- a/EFCore/src/Extensions/MySQLModelBuilderExtensions.cs +++ b/EFCore/src/Extensions/MySQLModelBuilderExtensions.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/src/Extensions/MySQLModelExtensions.cs b/EFCore/src/Extensions/MySQLModelExtensions.cs index 932546941..7f9f2cbb8 100644 --- a/EFCore/src/Extensions/MySQLModelExtensions.cs +++ b/EFCore/src/Extensions/MySQLModelExtensions.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/src/Extensions/MySQLPropertyBuilderExtensions.cs b/EFCore/src/Extensions/MySQLPropertyBuilderExtensions.cs index edd95f691..145f99d6e 100644 --- a/EFCore/src/Extensions/MySQLPropertyBuilderExtensions.cs +++ b/EFCore/src/Extensions/MySQLPropertyBuilderExtensions.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/src/Extensions/MySQLPropertyExtensions.cs b/EFCore/src/Extensions/MySQLPropertyExtensions.cs index 27b3b44cb..976550298 100644 --- a/EFCore/src/Extensions/MySQLPropertyExtensions.cs +++ b/EFCore/src/Extensions/MySQLPropertyExtensions.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -253,4 +253,4 @@ private static void CheckValueGenerationStrategy(IReadOnlyProperty property, MyS } } } -} \ No newline at end of file +} diff --git a/EFCore/src/Extensions/MySQLServiceCollectionExtensions.cs b/EFCore/src/Extensions/MySQLServiceCollectionExtensions.cs index db08f46e5..ce2e455a8 100644 --- a/EFCore/src/Extensions/MySQLServiceCollectionExtensions.cs +++ b/EFCore/src/Extensions/MySQLServiceCollectionExtensions.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -168,4 +168,4 @@ public static IServiceCollection AddEntityFrameworkMySQL(this IServiceCollection return services; } } -} \ No newline at end of file +} diff --git a/EFCore/src/Extensions/MySQLTypeBaseExtensions.cs b/EFCore/src/Extensions/MySQLTypeBaseExtensions.cs index 59f50fb40..509a2120d 100644 --- a/EFCore/src/Extensions/MySQLTypeBaseExtensions.cs +++ b/EFCore/src/Extensions/MySQLTypeBaseExtensions.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2023, Oracle and/or its affiliates. +// Copyright © 2023, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/src/Extensions/MySqlIndexBuilderExtensions.cs b/EFCore/src/Extensions/MySqlIndexBuilderExtensions.cs index 6409ac85a..7cee66361 100644 --- a/EFCore/src/Extensions/MySqlIndexBuilderExtensions.cs +++ b/EFCore/src/Extensions/MySqlIndexBuilderExtensions.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/src/Infrastructure/Internal/IMySQLOptions.cs b/EFCore/src/Infrastructure/Internal/IMySQLOptions.cs index 4252d8677..e23f97c94 100644 --- a/EFCore/src/Infrastructure/Internal/IMySQLOptions.cs +++ b/EFCore/src/Infrastructure/Internal/IMySQLOptions.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -52,4 +52,4 @@ public interface IMySQLOptions : ISingletonOptions /// The SchemaNameTranslator. MySQLSchemaNameTranslator? SchemaNameTranslator { get; } } -} \ No newline at end of file +} diff --git a/EFCore/src/Infrastructure/Internal/MySQLOptionsExtension.cs b/EFCore/src/Infrastructure/Internal/MySQLOptionsExtension.cs index 0231be384..c6c590b25 100644 --- a/EFCore/src/Infrastructure/Internal/MySQLOptionsExtension.cs +++ b/EFCore/src/Infrastructure/Internal/MySQLOptionsExtension.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -153,4 +153,4 @@ public override void PopulateDebugInfo(IDictionary debugInfo) = (Extension.CharSet?.GetHashCode() ?? 0L).ToString(CultureInfo.InvariantCulture); } } -} \ No newline at end of file +} diff --git a/EFCore/src/Infrastructure/MySQLDbContextOptionsBuilder.cs b/EFCore/src/Infrastructure/MySQLDbContextOptionsBuilder.cs index cae15cd48..350318233 100644 --- a/EFCore/src/Infrastructure/MySQLDbContextOptionsBuilder.cs +++ b/EFCore/src/Infrastructure/MySQLDbContextOptionsBuilder.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/src/Infrastructure/MySQLSchemaBehavior.cs b/EFCore/src/Infrastructure/MySQLSchemaBehavior.cs index acb63a8df..acb97d767 100644 --- a/EFCore/src/Infrastructure/MySQLSchemaBehavior.cs +++ b/EFCore/src/Infrastructure/MySQLSchemaBehavior.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/src/Internal/MySQLModelValidator.cs b/EFCore/src/Internal/MySQLModelValidator.cs index adebfc755..d8c4f4d2d 100644 --- a/EFCore/src/Internal/MySQLModelValidator.cs +++ b/EFCore/src/Internal/MySQLModelValidator.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -48,4 +48,4 @@ public override void Validate(IModel model, IDiagnosticsLogger Add(IColumn target, DiffConte } -} \ No newline at end of file +} diff --git a/EFCore/src/Migrations/Internal/MySQLMigrator.cs b/EFCore/src/Migrations/Internal/MySQLMigrator.cs index b4d944664..1cff48605 100644 --- a/EFCore/src/Migrations/Internal/MySQLMigrator.cs +++ b/EFCore/src/Migrations/Internal/MySQLMigrator.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/src/Migrations/MySQLMigrationsSqlGenerator.cs b/EFCore/src/Migrations/MySQLMigrationsSqlGenerator.cs index 7a02a8ecd..39b21d652 100644 --- a/EFCore/src/Migrations/MySQLMigrationsSqlGenerator.cs +++ b/EFCore/src/Migrations/MySQLMigrationsSqlGenerator.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/src/Migrations/Operations/CreateDatabaseOperation.cs b/EFCore/src/Migrations/Operations/CreateDatabaseOperation.cs index 6e0a422af..4dc9706fc 100644 --- a/EFCore/src/Migrations/Operations/CreateDatabaseOperation.cs +++ b/EFCore/src/Migrations/Operations/CreateDatabaseOperation.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/src/Migrations/Operations/DropDatabaseOperation.cs b/EFCore/src/Migrations/Operations/DropDatabaseOperation.cs index 3e1df9d00..0e485c20b 100644 --- a/EFCore/src/Migrations/Operations/DropDatabaseOperation.cs +++ b/EFCore/src/Migrations/Operations/DropDatabaseOperation.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -40,4 +40,4 @@ internal class MySQLDropDatabaseOperation : MigrationOperation ///
public virtual string Name { get; set; } = null!; } -} \ No newline at end of file +} diff --git a/EFCore/src/Migrations/Operations/MySQLDropPrimaryKeyAndRecreateForeignKeysOperation.cs b/EFCore/src/Migrations/Operations/MySQLDropPrimaryKeyAndRecreateForeignKeysOperation.cs index 68fcf8a10..4480fcc73 100644 --- a/EFCore/src/Migrations/Operations/MySQLDropPrimaryKeyAndRecreateForeignKeysOperation.cs +++ b/EFCore/src/Migrations/Operations/MySQLDropPrimaryKeyAndRecreateForeignKeysOperation.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/src/Migrations/Operations/MySQLDropUniqueConstraintAndRecreateForeignKeysOperation.cs b/EFCore/src/Migrations/Operations/MySQLDropUniqueConstraintAndRecreateForeignKeysOperation.cs index 574d77ae6..8989394bd 100644 --- a/EFCore/src/Migrations/Operations/MySQLDropUniqueConstraintAndRecreateForeignKeysOperation.cs +++ b/EFCore/src/Migrations/Operations/MySQLDropUniqueConstraintAndRecreateForeignKeysOperation.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/src/Properties/AssemblyInfo.cs b/EFCore/src/Properties/AssemblyInfo.cs index b9717d9db..5315d16f7 100644 --- a/EFCore/src/Properties/AssemblyInfo.cs +++ b/EFCore/src/Properties/AssemblyInfo.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -43,4 +43,4 @@ [assembly: InternalsVisibleTo("MySql.EntityFrameworkCore.Basic.Tests, PublicKey = 0024000004800000940000000602000000240000525341310004000001000100d973bda91f71752c78294126974a41a08643168271f65fc0fb3cd45f658da01fbca75ac74067d18e7afbf1467d7a519ce0248b13719717281bb4ddd4ecd71a580dfe0912dfc3690b1d24c7e1975bf7eed90e4ab14e10501eedf763bff8ac204f955c9c15c2cf4ebf6563d8320b6ea8d1ea3807623141f4b81ae30a6c886b3ee1")] [assembly: InternalsVisibleTo("MySql.EntityFrameworkCore.Design.Tests, PublicKey = 0024000004800000940000000602000000240000525341310004000001000100d973bda91f71752c78294126974a41a08643168271f65fc0fb3cd45f658da01fbca75ac74067d18e7afbf1467d7a519ce0248b13719717281bb4ddd4ecd71a580dfe0912dfc3690b1d24c7e1975bf7eed90e4ab14e10501eedf763bff8ac204f955c9c15c2cf4ebf6563d8320b6ea8d1ea3807623141f4b81ae30a6c886b3ee1")] [assembly: InternalsVisibleTo("MySql.EntityFrameworkCore.Migrations.Tests, PublicKey = 0024000004800000940000000602000000240000525341310004000001000100d973bda91f71752c78294126974a41a08643168271f65fc0fb3cd45f658da01fbca75ac74067d18e7afbf1467d7a519ce0248b13719717281bb4ddd4ecd71a580dfe0912dfc3690b1d24c7e1975bf7eed90e4ab14e10501eedf763bff8ac204f955c9c15c2cf4ebf6563d8320b6ea8d1ea3807623141f4b81ae30a6c886b3ee1")] -[assembly: DesignTimeProviderServices("MySql.EntityFrameworkCore.Design.Internal.MySQLDesignTimeServices")] \ No newline at end of file +[assembly: DesignTimeProviderServices("MySql.EntityFrameworkCore.Design.Internal.MySQLDesignTimeServices")] diff --git a/EFCore/src/Query/ExpressionTranslators/Internal/MySQLByteArrayMethodTranslator.cs b/EFCore/src/Query/ExpressionTranslators/Internal/MySQLByteArrayMethodTranslator.cs index e331121ca..d1a59fef5 100644 --- a/EFCore/src/Query/ExpressionTranslators/Internal/MySQLByteArrayMethodTranslator.cs +++ b/EFCore/src/Query/ExpressionTranslators/Internal/MySQLByteArrayMethodTranslator.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/src/Query/ExpressionTranslators/Internal/MySQLDbFunctionsExtensionsMethodTranslator.cs b/EFCore/src/Query/ExpressionTranslators/Internal/MySQLDbFunctionsExtensionsMethodTranslator.cs index 9c477b19f..6bb8eb80f 100644 --- a/EFCore/src/Query/ExpressionTranslators/Internal/MySQLDbFunctionsExtensionsMethodTranslator.cs +++ b/EFCore/src/Query/ExpressionTranslators/Internal/MySQLDbFunctionsExtensionsMethodTranslator.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/src/Query/ExpressionTranslators/Internal/MySQLRegexIsMatchTranslator.cs b/EFCore/src/Query/ExpressionTranslators/Internal/MySQLRegexIsMatchTranslator.cs index 5b027f243..f46e445cb 100644 --- a/EFCore/src/Query/ExpressionTranslators/Internal/MySQLRegexIsMatchTranslator.cs +++ b/EFCore/src/Query/ExpressionTranslators/Internal/MySQLRegexIsMatchTranslator.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/src/Query/ExpressionTranslators/Internal/MySQLStringLengthTranslator.cs b/EFCore/src/Query/ExpressionTranslators/Internal/MySQLStringLengthTranslator.cs index 18b445d2d..2bb6e6986 100644 --- a/EFCore/src/Query/ExpressionTranslators/Internal/MySQLStringLengthTranslator.cs +++ b/EFCore/src/Query/ExpressionTranslators/Internal/MySQLStringLengthTranslator.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -66,4 +66,4 @@ public SqlExpression Translate(SqlExpression? instance, MemberInfo member, Type throw new NotImplementedException(); } } -} \ No newline at end of file +} diff --git a/EFCore/src/Query/Expressions/Internal/MySQLBinaryExpression.cs b/EFCore/src/Query/Expressions/Internal/MySQLBinaryExpression.cs index ccf5d69f2..088c0d229 100644 --- a/EFCore/src/Query/Expressions/Internal/MySQLBinaryExpression.cs +++ b/EFCore/src/Query/Expressions/Internal/MySQLBinaryExpression.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/src/Query/Expressions/Internal/MySQLCollateExpression.cs b/EFCore/src/Query/Expressions/Internal/MySQLCollateExpression.cs index eac7aed15..0608e9f98 100644 --- a/EFCore/src/Query/Expressions/Internal/MySQLCollateExpression.cs +++ b/EFCore/src/Query/Expressions/Internal/MySQLCollateExpression.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/src/Query/Expressions/Internal/MySQLColumnAliasReferenceExpression.cs b/EFCore/src/Query/Expressions/Internal/MySQLColumnAliasReferenceExpression.cs index f78459e79..ca30dcf65 100644 --- a/EFCore/src/Query/Expressions/Internal/MySQLColumnAliasReferenceExpression.cs +++ b/EFCore/src/Query/Expressions/Internal/MySQLColumnAliasReferenceExpression.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/src/Query/Expressions/Internal/MySQLComplexFunctionArgumentExpression.cs b/EFCore/src/Query/Expressions/Internal/MySQLComplexFunctionArgumentExpression.cs index c15370204..528ee4a2c 100644 --- a/EFCore/src/Query/Expressions/Internal/MySQLComplexFunctionArgumentExpression.cs +++ b/EFCore/src/Query/Expressions/Internal/MySQLComplexFunctionArgumentExpression.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/src/Query/Expressions/Internal/MySQLJsonArrayIndexExpression.cs b/EFCore/src/Query/Expressions/Internal/MySQLJsonArrayIndexExpression.cs index ac6ad4501..0030496c4 100644 --- a/EFCore/src/Query/Expressions/Internal/MySQLJsonArrayIndexExpression.cs +++ b/EFCore/src/Query/Expressions/Internal/MySQLJsonArrayIndexExpression.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/src/Query/Expressions/Internal/MySQLJsonTraversalExpression.cs b/EFCore/src/Query/Expressions/Internal/MySQLJsonTraversalExpression.cs index 2ad30e237..f073a4194 100644 --- a/EFCore/src/Query/Expressions/Internal/MySQLJsonTraversalExpression.cs +++ b/EFCore/src/Query/Expressions/Internal/MySQLJsonTraversalExpression.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/src/Query/Expressions/Internal/MySQLMatchExpression.cs b/EFCore/src/Query/Expressions/Internal/MySQLMatchExpression.cs index 5a3875b2c..6469189c7 100644 --- a/EFCore/src/Query/Expressions/Internal/MySQLMatchExpression.cs +++ b/EFCore/src/Query/Expressions/Internal/MySQLMatchExpression.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/src/Query/Expressions/Internal/MySQLRegexpExpression.cs b/EFCore/src/Query/Expressions/Internal/MySQLRegexpExpression.cs index 6cb14eaeb..f10d3ea2e 100644 --- a/EFCore/src/Query/Expressions/Internal/MySQLRegexpExpression.cs +++ b/EFCore/src/Query/Expressions/Internal/MySQLRegexpExpression.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/src/Query/Expressions/Internal/MySQLStringComparisonMethodTranslator.cs b/EFCore/src/Query/Expressions/Internal/MySQLStringComparisonMethodTranslator.cs index 174e19ff8..952e87a71 100644 --- a/EFCore/src/Query/Expressions/Internal/MySQLStringComparisonMethodTranslator.cs +++ b/EFCore/src/Query/Expressions/Internal/MySQLStringComparisonMethodTranslator.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/src/Query/Internal/MySQLCommandParser.cs b/EFCore/src/Query/Internal/MySQLCommandParser.cs index 0552eef3d..2b98ff175 100644 --- a/EFCore/src/Query/Internal/MySQLCommandParser.cs +++ b/EFCore/src/Query/Internal/MySQLCommandParser.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/src/Query/Internal/MySQLCompatibilityExpressionVisitor.cs b/EFCore/src/Query/Internal/MySQLCompatibilityExpressionVisitor.cs index f4207fbf2..d462ea9d6 100644 --- a/EFCore/src/Query/Internal/MySQLCompatibilityExpressionVisitor.cs +++ b/EFCore/src/Query/Internal/MySQLCompatibilityExpressionVisitor.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -100,4 +100,4 @@ protected virtual Expression CheckTranslated(Expression? translated, Expression return translated; } } -} \ No newline at end of file +} diff --git a/EFCore/src/Query/Internal/MySQLCompiledQueryCacheKeyGenerator.cs b/EFCore/src/Query/Internal/MySQLCompiledQueryCacheKeyGenerator.cs index d7ecb43d8..bac0a49f2 100644 --- a/EFCore/src/Query/Internal/MySQLCompiledQueryCacheKeyGenerator.cs +++ b/EFCore/src/Query/Internal/MySQLCompiledQueryCacheKeyGenerator.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/src/Query/Internal/MySQLConvertTranslator.cs b/EFCore/src/Query/Internal/MySQLConvertTranslator.cs index 062f6d04b..c959987b6 100644 --- a/EFCore/src/Query/Internal/MySQLConvertTranslator.cs +++ b/EFCore/src/Query/Internal/MySQLConvertTranslator.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -70,4 +70,4 @@ public MySQLConvertTranslator(ISqlExpressionFactory sqlExpressionFactory) : null; } } -} \ No newline at end of file +} diff --git a/EFCore/src/Query/Internal/MySQLDateDiffFunctionsTranslator.cs b/EFCore/src/Query/Internal/MySQLDateDiffFunctionsTranslator.cs index 1830ab451..cd293d598 100644 --- a/EFCore/src/Query/Internal/MySQLDateDiffFunctionsTranslator.cs +++ b/EFCore/src/Query/Internal/MySQLDateDiffFunctionsTranslator.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -283,4 +283,4 @@ public MySQLDateDiffFunctionsTranslator(ISqlExpressionFactory sqlExpressionFacto return null; } } -} \ No newline at end of file +} diff --git a/EFCore/src/Query/Internal/MySQLDateTimeMemberTranslator.cs b/EFCore/src/Query/Internal/MySQLDateTimeMemberTranslator.cs index db8db62a4..7f4777754 100644 --- a/EFCore/src/Query/Internal/MySQLDateTimeMemberTranslator.cs +++ b/EFCore/src/Query/Internal/MySQLDateTimeMemberTranslator.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/src/Query/Internal/MySQLDateTimeMethodTranslator.cs b/EFCore/src/Query/Internal/MySQLDateTimeMethodTranslator.cs index e15e49787..d03a3cce7 100644 --- a/EFCore/src/Query/Internal/MySQLDateTimeMethodTranslator.cs +++ b/EFCore/src/Query/Internal/MySQLDateTimeMethodTranslator.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -157,4 +157,4 @@ sqlConstantExpression.Value is TimeOnly timeOnly && return null; } } -} \ No newline at end of file +} diff --git a/EFCore/src/Query/Internal/MySQLEvaluatableExpressionFilter.cs b/EFCore/src/Query/Internal/MySQLEvaluatableExpressionFilter.cs index f2a7de7b6..2118664fd 100644 --- a/EFCore/src/Query/Internal/MySQLEvaluatableExpressionFilter.cs +++ b/EFCore/src/Query/Internal/MySQLEvaluatableExpressionFilter.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/src/Query/Internal/MySQLMathTranslator.cs b/EFCore/src/Query/Internal/MySQLMathTranslator.cs index e820a0179..5704f945b 100644 --- a/EFCore/src/Query/Internal/MySQLMathTranslator.cs +++ b/EFCore/src/Query/Internal/MySQLMathTranslator.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -134,4 +134,4 @@ public MySQLMathMethodTranslator(ISqlExpressionFactory sqlExpressionFactory) return null; } } -} \ No newline at end of file +} diff --git a/EFCore/src/Query/Internal/MySQLMemberTranslatorProvider.cs b/EFCore/src/Query/Internal/MySQLMemberTranslatorProvider.cs index d20c26c71..d3c2cc9ab 100644 --- a/EFCore/src/Query/Internal/MySQLMemberTranslatorProvider.cs +++ b/EFCore/src/Query/Internal/MySQLMemberTranslatorProvider.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/src/Query/Internal/MySQLMethodCallTranslatorProvider.cs b/EFCore/src/Query/Internal/MySQLMethodCallTranslatorProvider.cs index 52fbce65c..d059f1170 100644 --- a/EFCore/src/Query/Internal/MySQLMethodCallTranslatorProvider.cs +++ b/EFCore/src/Query/Internal/MySQLMethodCallTranslatorProvider.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/src/Query/Internal/MySQLNewGuidTranslator.cs b/EFCore/src/Query/Internal/MySQLNewGuidTranslator.cs index ddd0510b8..f71d13bf8 100644 --- a/EFCore/src/Query/Internal/MySQLNewGuidTranslator.cs +++ b/EFCore/src/Query/Internal/MySQLNewGuidTranslator.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -59,4 +59,4 @@ public MySQLNewGuidTranslator(ISqlExpressionFactory sqlExpressionFactory) : null; } } -} \ No newline at end of file +} diff --git a/EFCore/src/Query/Internal/MySQLObjectToStringTranslator.cs b/EFCore/src/Query/Internal/MySQLObjectToStringTranslator.cs index 2ece1937b..382f88cca 100644 --- a/EFCore/src/Query/Internal/MySQLObjectToStringTranslator.cs +++ b/EFCore/src/Query/Internal/MySQLObjectToStringTranslator.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -95,4 +95,4 @@ public MySQLObjectToStringTranslator(ISqlExpressionFactory sqlExpressionFactory) : null; } } -} \ No newline at end of file +} diff --git a/EFCore/src/Query/Internal/MySQLParameterBasedSqlProcessor.cs b/EFCore/src/Query/Internal/MySQLParameterBasedSqlProcessor.cs index 10dd9070f..c23e34dd2 100644 --- a/EFCore/src/Query/Internal/MySQLParameterBasedSqlProcessor.cs +++ b/EFCore/src/Query/Internal/MySQLParameterBasedSqlProcessor.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/src/Query/Internal/MySQLParameterBasedSqlProcessorFactory.cs b/EFCore/src/Query/Internal/MySQLParameterBasedSqlProcessorFactory.cs index 463096bb3..e99afda1d 100644 --- a/EFCore/src/Query/Internal/MySQLParameterBasedSqlProcessorFactory.cs +++ b/EFCore/src/Query/Internal/MySQLParameterBasedSqlProcessorFactory.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/src/Query/Internal/MySQLQueryCompilationContext.cs b/EFCore/src/Query/Internal/MySQLQueryCompilationContext.cs index 79d755c11..14cae9543 100644 --- a/EFCore/src/Query/Internal/MySQLQueryCompilationContext.cs +++ b/EFCore/src/Query/Internal/MySQLQueryCompilationContext.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/src/Query/Internal/MySQLQueryCompilationContextFactory.cs b/EFCore/src/Query/Internal/MySQLQueryCompilationContextFactory.cs index 707d5c19d..0d1557b28 100644 --- a/EFCore/src/Query/Internal/MySQLQueryCompilationContextFactory.cs +++ b/EFCore/src/Query/Internal/MySQLQueryCompilationContextFactory.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/src/Query/Internal/MySQLQueryStringFactory.cs b/EFCore/src/Query/Internal/MySQLQueryStringFactory.cs index 112416908..d226ef133 100644 --- a/EFCore/src/Query/Internal/MySQLQueryStringFactory.cs +++ b/EFCore/src/Query/Internal/MySQLQueryStringFactory.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/src/Query/Internal/MySQLQueryTranslationPostprocessor.cs b/EFCore/src/Query/Internal/MySQLQueryTranslationPostprocessor.cs index 913ace28f..2e96e6b32 100644 --- a/EFCore/src/Query/Internal/MySQLQueryTranslationPostprocessor.cs +++ b/EFCore/src/Query/Internal/MySQLQueryTranslationPostprocessor.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -52,4 +52,4 @@ public override Expression Process(Expression query) return new MySQLCompatibilityExpressionVisitor(_options).Visit(query); } } -} \ No newline at end of file +} diff --git a/EFCore/src/Query/Internal/MySQLQueryTranslationPostprocessorFactory.cs b/EFCore/src/Query/Internal/MySQLQueryTranslationPostprocessorFactory.cs index 5bceb5265..79bd9c4d3 100644 --- a/EFCore/src/Query/Internal/MySQLQueryTranslationPostprocessorFactory.cs +++ b/EFCore/src/Query/Internal/MySQLQueryTranslationPostprocessorFactory.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/src/Query/Internal/MySQLSqlExpressionFactory.cs b/EFCore/src/Query/Internal/MySQLSqlExpressionFactory.cs index 270c91eea..bd440a1f1 100644 --- a/EFCore/src/Query/Internal/MySQLSqlExpressionFactory.cs +++ b/EFCore/src/Query/Internal/MySQLSqlExpressionFactory.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/src/Query/Internal/MySQLSqlNullabilityProcessor.cs b/EFCore/src/Query/Internal/MySQLSqlNullabilityProcessor.cs index 020b6202f..936cff59f 100644 --- a/EFCore/src/Query/Internal/MySQLSqlNullabilityProcessor.cs +++ b/EFCore/src/Query/Internal/MySQLSqlNullabilityProcessor.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/src/Query/Internal/MySQLSqlTranslatingExpressionVisitor.cs b/EFCore/src/Query/Internal/MySQLSqlTranslatingExpressionVisitor.cs index 763fee196..1d0634dcf 100644 --- a/EFCore/src/Query/Internal/MySQLSqlTranslatingExpressionVisitor.cs +++ b/EFCore/src/Query/Internal/MySQLSqlTranslatingExpressionVisitor.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -122,4 +122,4 @@ protected override Expression VisitUnary(UnaryExpression unaryExpression) private static string? GetProviderType(SqlExpression expression) => expression.TypeMapping?.StoreType; } -} \ No newline at end of file +} diff --git a/EFCore/src/Query/Internal/MySQLSqlTranslatingExpressionVisitorFactory.cs b/EFCore/src/Query/Internal/MySQLSqlTranslatingExpressionVisitorFactory.cs index 060d00609..d83df7410 100644 --- a/EFCore/src/Query/Internal/MySQLSqlTranslatingExpressionVisitorFactory.cs +++ b/EFCore/src/Query/Internal/MySQLSqlTranslatingExpressionVisitorFactory.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/src/Query/Internal/MySQLStringMemberTranslator.cs b/EFCore/src/Query/Internal/MySQLStringMemberTranslator.cs index b9a6a150c..c320307c3 100644 --- a/EFCore/src/Query/Internal/MySQLStringMemberTranslator.cs +++ b/EFCore/src/Query/Internal/MySQLStringMemberTranslator.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/src/Query/Internal/MySQLStringMethodTranslator.cs b/EFCore/src/Query/Internal/MySQLStringMethodTranslator.cs index ed9a719be..5e69861b1 100644 --- a/EFCore/src/Query/Internal/MySQLStringMethodTranslator.cs +++ b/EFCore/src/Query/Internal/MySQLStringMethodTranslator.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -290,4 +290,4 @@ private SqlExpression ProcessTrimMethod(SqlExpression instance, SqlExpression? t typeof(string)); } } -} \ No newline at end of file +} diff --git a/EFCore/src/Query/MySQLJsonString.cs b/EFCore/src/Query/MySQLJsonString.cs index 0a4e01128..86abded85 100644 --- a/EFCore/src/Query/MySQLJsonString.cs +++ b/EFCore/src/Query/MySQLJsonString.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/src/Query/Sql/Internal/MySQLQueryGeneratorFactory.cs b/EFCore/src/Query/Sql/Internal/MySQLQueryGeneratorFactory.cs index cc27aef05..20c8752ff 100644 --- a/EFCore/src/Query/Sql/Internal/MySQLQueryGeneratorFactory.cs +++ b/EFCore/src/Query/Sql/Internal/MySQLQueryGeneratorFactory.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/src/Query/Sql/Internal/MySQLQuerySqlGenerator.cs b/EFCore/src/Query/Sql/Internal/MySQLQuerySqlGenerator.cs index e8f57ed72..9d529e3ef 100644 --- a/EFCore/src/Query/Sql/Internal/MySQLQuerySqlGenerator.cs +++ b/EFCore/src/Query/Sql/Internal/MySQLQuerySqlGenerator.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/src/Scaffolding/Internal/MySQLCodeGenerator.cs b/EFCore/src/Scaffolding/Internal/MySQLCodeGenerator.cs index a56c916a4..0e24d85b8 100644 --- a/EFCore/src/Scaffolding/Internal/MySQLCodeGenerator.cs +++ b/EFCore/src/Scaffolding/Internal/MySQLCodeGenerator.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -55,4 +55,4 @@ public override MethodCallCodeFragment GenerateUseProvider(string connectionStri ? new object[] { connectionString } : new object[] { connectionString, new NestedClosureCodeFragment("x", providerOptions) }); } -} \ No newline at end of file +} diff --git a/EFCore/src/Scaffolding/Internal/MySQLDataReaderExtension.cs b/EFCore/src/Scaffolding/Internal/MySQLDataReaderExtension.cs index c6a31e83c..eaaac93d4 100644 --- a/EFCore/src/Scaffolding/Internal/MySQLDataReaderExtension.cs +++ b/EFCore/src/Scaffolding/Internal/MySQLDataReaderExtension.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/src/Scaffolding/Internal/MySQLDatabaseModelFactory.cs b/EFCore/src/Scaffolding/Internal/MySQLDatabaseModelFactory.cs index a6da60526..1c43cc806 100644 --- a/EFCore/src/Scaffolding/Internal/MySQLDatabaseModelFactory.cs +++ b/EFCore/src/Scaffolding/Internal/MySQLDatabaseModelFactory.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/src/Storage/Internal/ByteArrayComparer.cs b/EFCore/src/Storage/Internal/ByteArrayComparer.cs index b76ee8cef..72f36aa92 100644 --- a/EFCore/src/Storage/Internal/ByteArrayComparer.cs +++ b/EFCore/src/Storage/Internal/ByteArrayComparer.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -44,4 +44,4 @@ public ByteArrayComparer() { } } -} \ No newline at end of file +} diff --git a/EFCore/src/Storage/Internal/BytesToDateTimeConverter.cs b/EFCore/src/Storage/Internal/BytesToDateTimeConverter.cs index c3a588208..704cc911a 100644 --- a/EFCore/src/Storage/Internal/BytesToDateTimeConverter.cs +++ b/EFCore/src/Storage/Internal/BytesToDateTimeConverter.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -43,4 +43,4 @@ public BytesToDateTimeConverter() { } } -} \ No newline at end of file +} diff --git a/EFCore/src/Storage/Internal/IMySQLRelationalConnection.cs b/EFCore/src/Storage/Internal/IMySQLRelationalConnection.cs index 5e0e661b3..ca4d34b15 100644 --- a/EFCore/src/Storage/Internal/IMySQLRelationalConnection.cs +++ b/EFCore/src/Storage/Internal/IMySQLRelationalConnection.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -34,4 +34,4 @@ internal interface IMySQLRelationalConnection : IRelationalConnection { IMySQLRelationalConnection CreateSourceConnection(); } -} \ No newline at end of file +} diff --git a/EFCore/src/Storage/Internal/MySQLBoolTypeMapping.cs b/EFCore/src/Storage/Internal/MySQLBoolTypeMapping.cs index e413ec50d..918770f7c 100644 --- a/EFCore/src/Storage/Internal/MySQLBoolTypeMapping.cs +++ b/EFCore/src/Storage/Internal/MySQLBoolTypeMapping.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -62,4 +62,4 @@ protected override RelationalTypeMapping Clone(RelationalTypeMappingParameters p protected override string GenerateNonNullSqlLiteral(object value) => (bool)value ? "TRUE" : "FALSE"; } -} \ No newline at end of file +} diff --git a/EFCore/src/Storage/Internal/MySQLByteArrayTypeMapping.cs b/EFCore/src/Storage/Internal/MySQLByteArrayTypeMapping.cs index d81006957..9cdc33da4 100644 --- a/EFCore/src/Storage/Internal/MySQLByteArrayTypeMapping.cs +++ b/EFCore/src/Storage/Internal/MySQLByteArrayTypeMapping.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -117,4 +117,4 @@ protected override void ConfigureParameter(DbParameter parameter) /// protected override string GenerateNonNullSqlLiteral(object value) => ByteArrayFormatter.ToHex((byte[])value); } -} \ No newline at end of file +} diff --git a/EFCore/src/Storage/Internal/MySQLDatabaseCreator.cs b/EFCore/src/Storage/Internal/MySQLDatabaseCreator.cs index 613713a67..a91f1be01 100644 --- a/EFCore/src/Storage/Internal/MySQLDatabaseCreator.cs +++ b/EFCore/src/Storage/Internal/MySQLDatabaseCreator.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -268,4 +268,4 @@ private IReadOnlyList CreateDropCommands() // invalid connection may now be valid. private void ClearPool() => MySqlConnection.ClearPool((MySqlConnection)_connection.DbConnection); } -} \ No newline at end of file +} diff --git a/EFCore/src/Storage/Internal/MySQLDateTimeOffsetTypeMapping.cs b/EFCore/src/Storage/Internal/MySQLDateTimeOffsetTypeMapping.cs index adf4c952f..7c31ad5fd 100644 --- a/EFCore/src/Storage/Internal/MySQLDateTimeOffsetTypeMapping.cs +++ b/EFCore/src/Storage/Internal/MySQLDateTimeOffsetTypeMapping.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/src/Storage/Internal/MySQLDateTypeMapping.cs b/EFCore/src/Storage/Internal/MySQLDateTypeMapping.cs index 21e67c90e..03b6fd744 100644 --- a/EFCore/src/Storage/Internal/MySQLDateTypeMapping.cs +++ b/EFCore/src/Storage/Internal/MySQLDateTypeMapping.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/src/Storage/Internal/MySQLDatetimeTypeMapping.cs b/EFCore/src/Storage/Internal/MySQLDatetimeTypeMapping.cs index 69ba0b5de..38df28500 100644 --- a/EFCore/src/Storage/Internal/MySQLDatetimeTypeMapping.cs +++ b/EFCore/src/Storage/Internal/MySQLDatetimeTypeMapping.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -112,4 +112,4 @@ protected override void ConfigureParameter([NotNull] DbParameter parameter) } } } -} \ No newline at end of file +} diff --git a/EFCore/src/Storage/Internal/MySQLDecimalTypeMapping.cs b/EFCore/src/Storage/Internal/MySQLDecimalTypeMapping.cs index 50170708a..739bd4a75 100644 --- a/EFCore/src/Storage/Internal/MySQLDecimalTypeMapping.cs +++ b/EFCore/src/Storage/Internal/MySQLDecimalTypeMapping.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/src/Storage/Internal/MySQLDoubleTypeMapping.cs b/EFCore/src/Storage/Internal/MySQLDoubleTypeMapping.cs index be2f8e4b6..e5091a087 100644 --- a/EFCore/src/Storage/Internal/MySQLDoubleTypeMapping.cs +++ b/EFCore/src/Storage/Internal/MySQLDoubleTypeMapping.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/src/Storage/Internal/MySQLExecutionStrategy.cs b/EFCore/src/Storage/Internal/MySQLExecutionStrategy.cs index ba3fad038..cdee7a927 100644 --- a/EFCore/src/Storage/Internal/MySQLExecutionStrategy.cs +++ b/EFCore/src/Storage/Internal/MySQLExecutionStrategy.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/src/Storage/Internal/MySQLExecutionStrategyFactory.cs b/EFCore/src/Storage/Internal/MySQLExecutionStrategyFactory.cs index a6663fba1..a977b7cf2 100644 --- a/EFCore/src/Storage/Internal/MySQLExecutionStrategyFactory.cs +++ b/EFCore/src/Storage/Internal/MySQLExecutionStrategyFactory.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -42,4 +42,4 @@ public MySQLExecutionStrategyFactory( protected override IExecutionStrategy CreateDefaultStrategy(ExecutionStrategyDependencies dependencies) => new MySQLExecutionStrategy(dependencies); } -} \ No newline at end of file +} diff --git a/EFCore/src/Storage/Internal/MySQLFloatTypeMapping.cs b/EFCore/src/Storage/Internal/MySQLFloatTypeMapping.cs index 497cb11d7..0ace2680d 100644 --- a/EFCore/src/Storage/Internal/MySQLFloatTypeMapping.cs +++ b/EFCore/src/Storage/Internal/MySQLFloatTypeMapping.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/src/Storage/Internal/MySQLGeometryTypeMapping.cs b/EFCore/src/Storage/Internal/MySQLGeometryTypeMapping.cs index 3935f085c..02572bf57 100644 --- a/EFCore/src/Storage/Internal/MySQLGeometryTypeMapping.cs +++ b/EFCore/src/Storage/Internal/MySQLGeometryTypeMapping.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -72,4 +72,4 @@ public MySQLGeometryTypeMapping( protected override RelationalTypeMapping Clone(RelationalTypeMappingParameters parameters) => new MySQLGeometryTypeMapping(parameters); } -} \ No newline at end of file +} diff --git a/EFCore/src/Storage/Internal/MySQLGuidTypeMapping.cs b/EFCore/src/Storage/Internal/MySQLGuidTypeMapping.cs index aa0f06880..6f6977b93 100644 --- a/EFCore/src/Storage/Internal/MySQLGuidTypeMapping.cs +++ b/EFCore/src/Storage/Internal/MySQLGuidTypeMapping.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/src/Storage/Internal/MySQLJsonChangeTrackingOptions.cs b/EFCore/src/Storage/Internal/MySQLJsonChangeTrackingOptions.cs index 07a5cd07b..5396f175e 100644 --- a/EFCore/src/Storage/Internal/MySQLJsonChangeTrackingOptions.cs +++ b/EFCore/src/Storage/Internal/MySQLJsonChangeTrackingOptions.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/src/Storage/Internal/MySQLJsonTypeMapping.cs b/EFCore/src/Storage/Internal/MySQLJsonTypeMapping.cs index b8052d70d..996abd8ae 100644 --- a/EFCore/src/Storage/Internal/MySQLJsonTypeMapping.cs +++ b/EFCore/src/Storage/Internal/MySQLJsonTypeMapping.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/src/Storage/Internal/MySQLRelationalConnection.cs b/EFCore/src/Storage/Internal/MySQLRelationalConnection.cs index bdebfdc79..69dd43bb8 100644 --- a/EFCore/src/Storage/Internal/MySQLRelationalConnection.cs +++ b/EFCore/src/Storage/Internal/MySQLRelationalConnection.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -96,4 +96,4 @@ public override async Task OpenAsync(CancellationToken cancellationToken, return await base.OpenAsync(cancellationToken, errorsExpected).ConfigureAwait(false); } } -} \ No newline at end of file +} diff --git a/EFCore/src/Storage/Internal/MySQLScaffoldingConnectionSettings.cs b/EFCore/src/Storage/Internal/MySQLScaffoldingConnectionSettings.cs index 1f00a09e2..fc306bfa1 100644 --- a/EFCore/src/Storage/Internal/MySQLScaffoldingConnectionSettings.cs +++ b/EFCore/src/Storage/Internal/MySQLScaffoldingConnectionSettings.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/src/Storage/Internal/MySQLSqlGenerationHelper.cs b/EFCore/src/Storage/Internal/MySQLSqlGenerationHelper.cs index b50d44974..fc5ebe71d 100644 --- a/EFCore/src/Storage/Internal/MySQLSqlGenerationHelper.cs +++ b/EFCore/src/Storage/Internal/MySQLSqlGenerationHelper.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/src/Storage/Internal/MySQLStringTypeMapping.cs b/EFCore/src/Storage/Internal/MySQLStringTypeMapping.cs index 711b103d0..d4b1e6f8d 100644 --- a/EFCore/src/Storage/Internal/MySQLStringTypeMapping.cs +++ b/EFCore/src/Storage/Internal/MySQLStringTypeMapping.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/src/Storage/Internal/MySQLTimeSpanMapping.cs b/EFCore/src/Storage/Internal/MySQLTimeSpanMapping.cs index ebcd357b5..354217789 100644 --- a/EFCore/src/Storage/Internal/MySQLTimeSpanMapping.cs +++ b/EFCore/src/Storage/Internal/MySQLTimeSpanMapping.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/src/Storage/Internal/MySQLTransientExceptionDetector.cs b/EFCore/src/Storage/Internal/MySQLTransientExceptionDetector.cs index d79c4bf49..b8ce03b8c 100644 --- a/EFCore/src/Storage/Internal/MySQLTransientExceptionDetector.cs +++ b/EFCore/src/Storage/Internal/MySQLTransientExceptionDetector.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -41,4 +41,4 @@ public static bool ShouldRetryOn([NotNull] Exception ex) ? mySqlException.IsTransient : ex is TimeoutException; } -} \ No newline at end of file +} diff --git a/EFCore/src/Storage/Internal/MySQLTypeMapping.cs b/EFCore/src/Storage/Internal/MySQLTypeMapping.cs index b41ae11f4..15c9caecf 100644 --- a/EFCore/src/Storage/Internal/MySQLTypeMapping.cs +++ b/EFCore/src/Storage/Internal/MySQLTypeMapping.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/src/Storage/Internal/MySQLTypeMappingSource.cs b/EFCore/src/Storage/Internal/MySQLTypeMappingSource.cs index 273f5617d..5ee73bf1a 100644 --- a/EFCore/src/Storage/Internal/MySQLTypeMappingSource.cs +++ b/EFCore/src/Storage/Internal/MySQLTypeMappingSource.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -340,4 +340,4 @@ protected string ParseStoreTypeName(string? storeTypeName, ref bool? unicode, re } #endif } -} \ No newline at end of file +} diff --git a/EFCore/src/Update/IMySQLUpdateSqlGenerator.cs b/EFCore/src/Update/IMySQLUpdateSqlGenerator.cs index 30dcfd871..4c6c7d3b7 100644 --- a/EFCore/src/Update/IMySQLUpdateSqlGenerator.cs +++ b/EFCore/src/Update/IMySQLUpdateSqlGenerator.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/src/Update/MySQLModificationCommandBatch.cs b/EFCore/src/Update/MySQLModificationCommandBatch.cs index 960e4f9f8..9ea4cf0aa 100644 --- a/EFCore/src/Update/MySQLModificationCommandBatch.cs +++ b/EFCore/src/Update/MySQLModificationCommandBatch.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/src/Update/MySQLModificationCommandBatchFactory.cs b/EFCore/src/Update/MySQLModificationCommandBatchFactory.cs index 7991ef136..d104ca6b1 100644 --- a/EFCore/src/Update/MySQLModificationCommandBatchFactory.cs +++ b/EFCore/src/Update/MySQLModificationCommandBatchFactory.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/src/Update/MySQLUpdateSqlGenerator.cs b/EFCore/src/Update/MySQLUpdateSqlGenerator.cs index 3487e1cea..7350729a8 100644 --- a/EFCore/src/Update/MySQLUpdateSqlGenerator.cs +++ b/EFCore/src/Update/MySQLUpdateSqlGenerator.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/src/Utils/Check.cs b/EFCore/src/Utils/Check.cs index 8a3aed11d..6984e9625 100644 --- a/EFCore/src/Utils/Check.cs +++ b/EFCore/src/Utils/Check.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/src/Utils/CodeAnnotations.cs b/EFCore/src/Utils/CodeAnnotations.cs index 6556044ad..ea07d310e 100644 --- a/EFCore/src/Utils/CodeAnnotations.cs +++ b/EFCore/src/Utils/CodeAnnotations.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/src/Utils/CodeAttributes.cs b/EFCore/src/Utils/CodeAttributes.cs index e7c921ba5..95b9ec4ea 100644 --- a/EFCore/src/Utils/CodeAttributes.cs +++ b/EFCore/src/Utils/CodeAttributes.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -35,4 +35,4 @@ internal sealed class NotNullAttribute : Attribute { } [AttributeUsage(AttributeTargets.All)] internal sealed class CanBeNullAttribute : Attribute { } -} \ No newline at end of file +} diff --git a/EFCore/src/Utils/SharedTypeExtensions.cs b/EFCore/src/Utils/SharedTypeExtensions.cs index 800bbbbea..b1ebef71c 100644 --- a/EFCore/src/Utils/SharedTypeExtensions.cs +++ b/EFCore/src/Utils/SharedTypeExtensions.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -106,4 +106,4 @@ public static MethodInfo GetRequiredRuntimeMethod(this Type type, string name, p => type.GetTypeInfo().GetRuntimeMethod(name, parameters) ?? throw new InvalidOperationException($"Could not find method '{name}' on type '{type}'"); } -} \ No newline at end of file +} diff --git a/EFCore/src/Utils/Static.cs b/EFCore/src/Utils/Static.cs index 1d7578b46..484e87a4d 100644 --- a/EFCore/src/Utils/Static.cs +++ b/EFCore/src/Utils/Static.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/src/Utils/StringBuilderExtensions.cs b/EFCore/src/Utils/StringBuilderExtensions.cs index 046478b17..8a4785544 100644 --- a/EFCore/src/Utils/StringBuilderExtensions.cs +++ b/EFCore/src/Utils/StringBuilderExtensions.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/src/ValueGeneration/Internal/MySQLValueGeneratorSelector.cs b/EFCore/src/ValueGeneration/Internal/MySQLValueGeneratorSelector.cs index 0f4e52a1e..47119f3f1 100644 --- a/EFCore/src/ValueGeneration/Internal/MySQLValueGeneratorSelector.cs +++ b/EFCore/src/ValueGeneration/Internal/MySQLValueGeneratorSelector.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/BasicGuidTests.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/BasicGuidTests.cs index c7f13937b..5888e6e48 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/BasicGuidTests.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/BasicGuidTests.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/ConcurrencyTests.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/ConcurrencyTests.cs index fcc531c20..7591baea0 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/ConcurrencyTests.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/ConcurrencyTests.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/ConnectionTests.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/ConnectionTests.cs index cfa678fe6..1e88d0e76 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/ConnectionTests.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/ConnectionTests.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/DataTests.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/DataTests.cs index 8dc267629..8cf95c170 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/DataTests.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/DataTests.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/DbContextClasses/ConventionsContexts.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/DbContextClasses/ConventionsContexts.cs index 1efda8333..aa5b635b1 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/DbContextClasses/ConventionsContexts.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/DbContextClasses/ConventionsContexts.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/DbContextClasses/EFFluentAPIContexts.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/DbContextClasses/EFFluentAPIContexts.cs index 1bc3deca8..ad39fb4ba 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/DbContextClasses/EFFluentAPIContexts.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/DbContextClasses/EFFluentAPIContexts.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -155,4 +155,4 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) .IsConcurrencyToken(); } } -} \ No newline at end of file +} diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/DbContextClasses/EntitiesClasses.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/DbContextClasses/EntitiesClasses.cs index 0f1652c0a..78151cb87 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/DbContextClasses/EntitiesClasses.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/DbContextClasses/EntitiesClasses.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/DbContextClasses/SakilaLiteContext.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/DbContextClasses/SakilaLiteContext.cs index 0845bcb50..a3141586a 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/DbContextClasses/SakilaLiteContext.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/DbContextClasses/SakilaLiteContext.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/DbContextClasses/TestsContexts.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/DbContextClasses/TestsContexts.cs index 7ec491f0a..8f5036906 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/DbContextClasses/TestsContexts.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/DbContextClasses/TestsContexts.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/DbFunctionsMySQLTest.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/DbFunctionsMySQLTest.cs index 88ade0128..c24d54de8 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/DbFunctionsMySQLTest.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/DbFunctionsMySQLTest.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/EFCoreTests.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/EFCoreTests.cs index 5f9ff2254..c105145cd 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/EFCoreTests.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/EFCoreTests.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/FluentAPITests.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/FluentAPITests.cs index e36acc2e7..16851d3fc 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/FluentAPITests.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/FluentAPITests.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/FunctionalTests.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/FunctionalTests.cs index 841407edc..1c7a6336a 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/FunctionalTests.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/FunctionalTests.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/LoadingRelatedDataTests.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/LoadingRelatedDataTests.cs index d122a91f6..955c5432b 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/LoadingRelatedDataTests.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/LoadingRelatedDataTests.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/ModelingTests.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/ModelingTests.cs index 3df9fb4a3..6424d0277 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/ModelingTests.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/ModelingTests.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -197,4 +197,4 @@ public void ConvertToType() } } } -} \ No newline at end of file +} diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/MultiSchemaTests.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/MultiSchemaTests.cs index 59cba2e4f..503c32699 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/MultiSchemaTests.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/MultiSchemaTests.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -155,4 +155,4 @@ private void PopulateData() } } } -} \ No newline at end of file +} diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/MySQLDatabaseFacadeTest.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/MySQLDatabaseFacadeTest.cs index ffc9a6cb6..72cfe80e9 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/MySQLDatabaseFacadeTest.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/MySQLDatabaseFacadeTest.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/MySQLTypeMapperTests.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/MySQLTypeMapperTests.cs index 5738fc9d3..194600c28 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/MySQLTypeMapperTests.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/MySQLTypeMapperTests.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/Properties/DatabaseSetup.sql b/EFCore/tests/MySql.EFCore.Basic.Tests/Properties/DatabaseSetup.sql index 8f78b919b..4f4d91d2f 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/Properties/DatabaseSetup.sql +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/Properties/DatabaseSetup.sql @@ -1,17 +1,17 @@ /* -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -40,4 +40,4 @@ FLUSH PRIVILEGES; SET GLOBAL max_allowed_packet = 1048576; -FLUSH PRIVILEGES; \ No newline at end of file +FLUSH PRIVILEGES; diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/ShadowPropertiesTests.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/ShadowPropertiesTests.cs index 979fe44b8..acfe975f5 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/ShadowPropertiesTests.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/ShadowPropertiesTests.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/Utils/EntityTestsFixtureClass.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/Utils/EntityTestsFixtureClass.cs index 5416d7114..670bc5778 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/Utils/EntityTestsFixtureClass.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/Utils/EntityTestsFixtureClass.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/Utils/MySqlTestStore.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/Utils/MySqlTestStore.cs index 7470d9c30..5e807de8e 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/Utils/MySqlTestStore.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/Utils/MySqlTestStore.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/Utils/TestUtils.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/Utils/TestUtils.cs index 5c3b56c3e..a09e6ab14 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/Utils/TestUtils.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/Utils/TestUtils.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/tests/MySql.EFCore.Design.Tests/Extensions.cs b/EFCore/tests/MySql.EFCore.Design.Tests/Extensions.cs index 0ed03a4ff..db11322d0 100644 --- a/EFCore/tests/MySql.EFCore.Design.Tests/Extensions.cs +++ b/EFCore/tests/MySql.EFCore.Design.Tests/Extensions.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/tests/MySql.EFCore.Design.Tests/MySQLAnnotationCodeGeneratorTest.cs b/EFCore/tests/MySql.EFCore.Design.Tests/MySQLAnnotationCodeGeneratorTest.cs index 820f6d806..b913c72ac 100644 --- a/EFCore/tests/MySql.EFCore.Design.Tests/MySQLAnnotationCodeGeneratorTest.cs +++ b/EFCore/tests/MySql.EFCore.Design.Tests/MySQLAnnotationCodeGeneratorTest.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/tests/MySql.EFCore.Design.Tests/MySQLCodeGeneratorTest.cs b/EFCore/tests/MySql.EFCore.Design.Tests/MySQLCodeGeneratorTest.cs index a91b2200c..c0b65a21a 100644 --- a/EFCore/tests/MySql.EFCore.Design.Tests/MySQLCodeGeneratorTest.cs +++ b/EFCore/tests/MySql.EFCore.Design.Tests/MySQLCodeGeneratorTest.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/tests/MySql.EFCore.Design.Tests/MySQLDatabaseModelFactoryTest.cs b/EFCore/tests/MySql.EFCore.Design.Tests/MySQLDatabaseModelFactoryTest.cs index a63741fa9..b416915a6 100644 --- a/EFCore/tests/MySql.EFCore.Design.Tests/MySQLDatabaseModelFactoryTest.cs +++ b/EFCore/tests/MySql.EFCore.Design.Tests/MySQLDatabaseModelFactoryTest.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -347,4 +347,4 @@ public void CanFiltersViews() Assert.True(dbModel.Tables.Count == 2); } } -} \ No newline at end of file +} diff --git a/EFCore/tests/MySql.EFCore.Design.Tests/MySQLDatabaseModelFixture.cs b/EFCore/tests/MySql.EFCore.Design.Tests/MySQLDatabaseModelFixture.cs index 4cbb4bcda..3e7365b7b 100644 --- a/EFCore/tests/MySql.EFCore.Design.Tests/MySQLDatabaseModelFixture.cs +++ b/EFCore/tests/MySql.EFCore.Design.Tests/MySQLDatabaseModelFixture.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -75,4 +75,4 @@ public DatabaseModel CreateModel(string dbName, string sql, IEnumerable new DatabaseModelFactoryOptions(tables, schemas)); } } -} \ No newline at end of file +} diff --git a/EFCore/tests/MySql.EFCore.Design.Tests/MySQLDesignTimeProviderServicesTest.cs b/EFCore/tests/MySql.EFCore.Design.Tests/MySQLDesignTimeProviderServicesTest.cs index beb719f0d..3a37ccf82 100644 --- a/EFCore/tests/MySql.EFCore.Design.Tests/MySQLDesignTimeProviderServicesTest.cs +++ b/EFCore/tests/MySql.EFCore.Design.Tests/MySQLDesignTimeProviderServicesTest.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -55,4 +55,4 @@ public void EnsureAssemblyIdentityMatches() Assert.AreEqual(dtType.FullName, dtAttribute?.TypeName); } } -} \ No newline at end of file +} diff --git a/EFCore/tests/MySql.EFCore.Design.Tests/Properties/sakiladb-schema.sql b/EFCore/tests/MySql.EFCore.Design.Tests/Properties/sakiladb-schema.sql index 72c4e3812..5ea9e57d9 100644 --- a/EFCore/tests/MySql.EFCore.Design.Tests/Properties/sakiladb-schema.sql +++ b/EFCore/tests/MySql.EFCore.Design.Tests/Properties/sakiladb-schema.sql @@ -1,17 +1,17 @@ /* -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/tests/MySql.EFCore.Design.Tests/Properties/world.sql b/EFCore/tests/MySql.EFCore.Design.Tests/Properties/world.sql index 6d2e171ec..1251c03f6 100644 --- a/EFCore/tests/MySql.EFCore.Design.Tests/Properties/world.sql +++ b/EFCore/tests/MySql.EFCore.Design.Tests/Properties/world.sql @@ -1,17 +1,17 @@ /* -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/tests/MySql.EFCore.Migrations.Tests/MySQLHistoryRepositoryTests.cs b/EFCore/tests/MySql.EFCore.Migrations.Tests/MySQLHistoryRepositoryTests.cs index 148c3da26..35a1611d5 100644 --- a/EFCore/tests/MySql.EFCore.Migrations.Tests/MySQLHistoryRepositoryTests.cs +++ b/EFCore/tests/MySql.EFCore.Migrations.Tests/MySQLHistoryRepositoryTests.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/tests/MySql.EFCore.Migrations.Tests/MySQLMigrationsTests.cs b/EFCore/tests/MySql.EFCore.Migrations.Tests/MySQLMigrationsTests.cs index c4ef3aec4..30e97a470 100644 --- a/EFCore/tests/MySql.EFCore.Migrations.Tests/MySQLMigrationsTests.cs +++ b/EFCore/tests/MySql.EFCore.Migrations.Tests/MySQLMigrationsTests.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/tests/MySql.EFCore.Migrations.Tests/MySqlMigrationsGeneratorTest.cs b/EFCore/tests/MySql.EFCore.Migrations.Tests/MySqlMigrationsGeneratorTest.cs index 15d247903..f36545f30 100644 --- a/EFCore/tests/MySql.EFCore.Migrations.Tests/MySqlMigrationsGeneratorTest.cs +++ b/EFCore/tests/MySql.EFCore.Migrations.Tests/MySqlMigrationsGeneratorTest.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/tests/MySql.EFCore.Migrations.Tests/MySqlMigrationsGeneratorTestBase.cs b/EFCore/tests/MySql.EFCore.Migrations.Tests/MySqlMigrationsGeneratorTestBase.cs index b67616ac8..8e15deaad 100644 --- a/EFCore/tests/MySql.EFCore.Migrations.Tests/MySqlMigrationsGeneratorTestBase.cs +++ b/EFCore/tests/MySql.EFCore.Migrations.Tests/MySqlMigrationsGeneratorTestBase.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EFCore/tests/MySql.EFCore.Migrations.Tests/Utilities/ContextUtils.cs b/EFCore/tests/MySql.EFCore.Migrations.Tests/Utilities/ContextUtils.cs index 24afa9349..5f059f6a0 100644 --- a/EFCore/tests/MySql.EFCore.Migrations.Tests/Utilities/ContextUtils.cs +++ b/EFCore/tests/MySql.EFCore.Migrations.Tests/Utilities/ContextUtils.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EntityFramework/src/EFMySqlCommand.cs b/EntityFramework/src/EFMySqlCommand.cs index 39cc3af41..0dd6d642c 100644 --- a/EntityFramework/src/EFMySqlCommand.cs +++ b/EntityFramework/src/EFMySqlCommand.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2008, 2021, Oracle and/or its affiliates. +// Copyright © 2008, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EntityFramework/src/EFMySqlDataReader.cs b/EntityFramework/src/EFMySqlDataReader.cs index 791fa4e8c..c4342f567 100644 --- a/EntityFramework/src/EFMySqlDataReader.cs +++ b/EntityFramework/src/EFMySqlDataReader.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2008, 2017, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2008, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EntityFramework/src/Fragments/InputFragment.cs b/EntityFramework/src/Fragments/InputFragment.cs index 464932eac..80ea10800 100644 --- a/EntityFramework/src/Fragments/InputFragment.cs +++ b/EntityFramework/src/Fragments/InputFragment.cs @@ -1,16 +1,16 @@ -// Copyright © 2008, 2017, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2008, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EntityFramework/src/Fragments/JoinFragment.cs b/EntityFramework/src/Fragments/JoinFragment.cs index a3cdb7492..466c04bc6 100644 --- a/EntityFramework/src/Fragments/JoinFragment.cs +++ b/EntityFramework/src/Fragments/JoinFragment.cs @@ -1,16 +1,16 @@ -// Copyright © 2008, 2017, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2008, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EntityFramework/src/Fragments/SqlFragment.cs b/EntityFramework/src/Fragments/SqlFragment.cs index 82aea8756..97abc6c3b 100644 --- a/EntityFramework/src/Fragments/SqlFragment.cs +++ b/EntityFramework/src/Fragments/SqlFragment.cs @@ -1,16 +1,16 @@ -// Copyright © 2008, 2018, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2008, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EntityFramework/src/Fragments/TableFragment.cs b/EntityFramework/src/Fragments/TableFragment.cs index cd536d9d0..b9c6653d4 100644 --- a/EntityFramework/src/Fragments/TableFragment.cs +++ b/EntityFramework/src/Fragments/TableFragment.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2008, 2021, Oracle and/or its affiliates. +// Copyright © 2008, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -68,4 +68,4 @@ internal override void Accept(SqlFragmentVisitor visitor) visitor.Visit(this); } } -} \ No newline at end of file +} diff --git a/EntityFramework/src/Generators/DeleteGenerator.cs b/EntityFramework/src/Generators/DeleteGenerator.cs index 0a4a500d8..7b1cd1408 100644 --- a/EntityFramework/src/Generators/DeleteGenerator.cs +++ b/EntityFramework/src/Generators/DeleteGenerator.cs @@ -1,16 +1,16 @@ -// Copyright © 2008, 2017, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2008, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EntityFramework/src/Generators/FunctionGenerator.cs b/EntityFramework/src/Generators/FunctionGenerator.cs index 968aefdb1..6ec949f79 100644 --- a/EntityFramework/src/Generators/FunctionGenerator.cs +++ b/EntityFramework/src/Generators/FunctionGenerator.cs @@ -1,16 +1,16 @@ -// Copyright © 2008, 2017, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2008, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EntityFramework/src/Generators/FunctionProcessor.cs b/EntityFramework/src/Generators/FunctionProcessor.cs index bc0f1640e..d8f44727f 100644 --- a/EntityFramework/src/Generators/FunctionProcessor.cs +++ b/EntityFramework/src/Generators/FunctionProcessor.cs @@ -1,16 +1,16 @@ -// Copyright © 2008, 2018, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2008, 2024, Oracle and/or its affiliates. All rights reserved. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EntityFramework/src/Generators/InsertGenerator.cs b/EntityFramework/src/Generators/InsertGenerator.cs index 5968a2378..b1fbb5e34 100644 --- a/EntityFramework/src/Generators/InsertGenerator.cs +++ b/EntityFramework/src/Generators/InsertGenerator.cs @@ -1,16 +1,16 @@ -// Copyright © 2008, 2017, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2008, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EntityFramework/src/Generators/Scope.cs b/EntityFramework/src/Generators/Scope.cs index a73f12780..eabf4d397 100644 --- a/EntityFramework/src/Generators/Scope.cs +++ b/EntityFramework/src/Generators/Scope.cs @@ -1,16 +1,16 @@ -// Copyright © 2008, 2018, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2008, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EntityFramework/src/Generators/SelectGenerator.cs b/EntityFramework/src/Generators/SelectGenerator.cs index 222c9fc0e..a4da311f4 100644 --- a/EntityFramework/src/Generators/SelectGenerator.cs +++ b/EntityFramework/src/Generators/SelectGenerator.cs @@ -1,16 +1,16 @@ -// Copyright © 2008, 2017, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2008, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EntityFramework/src/Generators/SqlGenerator.cs b/EntityFramework/src/Generators/SqlGenerator.cs index 14091317c..717d87d5f 100644 --- a/EntityFramework/src/Generators/SqlGenerator.cs +++ b/EntityFramework/src/Generators/SqlGenerator.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2008, 2022, Oracle and/or its affiliates. +// Copyright © 2008, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EntityFramework/src/Generators/UpdateGenerator.cs b/EntityFramework/src/Generators/UpdateGenerator.cs index 7b309719b..d4e1169fc 100644 --- a/EntityFramework/src/Generators/UpdateGenerator.cs +++ b/EntityFramework/src/Generators/UpdateGenerator.cs @@ -1,16 +1,16 @@ -// Copyright © 2008, 2018, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2008, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EntityFramework/src/Metadata.cs b/EntityFramework/src/Metadata.cs index 95cb3024d..38b4709b2 100644 --- a/EntityFramework/src/Metadata.cs +++ b/EntityFramework/src/Metadata.cs @@ -1,16 +1,16 @@ -// Copyright © 2008, 2017, , Oracle and/or its affiliates. All rights reserved. +// Copyright © 2008, 2024, Oracle and/or its affiliates. All rights reserved. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EntityFramework/src/MySqlConnectionFactory.cs b/EntityFramework/src/MySqlConnectionFactory.cs index 05385119c..b8e0fa159 100644 --- a/EntityFramework/src/MySqlConnectionFactory.cs +++ b/EntityFramework/src/MySqlConnectionFactory.cs @@ -1,16 +1,16 @@ -// Copyright © 2008, 2017, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2008, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -53,4 +53,4 @@ public DbConnection CreateConnection(string connectionString) return new MySqlConnection(connectionString); } } -} \ No newline at end of file +} diff --git a/EntityFramework/src/MySqlDependencyResolver.cs b/EntityFramework/src/MySqlDependencyResolver.cs index 478791e44..c4f5eafea 100644 --- a/EntityFramework/src/MySqlDependencyResolver.cs +++ b/EntityFramework/src/MySqlDependencyResolver.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EntityFramework/src/MySqlEFConfiguration.cs b/EntityFramework/src/MySqlEFConfiguration.cs index abc7e2327..1f99e6a9a 100644 --- a/EntityFramework/src/MySqlEFConfiguration.cs +++ b/EntityFramework/src/MySqlEFConfiguration.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EntityFramework/src/MySqlExecutionStrategy.cs b/EntityFramework/src/MySqlExecutionStrategy.cs index 04dc463f6..8740d3173 100644 --- a/EntityFramework/src/MySqlExecutionStrategy.cs +++ b/EntityFramework/src/MySqlExecutionStrategy.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -244,4 +244,4 @@ public BackoffAlgorithmNdb() { } } -} \ No newline at end of file +} diff --git a/EntityFramework/src/MySqlHistoryContext.cs b/EntityFramework/src/MySqlHistoryContext.cs index b209507fd..9235ba7ef 100644 --- a/EntityFramework/src/MySqlHistoryContext.cs +++ b/EntityFramework/src/MySqlHistoryContext.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EntityFramework/src/MySqlLogger.cs b/EntityFramework/src/MySqlLogger.cs index 553d1b144..00624aaa9 100644 --- a/EntityFramework/src/MySqlLogger.cs +++ b/EntityFramework/src/MySqlLogger.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EntityFramework/src/MySqlMigrationSqlGenerator.cs b/EntityFramework/src/MySqlMigrationSqlGenerator.cs index 8ca716a3e..32e3b50ac 100644 --- a/EntityFramework/src/MySqlMigrationSqlGenerator.cs +++ b/EntityFramework/src/MySqlMigrationSqlGenerator.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2008, 2021, Oracle and/or its affiliates. +// Copyright © 2008, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EntityFramework/src/MySqlSpatialDataReader.cs b/EntityFramework/src/MySqlSpatialDataReader.cs index 5ae81d43b..8299b68f0 100644 --- a/EntityFramework/src/MySqlSpatialDataReader.cs +++ b/EntityFramework/src/MySqlSpatialDataReader.cs @@ -1,16 +1,16 @@ -// Copyright © 2013, 2017, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EntityFramework/src/MySqlSpatialServices.cs b/EntityFramework/src/MySqlSpatialServices.cs index f9bb26f48..f346f2ea6 100644 --- a/EntityFramework/src/MySqlSpatialServices.cs +++ b/EntityFramework/src/MySqlSpatialServices.cs @@ -1,16 +1,16 @@ -// Copyright © 2013, 2017, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EntityFramework/src/Properties/AssemblyInfo.cs b/EntityFramework/src/Properties/AssemblyInfo.cs index dc7661c9c..fa254f8c9 100644 --- a/EntityFramework/src/Properties/AssemblyInfo.cs +++ b/EntityFramework/src/Properties/AssemblyInfo.cs @@ -1,16 +1,16 @@ -// Copyright © 2008, 2023, Oracle and/or its affiliates. +// Copyright © 2008, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EntityFramework/src/Properties/Resources.Designer.cs b/EntityFramework/src/Properties/Resources.Designer.cs index 8ecbdd21c..3dd3a9932 100644 --- a/EntityFramework/src/Properties/Resources.Designer.cs +++ b/EntityFramework/src/Properties/Resources.Designer.cs @@ -1,99 +1,99 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.42000 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace MySql.Data.EntityFramework.Properties { - using System; - - - /// - /// A strongly-typed resource class, for looking up localized strings, etc. - /// - // This class was auto-generated by the StronglyTypedResourceBuilder - // class via a tool like ResGen or Visual Studio. - // To add or remove a member, edit your .ResX file then rerun ResGen - // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class Resources { - - private static global::System.Resources.ResourceManager resourceMan; - - private static global::System.Globalization.CultureInfo resourceCulture; - - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal Resources() { - } - - /// - /// Returns the cached ResourceManager instance used by this class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager { - get { - if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("MySql.Data.EntityFramework.Properties.Resources", typeof(Resources).Assembly); - resourceMan = temp; - } - return resourceMan; - } - } - - /// - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture { - get { - return resourceCulture; - } - set { - resourceCulture = value; - } - } - - /// - /// Looks up a localized string similar to The connection parameter must reference an object of type MySql.Data.MySqlConnection. - /// - internal static string ConnectionMustBeOfTypeMySqlConnection { - get { - return ResourceManager.GetString("ConnectionMustBeOfTypeMySqlConnection", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to There is no store type corresponding to the EDM type '{0}' of primitive type '{1}'.. - /// - internal static string NoStoreTypeForEdmType { - get { - return ResourceManager.GetString("NoStoreTypeForEdmType", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The underlying provider does not support the type '{0}'.. - /// - internal static string TypeNotSupported { - get { - return ResourceManager.GetString("TypeNotSupported", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Result type of a function is expected to be a collection of RowType or PrimitiveType. - /// - internal static string WrongFunctionResultType { - get { - return ResourceManager.GetString("WrongFunctionResultType", resourceCulture); - } - } - } -} +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace MySql.Data.EntityFramework.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("MySql.Data.EntityFramework.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to The connection parameter must reference an object of type MySql.Data.MySqlConnection. + /// + internal static string ConnectionMustBeOfTypeMySqlConnection { + get { + return ResourceManager.GetString("ConnectionMustBeOfTypeMySqlConnection", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to There is no store type corresponding to the EDM type '{0}' of primitive type '{1}'.. + /// + internal static string NoStoreTypeForEdmType { + get { + return ResourceManager.GetString("NoStoreTypeForEdmType", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The underlying provider does not support the type '{0}'.. + /// + internal static string TypeNotSupported { + get { + return ResourceManager.GetString("TypeNotSupported", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Result type of a function is expected to be a collection of RowType or PrimitiveType. + /// + internal static string WrongFunctionResultType { + get { + return ResourceManager.GetString("WrongFunctionResultType", resourceCulture); + } + } + } +} diff --git a/EntityFramework/src/ProviderManifest.cs b/EntityFramework/src/ProviderManifest.cs index 24ca857ba..0c3cf868f 100644 --- a/EntityFramework/src/ProviderManifest.cs +++ b/EntityFramework/src/ProviderManifest.cs @@ -1,16 +1,16 @@ -// Copyright © 2008, 2018, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2008, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EntityFramework/src/ProviderServices.cs b/EntityFramework/src/ProviderServices.cs index a10f90a7a..f992126ce 100644 --- a/EntityFramework/src/ProviderServices.cs +++ b/EntityFramework/src/ProviderServices.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2014, 2020, Oracle and/or its affiliates. +// Copyright © 2014, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EntityFramework/src/Statements/DeleteStatement.cs b/EntityFramework/src/Statements/DeleteStatement.cs index 345578028..e4f9db157 100644 --- a/EntityFramework/src/Statements/DeleteStatement.cs +++ b/EntityFramework/src/Statements/DeleteStatement.cs @@ -1,16 +1,16 @@ -// Copyright © 2008, 2017, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2008, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EntityFramework/src/Statements/InsertStatement.cs b/EntityFramework/src/Statements/InsertStatement.cs index 09cfa9370..9a818a170 100644 --- a/EntityFramework/src/Statements/InsertStatement.cs +++ b/EntityFramework/src/Statements/InsertStatement.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2008, 2022, Oracle and/or its affiliates. +// Copyright © 2008, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EntityFramework/src/Statements/SelectStatement.cs b/EntityFramework/src/Statements/SelectStatement.cs index c802edb45..96d8ab4ea 100644 --- a/EntityFramework/src/Statements/SelectStatement.cs +++ b/EntityFramework/src/Statements/SelectStatement.cs @@ -1,16 +1,16 @@ -// Copyright (C) 2008, 2021, Oracle and/or its affiliates. +// Copyright © 2008, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EntityFramework/src/Statements/UpdateStatement.cs b/EntityFramework/src/Statements/UpdateStatement.cs index 3dc7db55d..7ae917d37 100644 --- a/EntityFramework/src/Statements/UpdateStatement.cs +++ b/EntityFramework/src/Statements/UpdateStatement.cs @@ -1,16 +1,16 @@ -// Copyright © 2008, 2017, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2008, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/AggregateOperators.cs b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/AggregateOperators.cs index ac55d9e3b..2692f73d1 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/AggregateOperators.cs +++ b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/AggregateOperators.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/CanonicalFunctions.cs b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/CanonicalFunctions.cs index dc3cea487..765b90ce5 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/CanonicalFunctions.cs +++ b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/CanonicalFunctions.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/DataTypeTests.cs b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/DataTypeTests.cs index 8c0ca2e45..3d620c5d1 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/DataTypeTests.cs +++ b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/DataTypeTests.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/DatesTypesTests.cs b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/DatesTypesTests.cs index c4fa0e221..22b246a55 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/DatesTypesTests.cs +++ b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/DatesTypesTests.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2011, 2023 Oracle and/or its affiliates. +// Copyright © 2011, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/DefaultContext.cs b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/DefaultContext.cs index 9632e679f..33e99cb62 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/DefaultContext.cs +++ b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/DefaultContext.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2014, 2022, Oracle and/or its affiliates. +// Copyright © 2014, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -149,4 +149,4 @@ public class LongDataTest [StringLength(15)] public string Data { get; set; } } -} \ No newline at end of file +} diff --git a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/DefaultFixture.cs b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/DefaultFixture.cs index 28c6b3f9c..c575b0617 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/DefaultFixture.cs +++ b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/DefaultFixture.cs @@ -1,179 +1,179 @@ -// Copyright (c) 2013, 2020, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using System.Data.Entity.Core.Objects; -using System.Text.RegularExpressions; -using System.Data.Entity.Infrastructure; -using NUnit.Framework; -using System; -using MySql.Data.MySqlClient; - -namespace MySql.Data.EntityFramework.Tests -{ - public class DefaultFixture - { - public string host { get; set; } - public string user { get; set; } - public string password { get; set; } - public uint Port { get; set; } - public string database { get; set; } - public Version version { get; set; } - public MySqlConnection Connection { get; set; } - public string ConnectionString { get; set; } - public bool NeedSetup { get; set; } - - public DefaultFixture() - { - NeedSetup = true; - } - - [OneTimeSetUp] - public void OneTimeSetup() - { - if (NeedSetup) - { - NeedSetup = false; - - database = "db-" + this.GetType().Name.ToLower(); - if (database.Length > 32) - database = database.Substring(0, 32); - - MySqlConnectionStringBuilder sb = new MySqlConnectionStringBuilder(); - sb.Server = "localhost"; - string port = Environment.GetEnvironmentVariable("MYSQL_PORT"); - sb.Port = Port = string.IsNullOrEmpty(port) ? 3306 : uint.Parse(port); - sb.UserID = "root"; - sb.Pooling = false; - sb.AllowUserVariables = true; - sb.Database = database; - ConnectionString = sb.ToString(); - - using (DefaultContext ctx = new DefaultContext(ConnectionString)) - { - if (ctx.Database.Exists()) - ctx.Database.Delete(); - var context = ((IObjectContextAdapter)ctx).ObjectContext; - context.CreateDatabase(); - } - - Connection = new MySqlConnection(ConnectionString); - Connection.Open(); - LoadData(); - } - } - - [OneTimeTearDown] - public void OneTimeTearDown() - { - MySqlConnection.ClearAllPools(); - ExecSQL($"DROP DATABASE IF EXISTS `{Connection.Database}`"); - Connection.Close(); - } - - [SetUp] - public virtual void SetUp() - { - if (NeedSetup) - { - NeedSetup = false; - - using (DefaultContext ctx = new DefaultContext(ConnectionString)) - { - if (ctx.Database.Exists()) - ctx.Database.Delete(); - var context = ((IObjectContextAdapter)ctx).ObjectContext; - context.CreateDatabase(); - } - - LoadData(); - } - } - - [TearDown] - public virtual void TearDown() { } - - public virtual void LoadData() { } - - public Version Version - { - get - { - if (version == null) - { - string versionString = Connection.ServerVersion; - int i = 0; - while (i < versionString.Length && - (Char.IsDigit(versionString[i]) || versionString[i] == '.')) - i++; - - version = new Version(versionString.Substring(0, i)); - } - return version; - } - } - - public void ExecSQL(string sql) - { - MySqlCommand cmd = new MySqlCommand(sql, Connection); - cmd.ExecuteNonQuery(); - } - - public static void CheckSql(string actual, string expected) - { - var exp = Regex.Replace(expected, @"\s", string.Empty); - var act = Regex.Replace(actual, @"\s", string.Empty); - Assert.AreEqual(act, exp); - } - - public static void CheckSqlContains(string actual, string expected) - { - var exp = Regex.Replace(expected, @"\s", string.Empty); - var act = Regex.Replace(actual, @"\s", string.Empty); - Assert.True(act.Contains(exp)); - } - - public DefaultContext GetDefaultContext() - { - return new DefaultContext(ConnectionString); - } - - public void TestESql(string eSql, string expected, params ObjectParameter[] parms) - { - using (DefaultContext ctx = GetDefaultContext()) - { - var context = ((IObjectContextAdapter)ctx).ObjectContext; - ObjectQuery q = context.CreateQuery(eSql); - foreach (var p in parms) - q.Parameters.Add(p); - - string sql = q.ToTraceString(); - CheckSql(sql, expected); - } - } - } -} +// Copyright © 2013, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using System.Data.Entity.Core.Objects; +using System.Text.RegularExpressions; +using System.Data.Entity.Infrastructure; +using NUnit.Framework; +using System; +using MySql.Data.MySqlClient; + +namespace MySql.Data.EntityFramework.Tests +{ + public class DefaultFixture + { + public string host { get; set; } + public string user { get; set; } + public string password { get; set; } + public uint Port { get; set; } + public string database { get; set; } + public Version version { get; set; } + public MySqlConnection Connection { get; set; } + public string ConnectionString { get; set; } + public bool NeedSetup { get; set; } + + public DefaultFixture() + { + NeedSetup = true; + } + + [OneTimeSetUp] + public void OneTimeSetup() + { + if (NeedSetup) + { + NeedSetup = false; + + database = "db-" + this.GetType().Name.ToLower(); + if (database.Length > 32) + database = database.Substring(0, 32); + + MySqlConnectionStringBuilder sb = new MySqlConnectionStringBuilder(); + sb.Server = "localhost"; + string port = Environment.GetEnvironmentVariable("MYSQL_PORT"); + sb.Port = Port = string.IsNullOrEmpty(port) ? 3306 : uint.Parse(port); + sb.UserID = "root"; + sb.Pooling = false; + sb.AllowUserVariables = true; + sb.Database = database; + ConnectionString = sb.ToString(); + + using (DefaultContext ctx = new DefaultContext(ConnectionString)) + { + if (ctx.Database.Exists()) + ctx.Database.Delete(); + var context = ((IObjectContextAdapter)ctx).ObjectContext; + context.CreateDatabase(); + } + + Connection = new MySqlConnection(ConnectionString); + Connection.Open(); + LoadData(); + } + } + + [OneTimeTearDown] + public void OneTimeTearDown() + { + MySqlConnection.ClearAllPools(); + ExecSQL($"DROP DATABASE IF EXISTS `{Connection.Database}`"); + Connection.Close(); + } + + [SetUp] + public virtual void SetUp() + { + if (NeedSetup) + { + NeedSetup = false; + + using (DefaultContext ctx = new DefaultContext(ConnectionString)) + { + if (ctx.Database.Exists()) + ctx.Database.Delete(); + var context = ((IObjectContextAdapter)ctx).ObjectContext; + context.CreateDatabase(); + } + + LoadData(); + } + } + + [TearDown] + public virtual void TearDown() { } + + public virtual void LoadData() { } + + public Version Version + { + get + { + if (version == null) + { + string versionString = Connection.ServerVersion; + int i = 0; + while (i < versionString.Length && + (Char.IsDigit(versionString[i]) || versionString[i] == '.')) + i++; + + version = new Version(versionString.Substring(0, i)); + } + return version; + } + } + + public void ExecSQL(string sql) + { + MySqlCommand cmd = new MySqlCommand(sql, Connection); + cmd.ExecuteNonQuery(); + } + + public static void CheckSql(string actual, string expected) + { + var exp = Regex.Replace(expected, @"\s", string.Empty); + var act = Regex.Replace(actual, @"\s", string.Empty); + Assert.AreEqual(act, exp); + } + + public static void CheckSqlContains(string actual, string expected) + { + var exp = Regex.Replace(expected, @"\s", string.Empty); + var act = Regex.Replace(actual, @"\s", string.Empty); + Assert.True(act.Contains(exp)); + } + + public DefaultContext GetDefaultContext() + { + return new DefaultContext(ConnectionString); + } + + public void TestESql(string eSql, string expected, params ObjectParameter[] parms) + { + using (DefaultContext ctx = GetDefaultContext()) + { + var context = ((IObjectContextAdapter)ctx).ObjectContext; + ObjectQuery q = context.CreateQuery(eSql); + foreach (var p in parms) + q.Parameters.Add(p); + + string sql = q.ToTraceString(); + CheckSql(sql, expected); + } + } + } +} diff --git a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/DeleteTests.cs b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/DeleteTests.cs index 27aa0034c..305a60805 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/DeleteTests.cs +++ b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/DeleteTests.cs @@ -1,136 +1,136 @@ -// Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using System.Linq; -using NUnit.Framework; -using System.Data; -using System.Data.Entity; -using System.Data.Entity.Infrastructure; - -namespace MySql.Data.EntityFramework.Tests -{ - - public class DeleteTests : DefaultFixture - { - public override void LoadData() - { - using (DefaultContext ctx = new DefaultContext(ConnectionString)) - { - ctx.Products.Add(new Product() { Name = "Garbage Truck", MinAge = 8 }); - ctx.Products.Add(new Product() { Name = "Fire Truck", MinAge = 12 }); - ctx.Products.Add(new Product() { Name = "Hula Hoop", MinAge = 18 }); - ctx.SaveChanges(); - } - } - - [Test] - public void SimpleDeleteAllRows() - { - using (DefaultContext ctx = new DefaultContext(ConnectionString)) - { - Assert.True(ctx.Products.Count() > 0); - - foreach (Product p in ctx.Products) - ctx.Products.Remove(p); - ctx.SaveChanges(); - - Assert.AreEqual(0, ctx.Products.Count()); - } - // set the flag that will cause the setup to happen again - // since we just blew away a table - NeedSetup = true; - } - - [Test] - public void SimpleDeleteRowByParameter() - { - using (DefaultContext ctx = new DefaultContext(ConnectionString)) - { - int total = ctx.Products.Count(); - int cntLeft = ctx.Products.Where(b => b.MinAge >= 18).Count(); - // make sure the test is valid - Assert.True(total > cntLeft); - - foreach (Product p in ctx.Products.Where(b => b.MinAge < 18).ToList()) - ctx.Products.Remove(p); - ctx.SaveChanges(); - Assert.AreEqual(cntLeft, ctx.Products.Count()); - } - // set the flag that will cause the setup to happen again - // since we just blew away a table - NeedSetup = true; - } - - - public class Widget - { - public int Id { get; set; } - public WidgetDetail Detail { get; set; } - } - - public class WidgetDetail - { - public int Id { get; set; } - public Widget Widget { get; set; } - } - - public class WidgetContext : DbContext - { - public WidgetContext(string connStr) : base(connStr) - { - Database.SetInitializer(null); - } - - protected override void OnModelCreating(DbModelBuilder modelBuilder) - { - base.OnModelCreating(modelBuilder); - modelBuilder.Entity() - .HasRequired(b => b.Widget) - .WithOptional(a => a.Detail) - .WillCascadeOnDelete(true); - } - } - - /// - /// Fix for bug Cascading delete using CreateDatabase in Entity Framework - /// (http://bugs.mysql.com/bug.php?id=64779) using ModelFirst. - /// - [Test] - public void XOnDeleteCascade() - { - using (WidgetContext ctx = new WidgetContext(ConnectionString)) - { - var context = ((IObjectContextAdapter)ctx).ObjectContext; - var sql = context.CreateDatabaseScript(); - CheckSqlContains(sql, - @"ALTER TABLE `WidgetDetails` ADD CONSTRAINT WidgetDetail_Widget - FOREIGN KEY (Id) REFERENCES `Widgets` (Id) ON DELETE Cascade ON UPDATE NO ACTION;"); - } - } - } -} +// Copyright © 2013, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using System.Linq; +using NUnit.Framework; +using System.Data; +using System.Data.Entity; +using System.Data.Entity.Infrastructure; + +namespace MySql.Data.EntityFramework.Tests +{ + + public class DeleteTests : DefaultFixture + { + public override void LoadData() + { + using (DefaultContext ctx = new DefaultContext(ConnectionString)) + { + ctx.Products.Add(new Product() { Name = "Garbage Truck", MinAge = 8 }); + ctx.Products.Add(new Product() { Name = "Fire Truck", MinAge = 12 }); + ctx.Products.Add(new Product() { Name = "Hula Hoop", MinAge = 18 }); + ctx.SaveChanges(); + } + } + + [Test] + public void SimpleDeleteAllRows() + { + using (DefaultContext ctx = new DefaultContext(ConnectionString)) + { + Assert.True(ctx.Products.Count() > 0); + + foreach (Product p in ctx.Products) + ctx.Products.Remove(p); + ctx.SaveChanges(); + + Assert.AreEqual(0, ctx.Products.Count()); + } + // set the flag that will cause the setup to happen again + // since we just blew away a table + NeedSetup = true; + } + + [Test] + public void SimpleDeleteRowByParameter() + { + using (DefaultContext ctx = new DefaultContext(ConnectionString)) + { + int total = ctx.Products.Count(); + int cntLeft = ctx.Products.Where(b => b.MinAge >= 18).Count(); + // make sure the test is valid + Assert.True(total > cntLeft); + + foreach (Product p in ctx.Products.Where(b => b.MinAge < 18).ToList()) + ctx.Products.Remove(p); + ctx.SaveChanges(); + Assert.AreEqual(cntLeft, ctx.Products.Count()); + } + // set the flag that will cause the setup to happen again + // since we just blew away a table + NeedSetup = true; + } + + + public class Widget + { + public int Id { get; set; } + public WidgetDetail Detail { get; set; } + } + + public class WidgetDetail + { + public int Id { get; set; } + public Widget Widget { get; set; } + } + + public class WidgetContext : DbContext + { + public WidgetContext(string connStr) : base(connStr) + { + Database.SetInitializer(null); + } + + protected override void OnModelCreating(DbModelBuilder modelBuilder) + { + base.OnModelCreating(modelBuilder); + modelBuilder.Entity() + .HasRequired(b => b.Widget) + .WithOptional(a => a.Detail) + .WillCascadeOnDelete(true); + } + } + + /// + /// Fix for bug Cascading delete using CreateDatabase in Entity Framework + /// (http://bugs.mysql.com/bug.php?id=64779) using ModelFirst. + /// + [Test] + public void XOnDeleteCascade() + { + using (WidgetContext ctx = new WidgetContext(ConnectionString)) + { + var context = ((IObjectContextAdapter)ctx).ObjectContext; + var sql = context.CreateDatabaseScript(); + CheckSqlContains(sql, + @"ALTER TABLE `WidgetDetails` ADD CONSTRAINT WidgetDetail_Widget + FOREIGN KEY (Id) REFERENCES `Widgets` (Id) ON DELETE Cascade ON UPDATE NO ACTION;"); + } + } + } +} diff --git a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/ExpressionTests.cs b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/ExpressionTests.cs index 3e2fdc28b..9759feef3 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/ExpressionTests.cs +++ b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/ExpressionTests.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2015, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/GenericListener.cs b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/GenericListener.cs index 9223458bb..ac9eb770f 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/GenericListener.cs +++ b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/GenericListener.cs @@ -1,87 +1,87 @@ -// Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using System.Text; -using System.Diagnostics; -using System.Collections.Specialized; - -namespace MySql.Data.EntityFramework.Tests -{ - public class GenericListener : TraceListener - { - - StringCollection strings; - StringBuilder partial; - - public GenericListener() - { - strings = new StringCollection(); - partial = new StringBuilder(); - } - - public StringCollection Strings - { - get { return strings; } - } - - public int Find(string sToFind) - { - int count = 0; - foreach (string s in strings) - if (s.IndexOf(sToFind) != -1) - count++; - return count; - } - - public void Clear() - { - partial.Remove(0, partial.Length); - strings.Clear(); - } - - public override void Write(string message) - { - partial.Append(message); - } - - public override void WriteLine(string message) - { - Write(message); - strings.Add(partial.ToString()); - partial.Remove(0, partial.Length); - } - - public int CountLinesContaining(string text) - { - int count = 0; - foreach (string s in strings) - if (s.Contains(text)) count++; - return count; - } - } -} +// Copyright © 2013, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using System.Text; +using System.Diagnostics; +using System.Collections.Specialized; + +namespace MySql.Data.EntityFramework.Tests +{ + public class GenericListener : TraceListener + { + + StringCollection strings; + StringBuilder partial; + + public GenericListener() + { + strings = new StringCollection(); + partial = new StringBuilder(); + } + + public StringCollection Strings + { + get { return strings; } + } + + public int Find(string sToFind) + { + int count = 0; + foreach (string s in strings) + if (s.IndexOf(sToFind) != -1) + count++; + return count; + } + + public void Clear() + { + partial.Remove(0, partial.Length); + strings.Clear(); + } + + public override void Write(string message) + { + partial.Append(message); + } + + public override void WriteLine(string message) + { + Write(message); + strings.Add(partial.ToString()); + partial.Remove(0, partial.Length); + } + + public int CountLinesContaining(string text) + { + int count = 0; + foreach (string s in strings) + if (s.Contains(text)) count++; + return count; + } + } +} diff --git a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/InsertTests.cs b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/InsertTests.cs index 8a447a7ed..e2d7ec7a7 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/InsertTests.cs +++ b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/InsertTests.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2013, 2022, Oracle and/or its affiliates. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -158,4 +158,4 @@ public void SqlModeReplacedByANSI() } } } -} \ No newline at end of file +} diff --git a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/JoinTests.cs b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/JoinTests.cs index f31d10cd1..6528be396 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/JoinTests.cs +++ b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/JoinTests.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2014, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -292,4 +292,4 @@ where b.Pages > 300 // } // } } -} \ No newline at end of file +} diff --git a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/OrderingAndGrouping.cs b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/OrderingAndGrouping.cs index 29f4f791e..4160653a9 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/OrderingAndGrouping.cs +++ b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/OrderingAndGrouping.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -106,4 +106,4 @@ public void OrdersTableDoesNotProvokeSyntaxError() //} } } -} \ No newline at end of file +} diff --git a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/Paging.cs b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/Paging.cs index 70d98a558..ad95562d2 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/Paging.cs +++ b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/Paging.cs @@ -1,104 +1,104 @@ -// Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using System.Data; -using System.Linq; -using NUnit.Framework; - -namespace MySql.Data.EntityFramework.Tests -{ - public class Paging : DefaultFixture - { - public override void SetUp() - { - LoadData(); - } - - void LoadData() - { - using (DefaultContext ctx = new DefaultContext(ConnectionString)) - { - ctx.Products.Add(new Product() { Name = "Garbage Truck", MinAge = 8 }); - ctx.Products.Add(new Product() { Name = "Fire Truck", MinAge = 12 }); - ctx.Products.Add(new Product() { Name = "Hula Hoop", MinAge = 18 }); - ctx.SaveChanges(); - } - } - - [Test] - public void Take() - { - using (DefaultContext ctx = new DefaultContext(ConnectionString)) - { - var q = ctx.Books.Take(2); - var sql = q.ToString(); - CheckSql(sql, - @"SELECT `Id`, `Name`, `PubDate`, `Pages`, `Author_Id` FROM `Books` LIMIT 2"); - } - } - - [Test] - public void Skip() - { - using (DefaultContext ctx = new DefaultContext(ConnectionString)) - { - var q = ctx.Books.OrderBy(b=>b.Pages).Skip(3); - var sql = q.ToString(); - CheckSql(sql, - @"SELECT `Extent1`.`Id`, `Extent1`.`Name`, `Extent1`.`PubDate`, `Extent1`.`Pages`, `Extent1`.`Author_Id` - FROM `Books` AS `Extent1` ORDER BY `Extent1`.`Pages` ASC LIMIT 3,18446744073709551615"); - } - } - - [Test] - public void SkipAndTakeSimple() - { - using (DefaultContext ctx = new DefaultContext(ConnectionString)) - { - var q = ctx.Books.OrderBy(b => b.Pages).Skip(3).Take(4); - var sql = q.ToString(); - CheckSql(sql, - @"SELECT `Extent1`.`Id`, `Extent1`.`Name`, `Extent1`.`PubDate`, `Extent1`.`Pages`, `Extent1`.`Author_Id` - FROM `Books` AS `Extent1` ORDER BY `Extent1`.`Pages` ASC LIMIT 3,4"); - } - } - - // - // Tests fix for bug #64749 - Entity Framework - Take().Count() fails with EntityCommandCompilationException. - // - [Test] - public void TakeWithCount() - { - using (DefaultContext ctx = new DefaultContext(ConnectionString)) - { - int cnt = ctx.Products.Take(2).Count(); - Assert.AreEqual(2, cnt); - } - } - } -} \ No newline at end of file +// Copyright © 2014, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using System.Data; +using System.Linq; +using NUnit.Framework; + +namespace MySql.Data.EntityFramework.Tests +{ + public class Paging : DefaultFixture + { + public override void SetUp() + { + LoadData(); + } + + void LoadData() + { + using (DefaultContext ctx = new DefaultContext(ConnectionString)) + { + ctx.Products.Add(new Product() { Name = "Garbage Truck", MinAge = 8 }); + ctx.Products.Add(new Product() { Name = "Fire Truck", MinAge = 12 }); + ctx.Products.Add(new Product() { Name = "Hula Hoop", MinAge = 18 }); + ctx.SaveChanges(); + } + } + + [Test] + public void Take() + { + using (DefaultContext ctx = new DefaultContext(ConnectionString)) + { + var q = ctx.Books.Take(2); + var sql = q.ToString(); + CheckSql(sql, + @"SELECT `Id`, `Name`, `PubDate`, `Pages`, `Author_Id` FROM `Books` LIMIT 2"); + } + } + + [Test] + public void Skip() + { + using (DefaultContext ctx = new DefaultContext(ConnectionString)) + { + var q = ctx.Books.OrderBy(b=>b.Pages).Skip(3); + var sql = q.ToString(); + CheckSql(sql, + @"SELECT `Extent1`.`Id`, `Extent1`.`Name`, `Extent1`.`PubDate`, `Extent1`.`Pages`, `Extent1`.`Author_Id` + FROM `Books` AS `Extent1` ORDER BY `Extent1`.`Pages` ASC LIMIT 3,18446744073709551615"); + } + } + + [Test] + public void SkipAndTakeSimple() + { + using (DefaultContext ctx = new DefaultContext(ConnectionString)) + { + var q = ctx.Books.OrderBy(b => b.Pages).Skip(3).Take(4); + var sql = q.ToString(); + CheckSql(sql, + @"SELECT `Extent1`.`Id`, `Extent1`.`Name`, `Extent1`.`PubDate`, `Extent1`.`Pages`, `Extent1`.`Author_Id` + FROM `Books` AS `Extent1` ORDER BY `Extent1`.`Pages` ASC LIMIT 3,4"); + } + } + + // + // Tests fix for bug #64749 - Entity Framework - Take().Count() fails with EntityCommandCompilationException. + // + [Test] + public void TakeWithCount() + { + using (DefaultContext ctx = new DefaultContext(ConnectionString)) + { + int cnt = ctx.Products.Take(2).Count(); + Assert.AreEqual(2, cnt); + } + } + } +} diff --git a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/ProceduresAndFunctions.cs b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/ProceduresAndFunctions.cs index 1c8006bb1..0d436d480 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/ProceduresAndFunctions.cs +++ b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/ProceduresAndFunctions.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2013, 2023, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -94,4 +94,4 @@ public void CommandTimeout() } } } -} \ No newline at end of file +} diff --git a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/Properties/AssemblyInfo.cs b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/Properties/AssemblyInfo.cs index 270be36bb..95de9a1c9 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/Properties/AssemblyInfo.cs +++ b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/Properties/AssemblyInfo.cs @@ -1,55 +1,55 @@ -// Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using System.Reflection; -using System.Runtime.InteropServices; -using NUnit.Framework; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("MySql.Data.EntityFramework.Tests")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("Oracle")] -[assembly: AssemblyProduct("MySql.Data.EntityFramework.Tests")] -[assembly: AssemblyCopyright("Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved.")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("a4c0a8f2-5e48-4227-a712-bf8ae7446101")] - -//[assembly: InternalsVisibleTo("MySql.Data.EntityFramework.CodeFirTests, PublicKey = 0024000004800000940000000602000000240000525341310004000001000100d973bda91f71752c78294126974a41a08643168271f65fc0fb3cd45f658da01fbca75ac74067d18e7afbf1467d7a519ce0248b13719717281bb4ddd4ecd71a580dfe0912dfc3690b1d24c7e1975bf7eed90e4ab14e10501eedf763bff8ac204f955c9c15c2cf4ebf6563d8320b6ea8d1ea3807623141f4b81ae30a6c886b3ee1")] - -[assembly: NonParallelizable] \ No newline at end of file +// Copyright © 2008, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using System.Reflection; +using System.Runtime.InteropServices; +using NUnit.Framework; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("MySql.Data.EntityFramework.Tests")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Oracle")] +[assembly: AssemblyProduct("MySql.Data.EntityFramework.Tests")] +[assembly: AssemblyCopyright("Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved.")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("a4c0a8f2-5e48-4227-a712-bf8ae7446101")] + +//[assembly: InternalsVisibleTo("MySql.Data.EntityFramework.CodeFirTests, PublicKey = 0024000004800000940000000602000000240000525341310004000001000100d973bda91f71752c78294126974a41a08643168271f65fc0fb3cd45f658da01fbca75ac74067d18e7afbf1467d7a519ce0248b13719717281bb4ddd4ecd71a580dfe0912dfc3690b1d24c7e1975bf7eed90e4ab14e10501eedf763bff8ac204f955c9c15c2cf4ebf6563d8320b6ea8d1ea3807623141f4b81ae30a6c886b3ee1")] + +[assembly: NonParallelizable] diff --git a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/ProviderManifestTests.cs b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/ProviderManifestTests.cs index e99d76b52..e24e37635 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/ProviderManifestTests.cs +++ b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/ProviderManifestTests.cs @@ -1,103 +1,103 @@ -// Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using System; -using MySql.Data.MySqlClient; -using System.Data.Entity.Core.Metadata.Edm; -using NUnit.Framework; - -namespace MySql.Data.EntityFramework.Tests -{ - public class ProviderManifestTests : DefaultFixture - { - [Test] - public void TestingMaxLengthFacet() - { - using (MySqlConnection connection = new MySqlConnection(ConnectionString)) - { - MySqlProviderManifest pm = new MySqlProviderManifest(Version.ToString()); - TypeUsage tu = TypeUsage.CreateStringTypeUsage( - PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.String), false, false); - TypeUsage result = pm.GetStoreType(tu); - Assert.AreEqual("longtext", result.EdmType.Name); - - tu = TypeUsage.CreateStringTypeUsage( - PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.String), false, false, Int32.MaxValue); - result = pm.GetStoreType(tu); - Assert.AreEqual("longtext", result.EdmType.Name); - - tu = TypeUsage.CreateStringTypeUsage( - PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.String), false, false, 70000); - result = pm.GetStoreType(tu); - Assert.AreEqual("mediumtext", result.EdmType.Name); - - } - } - - /// - /// Bug #62135 Connector/NET Incorrectly Maps PrimitiveTypeKind.Byte to "tinyint" - /// - /// + /// Bug #62135 Connector/NET Incorrectly Maps PrimitiveTypeKind.Byte to "tinyint" + /// + /// ( - "SELECT VALUE b FROM Books AS b WHERE b.Pages > @pages", - @"SELECT `Extent1`.`Id`, `Extent1`.`Name`, `Extent1`.`PubDate`, `Extent1`.`Pages`, - `Extent1`.`Author_Id` FROM `Books` AS `Extent1` WHERE `Extent1`.`Pages` > @pages", - new ObjectParameter("pages", 200)); - } - - [Test] - public void WhereLiteralOnRelation() - { - TestESql( - "SELECT VALUE a FROM Authors AS a WHERE a.Address.City = 'Dallas'", - @"SELECT `Extent1`.`Id`, `Extent1`.`Name`, `Extent1`.`Age`, `Extent1`.`Address_City`, - `Extent1`.`Address_Street`, `Extent1`.`Address_State`, `Extent1`.`Address_ZipCode` - FROM `Authors` AS `Extent1` WHERE `Extent1`.`Address_City` = @gp1"); - } - - [Test] - public void WhereWithRelatedEntities1() - { - TestESql( - "SELECT VALUE b FROM Books AS b WHERE b.Author.Address.State = 'TX'", - @"SELECT `Extent1`.`Id`, `Extent1`.`Name`, `Extent1`.`PubDate`, `Extent1`.`Pages`, - `Extent1`.`Author_Id` FROM `Books` AS `Extent1` INNER JOIN `Authors` AS `Extent2` - ON `Extent1`.`Author_Id` = `Extent2`.`Id` WHERE `Extent2`.`Address_State` = @gp1"); - } - - [Test] - public void Exists() - { - TestESql( - @"SELECT VALUE a FROM Authors AS a WHERE EXISTS( - SELECT b FROM a.Books AS b WHERE b.Pages > 200)", - @"SELECT `Extent1`.`Id`, `Extent1`.`Name`, `Extent1`.`Age`, `Extent1`.`Address_City`, - `Extent1`.`Address_Street`, `Extent1`.`Address_State`, `Extent1`.`Address_ZipCode` - FROM `Authors` AS `Extent1` WHERE EXISTS(SELECT 1 AS `C1` FROM `Books` AS `Extent2` - WHERE (`Extent1`.`Id` = `Extent2`.`Author_Id`) AND (`Extent2`.`Pages` > 200))"); - } - } -} \ No newline at end of file +// Copyright © 2013, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using System.Data.Entity.Core.Objects; +using NUnit.Framework; + +namespace MySql.Data.EntityFramework.Tests +{ + public class RestrictionOperators : DefaultFixture + { + [Test] + public void SimpleSelectWithParam() + { + TestESql( + "SELECT VALUE b FROM Books AS b WHERE b.Pages > @pages", + @"SELECT `Extent1`.`Id`, `Extent1`.`Name`, `Extent1`.`PubDate`, `Extent1`.`Pages`, + `Extent1`.`Author_Id` FROM `Books` AS `Extent1` WHERE `Extent1`.`Pages` > @pages", + new ObjectParameter("pages", 200)); + } + + [Test] + public void WhereLiteralOnRelation() + { + TestESql( + "SELECT VALUE a FROM Authors AS a WHERE a.Address.City = 'Dallas'", + @"SELECT `Extent1`.`Id`, `Extent1`.`Name`, `Extent1`.`Age`, `Extent1`.`Address_City`, + `Extent1`.`Address_Street`, `Extent1`.`Address_State`, `Extent1`.`Address_ZipCode` + FROM `Authors` AS `Extent1` WHERE `Extent1`.`Address_City` = @gp1"); + } + + [Test] + public void WhereWithRelatedEntities1() + { + TestESql( + "SELECT VALUE b FROM Books AS b WHERE b.Author.Address.State = 'TX'", + @"SELECT `Extent1`.`Id`, `Extent1`.`Name`, `Extent1`.`PubDate`, `Extent1`.`Pages`, + `Extent1`.`Author_Id` FROM `Books` AS `Extent1` INNER JOIN `Authors` AS `Extent2` + ON `Extent1`.`Author_Id` = `Extent2`.`Id` WHERE `Extent2`.`Address_State` = @gp1"); + } + + [Test] + public void Exists() + { + TestESql( + @"SELECT VALUE a FROM Authors AS a WHERE EXISTS( + SELECT b FROM a.Books AS b WHERE b.Pages > 200)", + @"SELECT `Extent1`.`Id`, `Extent1`.`Name`, `Extent1`.`Age`, `Extent1`.`Address_City`, + `Extent1`.`Address_Street`, `Extent1`.`Address_State`, `Extent1`.`Address_ZipCode` + FROM `Authors` AS `Extent1` WHERE EXISTS(SELECT 1 AS `C1` FROM `Books` AS `Extent2` + WHERE (`Extent1`.`Id` = `Extent2`.`Author_Id`) AND (`Extent2`.`Pages` > 200))"); + } + } +} diff --git a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/SchemaInformation.cs b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/SchemaInformation.cs index 6d5b4dbab..6bf9c7fc6 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/SchemaInformation.cs +++ b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/SchemaInformation.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2014, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/SetOperators.cs b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/SetOperators.cs index 2826cb2dc..2c6c37e86 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/SetOperators.cs +++ b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/SetOperators.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2013, 2020 Oracle and/or its affiliates. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -98,4 +98,4 @@ where p.MinAge > 8 } } } -} \ No newline at end of file +} diff --git a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/SimpleQuery.cs b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/SimpleQuery.cs index ee3e2c31e..28c1730e3 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/SimpleQuery.cs +++ b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/SimpleQuery.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2014, 2021, Oracle and/or its affiliates. +// Copyright © 2014, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -88,4 +88,4 @@ public void TablesWithSchemaWithoutUsingProperty() } } } -} \ No newline at end of file +} diff --git a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/UpdateTests.cs b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/UpdateTests.cs index df74ec178..e47461739 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/UpdateTests.cs +++ b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/UpdateTests.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -71,4 +71,4 @@ public void UpdateSimple() } } } -} \ No newline at end of file +} diff --git a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/Wizard.cs b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/Wizard.cs index 2d77db265..fc4350fde 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/Wizard.cs +++ b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/Wizard.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2014, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -68,4 +68,4 @@ public void GetStoreSchemaDescriptionDoesNotThrowForServer50OrGreater() } } } -} \ No newline at end of file +} diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/Blogs.cs b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/Blogs.cs index 6cfb76543..fb191bfd1 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/Blogs.cs +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/Blogs.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2020 Oracle and/or its affiliates. +// Copyright © 2020, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/CodeFirstFixture.cs b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/CodeFirstFixture.cs index 6702b1fa9..4689889e1 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/CodeFirstFixture.cs +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/CodeFirstFixture.cs @@ -1,23 +1,29 @@ -// Copyright (c) 2013, 2021, Oracle and/or its affiliates. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // -// MySQL Connector/NET is licensed under the terms of the GPLv2 -// , like most -// MySQL Connectors. There are special exceptions to the terms and -// conditions of the GPLv2 as it is applied to this software, see the -// FLOSS License Exception -// . +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. // -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published -// by the Free Software Foundation; version 2 of the License. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -// for more details. +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. // -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA using MySql.Data.MySqlClient; diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/CodeFirstTests.cs b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/CodeFirstTests.cs index 96089b3f0..fb04f751c 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/CodeFirstTests.cs +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/CodeFirstTests.cs @@ -1,2254 +1,2254 @@ -// Copyright (c) 2014, 2023, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySql.Data.EntityFramework.Tests; -using MySql.Data.MySqlClient; -using MySql.EntityFramework.CodeFirst.Tests; -using MySql.EntityFramework.CodeFirst.Tests.Properties; -using NUnit.Framework; -using System; -using System.Collections.Generic; -using System.Data; -using System.Data.Entity; -using System.Data.Entity.Infrastructure; -using System.Data.Entity.Spatial; -using System.Diagnostics; -using System.Linq; -using System.Text.RegularExpressions; -using System.Threading; - -namespace MySql.Data.EntityFramework.CodeFirst.Tests -{ - public class CodeFirstTests : CodeFirstFixture - { - /// - /// Tests for fix of http://bugs.mysql.com/bug.php?id=61230 - /// ("The provider did not return a ProviderManifestToken string."). - /// - [Test] - public void SimpleCodeFirstSelect() - { -#if DEBUG - Debug.WriteLine(new StackTrace().GetFrame(0).GetMethod().Name); -#endif - MovieDBContext db = new MovieDBContext(); - db.Database.Initialize(true); - MovieDBInitialize.DoDataPopulation(db); - var l = db.Movies.ToList(); - int j = l.Count; - foreach (var i in l) - { - j--; - } - Assert.AreEqual(0, j); - } - - /// - /// Tests for fix of http://bugs.mysql.com/bug.php?id=62150 - /// ("EF4.1, Code First, CreateDatabaseScript() generates an invalid MySQL script."). - /// - [Test] - public void AlterTableTest() - { -#if DEBUG - Debug.WriteLine(new StackTrace().GetFrame(0).GetMethod().Name); -#endif - MovieDBContext db = new MovieDBContext(); - db.Database.Initialize(true); - MovieDBInitialize.DoDataPopulation(db); - var l = db.MovieFormats.ToList(); - int j = l.Count; - foreach (var i in l) - { - j--; - } - Assert.AreEqual(0, j); - MovieFormat m = new MovieFormat(); - m.Format = 8.0f; - db.MovieFormats.Add(m); - db.SaveChanges(); - MovieFormat m2 = db.MovieFormats.Where(p => p.Format == 8.0f).FirstOrDefault(); - Assert.NotNull(m2); - Assert.AreEqual(8.0f, m2.Format); - } - - /// - /// Fix for "Connector/Net Generates Incorrect SELECT Clause after UPDATE" (MySql bug #62134, Oracle bug #13491689). - /// - [Test] - public void ConcurrencyCheckWithNonDbGeneratedColumn() - { -#if DEBUG - Debug.WriteLine(new StackTrace().GetFrame(0).GetMethod().Name); -#endif - using (MovieDBContext db = new MovieDBContext()) - { - db.Database.Delete(); - db.Database.CreateIfNotExists(); - MovieDBInitialize.DoDataPopulation(db); - db.Database.ExecuteSqlCommand(@"DROP TABLE IF EXISTS `MovieReleases`"); - - db.Database.ExecuteSqlCommand( -@"CREATE TABLE IF NOT EXISTS `MovieReleases` ( - `Id` int(11) NOT NULL, - `Name` varbinary(45) NOT NULL, - `Timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - PRIMARY KEY (`Id`) -) ENGINE=InnoDB DEFAULT CHARSET=binary"); - MySqlTrace.Listeners.Clear(); - MySqlTrace.Switch.Level = SourceLevels.All; - GenericListener listener = new GenericListener(); - MySqlTrace.Listeners.Add(listener); - try - { - MovieRelease mr = db.MovieReleases.Create(); - mr.Id = 1; - mr.Name = "Commercial"; - db.MovieReleases.Add(mr); - db.SaveChanges(); - mr.Name = "Director's Cut"; - db.SaveChanges(); - } - finally - { - db.Database.ExecuteSqlCommand(@"DROP TABLE IF EXISTS `MovieReleases`"); - } - // Check sql - Regex rx = new Regex(@"Query Opened: (?UPDATE .*)", RegexOptions.Compiled | RegexOptions.Singleline); - foreach (string s in listener.Strings) - { - Match m = rx.Match(s); - if (m.Success) - { - CheckSql(m.Groups["item"].Value, SQLSyntax.UpdateWithSelectWithNonDbGeneratedLock); - //Assert.Pass(); - } - } - //Assert.Fail(); - } - } - - /// - /// This tests fix for http://bugs.mysql.com/bug.php?id=64216. - /// - [Test] - public void CheckByteArray() - { -#if DEBUG - Debug.WriteLine(new StackTrace().GetFrame(0).GetMethod().Name); -#endif - MovieDBContext db = new MovieDBContext(); - db.Database.Initialize(true); - string dbCreationScript = - ((IObjectContextAdapter)db).ObjectContext.CreateDatabaseScript(); - Regex rx = new Regex(@"`Data` (?[^\),]*)", RegexOptions.Compiled | RegexOptions.Singleline); - Match m = rx.Match(dbCreationScript); - Assert.AreEqual("longblob", m.Groups["type"].Value); - } - - /// - /// Validates a stored procedure call using Code First - /// Bug #14008699 - [Test] - public void CallStoredProcedure() - { -#if DEBUG - Debug.WriteLine(new StackTrace().GetFrame(0).GetMethod().Name); -#endif - using (MovieDBContext context = new MovieDBContext()) - { - context.Database.Initialize(true); - context.Database.ExecuteSqlCommand(@"drop procedure if exists `GetCount`"); - context.Database.ExecuteSqlCommand(@"create procedure `GetCount`() begin select 5; end;"); - long count = context.Database.SqlQuery("call GetCount").First(); - - Assert.AreEqual(5, count); - } - } - - /// - /// Tests for fix of http://bugs.mysql.com/bug.php?id=63920 - /// Maxlength error when it's used code-first and inheritance (discriminator generated column) - /// - [Test] - public void Bug63920_Test1() - { -#if DEBUG - Debug.WriteLine(new StackTrace().GetFrame(0).GetMethod().Name); -#endif - using (VehicleDbContext context = new VehicleDbContext()) - { - context.Database.Delete(); - context.Database.Initialize(true); - - context.Vehicles.Add(new Car { Id = 1, Name = "Mustang", Year = 2012, CarProperty = "Car" }); - context.Vehicles.Add(new Bike { Id = 101, Name = "Mountain", Year = 2011, BikeProperty = "Bike" }); - context.SaveChanges(); - - var list = context.Vehicles.ToList(); - - int records = -1; - using (MySqlConnection conn = new MySqlConnection(context.Database.Connection.ConnectionString)) - { - conn.Open(); - MySqlCommand cmd = new MySqlCommand("SELECT COUNT(*) FROM Vehicles", conn); - records = Convert.ToInt32(cmd.ExecuteScalar()); - } - - Assert.AreEqual(context.Vehicles.Count(), records); - } - } - - /// - /// Tests for fix of http://bugs.mysql.com/bug.php?id=63920 - /// Key reference generation script error when it's used code-first and a single table for the inherited models - /// - [Test] - public void Bug63920_Test2() - { -#if DEBUG - Debug.WriteLine(new StackTrace().GetFrame(0).GetMethod().Name); -#endif - using (VehicleDbContext2 context = new VehicleDbContext2()) - { - context.Database.Delete(); - context.Database.Initialize(true); - - context.Vehicles.Add(new Car2 { Id = 1, Name = "Mustang", Year = 2012, CarProperty = "Car" }); - context.Vehicles.Add(new Bike2 { Id = 101, Name = "Mountain", Year = 2011, BikeProperty = "Bike" }); - context.SaveChanges(); - - var list = context.Vehicles.ToList(); - - int records = -1; - using (MySqlConnection conn = new MySqlConnection(context.Database.Connection.ConnectionString)) - { - conn.Open(); - MySqlCommand cmd = new MySqlCommand("SELECT COUNT(*) FROM Vehicle2", conn); - records = Convert.ToInt32(cmd.ExecuteScalar()); - } - - Assert.AreEqual(context.Vehicles.Count(), records); - } - } - - /// - /// This test fix for precision customization for columns bug (http://bugs.mysql.com/bug.php?id=65001), - /// Trying to customize column precision in Code First does not work). - /// - [Test] - [Ignore("Fix this")] - public void TestPrecisionNscale() - { -#if DEBUG - Debug.WriteLine(new StackTrace().GetFrame(0).GetMethod().Name); -#endif - MovieDBContext db = new MovieDBContext(); - db.Database.Initialize(true); - var l = db.Movies.ToList(); - using (MySqlDataReader r = new MySqlCommand($@"select numeric_precision, numeric_scale from information_schema.columns -where table_schema = '{Connection.Database}' and table_name = 'movies' and column_name = 'Price'", Connection).ExecuteReader()) - { - r.Read(); - Assert.AreEqual(16, r.GetInt32(0)); - Assert.AreEqual(2, r.GetInt32(1)); - } - } - - /// - /// Test String types to StoreType for String - /// A string with FixedLength=true will become a char - /// Max Length left empty will be char(max) - /// Max Length(100) will be char(100) - /// while FixedLength=false will result in nvarchar. - /// Max Length left empty will be nvarchar(max) - /// Max Length(100) will be nvarchar(100) - /// - [Test] - public void TestStringTypeToStoreType() - { -#if DEBUG - Debug.WriteLine(new StackTrace().GetFrame(0).GetMethod().Name); -#endif - using (VehicleDbContext3 context = new VehicleDbContext3()) - { - if (context.Database.Exists()) context.Database.Delete(); - context.Database.CreateIfNotExists(); - context.Accessories.Add(new Accessory { Name = "Accesory One", Description = "Accesories descriptions", LongDescription = "Some long description" }); - context.SaveChanges(); - - using (MySqlConnection conn = new MySqlConnection(context.Database.Connection.ConnectionString)) - { - conn.Open(); - MySqlCommand query = new MySqlCommand("Select Column_name, Is_Nullable, Data_Type from information_schema.Columns where table_schema ='" + conn.Database + "' and table_name = 'Accessories' and column_name ='Description'", conn); - query.Connection = conn; - MySqlDataReader reader = query.ExecuteReader(); - while (reader.Read()) - { - Assert.AreEqual("Description", reader[0].ToString()); - Assert.AreEqual("NO", reader[1].ToString()); - Assert.AreEqual("mediumtext", reader[2].ToString()); - } - reader.Close(); - - query = new MySqlCommand("Select Column_name, Is_Nullable, Data_Type, character_maximum_length from information_schema.Columns where table_schema ='" + conn.Database + "' and table_name = 'Accessories' and column_name ='Name'", conn); - reader = query.ExecuteReader(); - while (reader.Read()) - { - Assert.AreEqual("Name", reader[0].ToString()); - Assert.AreEqual("NO", reader[1].ToString()); - Assert.AreEqual("varchar", reader[2].ToString()); - Assert.AreEqual("255", reader[3].ToString()); - } - reader.Close(); - - query = new MySqlCommand("Select Column_name, Is_Nullable, Data_Type, character_maximum_length from information_schema.Columns where table_schema ='" + conn.Database + "' and table_name = 'Accessories' and column_name ='LongDescription'", conn); - reader = query.ExecuteReader(); - while (reader.Read()) - { - Assert.AreEqual("LongDescription", reader[0].ToString()); - Assert.AreEqual("NO", reader[1].ToString()); - Assert.AreEqual("longtext", reader[2].ToString()); - Assert.AreEqual("4294967295", reader[3].ToString()); - } - } - } - } - - /// - /// Test fix for http://bugs.mysql.com/bug.php?id=66066 / http://clustra.no.oracle.com/orabugs/bug.php?id=14479715 - /// (Using EF, crash when generating insert with no values.). - /// - [Test] - public void AddingEmptyRow() - { -#if DEBUG - Debug.WriteLine(new StackTrace().GetFrame(0).GetMethod().Name); -#endif - using (MovieDBContext ctx = new MovieDBContext()) - { - ctx.Database.Initialize(true); - ctx.EntitySingleColumns.Add(new EntitySingleColumn()); - ctx.SaveChanges(); - } - - using (MovieDBContext ctx2 = new MovieDBContext()) - { - var q = from esc in ctx2.EntitySingleColumns where esc.Id == 1 select esc; - Assert.AreEqual(1, q.Count()); - } - } - - /// - /// Test for identity columns when type is Integer or Guid (auto-generate - /// values) - /// - [Test] - public void IdentityTest() - { -#if DEBUG - Debug.WriteLine(new StackTrace().GetFrame(0).GetMethod().Name); -#endif - using (VehicleDbContext context = new VehicleDbContext()) - { - context.Database.ExecuteSqlCommand("SET GLOBAL sql_mode='STRICT_ALL_TABLES'"); - if (context.Database.Exists()) context.Database.Delete(); - context.Database.CreateIfNotExists(); - - // Identity as Guid - Manufacturer nissan = new Manufacturer - { - Name = "Nissan" - }; - Manufacturer ford = new Manufacturer - { - Name = "Ford" - }; - context.Manufacturers.Add(nissan); - context.Manufacturers.Add(ford); - - // Identity as Integer - Distributor dis1 = new Distributor - { - Name = "Distributor1" - }; - Distributor dis2 = new Distributor - { - Name = "Distributor2" - }; - context.Distributors.Add(dis1); - context.Distributors.Add(dis2); - - context.SaveChanges(); - - using (MySqlConnection conn = new MySqlConnection(context.Database.Connection.ConnectionString)) - { - conn.Open(); - - // Validates Guid - MySqlCommand cmd = new MySqlCommand("SELECT * FROM Manufacturers", conn); - MySqlDataReader dr = cmd.ExecuteReader(); - Assert.False(!dr.HasRows, "No records found"); - - while (dr.Read()) - { - string name = dr.GetString(1); - switch (name) - { - case "Nissan": - Assert.AreEqual(dr.GetGuid(0), nissan.ManufacturerId); - Assert.AreEqual(dr.GetGuid(2), nissan.GroupIdentifier); - break; - case "Ford": - Assert.AreEqual(dr.GetGuid(0), ford.ManufacturerId); - Assert.AreEqual(dr.GetGuid(2), ford.GroupIdentifier); - break; - default: - //Assert.Fail(); - break; - } - } - dr.Close(); - - // Validates Integer - cmd = new MySqlCommand("SELECT * FROM Distributors", conn); - dr = cmd.ExecuteReader(); - if (!dr.HasRows) - //Assert.Fail("No records found"); - while (dr.Read()) - { - string name = dr.GetString(1); - switch (name) - { - case "Distributor1": - Assert.AreEqual(dr.GetInt32(0), dis1.DistributorId); - break; - case "Distributor2": - Assert.AreEqual(dr.GetInt32(0), dis2.DistributorId); - break; - default: - //Assert.Fail(); - break; - } - } - dr.Close(); - } - } - } - - /// - /// This test the fix for bug 67377. - /// - [Test] - public void FirstOrDefaultNested() - { -#if DEBUG - Debug.WriteLine(new StackTrace().GetFrame(0).GetMethod().Name); -#endif - using (MovieDBContext ctx = new MovieDBContext()) - { - ctx.Database.Initialize(true); - MovieDBInitialize.DoDataPopulation(ctx); - int DirectorId = 1; - var q = ctx.Movies.Where(p => p.Director.ID == DirectorId).Select(p => - new - { - Id = p.ID, - FirstMovieFormat = p.Formats.Count == 0 ? 0.0 : p.Formats.FirstOrDefault().Format - }); - string sql = q.ToString(); -#if DEBUG - Debug.WriteLine(sql); -#endif - int j = q.Count(); - foreach (var r in q) - { - j--; - } - Assert.AreEqual(0, j); - } - } - - /// - /// This tests the fix for bug 73549, Generated Sql does not contain ORDER BY statement whose is requested by LINQ. - /// - [Test] - public void FirstOrDefaultNestedWithOrderBy() - { -#if DEBUG - Debug.WriteLine(new StackTrace().GetFrame(0).GetMethod().Name); -#endif - using (SakilaDb db = new SakilaDb()) - { - var q = from cu in db.customers - let curAddr = db.addresses.OrderByDescending(p => p.address_id).Where(p => p.address_id == cu.address_id).FirstOrDefault() - join sto in db.stores on cu.store_id equals sto.store_id - orderby cu.customer_id descending - select new - { - curAddr.city.country.country1 - }; - string sql = q.ToString(); - CheckSql(sql, SQLSyntax.FirstOrDefaultNestedWithOrderBy); -#if DEBUG - Debug.WriteLine(sql); -#endif - int j = q.Count(); - foreach (var r in q) - { - //Debug.WriteLine( r.country1 ); - } - Assert.AreEqual(599, j); - } - } - - /// - /// SUPPORT FOR DATE TYPES WITH PRECISION - /// - [Test] - public void CanDefineDatesWithPrecisionFor56() - { -#if DEBUG - Debug.WriteLine(new StackTrace().GetFrame(0).GetMethod().Name); -#endif - - if (Version < new Version(5, 6)) return; - - using (var db = new ProductsDbContext()) - { - db.Database.Initialize(true); - using (MySqlConnection conn = new MySqlConnection(db.Database.Connection.ConnectionString)) - { - conn.Open(); - MySqlCommand query = new MySqlCommand("Select Column_name, Is_Nullable, Data_Type, DateTime_Precision from information_schema.Columns where table_schema ='" + conn.Database + "' and table_name = 'Products' and column_name ='DateTimeWithPrecision'", conn); - query.Connection = conn; - MySqlDataReader reader = query.ExecuteReader(); - while (reader.Read()) - { - Assert.AreEqual("DateTimeWithPrecision", reader[0].ToString()); - Assert.AreEqual("NO", reader[1].ToString()); - Assert.AreEqual("datetime", reader[2].ToString()); - Assert.AreEqual("3", reader[3].ToString()); - } - reader.Close(); - - query = new MySqlCommand("Select Column_name, Is_Nullable, Data_Type, DateTime_Precision from information_schema.Columns where table_schema ='" + conn.Database + "' and table_name = 'Products' and column_name ='TimeStampWithPrecision'", conn); - query.Connection = conn; - reader = query.ExecuteReader(); - while (reader.Read()) - { - Assert.AreEqual("TimeStampWithPrecision", reader[0].ToString()); - Assert.AreEqual("NO", reader[1].ToString()); - Assert.AreEqual("timestamp", reader[2].ToString()); - Assert.AreEqual("3", reader[3].ToString()); - } - reader.Close(); - } - db.Database.Delete(); - } - } - - /// - /// Orabug #15935094 SUPPORT FOR CURRENT_TIMESTAMP AS DEFAULT FOR DATETIME WITH EF - /// - [Test] - [Ignore("Fix this")] - public void CanDefineDateTimeAndTimestampWithIdentity() - { -#if DEBUG - Debug.WriteLine(new StackTrace().GetFrame(0).GetMethod().Name); -#endif - if (Version < new Version(5, 6)) return; - - using (var db = new ProductsDbContext()) - { - db.Database.Initialize(true); - MySqlConnection con = (MySqlConnection)db.Database.Connection; - MySqlCommand cmd = new MySqlCommand("set session sql_mode = '';", con); - con.Open(); - cmd.ExecuteNonQuery(); - con.Close(); - - Product product = new Product - { - //Omitting Identity Columns - DateTimeWithPrecision = DateTime.Now, - TimeStampWithPrecision = DateTime.Now - }; - - db.Products.Add(product); - db.SaveChanges(); - - var updateProduct = db.Products.First(); - updateProduct.DateTimeWithPrecision = new DateTime(2012, 3, 18, 23, 9, 7, 6); - db.SaveChanges(); - - Assert.NotNull(db.Products.First().Timestamp); - Assert.NotNull(db.Products.First().DateCreated); - Assert.AreEqual(new DateTime(2012, 3, 18, 23, 9, 7, 6), db.Products.First().DateTimeWithPrecision); - Assert.AreEqual(1, db.Products.Count()); - db.Database.Delete(); - } - } - - - /// - /// Test of fix for bug Support for EntityFramework 4.3 Code First Generated Identifiers (MySql Bug #67285, Oracle bug #16286397). - /// FKs are renamed to met http://dev.mysql.com/doc/refman/5.0/en/identifiers.html limitations. - /// - [Test] - public void LongIdentifiersInheritanceTPT() - { -#if DEBUG - Debug.WriteLine(new StackTrace().GetFrame(0).GetMethod().Name); -#endif - using (DinosauriaDBContext db = new DinosauriaDBContext()) - { - db.Database.Initialize(true); - Tyrannosauridae ty = new Tyrannosauridae() { Id = 1, Name = "Genghis Rex", SpecieName = "TRex", Weight = 1000 }; - db.dinos.Add(ty); - Oviraptorosauria ovi = new Oviraptorosauria() { Id = 2, EggsPerYear = 100, Name = "John the Velociraptor", SpecieName = "Oviraptor" }; - db.dinos.Add(ovi); - db.SaveChanges(); - } - } - - - /// - /// Test fix for http://bugs.mysql.com/bug.php?id=67183 - /// (Malformed Query while eager loading with EF 4 due to multiple projections). - /// - [Test] - public void ShipTest() - { -#if DEBUG - Debug.WriteLine(new StackTrace().GetFrame(0).GetMethod().Name); -#endif - using (var context = new ShipContext()) - { - context.Database.Initialize(true); - - var harbor = new Harbor - { - Ships = new HashSet - { - new Ship - { - CrewMembers = new HashSet - { - new CrewMember - { - Rank = new Rank { Description = "Rank A" }, - Clearance = new Clearance { Description = "Clearance A" }, - Description = "CrewMember A" - }, - new CrewMember - { - Rank = new Rank { Description = "Rank B" }, - Clearance = new Clearance { Description = "Clearance B" }, - Description = "CrewMember B" - } - }, - Description = "Ship AB" - }, - new Ship - { - CrewMembers = new HashSet - { - new CrewMember - { - Rank = new Rank { Description = "Rank C" }, - Clearance = new Clearance { Description = "Clearance C" }, - Description = "CrewMember C" - }, - new CrewMember - { - Rank = new Rank { Description = "Rank D" }, - Clearance = new Clearance { Description = "Clearance D" }, - Description = "CrewMember D" - } - }, - Description = "Ship CD" - } - }, - Description = "Harbor ABCD" - }; - - context.Harbors.Add(harbor); - context.SaveChanges(); - } - - using (var context = new ShipContext()) - { - DbSet dbSet = context.Set(); - IQueryable query = dbSet; - query = query.Include(entity => entity.Ships); - query = query.Include(entity => entity.Ships.Select(s => s.CrewMembers)); - query = query.Include(entity => entity.Ships.Select(s => s.CrewMembers.Select(cm => cm.Rank))); - query = query.Include(entity => entity.Ships.Select(s => s.CrewMembers.Select(cm => cm.Clearance))); - - string[] data = new string[] { - "1,Harbor ABCD,1,1,1,Ship AB,1,1,1,1,1,CrewMember A,1,Rank A,1,Clearance A", - "1,Harbor ABCD,1,1,1,Ship AB,1,2,1,2,2,CrewMember B,2,Rank B,2,Clearance B", - "1,Harbor ABCD,1,2,1,Ship CD,1,3,2,3,3,CrewMember C,3,Rank C,3,Clearance C", - "1,Harbor ABCD,1,2,1,Ship CD,1,4,2,4,4,CrewMember D,4,Rank D,4,Clearance D" - }; - Dictionary outData = new Dictionary(); - - var sqlString = query.ToString(); - CheckSql(sqlString, SQLSyntax.ShipQueryMalformedDueMultipleProjecttionsCorrectedEF6); - // see below for the generated SQL query - - var harbor = query.Single(); - - foreach (var ship in harbor.Ships) - { - foreach (var crewMember in ship.CrewMembers) - { - outData.Add(string.Format( - "{0},{1},1,{2},{3},{4},1,{5},{6},{7},{8},{9},{10},{11},{12},{13}", - harbor.HarborId, harbor.Description, ship.ShipId, harbor.HarborId, - ship.Description, crewMember.CrewMemberId, crewMember.ShipId, crewMember.RankId, - crewMember.ClearanceId, crewMember.Description, crewMember.Rank.RankId, - crewMember.Rank.Description, crewMember.Clearance.ClearanceId, - crewMember.Clearance.Description), null); - } - } - // check data integrity - Assert.AreEqual(outData.Count, data.Length); - for (int i = 0; i < data.Length; i++) - { - Assert.True(outData.ContainsKey(data[i])); - } - } - } - - /// - /// Tests fix for bug http://bugs.mysql.com/bug.php?id=68513, Error in LINQ to Entities query when using Distinct().Count(). - /// - [Test] - public void DistinctCount() - { -#if DEBUG - Debug.WriteLine(new StackTrace().GetFrame(0).GetMethod().Name); -#endif - using (SiteDbContext ctx = new SiteDbContext()) - { - ctx.Database.Initialize(true); - visitante v1 = new visitante() { nCdSite = 1, nCdVisitante = 1, sDsIp = "x1" }; - visitante v2 = new visitante() { nCdSite = 1, nCdVisitante = 2, sDsIp = "x2" }; - site s1 = new site() { nCdSite = 1, sDsTitulo = "MyNewsPage" }; - site s2 = new site() { nCdSite = 2, sDsTitulo = "MySearchPage" }; - ctx.Visitante.Add(v1); - ctx.Visitante.Add(v2); - ctx.Site.Add(s1); - ctx.Site.Add(s2); - ctx.SaveChanges(); - - var q = (from vis in ctx.Visitante.Include("site") - group vis by vis.nCdSite into g - select new retorno - { - Key = g.Key, - Online = g.Select(e => e.sDsIp).Distinct().Count() - }); - string sql = q.ToString(); - CheckSql(sql, SQLSyntax.CountGroupBy); - var q2 = q.ToList(); - foreach (var row in q2) - { - } - } - } - - /// - /// Tests fix for bug http://bugs.mysql.com/bug.php?id=68513, Error in LINQ to Entities query when using Distinct().Count(). - /// - [Test] - public void DistinctCount2() - { -#if DEBUG - Debug.WriteLine(new StackTrace().GetFrame(0).GetMethod().Name); -#endif - using (SiteDbContext ctx = new SiteDbContext()) - { - ctx.Database.Initialize(true); - visitante v1 = new visitante() { nCdSite = 1, nCdVisitante = 1, sDsIp = "x1" }; - visitante v2 = new visitante() { nCdSite = 1, nCdVisitante = 2, sDsIp = "x2" }; - site s1 = new site() { nCdSite = 1, sDsTitulo = "MyNewsPage" }; - site s2 = new site() { nCdSite = 2, sDsTitulo = "MySearchPage" }; - pagina p1 = new pagina() { nCdPagina = 1, nCdVisitante = 1, sDsTitulo = "index.html" }; - ctx.Visitante.Add(v1); - ctx.Visitante.Add(v2); - ctx.Site.Add(s1); - ctx.Site.Add(s2); - ctx.Pagina.Add(p1); - ctx.SaveChanges(); - - var q = (from pag in ctx.Pagina.Include("visitante").Include("site") - group pag by pag.visitante.nCdSite into g - select new retorno - { - Key = g.Key, - Online = g.Select(e => e.visitante.sDsIp).Distinct().Count() - }); - string sql = q.ToString(); - CheckSql(sql, SQLSyntax.CountGroupBy2); - var q2 = q.ToList(); - foreach (var row in q2) - { - } - } - } - - /// - /// Tests fix for bug http://bugs.mysql.com/bug.php?id=65723, MySql Provider for EntityFramework produces "bad" SQL for OrderBy. - /// - [Test] - public void BadOrderBy() - { -#if DEBUG - Debug.WriteLine(new StackTrace().GetFrame(0).GetMethod().Name); -#endif - using (MovieDBContext db = new MovieDBContext()) - { - db.Database.Initialize(true); - MovieDBInitialize.DoDataPopulation(db); - DateTime filterDate = new DateTime(1986, 1, 1); - var q = db.Movies.Where(p => p.ReleaseDate >= filterDate). - OrderByDescending(p => p.ReleaseDate).Take(2); - string sql = q.ToString(); - CheckSql(SQLSyntax.NestedOrderBy, sql); - // Data integrity testing - Movie[] data = new Movie[] { - new Movie() { ID = 4, Title = "Star Wars, The Sith Revenge", ReleaseDate = new DateTime( 2005, 5, 19 ) }, - new Movie() { ID = 2, Title = "The Matrix", ReleaseDate = new DateTime( 1999, 3, 31 ) } - }; - int i = 0; - foreach (Movie m in q) - { - Assert.AreEqual(data[i].ID, m.ID); - Assert.AreEqual(data[i].Title, m.Title); - Assert.AreEqual(data[i].ReleaseDate, m.ReleaseDate); - i++; - } - Assert.AreEqual(2, i); - } - } - - /// - /// Tests fix for bug http://bugs.mysql.com/bug.php?id=69751, Invalid SQL query generated for query with Contains, OrderBy, and Take. - /// - [Test] - public void BadContainsOrderByTake() - { -#if DEBUG - Debug.WriteLine(new StackTrace().GetFrame(0).GetMethod().Name); -#endif - using (MovieDBContext db = new MovieDBContext()) - { - db.Database.Initialize(true); - MovieDBInitialize.DoDataPopulation(db); - string title = "T"; - var q = from m in db.Movies - where m.Title.Contains(title) - orderby m.ID descending - select m; - var q1 = q.Take(10); - string sql = q1.ToString(); - - CheckSql(SQLSyntax.QueryWithOrderByTakeContains, sql); - - int i = 0; - foreach (var row in q1) - { - Assert.AreEqual(MovieDBInitialize.data[i].ID, row.ID); - Assert.AreEqual(MovieDBInitialize.data[i].Title, row.Title); - Assert.AreEqual(MovieDBInitialize.data[i].ReleaseDate, row.ReleaseDate); - i++; - } - } - } - - /// - /// Tests fix for bug http://bugs.mysql.com/bug.php?id=69922, Unknown column Extent1... - /// - [Test] - public void BadAliasTable() - { -#if DEBUG - Debug.WriteLine(new StackTrace().GetFrame(0).GetMethod().Name); -#endif - using (PromotionsDB db = new PromotionsDB()) - { - db.Database.Initialize(true); - DateTime now = DateTime.Now; - var q = db - .HomePromoes - .Where(x => - x.Active - && - (x.ActiveFrom == null || x.ActiveFrom <= now) - && - (x.ActiveTo == null || x.ActiveTo >= now) - ) - .OrderBy(x => x.DisplayOrder).Select(d => d); - string sql = q.ToString(); - foreach (var row in q) - { - } - } - } - - /// - /// Tests other variants of bug http://bugs.mysql.com/bug.php?id=69751, Invalid SQL query generated for query with Contains, OrderBy, and Take. - /// - [Test] - public void BadContainsOrderByTake2() - { -#if DEBUG - Debug.WriteLine(new StackTrace().GetFrame(0).GetMethod().Name); -#endif - using (MovieDBContext db = new MovieDBContext()) - { - db.Database.Initialize(true); - MovieDBInitialize.DoDataPopulation(db); - var q = db.Movies. - Where(m => !string.IsNullOrEmpty(m.Title) && m.Title.Contains("x")). - OrderByDescending(m => m.ID). - Skip(1). - Take(1); - string sql = q.ToString(); -#if DEBUG - Debug.WriteLine(sql); -#endif - List l = q.ToList(); - int j = l.Count; - foreach (Movie m in l) - { - j--; - } - Assert.AreEqual(0, j); - } - } - - /// - /// Tests other variants of bug http://bugs.mysql.com/bug.php?id=69751, Invalid SQL query generated for query with Contains, OrderBy, and Take. - /// - [Test] - public void BadContainsOrderByTake3() - { -#if DEBUG - Debug.WriteLine(new StackTrace().GetFrame(0).GetMethod().Name); -#endif - using (MovieDBContext db = new MovieDBContext()) - { - db.Database.Initialize(true); - MovieDBInitialize.DoDataPopulation(db); - var q = db.Movies. - Where(m => !string.IsNullOrEmpty(m.Title) && m.Title.Contains("x")). - OrderByDescending(m => m.ID). - Skip(1). - Take(1).Select(m => new - { - Id = m.ID, - CriticsScore = ( - m.Title == "Terminator 1" ? "Good" : - m.Title == "Predator" ? "Sunday best, cheese" : - m.Title == "The Matrix" ? "Really Good" : - m.Title == "Star Wars, The Sith Revenge" ? "Really Good" : "Unknown") - }); - string sql = q.ToString(); -#if DEBUG - Debug.WriteLine(sql); -#endif - int j = q.Count(); - foreach (var row in q) - { - j--; - } - Assert.AreEqual(0, j); - } - } - - /// - /// Tests other variants of bug http://bugs.mysql.com/bug.php?id=69751, Invalid SQL query generated for query with Contains, OrderBy, and Take. - /// - [Test] - public void BadContainsOrderByTake4() - { -#if DEBUG - Debug.WriteLine(new StackTrace().GetFrame(0).GetMethod().Name); -#endif - using (MovieDBContext db = new MovieDBContext()) - { - db.Database.Initialize(true); - MovieDBInitialize.DoDataPopulation(db); - bool q = db.Movies.Any(m => m.ReleaseDate.Year > 1985); - // string sql = q.ToString(); - //#if DEBUG - // Debug.WriteLine(sql); - //#endif - //foreach (var row in q) - //{ - //} - } - } - - /// - /// Tests other variants of bug http://bugs.mysql.com/bug.php?id=69751, Invalid SQL query generated for query with Contains, OrderBy, and Take. - /// - [Test] - public void BadContainsOrderByTake5() - { -#if DEBUG - Debug.WriteLine(new StackTrace().GetFrame(0).GetMethod().Name); -#endif - using (MovieDBContext db = new MovieDBContext()) - { - db.Database.Initialize(true); - MovieDBInitialize.DoDataPopulation(db); - // TODO: add subquery like - // var shifts = Shifts.Where(s => !EmployeeShifts.Where(es => es.ShiftID == s.ShiftID).Any()); - bool q = db.Movies.Where(m => m.ReleaseDate.Month != 10).Any(m => m.ReleaseDate.Year > 1985); - // string sql = q.ToString(); - //#if DEBUG - // Debug.WriteLine(sql); - //#endif - // foreach (var row in q) - // { - // } - } - } - - /// - /// Tests other variants of bug http://bugs.mysql.com/bug.php?id=69751, Invalid SQL query generated for query with Contains, OrderBy, and Take. - /// - [Test] - public void BadContainsOrderByTake6() - { -#if DEBUG - Debug.WriteLine(new StackTrace().GetFrame(0).GetMethod().Name); -#endif - using (MovieDBContext db = new MovieDBContext()) - { - db.Database.Initialize(true); - MovieDBInitialize.DoDataPopulation(db); - var q = from m in db.Movies - where m.Title.Contains("x") && db.Medias.Where(mm => mm.Format == "Digital").Any() - select m; - string sql = q.ToString(); -#if DEBUG - Debug.WriteLine(sql); -#endif - int j = q.Count(); - foreach (var row in q) - { - j--; - } - Assert.AreEqual(0, j); - } - } - - /// - /// Test for Mysql Bug 70602: http://bugs.mysql.com/bug.php?id=70602 - /// - [Test] - public void AutoIncrementBug() - { -#if DEBUG - Debug.WriteLine(new StackTrace().GetFrame(0).GetMethod().Name); -#endif - AutoIncrementBugContext dbContext = new AutoIncrementBugContext(); - - dbContext.Database.Initialize(true); - dbContext.AutoIncrementBug.Add(new AutoIncrementBug() { Description = "Test" }); - dbContext.SaveChanges(); - using (var reader = MySqlHelper.ExecuteReader(dbContext.Database.Connection.ConnectionString, - $"SHOW COLUMNS FROM {nameof(dbContext.AutoIncrementBug)}s WHERE UPPER(EXTRA) LIKE '%AUTO_INCREMENT%'")) - { - Assert.True(reader.HasRows); - } - dbContext.Database.Delete(); - } - - [Test] - public void SimpleCodeFirstSelectCbc() - { - MovieCodedBasedConfigDBContext db = new MovieCodedBasedConfigDBContext(); - db.Database.Initialize(true); - var l = db.Movies.ToList(); - foreach (var i in l) - { - Console.WriteLine(i); - } - } - - [Test] - [Ignore("Need to check. Bad statemen: CALL `MovieCodedBasedConfigDBContext`.``insert_movie``(@movie_name, @ReleaseDate, @Genre, @Price)")] - public void TestStoredProcedureMapping() - { - using (var db = new MovieCodedBasedConfigDBContext()) - { - db.Database.Initialize(true); - var movie = new MovieCBC() - { - Title = "Sharknado", - Genre = "Documental", - Price = 1.50M, - ReleaseDate = DateTime.Parse("01/07/2013") - }; - - db.Movies.Add(movie); - db.SaveChanges(); - movie.Genre = "Fiction"; - db.SaveChanges(); - db.Movies.Remove(movie); - db.SaveChanges(); - } - } - - [Test] - public void MigrationHistoryConfigurationTest() - { - MovieCodedBasedConfigDBContext db = new MovieCodedBasedConfigDBContext(); - db.Database.Initialize(true); - var l = db.Movies.ToList(); - foreach (var i in l) - { - } - var result = MySqlHelper.ExecuteScalar($"server=localhost;User Id=root;database={db.Database.Connection.Database};logging=true; port=" + Port + ";", "SELECT COUNT(_MigrationId) FROM __MySqlMigrations;"); - Assert.AreEqual(1, int.Parse(result.ToString())); - } - - [Test] - public void DbSetRangeTest() - { - using (MovieDBContext db = new MovieDBContext()) - { - db.Database.Initialize(true); - Movie m1 = new Movie() { Title = "Terminator 1", ReleaseDate = new DateTime(1984, 10, 26) }; - Movie m2 = new Movie() { Title = "The Matrix", ReleaseDate = new DateTime(1999, 3, 31) }; - Movie m3 = new Movie() { Title = "Predator", ReleaseDate = new DateTime(1987, 6, 12) }; - Movie m4 = new Movie() { Title = "Star Wars, The Sith Revenge", ReleaseDate = new DateTime(2005, 5, 19) }; - db.Movies.AddRange(new Movie[] { m1, m2, m3, m4 }); - db.SaveChanges(); - var q = from m in db.Movies select m; - Assert.AreEqual(4, q.Count()); - foreach (var row in q) - { - } - db.Movies.RemoveRange(q.ToList()); - db.SaveChanges(); - var q2 = from m in db.Movies select m; - Assert.AreEqual(0, q2.Count()); - } - } - - [Test] - public void EnumSupportTest() - { - using (var dbCtx = new EnumTestSupportContext()) - { - dbCtx.Database.Initialize(true); - dbCtx.SchoolSchedules.Add(new SchoolSchedule() { TeacherName = "Pako", Subject = SchoolSubject.History }); - dbCtx.SaveChanges(); - - var schedule = (from s in dbCtx.SchoolSchedules - where s.Subject == SchoolSubject.History - select s).FirstOrDefault(); - - Assert.AreNotEqual(null, schedule); - Assert.AreEqual(SchoolSubject.History, schedule.Subject); - } - } - - - [Test] - [Ignore("This test needs MicrosoftSqlServer.Types which is not available for all the target frameworks.")] - public void SpatialSupportTest() - { - using (var dbCtx = new JourneyContext()) - { - dbCtx.Database.Initialize(true); - dbCtx.MyPlaces.Add(new MyPlace() - { - name = "JFK INTERNATIONAL AIRPORT OF NEW YORK", - location = DbGeometry.FromText("POINT(40.644047 -73.782291)"), - }); - dbCtx.MyPlaces.Add(new MyPlace - { - name = "ALLEY POND PARK", - location = DbGeometry.FromText("POINT(40.745696 -73.742638)") - }); - dbCtx.MyPlaces.Add(new MyPlace - { - name = "CUNNINGHAM PARK", - location = DbGeometry.FromText("POINT(40.735031 -73.768387)") - }); - dbCtx.MyPlaces.Add(new MyPlace - { - name = "QUEENS VILLAGE STATION", - location = DbGeometry.FromText("POINT(40.717957 -73.736501)") - }); - dbCtx.SaveChanges(); - - var place = (from p in dbCtx.MyPlaces - where p.name == "JFK INTERNATIONAL AIRPORT OF NEW YORK" - select p).FirstOrDefault(); - - var point = DbGeometry.FromText("POINT(40.717957 -73.736501)"); - - var distance = (point.Distance(place.location) * 100); - - Assert.AreNotEqual(null, place); - Assert.AreEqual(8.6944880240295852D, distance.Value); - - var points = from p in dbCtx.MyPlaces - select new { name = p.name, location = p.location }; - foreach (var item in points) - { - var distanceX = DbGeometry.FromText("POINT(40.717957 -73.736501)").Distance(item.location) * 100; - Assert.IsNotNull(distanceX); - } - - foreach (MyPlace p in dbCtx.MyPlaces) - dbCtx.MyPlaces.Remove(p); - dbCtx.SaveChanges(); - - dbCtx.MyPlaces.Add(new MyPlace - { - name = "AGraphic Design Institute", - location = DbGeometry.FromText(string.Format("POINT({0} {1})", -122.336106, 47.605049), 101) - }); - - dbCtx.MyPlaces.Add(new MyPlace - { - name = "AGraphic Design Institute", - location = DbGeometry.FromText("POINT(-123.336106 47.605049)", 102) - }); - - dbCtx.MyPlaces.Add(new MyPlace - { - name = "BGraphic Design Institute", - location = DbGeometry.FromText("POINT(-113.336106 47.605049)", 103) - }); - - dbCtx.MyPlaces.Add(new MyPlace - { - name = "Graphic Design Institute", - location = DbGeometry.FromText(string.Format("POINT({0} {1})", 51.5, -1.28), 4326) - }); - dbCtx.SaveChanges(); - - var result = (from u in dbCtx.MyPlaces select u.location.CoordinateSystemId).ToList(); - foreach (var item in result) - Assert.IsNotNull(item); - var res = dbCtx.MyPlaces.OrderBy(q => q.name.Take(1).Skip(1).ToList()); - Assert.IsNotNull(res); - - var pointA1 = DbGeometry.FromText(string.Format("POINT(40.644047 -73.782291)")); - var pointB1 = DbGeometry.FromText("POINT(40.717957 -73.736501)"); - var distance1 = pointA1.Distance(pointB1); - - var pointA2 = DbGeometry.FromText("POINT(2.5 2.5)"); - var pointB2 = DbGeometry.FromText("POINT(4 0.8)"); - var distance2 = pointA2.Distance(pointB2); - - var pointA3 = DbGeometry.FromText("POINT(3 -4)"); - var pointB3 = DbGeometry.FromText("POINT(-1 3)"); - var distance3 = pointA3.Distance(pointB3); - - Assert.True(distance1.Value == 0.086944880240295855 && distance2.Value == 2.2671568097509267 && - distance3.Value == 8.06225774829855); - - } - } - - [Test] - public void BeginTransactionSupportTest() - { - using (var dbcontext = new MovieCodedBasedConfigDBContext()) - { - dbcontext.Database.Initialize(true); - using (var transaction = dbcontext.Database.BeginTransaction()) - { - try - { - dbcontext.Movies.Add(new MovieCBC() - { - Title = "Sharknado", - Genre = "Documental", - Price = 1.50M, - ReleaseDate = DateTime.Parse("01/07/2013") - }); - - dbcontext.SaveChanges(); - var result = MySqlHelper.ExecuteScalar("server=localhost;User Id=root;database=test;logging=true;port=" + Port + ";", "select COUNT(*) from moviecbcs;"); - Assert.AreEqual(0, int.Parse(result.ToString())); - - transaction.Commit(); - - result = MySqlHelper.ExecuteScalar("server=localhost;User Id=root;database=test;logging=true; port=" + Port + ";", "select COUNT(*) from moviecbcs;"); - Assert.AreEqual(1, int.Parse(result.ToString())); - } - catch (Exception) - { - transaction.Rollback(); - } - } - } - } - - /// - /// This test covers two new features on EF6: - /// 1- "DbContext.Database.UseTransaction, that use a transaction created from an open connection" - /// 2- "DbContext can now be created with a DbConnection that is already opened" - /// - [Test] - public void UseTransactionSupportTest() - { - using (var context = new MovieCodedBasedConfigDBContext()) - { - context.Database.CreateIfNotExists(); - } - using (var connection = new MySqlConnection($"server=localhost;User Id=root;database={nameof(MovieCodedBasedConfigDBContext)};logging=true; port=" + Port + ";")) - { - connection.Open(); - using (var transaction = connection.BeginTransaction()) - { - try - { - using (var dbcontext = new MovieCodedBasedConfigDBContext(connection, contextOwnsConnection: false)) - { - dbcontext.Database.Initialize(true); - dbcontext.Database.UseTransaction(transaction); - dbcontext.Movies.Add(new MovieCBC() - { - Title = "Sharknado", - Genre = "Documental", - Price = 1.50M, - ReleaseDate = DateTime.Parse("01/07/2013") - }); - - dbcontext.SaveChanges(); - } - var result = MySqlHelper.ExecuteScalar("server=localhost;User Id=root;database=test;logging=true; port=" + Port + ";", "select COUNT(*) from moviecbcs;"); - Assert.AreEqual(0, int.Parse(result.ToString())); - - transaction.Commit(); - - result = MySqlHelper.ExecuteScalar("server=localhost;User Id=root;database=test;logging=true; port=" + Port + ";", "select COUNT(*) from moviecbcs;"); - Assert.AreEqual(1, int.Parse(result.ToString())); - } - catch (Exception) - { - transaction.Rollback(); - } - } - } - } - - [Test] - [Ignore("Need to check. Bad statemen: CALL `MovieCodedBasedConfigDBContext`.``insert_movie``(@movie_name, @ReleaseDate, @Genre, @Price)")] - public void HasChangesSupportTest() - { - using (var dbcontext = new MovieCodedBasedConfigDBContext()) - { - dbcontext.Database.Initialize(true); - - dbcontext.Movies.Add(new MovieCBC() - { - Title = "Sharknado", - Genre = "Documental", - Price = 1.50M, - ReleaseDate = DateTime.Parse("01/07/2013") - }); - - Assert.True(dbcontext.ChangeTracker.HasChanges()); - dbcontext.SaveChanges(); - Assert.False(dbcontext.ChangeTracker.HasChanges()); - } - } - - [Test] - [Ignore("Need to check. Bad statemen: CALL `MovieCodedBasedConfigDBContext`.``insert_movie``(@movie_name, @ReleaseDate, @Genre, @Price)")] - public void MySqlLoggingToFileSupportTest() - { - string logName = "mysql.log"; - //if (System.IO.File.Exists(logName)) - // System.IO.File.Delete(logName); - - using (var dbcontext = new MovieCodedBasedConfigDBContext()) - { - dbcontext.Database.Log = MySqlLogger.Logger(logName, true).Write; - - dbcontext.Database.Initialize(true); - dbcontext.Movies.Add(new MovieCBC() - { - Title = "Sharknado", - Genre = "Documental", - Price = 1.50M, - ReleaseDate = DateTime.Parse("01/07/2013") - }); - dbcontext.SaveChanges(); - } - - Assert.AreEqual(true, System.IO.File.Exists(logName)); - } - - [Test] - [Ignore("Need to check. Bad statemen: CALL `MovieCodedBasedConfigDBContext`.``insert_movie``(@movie_name, @ReleaseDate, @Genre, @Price)")] - public void MySqlLoggingToConsoleSupportTest() - { - string logName = "mysql_2.log"; - if (System.IO.File.Exists(logName)) - System.IO.File.Delete(logName); - - System.IO.FileStream file; - System.IO.StreamWriter writer; - System.IO.TextWriter txtOut = Console.Out; - try - { - file = new System.IO.FileStream(logName, System.IO.FileMode.OpenOrCreate, System.IO.FileAccess.Write); - writer = new System.IO.StreamWriter(file); - } - catch (Exception e) - { - throw e; - } - Console.SetOut(writer); - - using (var dbcontext = new MovieCodedBasedConfigDBContext()) - { - dbcontext.Database.Log = new MySqlLogger(s => Console.Write(s)).Write; - - dbcontext.Database.Initialize(true); - dbcontext.Movies.Add(new MovieCBC() - { - Title = "Sharknado", - Genre = "Documental", - Price = 1.50M, - ReleaseDate = DateTime.Parse("01/07/2013") - }); - dbcontext.SaveChanges(); - } - Console.SetOut(txtOut); - writer.Close(); - file.Close(); - - Assert.AreEqual(true, System.IO.File.Exists(logName)); - } - - [Test] - public void EntityAndComplexTypeSupportTest() - { - using (var dbContext = new EntityAndComplexTypeContext()) - { - dbContext.Database.Initialize(true); - dbContext.Students.Add( - new Student() - { - Name = "Pakorasu Pakolas", - Address = new Address() { City = "Mazatlan", Street = "Tierra de Venados 440" }, - Schedule = new List() { new SchoolSchedule() { TeacherName = "Pako", Subject = SchoolSubject.History } } - }); - dbContext.SaveChanges(); - - var student = (from s in dbContext.Students - select s).FirstOrDefault(); - - Assert.AreNotEqual(null, student); - Assert.AreNotEqual(null, student.Schedule); - Assert.AreNotEqual(true, string.IsNullOrEmpty(student.Address.Street)); - Assert.AreNotEqual(0, student.Schedule.Count()); - } - } - - /// - /// TO RUN THIS TEST ITS NECESSARY TO ENABLE THE EXECUTION STRATEGY IN THE CLASS MySqlEFConfiguration (Source\MySql.Data.Entity\MySqlConfiguration.cs) AS WELL AS START A MYSQL SERVER INSTACE WITH THE OPTION "--max_connections=3" - /// WHY 3?: 1)For main process (User: root, DB: mysql). 2)For Setup Class. 3)For the connections in this test. - /// The expected result is that opening a third connection and trying to open a fourth(with an asynchronous task) the execution strategy implementation handle the reconnection process until the third one is closed. - /// - //[Test] //<---DON'T FORGET ME TO RUN! =D - public void ExecutionStrategyTest() - { - var connection = new MySqlConnection("server=localhost;User Id=root;logging=true; port=" + Port + ";"); - using (var dbcontext = new MovieCodedBasedConfigDBContext()) - { - dbcontext.Database.Initialize(true); - dbcontext.Movies.Add(new MovieCBC() - { - Title = "Sharknado", - Genre = "Documental", - Price = 1.50M, - ReleaseDate = DateTime.Parse("01/07/2013") - }); - connection.Open(); - System.Threading.Tasks.Task.Factory.StartNew(() => { dbcontext.SaveChanges(); }); - Thread.Sleep(1000); - connection.Close(); - connection.Dispose(); - } - var result = MySqlHelper.ExecuteScalar("server=localhost;User Id=root;database=test;logging=true; port=" + Port + ";", "select COUNT(*) from moviecbcs;"); - Assert.AreEqual(1, int.Parse(result.ToString())); - } - - [Test] - public void UnknownProjectC1() - { -#if DEBUG - Debug.WriteLine(new StackTrace().GetFrame(0).GetMethod().Name); -#endif - using (MovieDBContext db = new MovieDBContext()) - { - db.Database.Initialize(true); - MovieDBInitialize.DoDataPopulation(db); - long myKey = 20; - var q = (from r in db.Movies where (r.ID == myKey) select (long)r.ID).OrderBy(p => p); - string sql = q.ToString(); - CheckSql(sql, SQLSyntax.UnknownProjectC1EF6); - -#if DEBUG - Debug.WriteLine(sql); -#endif - long[] array = (from r in db.Movies where (r.ID == myKey) select (long)r.ID).OrderBy(p => p).ToArray(); - } - } - - [Test] - public void StartsWithTest() - { -#if DEBUG - Debug.WriteLine(new StackTrace().GetFrame(0).GetMethod().Name); -#endif - MovieDBContext db = new MovieDBContext(); - db.Database.Initialize(true); - MovieDBInitialize.DoDataPopulation(db); - string term = "The"; - var l = db.Movies.Where(p => p.Title.StartsWith(term)); - - string sql = l.ToString(); - - CheckSql(sql, SQLSyntax.QueryWithStartsWith); - -#if DEBUG - Debug.WriteLine(sql); -#endif - int j = l.Count(); - foreach (var i in l) - { - j--; - } - Assert.AreEqual(0, j); - } - - [Test] - public void EndsWithTest() - { -#if DEBUG - Debug.WriteLine(new StackTrace().GetFrame(0).GetMethod().Name); -#endif - MovieDBContext db = new MovieDBContext(); - db.Database.Initialize(true); - MovieDBInitialize.DoDataPopulation(db); - string term = "The"; - var l = db.Movies.Where(p => p.Title.EndsWith(term)); - - string sql = l.ToString(); - - CheckSql(sql, SQLSyntax.QueryWithEndsWith); - -#if DEBUG - Debug.WriteLine(sql); -#endif - int j = l.Count(); - foreach (var i in l) - { - j--; - } - Assert.AreEqual(0, j); - } - - [Test] - public void ContainsTest() - { -#if DEBUG - Debug.WriteLine(new StackTrace().GetFrame(0).GetMethod().Name); -#endif - MovieDBContext db = new MovieDBContext(); - db.Database.Initialize(true); - MovieDBInitialize.DoDataPopulation(db); - string term = "The"; - var l = db.Movies.Where(p => p.Title.Contains(term)); - - string sql = l.ToString(); - CheckSql(sql, SQLSyntax.QueryWithContains); - -#if DEBUG - Debug.WriteLine(sql); -#endif - int j = l.Count(); - foreach (var i in l) - { - j--; - } - Assert.AreEqual(0, j); - } - - - /// - /// Test to reproduce bug http://bugs.mysql.com/bug.php?id=73643, Exception when using IEnumera.Contains(model.property) in Where predicate - /// - [Test] - public void TestContainsListWithCast() - { -#if DEBUG - Debug.WriteLine(new StackTrace().GetFrame(0).GetMethod().Name); -#endif - using (MovieDBContext db = new MovieDBContext()) - { - db.Database.Initialize(true); - - long[] longs = new long[] { 1, 2, 3 }; - var q = db.Movies.Where(p => longs.Contains((long)p.ID)); - string sql = q.ToString(); - CheckSql(sql, SQLSyntax.TestContainsListWithCast); -#if DEBUG - Debug.WriteLine(sql); -#endif - var l = q.ToList(); - } - } - - /// - /// Test to reproduce bug http://bugs.mysql.com/bug.php?id=73643, Exception when using IEnumera.Contains(model.property) in Where predicate - /// - [Test] - public void TestContainsListWitConstant() - { -#if DEBUG - Debug.WriteLine(new StackTrace().GetFrame(0).GetMethod().Name); -#endif - using (MovieDBContext db = new MovieDBContext()) - { - db.Database.Initialize(true); - - List strIds = new List(new string[] { "two" }); - var q = db.Movies.Where(p => strIds.Contains("two")); - string sql = q.ToString(); - CheckSql(sql, SQLSyntax.TestContainsListWitConstant); -#if DEBUG - Debug.WriteLine(sql); -#endif - var l = q.ToList(); - } - } - - /// - /// Test to reproduce bug http://bugs.mysql.com/bug.php?id=73643, Exception when using IEnumera.Contains(model.property) in Where predicate - /// - [Test] - public void TestContainsListWithParameterReference() - { -#if DEBUG - Debug.WriteLine(new StackTrace().GetFrame(0).GetMethod().Name); -#endif - using (MovieDBContext db = new MovieDBContext()) - { - db.Database.Initialize(true); - - long[] longs = new long[] { 1, 2, 3 }; - int myNum = 1; - var q = db.Movies.Where(p => longs.Contains(myNum)); - string sql = q.ToString(); - CheckSql(sql, SQLSyntax.TestContainsListWithParameterReference); -#if DEBUG - Debug.WriteLine(sql); -#endif - var l = q.ToList(); - } - } - - [Test] - public void ReplaceTableNameVisitor() - { - using (SakilaDb context = new SakilaDb()) - { - var date = new DateTime(2005, 6, 1); - var rentals = context.customers.Where(t => t.rentals.Any(r => r.rental_date < date)).OrderBy(o => o.customer_id); - string sql = rentals.ToString(); - CheckSql(sql, SQLSyntax.ReplaceNameVisitorQuery); -#if DEBUG - Debug.WriteLine(sql); -#endif - var result = rentals.ToList(); - Assert.AreEqual(520, rentals.Count()); - } - } - - - /// - /// Bug #70941 - Invalid SQL query when eager loading two nested collections - /// - [Test] - public void InvalidQuery() - { - using (UsingUnionContext context = new UsingUnionContext()) - { - if (context.Database.Exists()) - context.Database.Delete(); - - context.Database.Create(); - - for (int i = 1; i <= 3; i++) - { - var order = new Order(); - var items = new List(); - - items.Add(new Item { Id = 1 }); - items.Add(new Item { Id = 2 }); - items.Add(new Item { Id = 3 }); - - order.Items = items; - var client = new Client { Id = i }; - client.Orders = new List(); - client.Orders.Add(order); - - context.Clients.Add(client); - } - context.SaveChanges(); - - var clients = context.Clients - .Include(c => c.Orders.Select(o => o.Items)) - .Include(c => c.Orders.Select(o => o.Discounts)).ToList(); - - Assert.AreEqual(clients.Count(), 3); - Assert.AreEqual(clients.Where(t => t.Id == 1).Single().Orders.Count(), 1); - Assert.AreEqual(clients.Where(t => t.Id == 1).Single().Orders.Where(j => j.Id == 1).Single().Items.Count(), 3); - } - } - - /// - /// Bug #28095165 - CONTRIBUTION: FIX CONCURRENCYCHECK + DATABASEGENERATEDOPTION.COMPUTED - /// - [Test] - public void ConcurrencyCheckWithDbGeneratedColumn() - { -#if DEBUG - Debug.WriteLine(new StackTrace().GetFrame(0).GetMethod().Name); -#endif - using (MovieDBContext db = new MovieDBContext()) - { - db.Database.Delete(); - db.Database.CreateIfNotExists(); - db.Database.Log = (e) => Debug.WriteLine(e); - db.Database.ExecuteSqlCommand(@"DROP TABLE IF EXISTS `MovieReleases2`"); - - db.Database.ExecuteSqlCommand( - @"CREATE TABLE IF NOT EXISTS `MovieRelease2` ( - `Id` int(11) NOT NULL, - `Name` varchar(45) NOT NULL, - `Timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - `RowVersion` bigint NOT NULL DEFAULT 0, - PRIMARY KEY (`Id`) - ) ENGINE=InnoDB DEFAULT CHARSET=binary"); - - db.Database.ExecuteSqlCommand( - @"CREATE TRIGGER `trg_MovieRelease2_before_update` - BEFORE UPDATE ON `MovieRelease2` - FOR EACH ROW SET NEW.RowVersion = OLD.RowVersion + 1;"); - - MySqlTrace.Listeners.Clear(); - MySqlTrace.Switch.Level = SourceLevels.All; - GenericListener listener = new GenericListener(); - MySqlTrace.Listeners.Add(listener); - - try - { - MovieRelease2 mr = db.MovieReleases2.Create(); - mr.Id = 1; - mr.Name = "Commercial"; - db.MovieReleases2.Add(mr); - Assert.AreEqual(mr.RowVersion, 0); - db.SaveChanges(); // ADD - Assert.AreEqual(mr.RowVersion, 0); - - mr.Name = "Director's Cut"; - db.SaveChanges(); // UPDATE #1 - Assert.AreEqual(mr.RowVersion, 1); - - mr.Name = "Avengers"; - db.SaveChanges(); // UPDATE #2 - Assert.AreEqual(mr.RowVersion, 2); - } - finally - { - db.Database.ExecuteSqlCommand(@"DROP TABLE IF EXISTS `MovieReleases2`"); - } - // Check sql - Regex rx = new Regex(@"Query Opened: (?UPDATE .*)", RegexOptions.Compiled | RegexOptions.Singleline); - int n = 0; - foreach (string s in listener.Strings) - { - Match m = rx.Match(s); - if (m.Success) - { - if (n++ == 0) - { - CheckSql(m.Groups["item"].Value, SQLSyntax.UpdateWithSelectWithDbGeneratedLock1); - } - else - { - CheckSql(m.Groups["item"].Value, SQLSyntax.UpdateWithSelectWithDbGeneratedLock2); - } - } - } - } - } - - /// - /// Bug #31323788 - EF6 CODE FIRST - TABLE SCHEMAS ARE LOST, BUT AUTOMATIC MIGRATIONS USES THEM - /// - [Test] - public void TablesWithSchema() - { - using (BlogContext context = new BlogContext()) - { - var blog = new Blog { Title = "Blog_1" }; - context.Blog.Add(blog); - - blog = new Blog { Title = "Blog_2" }; - context.Blog.Add(blog); - - context.SaveChanges(); - Assert.AreEqual(2, context.Blog.Count()); - Assert.AreEqual(2, context.Blog.First(b => b.Title == "Blog_2").BlogId); - - context.Blog.Remove(blog); - context.SaveChanges(); - Assert.AreEqual(1, context.Blog.Count()); - Assert.AreEqual("Blog_1", context.Blog.First().Title); - } - } - - [Test, Description("UNION SYNTAX MISSING REQUIRED PARENTHESIS")] - public void UnionSyntax() - { - using (var context = new ContextForString()) - { - context.Database.Delete(); - context.Database.Create(); - context.StringUsers.Add(new StringUser - { - StringUserId = 1, - Name50 = "Juan", - Name100 = "100", - Name200 = "200", - Name300 = "300" - }); - context.StringUsers.Add(new StringUser - { - StringUserId = 2, - Name50 = "Pedro", - Name100 = "cien", - Name200 = "doscientos", - Name300 = "trescientos" - }); - context.StringUsers.Add(new StringUser - { - StringUserId = 3, - Name50 = "Lupe", - Name100 = "101", - Name200 = "cxvbx", - Name300 = "301" - }); - context.StringUsers.Add(new StringUser - { - StringUserId = 4, - Name50 = "Luis", - Name100 = "asdf", - Name200 = "wrwe", - Name300 = "xcvb" - }); - context.StringUsers.Add(new StringUser - { - StringUserId = 5, - Name50 = "Pepe", - Name100 = "asdf", - Name200 = "zxvz", - Name300 = "fgsd" - }); - context.SaveChanges(); - - var query1 = context.StringUsers; - var query2 = query1.Take(0).Concat(query1); - var query3 = query1.Concat(query1.Take(0)); - Assert.True((query1.Count() == 5) & (query2.Count() == 5) & (query3.Count() == 5)); - } - } - - [Test, Description("FK name ,longer than 64 chars are named to FK_")] - public void NormalForeignKey() - { - using (var context = new ContextForNormalFk()) - { - context.Database.Initialize(true); - using (MySqlConnection conn = new MySqlConnection(context.Database.Connection.ConnectionString)) - { - conn.Open(); - var cmd = new MySqlCommand(); - var entityName = (context.Permisos.GetType().FullName.Split(',')[0]).Substring(66).ToLowerInvariant(); - var contextName = context.GetType().Name.ToLowerInvariant(); - cmd.Connection = conn; - cmd.CommandText = - $"SELECT CONSTRAINT_NAME FROM information_schema.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_SCHEMA = '{contextName}' and TABLE_NAME = '{entityName}';"; - cmd.ExecuteNonQuery(); - - using (var reader = cmd.ExecuteReader()) - { - while (reader.Read()) - { - var val = reader.GetValue(0); - Assert.True(val.ToString().Contains("FK_")); - } - } - } - } - } - - [Test, Description("FK name ,longer than 64 chars are named to FK_")] - public void LongForeignKey() - { - using (var context = new ContextForLongFk()) - { - context.Database.Initialize(true); - var entityName = (context.Permisos.GetType().FullName.Split(',')[0]).Substring(66).ToLowerInvariant(); - var contextName = context.GetType().Name.ToLowerInvariant(); - using (MySqlConnection conn = new MySqlConnection(context.Database.Connection.ConnectionString)) - { - conn.Open(); - var cmd = new MySqlCommand(); - cmd.Connection = conn; - cmd.CommandText = - $"SELECT CONSTRAINT_NAME FROM information_schema.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_SCHEMA = '{contextName}' and TABLE_NAME = '{entityName}';"; - cmd.ExecuteNonQuery(); - - using (var reader = cmd.ExecuteReader()) - { - while (reader.Read()) - { - var val = reader.GetValue(0); - Assert.True(val.ToString().Contains("FK_")); - } - } - } - } - } - - [Test, Description("Verify that Null Reference Exception is not thrown when try to save entity with TINYINT AS PK ")] - public void SaveTinyIntAsPK() - { - using (var context = new ContextForTinyPk()) - { - context.Database.Delete(); - context.Database.Create(); - context.TinyPkUseRs.Add(new TinyPkUser - { - StringUserId = 1, - Name50 = "Juan", - Name100 = "100", - Name200 = "200", - Name300 = "300" - }); - - context.TinyPkUseRs.Add(new TinyPkUser - { - StringUserId = 2, - Name50 = "Pedro", - Name100 = "cien", - Name200 = "doscientos", - Name300 = "trescientos" - }); - - context.TinyPkUseRs.Add(new TinyPkUser - { - StringUserId = 3, - Name50 = "Lupe", - Name100 = "101", - Name200 = "cxvbx", - Name300 = "301" - }); - - context.TinyPkUseRs.Add(new TinyPkUser - { - StringUserId = 4, - Name50 = "Luis", - Name100 = "asdf", - Name200 = "wrwe", - Name300 = "xcvb" - }); - - context.TinyPkUseRs.Add(new TinyPkUser - { - StringUserId = 5, - Name50 = "Pepe", - Name100 = "asdf", - Name200 = "zxvz", - Name300 = "fgsd" - }); - context.SaveChanges(); - var query1 = context.TinyPkUseRs; - var query2 = query1.Take(0).Concat(query1); - var query3 = query1.Concat(query1.Take(0)); - Assert.True((query1.Count() == 5) & (query2.Count() == 5) & (query3.Count() == 5)); - } - } - - [Test, Description("Verify that Null Reference Exception is not thrown when try to save entity with BIGINT AS PK ")] - public void SaveBigIntAsPK() - { - using (var context = new ContextForBigIntPk()) - { - context.Database.Delete(); - context.Database.Create(); - context.BigIntPkUseRs.Add(new BigIntPkUser - { - StringUserId = 934157136952, - Name50 = "Juan", - Name100 = "100", - Name200 = "200", - Name300 = "300" - }); - - context.BigIntPkUseRs.Add(new BigIntPkUser - { - StringUserId = 934157136953, - Name50 = "Pedro", - Name100 = "cien", - Name200 = "doscientos", - Name300 = "trescientos" - }); - - context.BigIntPkUseRs.Add(new BigIntPkUser - { - StringUserId = 9223372036854775807, - Name50 = "Lupe", - Name100 = "101", - Name200 = "cxvbx", - Name300 = "301" - }); - - context.BigIntPkUseRs.Add(new BigIntPkUser - { - StringUserId = 0, - Name50 = "Luis", - Name100 = "asdf", - Name200 = "wrwe", - Name300 = "xcvb" - }); - - context.BigIntPkUseRs.Add(new BigIntPkUser - { - StringUserId = -9223372036854775808, - Name50 = "Pepe", - Name100 = "asdf", - Name200 = "zxvz", - Name300 = "fgsd" - }); - context.SaveChanges(); - var query1 = context.BigIntPkUseRs; - var query2 = query1.Take(0).Concat(query1); - var query3 = query1.Concat(query1.Take(0)); - Assert.True((query1.Count() == 5) & (query2.Count() == 5) & (query3.Count() == 5)); - } - } - - [Test, Description("TRANSACTION AFTER A FAILED TRANSACTION((USING BeginTransaction)) Commit")] - public void BeginTransNested() - { - using (var context = new EnumTestSupportContext()) - { - using (var trans = context.Database.BeginTransaction()) - { - Thread.Sleep(5000); - Assert.Catch(() => context.Database.ExecuteSqlCommand("update table schoolschedule")); - trans.Commit(); - } - using (var trans = context.Database.BeginTransaction()) - { - context.SchoolSchedules.Add(new SchoolSchedule - { - TeacherName = "Ruben", - Subject = SchoolSubject.History - }); - ; - - context.SchoolSchedules.Add(new SchoolSchedule - { - TeacherName = "Peter", - Subject = SchoolSubject.Chemistry - }); - ; - - context.SchoolSchedules.Add(new SchoolSchedule - { - TeacherName = "Juan", - Subject = SchoolSubject.Math - }); - ; - context.SaveChanges(); - trans.Commit(); - } - var count = context.SchoolSchedules.Count(); - Assert.AreEqual(3, count); - //Rollback - using (var trans = context.Database.BeginTransaction()) - { - Assert.Catch(() => context.Database.ExecuteSqlCommand("update table schoolschedule")); - trans.Rollback(); - } - using (var trans = context.Database.BeginTransaction()) - { - context.SchoolSchedules.Add(new SchoolSchedule - { - TeacherName = "Andrew", - Subject = SchoolSubject.History - }); ; - ; - context.SaveChanges(); - trans.Commit(); - } - count = context.SchoolSchedules.Count(); - Assert.AreEqual(4, count); - } - - } - - [Test, Description("TRANSACTION AFTER A FAILED TRANSACTION((USING BeginTransaction)) Stress Test")] - public void TransactionAfterFailStressTest() - { - for (var i = 0; i < 100; i++) - { - using (var context = new EnumTestSupportContext()) - { - using (var trans = context.Database.BeginTransaction()) - { - Assert.Catch(() => context.Database.ExecuteSqlCommand("update table schoolschedule")); - trans.Commit(); - } - using (var trans = context.Database.BeginTransaction()) - { - context.SchoolSchedules.Add(new SchoolSchedule - { - TeacherName = "Ruben", - Subject = SchoolSubject.History - }); - ; - - context.SchoolSchedules.Add(new SchoolSchedule - { - TeacherName = "Peter", - Subject = SchoolSubject.Chemistry - }); - ; - - context.SchoolSchedules.Add(new SchoolSchedule - { - TeacherName = "Juan", - Subject = SchoolSubject.Math - }); - context.SaveChanges(); - trans.Commit(); - var count = context.SchoolSchedules.Count(); - Assert.True(count > 0); - } - } - } - } - - - [Test, Description("Wrong SQL Statement to set primary key ")] - public void WrongSQLStatementPK() - { - using (var context = new EducationContext()) - { - context.Database.Delete(); - context.Database.Create(); - context.Passports.Add(new Passport { Key = 1 }); - context.SaveChanges(); - context.Database.ExecuteSqlCommand("ALTER TABLE `passports` CHANGE `Key` `Key1` int NOT NULL AUTO_INCREMENT UNIQUE"); - context.Database.ExecuteSqlCommand("ALTER TABLE `passports` DROP PRIMARY KEY"); - } - - using (var context = new EducationContext()) - { - context.Passports.Add(new Passport { Key = 1 }); - Exception ex = Assert.Catch(() => context.SaveChanges()); - context.Database.Delete(); - } - } - - /// - /// Bug #34498485 [MySQL.Data.EntityFramework does not handle LIKE (Edm.IndexOf) cases] - /// - [Test] - public void TestListMatchingLike() - { - using (VehicleDbContext2 context = new VehicleDbContext2()) - { - context.Database.Delete(); - context.Database.Initialize(true); - - context.Vehicles.Add(new Car2 { Id = 1, Name = "Mustang", Year = 2012, CarProperty = "Car" }); - context.Vehicles.Add(new Bike2 { Id = 101, Name = "Mountain", Year = 2011, BikeProperty = "Bike" }); - context.SaveChanges(); - - string[] matchText = new string[] { "must", "tan" }; - var list = context.Vehicles.Where(v => matchText.Any(t => v.Name.Contains(t))); - Assert.AreEqual(1, list.Count()); - - matchText = new string[] { "mus't", "tan" }; - list = context.Vehicles.Where(v => matchText.Any(t => v.Name.Contains(t))); - Assert.AreEqual(1, list.Count()); - - matchText = new string[] { "%" }; - list = context.Vehicles.Where(v => matchText.Any(t => v.Name.Contains(t))); - Assert.AreEqual(0, list.Count()); - - matchText = new string[] { "tan" }; - list = context.Vehicles.Where(v => matchText.Any(t => v.Name.Contains(t))); - Assert.AreEqual(1, list.Count()); - - matchText = new string[] { "_" }; - list = context.Vehicles.Where(v => matchText.Any(t => v.Name.Contains(t))); - Assert.AreEqual(0, list.Count()); - } - } - } -} \ No newline at end of file +// Copyright © 2014, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySql.Data.EntityFramework.Tests; +using MySql.Data.MySqlClient; +using MySql.EntityFramework.CodeFirst.Tests; +using MySql.EntityFramework.CodeFirst.Tests.Properties; +using NUnit.Framework; +using System; +using System.Collections.Generic; +using System.Data; +using System.Data.Entity; +using System.Data.Entity.Infrastructure; +using System.Data.Entity.Spatial; +using System.Diagnostics; +using System.Linq; +using System.Text.RegularExpressions; +using System.Threading; + +namespace MySql.Data.EntityFramework.CodeFirst.Tests +{ + public class CodeFirstTests : CodeFirstFixture + { + /// + /// Tests for fix of http://bugs.mysql.com/bug.php?id=61230 + /// ("The provider did not return a ProviderManifestToken string."). + /// + [Test] + public void SimpleCodeFirstSelect() + { +#if DEBUG + Debug.WriteLine(new StackTrace().GetFrame(0).GetMethod().Name); +#endif + MovieDBContext db = new MovieDBContext(); + db.Database.Initialize(true); + MovieDBInitialize.DoDataPopulation(db); + var l = db.Movies.ToList(); + int j = l.Count; + foreach (var i in l) + { + j--; + } + Assert.AreEqual(0, j); + } + + /// + /// Tests for fix of http://bugs.mysql.com/bug.php?id=62150 + /// ("EF4.1, Code First, CreateDatabaseScript() generates an invalid MySQL script."). + /// + [Test] + public void AlterTableTest() + { +#if DEBUG + Debug.WriteLine(new StackTrace().GetFrame(0).GetMethod().Name); +#endif + MovieDBContext db = new MovieDBContext(); + db.Database.Initialize(true); + MovieDBInitialize.DoDataPopulation(db); + var l = db.MovieFormats.ToList(); + int j = l.Count; + foreach (var i in l) + { + j--; + } + Assert.AreEqual(0, j); + MovieFormat m = new MovieFormat(); + m.Format = 8.0f; + db.MovieFormats.Add(m); + db.SaveChanges(); + MovieFormat m2 = db.MovieFormats.Where(p => p.Format == 8.0f).FirstOrDefault(); + Assert.NotNull(m2); + Assert.AreEqual(8.0f, m2.Format); + } + + /// + /// Fix for "Connector/Net Generates Incorrect SELECT Clause after UPDATE" (MySql bug #62134, Oracle bug #13491689). + /// + [Test] + public void ConcurrencyCheckWithNonDbGeneratedColumn() + { +#if DEBUG + Debug.WriteLine(new StackTrace().GetFrame(0).GetMethod().Name); +#endif + using (MovieDBContext db = new MovieDBContext()) + { + db.Database.Delete(); + db.Database.CreateIfNotExists(); + MovieDBInitialize.DoDataPopulation(db); + db.Database.ExecuteSqlCommand(@"DROP TABLE IF EXISTS `MovieReleases`"); + + db.Database.ExecuteSqlCommand( +@"CREATE TABLE IF NOT EXISTS `MovieReleases` ( + `Id` int(11) NOT NULL, + `Name` varbinary(45) NOT NULL, + `Timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (`Id`) +) ENGINE=InnoDB DEFAULT CHARSET=binary"); + MySqlTrace.Listeners.Clear(); + MySqlTrace.Switch.Level = SourceLevels.All; + GenericListener listener = new GenericListener(); + MySqlTrace.Listeners.Add(listener); + try + { + MovieRelease mr = db.MovieReleases.Create(); + mr.Id = 1; + mr.Name = "Commercial"; + db.MovieReleases.Add(mr); + db.SaveChanges(); + mr.Name = "Director's Cut"; + db.SaveChanges(); + } + finally + { + db.Database.ExecuteSqlCommand(@"DROP TABLE IF EXISTS `MovieReleases`"); + } + // Check sql + Regex rx = new Regex(@"Query Opened: (?UPDATE .*)", RegexOptions.Compiled | RegexOptions.Singleline); + foreach (string s in listener.Strings) + { + Match m = rx.Match(s); + if (m.Success) + { + CheckSql(m.Groups["item"].Value, SQLSyntax.UpdateWithSelectWithNonDbGeneratedLock); + //Assert.Pass(); + } + } + //Assert.Fail(); + } + } + + /// + /// This tests fix for http://bugs.mysql.com/bug.php?id=64216. + /// + [Test] + public void CheckByteArray() + { +#if DEBUG + Debug.WriteLine(new StackTrace().GetFrame(0).GetMethod().Name); +#endif + MovieDBContext db = new MovieDBContext(); + db.Database.Initialize(true); + string dbCreationScript = + ((IObjectContextAdapter)db).ObjectContext.CreateDatabaseScript(); + Regex rx = new Regex(@"`Data` (?[^\),]*)", RegexOptions.Compiled | RegexOptions.Singleline); + Match m = rx.Match(dbCreationScript); + Assert.AreEqual("longblob", m.Groups["type"].Value); + } + + /// + /// Validates a stored procedure call using Code First + /// Bug #14008699 + [Test] + public void CallStoredProcedure() + { +#if DEBUG + Debug.WriteLine(new StackTrace().GetFrame(0).GetMethod().Name); +#endif + using (MovieDBContext context = new MovieDBContext()) + { + context.Database.Initialize(true); + context.Database.ExecuteSqlCommand(@"drop procedure if exists `GetCount`"); + context.Database.ExecuteSqlCommand(@"create procedure `GetCount`() begin select 5; end;"); + long count = context.Database.SqlQuery("call GetCount").First(); + + Assert.AreEqual(5, count); + } + } + + /// + /// Tests for fix of http://bugs.mysql.com/bug.php?id=63920 + /// Maxlength error when it's used code-first and inheritance (discriminator generated column) + /// + [Test] + public void Bug63920_Test1() + { +#if DEBUG + Debug.WriteLine(new StackTrace().GetFrame(0).GetMethod().Name); +#endif + using (VehicleDbContext context = new VehicleDbContext()) + { + context.Database.Delete(); + context.Database.Initialize(true); + + context.Vehicles.Add(new Car { Id = 1, Name = "Mustang", Year = 2012, CarProperty = "Car" }); + context.Vehicles.Add(new Bike { Id = 101, Name = "Mountain", Year = 2011, BikeProperty = "Bike" }); + context.SaveChanges(); + + var list = context.Vehicles.ToList(); + + int records = -1; + using (MySqlConnection conn = new MySqlConnection(context.Database.Connection.ConnectionString)) + { + conn.Open(); + MySqlCommand cmd = new MySqlCommand("SELECT COUNT(*) FROM Vehicles", conn); + records = Convert.ToInt32(cmd.ExecuteScalar()); + } + + Assert.AreEqual(context.Vehicles.Count(), records); + } + } + + /// + /// Tests for fix of http://bugs.mysql.com/bug.php?id=63920 + /// Key reference generation script error when it's used code-first and a single table for the inherited models + /// + [Test] + public void Bug63920_Test2() + { +#if DEBUG + Debug.WriteLine(new StackTrace().GetFrame(0).GetMethod().Name); +#endif + using (VehicleDbContext2 context = new VehicleDbContext2()) + { + context.Database.Delete(); + context.Database.Initialize(true); + + context.Vehicles.Add(new Car2 { Id = 1, Name = "Mustang", Year = 2012, CarProperty = "Car" }); + context.Vehicles.Add(new Bike2 { Id = 101, Name = "Mountain", Year = 2011, BikeProperty = "Bike" }); + context.SaveChanges(); + + var list = context.Vehicles.ToList(); + + int records = -1; + using (MySqlConnection conn = new MySqlConnection(context.Database.Connection.ConnectionString)) + { + conn.Open(); + MySqlCommand cmd = new MySqlCommand("SELECT COUNT(*) FROM Vehicle2", conn); + records = Convert.ToInt32(cmd.ExecuteScalar()); + } + + Assert.AreEqual(context.Vehicles.Count(), records); + } + } + + /// + /// This test fix for precision customization for columns bug (http://bugs.mysql.com/bug.php?id=65001), + /// Trying to customize column precision in Code First does not work). + /// + [Test] + [Ignore("Fix this")] + public void TestPrecisionNscale() + { +#if DEBUG + Debug.WriteLine(new StackTrace().GetFrame(0).GetMethod().Name); +#endif + MovieDBContext db = new MovieDBContext(); + db.Database.Initialize(true); + var l = db.Movies.ToList(); + using (MySqlDataReader r = new MySqlCommand($@"select numeric_precision, numeric_scale from information_schema.columns +where table_schema = '{Connection.Database}' and table_name = 'movies' and column_name = 'Price'", Connection).ExecuteReader()) + { + r.Read(); + Assert.AreEqual(16, r.GetInt32(0)); + Assert.AreEqual(2, r.GetInt32(1)); + } + } + + /// + /// Test String types to StoreType for String + /// A string with FixedLength=true will become a char + /// Max Length left empty will be char(max) + /// Max Length(100) will be char(100) + /// while FixedLength=false will result in nvarchar. + /// Max Length left empty will be nvarchar(max) + /// Max Length(100) will be nvarchar(100) + /// + [Test] + public void TestStringTypeToStoreType() + { +#if DEBUG + Debug.WriteLine(new StackTrace().GetFrame(0).GetMethod().Name); +#endif + using (VehicleDbContext3 context = new VehicleDbContext3()) + { + if (context.Database.Exists()) context.Database.Delete(); + context.Database.CreateIfNotExists(); + context.Accessories.Add(new Accessory { Name = "Accesory One", Description = "Accesories descriptions", LongDescription = "Some long description" }); + context.SaveChanges(); + + using (MySqlConnection conn = new MySqlConnection(context.Database.Connection.ConnectionString)) + { + conn.Open(); + MySqlCommand query = new MySqlCommand("Select Column_name, Is_Nullable, Data_Type from information_schema.Columns where table_schema ='" + conn.Database + "' and table_name = 'Accessories' and column_name ='Description'", conn); + query.Connection = conn; + MySqlDataReader reader = query.ExecuteReader(); + while (reader.Read()) + { + Assert.AreEqual("Description", reader[0].ToString()); + Assert.AreEqual("NO", reader[1].ToString()); + Assert.AreEqual("mediumtext", reader[2].ToString()); + } + reader.Close(); + + query = new MySqlCommand("Select Column_name, Is_Nullable, Data_Type, character_maximum_length from information_schema.Columns where table_schema ='" + conn.Database + "' and table_name = 'Accessories' and column_name ='Name'", conn); + reader = query.ExecuteReader(); + while (reader.Read()) + { + Assert.AreEqual("Name", reader[0].ToString()); + Assert.AreEqual("NO", reader[1].ToString()); + Assert.AreEqual("varchar", reader[2].ToString()); + Assert.AreEqual("255", reader[3].ToString()); + } + reader.Close(); + + query = new MySqlCommand("Select Column_name, Is_Nullable, Data_Type, character_maximum_length from information_schema.Columns where table_schema ='" + conn.Database + "' and table_name = 'Accessories' and column_name ='LongDescription'", conn); + reader = query.ExecuteReader(); + while (reader.Read()) + { + Assert.AreEqual("LongDescription", reader[0].ToString()); + Assert.AreEqual("NO", reader[1].ToString()); + Assert.AreEqual("longtext", reader[2].ToString()); + Assert.AreEqual("4294967295", reader[3].ToString()); + } + } + } + } + + /// + /// Test fix for http://bugs.mysql.com/bug.php?id=66066 / http://clustra.no.oracle.com/orabugs/bug.php?id=14479715 + /// (Using EF, crash when generating insert with no values.). + /// + [Test] + public void AddingEmptyRow() + { +#if DEBUG + Debug.WriteLine(new StackTrace().GetFrame(0).GetMethod().Name); +#endif + using (MovieDBContext ctx = new MovieDBContext()) + { + ctx.Database.Initialize(true); + ctx.EntitySingleColumns.Add(new EntitySingleColumn()); + ctx.SaveChanges(); + } + + using (MovieDBContext ctx2 = new MovieDBContext()) + { + var q = from esc in ctx2.EntitySingleColumns where esc.Id == 1 select esc; + Assert.AreEqual(1, q.Count()); + } + } + + /// + /// Test for identity columns when type is Integer or Guid (auto-generate + /// values) + /// + [Test] + public void IdentityTest() + { +#if DEBUG + Debug.WriteLine(new StackTrace().GetFrame(0).GetMethod().Name); +#endif + using (VehicleDbContext context = new VehicleDbContext()) + { + context.Database.ExecuteSqlCommand("SET GLOBAL sql_mode='STRICT_ALL_TABLES'"); + if (context.Database.Exists()) context.Database.Delete(); + context.Database.CreateIfNotExists(); + + // Identity as Guid + Manufacturer nissan = new Manufacturer + { + Name = "Nissan" + }; + Manufacturer ford = new Manufacturer + { + Name = "Ford" + }; + context.Manufacturers.Add(nissan); + context.Manufacturers.Add(ford); + + // Identity as Integer + Distributor dis1 = new Distributor + { + Name = "Distributor1" + }; + Distributor dis2 = new Distributor + { + Name = "Distributor2" + }; + context.Distributors.Add(dis1); + context.Distributors.Add(dis2); + + context.SaveChanges(); + + using (MySqlConnection conn = new MySqlConnection(context.Database.Connection.ConnectionString)) + { + conn.Open(); + + // Validates Guid + MySqlCommand cmd = new MySqlCommand("SELECT * FROM Manufacturers", conn); + MySqlDataReader dr = cmd.ExecuteReader(); + Assert.False(!dr.HasRows, "No records found"); + + while (dr.Read()) + { + string name = dr.GetString(1); + switch (name) + { + case "Nissan": + Assert.AreEqual(dr.GetGuid(0), nissan.ManufacturerId); + Assert.AreEqual(dr.GetGuid(2), nissan.GroupIdentifier); + break; + case "Ford": + Assert.AreEqual(dr.GetGuid(0), ford.ManufacturerId); + Assert.AreEqual(dr.GetGuid(2), ford.GroupIdentifier); + break; + default: + //Assert.Fail(); + break; + } + } + dr.Close(); + + // Validates Integer + cmd = new MySqlCommand("SELECT * FROM Distributors", conn); + dr = cmd.ExecuteReader(); + if (!dr.HasRows) + //Assert.Fail("No records found"); + while (dr.Read()) + { + string name = dr.GetString(1); + switch (name) + { + case "Distributor1": + Assert.AreEqual(dr.GetInt32(0), dis1.DistributorId); + break; + case "Distributor2": + Assert.AreEqual(dr.GetInt32(0), dis2.DistributorId); + break; + default: + //Assert.Fail(); + break; + } + } + dr.Close(); + } + } + } + + /// + /// This test the fix for bug 67377. + /// + [Test] + public void FirstOrDefaultNested() + { +#if DEBUG + Debug.WriteLine(new StackTrace().GetFrame(0).GetMethod().Name); +#endif + using (MovieDBContext ctx = new MovieDBContext()) + { + ctx.Database.Initialize(true); + MovieDBInitialize.DoDataPopulation(ctx); + int DirectorId = 1; + var q = ctx.Movies.Where(p => p.Director.ID == DirectorId).Select(p => + new + { + Id = p.ID, + FirstMovieFormat = p.Formats.Count == 0 ? 0.0 : p.Formats.FirstOrDefault().Format + }); + string sql = q.ToString(); +#if DEBUG + Debug.WriteLine(sql); +#endif + int j = q.Count(); + foreach (var r in q) + { + j--; + } + Assert.AreEqual(0, j); + } + } + + /// + /// This tests the fix for bug 73549, Generated Sql does not contain ORDER BY statement whose is requested by LINQ. + /// + [Test] + public void FirstOrDefaultNestedWithOrderBy() + { +#if DEBUG + Debug.WriteLine(new StackTrace().GetFrame(0).GetMethod().Name); +#endif + using (SakilaDb db = new SakilaDb()) + { + var q = from cu in db.customers + let curAddr = db.addresses.OrderByDescending(p => p.address_id).Where(p => p.address_id == cu.address_id).FirstOrDefault() + join sto in db.stores on cu.store_id equals sto.store_id + orderby cu.customer_id descending + select new + { + curAddr.city.country.country1 + }; + string sql = q.ToString(); + CheckSql(sql, SQLSyntax.FirstOrDefaultNestedWithOrderBy); +#if DEBUG + Debug.WriteLine(sql); +#endif + int j = q.Count(); + foreach (var r in q) + { + //Debug.WriteLine( r.country1 ); + } + Assert.AreEqual(599, j); + } + } + + /// + /// SUPPORT FOR DATE TYPES WITH PRECISION + /// + [Test] + public void CanDefineDatesWithPrecisionFor56() + { +#if DEBUG + Debug.WriteLine(new StackTrace().GetFrame(0).GetMethod().Name); +#endif + + if (Version < new Version(5, 6)) return; + + using (var db = new ProductsDbContext()) + { + db.Database.Initialize(true); + using (MySqlConnection conn = new MySqlConnection(db.Database.Connection.ConnectionString)) + { + conn.Open(); + MySqlCommand query = new MySqlCommand("Select Column_name, Is_Nullable, Data_Type, DateTime_Precision from information_schema.Columns where table_schema ='" + conn.Database + "' and table_name = 'Products' and column_name ='DateTimeWithPrecision'", conn); + query.Connection = conn; + MySqlDataReader reader = query.ExecuteReader(); + while (reader.Read()) + { + Assert.AreEqual("DateTimeWithPrecision", reader[0].ToString()); + Assert.AreEqual("NO", reader[1].ToString()); + Assert.AreEqual("datetime", reader[2].ToString()); + Assert.AreEqual("3", reader[3].ToString()); + } + reader.Close(); + + query = new MySqlCommand("Select Column_name, Is_Nullable, Data_Type, DateTime_Precision from information_schema.Columns where table_schema ='" + conn.Database + "' and table_name = 'Products' and column_name ='TimeStampWithPrecision'", conn); + query.Connection = conn; + reader = query.ExecuteReader(); + while (reader.Read()) + { + Assert.AreEqual("TimeStampWithPrecision", reader[0].ToString()); + Assert.AreEqual("NO", reader[1].ToString()); + Assert.AreEqual("timestamp", reader[2].ToString()); + Assert.AreEqual("3", reader[3].ToString()); + } + reader.Close(); + } + db.Database.Delete(); + } + } + + /// + /// Orabug #15935094 SUPPORT FOR CURRENT_TIMESTAMP AS DEFAULT FOR DATETIME WITH EF + /// + [Test] + [Ignore("Fix this")] + public void CanDefineDateTimeAndTimestampWithIdentity() + { +#if DEBUG + Debug.WriteLine(new StackTrace().GetFrame(0).GetMethod().Name); +#endif + if (Version < new Version(5, 6)) return; + + using (var db = new ProductsDbContext()) + { + db.Database.Initialize(true); + MySqlConnection con = (MySqlConnection)db.Database.Connection; + MySqlCommand cmd = new MySqlCommand("set session sql_mode = '';", con); + con.Open(); + cmd.ExecuteNonQuery(); + con.Close(); + + Product product = new Product + { + //Omitting Identity Columns + DateTimeWithPrecision = DateTime.Now, + TimeStampWithPrecision = DateTime.Now + }; + + db.Products.Add(product); + db.SaveChanges(); + + var updateProduct = db.Products.First(); + updateProduct.DateTimeWithPrecision = new DateTime(2012, 3, 18, 23, 9, 7, 6); + db.SaveChanges(); + + Assert.NotNull(db.Products.First().Timestamp); + Assert.NotNull(db.Products.First().DateCreated); + Assert.AreEqual(new DateTime(2012, 3, 18, 23, 9, 7, 6), db.Products.First().DateTimeWithPrecision); + Assert.AreEqual(1, db.Products.Count()); + db.Database.Delete(); + } + } + + + /// + /// Test of fix for bug Support for EntityFramework 4.3 Code First Generated Identifiers (MySql Bug #67285, Oracle bug #16286397). + /// FKs are renamed to met http://dev.mysql.com/doc/refman/5.0/en/identifiers.html limitations. + /// + [Test] + public void LongIdentifiersInheritanceTPT() + { +#if DEBUG + Debug.WriteLine(new StackTrace().GetFrame(0).GetMethod().Name); +#endif + using (DinosauriaDBContext db = new DinosauriaDBContext()) + { + db.Database.Initialize(true); + Tyrannosauridae ty = new Tyrannosauridae() { Id = 1, Name = "Genghis Rex", SpecieName = "TRex", Weight = 1000 }; + db.dinos.Add(ty); + Oviraptorosauria ovi = new Oviraptorosauria() { Id = 2, EggsPerYear = 100, Name = "John the Velociraptor", SpecieName = "Oviraptor" }; + db.dinos.Add(ovi); + db.SaveChanges(); + } + } + + + /// + /// Test fix for http://bugs.mysql.com/bug.php?id=67183 + /// (Malformed Query while eager loading with EF 4 due to multiple projections). + /// + [Test] + public void ShipTest() + { +#if DEBUG + Debug.WriteLine(new StackTrace().GetFrame(0).GetMethod().Name); +#endif + using (var context = new ShipContext()) + { + context.Database.Initialize(true); + + var harbor = new Harbor + { + Ships = new HashSet + { + new Ship + { + CrewMembers = new HashSet + { + new CrewMember + { + Rank = new Rank { Description = "Rank A" }, + Clearance = new Clearance { Description = "Clearance A" }, + Description = "CrewMember A" + }, + new CrewMember + { + Rank = new Rank { Description = "Rank B" }, + Clearance = new Clearance { Description = "Clearance B" }, + Description = "CrewMember B" + } + }, + Description = "Ship AB" + }, + new Ship + { + CrewMembers = new HashSet + { + new CrewMember + { + Rank = new Rank { Description = "Rank C" }, + Clearance = new Clearance { Description = "Clearance C" }, + Description = "CrewMember C" + }, + new CrewMember + { + Rank = new Rank { Description = "Rank D" }, + Clearance = new Clearance { Description = "Clearance D" }, + Description = "CrewMember D" + } + }, + Description = "Ship CD" + } + }, + Description = "Harbor ABCD" + }; + + context.Harbors.Add(harbor); + context.SaveChanges(); + } + + using (var context = new ShipContext()) + { + DbSet dbSet = context.Set(); + IQueryable query = dbSet; + query = query.Include(entity => entity.Ships); + query = query.Include(entity => entity.Ships.Select(s => s.CrewMembers)); + query = query.Include(entity => entity.Ships.Select(s => s.CrewMembers.Select(cm => cm.Rank))); + query = query.Include(entity => entity.Ships.Select(s => s.CrewMembers.Select(cm => cm.Clearance))); + + string[] data = new string[] { + "1,Harbor ABCD,1,1,1,Ship AB,1,1,1,1,1,CrewMember A,1,Rank A,1,Clearance A", + "1,Harbor ABCD,1,1,1,Ship AB,1,2,1,2,2,CrewMember B,2,Rank B,2,Clearance B", + "1,Harbor ABCD,1,2,1,Ship CD,1,3,2,3,3,CrewMember C,3,Rank C,3,Clearance C", + "1,Harbor ABCD,1,2,1,Ship CD,1,4,2,4,4,CrewMember D,4,Rank D,4,Clearance D" + }; + Dictionary outData = new Dictionary(); + + var sqlString = query.ToString(); + CheckSql(sqlString, SQLSyntax.ShipQueryMalformedDueMultipleProjecttionsCorrectedEF6); + // see below for the generated SQL query + + var harbor = query.Single(); + + foreach (var ship in harbor.Ships) + { + foreach (var crewMember in ship.CrewMembers) + { + outData.Add(string.Format( + "{0},{1},1,{2},{3},{4},1,{5},{6},{7},{8},{9},{10},{11},{12},{13}", + harbor.HarborId, harbor.Description, ship.ShipId, harbor.HarborId, + ship.Description, crewMember.CrewMemberId, crewMember.ShipId, crewMember.RankId, + crewMember.ClearanceId, crewMember.Description, crewMember.Rank.RankId, + crewMember.Rank.Description, crewMember.Clearance.ClearanceId, + crewMember.Clearance.Description), null); + } + } + // check data integrity + Assert.AreEqual(outData.Count, data.Length); + for (int i = 0; i < data.Length; i++) + { + Assert.True(outData.ContainsKey(data[i])); + } + } + } + + /// + /// Tests fix for bug http://bugs.mysql.com/bug.php?id=68513, Error in LINQ to Entities query when using Distinct().Count(). + /// + [Test] + public void DistinctCount() + { +#if DEBUG + Debug.WriteLine(new StackTrace().GetFrame(0).GetMethod().Name); +#endif + using (SiteDbContext ctx = new SiteDbContext()) + { + ctx.Database.Initialize(true); + visitante v1 = new visitante() { nCdSite = 1, nCdVisitante = 1, sDsIp = "x1" }; + visitante v2 = new visitante() { nCdSite = 1, nCdVisitante = 2, sDsIp = "x2" }; + site s1 = new site() { nCdSite = 1, sDsTitulo = "MyNewsPage" }; + site s2 = new site() { nCdSite = 2, sDsTitulo = "MySearchPage" }; + ctx.Visitante.Add(v1); + ctx.Visitante.Add(v2); + ctx.Site.Add(s1); + ctx.Site.Add(s2); + ctx.SaveChanges(); + + var q = (from vis in ctx.Visitante.Include("site") + group vis by vis.nCdSite into g + select new retorno + { + Key = g.Key, + Online = g.Select(e => e.sDsIp).Distinct().Count() + }); + string sql = q.ToString(); + CheckSql(sql, SQLSyntax.CountGroupBy); + var q2 = q.ToList(); + foreach (var row in q2) + { + } + } + } + + /// + /// Tests fix for bug http://bugs.mysql.com/bug.php?id=68513, Error in LINQ to Entities query when using Distinct().Count(). + /// + [Test] + public void DistinctCount2() + { +#if DEBUG + Debug.WriteLine(new StackTrace().GetFrame(0).GetMethod().Name); +#endif + using (SiteDbContext ctx = new SiteDbContext()) + { + ctx.Database.Initialize(true); + visitante v1 = new visitante() { nCdSite = 1, nCdVisitante = 1, sDsIp = "x1" }; + visitante v2 = new visitante() { nCdSite = 1, nCdVisitante = 2, sDsIp = "x2" }; + site s1 = new site() { nCdSite = 1, sDsTitulo = "MyNewsPage" }; + site s2 = new site() { nCdSite = 2, sDsTitulo = "MySearchPage" }; + pagina p1 = new pagina() { nCdPagina = 1, nCdVisitante = 1, sDsTitulo = "index.html" }; + ctx.Visitante.Add(v1); + ctx.Visitante.Add(v2); + ctx.Site.Add(s1); + ctx.Site.Add(s2); + ctx.Pagina.Add(p1); + ctx.SaveChanges(); + + var q = (from pag in ctx.Pagina.Include("visitante").Include("site") + group pag by pag.visitante.nCdSite into g + select new retorno + { + Key = g.Key, + Online = g.Select(e => e.visitante.sDsIp).Distinct().Count() + }); + string sql = q.ToString(); + CheckSql(sql, SQLSyntax.CountGroupBy2); + var q2 = q.ToList(); + foreach (var row in q2) + { + } + } + } + + /// + /// Tests fix for bug http://bugs.mysql.com/bug.php?id=65723, MySql Provider for EntityFramework produces "bad" SQL for OrderBy. + /// + [Test] + public void BadOrderBy() + { +#if DEBUG + Debug.WriteLine(new StackTrace().GetFrame(0).GetMethod().Name); +#endif + using (MovieDBContext db = new MovieDBContext()) + { + db.Database.Initialize(true); + MovieDBInitialize.DoDataPopulation(db); + DateTime filterDate = new DateTime(1986, 1, 1); + var q = db.Movies.Where(p => p.ReleaseDate >= filterDate). + OrderByDescending(p => p.ReleaseDate).Take(2); + string sql = q.ToString(); + CheckSql(SQLSyntax.NestedOrderBy, sql); + // Data integrity testing + Movie[] data = new Movie[] { + new Movie() { ID = 4, Title = "Star Wars, The Sith Revenge", ReleaseDate = new DateTime( 2005, 5, 19 ) }, + new Movie() { ID = 2, Title = "The Matrix", ReleaseDate = new DateTime( 1999, 3, 31 ) } + }; + int i = 0; + foreach (Movie m in q) + { + Assert.AreEqual(data[i].ID, m.ID); + Assert.AreEqual(data[i].Title, m.Title); + Assert.AreEqual(data[i].ReleaseDate, m.ReleaseDate); + i++; + } + Assert.AreEqual(2, i); + } + } + + /// + /// Tests fix for bug http://bugs.mysql.com/bug.php?id=69751, Invalid SQL query generated for query with Contains, OrderBy, and Take. + /// + [Test] + public void BadContainsOrderByTake() + { +#if DEBUG + Debug.WriteLine(new StackTrace().GetFrame(0).GetMethod().Name); +#endif + using (MovieDBContext db = new MovieDBContext()) + { + db.Database.Initialize(true); + MovieDBInitialize.DoDataPopulation(db); + string title = "T"; + var q = from m in db.Movies + where m.Title.Contains(title) + orderby m.ID descending + select m; + var q1 = q.Take(10); + string sql = q1.ToString(); + + CheckSql(SQLSyntax.QueryWithOrderByTakeContains, sql); + + int i = 0; + foreach (var row in q1) + { + Assert.AreEqual(MovieDBInitialize.data[i].ID, row.ID); + Assert.AreEqual(MovieDBInitialize.data[i].Title, row.Title); + Assert.AreEqual(MovieDBInitialize.data[i].ReleaseDate, row.ReleaseDate); + i++; + } + } + } + + /// + /// Tests fix for bug http://bugs.mysql.com/bug.php?id=69922, Unknown column Extent1... + /// + [Test] + public void BadAliasTable() + { +#if DEBUG + Debug.WriteLine(new StackTrace().GetFrame(0).GetMethod().Name); +#endif + using (PromotionsDB db = new PromotionsDB()) + { + db.Database.Initialize(true); + DateTime now = DateTime.Now; + var q = db + .HomePromoes + .Where(x => + x.Active + && + (x.ActiveFrom == null || x.ActiveFrom <= now) + && + (x.ActiveTo == null || x.ActiveTo >= now) + ) + .OrderBy(x => x.DisplayOrder).Select(d => d); + string sql = q.ToString(); + foreach (var row in q) + { + } + } + } + + /// + /// Tests other variants of bug http://bugs.mysql.com/bug.php?id=69751, Invalid SQL query generated for query with Contains, OrderBy, and Take. + /// + [Test] + public void BadContainsOrderByTake2() + { +#if DEBUG + Debug.WriteLine(new StackTrace().GetFrame(0).GetMethod().Name); +#endif + using (MovieDBContext db = new MovieDBContext()) + { + db.Database.Initialize(true); + MovieDBInitialize.DoDataPopulation(db); + var q = db.Movies. + Where(m => !string.IsNullOrEmpty(m.Title) && m.Title.Contains("x")). + OrderByDescending(m => m.ID). + Skip(1). + Take(1); + string sql = q.ToString(); +#if DEBUG + Debug.WriteLine(sql); +#endif + List l = q.ToList(); + int j = l.Count; + foreach (Movie m in l) + { + j--; + } + Assert.AreEqual(0, j); + } + } + + /// + /// Tests other variants of bug http://bugs.mysql.com/bug.php?id=69751, Invalid SQL query generated for query with Contains, OrderBy, and Take. + /// + [Test] + public void BadContainsOrderByTake3() + { +#if DEBUG + Debug.WriteLine(new StackTrace().GetFrame(0).GetMethod().Name); +#endif + using (MovieDBContext db = new MovieDBContext()) + { + db.Database.Initialize(true); + MovieDBInitialize.DoDataPopulation(db); + var q = db.Movies. + Where(m => !string.IsNullOrEmpty(m.Title) && m.Title.Contains("x")). + OrderByDescending(m => m.ID). + Skip(1). + Take(1).Select(m => new + { + Id = m.ID, + CriticsScore = ( + m.Title == "Terminator 1" ? "Good" : + m.Title == "Predator" ? "Sunday best, cheese" : + m.Title == "The Matrix" ? "Really Good" : + m.Title == "Star Wars, The Sith Revenge" ? "Really Good" : "Unknown") + }); + string sql = q.ToString(); +#if DEBUG + Debug.WriteLine(sql); +#endif + int j = q.Count(); + foreach (var row in q) + { + j--; + } + Assert.AreEqual(0, j); + } + } + + /// + /// Tests other variants of bug http://bugs.mysql.com/bug.php?id=69751, Invalid SQL query generated for query with Contains, OrderBy, and Take. + /// + [Test] + public void BadContainsOrderByTake4() + { +#if DEBUG + Debug.WriteLine(new StackTrace().GetFrame(0).GetMethod().Name); +#endif + using (MovieDBContext db = new MovieDBContext()) + { + db.Database.Initialize(true); + MovieDBInitialize.DoDataPopulation(db); + bool q = db.Movies.Any(m => m.ReleaseDate.Year > 1985); + // string sql = q.ToString(); + //#if DEBUG + // Debug.WriteLine(sql); + //#endif + //foreach (var row in q) + //{ + //} + } + } + + /// + /// Tests other variants of bug http://bugs.mysql.com/bug.php?id=69751, Invalid SQL query generated for query with Contains, OrderBy, and Take. + /// + [Test] + public void BadContainsOrderByTake5() + { +#if DEBUG + Debug.WriteLine(new StackTrace().GetFrame(0).GetMethod().Name); +#endif + using (MovieDBContext db = new MovieDBContext()) + { + db.Database.Initialize(true); + MovieDBInitialize.DoDataPopulation(db); + // TODO: add subquery like + // var shifts = Shifts.Where(s => !EmployeeShifts.Where(es => es.ShiftID == s.ShiftID).Any()); + bool q = db.Movies.Where(m => m.ReleaseDate.Month != 10).Any(m => m.ReleaseDate.Year > 1985); + // string sql = q.ToString(); + //#if DEBUG + // Debug.WriteLine(sql); + //#endif + // foreach (var row in q) + // { + // } + } + } + + /// + /// Tests other variants of bug http://bugs.mysql.com/bug.php?id=69751, Invalid SQL query generated for query with Contains, OrderBy, and Take. + /// + [Test] + public void BadContainsOrderByTake6() + { +#if DEBUG + Debug.WriteLine(new StackTrace().GetFrame(0).GetMethod().Name); +#endif + using (MovieDBContext db = new MovieDBContext()) + { + db.Database.Initialize(true); + MovieDBInitialize.DoDataPopulation(db); + var q = from m in db.Movies + where m.Title.Contains("x") && db.Medias.Where(mm => mm.Format == "Digital").Any() + select m; + string sql = q.ToString(); +#if DEBUG + Debug.WriteLine(sql); +#endif + int j = q.Count(); + foreach (var row in q) + { + j--; + } + Assert.AreEqual(0, j); + } + } + + /// + /// Test for Mysql Bug 70602: http://bugs.mysql.com/bug.php?id=70602 + /// + [Test] + public void AutoIncrementBug() + { +#if DEBUG + Debug.WriteLine(new StackTrace().GetFrame(0).GetMethod().Name); +#endif + AutoIncrementBugContext dbContext = new AutoIncrementBugContext(); + + dbContext.Database.Initialize(true); + dbContext.AutoIncrementBug.Add(new AutoIncrementBug() { Description = "Test" }); + dbContext.SaveChanges(); + using (var reader = MySqlHelper.ExecuteReader(dbContext.Database.Connection.ConnectionString, + $"SHOW COLUMNS FROM {nameof(dbContext.AutoIncrementBug)}s WHERE UPPER(EXTRA) LIKE '%AUTO_INCREMENT%'")) + { + Assert.True(reader.HasRows); + } + dbContext.Database.Delete(); + } + + [Test] + public void SimpleCodeFirstSelectCbc() + { + MovieCodedBasedConfigDBContext db = new MovieCodedBasedConfigDBContext(); + db.Database.Initialize(true); + var l = db.Movies.ToList(); + foreach (var i in l) + { + Console.WriteLine(i); + } + } + + [Test] + [Ignore("Need to check. Bad statemen: CALL `MovieCodedBasedConfigDBContext`.``insert_movie``(@movie_name, @ReleaseDate, @Genre, @Price)")] + public void TestStoredProcedureMapping() + { + using (var db = new MovieCodedBasedConfigDBContext()) + { + db.Database.Initialize(true); + var movie = new MovieCBC() + { + Title = "Sharknado", + Genre = "Documental", + Price = 1.50M, + ReleaseDate = DateTime.Parse("01/07/2013") + }; + + db.Movies.Add(movie); + db.SaveChanges(); + movie.Genre = "Fiction"; + db.SaveChanges(); + db.Movies.Remove(movie); + db.SaveChanges(); + } + } + + [Test] + public void MigrationHistoryConfigurationTest() + { + MovieCodedBasedConfigDBContext db = new MovieCodedBasedConfigDBContext(); + db.Database.Initialize(true); + var l = db.Movies.ToList(); + foreach (var i in l) + { + } + var result = MySqlHelper.ExecuteScalar($"server=localhost;User Id=root;database={db.Database.Connection.Database};logging=true; port=" + Port + ";", "SELECT COUNT(_MigrationId) FROM __MySqlMigrations;"); + Assert.AreEqual(1, int.Parse(result.ToString())); + } + + [Test] + public void DbSetRangeTest() + { + using (MovieDBContext db = new MovieDBContext()) + { + db.Database.Initialize(true); + Movie m1 = new Movie() { Title = "Terminator 1", ReleaseDate = new DateTime(1984, 10, 26) }; + Movie m2 = new Movie() { Title = "The Matrix", ReleaseDate = new DateTime(1999, 3, 31) }; + Movie m3 = new Movie() { Title = "Predator", ReleaseDate = new DateTime(1987, 6, 12) }; + Movie m4 = new Movie() { Title = "Star Wars, The Sith Revenge", ReleaseDate = new DateTime(2005, 5, 19) }; + db.Movies.AddRange(new Movie[] { m1, m2, m3, m4 }); + db.SaveChanges(); + var q = from m in db.Movies select m; + Assert.AreEqual(4, q.Count()); + foreach (var row in q) + { + } + db.Movies.RemoveRange(q.ToList()); + db.SaveChanges(); + var q2 = from m in db.Movies select m; + Assert.AreEqual(0, q2.Count()); + } + } + + [Test] + public void EnumSupportTest() + { + using (var dbCtx = new EnumTestSupportContext()) + { + dbCtx.Database.Initialize(true); + dbCtx.SchoolSchedules.Add(new SchoolSchedule() { TeacherName = "Pako", Subject = SchoolSubject.History }); + dbCtx.SaveChanges(); + + var schedule = (from s in dbCtx.SchoolSchedules + where s.Subject == SchoolSubject.History + select s).FirstOrDefault(); + + Assert.AreNotEqual(null, schedule); + Assert.AreEqual(SchoolSubject.History, schedule.Subject); + } + } + + + [Test] + [Ignore("This test needs MicrosoftSqlServer.Types which is not available for all the target frameworks.")] + public void SpatialSupportTest() + { + using (var dbCtx = new JourneyContext()) + { + dbCtx.Database.Initialize(true); + dbCtx.MyPlaces.Add(new MyPlace() + { + name = "JFK INTERNATIONAL AIRPORT OF NEW YORK", + location = DbGeometry.FromText("POINT(40.644047 -73.782291)"), + }); + dbCtx.MyPlaces.Add(new MyPlace + { + name = "ALLEY POND PARK", + location = DbGeometry.FromText("POINT(40.745696 -73.742638)") + }); + dbCtx.MyPlaces.Add(new MyPlace + { + name = "CUNNINGHAM PARK", + location = DbGeometry.FromText("POINT(40.735031 -73.768387)") + }); + dbCtx.MyPlaces.Add(new MyPlace + { + name = "QUEENS VILLAGE STATION", + location = DbGeometry.FromText("POINT(40.717957 -73.736501)") + }); + dbCtx.SaveChanges(); + + var place = (from p in dbCtx.MyPlaces + where p.name == "JFK INTERNATIONAL AIRPORT OF NEW YORK" + select p).FirstOrDefault(); + + var point = DbGeometry.FromText("POINT(40.717957 -73.736501)"); + + var distance = (point.Distance(place.location) * 100); + + Assert.AreNotEqual(null, place); + Assert.AreEqual(8.6944880240295852D, distance.Value); + + var points = from p in dbCtx.MyPlaces + select new { name = p.name, location = p.location }; + foreach (var item in points) + { + var distanceX = DbGeometry.FromText("POINT(40.717957 -73.736501)").Distance(item.location) * 100; + Assert.IsNotNull(distanceX); + } + + foreach (MyPlace p in dbCtx.MyPlaces) + dbCtx.MyPlaces.Remove(p); + dbCtx.SaveChanges(); + + dbCtx.MyPlaces.Add(new MyPlace + { + name = "AGraphic Design Institute", + location = DbGeometry.FromText(string.Format("POINT({0} {1})", -122.336106, 47.605049), 101) + }); + + dbCtx.MyPlaces.Add(new MyPlace + { + name = "AGraphic Design Institute", + location = DbGeometry.FromText("POINT(-123.336106 47.605049)", 102) + }); + + dbCtx.MyPlaces.Add(new MyPlace + { + name = "BGraphic Design Institute", + location = DbGeometry.FromText("POINT(-113.336106 47.605049)", 103) + }); + + dbCtx.MyPlaces.Add(new MyPlace + { + name = "Graphic Design Institute", + location = DbGeometry.FromText(string.Format("POINT({0} {1})", 51.5, -1.28), 4326) + }); + dbCtx.SaveChanges(); + + var result = (from u in dbCtx.MyPlaces select u.location.CoordinateSystemId).ToList(); + foreach (var item in result) + Assert.IsNotNull(item); + var res = dbCtx.MyPlaces.OrderBy(q => q.name.Take(1).Skip(1).ToList()); + Assert.IsNotNull(res); + + var pointA1 = DbGeometry.FromText(string.Format("POINT(40.644047 -73.782291)")); + var pointB1 = DbGeometry.FromText("POINT(40.717957 -73.736501)"); + var distance1 = pointA1.Distance(pointB1); + + var pointA2 = DbGeometry.FromText("POINT(2.5 2.5)"); + var pointB2 = DbGeometry.FromText("POINT(4 0.8)"); + var distance2 = pointA2.Distance(pointB2); + + var pointA3 = DbGeometry.FromText("POINT(3 -4)"); + var pointB3 = DbGeometry.FromText("POINT(-1 3)"); + var distance3 = pointA3.Distance(pointB3); + + Assert.True(distance1.Value == 0.086944880240295855 && distance2.Value == 2.2671568097509267 && + distance3.Value == 8.06225774829855); + + } + } + + [Test] + public void BeginTransactionSupportTest() + { + using (var dbcontext = new MovieCodedBasedConfigDBContext()) + { + dbcontext.Database.Initialize(true); + using (var transaction = dbcontext.Database.BeginTransaction()) + { + try + { + dbcontext.Movies.Add(new MovieCBC() + { + Title = "Sharknado", + Genre = "Documental", + Price = 1.50M, + ReleaseDate = DateTime.Parse("01/07/2013") + }); + + dbcontext.SaveChanges(); + var result = MySqlHelper.ExecuteScalar("server=localhost;User Id=root;database=test;logging=true;port=" + Port + ";", "select COUNT(*) from moviecbcs;"); + Assert.AreEqual(0, int.Parse(result.ToString())); + + transaction.Commit(); + + result = MySqlHelper.ExecuteScalar("server=localhost;User Id=root;database=test;logging=true; port=" + Port + ";", "select COUNT(*) from moviecbcs;"); + Assert.AreEqual(1, int.Parse(result.ToString())); + } + catch (Exception) + { + transaction.Rollback(); + } + } + } + } + + /// + /// This test covers two new features on EF6: + /// 1- "DbContext.Database.UseTransaction, that use a transaction created from an open connection" + /// 2- "DbContext can now be created with a DbConnection that is already opened" + /// + [Test] + public void UseTransactionSupportTest() + { + using (var context = new MovieCodedBasedConfigDBContext()) + { + context.Database.CreateIfNotExists(); + } + using (var connection = new MySqlConnection($"server=localhost;User Id=root;database={nameof(MovieCodedBasedConfigDBContext)};logging=true; port=" + Port + ";")) + { + connection.Open(); + using (var transaction = connection.BeginTransaction()) + { + try + { + using (var dbcontext = new MovieCodedBasedConfigDBContext(connection, contextOwnsConnection: false)) + { + dbcontext.Database.Initialize(true); + dbcontext.Database.UseTransaction(transaction); + dbcontext.Movies.Add(new MovieCBC() + { + Title = "Sharknado", + Genre = "Documental", + Price = 1.50M, + ReleaseDate = DateTime.Parse("01/07/2013") + }); + + dbcontext.SaveChanges(); + } + var result = MySqlHelper.ExecuteScalar("server=localhost;User Id=root;database=test;logging=true; port=" + Port + ";", "select COUNT(*) from moviecbcs;"); + Assert.AreEqual(0, int.Parse(result.ToString())); + + transaction.Commit(); + + result = MySqlHelper.ExecuteScalar("server=localhost;User Id=root;database=test;logging=true; port=" + Port + ";", "select COUNT(*) from moviecbcs;"); + Assert.AreEqual(1, int.Parse(result.ToString())); + } + catch (Exception) + { + transaction.Rollback(); + } + } + } + } + + [Test] + [Ignore("Need to check. Bad statemen: CALL `MovieCodedBasedConfigDBContext`.``insert_movie``(@movie_name, @ReleaseDate, @Genre, @Price)")] + public void HasChangesSupportTest() + { + using (var dbcontext = new MovieCodedBasedConfigDBContext()) + { + dbcontext.Database.Initialize(true); + + dbcontext.Movies.Add(new MovieCBC() + { + Title = "Sharknado", + Genre = "Documental", + Price = 1.50M, + ReleaseDate = DateTime.Parse("01/07/2013") + }); + + Assert.True(dbcontext.ChangeTracker.HasChanges()); + dbcontext.SaveChanges(); + Assert.False(dbcontext.ChangeTracker.HasChanges()); + } + } + + [Test] + [Ignore("Need to check. Bad statemen: CALL `MovieCodedBasedConfigDBContext`.``insert_movie``(@movie_name, @ReleaseDate, @Genre, @Price)")] + public void MySqlLoggingToFileSupportTest() + { + string logName = "mysql.log"; + //if (System.IO.File.Exists(logName)) + // System.IO.File.Delete(logName); + + using (var dbcontext = new MovieCodedBasedConfigDBContext()) + { + dbcontext.Database.Log = MySqlLogger.Logger(logName, true).Write; + + dbcontext.Database.Initialize(true); + dbcontext.Movies.Add(new MovieCBC() + { + Title = "Sharknado", + Genre = "Documental", + Price = 1.50M, + ReleaseDate = DateTime.Parse("01/07/2013") + }); + dbcontext.SaveChanges(); + } + + Assert.AreEqual(true, System.IO.File.Exists(logName)); + } + + [Test] + [Ignore("Need to check. Bad statemen: CALL `MovieCodedBasedConfigDBContext`.``insert_movie``(@movie_name, @ReleaseDate, @Genre, @Price)")] + public void MySqlLoggingToConsoleSupportTest() + { + string logName = "mysql_2.log"; + if (System.IO.File.Exists(logName)) + System.IO.File.Delete(logName); + + System.IO.FileStream file; + System.IO.StreamWriter writer; + System.IO.TextWriter txtOut = Console.Out; + try + { + file = new System.IO.FileStream(logName, System.IO.FileMode.OpenOrCreate, System.IO.FileAccess.Write); + writer = new System.IO.StreamWriter(file); + } + catch (Exception e) + { + throw e; + } + Console.SetOut(writer); + + using (var dbcontext = new MovieCodedBasedConfigDBContext()) + { + dbcontext.Database.Log = new MySqlLogger(s => Console.Write(s)).Write; + + dbcontext.Database.Initialize(true); + dbcontext.Movies.Add(new MovieCBC() + { + Title = "Sharknado", + Genre = "Documental", + Price = 1.50M, + ReleaseDate = DateTime.Parse("01/07/2013") + }); + dbcontext.SaveChanges(); + } + Console.SetOut(txtOut); + writer.Close(); + file.Close(); + + Assert.AreEqual(true, System.IO.File.Exists(logName)); + } + + [Test] + public void EntityAndComplexTypeSupportTest() + { + using (var dbContext = new EntityAndComplexTypeContext()) + { + dbContext.Database.Initialize(true); + dbContext.Students.Add( + new Student() + { + Name = "Pakorasu Pakolas", + Address = new Address() { City = "Mazatlan", Street = "Tierra de Venados 440" }, + Schedule = new List() { new SchoolSchedule() { TeacherName = "Pako", Subject = SchoolSubject.History } } + }); + dbContext.SaveChanges(); + + var student = (from s in dbContext.Students + select s).FirstOrDefault(); + + Assert.AreNotEqual(null, student); + Assert.AreNotEqual(null, student.Schedule); + Assert.AreNotEqual(true, string.IsNullOrEmpty(student.Address.Street)); + Assert.AreNotEqual(0, student.Schedule.Count()); + } + } + + /// + /// TO RUN THIS TEST ITS NECESSARY TO ENABLE THE EXECUTION STRATEGY IN THE CLASS MySqlEFConfiguration (Source\MySql.Data.Entity\MySqlConfiguration.cs) AS WELL AS START A MYSQL SERVER INSTACE WITH THE OPTION "--max_connections=3" + /// WHY 3?: 1)For main process (User: root, DB: mysql). 2)For Setup Class. 3)For the connections in this test. + /// The expected result is that opening a third connection and trying to open a fourth(with an asynchronous task) the execution strategy implementation handle the reconnection process until the third one is closed. + /// + //[Test] //<---DON'T FORGET ME TO RUN! =D + public void ExecutionStrategyTest() + { + var connection = new MySqlConnection("server=localhost;User Id=root;logging=true; port=" + Port + ";"); + using (var dbcontext = new MovieCodedBasedConfigDBContext()) + { + dbcontext.Database.Initialize(true); + dbcontext.Movies.Add(new MovieCBC() + { + Title = "Sharknado", + Genre = "Documental", + Price = 1.50M, + ReleaseDate = DateTime.Parse("01/07/2013") + }); + connection.Open(); + System.Threading.Tasks.Task.Factory.StartNew(() => { dbcontext.SaveChanges(); }); + Thread.Sleep(1000); + connection.Close(); + connection.Dispose(); + } + var result = MySqlHelper.ExecuteScalar("server=localhost;User Id=root;database=test;logging=true; port=" + Port + ";", "select COUNT(*) from moviecbcs;"); + Assert.AreEqual(1, int.Parse(result.ToString())); + } + + [Test] + public void UnknownProjectC1() + { +#if DEBUG + Debug.WriteLine(new StackTrace().GetFrame(0).GetMethod().Name); +#endif + using (MovieDBContext db = new MovieDBContext()) + { + db.Database.Initialize(true); + MovieDBInitialize.DoDataPopulation(db); + long myKey = 20; + var q = (from r in db.Movies where (r.ID == myKey) select (long)r.ID).OrderBy(p => p); + string sql = q.ToString(); + CheckSql(sql, SQLSyntax.UnknownProjectC1EF6); + +#if DEBUG + Debug.WriteLine(sql); +#endif + long[] array = (from r in db.Movies where (r.ID == myKey) select (long)r.ID).OrderBy(p => p).ToArray(); + } + } + + [Test] + public void StartsWithTest() + { +#if DEBUG + Debug.WriteLine(new StackTrace().GetFrame(0).GetMethod().Name); +#endif + MovieDBContext db = new MovieDBContext(); + db.Database.Initialize(true); + MovieDBInitialize.DoDataPopulation(db); + string term = "The"; + var l = db.Movies.Where(p => p.Title.StartsWith(term)); + + string sql = l.ToString(); + + CheckSql(sql, SQLSyntax.QueryWithStartsWith); + +#if DEBUG + Debug.WriteLine(sql); +#endif + int j = l.Count(); + foreach (var i in l) + { + j--; + } + Assert.AreEqual(0, j); + } + + [Test] + public void EndsWithTest() + { +#if DEBUG + Debug.WriteLine(new StackTrace().GetFrame(0).GetMethod().Name); +#endif + MovieDBContext db = new MovieDBContext(); + db.Database.Initialize(true); + MovieDBInitialize.DoDataPopulation(db); + string term = "The"; + var l = db.Movies.Where(p => p.Title.EndsWith(term)); + + string sql = l.ToString(); + + CheckSql(sql, SQLSyntax.QueryWithEndsWith); + +#if DEBUG + Debug.WriteLine(sql); +#endif + int j = l.Count(); + foreach (var i in l) + { + j--; + } + Assert.AreEqual(0, j); + } + + [Test] + public void ContainsTest() + { +#if DEBUG + Debug.WriteLine(new StackTrace().GetFrame(0).GetMethod().Name); +#endif + MovieDBContext db = new MovieDBContext(); + db.Database.Initialize(true); + MovieDBInitialize.DoDataPopulation(db); + string term = "The"; + var l = db.Movies.Where(p => p.Title.Contains(term)); + + string sql = l.ToString(); + CheckSql(sql, SQLSyntax.QueryWithContains); + +#if DEBUG + Debug.WriteLine(sql); +#endif + int j = l.Count(); + foreach (var i in l) + { + j--; + } + Assert.AreEqual(0, j); + } + + + /// + /// Test to reproduce bug http://bugs.mysql.com/bug.php?id=73643, Exception when using IEnumera.Contains(model.property) in Where predicate + /// + [Test] + public void TestContainsListWithCast() + { +#if DEBUG + Debug.WriteLine(new StackTrace().GetFrame(0).GetMethod().Name); +#endif + using (MovieDBContext db = new MovieDBContext()) + { + db.Database.Initialize(true); + + long[] longs = new long[] { 1, 2, 3 }; + var q = db.Movies.Where(p => longs.Contains((long)p.ID)); + string sql = q.ToString(); + CheckSql(sql, SQLSyntax.TestContainsListWithCast); +#if DEBUG + Debug.WriteLine(sql); +#endif + var l = q.ToList(); + } + } + + /// + /// Test to reproduce bug http://bugs.mysql.com/bug.php?id=73643, Exception when using IEnumera.Contains(model.property) in Where predicate + /// + [Test] + public void TestContainsListWitConstant() + { +#if DEBUG + Debug.WriteLine(new StackTrace().GetFrame(0).GetMethod().Name); +#endif + using (MovieDBContext db = new MovieDBContext()) + { + db.Database.Initialize(true); + + List strIds = new List(new string[] { "two" }); + var q = db.Movies.Where(p => strIds.Contains("two")); + string sql = q.ToString(); + CheckSql(sql, SQLSyntax.TestContainsListWitConstant); +#if DEBUG + Debug.WriteLine(sql); +#endif + var l = q.ToList(); + } + } + + /// + /// Test to reproduce bug http://bugs.mysql.com/bug.php?id=73643, Exception when using IEnumera.Contains(model.property) in Where predicate + /// + [Test] + public void TestContainsListWithParameterReference() + { +#if DEBUG + Debug.WriteLine(new StackTrace().GetFrame(0).GetMethod().Name); +#endif + using (MovieDBContext db = new MovieDBContext()) + { + db.Database.Initialize(true); + + long[] longs = new long[] { 1, 2, 3 }; + int myNum = 1; + var q = db.Movies.Where(p => longs.Contains(myNum)); + string sql = q.ToString(); + CheckSql(sql, SQLSyntax.TestContainsListWithParameterReference); +#if DEBUG + Debug.WriteLine(sql); +#endif + var l = q.ToList(); + } + } + + [Test] + public void ReplaceTableNameVisitor() + { + using (SakilaDb context = new SakilaDb()) + { + var date = new DateTime(2005, 6, 1); + var rentals = context.customers.Where(t => t.rentals.Any(r => r.rental_date < date)).OrderBy(o => o.customer_id); + string sql = rentals.ToString(); + CheckSql(sql, SQLSyntax.ReplaceNameVisitorQuery); +#if DEBUG + Debug.WriteLine(sql); +#endif + var result = rentals.ToList(); + Assert.AreEqual(520, rentals.Count()); + } + } + + + /// + /// Bug #70941 - Invalid SQL query when eager loading two nested collections + /// + [Test] + public void InvalidQuery() + { + using (UsingUnionContext context = new UsingUnionContext()) + { + if (context.Database.Exists()) + context.Database.Delete(); + + context.Database.Create(); + + for (int i = 1; i <= 3; i++) + { + var order = new Order(); + var items = new List(); + + items.Add(new Item { Id = 1 }); + items.Add(new Item { Id = 2 }); + items.Add(new Item { Id = 3 }); + + order.Items = items; + var client = new Client { Id = i }; + client.Orders = new List(); + client.Orders.Add(order); + + context.Clients.Add(client); + } + context.SaveChanges(); + + var clients = context.Clients + .Include(c => c.Orders.Select(o => o.Items)) + .Include(c => c.Orders.Select(o => o.Discounts)).ToList(); + + Assert.AreEqual(clients.Count(), 3); + Assert.AreEqual(clients.Where(t => t.Id == 1).Single().Orders.Count(), 1); + Assert.AreEqual(clients.Where(t => t.Id == 1).Single().Orders.Where(j => j.Id == 1).Single().Items.Count(), 3); + } + } + + /// + /// Bug #28095165 - CONTRIBUTION: FIX CONCURRENCYCHECK + DATABASEGENERATEDOPTION.COMPUTED + /// + [Test] + public void ConcurrencyCheckWithDbGeneratedColumn() + { +#if DEBUG + Debug.WriteLine(new StackTrace().GetFrame(0).GetMethod().Name); +#endif + using (MovieDBContext db = new MovieDBContext()) + { + db.Database.Delete(); + db.Database.CreateIfNotExists(); + db.Database.Log = (e) => Debug.WriteLine(e); + db.Database.ExecuteSqlCommand(@"DROP TABLE IF EXISTS `MovieReleases2`"); + + db.Database.ExecuteSqlCommand( + @"CREATE TABLE IF NOT EXISTS `MovieRelease2` ( + `Id` int(11) NOT NULL, + `Name` varchar(45) NOT NULL, + `Timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `RowVersion` bigint NOT NULL DEFAULT 0, + PRIMARY KEY (`Id`) + ) ENGINE=InnoDB DEFAULT CHARSET=binary"); + + db.Database.ExecuteSqlCommand( + @"CREATE TRIGGER `trg_MovieRelease2_before_update` + BEFORE UPDATE ON `MovieRelease2` + FOR EACH ROW SET NEW.RowVersion = OLD.RowVersion + 1;"); + + MySqlTrace.Listeners.Clear(); + MySqlTrace.Switch.Level = SourceLevels.All; + GenericListener listener = new GenericListener(); + MySqlTrace.Listeners.Add(listener); + + try + { + MovieRelease2 mr = db.MovieReleases2.Create(); + mr.Id = 1; + mr.Name = "Commercial"; + db.MovieReleases2.Add(mr); + Assert.AreEqual(mr.RowVersion, 0); + db.SaveChanges(); // ADD + Assert.AreEqual(mr.RowVersion, 0); + + mr.Name = "Director's Cut"; + db.SaveChanges(); // UPDATE #1 + Assert.AreEqual(mr.RowVersion, 1); + + mr.Name = "Avengers"; + db.SaveChanges(); // UPDATE #2 + Assert.AreEqual(mr.RowVersion, 2); + } + finally + { + db.Database.ExecuteSqlCommand(@"DROP TABLE IF EXISTS `MovieReleases2`"); + } + // Check sql + Regex rx = new Regex(@"Query Opened: (?UPDATE .*)", RegexOptions.Compiled | RegexOptions.Singleline); + int n = 0; + foreach (string s in listener.Strings) + { + Match m = rx.Match(s); + if (m.Success) + { + if (n++ == 0) + { + CheckSql(m.Groups["item"].Value, SQLSyntax.UpdateWithSelectWithDbGeneratedLock1); + } + else + { + CheckSql(m.Groups["item"].Value, SQLSyntax.UpdateWithSelectWithDbGeneratedLock2); + } + } + } + } + } + + /// + /// Bug #31323788 - EF6 CODE FIRST - TABLE SCHEMAS ARE LOST, BUT AUTOMATIC MIGRATIONS USES THEM + /// + [Test] + public void TablesWithSchema() + { + using (BlogContext context = new BlogContext()) + { + var blog = new Blog { Title = "Blog_1" }; + context.Blog.Add(blog); + + blog = new Blog { Title = "Blog_2" }; + context.Blog.Add(blog); + + context.SaveChanges(); + Assert.AreEqual(2, context.Blog.Count()); + Assert.AreEqual(2, context.Blog.First(b => b.Title == "Blog_2").BlogId); + + context.Blog.Remove(blog); + context.SaveChanges(); + Assert.AreEqual(1, context.Blog.Count()); + Assert.AreEqual("Blog_1", context.Blog.First().Title); + } + } + + [Test, Description("UNION SYNTAX MISSING REQUIRED PARENTHESIS")] + public void UnionSyntax() + { + using (var context = new ContextForString()) + { + context.Database.Delete(); + context.Database.Create(); + context.StringUsers.Add(new StringUser + { + StringUserId = 1, + Name50 = "Juan", + Name100 = "100", + Name200 = "200", + Name300 = "300" + }); + context.StringUsers.Add(new StringUser + { + StringUserId = 2, + Name50 = "Pedro", + Name100 = "cien", + Name200 = "doscientos", + Name300 = "trescientos" + }); + context.StringUsers.Add(new StringUser + { + StringUserId = 3, + Name50 = "Lupe", + Name100 = "101", + Name200 = "cxvbx", + Name300 = "301" + }); + context.StringUsers.Add(new StringUser + { + StringUserId = 4, + Name50 = "Luis", + Name100 = "asdf", + Name200 = "wrwe", + Name300 = "xcvb" + }); + context.StringUsers.Add(new StringUser + { + StringUserId = 5, + Name50 = "Pepe", + Name100 = "asdf", + Name200 = "zxvz", + Name300 = "fgsd" + }); + context.SaveChanges(); + + var query1 = context.StringUsers; + var query2 = query1.Take(0).Concat(query1); + var query3 = query1.Concat(query1.Take(0)); + Assert.True((query1.Count() == 5) & (query2.Count() == 5) & (query3.Count() == 5)); + } + } + + [Test, Description("FK name ,longer than 64 chars are named to FK_")] + public void NormalForeignKey() + { + using (var context = new ContextForNormalFk()) + { + context.Database.Initialize(true); + using (MySqlConnection conn = new MySqlConnection(context.Database.Connection.ConnectionString)) + { + conn.Open(); + var cmd = new MySqlCommand(); + var entityName = (context.Permisos.GetType().FullName.Split(',')[0]).Substring(66).ToLowerInvariant(); + var contextName = context.GetType().Name.ToLowerInvariant(); + cmd.Connection = conn; + cmd.CommandText = + $"SELECT CONSTRAINT_NAME FROM information_schema.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_SCHEMA = '{contextName}' and TABLE_NAME = '{entityName}';"; + cmd.ExecuteNonQuery(); + + using (var reader = cmd.ExecuteReader()) + { + while (reader.Read()) + { + var val = reader.GetValue(0); + Assert.True(val.ToString().Contains("FK_")); + } + } + } + } + } + + [Test, Description("FK name ,longer than 64 chars are named to FK_")] + public void LongForeignKey() + { + using (var context = new ContextForLongFk()) + { + context.Database.Initialize(true); + var entityName = (context.Permisos.GetType().FullName.Split(',')[0]).Substring(66).ToLowerInvariant(); + var contextName = context.GetType().Name.ToLowerInvariant(); + using (MySqlConnection conn = new MySqlConnection(context.Database.Connection.ConnectionString)) + { + conn.Open(); + var cmd = new MySqlCommand(); + cmd.Connection = conn; + cmd.CommandText = + $"SELECT CONSTRAINT_NAME FROM information_schema.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_SCHEMA = '{contextName}' and TABLE_NAME = '{entityName}';"; + cmd.ExecuteNonQuery(); + + using (var reader = cmd.ExecuteReader()) + { + while (reader.Read()) + { + var val = reader.GetValue(0); + Assert.True(val.ToString().Contains("FK_")); + } + } + } + } + } + + [Test, Description("Verify that Null Reference Exception is not thrown when try to save entity with TINYINT AS PK ")] + public void SaveTinyIntAsPK() + { + using (var context = new ContextForTinyPk()) + { + context.Database.Delete(); + context.Database.Create(); + context.TinyPkUseRs.Add(new TinyPkUser + { + StringUserId = 1, + Name50 = "Juan", + Name100 = "100", + Name200 = "200", + Name300 = "300" + }); + + context.TinyPkUseRs.Add(new TinyPkUser + { + StringUserId = 2, + Name50 = "Pedro", + Name100 = "cien", + Name200 = "doscientos", + Name300 = "trescientos" + }); + + context.TinyPkUseRs.Add(new TinyPkUser + { + StringUserId = 3, + Name50 = "Lupe", + Name100 = "101", + Name200 = "cxvbx", + Name300 = "301" + }); + + context.TinyPkUseRs.Add(new TinyPkUser + { + StringUserId = 4, + Name50 = "Luis", + Name100 = "asdf", + Name200 = "wrwe", + Name300 = "xcvb" + }); + + context.TinyPkUseRs.Add(new TinyPkUser + { + StringUserId = 5, + Name50 = "Pepe", + Name100 = "asdf", + Name200 = "zxvz", + Name300 = "fgsd" + }); + context.SaveChanges(); + var query1 = context.TinyPkUseRs; + var query2 = query1.Take(0).Concat(query1); + var query3 = query1.Concat(query1.Take(0)); + Assert.True((query1.Count() == 5) & (query2.Count() == 5) & (query3.Count() == 5)); + } + } + + [Test, Description("Verify that Null Reference Exception is not thrown when try to save entity with BIGINT AS PK ")] + public void SaveBigIntAsPK() + { + using (var context = new ContextForBigIntPk()) + { + context.Database.Delete(); + context.Database.Create(); + context.BigIntPkUseRs.Add(new BigIntPkUser + { + StringUserId = 934157136952, + Name50 = "Juan", + Name100 = "100", + Name200 = "200", + Name300 = "300" + }); + + context.BigIntPkUseRs.Add(new BigIntPkUser + { + StringUserId = 934157136953, + Name50 = "Pedro", + Name100 = "cien", + Name200 = "doscientos", + Name300 = "trescientos" + }); + + context.BigIntPkUseRs.Add(new BigIntPkUser + { + StringUserId = 9223372036854775807, + Name50 = "Lupe", + Name100 = "101", + Name200 = "cxvbx", + Name300 = "301" + }); + + context.BigIntPkUseRs.Add(new BigIntPkUser + { + StringUserId = 0, + Name50 = "Luis", + Name100 = "asdf", + Name200 = "wrwe", + Name300 = "xcvb" + }); + + context.BigIntPkUseRs.Add(new BigIntPkUser + { + StringUserId = -9223372036854775808, + Name50 = "Pepe", + Name100 = "asdf", + Name200 = "zxvz", + Name300 = "fgsd" + }); + context.SaveChanges(); + var query1 = context.BigIntPkUseRs; + var query2 = query1.Take(0).Concat(query1); + var query3 = query1.Concat(query1.Take(0)); + Assert.True((query1.Count() == 5) & (query2.Count() == 5) & (query3.Count() == 5)); + } + } + + [Test, Description("TRANSACTION AFTER A FAILED TRANSACTION((USING BeginTransaction)) Commit")] + public void BeginTransNested() + { + using (var context = new EnumTestSupportContext()) + { + using (var trans = context.Database.BeginTransaction()) + { + Thread.Sleep(5000); + Assert.Catch(() => context.Database.ExecuteSqlCommand("update table schoolschedule")); + trans.Commit(); + } + using (var trans = context.Database.BeginTransaction()) + { + context.SchoolSchedules.Add(new SchoolSchedule + { + TeacherName = "Ruben", + Subject = SchoolSubject.History + }); + ; + + context.SchoolSchedules.Add(new SchoolSchedule + { + TeacherName = "Peter", + Subject = SchoolSubject.Chemistry + }); + ; + + context.SchoolSchedules.Add(new SchoolSchedule + { + TeacherName = "Juan", + Subject = SchoolSubject.Math + }); + ; + context.SaveChanges(); + trans.Commit(); + } + var count = context.SchoolSchedules.Count(); + Assert.AreEqual(3, count); + //Rollback + using (var trans = context.Database.BeginTransaction()) + { + Assert.Catch(() => context.Database.ExecuteSqlCommand("update table schoolschedule")); + trans.Rollback(); + } + using (var trans = context.Database.BeginTransaction()) + { + context.SchoolSchedules.Add(new SchoolSchedule + { + TeacherName = "Andrew", + Subject = SchoolSubject.History + }); ; + ; + context.SaveChanges(); + trans.Commit(); + } + count = context.SchoolSchedules.Count(); + Assert.AreEqual(4, count); + } + + } + + [Test, Description("TRANSACTION AFTER A FAILED TRANSACTION((USING BeginTransaction)) Stress Test")] + public void TransactionAfterFailStressTest() + { + for (var i = 0; i < 100; i++) + { + using (var context = new EnumTestSupportContext()) + { + using (var trans = context.Database.BeginTransaction()) + { + Assert.Catch(() => context.Database.ExecuteSqlCommand("update table schoolschedule")); + trans.Commit(); + } + using (var trans = context.Database.BeginTransaction()) + { + context.SchoolSchedules.Add(new SchoolSchedule + { + TeacherName = "Ruben", + Subject = SchoolSubject.History + }); + ; + + context.SchoolSchedules.Add(new SchoolSchedule + { + TeacherName = "Peter", + Subject = SchoolSubject.Chemistry + }); + ; + + context.SchoolSchedules.Add(new SchoolSchedule + { + TeacherName = "Juan", + Subject = SchoolSubject.Math + }); + context.SaveChanges(); + trans.Commit(); + var count = context.SchoolSchedules.Count(); + Assert.True(count > 0); + } + } + } + } + + + [Test, Description("Wrong SQL Statement to set primary key ")] + public void WrongSQLStatementPK() + { + using (var context = new EducationContext()) + { + context.Database.Delete(); + context.Database.Create(); + context.Passports.Add(new Passport { Key = 1 }); + context.SaveChanges(); + context.Database.ExecuteSqlCommand("ALTER TABLE `passports` CHANGE `Key` `Key1` int NOT NULL AUTO_INCREMENT UNIQUE"); + context.Database.ExecuteSqlCommand("ALTER TABLE `passports` DROP PRIMARY KEY"); + } + + using (var context = new EducationContext()) + { + context.Passports.Add(new Passport { Key = 1 }); + Exception ex = Assert.Catch(() => context.SaveChanges()); + context.Database.Delete(); + } + } + + /// + /// Bug #34498485 [MySQL.Data.EntityFramework does not handle LIKE (Edm.IndexOf) cases] + /// + [Test] + public void TestListMatchingLike() + { + using (VehicleDbContext2 context = new VehicleDbContext2()) + { + context.Database.Delete(); + context.Database.Initialize(true); + + context.Vehicles.Add(new Car2 { Id = 1, Name = "Mustang", Year = 2012, CarProperty = "Car" }); + context.Vehicles.Add(new Bike2 { Id = 101, Name = "Mountain", Year = 2011, BikeProperty = "Bike" }); + context.SaveChanges(); + + string[] matchText = new string[] { "must", "tan" }; + var list = context.Vehicles.Where(v => matchText.Any(t => v.Name.Contains(t))); + Assert.AreEqual(1, list.Count()); + + matchText = new string[] { "mus't", "tan" }; + list = context.Vehicles.Where(v => matchText.Any(t => v.Name.Contains(t))); + Assert.AreEqual(1, list.Count()); + + matchText = new string[] { "%" }; + list = context.Vehicles.Where(v => matchText.Any(t => v.Name.Contains(t))); + Assert.AreEqual(0, list.Count()); + + matchText = new string[] { "tan" }; + list = context.Vehicles.Where(v => matchText.Any(t => v.Name.Contains(t))); + Assert.AreEqual(1, list.Count()); + + matchText = new string[] { "_" }; + list = context.Vehicles.Where(v => matchText.Any(t => v.Name.Contains(t))); + Assert.AreEqual(0, list.Count()); + } + } + } +} diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/ContextForNormalFk.cs b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/ContextForNormalFk.cs index af0011378..6596b2980 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/ContextForNormalFk.cs +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/ContextForNormalFk.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021 Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/ContextForString.cs b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/ContextForString.cs index e856ae228..b4aa8c757 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/ContextForString.cs +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/ContextForString.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021 Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/Dinosauria.cs b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/Dinosauria.cs index c8eee7e95..88cea952a 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/Dinosauria.cs +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/Dinosauria.cs @@ -1,89 +1,89 @@ -// Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.ComponentModel.DataAnnotations; -using System.Data.Entity; -using System.ComponentModel.DataAnnotations.Schema; - - - -namespace MySql.Data.EntityFramework.CodeFirst.Tests -{ - /* - * This data model tests very long names to break FK limit of 64 chars. - * Also uses Table per Type inheritance (TPT). - * */ - public class Animalia_Chordata_Dinosauria_Eusaurischia_Theropoda - { - [Key, DatabaseGenerated(DatabaseGeneratedOption.None)] - public int Id { get; set; } - - [MaxLength(40)] - public string Name { get; set; } - } - - [Table("Tyrannosauridaes")] - public class Tyrannosauridae : Animalia_Chordata_Dinosauria_Eusaurischia_Theropoda - { - public string SpecieName { get; set; } - public float Weight { get; set; } - } - - [Table("Oviraptorosaurias")] - public class Oviraptorosauria : Animalia_Chordata_Dinosauria_Eusaurischia_Theropoda - { - public string SpecieName { get; set; } - public int EggsPerYear { get; set; } - } - - [DbConfigurationType(typeof(MySqlEFConfiguration))] - public class DinosauriaDBContext : DbContext - { - public DbSet dinos { get; set; } - - public DinosauriaDBContext() : base(CodeFirstFixture.GetEFConnectionString()) - { - Database.SetInitializer(new DinosauriaDBInitializer()); - } - - protected override void OnModelCreating(DbModelBuilder modelBuilder) - { - modelBuilder.Entity().ToTable("Tyrannosauridaes"); - modelBuilder.Entity().ToTable("Oviraptorosaurias"); - } - } - - public class DinosauriaDBInitializer : DropCreateDatabaseReallyAlways - { - } -} +// Copyright © 2014, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.ComponentModel.DataAnnotations; +using System.Data.Entity; +using System.ComponentModel.DataAnnotations.Schema; + + + +namespace MySql.Data.EntityFramework.CodeFirst.Tests +{ + /* + * This data model tests very long names to break FK limit of 64 chars. + * Also uses Table per Type inheritance (TPT). + * */ + public class Animalia_Chordata_Dinosauria_Eusaurischia_Theropoda + { + [Key, DatabaseGenerated(DatabaseGeneratedOption.None)] + public int Id { get; set; } + + [MaxLength(40)] + public string Name { get; set; } + } + + [Table("Tyrannosauridaes")] + public class Tyrannosauridae : Animalia_Chordata_Dinosauria_Eusaurischia_Theropoda + { + public string SpecieName { get; set; } + public float Weight { get; set; } + } + + [Table("Oviraptorosaurias")] + public class Oviraptorosauria : Animalia_Chordata_Dinosauria_Eusaurischia_Theropoda + { + public string SpecieName { get; set; } + public int EggsPerYear { get; set; } + } + + [DbConfigurationType(typeof(MySqlEFConfiguration))] + public class DinosauriaDBContext : DbContext + { + public DbSet dinos { get; set; } + + public DinosauriaDBContext() : base(CodeFirstFixture.GetEFConnectionString()) + { + Database.SetInitializer(new DinosauriaDBInitializer()); + } + + protected override void OnModelCreating(DbModelBuilder modelBuilder) + { + modelBuilder.Entity().ToTable("Tyrannosauridaes"); + modelBuilder.Entity().ToTable("Oviraptorosaurias"); + } + } + + public class DinosauriaDBInitializer : DropCreateDatabaseReallyAlways + { + } +} diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/Movie.cs b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/Movie.cs index 36548776d..b9eef7b50 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/Movie.cs +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/Movie.cs @@ -1,176 +1,176 @@ -// Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - - -using System; -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; -using System.Linq; -using System.Text; -using System.Data.Entity; -using System.Data.Entity.ModelConfiguration.Conventions; -using System.Data.Entity.Migrations; -using System.ComponentModel.DataAnnotations.Schema; - - -namespace MySql.Data.EntityFramework.CodeFirst.Tests -{ - public class Movie - { - public int ID { get; set; } - public string Title { get; set; } - public DateTime ReleaseDate { get; set; } - public string Genre { get; set; } - public decimal Price { get; set; } - public Director Director { get; set; } - public virtual ICollection Formats { get; set; } - public virtual ICollection Medias { get; set; } - public byte[] Data { get; set; } - } - - public class MovieMedia - { - public int ID { get; set; } - public int MovieID { get; set; } - public string Format { get; set; } - } - - public class Director - { - public int ID { get; set; } - public string Name { get; set; } - public int YearBorn { get; set; } - } - - public class MovieFormat - { - [Key] - public float Format { get; set; } - } - - [DbConfigurationType(typeof(MySqlEFConfiguration))] - public class MovieDBContext : DbContext - { - public DbSet Movies { get; set; } - public DbSet MovieFormats { get; set; } - public DbSet MovieReleases { get; set; } - public DbSet MovieReleases2 { get; set; } - public DbSet EntitySingleColumns { get; set; } - public DbSet Medias { get; set; } - - - - public MovieDBContext() : base(CodeFirstFixture.GetEFConnectionString()) - { - //Database.SetInitializer(new MigrateDatabaseToLatestVersion>()); - Database.SetInitializer(new DropCreateDatabaseAlways()); - } - - protected override void OnModelCreating(DbModelBuilder modelBuilder) - { - base.OnModelCreating(modelBuilder); - modelBuilder.Configurations.AddFromAssembly(System.Reflection.Assembly.GetExecutingAssembly()); - modelBuilder.Entity().Property(x => x.Price).HasPrecision(16, 2); - modelBuilder.Entity().HasMany(p => p.Formats); - modelBuilder.Entity().HasMany( p => p.Medias ); -} - } - - public class EntitySingleColumn - { - public int Id { get; set; } - } - - public class MovieRelease - { - [Key, DatabaseGenerated(DatabaseGeneratedOption.None)] - public virtual int Id { get; set; } - - [DatabaseGenerated(DatabaseGeneratedOption.Computed)] - public virtual DateTime Timestamp { get; set; } - - // Test: ConcurrencyCheck + Not Computed - [ConcurrencyCheck, Required, MaxLength(45)] - public virtual string Name { get; set; } - } - - public class MovieRelease2 - { - [Key, DatabaseGenerated(DatabaseGeneratedOption.None)] - public virtual int Id { get; set; } - - //[DatabaseGenerated(DatabaseGeneratedOption.Computed)] - //public virtual DateTime Timestamp { get; set; } - - // Test: non computed column - [Required, MaxLength(45)] - public virtual string Name { get; set; } - - // Test: ConcurrencyCheck + Computed - [ConcurrencyCheck, DatabaseGenerated(DatabaseGeneratedOption.Computed)] - [Column(TypeName = "bigint")] - public virtual long RowVersion { get; set; } - } - - public class MovieDBInitialize : DropCreateDatabaseReallyAlways - { - public static Movie[] data = new Movie[] { - new Movie() { ID = 4, Title = "Star Wars, The Sith Revenge", ReleaseDate = new DateTime( 2005, 5, 19 ) }, - new Movie() { ID = 3, Title = "Predator", ReleaseDate = new DateTime(1987, 6, 12) }, - new Movie() { ID = 2, Title = "The Matrix", ReleaseDate = new DateTime( 1999, 3, 31 ) }, - new Movie() { ID = 1, Title = "Terminator 1", ReleaseDate = new DateTime(1984, 10, 26) } - }; - - internal static void DoDataPopulation( MovieDBContext ctx ) - { - ctx.Database.ExecuteSqlCommand("CREATE PROCEDURE GetCount() BEGIN SELECT 5; END"); - Movie m1 = new Movie() { Title = "Terminator 1", ReleaseDate = new DateTime(1984, 10, 26) }; - Movie m2 = new Movie() { Title = "The Matrix", ReleaseDate = new DateTime(1999, 3, 31) }; - Movie m3 = new Movie() { Title = "Predator", ReleaseDate = new DateTime(1987, 6, 12) }; - Movie m4 = new Movie() { Title = "Star Wars, The Sith Revenge", ReleaseDate = new DateTime(2005, 5, 19) }; - ctx.Movies.Add(m1); - ctx.Movies.Add(m2); - ctx.Movies.Add(m3); - ctx.Movies.Add(m4); - ctx.SaveChanges(); - ctx.Entry(m1).Collection(p => p.Medias).Load(); - m1.Medias.Add( new MovieMedia() { Format = "DVD" } ); - m1.Medias.Add( new MovieMedia() { Format = "BlueRay" } ); - ctx.Entry(m2).Collection(p => p.Medias).Load(); - m2.Medias.Add(new MovieMedia() { Format = "DVD" }); - m2.Medias.Add(new MovieMedia() { Format = "Digital" }); - ctx.Entry(m3).Collection(p => p.Medias).Load(); - m3.Medias.Add(new MovieMedia() { Format = "DVD" }); - m3.Medias.Add(new MovieMedia() { Format = "VHS" }); - ctx.Entry(m4).Collection(p => p.Medias).Load(); - m4.Medias.Add(new MovieMedia() { Format = "Digital" }); - m4.Medias.Add(new MovieMedia() { Format = "VHS" }); - ctx.SaveChanges(); - } - } -} \ No newline at end of file +// Copyright © 2014, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Linq; +using System.Text; +using System.Data.Entity; +using System.Data.Entity.ModelConfiguration.Conventions; +using System.Data.Entity.Migrations; +using System.ComponentModel.DataAnnotations.Schema; + + +namespace MySql.Data.EntityFramework.CodeFirst.Tests +{ + public class Movie + { + public int ID { get; set; } + public string Title { get; set; } + public DateTime ReleaseDate { get; set; } + public string Genre { get; set; } + public decimal Price { get; set; } + public Director Director { get; set; } + public virtual ICollection Formats { get; set; } + public virtual ICollection Medias { get; set; } + public byte[] Data { get; set; } + } + + public class MovieMedia + { + public int ID { get; set; } + public int MovieID { get; set; } + public string Format { get; set; } + } + + public class Director + { + public int ID { get; set; } + public string Name { get; set; } + public int YearBorn { get; set; } + } + + public class MovieFormat + { + [Key] + public float Format { get; set; } + } + + [DbConfigurationType(typeof(MySqlEFConfiguration))] + public class MovieDBContext : DbContext + { + public DbSet Movies { get; set; } + public DbSet MovieFormats { get; set; } + public DbSet MovieReleases { get; set; } + public DbSet MovieReleases2 { get; set; } + public DbSet EntitySingleColumns { get; set; } + public DbSet Medias { get; set; } + + + + public MovieDBContext() : base(CodeFirstFixture.GetEFConnectionString()) + { + //Database.SetInitializer(new MigrateDatabaseToLatestVersion>()); + Database.SetInitializer(new DropCreateDatabaseAlways()); + } + + protected override void OnModelCreating(DbModelBuilder modelBuilder) + { + base.OnModelCreating(modelBuilder); + modelBuilder.Configurations.AddFromAssembly(System.Reflection.Assembly.GetExecutingAssembly()); + modelBuilder.Entity().Property(x => x.Price).HasPrecision(16, 2); + modelBuilder.Entity().HasMany(p => p.Formats); + modelBuilder.Entity().HasMany( p => p.Medias ); +} + } + + public class EntitySingleColumn + { + public int Id { get; set; } + } + + public class MovieRelease + { + [Key, DatabaseGenerated(DatabaseGeneratedOption.None)] + public virtual int Id { get; set; } + + [DatabaseGenerated(DatabaseGeneratedOption.Computed)] + public virtual DateTime Timestamp { get; set; } + + // Test: ConcurrencyCheck + Not Computed + [ConcurrencyCheck, Required, MaxLength(45)] + public virtual string Name { get; set; } + } + + public class MovieRelease2 + { + [Key, DatabaseGenerated(DatabaseGeneratedOption.None)] + public virtual int Id { get; set; } + + //[DatabaseGenerated(DatabaseGeneratedOption.Computed)] + //public virtual DateTime Timestamp { get; set; } + + // Test: non computed column + [Required, MaxLength(45)] + public virtual string Name { get; set; } + + // Test: ConcurrencyCheck + Computed + [ConcurrencyCheck, DatabaseGenerated(DatabaseGeneratedOption.Computed)] + [Column(TypeName = "bigint")] + public virtual long RowVersion { get; set; } + } + + public class MovieDBInitialize : DropCreateDatabaseReallyAlways + { + public static Movie[] data = new Movie[] { + new Movie() { ID = 4, Title = "Star Wars, The Sith Revenge", ReleaseDate = new DateTime( 2005, 5, 19 ) }, + new Movie() { ID = 3, Title = "Predator", ReleaseDate = new DateTime(1987, 6, 12) }, + new Movie() { ID = 2, Title = "The Matrix", ReleaseDate = new DateTime( 1999, 3, 31 ) }, + new Movie() { ID = 1, Title = "Terminator 1", ReleaseDate = new DateTime(1984, 10, 26) } + }; + + internal static void DoDataPopulation( MovieDBContext ctx ) + { + ctx.Database.ExecuteSqlCommand("CREATE PROCEDURE GetCount() BEGIN SELECT 5; END"); + Movie m1 = new Movie() { Title = "Terminator 1", ReleaseDate = new DateTime(1984, 10, 26) }; + Movie m2 = new Movie() { Title = "The Matrix", ReleaseDate = new DateTime(1999, 3, 31) }; + Movie m3 = new Movie() { Title = "Predator", ReleaseDate = new DateTime(1987, 6, 12) }; + Movie m4 = new Movie() { Title = "Star Wars, The Sith Revenge", ReleaseDate = new DateTime(2005, 5, 19) }; + ctx.Movies.Add(m1); + ctx.Movies.Add(m2); + ctx.Movies.Add(m3); + ctx.Movies.Add(m4); + ctx.SaveChanges(); + ctx.Entry(m1).Collection(p => p.Medias).Load(); + m1.Medias.Add( new MovieMedia() { Format = "DVD" } ); + m1.Medias.Add( new MovieMedia() { Format = "BlueRay" } ); + ctx.Entry(m2).Collection(p => p.Medias).Load(); + m2.Medias.Add(new MovieMedia() { Format = "DVD" }); + m2.Medias.Add(new MovieMedia() { Format = "Digital" }); + ctx.Entry(m3).Collection(p => p.Medias).Load(); + m3.Medias.Add(new MovieMedia() { Format = "DVD" }); + m3.Medias.Add(new MovieMedia() { Format = "VHS" }); + ctx.Entry(m4).Collection(p => p.Medias).Load(); + m4.Medias.Add(new MovieMedia() { Format = "Digital" }); + m4.Medias.Add(new MovieMedia() { Format = "VHS" }); + ctx.SaveChanges(); + } + } +} diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/MovieContextCodeBasedConfiguration.cs b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/MovieContextCodeBasedConfiguration.cs index 5e8d55cf6..a15080adc 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/MovieContextCodeBasedConfiguration.cs +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/MovieContextCodeBasedConfiguration.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -282,4 +282,4 @@ protected override void OnModelCreating(DbModelBuilder modelBuilder) } } #endregion -} \ No newline at end of file +} diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/PromotionsDB.cs b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/PromotionsDB.cs index fa8c0c36f..0c828a3c2 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/PromotionsDB.cs +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/PromotionsDB.cs @@ -1,89 +1,89 @@ -// Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Data.Entity; -using System.ComponentModel.DataAnnotations; -using System.ComponentModel.DataAnnotations.Schema; - -namespace MySql.Data.EntityFramework.CodeFirst.Tests -{ - [DbConfigurationType(typeof(MySqlEFConfiguration))] - public class PromotionsDB : DbContext - { - private bool disposed = false; - - public virtual DbSet HomePromoes { get; set; } - - public PromotionsDB() : base(CodeFirstFixture.GetEFConnectionString()) - { - Database.SetInitializer(new PromotionsDBInitializer()); - } - - protected override void Dispose(bool disposing) - { - if (disposed) - return; - - if (disposing) - { - Database.Delete(); - } - - base.Dispose(disposing); - disposed = true; - } - } - - public class PromotionsDBInitializer : DropCreateDatabaseReallyAlways - { - } - - public class HomePromo - { - [DatabaseGenerated(DatabaseGeneratedOption.Identity)] - [Key] - public int ID { get; set; } - - public string Image { get; set; } - - public string Url { get; set; } - - public int DisplayOrder { get; set; } - - [Column("Active")] - public bool Active { get; set; } - [Column("ActiveFrom")] - public DateTime? ActiveFrom { get; set; } - [Column("ActiveTo")] - public DateTime? ActiveTo { get; set; } - } -} +// Copyright © 2014, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Data.Entity; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; + +namespace MySql.Data.EntityFramework.CodeFirst.Tests +{ + [DbConfigurationType(typeof(MySqlEFConfiguration))] + public class PromotionsDB : DbContext + { + private bool disposed = false; + + public virtual DbSet HomePromoes { get; set; } + + public PromotionsDB() : base(CodeFirstFixture.GetEFConnectionString()) + { + Database.SetInitializer(new PromotionsDBInitializer()); + } + + protected override void Dispose(bool disposing) + { + if (disposed) + return; + + if (disposing) + { + Database.Delete(); + } + + base.Dispose(disposing); + disposed = true; + } + } + + public class PromotionsDBInitializer : DropCreateDatabaseReallyAlways + { + } + + public class HomePromo + { + [DatabaseGenerated(DatabaseGeneratedOption.Identity)] + [Key] + public int ID { get; set; } + + public string Image { get; set; } + + public string Url { get; set; } + + public int DisplayOrder { get; set; } + + [Column("Active")] + public bool Active { get; set; } + [Column("ActiveFrom")] + public DateTime? ActiveFrom { get; set; } + [Column("ActiveTo")] + public DateTime? ActiveTo { get; set; } + } +} diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/Properties/AssemblyInfo.cs b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/Properties/AssemblyInfo.cs index 0dac870b6..6f4cc1fb9 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/Properties/AssemblyInfo.cs +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/Properties/AssemblyInfo.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2014, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -53,4 +53,4 @@ #if !DEBUG [assembly: AssemblyKeyName("ConnectorNet")] #endif -[assembly: NonParallelizable] \ No newline at end of file +[assembly: NonParallelizable] diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/Properties/SQLSyntax.Designer.cs b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/Properties/SQLSyntax.Designer.cs index 4c020c55a..f96530dd5 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/Properties/SQLSyntax.Designer.cs +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/Properties/SQLSyntax.Designer.cs @@ -1,383 +1,383 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.42000 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace MySql.EntityFramework.CodeFirst.Tests.Properties { - using System; - - - /// - /// A strongly-typed resource class, for looking up localized strings, etc. - /// - // This class was auto-generated by the StronglyTypedResourceBuilder - // class via a tool like ResGen or Visual Studio. - // To add or remove a member, edit your .ResX file then rerun ResGen - // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class SQLSyntax { - - private static global::System.Resources.ResourceManager resourceMan; - - private static global::System.Globalization.CultureInfo resourceCulture; - - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal SQLSyntax() { - } - - /// - /// Returns the cached ResourceManager instance used by this class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager { - get { - if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("MySql.EntityFramework.CodeFirst.Tests.Properties.SQLSyntax", typeof(SQLSyntax).Assembly); - resourceMan = temp; - } - return resourceMan; - } - } - - /// - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture { - get { - return resourceCulture; - } - set { - resourceCulture = value; - } - } - - /// - /// Looks up a localized string similar to SELECT - ///1 AS `C1`, - ///`Project3`.`nCdSite`, - ///`Project3`.`C1` AS `C2` - ///FROM (SELECT - ///`visitante`.`nCdSite`, - ///COUNT(DISTINCT `visitante`.`sDsIp`) AS `C1` - ///FROM `visitante` - /// GROUP BY - ///`visitante`.`nCdSite`) AS `Project3`. - /// - internal static string CountGroupBy { - get { - return ResourceManager.GetString("CountGroupBy", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to SELECT - ///1 AS `C1`, - ///`Project3`.`nCdSite`, - ///`Project3`.`C1` AS `C2` - ///FROM (SELECT - ///`Extent4`.`nCdSite`, - ///COUNT(DISTINCT `Extent4`.`sDsIp`) AS `C1` - ///FROM `pagina` AS `Extent3` INNER JOIN `visitante` AS `Extent4` ON `Extent3`.`nCdVisitante` = `Extent4`.`nCdVisitante` - /// GROUP BY - ///`Extent4`.`nCdSite`) AS `Project3`. - /// - internal static string CountGroupBy2 { - get { - return ResourceManager.GetString("CountGroupBy2", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to SELECT - /// `Apply1`.`customer_id`, - /// `Extent5`.`country` - /// FROM (SELECT - /// `Extent1`.`customer_id`, - /// `Extent1`.`store_id`, - /// `Extent1`.`first_name`, - /// `Extent1`.`last_name`, - /// `Extent1`.`email`, - /// `Extent1`.`address_id`, - /// `Extent1`.`active`, - /// `Extent1`.`create_date`, - /// `Extent1`.`last_update`, - /// (SELECT - /// `Project1`.`address_id` - /// FROM `address` AS `Project1` - /// WHERE `Project1`.`address_id` = `Extent1`.`address_id` - /// ORDER BY - /// `Project1`.`address_id` DESC LIMIT 1) AS `ADDRESS [rest of string was truncated]";. - /// - internal static string FirstOrDefaultNestedWithOrderBy { - get { - return ResourceManager.GetString("FirstOrDefaultNestedWithOrderBy", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to SELECT - /// `Project1`.`ID`, - /// `Project1`.`Title`, - /// `Project1`.`ReleaseDate`, - /// `Project1`.`Genre`, - /// `Project1`.`Price`, - /// `Project1`.`Data`, - /// `Project1`.`Director_ID` - /// FROM `Movies` AS `Project1` - /// WHERE `Project1`.`ReleaseDate` >= @p__linq__0 - /// ORDER BY - /// `Project1`.`ReleaseDate` DESC LIMIT 2. - /// - internal static string NestedOrderBy { - get { - return ResourceManager.GetString("NestedOrderBy", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to SELECT - ///`Extent1`.`ID`, - ///`Extent1`.`Title`, - ///`Extent1`.`ReleaseDate`, - ///`Extent1`.`Genre`, - ///`Extent1`.`Price`, - ///`Extent1`.`Data`, - ///`Extent1`.`Director_ID` - ///FROM `Movies` AS `Extent1` - /// WHERE `Extent1`.`Title` LIKE @p__linq__0. - /// - internal static string QueryWithContains { - get { - return ResourceManager.GetString("QueryWithContains", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to SELECT - ///`Extent1`.`ID`, - ///`Extent1`.`Title`, - ///`Extent1`.`ReleaseDate`, - ///`Extent1`.`Genre`, - ///`Extent1`.`Price`, - ///`Extent1`.`Data`, - ///`Extent1`.`Director_ID` - ///FROM `Movies` AS `Extent1` - /// WHERE `Extent1`.`Title` LIKE @p__linq__0. - /// - internal static string QueryWithEndsWith { - get { - return ResourceManager.GetString("QueryWithEndsWith", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to SELECT - ///`Project1`.`ID`, - ///`Project1`.`Title`, - ///`Project1`.`ReleaseDate`, - ///`Project1`.`Genre`, - ///`Project1`.`Price`, - ///`Project1`.`Data`, - ///`Project1`.`Director_ID` - ///FROM `Movies` AS `Project1` - /// WHERE `Project1`.`Title` LIKE @p__linq__0 - /// ORDER BY - ///`Project1`.`ID` DESC LIMIT 10. - /// - internal static string QueryWithOrderByTakeContains { - get { - return ResourceManager.GetString("QueryWithOrderByTakeContains", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to SELECT - ///`Extent1`.`ID`, - ///`Extent1`.`Title`, - ///`Extent1`.`ReleaseDate`, - ///`Extent1`.`Genre`, - ///`Extent1`.`Price`, - ///`Extent1`.`Data`, - ///`Extent1`.`Director_ID` - ///FROM `Movies` AS `Extent1` - /// WHERE `Extent1`.`Title` LIKE @p__linq__0. - /// - internal static string QueryWithStartsWith { - get { - return ResourceManager.GetString("QueryWithStartsWith", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to SELECT - /// `Project2`.`customer_id`, - /// `Project2`.`store_id`, - /// `Project2`.`first_name`, - /// `Project2`.`last_name`, - /// `Project2`.`email`, - /// `Project2`.`address_id`, - /// `Project2`.`active`, - /// `Project2`.`create_date`, - /// `Project2`.`last_update` - /// FROM `customer` AS `Project2` - /// WHERE EXISTS(SELECT - /// 1 AS `C1` - /// FROM `rental` AS `Extent2` - /// WHERE (`Project2`.`customer_id` = `Extent2`.`customer_id`) AND (`Extent2`.`rental_date` < @p__linq__0)) - /// ORDER BY - /// `Project2`.`customer_id` ASC. - /// - internal static string ReplaceNameVisitorQuery { - get { - return ResourceManager.GetString("ReplaceNameVisitorQuery", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to SELECT - ///`Project1`.`HarborId`, - ///`Project1`.`Description`, - ///`Project1`.`C2` AS `C1`, - ///`Project1`.`ShipId`, - ///`Project1`.`HarborId1`, - ///`Project1`.`Description1`, - ///`Project1`.`C1` AS `C2`, - ///`Project1`.`CrewMemberId`, - ///`Project1`.`ShipId1`, - ///`Project1`.`RankId`, - ///`Project1`.`ClearanceId`, - ///`Project1`.`Description2`, - ///`Project1`.`RankId1`, - ///`Project1`.`Description3`, - ///`Project1`.`ClearanceId1`, - ///`Project1`.`Description4` - ///FROM (SELECT - ///`Extent1`.`HarborId`, - ///`Extent1`.`Description`, - ///`Join3`.`Shi [rest of string was truncated]";. - /// - internal static string ShipQueryMalformedDueMultipleProjecttionsCorrectedEF6 { - get { - return ResourceManager.GetString("ShipQueryMalformedDueMultipleProjecttionsCorrectedEF6", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to SELECT - /// `Extent1`.`ID`, - /// `Extent1`.`Title`, - /// `Extent1`.`ReleaseDate`, - /// `Extent1`.`Genre`, - /// `Extent1`.`Price`, - /// `Extent1`.`Data`, - /// `Extent1`.`Director_ID` - /// FROM `Movies` AS `Extent1` - /// WHERE (@gp1 IN ( @gp2 )) AND (@gp3 IS NOT NULL). - /// - internal static string TestContainsListWitConstant { - get { - return ResourceManager.GetString("TestContainsListWitConstant", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to SELECT - /// `Extent1`.`ID`, - /// `Extent1`.`Title`, - /// `Extent1`.`ReleaseDate`, - /// `Extent1`.`Genre`, - /// `Extent1`.`Price`, - /// `Extent1`.`Data`, - /// `Extent1`.`Director_ID` - /// FROM `Movies` AS `Extent1` - /// WHERE (`Extent1`.`ID` IN ( 1,2,3 )) AND (`Extent1`.`ID` IS NOT NULL). - /// - internal static string TestContainsListWithCast { - get { - return ResourceManager.GetString("TestContainsListWithCast", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to SELECT - ///`Extent1`.`ID`, - ///`Extent1`.`Title`, - ///`Extent1`.`ReleaseDate`, - ///`Extent1`.`Genre`, - ///`Extent1`.`Price`, - ///`Extent1`.`Data`, - ///`Extent1`.`Director_ID` - ///FROM `Movies` AS `Extent1` - /// WHERE @p__linq__0 IN ( 1,2,3 ). - /// - internal static string TestContainsListWithParameterReference { - get { - return ResourceManager.GetString("TestContainsListWithParameterReference", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to SELECT - /// `Project1`.`ID` AS `C1` - /// FROM `Movies` AS `Project1` - /// WHERE (`Project1`.`ID`) = @p__linq__0 - /// ORDER BY - /// `Project1`.`ID` ASC. - /// - internal static string UnknownProjectC1 { - get { - return ResourceManager.GetString("UnknownProjectC1", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to SELECT - ///`Project1`.`ID` AS `C1` - ///FROM `Movies` AS `Project1` - /// WHERE (`Project1`.`ID`) = @p__linq__0 - /// ORDER BY - ///`Project1`.`ID` ASC. - /// - internal static string UnknownProjectC1EF6 { - get { - return ResourceManager.GetString("UnknownProjectC1EF6", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to UPDATE `MovieRelease2` SET `Name`='Director\'s Cut' WHERE (`Id` = 1) AND (`RowVersion` = 0); SELECT `RowVersion` FROM `MovieRelease2` WHERE row_count() = 1 and (`Id` = 1). - /// - internal static string UpdateWithSelectWithDbGeneratedLock1 { - get { - return ResourceManager.GetString("UpdateWithSelectWithDbGeneratedLock1", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to UPDATE `MovieRelease2` SET `Name`='Avengers' WHERE (`Id` = 1) AND (`RowVersion` = 1); SELECT `RowVersion` FROM `MovieRelease2` WHERE row_count() = 1 and (`Id` = 1). - /// - internal static string UpdateWithSelectWithDbGeneratedLock2 { - get { - return ResourceManager.GetString("UpdateWithSelectWithDbGeneratedLock2", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to UPDATE `MovieReleases` SET `Name`='Director\'s Cut' WHERE (`Id` = 1) AND (`Name` = 'Commercial'); SELECT `Timestamp` FROM `MovieReleases` WHERE row_count() = 1 and ((`Id` = 1) AND (`Name` = 'Director\'s Cut')). - /// - internal static string UpdateWithSelectWithNonDbGeneratedLock { - get { - return ResourceManager.GetString("UpdateWithSelectWithNonDbGeneratedLock", resourceCulture); - } - } - } -} +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace MySql.EntityFramework.CodeFirst.Tests.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class SQLSyntax { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal SQLSyntax() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("MySql.EntityFramework.CodeFirst.Tests.Properties.SQLSyntax", typeof(SQLSyntax).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to SELECT + ///1 AS `C1`, + ///`Project3`.`nCdSite`, + ///`Project3`.`C1` AS `C2` + ///FROM (SELECT + ///`visitante`.`nCdSite`, + ///COUNT(DISTINCT `visitante`.`sDsIp`) AS `C1` + ///FROM `visitante` + /// GROUP BY + ///`visitante`.`nCdSite`) AS `Project3`. + /// + internal static string CountGroupBy { + get { + return ResourceManager.GetString("CountGroupBy", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to SELECT + ///1 AS `C1`, + ///`Project3`.`nCdSite`, + ///`Project3`.`C1` AS `C2` + ///FROM (SELECT + ///`Extent4`.`nCdSite`, + ///COUNT(DISTINCT `Extent4`.`sDsIp`) AS `C1` + ///FROM `pagina` AS `Extent3` INNER JOIN `visitante` AS `Extent4` ON `Extent3`.`nCdVisitante` = `Extent4`.`nCdVisitante` + /// GROUP BY + ///`Extent4`.`nCdSite`) AS `Project3`. + /// + internal static string CountGroupBy2 { + get { + return ResourceManager.GetString("CountGroupBy2", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to SELECT + /// `Apply1`.`customer_id`, + /// `Extent5`.`country` + /// FROM (SELECT + /// `Extent1`.`customer_id`, + /// `Extent1`.`store_id`, + /// `Extent1`.`first_name`, + /// `Extent1`.`last_name`, + /// `Extent1`.`email`, + /// `Extent1`.`address_id`, + /// `Extent1`.`active`, + /// `Extent1`.`create_date`, + /// `Extent1`.`last_update`, + /// (SELECT + /// `Project1`.`address_id` + /// FROM `address` AS `Project1` + /// WHERE `Project1`.`address_id` = `Extent1`.`address_id` + /// ORDER BY + /// `Project1`.`address_id` DESC LIMIT 1) AS `ADDRESS [rest of string was truncated]";. + /// + internal static string FirstOrDefaultNestedWithOrderBy { + get { + return ResourceManager.GetString("FirstOrDefaultNestedWithOrderBy", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to SELECT + /// `Project1`.`ID`, + /// `Project1`.`Title`, + /// `Project1`.`ReleaseDate`, + /// `Project1`.`Genre`, + /// `Project1`.`Price`, + /// `Project1`.`Data`, + /// `Project1`.`Director_ID` + /// FROM `Movies` AS `Project1` + /// WHERE `Project1`.`ReleaseDate` >= @p__linq__0 + /// ORDER BY + /// `Project1`.`ReleaseDate` DESC LIMIT 2. + /// + internal static string NestedOrderBy { + get { + return ResourceManager.GetString("NestedOrderBy", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to SELECT + ///`Extent1`.`ID`, + ///`Extent1`.`Title`, + ///`Extent1`.`ReleaseDate`, + ///`Extent1`.`Genre`, + ///`Extent1`.`Price`, + ///`Extent1`.`Data`, + ///`Extent1`.`Director_ID` + ///FROM `Movies` AS `Extent1` + /// WHERE `Extent1`.`Title` LIKE @p__linq__0. + /// + internal static string QueryWithContains { + get { + return ResourceManager.GetString("QueryWithContains", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to SELECT + ///`Extent1`.`ID`, + ///`Extent1`.`Title`, + ///`Extent1`.`ReleaseDate`, + ///`Extent1`.`Genre`, + ///`Extent1`.`Price`, + ///`Extent1`.`Data`, + ///`Extent1`.`Director_ID` + ///FROM `Movies` AS `Extent1` + /// WHERE `Extent1`.`Title` LIKE @p__linq__0. + /// + internal static string QueryWithEndsWith { + get { + return ResourceManager.GetString("QueryWithEndsWith", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to SELECT + ///`Project1`.`ID`, + ///`Project1`.`Title`, + ///`Project1`.`ReleaseDate`, + ///`Project1`.`Genre`, + ///`Project1`.`Price`, + ///`Project1`.`Data`, + ///`Project1`.`Director_ID` + ///FROM `Movies` AS `Project1` + /// WHERE `Project1`.`Title` LIKE @p__linq__0 + /// ORDER BY + ///`Project1`.`ID` DESC LIMIT 10. + /// + internal static string QueryWithOrderByTakeContains { + get { + return ResourceManager.GetString("QueryWithOrderByTakeContains", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to SELECT + ///`Extent1`.`ID`, + ///`Extent1`.`Title`, + ///`Extent1`.`ReleaseDate`, + ///`Extent1`.`Genre`, + ///`Extent1`.`Price`, + ///`Extent1`.`Data`, + ///`Extent1`.`Director_ID` + ///FROM `Movies` AS `Extent1` + /// WHERE `Extent1`.`Title` LIKE @p__linq__0. + /// + internal static string QueryWithStartsWith { + get { + return ResourceManager.GetString("QueryWithStartsWith", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to SELECT + /// `Project2`.`customer_id`, + /// `Project2`.`store_id`, + /// `Project2`.`first_name`, + /// `Project2`.`last_name`, + /// `Project2`.`email`, + /// `Project2`.`address_id`, + /// `Project2`.`active`, + /// `Project2`.`create_date`, + /// `Project2`.`last_update` + /// FROM `customer` AS `Project2` + /// WHERE EXISTS(SELECT + /// 1 AS `C1` + /// FROM `rental` AS `Extent2` + /// WHERE (`Project2`.`customer_id` = `Extent2`.`customer_id`) AND (`Extent2`.`rental_date` < @p__linq__0)) + /// ORDER BY + /// `Project2`.`customer_id` ASC. + /// + internal static string ReplaceNameVisitorQuery { + get { + return ResourceManager.GetString("ReplaceNameVisitorQuery", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to SELECT + ///`Project1`.`HarborId`, + ///`Project1`.`Description`, + ///`Project1`.`C2` AS `C1`, + ///`Project1`.`ShipId`, + ///`Project1`.`HarborId1`, + ///`Project1`.`Description1`, + ///`Project1`.`C1` AS `C2`, + ///`Project1`.`CrewMemberId`, + ///`Project1`.`ShipId1`, + ///`Project1`.`RankId`, + ///`Project1`.`ClearanceId`, + ///`Project1`.`Description2`, + ///`Project1`.`RankId1`, + ///`Project1`.`Description3`, + ///`Project1`.`ClearanceId1`, + ///`Project1`.`Description4` + ///FROM (SELECT + ///`Extent1`.`HarborId`, + ///`Extent1`.`Description`, + ///`Join3`.`Shi [rest of string was truncated]";. + /// + internal static string ShipQueryMalformedDueMultipleProjecttionsCorrectedEF6 { + get { + return ResourceManager.GetString("ShipQueryMalformedDueMultipleProjecttionsCorrectedEF6", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to SELECT + /// `Extent1`.`ID`, + /// `Extent1`.`Title`, + /// `Extent1`.`ReleaseDate`, + /// `Extent1`.`Genre`, + /// `Extent1`.`Price`, + /// `Extent1`.`Data`, + /// `Extent1`.`Director_ID` + /// FROM `Movies` AS `Extent1` + /// WHERE (@gp1 IN ( @gp2 )) AND (@gp3 IS NOT NULL). + /// + internal static string TestContainsListWitConstant { + get { + return ResourceManager.GetString("TestContainsListWitConstant", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to SELECT + /// `Extent1`.`ID`, + /// `Extent1`.`Title`, + /// `Extent1`.`ReleaseDate`, + /// `Extent1`.`Genre`, + /// `Extent1`.`Price`, + /// `Extent1`.`Data`, + /// `Extent1`.`Director_ID` + /// FROM `Movies` AS `Extent1` + /// WHERE (`Extent1`.`ID` IN ( 1,2,3 )) AND (`Extent1`.`ID` IS NOT NULL). + /// + internal static string TestContainsListWithCast { + get { + return ResourceManager.GetString("TestContainsListWithCast", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to SELECT + ///`Extent1`.`ID`, + ///`Extent1`.`Title`, + ///`Extent1`.`ReleaseDate`, + ///`Extent1`.`Genre`, + ///`Extent1`.`Price`, + ///`Extent1`.`Data`, + ///`Extent1`.`Director_ID` + ///FROM `Movies` AS `Extent1` + /// WHERE @p__linq__0 IN ( 1,2,3 ). + /// + internal static string TestContainsListWithParameterReference { + get { + return ResourceManager.GetString("TestContainsListWithParameterReference", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to SELECT + /// `Project1`.`ID` AS `C1` + /// FROM `Movies` AS `Project1` + /// WHERE (`Project1`.`ID`) = @p__linq__0 + /// ORDER BY + /// `Project1`.`ID` ASC. + /// + internal static string UnknownProjectC1 { + get { + return ResourceManager.GetString("UnknownProjectC1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to SELECT + ///`Project1`.`ID` AS `C1` + ///FROM `Movies` AS `Project1` + /// WHERE (`Project1`.`ID`) = @p__linq__0 + /// ORDER BY + ///`Project1`.`ID` ASC. + /// + internal static string UnknownProjectC1EF6 { + get { + return ResourceManager.GetString("UnknownProjectC1EF6", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to UPDATE `MovieRelease2` SET `Name`='Director\'s Cut' WHERE (`Id` = 1) AND (`RowVersion` = 0); SELECT `RowVersion` FROM `MovieRelease2` WHERE row_count() = 1 and (`Id` = 1). + /// + internal static string UpdateWithSelectWithDbGeneratedLock1 { + get { + return ResourceManager.GetString("UpdateWithSelectWithDbGeneratedLock1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to UPDATE `MovieRelease2` SET `Name`='Avengers' WHERE (`Id` = 1) AND (`RowVersion` = 1); SELECT `RowVersion` FROM `MovieRelease2` WHERE row_count() = 1 and (`Id` = 1). + /// + internal static string UpdateWithSelectWithDbGeneratedLock2 { + get { + return ResourceManager.GetString("UpdateWithSelectWithDbGeneratedLock2", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to UPDATE `MovieReleases` SET `Name`='Director\'s Cut' WHERE (`Id` = 1) AND (`Name` = 'Commercial'); SELECT `Timestamp` FROM `MovieReleases` WHERE row_count() = 1 and ((`Id` = 1) AND (`Name` = 'Director\'s Cut')). + /// + internal static string UpdateWithSelectWithNonDbGeneratedLock { + get { + return ResourceManager.GetString("UpdateWithSelectWithNonDbGeneratedLock", resourceCulture); + } + } + } +} diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/SakilaDb.cs b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/SakilaDb.cs index 77487489c..e55e11b2b 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/SakilaDb.cs +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/SakilaDb.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2015, 2020 Oracle and/or its affiliates. +// Copyright © 2015, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/actor.cs b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/actor.cs index 06acff9ef..807687777 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/actor.cs +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/actor.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2014, 2020 Oracle and/or its affiliates. +// Copyright © 2014, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/actor_info.cs b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/actor_info.cs index 7a8042fc8..5bbca857d 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/actor_info.cs +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/actor_info.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2014, 2020 Oracle and/or its affiliates. +// Copyright © 2014, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/address.cs b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/address.cs index 883c274ec..468690dd3 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/address.cs +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/address.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2014, 2020 Oracle and/or its affiliates. +// Copyright © 2014, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/category.cs b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/category.cs index a930c8ba5..73427f5a1 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/category.cs +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/category.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2014, 2020 Oracle and/or its affiliates. +// Copyright © 2014, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/city.cs b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/city.cs index 5c07e4e8d..d85e1697b 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/city.cs +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/city.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2014, 2020 Oracle and/or its affiliates. +// Copyright © 2014, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/country.cs b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/country.cs index 37e775527..976f99ed4 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/country.cs +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/country.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2014, 2020 Oracle and/or its affiliates. +// Copyright © 2014, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/customer.cs b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/customer.cs index 9caceab99..1e3e91d29 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/customer.cs +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/customer.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2014, 2020 Oracle and/or its affiliates. +// Copyright © 2014, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/customer_list.cs b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/customer_list.cs index ed634812e..723dbbaa2 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/customer_list.cs +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/customer_list.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2014, 2020 Oracle and/or its affiliates. +// Copyright © 2014, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/film.cs b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/film.cs index 49ca54a03..0bfd594bf 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/film.cs +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/film.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2014, 2020 Oracle and/or its affiliates. +// Copyright © 2014, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/film_actor.cs b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/film_actor.cs index 5483a11de..2c7f0b3ad 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/film_actor.cs +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/film_actor.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2014, 2020 Oracle and/or its affiliates. +// Copyright © 2014, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/film_category.cs b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/film_category.cs index 9c4d8dafb..141bc32c0 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/film_category.cs +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/film_category.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2014, 2020 Oracle and/or its affiliates. +// Copyright © 2014, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/film_list.cs b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/film_list.cs index 5603836b7..72d666a2f 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/film_list.cs +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/film_list.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2014, 2020 Oracle and/or its affiliates. +// Copyright © 2014, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/film_text.cs b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/film_text.cs index 4dcd0b851..4172112a3 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/film_text.cs +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/film_text.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2014, 2020 Oracle and/or its affiliates. +// Copyright © 2014, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/inventory.cs b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/inventory.cs index e86f0b342..dfe44cc9d 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/inventory.cs +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/inventory.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2014, 2020 Oracle and/or its affiliates. +// Copyright © 2014, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/language.cs b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/language.cs index c95c93c1e..11e03594a 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/language.cs +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/language.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2014, 2020 Oracle and/or its affiliates. +// Copyright © 2014, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/nicer_but_slower_film_list.cs b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/nicer_but_slower_film_list.cs index ae11f853b..18a3ba82a 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/nicer_but_slower_film_list.cs +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/nicer_but_slower_film_list.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2014, 2020 Oracle and/or its affiliates. +// Copyright © 2014, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/payment.cs b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/payment.cs index c3f42f3a1..e5e340e12 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/payment.cs +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/payment.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2014, 2020 Oracle and/or its affiliates. +// Copyright © 2014, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/rental.cs b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/rental.cs index 0ee2ad063..0666386ae 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/rental.cs +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/rental.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2014, 2020 Oracle and/or its affiliates. +// Copyright © 2014, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/sales_by_film_category.cs b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/sales_by_film_category.cs index dc09c05b7..3d57e8646 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/sales_by_film_category.cs +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/sales_by_film_category.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2014, 2020 Oracle and/or its affiliates. +// Copyright © 2014, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/sales_by_store.cs b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/sales_by_store.cs index 1895eab8f..b201072ba 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/sales_by_store.cs +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/sales_by_store.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2014, 2020 Oracle and/or its affiliates. +// Copyright © 2014, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/staff.cs b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/staff.cs index 74c055f33..e6b1de971 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/staff.cs +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/staff.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2014, 2020 Oracle and/or its affiliates. +// Copyright © 2014, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/staff_list.cs b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/staff_list.cs index fbc560777..8178a9b58 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/staff_list.cs +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/staff_list.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2014, 2020 Oracle and/or its affiliates. +// Copyright © 2014, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/store.cs b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/store.cs index e8874bf6e..1e06daa1f 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/store.cs +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/store.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2014, 2020 Oracle and/or its affiliates. +// Copyright © 2014, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/Ship.cs b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/Ship.cs index 67b7b304b..c84880871 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/Ship.cs +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/Ship.cs @@ -1,99 +1,99 @@ -// Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Data.Entity; - - -namespace MySql.Data.EntityFramework.CodeFirst.Tests -{ - public class Harbor - { - public int HarborId { get; set; } - public virtual ICollection Ships { get; set; } - - public string Description { get; set; } - } - - public class Ship - { - public int ShipId { get; set; } - public int HarborId { get; set; } - public virtual Harbor Harbor { get; set; } - public virtual ICollection CrewMembers { get; set; } - - public string Description { get; set; } - } - - public class CrewMember - { - public int CrewMemberId { get; set; } - public int ShipId { get; set; } - public virtual Ship Ship { get; set; } - public int RankId { get; set; } - public virtual Rank Rank { get; set; } - public int ClearanceId { get; set; } - public virtual Clearance Clearance { get; set; } - - public string Description { get; set; } - } - - public class Rank - { - public int RankId { get; set; } - public virtual ICollection CrewMembers { get; set; } - - public string Description { get; set; } - } - - public class Clearance - { - public int ClearanceId { get; set; } - public virtual ICollection CrewMembers { get; set; } - - public string Description { get; set; } - } - - [DbConfigurationType(typeof(MySqlEFConfiguration))] - public class ShipContext : DbContext - { - public DbSet Harbors { get; set; } - public DbSet Ships { get; set; } - public DbSet CrewMembers { get; set; } - public DbSet Ranks { get; set; } - public DbSet Clearances { get; set; } - - public ShipContext() : base(CodeFirstFixture.GetEFConnectionString()) - { - Database.SetInitializer(new DropCreateDatabaseAlways()); - } - } -} +// Copyright © 2013, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Data.Entity; + + +namespace MySql.Data.EntityFramework.CodeFirst.Tests +{ + public class Harbor + { + public int HarborId { get; set; } + public virtual ICollection Ships { get; set; } + + public string Description { get; set; } + } + + public class Ship + { + public int ShipId { get; set; } + public int HarborId { get; set; } + public virtual Harbor Harbor { get; set; } + public virtual ICollection CrewMembers { get; set; } + + public string Description { get; set; } + } + + public class CrewMember + { + public int CrewMemberId { get; set; } + public int ShipId { get; set; } + public virtual Ship Ship { get; set; } + public int RankId { get; set; } + public virtual Rank Rank { get; set; } + public int ClearanceId { get; set; } + public virtual Clearance Clearance { get; set; } + + public string Description { get; set; } + } + + public class Rank + { + public int RankId { get; set; } + public virtual ICollection CrewMembers { get; set; } + + public string Description { get; set; } + } + + public class Clearance + { + public int ClearanceId { get; set; } + public virtual ICollection CrewMembers { get; set; } + + public string Description { get; set; } + } + + [DbConfigurationType(typeof(MySqlEFConfiguration))] + public class ShipContext : DbContext + { + public DbSet Harbors { get; set; } + public DbSet Ships { get; set; } + public DbSet CrewMembers { get; set; } + public DbSet Ranks { get; set; } + public DbSet Clearances { get; set; } + + public ShipContext() : base(CodeFirstFixture.GetEFConnectionString()) + { + Database.SetInitializer(new DropCreateDatabaseAlways()); + } + } +} diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SiteDB.cs b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SiteDB.cs index 7910e1153..0c4ef948f 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SiteDB.cs +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SiteDB.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2014, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/TransactionTests.cs b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/TransactionTests.cs index 4a5e276b6..ad63970cc 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/TransactionTests.cs +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/TransactionTests.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2016, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/Vehicle.cs b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/Vehicle.cs index 3c579edb7..a5b8989cb 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/Vehicle.cs +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/Vehicle.cs @@ -1,362 +1,362 @@ -// Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Data.Entity; -using System.ComponentModel.DataAnnotations; -using System.ComponentModel.DataAnnotations.Schema; - - -namespace MySql.Data.EntityFramework.CodeFirst.Tests -{ - - [DbConfigurationType(typeof(MySqlEFConfiguration))] - public class VehicleDbContext : DbContext - { - public DbSet Vehicles { get; set; } - public DbSet Manufacturers { get; set; } - public DbSet Distributors { get; set; } - - public VehicleDbContext() : base(CodeFirstFixture.GetEFConnectionString()) - { - Database.SetInitializer(new VehicleDBInitializer()); - } - - protected override void OnModelCreating(DbModelBuilder modelBuilder) - { - //modelBuilder.Entity() - // .Map(o => o.ToTable("Cars")) - // .Map(o => o.ToTable("Bikes")); - modelBuilder.Entity().ToTable("Cars"); - modelBuilder.Entity().ToTable("Bikes"); - } - } - - public class VehicleDBInitializer : DropCreateDatabaseReallyAlways - { - } - - [DbConfigurationType(typeof(MySqlEFConfiguration))] - public class VehicleDbContext2 : DbContext - { - public DbSet Vehicles { get; set; } - - public VehicleDbContext2() : base(CodeFirstFixture.GetEFConnectionString()) - { - Database.SetInitializer(new VehicleDBInitializer2()); - } - } - - public class VehicleDBInitializer2 : DropCreateDatabaseReallyAlways - { - } - - /// - /// This initializer really drops the database, not just once per AppDomain (like the DropCreateDatabaseAlways). - /// - /// - public class DropCreateDatabaseReallyAlways : IDatabaseInitializer where TContext : DbContext - { - public void InitializeDatabase(TContext context) - { - context.Database.Delete(); - context.Database.CreateIfNotExists(); - this.Seed(context); - context.SaveChanges(); - } - - protected virtual void Seed(TContext context) - { - } - } - - public class Vehicle - { - public int Id { get; set; } - public int Year { get; set; } - - [MaxLength(1024)] - public string Name { get; set; } - } - - [DbConfigurationType(typeof(MySqlEFConfiguration))] - public class VehicleDbContext3 : DbContext - { - public DbSet Accessories { get; set; } - - public VehicleDbContext3() : base(CodeFirstFixture.GetEFConnectionString()) - { - - } - } - - public class Accessory - { - [Key] - [MaxLength(255)] - public string Name { get; set; } - - [Required] - [MaxLength(80000)] - public string Description { get; set; } - - [Required] - [MaxLength(16777216)] - public string LongDescription { get; set; } - - } - - public class Car : Vehicle - { - public string CarProperty { get; set; } - } - - public class Bike : Vehicle - { - public string BikeProperty { get; set; } - } - public class Vehicle2 - { - public int Id { get; set; } - public int Year { get; set; } - [MaxLength(1024)] - public string Name { get; set; } - } - - public class Car2 : Vehicle2 - { - public string CarProperty { get; set; } - } - - public class Bike2 : Vehicle2 - { - public string BikeProperty { get; set; } - } - - public class Manufacturer - { - [DatabaseGenerated(DatabaseGeneratedOption.Identity)] - public Guid ManufacturerId { get; set; } - public string Name { get; set; } - [DatabaseGenerated(DatabaseGeneratedOption.Identity)] - public Guid GroupIdentifier { get; set; } - } - - public class Distributor - { - public int DistributorId { get; set; } - public string Name { get; set; } - } - - - public class Product - { - [DatabaseGenerated(DatabaseGeneratedOption.Identity)] - public int Id { get; set; } - - [DatabaseGenerated(DatabaseGeneratedOption.Identity)] - public DateTime DateCreated { get; set; } - - [DatabaseGenerated(DatabaseGeneratedOption.Identity)] - [Column(TypeName = "timestamp")] - public DateTime Timestamp { get; set; } - - public DateTime DateTimeWithPrecision { get; set; } - - [Column(TypeName = "TimeStamp")] - public DateTime TimeStampWithPrecision { get; set; } - - } - - [DbConfigurationType(typeof(MySqlEFConfiguration))] - public class ProductsDbContext : DbContext - { - public DbSet Products { get; set; } - - public ProductsDbContext() : base(CodeFirstFixture.GetEFConnectionString()) - { - - } - - protected override void OnModelCreating(DbModelBuilder modelBuilder) - { - base.OnModelCreating(modelBuilder); - - Database.SetInitializer(new ProductDBInitializer()); - - modelBuilder.Entity() - .Property(f => f.DateTimeWithPrecision) - .HasColumnType("DateTime") - .HasPrecision(3); - - modelBuilder.Entity() - .Property(f => f.TimeStampWithPrecision) - .HasColumnType("Timestamp") - .HasPrecision(3); - - Database.SetInitializer(new MigrateDatabaseToLatestVersion>()); - } - } - - public class ProductDBInitializer : DropCreateDatabaseReallyAlways - { - } - - public class Names - { - [DatabaseGenerated(DatabaseGeneratedOption.Identity)] - public int Id { get; set; } - - public DateTime DateCreated { get; set; } - } - - [DbConfigurationType(typeof(MySqlEFConfiguration))] - public class ShortDbContext : DbContext - { - public DbSet Names { get; set; } - - public ShortDbContext() : base(CodeFirstFixture.GetEFConnectionString()) - { - - } - - protected override void OnModelCreating(DbModelBuilder modelBuilder) - { - modelBuilder.Entity() - .Property(f => f.DateCreated) - .HasColumnType("DateTime") - .HasPrecision(9); - } - } - - [DbConfigurationType(typeof(MySqlEFConfiguration))] - public class AutoIncrementBugContext : DbContext - { - public DbSet AutoIncrementBug { get; set; } - - public AutoIncrementBugContext() : base(CodeFirstFixture.GetEFConnectionString()) - { - Database.SetInitializer(new AutoIncrementBugInitialize()); - Database.SetInitializer(new DropCreateDatabaseAlways()); - } - - protected override void OnModelCreating(DbModelBuilder modelBuilder) - { - base.OnModelCreating(modelBuilder); - } - } - - public class AutoIncrementBugInitialize : IDatabaseInitializer where TContext : DbContext - { - public void InitializeDatabase(TContext context) - { - context.Database.Delete(); - context.Database.CreateIfNotExists(); - this.Seed(context); - context.SaveChanges(); - } - - protected virtual void Seed(TContext context) - { - } - } - - public class AutoIncrementBug - { - [Key] - public short MyKey { get; set; } - [DatabaseGenerated(DatabaseGeneratedOption.Identity)] - public long AutoIncrementBugId { get; set; } - public string Description { get; set; } - } - - public class AutoIncrementConfiguration : System.Data.Entity.Migrations.DbMigrationsConfiguration where TContext : DbContext - { - public AutoIncrementConfiguration() - { - AutomaticMigrationsEnabled = true; - //CodeGenerator = new MySqlMigrationCodeGenerator(); - SetSqlGenerator("MySql.Data.MySqlClient", new MySql.Data.EntityFramework.MySqlMigrationSqlGenerator()); - } - } - - - [Table("client")] - public class Client - { - [Key] - public int Id { get; set; } - public ICollection Orders { get; set; } - } - - [Table("order")] - public class Order - { - [Key] - public int Id { get; set; } - public ICollection Items { get; set; } - public ICollection Discounts { get; set; } - } - - [Table("item")] - public class Item - { - [Key] - public int Id { get; set; } - } - - [Table("discount")] - public class Discount - { - [Key] - public int Id { get; set; } - } - - - [DbConfigurationType(typeof(MySqlEFConfiguration))] - public class UsingUnionContext : DbContext - { - public DbSet Clients { get; set; } - public DbSet Items { get; set; } - - public DbSet Orders { get; set; } - - public DbSet Discounts { get; set; } - - public UsingUnionContext() : base(CodeFirstFixture.GetEFConnectionString()) - { - - } - } - - - -} +// Copyright © 2014, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Data.Entity; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; + + +namespace MySql.Data.EntityFramework.CodeFirst.Tests +{ + + [DbConfigurationType(typeof(MySqlEFConfiguration))] + public class VehicleDbContext : DbContext + { + public DbSet Vehicles { get; set; } + public DbSet Manufacturers { get; set; } + public DbSet Distributors { get; set; } + + public VehicleDbContext() : base(CodeFirstFixture.GetEFConnectionString()) + { + Database.SetInitializer(new VehicleDBInitializer()); + } + + protected override void OnModelCreating(DbModelBuilder modelBuilder) + { + //modelBuilder.Entity() + // .Map(o => o.ToTable("Cars")) + // .Map(o => o.ToTable("Bikes")); + modelBuilder.Entity().ToTable("Cars"); + modelBuilder.Entity().ToTable("Bikes"); + } + } + + public class VehicleDBInitializer : DropCreateDatabaseReallyAlways + { + } + + [DbConfigurationType(typeof(MySqlEFConfiguration))] + public class VehicleDbContext2 : DbContext + { + public DbSet Vehicles { get; set; } + + public VehicleDbContext2() : base(CodeFirstFixture.GetEFConnectionString()) + { + Database.SetInitializer(new VehicleDBInitializer2()); + } + } + + public class VehicleDBInitializer2 : DropCreateDatabaseReallyAlways + { + } + + /// + /// This initializer really drops the database, not just once per AppDomain (like the DropCreateDatabaseAlways). + /// + /// + public class DropCreateDatabaseReallyAlways : IDatabaseInitializer where TContext : DbContext + { + public void InitializeDatabase(TContext context) + { + context.Database.Delete(); + context.Database.CreateIfNotExists(); + this.Seed(context); + context.SaveChanges(); + } + + protected virtual void Seed(TContext context) + { + } + } + + public class Vehicle + { + public int Id { get; set; } + public int Year { get; set; } + + [MaxLength(1024)] + public string Name { get; set; } + } + + [DbConfigurationType(typeof(MySqlEFConfiguration))] + public class VehicleDbContext3 : DbContext + { + public DbSet Accessories { get; set; } + + public VehicleDbContext3() : base(CodeFirstFixture.GetEFConnectionString()) + { + + } + } + + public class Accessory + { + [Key] + [MaxLength(255)] + public string Name { get; set; } + + [Required] + [MaxLength(80000)] + public string Description { get; set; } + + [Required] + [MaxLength(16777216)] + public string LongDescription { get; set; } + + } + + public class Car : Vehicle + { + public string CarProperty { get; set; } + } + + public class Bike : Vehicle + { + public string BikeProperty { get; set; } + } + public class Vehicle2 + { + public int Id { get; set; } + public int Year { get; set; } + [MaxLength(1024)] + public string Name { get; set; } + } + + public class Car2 : Vehicle2 + { + public string CarProperty { get; set; } + } + + public class Bike2 : Vehicle2 + { + public string BikeProperty { get; set; } + } + + public class Manufacturer + { + [DatabaseGenerated(DatabaseGeneratedOption.Identity)] + public Guid ManufacturerId { get; set; } + public string Name { get; set; } + [DatabaseGenerated(DatabaseGeneratedOption.Identity)] + public Guid GroupIdentifier { get; set; } + } + + public class Distributor + { + public int DistributorId { get; set; } + public string Name { get; set; } + } + + + public class Product + { + [DatabaseGenerated(DatabaseGeneratedOption.Identity)] + public int Id { get; set; } + + [DatabaseGenerated(DatabaseGeneratedOption.Identity)] + public DateTime DateCreated { get; set; } + + [DatabaseGenerated(DatabaseGeneratedOption.Identity)] + [Column(TypeName = "timestamp")] + public DateTime Timestamp { get; set; } + + public DateTime DateTimeWithPrecision { get; set; } + + [Column(TypeName = "TimeStamp")] + public DateTime TimeStampWithPrecision { get; set; } + + } + + [DbConfigurationType(typeof(MySqlEFConfiguration))] + public class ProductsDbContext : DbContext + { + public DbSet Products { get; set; } + + public ProductsDbContext() : base(CodeFirstFixture.GetEFConnectionString()) + { + + } + + protected override void OnModelCreating(DbModelBuilder modelBuilder) + { + base.OnModelCreating(modelBuilder); + + Database.SetInitializer(new ProductDBInitializer()); + + modelBuilder.Entity() + .Property(f => f.DateTimeWithPrecision) + .HasColumnType("DateTime") + .HasPrecision(3); + + modelBuilder.Entity() + .Property(f => f.TimeStampWithPrecision) + .HasColumnType("Timestamp") + .HasPrecision(3); + + Database.SetInitializer(new MigrateDatabaseToLatestVersion>()); + } + } + + public class ProductDBInitializer : DropCreateDatabaseReallyAlways + { + } + + public class Names + { + [DatabaseGenerated(DatabaseGeneratedOption.Identity)] + public int Id { get; set; } + + public DateTime DateCreated { get; set; } + } + + [DbConfigurationType(typeof(MySqlEFConfiguration))] + public class ShortDbContext : DbContext + { + public DbSet Names { get; set; } + + public ShortDbContext() : base(CodeFirstFixture.GetEFConnectionString()) + { + + } + + protected override void OnModelCreating(DbModelBuilder modelBuilder) + { + modelBuilder.Entity() + .Property(f => f.DateCreated) + .HasColumnType("DateTime") + .HasPrecision(9); + } + } + + [DbConfigurationType(typeof(MySqlEFConfiguration))] + public class AutoIncrementBugContext : DbContext + { + public DbSet AutoIncrementBug { get; set; } + + public AutoIncrementBugContext() : base(CodeFirstFixture.GetEFConnectionString()) + { + Database.SetInitializer(new AutoIncrementBugInitialize()); + Database.SetInitializer(new DropCreateDatabaseAlways()); + } + + protected override void OnModelCreating(DbModelBuilder modelBuilder) + { + base.OnModelCreating(modelBuilder); + } + } + + public class AutoIncrementBugInitialize : IDatabaseInitializer where TContext : DbContext + { + public void InitializeDatabase(TContext context) + { + context.Database.Delete(); + context.Database.CreateIfNotExists(); + this.Seed(context); + context.SaveChanges(); + } + + protected virtual void Seed(TContext context) + { + } + } + + public class AutoIncrementBug + { + [Key] + public short MyKey { get; set; } + [DatabaseGenerated(DatabaseGeneratedOption.Identity)] + public long AutoIncrementBugId { get; set; } + public string Description { get; set; } + } + + public class AutoIncrementConfiguration : System.Data.Entity.Migrations.DbMigrationsConfiguration where TContext : DbContext + { + public AutoIncrementConfiguration() + { + AutomaticMigrationsEnabled = true; + //CodeGenerator = new MySqlMigrationCodeGenerator(); + SetSqlGenerator("MySql.Data.MySqlClient", new MySql.Data.EntityFramework.MySqlMigrationSqlGenerator()); + } + } + + + [Table("client")] + public class Client + { + [Key] + public int Id { get; set; } + public ICollection Orders { get; set; } + } + + [Table("order")] + public class Order + { + [Key] + public int Id { get; set; } + public ICollection Items { get; set; } + public ICollection Discounts { get; set; } + } + + [Table("item")] + public class Item + { + [Key] + public int Id { get; set; } + } + + [Table("discount")] + public class Discount + { + [Key] + public int Id { get; set; } + } + + + [DbConfigurationType(typeof(MySqlEFConfiguration))] + public class UsingUnionContext : DbContext + { + public DbSet Clients { get; set; } + public DbSet Items { get; set; } + + public DbSet Orders { get; set; } + + public DbSet Discounts { get; set; } + + public UsingUnionContext() : base(CodeFirstFixture.GetEFConnectionString()) + { + + } + } + + + +} diff --git a/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/BlogsModel.cs b/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/BlogsModel.cs index 9e0086c75..c83ee138e 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/BlogsModel.cs +++ b/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/BlogsModel.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2013, 2020 Oracle and/or its affiliates. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/MyConfiguration.cs b/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/MyConfiguration.cs index 25cab30ef..79e6de550 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/MyConfiguration.cs +++ b/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/MyConfiguration.cs @@ -1,16 +1,16 @@ -// Copyright © 2013, 2017, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/MySqlMigrationsTests.cs b/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/MySqlMigrationsTests.cs index e0dd5f6c7..bf2974f29 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/MySqlMigrationsTests.cs +++ b/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/MySqlMigrationsTests.cs @@ -1,460 +1,460 @@ -// Copyright (c) 2013, 2020 Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using System; -using System.Collections.Generic; -using System.Data.Entity; -using System.Data.Entity.Infrastructure; -using System.Data.Entity.Migrations.Model; -using System.Data.Entity.Migrations.Sql; -using System.Linq; -using NUnit.Framework; -using MySql.Data.MySqlClient; -using System.Data.Entity.Core.EntityClient; -using System.Data.Entity.Core.Metadata.Edm; - -namespace MySql.Data.EntityFramework.Migrations.Tests -{ - public class MySqlMigrationsTests : SetUpMigrationsTests - { - private MySqlProviderManifest ProviderManifest; - - public MySqlMigrationsTests() - { - Database.SetInitializer(new MigrateDatabaseToLatestVersion()); - } - - private MySqlConnection GetConnectionFromContext(DbContext ctx) - { - return (MySqlConnection)((EntityConnection)(((IObjectContextAdapter)ctx).ObjectContext.Connection)).StoreConnection; - } - - /// - /// Add int32 type column to existing table - /// - [Test] - public void AddColumnOperationMigration() - { - var migrationOperations = new List(); - - if (ProviderManifest == null) - ProviderManifest = new MySqlProviderManifest(Version.ToString()); - - TypeUsage tu = TypeUsage.CreateDefaultTypeUsage(PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.Int32)); - TypeUsage result = ProviderManifest.GetStoreType(tu); - - var intColumn = new ColumnModel(PrimitiveTypeKind.Int32, result) - { - Name = "TotalPosts", - IsNullable = false - }; - - var addColumnMigratioOperation = new AddColumnOperation("Blogs", intColumn); - migrationOperations.Add(addColumnMigratioOperation); - - using (BlogContext context = new BlogContext()) - { - if (context.Database.Exists()) context.Database.Delete(); - context.Database.Create(); - - using (MySqlConnection conn = new MySqlConnection(context.Database.Connection.ConnectionString)) - { - if (conn.State == System.Data.ConnectionState.Closed) conn.Open(); - Assert.AreEqual(true, GenerateAndExecuteMySQLStatements(migrationOperations)); - - MySqlCommand query = new MySqlCommand("Select Column_name, Is_Nullable, Data_Type from information_schema.Columns where table_schema ='" + conn.Database + "' and table_name = 'Blogs' and column_name ='TotalPosts'", conn); - MySqlDataReader reader = query.ExecuteReader(); - while (reader.Read()) - { - Assert.AreEqual("TotalPosts", reader[0].ToString()); - Assert.AreEqual("NO", reader[1].ToString()); - Assert.AreEqual("int", reader[2].ToString()); - } - reader.Close(); - conn.Close(); - } - } - } - - /// - /// CreateTable operation - /// with the following columns int PostId string Title string Body - /// - [Test] - public void CreateTableOperationMigration() - { - - var migrationOperations = new List(); - var createTableOperation = CreateTableOperation(); - - migrationOperations.Add(createTableOperation); - - using (BlogContext context = new BlogContext()) - { - if (context.Database.Exists()) context.Database.Delete(); - context.Database.Create(); - - using (var conn = new MySqlConnection(context.Database.Connection.ConnectionString)) - { - if (conn.State == System.Data.ConnectionState.Closed) conn.Open(); - Assert.True(GenerateAndExecuteMySQLStatements(migrationOperations)); - using (MySqlCommand query = new MySqlCommand($"SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA ='{conn.Database}'" + - $" AND TABLE_NAME = 'Posts'", conn)) - { - using (MySqlDataReader reader = query.ExecuteReader()) - { - while (reader.Read()) - Assert.That(createTableOperation.Columns.Where(t => t.Name.Equals(reader[0].ToString())), Has.One.Items); - reader.Close(); - } - - - query.CommandText = $"SELECT COLUMN_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = '{conn.Database}' AND " + - $"TABLE_NAME = 'Posts' AND COLUMN_NAME = 'Password'"; - - StringAssert.AreEqualIgnoringCase("binary(10)", query.ExecuteScalar().ToString()); - } - } - } - } - - /// - /// CreateForeignKey operation - /// between Blogs and Posts table - /// - [Test] - public void CreateForeignKeyOperation() - { - var migrationOperations = new List(); - - // create dependant table Posts - var createTableOperation = CreateTableOperation(); - migrationOperations.Add(createTableOperation); - - // Add column BlogId to create the constraints - - if (ProviderManifest == null) - ProviderManifest = new MySqlProviderManifest(Version.ToString()); - - TypeUsage tu = TypeUsage.CreateDefaultTypeUsage(PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.Int32)); - TypeUsage result = ProviderManifest.GetStoreType(tu); - - var intColumn = new ColumnModel(PrimitiveTypeKind.Int32, result) - { - Name = "BlogId", - IsNullable = false - }; - - var addColumnMigratioOperation = new AddColumnOperation("Posts", intColumn); - migrationOperations.Add(addColumnMigratioOperation); - - // create constrain object - var createForeignkeyOperation = new AddForeignKeyOperation(); - - createForeignkeyOperation.Name = "FKBlogs"; - createForeignkeyOperation.DependentTable = "Posts"; - createForeignkeyOperation.DependentColumns.Add("BlogId"); - createForeignkeyOperation.CascadeDelete = true; - createForeignkeyOperation.PrincipalTable = "Blogs"; - createForeignkeyOperation.PrincipalColumns.Add("BlogId"); - - //create index to use - migrationOperations.Add(createForeignkeyOperation.CreateCreateIndexOperation()); - - migrationOperations.Add(createForeignkeyOperation); - - - using (BlogContext context = new BlogContext()) - { - - if (context.Database.Exists()) context.Database.Delete(); - context.Database.Create(); - - Assert.AreEqual(true, GenerateAndExecuteMySQLStatements(migrationOperations)); - - using (var conn = new MySqlConnection(context.Database.Connection.ConnectionString)) - { - if (conn.State == System.Data.ConnectionState.Closed) conn.Open(); - // check for foreign key creation - MySqlCommand query = new MySqlCommand("select Count(*) from information_schema.table_constraints where LOWER(constraint_type) = 'foreign key' and constraint_schema = '" + conn.Database + "' and constraint_name = 'FKBlogs'", conn); - int rows = Convert.ToInt32(query.ExecuteScalar()); - Assert.AreEqual(1, rows); - // check for table creation - query = new MySqlCommand("select Count(*) from information_schema.Tables WHERE `table_name` = 'Posts' and `table_schema` = '" + conn.Database + "' ", conn); - rows = Convert.ToInt32(query.ExecuteScalar()); - Assert.AreEqual(1, rows); - conn.Close(); - } - - // Test fix for - MySqlConnection con = GetConnectionFromContext(context); - con.Open(); - try - { - MySqlCommand cmd = new MySqlCommand("show create table `Posts`", con); - using (MySqlDataReader r = cmd.ExecuteReader()) - { - r.Read(); - string sql = r.GetString(1); - Assert.True(sql.IndexOf( - " CONSTRAINT `FKBlogs` FOREIGN KEY (`BlogId`) REFERENCES `blogs` (`BlogId`) ON DELETE CASCADE ON UPDATE CASCADE", - StringComparison.OrdinalIgnoreCase) != -1); - } - } - finally - { - con.Close(); - } - } - } - - - /// - /// Remove PK and the autoincrement property for the column - /// - - [Test] - public void DropPrimaryKeyOperationWithAnonymousArguments() - { - - var migrationOperations = new List(); - - // create table where the PK exists - var createTableOperation = CreateTableOperation(); - migrationOperations.Add(createTableOperation); - - var createDropPKOperation = new DropPrimaryKeyOperation(anonymousArguments: new { DeleteAutoIncrement = true }); - createDropPKOperation.Table = "Posts"; - createDropPKOperation.Columns.Add("PostId"); - migrationOperations.Add(createDropPKOperation); - - using (BlogContext context = new BlogContext()) - { - if (context.Database.Exists()) context.Database.Delete(); - context.Database.Create(); - - - Assert.AreEqual(true, GenerateAndExecuteMySQLStatements(migrationOperations)); - - using (var conn = new MySqlConnection(context.Database.Connection.ConnectionString)) - { - if (conn.State == System.Data.ConnectionState.Closed) conn.Open(); - - // check for table creation - var query = new MySqlCommand("select Count(*) from information_schema.Tables WHERE `table_name` = 'Posts' and `table_schema` = '" + conn.Database + "' ", conn); - int rows = Convert.ToInt32(query.ExecuteScalar()); - Assert.AreEqual(1, rows); - - // check if PK exists - query = new MySqlCommand("select Count(*) from information_schema.table_constraints where `constraint_type` = 'primary key' and `constraint_schema` = '" + conn.Database + "' and table_name= 'Posts'", conn); - rows = Convert.ToInt32(query.ExecuteScalar()); - Assert.AreEqual(0, rows); - - //check the definition of the column that was PK - query = new MySqlCommand("Select Column_name, Is_Nullable, Data_Type from information_schema.Columns where table_schema ='" + conn.Database + "' and table_name = 'Posts' and column_name ='PostId'", conn); - MySqlDataReader reader = query.ExecuteReader(); - while (reader.Read()) - { - Assert.AreEqual("PostId", reader[0].ToString()); - Assert.AreEqual("NO", reader[1].ToString()); - Assert.AreEqual("int", reader[2].ToString()); - } - reader.Close(); - conn.Close(); - } - } - } - - - /// - /// Drop primary key. No anonymous arguments - /// - [Test] - public void DropPrimaryKeyOperation() - { - - var migrationOperations = new List(); - - // create table where the PK exists - var createTableOperation = CreateTableOperation(); - migrationOperations.Add(createTableOperation); - - var createDropPKOperation = new DropPrimaryKeyOperation(anonymousArguments: new { DeleteAutoIncrement = true }); - createDropPKOperation.Table = "Posts"; - createDropPKOperation.Columns.Add("PostId"); - migrationOperations.Add(createDropPKOperation); - - using (BlogContext context = new BlogContext()) - { - if (context.Database.Exists()) context.Database.Delete(); - context.Database.Create(); - - - Assert.AreEqual(true, GenerateAndExecuteMySQLStatements(migrationOperations)); - - using (var conn = new MySqlConnection(context.Database.Connection.ConnectionString)) - { - if (conn.State == System.Data.ConnectionState.Closed) conn.Open(); - - // check for table creation - var query = new MySqlCommand("select Count(*) from information_schema.Tables WHERE `table_name` = 'Posts' and `table_schema` = '" + conn.Database + "' ", conn); - int rows = Convert.ToInt32(query.ExecuteScalar()); - Assert.AreEqual(1, rows); - - // check if PK exists - query = new MySqlCommand("select Count(*) from information_schema.table_constraints where `constraint_type` = 'primary key' and `constraint_schema` = '" + conn.Database + "' and table_name= 'Posts'", conn); - rows = Convert.ToInt32(query.ExecuteScalar()); - Assert.AreEqual(0, rows); - - //check the definition of the column that was PK - query = new MySqlCommand("Select Column_name, Is_Nullable, Data_Type from information_schema.Columns where table_schema ='" + conn.Database + "' and table_name = 'Posts' and column_name ='PostId'", conn); - MySqlDataReader reader = query.ExecuteReader(); - while (reader.Read()) - { - Assert.AreEqual("PostId", reader[0].ToString()); - Assert.AreEqual("NO", reader[1].ToString()); - Assert.AreEqual("int", reader[2].ToString()); - } - reader.Close(); - conn.Close(); - } - } - } - - - /// - /// Creates a table named Posts - /// and columns int PostId, string Title, string Body - /// - /// - - private CreateTableOperation CreateTableOperation() - { - TypeUsage tu; - TypeUsage result; - - if (ProviderManifest == null) - ProviderManifest = new MySqlProviderManifest(Version.ToString()); - - var createTableOperation = new CreateTableOperation("Posts"); - - //Column model for int IdPost - tu = TypeUsage.CreateDefaultTypeUsage(PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.Int32)); - result = ProviderManifest.GetStoreType(tu); - - var intColumn = new ColumnModel(PrimitiveTypeKind.Int32, result) - { - Name = "PostId", - IsNullable = false, - IsIdentity = true - }; - - createTableOperation.Columns.Add(intColumn); - - //Column model for string - tu = TypeUsage.CreateDefaultTypeUsage(PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.String)); - result = ProviderManifest.GetStoreType(tu); - - var stringColumnTitle = new ColumnModel(PrimitiveTypeKind.String, result) - { - Name = "Title", - IsNullable = false - }; - - var stringColumnBody = new ColumnModel(PrimitiveTypeKind.String, result) - { - Name = "Body", - IsNullable = true - }; - - createTableOperation.Columns.Add(stringColumnTitle); - createTableOperation.Columns.Add(stringColumnBody); - - //Column model for binary - tu = TypeUsage.CreateDefaultTypeUsage(PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.Binary)); - result = ProviderManifest.GetStoreType(tu); - - var binaryColumn = new ColumnModel(PrimitiveTypeKind.Binary, result) - { - Name = "Password", - MaxLength = 10, - StoreType = "binary" - }; - - createTableOperation.Columns.Add(binaryColumn); - - var primaryKey = new AddPrimaryKeyOperation(); - - primaryKey.Columns.Add("PostId"); - - createTableOperation.PrimaryKey = primaryKey; - - return createTableOperation; - - } - - - /// - /// Generate and apply sql statemens from the - /// migration operations list - /// return false is case of fail or if database doesn't exist - /// - private bool GenerateAndExecuteMySQLStatements(List migrationOperations) - { - MySqlProviderServices ProviderServices; - - ProviderServices = new MySqlProviderServices(); - - using (BlogContext context = new BlogContext()) - { - if (!context.Database.Exists()) return false; - - using (MySqlConnection conn = new MySqlConnection(context.Database.Connection.ConnectionString)) - { - var migratorGenerator = new MySqlMigrationSqlGenerator(); - var Token = ProviderServices.GetProviderManifestToken(conn); - var sqlStmts = migratorGenerator.Generate(migrationOperations, providerManifestToken: Token); - if (conn.State == System.Data.ConnectionState.Closed) conn.Open(); - foreach (MigrationStatement stmt in sqlStmts) - { - try - { - MySqlCommand cmd = new MySqlCommand(stmt.Sql, conn); - cmd.ExecuteNonQuery(); - } - catch (Exception) - { - return false; - } - } - } - } - return true; - } - } -} \ No newline at end of file +// Copyright © 2013, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using System; +using System.Collections.Generic; +using System.Data.Entity; +using System.Data.Entity.Infrastructure; +using System.Data.Entity.Migrations.Model; +using System.Data.Entity.Migrations.Sql; +using System.Linq; +using NUnit.Framework; +using MySql.Data.MySqlClient; +using System.Data.Entity.Core.EntityClient; +using System.Data.Entity.Core.Metadata.Edm; + +namespace MySql.Data.EntityFramework.Migrations.Tests +{ + public class MySqlMigrationsTests : SetUpMigrationsTests + { + private MySqlProviderManifest ProviderManifest; + + public MySqlMigrationsTests() + { + Database.SetInitializer(new MigrateDatabaseToLatestVersion()); + } + + private MySqlConnection GetConnectionFromContext(DbContext ctx) + { + return (MySqlConnection)((EntityConnection)(((IObjectContextAdapter)ctx).ObjectContext.Connection)).StoreConnection; + } + + /// + /// Add int32 type column to existing table + /// + [Test] + public void AddColumnOperationMigration() + { + var migrationOperations = new List(); + + if (ProviderManifest == null) + ProviderManifest = new MySqlProviderManifest(Version.ToString()); + + TypeUsage tu = TypeUsage.CreateDefaultTypeUsage(PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.Int32)); + TypeUsage result = ProviderManifest.GetStoreType(tu); + + var intColumn = new ColumnModel(PrimitiveTypeKind.Int32, result) + { + Name = "TotalPosts", + IsNullable = false + }; + + var addColumnMigratioOperation = new AddColumnOperation("Blogs", intColumn); + migrationOperations.Add(addColumnMigratioOperation); + + using (BlogContext context = new BlogContext()) + { + if (context.Database.Exists()) context.Database.Delete(); + context.Database.Create(); + + using (MySqlConnection conn = new MySqlConnection(context.Database.Connection.ConnectionString)) + { + if (conn.State == System.Data.ConnectionState.Closed) conn.Open(); + Assert.AreEqual(true, GenerateAndExecuteMySQLStatements(migrationOperations)); + + MySqlCommand query = new MySqlCommand("Select Column_name, Is_Nullable, Data_Type from information_schema.Columns where table_schema ='" + conn.Database + "' and table_name = 'Blogs' and column_name ='TotalPosts'", conn); + MySqlDataReader reader = query.ExecuteReader(); + while (reader.Read()) + { + Assert.AreEqual("TotalPosts", reader[0].ToString()); + Assert.AreEqual("NO", reader[1].ToString()); + Assert.AreEqual("int", reader[2].ToString()); + } + reader.Close(); + conn.Close(); + } + } + } + + /// + /// CreateTable operation + /// with the following columns int PostId string Title string Body + /// + [Test] + public void CreateTableOperationMigration() + { + + var migrationOperations = new List(); + var createTableOperation = CreateTableOperation(); + + migrationOperations.Add(createTableOperation); + + using (BlogContext context = new BlogContext()) + { + if (context.Database.Exists()) context.Database.Delete(); + context.Database.Create(); + + using (var conn = new MySqlConnection(context.Database.Connection.ConnectionString)) + { + if (conn.State == System.Data.ConnectionState.Closed) conn.Open(); + Assert.True(GenerateAndExecuteMySQLStatements(migrationOperations)); + using (MySqlCommand query = new MySqlCommand($"SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA ='{conn.Database}'" + + $" AND TABLE_NAME = 'Posts'", conn)) + { + using (MySqlDataReader reader = query.ExecuteReader()) + { + while (reader.Read()) + Assert.That(createTableOperation.Columns.Where(t => t.Name.Equals(reader[0].ToString())), Has.One.Items); + reader.Close(); + } + + + query.CommandText = $"SELECT COLUMN_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = '{conn.Database}' AND " + + $"TABLE_NAME = 'Posts' AND COLUMN_NAME = 'Password'"; + + StringAssert.AreEqualIgnoringCase("binary(10)", query.ExecuteScalar().ToString()); + } + } + } + } + + /// + /// CreateForeignKey operation + /// between Blogs and Posts table + /// + [Test] + public void CreateForeignKeyOperation() + { + var migrationOperations = new List(); + + // create dependant table Posts + var createTableOperation = CreateTableOperation(); + migrationOperations.Add(createTableOperation); + + // Add column BlogId to create the constraints + + if (ProviderManifest == null) + ProviderManifest = new MySqlProviderManifest(Version.ToString()); + + TypeUsage tu = TypeUsage.CreateDefaultTypeUsage(PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.Int32)); + TypeUsage result = ProviderManifest.GetStoreType(tu); + + var intColumn = new ColumnModel(PrimitiveTypeKind.Int32, result) + { + Name = "BlogId", + IsNullable = false + }; + + var addColumnMigratioOperation = new AddColumnOperation("Posts", intColumn); + migrationOperations.Add(addColumnMigratioOperation); + + // create constrain object + var createForeignkeyOperation = new AddForeignKeyOperation(); + + createForeignkeyOperation.Name = "FKBlogs"; + createForeignkeyOperation.DependentTable = "Posts"; + createForeignkeyOperation.DependentColumns.Add("BlogId"); + createForeignkeyOperation.CascadeDelete = true; + createForeignkeyOperation.PrincipalTable = "Blogs"; + createForeignkeyOperation.PrincipalColumns.Add("BlogId"); + + //create index to use + migrationOperations.Add(createForeignkeyOperation.CreateCreateIndexOperation()); + + migrationOperations.Add(createForeignkeyOperation); + + + using (BlogContext context = new BlogContext()) + { + + if (context.Database.Exists()) context.Database.Delete(); + context.Database.Create(); + + Assert.AreEqual(true, GenerateAndExecuteMySQLStatements(migrationOperations)); + + using (var conn = new MySqlConnection(context.Database.Connection.ConnectionString)) + { + if (conn.State == System.Data.ConnectionState.Closed) conn.Open(); + // check for foreign key creation + MySqlCommand query = new MySqlCommand("select Count(*) from information_schema.table_constraints where LOWER(constraint_type) = 'foreign key' and constraint_schema = '" + conn.Database + "' and constraint_name = 'FKBlogs'", conn); + int rows = Convert.ToInt32(query.ExecuteScalar()); + Assert.AreEqual(1, rows); + // check for table creation + query = new MySqlCommand("select Count(*) from information_schema.Tables WHERE `table_name` = 'Posts' and `table_schema` = '" + conn.Database + "' ", conn); + rows = Convert.ToInt32(query.ExecuteScalar()); + Assert.AreEqual(1, rows); + conn.Close(); + } + + // Test fix for + MySqlConnection con = GetConnectionFromContext(context); + con.Open(); + try + { + MySqlCommand cmd = new MySqlCommand("show create table `Posts`", con); + using (MySqlDataReader r = cmd.ExecuteReader()) + { + r.Read(); + string sql = r.GetString(1); + Assert.True(sql.IndexOf( + " CONSTRAINT `FKBlogs` FOREIGN KEY (`BlogId`) REFERENCES `blogs` (`BlogId`) ON DELETE CASCADE ON UPDATE CASCADE", + StringComparison.OrdinalIgnoreCase) != -1); + } + } + finally + { + con.Close(); + } + } + } + + + /// + /// Remove PK and the autoincrement property for the column + /// + + [Test] + public void DropPrimaryKeyOperationWithAnonymousArguments() + { + + var migrationOperations = new List(); + + // create table where the PK exists + var createTableOperation = CreateTableOperation(); + migrationOperations.Add(createTableOperation); + + var createDropPKOperation = new DropPrimaryKeyOperation(anonymousArguments: new { DeleteAutoIncrement = true }); + createDropPKOperation.Table = "Posts"; + createDropPKOperation.Columns.Add("PostId"); + migrationOperations.Add(createDropPKOperation); + + using (BlogContext context = new BlogContext()) + { + if (context.Database.Exists()) context.Database.Delete(); + context.Database.Create(); + + + Assert.AreEqual(true, GenerateAndExecuteMySQLStatements(migrationOperations)); + + using (var conn = new MySqlConnection(context.Database.Connection.ConnectionString)) + { + if (conn.State == System.Data.ConnectionState.Closed) conn.Open(); + + // check for table creation + var query = new MySqlCommand("select Count(*) from information_schema.Tables WHERE `table_name` = 'Posts' and `table_schema` = '" + conn.Database + "' ", conn); + int rows = Convert.ToInt32(query.ExecuteScalar()); + Assert.AreEqual(1, rows); + + // check if PK exists + query = new MySqlCommand("select Count(*) from information_schema.table_constraints where `constraint_type` = 'primary key' and `constraint_schema` = '" + conn.Database + "' and table_name= 'Posts'", conn); + rows = Convert.ToInt32(query.ExecuteScalar()); + Assert.AreEqual(0, rows); + + //check the definition of the column that was PK + query = new MySqlCommand("Select Column_name, Is_Nullable, Data_Type from information_schema.Columns where table_schema ='" + conn.Database + "' and table_name = 'Posts' and column_name ='PostId'", conn); + MySqlDataReader reader = query.ExecuteReader(); + while (reader.Read()) + { + Assert.AreEqual("PostId", reader[0].ToString()); + Assert.AreEqual("NO", reader[1].ToString()); + Assert.AreEqual("int", reader[2].ToString()); + } + reader.Close(); + conn.Close(); + } + } + } + + + /// + /// Drop primary key. No anonymous arguments + /// + [Test] + public void DropPrimaryKeyOperation() + { + + var migrationOperations = new List(); + + // create table where the PK exists + var createTableOperation = CreateTableOperation(); + migrationOperations.Add(createTableOperation); + + var createDropPKOperation = new DropPrimaryKeyOperation(anonymousArguments: new { DeleteAutoIncrement = true }); + createDropPKOperation.Table = "Posts"; + createDropPKOperation.Columns.Add("PostId"); + migrationOperations.Add(createDropPKOperation); + + using (BlogContext context = new BlogContext()) + { + if (context.Database.Exists()) context.Database.Delete(); + context.Database.Create(); + + + Assert.AreEqual(true, GenerateAndExecuteMySQLStatements(migrationOperations)); + + using (var conn = new MySqlConnection(context.Database.Connection.ConnectionString)) + { + if (conn.State == System.Data.ConnectionState.Closed) conn.Open(); + + // check for table creation + var query = new MySqlCommand("select Count(*) from information_schema.Tables WHERE `table_name` = 'Posts' and `table_schema` = '" + conn.Database + "' ", conn); + int rows = Convert.ToInt32(query.ExecuteScalar()); + Assert.AreEqual(1, rows); + + // check if PK exists + query = new MySqlCommand("select Count(*) from information_schema.table_constraints where `constraint_type` = 'primary key' and `constraint_schema` = '" + conn.Database + "' and table_name= 'Posts'", conn); + rows = Convert.ToInt32(query.ExecuteScalar()); + Assert.AreEqual(0, rows); + + //check the definition of the column that was PK + query = new MySqlCommand("Select Column_name, Is_Nullable, Data_Type from information_schema.Columns where table_schema ='" + conn.Database + "' and table_name = 'Posts' and column_name ='PostId'", conn); + MySqlDataReader reader = query.ExecuteReader(); + while (reader.Read()) + { + Assert.AreEqual("PostId", reader[0].ToString()); + Assert.AreEqual("NO", reader[1].ToString()); + Assert.AreEqual("int", reader[2].ToString()); + } + reader.Close(); + conn.Close(); + } + } + } + + + /// + /// Creates a table named Posts + /// and columns int PostId, string Title, string Body + /// + /// + + private CreateTableOperation CreateTableOperation() + { + TypeUsage tu; + TypeUsage result; + + if (ProviderManifest == null) + ProviderManifest = new MySqlProviderManifest(Version.ToString()); + + var createTableOperation = new CreateTableOperation("Posts"); + + //Column model for int IdPost + tu = TypeUsage.CreateDefaultTypeUsage(PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.Int32)); + result = ProviderManifest.GetStoreType(tu); + + var intColumn = new ColumnModel(PrimitiveTypeKind.Int32, result) + { + Name = "PostId", + IsNullable = false, + IsIdentity = true + }; + + createTableOperation.Columns.Add(intColumn); + + //Column model for string + tu = TypeUsage.CreateDefaultTypeUsage(PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.String)); + result = ProviderManifest.GetStoreType(tu); + + var stringColumnTitle = new ColumnModel(PrimitiveTypeKind.String, result) + { + Name = "Title", + IsNullable = false + }; + + var stringColumnBody = new ColumnModel(PrimitiveTypeKind.String, result) + { + Name = "Body", + IsNullable = true + }; + + createTableOperation.Columns.Add(stringColumnTitle); + createTableOperation.Columns.Add(stringColumnBody); + + //Column model for binary + tu = TypeUsage.CreateDefaultTypeUsage(PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.Binary)); + result = ProviderManifest.GetStoreType(tu); + + var binaryColumn = new ColumnModel(PrimitiveTypeKind.Binary, result) + { + Name = "Password", + MaxLength = 10, + StoreType = "binary" + }; + + createTableOperation.Columns.Add(binaryColumn); + + var primaryKey = new AddPrimaryKeyOperation(); + + primaryKey.Columns.Add("PostId"); + + createTableOperation.PrimaryKey = primaryKey; + + return createTableOperation; + + } + + + /// + /// Generate and apply sql statemens from the + /// migration operations list + /// return false is case of fail or if database doesn't exist + /// + private bool GenerateAndExecuteMySQLStatements(List migrationOperations) + { + MySqlProviderServices ProviderServices; + + ProviderServices = new MySqlProviderServices(); + + using (BlogContext context = new BlogContext()) + { + if (!context.Database.Exists()) return false; + + using (MySqlConnection conn = new MySqlConnection(context.Database.Connection.ConnectionString)) + { + var migratorGenerator = new MySqlMigrationSqlGenerator(); + var Token = ProviderServices.GetProviderManifestToken(conn); + var sqlStmts = migratorGenerator.Generate(migrationOperations, providerManifestToken: Token); + if (conn.State == System.Data.ConnectionState.Closed) conn.Open(); + foreach (MigrationStatement stmt in sqlStmts) + { + try + { + MySqlCommand cmd = new MySqlCommand(stmt.Sql, conn); + cmd.ExecuteNonQuery(); + } + catch (Exception) + { + return false; + } + } + } + } + return true; + } + } +} diff --git a/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/Properties/AssemblyInfo.cs b/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/Properties/AssemblyInfo.cs index a28f3ab9c..4c56279e1 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/Properties/AssemblyInfo.cs +++ b/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/Properties/AssemblyInfo.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -54,4 +54,4 @@ #if !DEBUG [assembly: AssemblyKeyName("ConnectorNet")] #endif -[assembly: NonParallelizable] \ No newline at end of file +[assembly: NonParallelizable] diff --git a/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/SetUpMigrationsTests.cs b/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/SetUpMigrationsTests.cs index 7bb327775..62d31c7d6 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/SetUpMigrationsTests.cs +++ b/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/SetUpMigrationsTests.cs @@ -1,115 +1,115 @@ -// Copyright (c) 2013, 2023 Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySql.Data.EntityFramework.Properties; -using MySql.Data.EntityFramework.Tests; -using NUnit.Framework; -using System; -using System.Configuration; -using System.Data; -using System.Data.Entity.Migrations; -using System.IO; -using System.Reflection; -using System.Runtime.InteropServices; - -namespace MySql.Data.EntityFramework.Migrations.Tests -{ - public class SetUpMigrationsTests : DefaultFixture - { - - private Configuration configuration; - public DbMigrator Migrator; - public static string ConnectionStringBlogContext { get; set; } - - [OneTimeSetUp] - public new void OneTimeSetup() - { - ConnectionStringBlogContext = RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? MySql.EntityFramework.Migrations.Tests.Properties.Resources.ConnStringMacOS : MySql.EntityFramework.Migrations.Tests.Properties.Resources.ConnString; - - configuration = new Configuration(); - DataSet dataSet = ConfigurationManager.GetSection("system.data") as System.Data.DataSet; - if (dataSet != null) - { - DataView vi = dataSet.Tables[0].DefaultView; - vi.Sort = "Name"; - int idx = -1; - if (((idx = vi.Find("MySql")) != -1) || ((idx = vi.Find("MySQL Data Provider")) != -1)) - { - DataRow row = vi[idx].Row; - dataSet.Tables[0].Rows.Remove(row); - } - dataSet.Tables[0].Rows.Add("MySql" - , "MySql.Data.MySqlClient" - , "MySql.Data.MySqlClient" - , - typeof(MySql.Data.MySqlClient.MySqlClientFactory).AssemblyQualifiedName); - } - Migrator = new DbMigrator(configuration); - } - - [OneTimeTearDown] - public new void OneTimeTearDown() - { - using (BlogContext context = new BlogContext()) - { - if (context.Database.Exists()) - { - context.Database.Delete(); - } - } - } - } - - internal sealed class Configuration : DbMigrationsConfiguration - { - public Configuration() - { - CodeGenerator = new MySqlMigrationCodeGenerator(); - AutomaticMigrationsEnabled = false; - SetSqlGenerator("MySql.Data.MySqlClient", new MySql.Data.EntityFramework.MySqlMigrationSqlGenerator()); - } - - protected override void Seed(BlogContext context) - { - } - } - - internal sealed class EF6Configuration : DbMigrationsConfiguration - { - public EF6Configuration() - { - CodeGenerator = new MySqlMigrationCodeGenerator(); - AutomaticMigrationsEnabled = true; - SetSqlGenerator("MySql.Data.MySqlClient", new MySql.Data.EntityFramework.MySqlMigrationSqlGenerator()); - } - - protected override void Seed(BlogContext context) - { - } - } -} \ No newline at end of file +// Copyright © 2013, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySql.Data.EntityFramework.Properties; +using MySql.Data.EntityFramework.Tests; +using NUnit.Framework; +using System; +using System.Configuration; +using System.Data; +using System.Data.Entity.Migrations; +using System.IO; +using System.Reflection; +using System.Runtime.InteropServices; + +namespace MySql.Data.EntityFramework.Migrations.Tests +{ + public class SetUpMigrationsTests : DefaultFixture + { + + private Configuration configuration; + public DbMigrator Migrator; + public static string ConnectionStringBlogContext { get; set; } + + [OneTimeSetUp] + public new void OneTimeSetup() + { + ConnectionStringBlogContext = RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? MySql.EntityFramework.Migrations.Tests.Properties.Resources.ConnStringMacOS : MySql.EntityFramework.Migrations.Tests.Properties.Resources.ConnString; + + configuration = new Configuration(); + DataSet dataSet = ConfigurationManager.GetSection("system.data") as System.Data.DataSet; + if (dataSet != null) + { + DataView vi = dataSet.Tables[0].DefaultView; + vi.Sort = "Name"; + int idx = -1; + if (((idx = vi.Find("MySql")) != -1) || ((idx = vi.Find("MySQL Data Provider")) != -1)) + { + DataRow row = vi[idx].Row; + dataSet.Tables[0].Rows.Remove(row); + } + dataSet.Tables[0].Rows.Add("MySql" + , "MySql.Data.MySqlClient" + , "MySql.Data.MySqlClient" + , + typeof(MySql.Data.MySqlClient.MySqlClientFactory).AssemblyQualifiedName); + } + Migrator = new DbMigrator(configuration); + } + + [OneTimeTearDown] + public new void OneTimeTearDown() + { + using (BlogContext context = new BlogContext()) + { + if (context.Database.Exists()) + { + context.Database.Delete(); + } + } + } + } + + internal sealed class Configuration : DbMigrationsConfiguration + { + public Configuration() + { + CodeGenerator = new MySqlMigrationCodeGenerator(); + AutomaticMigrationsEnabled = false; + SetSqlGenerator("MySql.Data.MySqlClient", new MySql.Data.EntityFramework.MySqlMigrationSqlGenerator()); + } + + protected override void Seed(BlogContext context) + { + } + } + + internal sealed class EF6Configuration : DbMigrationsConfiguration + { + public EF6Configuration() + { + CodeGenerator = new MySqlMigrationCodeGenerator(); + AutomaticMigrationsEnabled = true; + SetSqlGenerator("MySql.Data.MySqlClient", new MySql.Data.EntityFramework.MySqlMigrationSqlGenerator()); + } + + protected override void Seed(BlogContext context) + { + } + } +} diff --git a/LICENSE b/LICENSE index 48062d95d..8e4d63098 100644 --- a/LICENSE +++ b/LICENSE @@ -19,13 +19,14 @@ Licensing Information of the GNU General Public License (GPLv2), as set forth below, with the following additional permissions: - This distribution of MySQL Connector/NET 8.3.0 Community is distributed - with certain software (including but not limited to OpenSSL) that is - licensed under separate terms, as designated in a particular file or - component or in the license documentation. Without limiting your rights - under the GPLv2, the authors of MySQL hereby grant you an additional - permission to link the program and your derivative works with the - separately licensed software that they have included with the program. + This distribution of MySQL Connector/Net is designed to work with certain + software (including but not limited to OpenSSL) that is licensed under + separate terms, as designated in a particular file or component or in the + license documentation. Without limiting your rights under the GPLv2, the + authors of MySQL hereby grant you an additional permission to link the + program and your derivative works with the separately licensed software + that they have either included with the program or referenced in the + documenation. Without limiting the foregoing grant of rights under the GPLv2 and additional permission as to separately licensed software, this diff --git a/MySQL.Data.OpenTelemetry/src/TraceProviderBuilderExtension.cs b/MySQL.Data.OpenTelemetry/src/TraceProviderBuilderExtension.cs index 3722078d4..76393c2a3 100644 --- a/MySQL.Data.OpenTelemetry/src/TraceProviderBuilderExtension.cs +++ b/MySQL.Data.OpenTelemetry/src/TraceProviderBuilderExtension.cs @@ -1,3 +1,31 @@ +// Copyright © 2023, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + using System; using OpenTelemetry.Trace; diff --git a/MySQL.Data/MySql.Replication.Tests/BaseTest.cs b/MySQL.Data/MySql.Replication.Tests/BaseTest.cs index 9e1310b9c..12f0220d2 100644 --- a/MySQL.Data/MySql.Replication.Tests/BaseTest.cs +++ b/MySQL.Data/MySql.Replication.Tests/BaseTest.cs @@ -1,172 +1,172 @@ -// Copyright (c) 2013, 2020, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using NUnit.Framework; -using System.Reflection; -using MySql.Data.MySqlClient; -using System.Configuration; - -namespace MySql.LoadBalancing.Tests -{ - public class BaseTest - { - protected string databaseName; - protected int sourcePort; - protected int replicaPort; - protected string server; - private MySqlConnectionStringBuilder connStringRootSource; - private MySqlConnectionStringBuilder connStringReplica; - - protected string ConnectionString - { - get - { - return string.Format("{0}database={1};", ConnectionStringNoDb, databaseName); - } - } - - protected string ConnectionStringNoDb - { - get - { - return string.Format("server={0};", server); - } - } - - protected string ConnectionStringRootSource - { - get - { - return connStringRootSource.ConnectionString; - } - } - - protected string ConnectionStringReplica - { - get - { - return connStringReplica.ConnectionString; - } - } - - - - public BaseTest() - { - Initialize(); - LoadBaseConfiguration(); - } - - protected void LoadBaseConfiguration() - { - string sourcePortString = ValueIfEmpty(ConfigurationManager.AppSettings["sourcePort"], "3305"); - string replicaPortString = ValueIfEmpty(ConfigurationManager.AppSettings["replicaPort"], "3307"); - server = ValueIfEmpty(ConfigurationManager.AppSettings["server"], "Group1"); - - sourcePort = int.Parse(sourcePortString); - replicaPort = int.Parse(replicaPortString); - - connStringRootSource = new MySqlConnectionStringBuilder(); - connStringRootSource.UserID = ValueIfEmpty(ConfigurationManager.AppSettings["rootuser"], "root"); - connStringRootSource.Password = ValueIfEmpty(ConfigurationManager.AppSettings["rootpassword"], string.Empty); - connStringRootSource.Server = ValueIfEmpty(ConfigurationManager.AppSettings["host"], "localhost"); - connStringRootSource.Port = (uint)sourcePort; - - connStringReplica = new MySqlConnectionStringBuilder(); - connStringReplica.UserID = ValueIfEmpty(ConfigurationManager.AppSettings["replicaUser"], "lbuser"); - connStringReplica.Password = ValueIfEmpty(ConfigurationManager.AppSettings["replicaPassword"], "lbpass"); - connStringReplica.Server = ValueIfEmpty(ConfigurationManager.AppSettings["replicaHost"], "localhost"); - connStringReplica.Port = (uint)replicaPort; - connStringReplica.Database = databaseName; - } - - protected virtual void Initialize() - { - // we don't use FileVersion because it's not available - // on the compact framework - string fullname = Assembly.GetExecutingAssembly().FullName; - string[] parts = fullname.Split(new char[] { '=' }); - string[] versionParts = parts[1].Split(new char[] { '.' }); - databaseName = String.Format("dblb{0}{1}", versionParts[0], versionParts[1]); - } - - [SetUp] - public void Setup() - { - using (MySqlConnection connection = new MySqlConnection(ConnectionStringRootSource)) - { - connection.Open(); - MySqlScript script = new MySqlScript(connection); - - // Sets users - script.Query = Properties.Resources._01_Startup_root_script; - script.Execute(); - - // Sets database objects - script.Query = string.Format(Properties.Resources._02_Startup_script, databaseName); - script.Execute(); - } - } - - //[TearDown] - public void Teardown() - { - using (MySqlConnection connection = new MySqlConnection(ConnectionStringRootSource)) - { - connection.Open(); - MySqlCommand cmd = new MySqlCommand(string.Empty, connection); - - cmd.CommandText = "DROP USER lbuser@localhost;"; - cmd.CommandText += "DROP DATABASE IF EXISTS " + databaseName; - cmd.ExecuteNonQuery(); - } - } - - protected MySqlDataReader ExecuteQuery(MySqlConnection connection, string query) - { - MySqlCommand cmd = new MySqlCommand(query, connection); - return cmd.ExecuteReader(); - } - - protected int ExecuteNonQuery(MySqlConnection connection, string query) - { - MySqlCommand cmd = new MySqlCommand(query, connection); - return cmd.ExecuteNonQuery(); - } - - private string ValueIfEmpty(string value, string valueIfEmtpy) - { - if (string.IsNullOrEmpty(value)) return valueIfEmtpy; - return value; - } - } -} +// Copyright © 2013, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using NUnit.Framework; +using System.Reflection; +using MySql.Data.MySqlClient; +using System.Configuration; + +namespace MySql.LoadBalancing.Tests +{ + public class BaseTest + { + protected string databaseName; + protected int sourcePort; + protected int replicaPort; + protected string server; + private MySqlConnectionStringBuilder connStringRootSource; + private MySqlConnectionStringBuilder connStringReplica; + + protected string ConnectionString + { + get + { + return string.Format("{0}database={1};", ConnectionStringNoDb, databaseName); + } + } + + protected string ConnectionStringNoDb + { + get + { + return string.Format("server={0};", server); + } + } + + protected string ConnectionStringRootSource + { + get + { + return connStringRootSource.ConnectionString; + } + } + + protected string ConnectionStringReplica + { + get + { + return connStringReplica.ConnectionString; + } + } + + + + public BaseTest() + { + Initialize(); + LoadBaseConfiguration(); + } + + protected void LoadBaseConfiguration() + { + string sourcePortString = ValueIfEmpty(ConfigurationManager.AppSettings["sourcePort"], "3305"); + string replicaPortString = ValueIfEmpty(ConfigurationManager.AppSettings["replicaPort"], "3307"); + server = ValueIfEmpty(ConfigurationManager.AppSettings["server"], "Group1"); + + sourcePort = int.Parse(sourcePortString); + replicaPort = int.Parse(replicaPortString); + + connStringRootSource = new MySqlConnectionStringBuilder(); + connStringRootSource.UserID = ValueIfEmpty(ConfigurationManager.AppSettings["rootuser"], "root"); + connStringRootSource.Password = ValueIfEmpty(ConfigurationManager.AppSettings["rootpassword"], string.Empty); + connStringRootSource.Server = ValueIfEmpty(ConfigurationManager.AppSettings["host"], "localhost"); + connStringRootSource.Port = (uint)sourcePort; + + connStringReplica = new MySqlConnectionStringBuilder(); + connStringReplica.UserID = ValueIfEmpty(ConfigurationManager.AppSettings["replicaUser"], "lbuser"); + connStringReplica.Password = ValueIfEmpty(ConfigurationManager.AppSettings["replicaPassword"], "lbpass"); + connStringReplica.Server = ValueIfEmpty(ConfigurationManager.AppSettings["replicaHost"], "localhost"); + connStringReplica.Port = (uint)replicaPort; + connStringReplica.Database = databaseName; + } + + protected virtual void Initialize() + { + // we don't use FileVersion because it's not available + // on the compact framework + string fullname = Assembly.GetExecutingAssembly().FullName; + string[] parts = fullname.Split(new char[] { '=' }); + string[] versionParts = parts[1].Split(new char[] { '.' }); + databaseName = String.Format("dblb{0}{1}", versionParts[0], versionParts[1]); + } + + [SetUp] + public void Setup() + { + using (MySqlConnection connection = new MySqlConnection(ConnectionStringRootSource)) + { + connection.Open(); + MySqlScript script = new MySqlScript(connection); + + // Sets users + script.Query = Properties.Resources._01_Startup_root_script; + script.Execute(); + + // Sets database objects + script.Query = string.Format(Properties.Resources._02_Startup_script, databaseName); + script.Execute(); + } + } + + //[TearDown] + public void Teardown() + { + using (MySqlConnection connection = new MySqlConnection(ConnectionStringRootSource)) + { + connection.Open(); + MySqlCommand cmd = new MySqlCommand(string.Empty, connection); + + cmd.CommandText = "DROP USER lbuser@localhost;"; + cmd.CommandText += "DROP DATABASE IF EXISTS " + databaseName; + cmd.ExecuteNonQuery(); + } + } + + protected MySqlDataReader ExecuteQuery(MySqlConnection connection, string query) + { + MySqlCommand cmd = new MySqlCommand(query, connection); + return cmd.ExecuteReader(); + } + + protected int ExecuteNonQuery(MySqlConnection connection, string query) + { + MySqlCommand cmd = new MySqlCommand(query, connection); + return cmd.ExecuteNonQuery(); + } + + private string ValueIfEmpty(string value, string valueIfEmtpy) + { + if (string.IsNullOrEmpty(value)) return valueIfEmtpy; + return value; + } + } +} diff --git a/MySQL.Data/MySql.Replication.Tests/Properties/AssemblyInfo.cs b/MySQL.Data/MySql.Replication.Tests/Properties/AssemblyInfo.cs index b7762a94b..1fed11efd 100644 --- a/MySQL.Data/MySql.Replication.Tests/Properties/AssemblyInfo.cs +++ b/MySQL.Data/MySql.Replication.Tests/Properties/AssemblyInfo.cs @@ -1,55 +1,55 @@ -// Copyright © 2013, 2019, Oracle and/or its affiliates. All rights reserved. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - - -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("MySql.LoadBalancing.Tests")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("Oracle Corporation")] -[assembly: AssemblyProduct("MySql.LoadBalancing.Tests")] -[assembly: AssemblyCopyright("Copyright © 2013, 2019, Oracle and/or its affiliates. All rights reserved.")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("02681727-f306-4923-8c16-717d6f1716ce")] - -[assembly: AssemblyDelaySign(true)] -[assembly: AssemblyKeyFileAttribute(@"..\..\ConnectorNetPublicKey.snk")] +// Copyright © 2013, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("MySql.LoadBalancing.Tests")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Oracle Corporation")] +[assembly: AssemblyProduct("MySql.LoadBalancing.Tests")] +[assembly: AssemblyCopyright("Copyright © 2013, 2019, Oracle and/or its affiliates. All rights reserved.")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("02681727-f306-4923-8c16-717d6f1716ce")] + +[assembly: AssemblyDelaySign(true)] +[assembly: AssemblyKeyFileAttribute(@"..\..\ConnectorNetPublicKey.snk")] diff --git a/MySQL.Data/MySql.Replication.Tests/Properties/Resources.Designer.cs b/MySQL.Data/MySql.Replication.Tests/Properties/Resources.Designer.cs index ff6244c10..72af81f13 100644 --- a/MySQL.Data/MySql.Replication.Tests/Properties/Resources.Designer.cs +++ b/MySQL.Data/MySql.Replication.Tests/Properties/Resources.Designer.cs @@ -1,112 +1,112 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.42000 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace MySql.Replication.Tests.Properties { - using System; - - - /// - /// A strongly-typed resource class, for looking up localized strings, etc. - /// - // This class was auto-generated by the StronglyTypedResourceBuilder - // class via a tool like ResGen or Visual Studio. - // To add or remove a member, edit your .ResX file then rerun ResGen - // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class Resources { - - private static global::System.Resources.ResourceManager resourceMan; - - private static global::System.Globalization.CultureInfo resourceCulture; - - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal Resources() { - } - - /// - /// Returns the cached ResourceManager instance used by this class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager { - get { - if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("MySql.Replication.Tests.Properties.Resources", typeof(Resources).Assembly); - resourceMan = temp; - } - return resourceMan; - } - } - - /// - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture { - get { - return resourceCulture; - } - set { - resourceCulture = value; - } - } - - /// - /// Looks up a localized string similar to -- Users - /// - ///GRANT ALL ON *.* TO lbuser@localhost IDENTIFIED BY 'lbpass'; - /// - ///REVOKE SUPER ON *.* FROM lbuser@localhost; - ///. - /// - internal static string _01_Startup_root_script { - get { - return ResourceManager.GetString("_01_Startup_root_script", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to DROP DATABASE IF EXISTS {0}; - /// - /// - ///CREATE DATABASE {0}; - ///USE {0}; - /// - ///CREATE TABLE items ( - /// item_id int primary key auto_increment, - /// description varchar(50) not null, - /// brand varchar(50), - /// price float not null, - /// quantity int not null - ///); - /// - ///CREATE TABLE stores( - /// store_id int primary key auto_increment, - /// name varchar(50) not null, - /// address varchar(100) - ///); - /// - ///CREATE TABLE employees( - /// employee_id int primary key auto_increment, - /// name varchar(50) not null, - /// store_id int, - /// active bool - ///); - /// [rest of string was truncated]";. - /// - internal static string _02_Startup_script { - get { - return ResourceManager.GetString("_02_Startup_script", resourceCulture); - } - } - } -} +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace MySql.Replication.Tests.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("MySql.Replication.Tests.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to -- Users + /// + ///GRANT ALL ON *.* TO lbuser@localhost IDENTIFIED BY 'lbpass'; + /// + ///REVOKE SUPER ON *.* FROM lbuser@localhost; + ///. + /// + internal static string _01_Startup_root_script { + get { + return ResourceManager.GetString("_01_Startup_root_script", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to DROP DATABASE IF EXISTS {0}; + /// + /// + ///CREATE DATABASE {0}; + ///USE {0}; + /// + ///CREATE TABLE items ( + /// item_id int primary key auto_increment, + /// description varchar(50) not null, + /// brand varchar(50), + /// price float not null, + /// quantity int not null + ///); + /// + ///CREATE TABLE stores( + /// store_id int primary key auto_increment, + /// name varchar(50) not null, + /// address varchar(100) + ///); + /// + ///CREATE TABLE employees( + /// employee_id int primary key auto_increment, + /// name varchar(50) not null, + /// store_id int, + /// active bool + ///); + /// [rest of string was truncated]";. + /// + internal static string _02_Startup_script { + get { + return ResourceManager.GetString("_02_Startup_script", resourceCulture); + } + } + } +} diff --git a/MySQL.Data/MySql.Replication.Tests/ReplicationTest.cs b/MySQL.Data/MySql.Replication.Tests/ReplicationTest.cs index d3dea4de5..ce9dc5ff1 100644 --- a/MySQL.Data/MySql.Replication.Tests/ReplicationTest.cs +++ b/MySQL.Data/MySql.Replication.Tests/ReplicationTest.cs @@ -1,246 +1,246 @@ -// Copyright (c) 2013, 2020, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using MySql.Data.MySqlClient; -using Xunit; -using System.Diagnostics; -using MySql.Data; - -namespace MySql.Replication.Tests -{ - public class ReplicationTest : IUseFixture, IDisposable - { - - private SetUp st; - - public void SetFixture(SetUp data) - { - st = data; - } - - public void Dispose() - { - MySqlConnectionStringBuilder connString = new MySqlConnectionStringBuilder(st.ConnectionStringRootSource); - connString.Database = st.databaseName; - using (MySqlConnection conn = new MySqlConnection(connString.ToString())) - { - conn.Open(); - st.ExecuteNonQuery(conn, "DELETE FROM orders"); - st.ExecuteNonQuery(conn, "DELETE FROM order_details"); - } - } - - /// - /// Validates that the replica is readonly - /// - [Fact] - public void _ReplicaAsReadOnly() - { - using (MySqlConnection conn = new MySqlConnection(st.ConnectionStringReplica)) - { - conn.Open(); - MySqlException ex = Assert.Throws(() => st.ExecuteNonQuery(conn, "INSERT INTO orders VALUES(null, 1, 'James')")); - // Error 1290: The MySQL server is running with the --read-only option so - // it cannot execute this statement - Assert.Equal(1290, ex.Number); - } - } - - /// - /// Validates that each request for a connection is switched between the - /// source and replica; also validates that all non-read statements are sent - /// to the source - /// - [Fact] - public void RoundRobinWritting() - { - using (MySqlConnection conn = new MySqlConnection(st.ConnectionString)) - { - conn.Open(); - - st.ExecuteNonQuery(conn, "INSERT INTO orders VALUES(null, 1, 'James')"); - st.ExecuteNonQuery(conn, "INSERT INTO order_details VALUES(1, 1, 1, 0, 0)"); - st.ExecuteNonQuery(conn, "INSERT INTO order_details VALUES(1, 2, 1, 0, 0)"); - - Assert.Equal(st.replicaPort, GetPort(conn)); - Assert.Equal(st.sourcePort, GetPort(conn)); - Assert.Equal(st.replicaPort, GetPort(conn)); - Assert.Equal(st.sourcePort, GetPort(conn)); - - st.ExecuteNonQuery(conn, "INSERT INTO order_details VALUES(1, 3, 1, 0, 0)"); - } - } - - /// - /// Test for a source connection failure - /// - [Fact] - public void RoundRobinReadOnly() - { - using (MySqlConnection conn = new MySqlConnection("server=Group2;")) - { - conn.Open(); - - - MySqlException ex = Assert.Throws(() => st.ExecuteNonQuery(conn, "INSERT INTO orders VALUES(null, 1, 'James')")); - - Assert.Equal(Resources.Replication_NoAvailableServer, ex.Message); - - int currentPort = GetPort(conn); - Assert.True(currentPort != (currentPort = GetPort(conn)), "1st try"); - Assert.True(currentPort != (currentPort = GetPort(conn)), "2nd try"); - Assert.True(currentPort != (currentPort = GetPort(conn)), "3rd try"); - Assert.True(currentPort != (currentPort = GetPort(conn)), "4th try"); - } - } - - /// - /// Validates that data inserted in source is replicated into replica - /// - [Fact] - public void RoundRobinValidateReplicaData() - { - using (MySqlConnection conn = new MySqlConnection(st.ConnectionString)) - { - conn.Open(); - - st.ExecuteNonQuery(conn, "INSERT INTO orders VALUES(null, 2, 'Bruce')"); - } - - // Waits for replication on replica - System.Threading.Thread.Sleep(3000); - - // validates data on replica - using (MySqlConnection replicaConn = new MySqlConnection(st.ConnectionStringReplica)) - { - replicaConn.Open(); - MySqlDataReader dr = st.ExecuteQuery(replicaConn, "SELECT * FROM orders"); - Assert.True(dr.Read()); - Assert.Equal(2, dr.GetValue(1)); - Assert.Equal("Bruce", dr.GetValue(2)); - } - } - - [Fact] - public void ValidateLogging() - { - MySqlTrace.Listeners.Clear(); - MySqlTrace.Switch.Level = SourceLevels.All; - MySql.Data.MySqlClient.Tests.GenericListener listener = new MySql.Data.MySqlClient.Tests.GenericListener(); - MySqlTrace.Listeners.Add(listener); - using (MySqlConnection conn = new MySqlConnection(st.ConnectionString )) - { - conn.Open(); - - st.ExecuteNonQuery(conn, "INSERT INTO orders VALUES(null, 2, 'Bruce')"); - st.ExecuteNonQuery(conn, "INSERT INTO orders VALUES(null, 1, 'James')"); - st.ExecuteNonQuery(conn, "INSERT INTO order_details VALUES(1, 1, 1, 0, 0)"); - st.ExecuteNonQuery(conn, "INSERT INTO order_details VALUES(1, 2, 1, 0, 0)"); - } - - // Waits for replication on replica - System.Threading.Thread.Sleep(3000); - - // validates data on replica - using (MySqlConnection replicaConn = new MySqlConnection(st.ConnectionStringReplica)) - { - replicaConn.Open(); - MySqlDataReader dr = st.ExecuteQuery(replicaConn, "SELECT * FROM orders"); - Assert.True(dr.Read()); - Assert.Equal(2, dr.GetValue(1)); - Assert.Equal("Bruce", dr.GetValue(2)); - } - Debug.WriteLine("Start of tracing"); - foreach (string s in listener.Strings) - { - Debug.WriteLine(s); - } - Debug.WriteLine("End of tracing"); - } - - /// - /// When using transactions, load balancing must lock on the current server. - /// - [Fact] - public void ValidateTransactions() - { - MySqlTrace.Listeners.Clear(); - MySqlTrace.Switch.Level = SourceLevels.All; - MySql.Data.MySqlClient.Tests.GenericListener listener = new MySql.Data.MySqlClient.Tests.GenericListener(); - MySqlTrace.Listeners.Add(listener); - using (MySqlConnection conn = new MySqlConnection(st.ConnectionString)) - { - conn.Open(); - MySqlTransaction tx = conn.BeginTransaction(); - st.ExecuteNonQuery(conn, "INSERT INTO orders VALUES(null, 2, 'Bruce')"); - st.ExecuteNonQuery(conn, "INSERT INTO orders VALUES(null, 1, 'James')"); - st.ExecuteNonQuery(conn, "INSERT INTO order_details VALUES(1, 1, 1, 0, 0)"); - st.ExecuteNonQuery(conn, "INSERT INTO order_details VALUES(1, 2, 1, 0, 0)"); - tx.Commit(); - } - - // Waits for replication on replica - System.Threading.Thread.Sleep(3000); - - // validates data on replica - using (MySqlConnection replicaConn = new MySqlConnection(st.ConnectionStringReplica)) - { - replicaConn.Open(); - MySqlDataReader dr = st.ExecuteQuery(replicaConn, "SELECT * FROM orders"); - Assert.True(dr.Read()); - Assert.Equal(2, dr.GetValue(1)); - Assert.Equal("Bruce", dr.GetValue(2)); - } - Debug.WriteLine("Start of tracing"); - foreach (string s in listener.Strings) - { - Debug.WriteLine(s); - } - Debug.WriteLine("End of tracing"); - } - - #region Private methods - - private int GetPort(MySqlConnection connection) - { - MySqlDataReader dr = st.ExecuteQuery(connection, "SHOW VARIABLES LIKE 'port';"); - - dr.Read(); - int port = dr.GetInt32(1); - dr.Close(); - - return port; - } - - #endregion - } -} +// Copyright © 2013, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using MySql.Data.MySqlClient; +using Xunit; +using System.Diagnostics; +using MySql.Data; + +namespace MySql.Replication.Tests +{ + public class ReplicationTest : IUseFixture, IDisposable + { + + private SetUp st; + + public void SetFixture(SetUp data) + { + st = data; + } + + public void Dispose() + { + MySqlConnectionStringBuilder connString = new MySqlConnectionStringBuilder(st.ConnectionStringRootSource); + connString.Database = st.databaseName; + using (MySqlConnection conn = new MySqlConnection(connString.ToString())) + { + conn.Open(); + st.ExecuteNonQuery(conn, "DELETE FROM orders"); + st.ExecuteNonQuery(conn, "DELETE FROM order_details"); + } + } + + /// + /// Validates that the replica is readonly + /// + [Fact] + public void _ReplicaAsReadOnly() + { + using (MySqlConnection conn = new MySqlConnection(st.ConnectionStringReplica)) + { + conn.Open(); + MySqlException ex = Assert.Throws(() => st.ExecuteNonQuery(conn, "INSERT INTO orders VALUES(null, 1, 'James')")); + // Error 1290: The MySQL server is running with the --read-only option so + // it cannot execute this statement + Assert.Equal(1290, ex.Number); + } + } + + /// + /// Validates that each request for a connection is switched between the + /// source and replica; also validates that all non-read statements are sent + /// to the source + /// + [Fact] + public void RoundRobinWritting() + { + using (MySqlConnection conn = new MySqlConnection(st.ConnectionString)) + { + conn.Open(); + + st.ExecuteNonQuery(conn, "INSERT INTO orders VALUES(null, 1, 'James')"); + st.ExecuteNonQuery(conn, "INSERT INTO order_details VALUES(1, 1, 1, 0, 0)"); + st.ExecuteNonQuery(conn, "INSERT INTO order_details VALUES(1, 2, 1, 0, 0)"); + + Assert.Equal(st.replicaPort, GetPort(conn)); + Assert.Equal(st.sourcePort, GetPort(conn)); + Assert.Equal(st.replicaPort, GetPort(conn)); + Assert.Equal(st.sourcePort, GetPort(conn)); + + st.ExecuteNonQuery(conn, "INSERT INTO order_details VALUES(1, 3, 1, 0, 0)"); + } + } + + /// + /// Test for a source connection failure + /// + [Fact] + public void RoundRobinReadOnly() + { + using (MySqlConnection conn = new MySqlConnection("server=Group2;")) + { + conn.Open(); + + + MySqlException ex = Assert.Throws(() => st.ExecuteNonQuery(conn, "INSERT INTO orders VALUES(null, 1, 'James')")); + + Assert.Equal(Resources.Replication_NoAvailableServer, ex.Message); + + int currentPort = GetPort(conn); + Assert.True(currentPort != (currentPort = GetPort(conn)), "1st try"); + Assert.True(currentPort != (currentPort = GetPort(conn)), "2nd try"); + Assert.True(currentPort != (currentPort = GetPort(conn)), "3rd try"); + Assert.True(currentPort != (currentPort = GetPort(conn)), "4th try"); + } + } + + /// + /// Validates that data inserted in source is replicated into replica + /// + [Fact] + public void RoundRobinValidateReplicaData() + { + using (MySqlConnection conn = new MySqlConnection(st.ConnectionString)) + { + conn.Open(); + + st.ExecuteNonQuery(conn, "INSERT INTO orders VALUES(null, 2, 'Bruce')"); + } + + // Waits for replication on replica + System.Threading.Thread.Sleep(3000); + + // validates data on replica + using (MySqlConnection replicaConn = new MySqlConnection(st.ConnectionStringReplica)) + { + replicaConn.Open(); + MySqlDataReader dr = st.ExecuteQuery(replicaConn, "SELECT * FROM orders"); + Assert.True(dr.Read()); + Assert.Equal(2, dr.GetValue(1)); + Assert.Equal("Bruce", dr.GetValue(2)); + } + } + + [Fact] + public void ValidateLogging() + { + MySqlTrace.Listeners.Clear(); + MySqlTrace.Switch.Level = SourceLevels.All; + MySql.Data.MySqlClient.Tests.GenericListener listener = new MySql.Data.MySqlClient.Tests.GenericListener(); + MySqlTrace.Listeners.Add(listener); + using (MySqlConnection conn = new MySqlConnection(st.ConnectionString )) + { + conn.Open(); + + st.ExecuteNonQuery(conn, "INSERT INTO orders VALUES(null, 2, 'Bruce')"); + st.ExecuteNonQuery(conn, "INSERT INTO orders VALUES(null, 1, 'James')"); + st.ExecuteNonQuery(conn, "INSERT INTO order_details VALUES(1, 1, 1, 0, 0)"); + st.ExecuteNonQuery(conn, "INSERT INTO order_details VALUES(1, 2, 1, 0, 0)"); + } + + // Waits for replication on replica + System.Threading.Thread.Sleep(3000); + + // validates data on replica + using (MySqlConnection replicaConn = new MySqlConnection(st.ConnectionStringReplica)) + { + replicaConn.Open(); + MySqlDataReader dr = st.ExecuteQuery(replicaConn, "SELECT * FROM orders"); + Assert.True(dr.Read()); + Assert.Equal(2, dr.GetValue(1)); + Assert.Equal("Bruce", dr.GetValue(2)); + } + Debug.WriteLine("Start of tracing"); + foreach (string s in listener.Strings) + { + Debug.WriteLine(s); + } + Debug.WriteLine("End of tracing"); + } + + /// + /// When using transactions, load balancing must lock on the current server. + /// + [Fact] + public void ValidateTransactions() + { + MySqlTrace.Listeners.Clear(); + MySqlTrace.Switch.Level = SourceLevels.All; + MySql.Data.MySqlClient.Tests.GenericListener listener = new MySql.Data.MySqlClient.Tests.GenericListener(); + MySqlTrace.Listeners.Add(listener); + using (MySqlConnection conn = new MySqlConnection(st.ConnectionString)) + { + conn.Open(); + MySqlTransaction tx = conn.BeginTransaction(); + st.ExecuteNonQuery(conn, "INSERT INTO orders VALUES(null, 2, 'Bruce')"); + st.ExecuteNonQuery(conn, "INSERT INTO orders VALUES(null, 1, 'James')"); + st.ExecuteNonQuery(conn, "INSERT INTO order_details VALUES(1, 1, 1, 0, 0)"); + st.ExecuteNonQuery(conn, "INSERT INTO order_details VALUES(1, 2, 1, 0, 0)"); + tx.Commit(); + } + + // Waits for replication on replica + System.Threading.Thread.Sleep(3000); + + // validates data on replica + using (MySqlConnection replicaConn = new MySqlConnection(st.ConnectionStringReplica)) + { + replicaConn.Open(); + MySqlDataReader dr = st.ExecuteQuery(replicaConn, "SELECT * FROM orders"); + Assert.True(dr.Read()); + Assert.Equal(2, dr.GetValue(1)); + Assert.Equal("Bruce", dr.GetValue(2)); + } + Debug.WriteLine("Start of tracing"); + foreach (string s in listener.Strings) + { + Debug.WriteLine(s); + } + Debug.WriteLine("End of tracing"); + } + + #region Private methods + + private int GetPort(MySqlConnection connection) + { + MySqlDataReader dr = st.ExecuteQuery(connection, "SHOW VARIABLES LIKE 'port';"); + + dr.Read(); + int port = dr.GetInt32(1); + dr.Close(); + + return port; + } + + #endregion + } +} diff --git a/MySQL.Data/MySql.Replication.Tests/SetUp.cs b/MySQL.Data/MySql.Replication.Tests/SetUp.cs index bef3bd551..72bba93ff 100644 --- a/MySQL.Data/MySql.Replication.Tests/SetUp.cs +++ b/MySQL.Data/MySql.Replication.Tests/SetUp.cs @@ -1,158 +1,158 @@ -// Copyright (c) 2013, 2020, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Reflection; -using MySql.Data.MySqlClient; -using System.Configuration; - -namespace MySql.Replication.Tests -{ - public class SetUp : IDisposable - { - protected internal string databaseName; - protected internal int sourcePort; - protected internal int replicaPort; - protected internal string groupName; - private MySqlConnectionStringBuilder connStringRootSource; - private MySqlConnectionStringBuilder connStringReplica; - - protected internal string ConnectionString - { - get - { - return string.Format("{0}database={1};", ConnectionStringNoDb, databaseName); - } - } - - protected internal string ConnectionStringNoDb - { - get - { - return string.Format("server={0};", groupName); - } - } - - protected internal string ConnectionStringRootSource - { - get - { - return connStringRootSource.ConnectionString; - } - } - - protected internal string ConnectionStringReplica - { - get - { - return connStringReplica.ConnectionString; - } - } - - public SetUp() - { - Initialize(); - LoadBaseConfiguration(); - - using (MySqlConnection connection = new MySqlConnection(ConnectionStringRootSource)) - { - connection.Open(); - MySqlScript script = new MySqlScript(connection); - - // Sets users - script.Query = Properties.Resources._01_Startup_root_script; - script.Execute(); - - // Sets database objects - script.Query = string.Format(Properties.Resources._02_Startup_script, databaseName); - script.Execute(); - } - } - - protected internal void LoadBaseConfiguration() - { - ReplicationServerGroupConfigurationElement group1 = (ConfigurationManager.GetSection("MySQL") as MySqlConfiguration).Replication.ServerGroups.ToArray()[0]; - ReplicationServerConfigurationElement sourceConfiguration = group1.Servers.ToArray()[0]; - ReplicationServerConfigurationElement replicaConfiguration = group1.Servers.ToArray()[1]; - - groupName = group1.Name; - - connStringRootSource = new MySqlConnectionStringBuilder(sourceConfiguration.ConnectionString); - sourcePort = (int)connStringRootSource.Port; - - connStringReplica = new MySqlConnectionStringBuilder(replicaConfiguration.ConnectionString); - replicaPort = (int)connStringReplica.Port; - connStringReplica.Database = databaseName; - } - - protected virtual void Initialize() - { - // we don't use FileVersion because it's not available - // on the compact framework - string fullname = Assembly.GetExecutingAssembly().FullName; - string[] parts = fullname.Split(new char[] { '=' }); - string[] versionParts = parts[1].Split(new char[] { '.' }); - databaseName = String.Format("dblb{0}{1}", versionParts[0], versionParts[1]); - } - - - public void Dispose() - { - using (MySqlConnection connection = new MySqlConnection(ConnectionStringRootSource)) - { - connection.Open(); - MySqlCommand cmd = new MySqlCommand(string.Empty, connection); - - cmd.CommandText = "DROP USER lbuser@localhost;"; - cmd.CommandText += "DROP DATABASE IF EXISTS " + databaseName; - cmd.ExecuteNonQuery(); - } - } - - protected internal MySqlDataReader ExecuteQuery(MySqlConnection connection, string query) - { - MySqlCommand cmd = new MySqlCommand(query, connection); - return cmd.ExecuteReader(); - } - - protected internal int ExecuteNonQuery(MySqlConnection connection, string query) - { - MySqlCommand cmd = new MySqlCommand(query, connection); - return cmd.ExecuteNonQuery(); - } - - private string ValueIfEmpty(string value, string valueIfEmtpy) - { - if (string.IsNullOrEmpty(value)) return valueIfEmtpy; - return value; - } - } -} +// Copyright © 2013, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Reflection; +using MySql.Data.MySqlClient; +using System.Configuration; + +namespace MySql.Replication.Tests +{ + public class SetUp : IDisposable + { + protected internal string databaseName; + protected internal int sourcePort; + protected internal int replicaPort; + protected internal string groupName; + private MySqlConnectionStringBuilder connStringRootSource; + private MySqlConnectionStringBuilder connStringReplica; + + protected internal string ConnectionString + { + get + { + return string.Format("{0}database={1};", ConnectionStringNoDb, databaseName); + } + } + + protected internal string ConnectionStringNoDb + { + get + { + return string.Format("server={0};", groupName); + } + } + + protected internal string ConnectionStringRootSource + { + get + { + return connStringRootSource.ConnectionString; + } + } + + protected internal string ConnectionStringReplica + { + get + { + return connStringReplica.ConnectionString; + } + } + + public SetUp() + { + Initialize(); + LoadBaseConfiguration(); + + using (MySqlConnection connection = new MySqlConnection(ConnectionStringRootSource)) + { + connection.Open(); + MySqlScript script = new MySqlScript(connection); + + // Sets users + script.Query = Properties.Resources._01_Startup_root_script; + script.Execute(); + + // Sets database objects + script.Query = string.Format(Properties.Resources._02_Startup_script, databaseName); + script.Execute(); + } + } + + protected internal void LoadBaseConfiguration() + { + ReplicationServerGroupConfigurationElement group1 = (ConfigurationManager.GetSection("MySQL") as MySqlConfiguration).Replication.ServerGroups.ToArray()[0]; + ReplicationServerConfigurationElement sourceConfiguration = group1.Servers.ToArray()[0]; + ReplicationServerConfigurationElement replicaConfiguration = group1.Servers.ToArray()[1]; + + groupName = group1.Name; + + connStringRootSource = new MySqlConnectionStringBuilder(sourceConfiguration.ConnectionString); + sourcePort = (int)connStringRootSource.Port; + + connStringReplica = new MySqlConnectionStringBuilder(replicaConfiguration.ConnectionString); + replicaPort = (int)connStringReplica.Port; + connStringReplica.Database = databaseName; + } + + protected virtual void Initialize() + { + // we don't use FileVersion because it's not available + // on the compact framework + string fullname = Assembly.GetExecutingAssembly().FullName; + string[] parts = fullname.Split(new char[] { '=' }); + string[] versionParts = parts[1].Split(new char[] { '.' }); + databaseName = String.Format("dblb{0}{1}", versionParts[0], versionParts[1]); + } + + + public void Dispose() + { + using (MySqlConnection connection = new MySqlConnection(ConnectionStringRootSource)) + { + connection.Open(); + MySqlCommand cmd = new MySqlCommand(string.Empty, connection); + + cmd.CommandText = "DROP USER lbuser@localhost;"; + cmd.CommandText += "DROP DATABASE IF EXISTS " + databaseName; + cmd.ExecuteNonQuery(); + } + } + + protected internal MySqlDataReader ExecuteQuery(MySqlConnection connection, string query) + { + MySqlCommand cmd = new MySqlCommand(query, connection); + return cmd.ExecuteReader(); + } + + protected internal int ExecuteNonQuery(MySqlConnection connection, string query) + { + MySqlCommand cmd = new MySqlCommand(query, connection); + return cmd.ExecuteNonQuery(); + } + + private string ValueIfEmpty(string value, string valueIfEmtpy) + { + if (string.IsNullOrEmpty(value)) return valueIfEmtpy; + return value; + } + } +} diff --git a/MySQL.Data/src/Authentication/AuthenticationManager.cs b/MySQL.Data/src/Authentication/AuthenticationManager.cs index 9d4099359..3dfe08708 100644 --- a/MySQL.Data/src/Authentication/AuthenticationManager.cs +++ b/MySQL.Data/src/Authentication/AuthenticationManager.cs @@ -1,97 +1,97 @@ -// Copyright (c) 2012, 2022, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using System; -using System.Collections.Generic; -using System.Reflection; - -namespace MySql.Data.MySqlClient.Authentication -{ - internal partial class AuthenticationPluginManager - { - private static readonly Dictionary Plugins = new Dictionary(); - - static partial void AuthenticationManagerCtorConfiguration(); - - static AuthenticationPluginManager() - { - Plugins["mysql_native_password"] = new PluginInfo("MySql.Data.MySqlClient.Authentication.MySqlNativePasswordPlugin"); - Plugins["sha256_password"] = new PluginInfo("MySql.Data.MySqlClient.Authentication.Sha256AuthenticationPlugin"); - Plugins["authentication_windows_client"] = new PluginInfo("MySql.Data.MySqlClient.Authentication.MySqlWindowsAuthenticationPlugin"); - Plugins["caching_sha2_password"] = new PluginInfo("MySql.Data.MySqlClient.Authentication.CachingSha2AuthenticationPlugin"); - Plugins["authentication_ldap_sasl_client"] = new PluginInfo("MySql.Data.MySqlClient.Authentication.MySqlSASLPlugin"); - Plugins["mysql_clear_password"] = new PluginInfo("MySql.Data.MySqlClient.Authentication.MySqlClearPasswordPlugin"); - Plugins["authentication_kerberos_client"] = new PluginInfo("MySql.Data.MySqlClient.Authentication.KerberosAuthenticationPlugin"); - Plugins["authentication_oci_client"] = new PluginInfo("MySql.Data.MySqlClient.Authentication.OciAuthenticationPlugin"); - Plugins["authentication_fido_client"] = new PluginInfo("MySql.Data.MySqlClient.Authentication.FidoAuthenticationPlugin"); - Plugins["authentication_webauthn_client"] = new PluginInfo("MySql.Data.MySqlClient.Authentication.WebAuthnAuthenticationPlugin"); - - AuthenticationManagerCtorConfiguration(); - } - - public static MySqlAuthenticationPlugin GetPlugin(string method) - { - ValidateAuthenticationPlugin(method); - return CreatePlugin(method); - } - - private static MySqlAuthenticationPlugin CreatePlugin(string method) - { - PluginInfo pi = Plugins[method]; - - try - { - Type t = Type.GetType(pi.Type); - MySqlAuthenticationPlugin o = (MySqlAuthenticationPlugin)Activator.CreateInstance(t); - return o; - } - catch (Exception e) - { - throw new MySqlException(String.Format(Resources.UnableToCreateAuthPlugin, method), e); - } - } - - public static void ValidateAuthenticationPlugin(string method) - { - if (!Plugins.ContainsKey(method)) - throw new MySqlException(String.Format(Resources.AuthenticationMethodNotSupported, method)); - } - } - - struct PluginInfo - { - public string Type; - public Assembly Assembly; - - public PluginInfo(string type) - { - Type = type; - Assembly = null; - } - } -} +// Copyright © 2012, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using System; +using System.Collections.Generic; +using System.Reflection; + +namespace MySql.Data.MySqlClient.Authentication +{ + internal partial class AuthenticationPluginManager + { + private static readonly Dictionary Plugins = new Dictionary(); + + static partial void AuthenticationManagerCtorConfiguration(); + + static AuthenticationPluginManager() + { + Plugins["mysql_native_password"] = new PluginInfo("MySql.Data.MySqlClient.Authentication.MySqlNativePasswordPlugin"); + Plugins["sha256_password"] = new PluginInfo("MySql.Data.MySqlClient.Authentication.Sha256AuthenticationPlugin"); + Plugins["authentication_windows_client"] = new PluginInfo("MySql.Data.MySqlClient.Authentication.MySqlWindowsAuthenticationPlugin"); + Plugins["caching_sha2_password"] = new PluginInfo("MySql.Data.MySqlClient.Authentication.CachingSha2AuthenticationPlugin"); + Plugins["authentication_ldap_sasl_client"] = new PluginInfo("MySql.Data.MySqlClient.Authentication.MySqlSASLPlugin"); + Plugins["mysql_clear_password"] = new PluginInfo("MySql.Data.MySqlClient.Authentication.MySqlClearPasswordPlugin"); + Plugins["authentication_kerberos_client"] = new PluginInfo("MySql.Data.MySqlClient.Authentication.KerberosAuthenticationPlugin"); + Plugins["authentication_oci_client"] = new PluginInfo("MySql.Data.MySqlClient.Authentication.OciAuthenticationPlugin"); + Plugins["authentication_fido_client"] = new PluginInfo("MySql.Data.MySqlClient.Authentication.FidoAuthenticationPlugin"); + Plugins["authentication_webauthn_client"] = new PluginInfo("MySql.Data.MySqlClient.Authentication.WebAuthnAuthenticationPlugin"); + + AuthenticationManagerCtorConfiguration(); + } + + public static MySqlAuthenticationPlugin GetPlugin(string method) + { + ValidateAuthenticationPlugin(method); + return CreatePlugin(method); + } + + private static MySqlAuthenticationPlugin CreatePlugin(string method) + { + PluginInfo pi = Plugins[method]; + + try + { + Type t = Type.GetType(pi.Type); + MySqlAuthenticationPlugin o = (MySqlAuthenticationPlugin)Activator.CreateInstance(t); + return o; + } + catch (Exception e) + { + throw new MySqlException(String.Format(Resources.UnableToCreateAuthPlugin, method), e); + } + } + + public static void ValidateAuthenticationPlugin(string method) + { + if (!Plugins.ContainsKey(method)) + throw new MySqlException(String.Format(Resources.AuthenticationMethodNotSupported, method)); + } + } + + struct PluginInfo + { + public string Type; + public Assembly Assembly; + + public PluginInfo(string type) + { + Type = type; + Assembly = null; + } + } +} diff --git a/MySQL.Data/src/Authentication/CachingSha2AuthenticationPlugin.cs b/MySQL.Data/src/Authentication/CachingSha2AuthenticationPlugin.cs index bf6183e70..f93b060a8 100644 --- a/MySQL.Data/src/Authentication/CachingSha2AuthenticationPlugin.cs +++ b/MySQL.Data/src/Authentication/CachingSha2AuthenticationPlugin.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2017, 2022, Oracle and/or its affiliates. +// Copyright © 2017, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -178,4 +178,4 @@ internal enum AuthStage FAST_AUTH = 2, FULL_AUTH = 3 } -} \ No newline at end of file +} diff --git a/MySQL.Data/src/Authentication/ClearPasswordPlugin.cs b/MySQL.Data/src/Authentication/ClearPasswordPlugin.cs index 135997166..6a7c4744a 100644 --- a/MySQL.Data/src/Authentication/ClearPasswordPlugin.cs +++ b/MySQL.Data/src/Authentication/ClearPasswordPlugin.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2020, 2022, Oracle and/or its affiliates. +// Copyright © 2020, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/Authentication/FIDO/FidoAssertion.cs b/MySQL.Data/src/Authentication/FIDO/FidoAssertion.cs index 4d2bad412..9c9f610a3 100644 --- a/MySQL.Data/src/Authentication/FIDO/FidoAssertion.cs +++ b/MySQL.Data/src/Authentication/FIDO/FidoAssertion.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2022, 2023, Oracle and/or its affiliates. +// Copyright © 2022, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/Authentication/FIDO/FidoDevice.cs b/MySQL.Data/src/Authentication/FIDO/FidoDevice.cs index dd015fe17..32fde9da4 100644 --- a/MySQL.Data/src/Authentication/FIDO/FidoDevice.cs +++ b/MySQL.Data/src/Authentication/FIDO/FidoDevice.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2022, 2023, Oracle and/or its affiliates. +// Copyright © 2022, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/Authentication/FIDO/FidoDeviceInfo.cs b/MySQL.Data/src/Authentication/FIDO/FidoDeviceInfo.cs index a34d03266..ccac1e5a3 100644 --- a/MySQL.Data/src/Authentication/FIDO/FidoDeviceInfo.cs +++ b/MySQL.Data/src/Authentication/FIDO/FidoDeviceInfo.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2022, Oracle and/or its affiliates. +// Copyright © 2022, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/Authentication/FIDO/Native/NativeMethods.cs b/MySQL.Data/src/Authentication/FIDO/Native/NativeMethods.cs index 47404be9b..53d00e0ee 100644 --- a/MySQL.Data/src/Authentication/FIDO/Native/NativeMethods.cs +++ b/MySQL.Data/src/Authentication/FIDO/Native/NativeMethods.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2022, 2023, Oracle and/or its affiliates. +// Copyright © 2022, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General internal License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/Authentication/FIDO/Native/Structs.cs b/MySQL.Data/src/Authentication/FIDO/Native/Structs.cs index d798bf048..c56b3570c 100644 --- a/MySQL.Data/src/Authentication/FIDO/Native/Structs.cs +++ b/MySQL.Data/src/Authentication/FIDO/Native/Structs.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2022, Oracle and/or its affiliates. +// Copyright © 2022, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/Authentication/FIDO/Utility/ConstStringMarshaler.cs b/MySQL.Data/src/Authentication/FIDO/Utility/ConstStringMarshaler.cs index 57cf867cc..c6d7e6317 100644 --- a/MySQL.Data/src/Authentication/FIDO/Utility/ConstStringMarshaler.cs +++ b/MySQL.Data/src/Authentication/FIDO/Utility/ConstStringMarshaler.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2022, Oracle and/or its affiliates. +// Copyright © 2022, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/Authentication/FIDO/Utility/Enums.cs b/MySQL.Data/src/Authentication/FIDO/Utility/Enums.cs index ccdec93c5..68ec522d4 100644 --- a/MySQL.Data/src/Authentication/FIDO/Utility/Enums.cs +++ b/MySQL.Data/src/Authentication/FIDO/Utility/Enums.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2022, Oracle and/or its affiliates. +// Copyright © 2022, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/Authentication/FIDO/Utility/Extensions.cs b/MySQL.Data/src/Authentication/FIDO/Utility/Extensions.cs index e9be6c55a..2e9fd33cf 100644 --- a/MySQL.Data/src/Authentication/FIDO/Utility/Extensions.cs +++ b/MySQL.Data/src/Authentication/FIDO/Utility/Extensions.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2022, Oracle and/or its affiliates. +// Copyright © 2022, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/Authentication/FIDO/Utility/FidoExceptions.cs b/MySQL.Data/src/Authentication/FIDO/Utility/FidoExceptions.cs index 560bdd0d0..4d628afe8 100644 --- a/MySQL.Data/src/Authentication/FIDO/Utility/FidoExceptions.cs +++ b/MySQL.Data/src/Authentication/FIDO/Utility/FidoExceptions.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2022, Oracle and/or its affiliates. +// Copyright © 2022, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/Authentication/FIDO/Utility/Init.cs b/MySQL.Data/src/Authentication/FIDO/Utility/Init.cs index 2e159a005..3b359c321 100644 --- a/MySQL.Data/src/Authentication/FIDO/Utility/Init.cs +++ b/MySQL.Data/src/Authentication/FIDO/Utility/Init.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2022, Oracle and/or its affiliates. +// Copyright © 2022, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/Authentication/FidoAuthenticationPlugin.cs b/MySQL.Data/src/Authentication/FidoAuthenticationPlugin.cs index 5936c1e12..9976a137a 100644 --- a/MySQL.Data/src/Authentication/FidoAuthenticationPlugin.cs +++ b/MySQL.Data/src/Authentication/FidoAuthenticationPlugin.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2022, 2023, Oracle and/or its affiliates. +// Copyright © 2022, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/Authentication/GSSAPI/Const.cs b/MySQL.Data/src/Authentication/GSSAPI/Const.cs index e1e70f7c6..4f70c4844 100644 --- a/MySQL.Data/src/Authentication/GSSAPI/Const.cs +++ b/MySQL.Data/src/Authentication/GSSAPI/Const.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021 Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/Authentication/GSSAPI/GssContext.cs b/MySQL.Data/src/Authentication/GSSAPI/GssContext.cs index 0f2030035..70b070323 100644 --- a/MySQL.Data/src/Authentication/GSSAPI/GssContext.cs +++ b/MySQL.Data/src/Authentication/GSSAPI/GssContext.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2020, Oracle and/or its affiliates. +// Copyright © 2020, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -231,4 +231,4 @@ public void Dispose() GC.SuppressFinalize(this); } } -} \ No newline at end of file +} diff --git a/MySQL.Data/src/Authentication/GSSAPI/GssContextFlags.cs b/MySQL.Data/src/Authentication/GSSAPI/GssContextFlags.cs index a56b71683..d94f00a49 100644 --- a/MySQL.Data/src/Authentication/GSSAPI/GssContextFlags.cs +++ b/MySQL.Data/src/Authentication/GSSAPI/GssContextFlags.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2020, Oracle and/or its affiliates. +// Copyright © 2020, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -77,4 +77,4 @@ internal enum GssContextFlags Trans = 256, DelegPolicy = 32768 } -} \ No newline at end of file +} diff --git a/MySQL.Data/src/Authentication/GSSAPI/GssCredentials.cs b/MySQL.Data/src/Authentication/GSSAPI/GssCredentials.cs index e30fa6f71..49ca4af7b 100644 --- a/MySQL.Data/src/Authentication/GSSAPI/GssCredentials.cs +++ b/MySQL.Data/src/Authentication/GSSAPI/GssCredentials.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2022, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -225,4 +225,4 @@ public void Dispose() majorStatus, minorStatus, Const.GssNtHostBasedService)); } } -} \ No newline at end of file +} diff --git a/MySQL.Data/src/Authentication/GSSAPI/GssapiMechanism.cs b/MySQL.Data/src/Authentication/GSSAPI/GssapiMechanism.cs index 0c232c7b7..59653a8f7 100644 --- a/MySQL.Data/src/Authentication/GSSAPI/GssapiMechanism.cs +++ b/MySQL.Data/src/Authentication/GSSAPI/GssapiMechanism.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -124,4 +124,4 @@ internal byte[] DoFinalHandshake(byte[] data) return response; } } -} \ No newline at end of file +} diff --git a/MySQL.Data/src/Authentication/GSSAPI/Native/GssBufferDescStruct.cs b/MySQL.Data/src/Authentication/GSSAPI/Native/GssBufferDescStruct.cs index d62569322..90dd88441 100644 --- a/MySQL.Data/src/Authentication/GSSAPI/Native/GssBufferDescStruct.cs +++ b/MySQL.Data/src/Authentication/GSSAPI/Native/GssBufferDescStruct.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2020, Oracle and/or its affiliates. +// Copyright © 2020, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -40,4 +40,4 @@ internal struct GssBufferDescStruct /// void* public IntPtr value; } -} \ No newline at end of file +} diff --git a/MySQL.Data/src/Authentication/GSSAPI/Native/GssOidStruct.cs b/MySQL.Data/src/Authentication/GSSAPI/Native/GssOidStruct.cs index cc5422c89..5c1e68877 100644 --- a/MySQL.Data/src/Authentication/GSSAPI/Native/GssOidStruct.cs +++ b/MySQL.Data/src/Authentication/GSSAPI/Native/GssOidStruct.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2020, Oracle and/or its affiliates. +// Copyright © 2020, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -50,4 +50,4 @@ internal struct GssOidSetStruct /// void* public IntPtr elements; } -} \ No newline at end of file +} diff --git a/MySQL.Data/src/Authentication/GSSAPI/Native/NativeMethods.cs b/MySQL.Data/src/Authentication/GSSAPI/Native/NativeMethods.cs index 0f1832dd4..fc4c22001 100644 --- a/MySQL.Data/src/Authentication/GSSAPI/Native/NativeMethods.cs +++ b/MySQL.Data/src/Authentication/GSSAPI/Native/NativeMethods.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -471,4 +471,4 @@ internal static uint gss_wrap( : NativeMethodsLinux.gss_wrap(out minorStatus, contextHandle, 0, Const.GSS_C_QOP_DEFAULT, ref inputMessage, 0, out outputMessage); } } -} \ No newline at end of file +} diff --git a/MySQL.Data/src/Authentication/GSSAPI/Native/NativeMethodsLinux.cs b/MySQL.Data/src/Authentication/GSSAPI/Native/NativeMethodsLinux.cs index f0447a86c..90b3747df 100644 --- a/MySQL.Data/src/Authentication/GSSAPI/Native/NativeMethodsLinux.cs +++ b/MySQL.Data/src/Authentication/GSSAPI/Native/NativeMethodsLinux.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2022, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -149,4 +149,4 @@ internal static extern uint gss_display_name( out GssBufferDescStruct NameBuffer, out GssOidDescStruct nameType); } -} \ No newline at end of file +} diff --git a/MySQL.Data/src/Authentication/GSSAPI/Native/NativeMethodsWin64.cs b/MySQL.Data/src/Authentication/GSSAPI/Native/NativeMethodsWin64.cs index 61b9c2b4e..69e4bd2e1 100644 --- a/MySQL.Data/src/Authentication/GSSAPI/Native/NativeMethodsWin64.cs +++ b/MySQL.Data/src/Authentication/GSSAPI/Native/NativeMethodsWin64.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2022, Oracle and/or its affiliates. +// Copyright © 2022, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -149,4 +149,4 @@ internal static extern uint gss_display_name( out GssBufferDescStruct NameBuffer, out GssOidDescStruct nameType); } -} \ No newline at end of file +} diff --git a/MySQL.Data/src/Authentication/GSSAPI/Utility/Disposable.cs b/MySQL.Data/src/Authentication/GSSAPI/Utility/Disposable.cs index 325b15319..f4ad1e83f 100644 --- a/MySQL.Data/src/Authentication/GSSAPI/Utility/Disposable.cs +++ b/MySQL.Data/src/Authentication/GSSAPI/Utility/Disposable.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2020, 2023, Oracle and/or its affiliates. +// Copyright © 2020, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -117,4 +117,4 @@ public void Dispose() _disposeAction?.Invoke(); } } -} \ No newline at end of file +} diff --git a/MySQL.Data/src/Authentication/GSSAPI/Utility/ExceptionMessages.cs b/MySQL.Data/src/Authentication/GSSAPI/Utility/ExceptionMessages.cs index cf4f76260..3fe8da347 100644 --- a/MySQL.Data/src/Authentication/GSSAPI/Utility/ExceptionMessages.cs +++ b/MySQL.Data/src/Authentication/GSSAPI/Utility/ExceptionMessages.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2020, Oracle and/or its affiliates. +// Copyright © 2020, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -65,4 +65,4 @@ private static string TranslateMinorStatusCode(uint status, GssOidDescStruct oid return buffer.value == IntPtr.Zero ? string.Empty : Marshal.PtrToStringAnsi(buffer.value); } } -} \ No newline at end of file +} diff --git a/MySQL.Data/src/Authentication/GSSAPI/Utility/GssType.cs b/MySQL.Data/src/Authentication/GSSAPI/Utility/GssType.cs index cdad230e2..ba2b00f56 100644 --- a/MySQL.Data/src/Authentication/GSSAPI/Utility/GssType.cs +++ b/MySQL.Data/src/Authentication/GSSAPI/Utility/GssType.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2020, Oracle and/or its affiliates. +// Copyright © 2020, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -53,4 +53,4 @@ public static Disposable GetBufferFromBytes(byte[] buffer) majorStatus, minorStatus, Const.GSS_C_NO_OID)); }); } -} \ No newline at end of file +} diff --git a/MySQL.Data/src/Authentication/GSSAPI/Utility/KerberosConfig.cs b/MySQL.Data/src/Authentication/GSSAPI/Utility/KerberosConfig.cs index 49102bd6b..b00744684 100644 --- a/MySQL.Data/src/Authentication/GSSAPI/Utility/KerberosConfig.cs +++ b/MySQL.Data/src/Authentication/GSSAPI/Utility/KerberosConfig.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -225,4 +225,4 @@ private static void ReadValues(string currentLine, StringReader reader, List - /// Defines the default behavior for an authentication plugin. - /// - public abstract class MySqlAuthenticationPlugin - { - internal NativeDriver _driver; - - /// - /// Handles the iteration of the multifactor authentication. - /// - private int _mfaIteration = 1; - - /// - /// Gets the AuthPlugin name of the AuthSwitchRequest. - /// - internal string SwitchedPlugin { get; private set; } - - /// - /// Gets or sets the authentication data returned by the server. - /// - protected byte[] AuthenticationData; - - /// - /// This is a factory method that is used only internally. It creates an auth plugin based on the method type - /// - /// Authentication method. - /// The driver. - /// The authentication data. - /// Boolean that indicates if the function will be executed asynchronously. - /// MultiFactorAuthentication iteration. - /// - internal static async Task GetPluginAsync(string method, NativeDriver driver, byte[] authData, bool execAsync, int mfaIteration = 1) - { - if (method == "mysql_old_password") - { - await driver.CloseAsync(true, execAsync).ConfigureAwait(false); - throw new MySqlException(Resources.OldPasswordsNotSupported); - } - MySqlAuthenticationPlugin plugin = AuthenticationPluginManager.GetPlugin(method); - if (plugin == null) - throw new MySqlException(String.Format(Resources.UnknownAuthenticationMethod, method)); - - plugin._driver = driver; - plugin._mfaIteration = mfaIteration; - plugin.SetAuthData(authData); - return plugin; - } - - /// - /// Gets the connection option settings. - /// - protected MySqlConnectionStringBuilder Settings => _driver.Settings; - - /// - /// Gets the server version associated with this authentication plugin. - /// - protected Version ServerVersion => new Version(_driver.Version.Major, _driver.Version.Minor, _driver.Version.Build); - - internal ClientFlags Flags => _driver.Flags; - - /// - /// Gets the encoding assigned to the native driver. - /// - protected Encoding Encoding => _driver.Encoding; - - /// - /// Sets the authentication data required to encode, encrypt, or convert the password of the user. - /// - /// A byte array containing the authentication data provided by the server. - /// This method may be overriden based on the requirements by the implementing authentication plugin. - protected virtual void SetAuthData(byte[] data) - { - AuthenticationData = data; - } - - /// - /// Defines the behavior when checking for constraints. - /// - /// This method is intended to be overriden. - protected virtual void CheckConstraints() - { - } - - /// - /// Throws a that encapsulates the original exception. - /// - /// The exception to encapsulate. - protected virtual void AuthenticationFailed(MySqlException ex) - { - string msg = String.Format(Resources.AuthenticationFailed, Settings.Server, GetUsername(), PluginName, ex.Message); - throw new MySqlException(msg, ex.Number, ex); - } - - /// - /// Defines the behavior when authentication is successful. - /// - /// This method is intended to be overriden. - protected virtual void AuthenticationSuccessful() - { - } - - /// - /// Defines the behavior when more data is required from the server. - /// - /// The data returned by the server. - /// Boolean that indicates if the function will be executed asynchronously. - /// The data to return to the server. - /// This method is intended to be overriden. - protected virtual Task MoreDataAsync(byte[] data, bool execAsync) - { - return Task.FromResult(null); - } - - internal async Task AuthenticateAsync(bool reset, bool execAsync) - { - CheckConstraints(); - - MySqlPacket packet = _driver.Packet; - - // send auth response - await packet.WriteStringAsync(GetUsername(), execAsync).ConfigureAwait(false); - - // now write the password - await WritePasswordAsync(packet, execAsync).ConfigureAwait(false); - - if ((Flags & ClientFlags.CONNECT_WITH_DB) != 0 || reset) - { - if (!String.IsNullOrEmpty(Settings.Database)) - await packet.WriteStringAsync(Settings.Database, execAsync).ConfigureAwait(false); - } - - if (reset) - await packet.WriteIntegerAsync(8, 2, execAsync).ConfigureAwait(false); - - if ((Flags & ClientFlags.PLUGIN_AUTH) != 0) - await packet.WriteStringAsync(PluginName, execAsync).ConfigureAwait(false); - - await _driver.SetConnectAttrsAsync(execAsync).ConfigureAwait(false); - await _driver.SendPacketAsync(packet, execAsync); - - // Read server response. - packet = await ReadPacketAsync(execAsync).ConfigureAwait(false); - byte[] b = packet.Buffer; - - if (PluginName == "caching_sha2_password" && b[0] == 0x01) - { - // React to the authentication type set by server: FAST, FULL. - await ContinueAuthenticationAsync(execAsync, new byte[] { b[1] }).ConfigureAwait(false); - } - - // Auth switch request Protocol::AuthSwitchRequest. - if (b[0] == 0xfe) - { - if (packet.IsLastPacket) - { - await _driver.CloseAsync(true, execAsync).ConfigureAwait(false); - throw new MySqlException(Resources.OldPasswordsNotSupported); - } - else - { - await HandleAuthChangeAsync(packet, execAsync).ConfigureAwait(false); - } - } - - // Auth request Protocol::AuthNextFactor. - while (packet.Buffer[0] == 0x02) - { - ++_mfaIteration; - await HandleMFAAsync(packet, execAsync).ConfigureAwait(false); - } - - await _driver.ReadOkAsync(false, execAsync).ConfigureAwait(false); - - AuthenticationSuccessful(); - } - - private async Task WritePasswordAsync(MySqlPacket packet, bool execAsync) - { - bool secure = (Flags & ClientFlags.SECURE_CONNECTION) != 0; - object password = GetPassword(); - if (password is string) - { - if (secure) - await packet.WriteLenStringAsync((string)password, execAsync).ConfigureAwait(false); - else - await packet.WriteStringAsync((string)password, execAsync).ConfigureAwait(false); - } - else if (password == null) - packet.WriteByte(0); - else if (password is byte[]) - await packet.WriteAsync(password as byte[], execAsync).ConfigureAwait(false); - else throw new MySqlException("Unexpected password format: " + password.GetType()); - } - - internal async Task ReadPacketAsync(bool execAsync) - { - try - { - MySqlPacket p = await _driver.ReadPacketAsync(execAsync).ConfigureAwait(false); - return p; - } - catch (MySqlException ex) - { - // Make sure this is an auth failed ex - AuthenticationFailed(ex); - return null; - } - } - - private async Task HandleMFAAsync(MySqlPacket packet, bool execAsync) - { - byte b = packet.ReadByte(); - Debug.Assert(b == 0x02); - - var nextPlugin = await NextPluginAsync(packet, execAsync).ConfigureAwait(false); - nextPlugin.CheckConstraints(); - await nextPlugin.ContinueAuthenticationAsync(execAsync).ConfigureAwait(false); - } - - private async Task HandleAuthChangeAsync(MySqlPacket packet, bool execAsync) - { - byte b = packet.ReadByte(); - Debug.Assert(b == 0xfe); - - var nextPlugin = await NextPluginAsync(packet, execAsync).ConfigureAwait(false); - nextPlugin.CheckConstraints(); - await nextPlugin.ContinueAuthenticationAsync(execAsync).ConfigureAwait(false); - } - - private async Task NextPluginAsync(MySqlPacket packet, bool execAsync) - { - string method = packet.ReadString(); - SwitchedPlugin = method; - byte[] authData = new byte[packet.Length - packet.Position]; - Array.Copy(packet.Buffer, packet.Position, authData, 0, authData.Length); - - MySqlAuthenticationPlugin plugin = await GetPluginAsync(method, _driver, authData, execAsync, _mfaIteration).ConfigureAwait(false); - return plugin; - } - - private async Task ContinueAuthenticationAsync(bool execAsync, byte[] data = null) - { - MySqlPacket packet = _driver.Packet; - packet.Clear(); - - byte[] moreData = await MoreDataAsync(data, execAsync).ConfigureAwait(false); - - while (moreData != null) - { - packet.Clear(); - await packet.WriteAsync(moreData, execAsync).ConfigureAwait(false); - await _driver.SendPacketAsync(packet, execAsync).ConfigureAwait(false); - - packet = await ReadPacketAsync(execAsync).ConfigureAwait(false); - byte prefixByte = packet.Buffer[0]; - if (prefixByte != 1) return; - - // A prefix of 0x01 means need more auth data. - byte[] responseData = new byte[packet.Length - 1]; - Array.Copy(packet.Buffer, 1, responseData, 0, responseData.Length); - moreData = await MoreDataAsync(responseData, execAsync).ConfigureAwait(false); - } - // We get here if MoreData returned null but the last packet read was a more data packet. - await ReadPacketAsync(execAsync).ConfigureAwait(false); - } - - /// - /// Gets the password for the iteration of the multifactor authentication - /// - /// A password - protected string GetMFAPassword() - { - switch (_mfaIteration) - { - case 2: - return Settings.Password2; - case 3: - return Settings.Password3; - default: - return Settings.Password; - } - } - - /// - /// Gets the plugin name based on the authentication plugin type defined during the creation of this object. - /// - public abstract string PluginName { get; } - - /// - /// Gets the user name associated to the connection settings. - /// - /// The user name associated to the connection settings. - public virtual string GetUsername() - { - return !string.IsNullOrWhiteSpace(Settings.UserID) ? Settings.UserID : Environment.UserName; - } - - /// - /// Gets the encoded, encrypted, or converted password based on the authentication plugin type defined during the creation of this object. - /// This method is intended to be overriden. - /// - /// An object containing the encoded, encrypted, or converted password. - public virtual object GetPassword() - { - return null; - } - } -} +// Copyright © 2012, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using System; +using System.Diagnostics; +using System.Text; +using System.Threading.Tasks; + +namespace MySql.Data.MySqlClient.Authentication +{ + /// + /// Defines the default behavior for an authentication plugin. + /// + public abstract class MySqlAuthenticationPlugin + { + internal NativeDriver _driver; + + /// + /// Handles the iteration of the multifactor authentication. + /// + private int _mfaIteration = 1; + + /// + /// Gets the AuthPlugin name of the AuthSwitchRequest. + /// + internal string SwitchedPlugin { get; private set; } + + /// + /// Gets or sets the authentication data returned by the server. + /// + protected byte[] AuthenticationData; + + /// + /// This is a factory method that is used only internally. It creates an auth plugin based on the method type + /// + /// Authentication method. + /// The driver. + /// The authentication data. + /// Boolean that indicates if the function will be executed asynchronously. + /// MultiFactorAuthentication iteration. + /// + internal static async Task GetPluginAsync(string method, NativeDriver driver, byte[] authData, bool execAsync, int mfaIteration = 1) + { + if (method == "mysql_old_password") + { + await driver.CloseAsync(true, execAsync).ConfigureAwait(false); + throw new MySqlException(Resources.OldPasswordsNotSupported); + } + MySqlAuthenticationPlugin plugin = AuthenticationPluginManager.GetPlugin(method); + if (plugin == null) + throw new MySqlException(String.Format(Resources.UnknownAuthenticationMethod, method)); + + plugin._driver = driver; + plugin._mfaIteration = mfaIteration; + plugin.SetAuthData(authData); + return plugin; + } + + /// + /// Gets the connection option settings. + /// + protected MySqlConnectionStringBuilder Settings => _driver.Settings; + + /// + /// Gets the server version associated with this authentication plugin. + /// + protected Version ServerVersion => new Version(_driver.Version.Major, _driver.Version.Minor, _driver.Version.Build); + + internal ClientFlags Flags => _driver.Flags; + + /// + /// Gets the encoding assigned to the native driver. + /// + protected Encoding Encoding => _driver.Encoding; + + /// + /// Sets the authentication data required to encode, encrypt, or convert the password of the user. + /// + /// A byte array containing the authentication data provided by the server. + /// This method may be overriden based on the requirements by the implementing authentication plugin. + protected virtual void SetAuthData(byte[] data) + { + AuthenticationData = data; + } + + /// + /// Defines the behavior when checking for constraints. + /// + /// This method is intended to be overriden. + protected virtual void CheckConstraints() + { + } + + /// + /// Throws a that encapsulates the original exception. + /// + /// The exception to encapsulate. + protected virtual void AuthenticationFailed(MySqlException ex) + { + string msg = String.Format(Resources.AuthenticationFailed, Settings.Server, GetUsername(), PluginName, ex.Message); + throw new MySqlException(msg, ex.Number, ex); + } + + /// + /// Defines the behavior when authentication is successful. + /// + /// This method is intended to be overriden. + protected virtual void AuthenticationSuccessful() + { + } + + /// + /// Defines the behavior when more data is required from the server. + /// + /// The data returned by the server. + /// Boolean that indicates if the function will be executed asynchronously. + /// The data to return to the server. + /// This method is intended to be overriden. + protected virtual Task MoreDataAsync(byte[] data, bool execAsync) + { + return Task.FromResult(null); + } + + internal async Task AuthenticateAsync(bool reset, bool execAsync) + { + CheckConstraints(); + + MySqlPacket packet = _driver.Packet; + + // send auth response + await packet.WriteStringAsync(GetUsername(), execAsync).ConfigureAwait(false); + + // now write the password + await WritePasswordAsync(packet, execAsync).ConfigureAwait(false); + + if ((Flags & ClientFlags.CONNECT_WITH_DB) != 0 || reset) + { + if (!String.IsNullOrEmpty(Settings.Database)) + await packet.WriteStringAsync(Settings.Database, execAsync).ConfigureAwait(false); + } + + if (reset) + await packet.WriteIntegerAsync(8, 2, execAsync).ConfigureAwait(false); + + if ((Flags & ClientFlags.PLUGIN_AUTH) != 0) + await packet.WriteStringAsync(PluginName, execAsync).ConfigureAwait(false); + + await _driver.SetConnectAttrsAsync(execAsync).ConfigureAwait(false); + await _driver.SendPacketAsync(packet, execAsync); + + // Read server response. + packet = await ReadPacketAsync(execAsync).ConfigureAwait(false); + byte[] b = packet.Buffer; + + if (PluginName == "caching_sha2_password" && b[0] == 0x01) + { + // React to the authentication type set by server: FAST, FULL. + await ContinueAuthenticationAsync(execAsync, new byte[] { b[1] }).ConfigureAwait(false); + } + + // Auth switch request Protocol::AuthSwitchRequest. + if (b[0] == 0xfe) + { + if (packet.IsLastPacket) + { + await _driver.CloseAsync(true, execAsync).ConfigureAwait(false); + throw new MySqlException(Resources.OldPasswordsNotSupported); + } + else + { + await HandleAuthChangeAsync(packet, execAsync).ConfigureAwait(false); + } + } + + // Auth request Protocol::AuthNextFactor. + while (packet.Buffer[0] == 0x02) + { + ++_mfaIteration; + await HandleMFAAsync(packet, execAsync).ConfigureAwait(false); + } + + await _driver.ReadOkAsync(false, execAsync).ConfigureAwait(false); + + AuthenticationSuccessful(); + } + + private async Task WritePasswordAsync(MySqlPacket packet, bool execAsync) + { + bool secure = (Flags & ClientFlags.SECURE_CONNECTION) != 0; + object password = GetPassword(); + if (password is string) + { + if (secure) + await packet.WriteLenStringAsync((string)password, execAsync).ConfigureAwait(false); + else + await packet.WriteStringAsync((string)password, execAsync).ConfigureAwait(false); + } + else if (password == null) + packet.WriteByte(0); + else if (password is byte[]) + await packet.WriteAsync(password as byte[], execAsync).ConfigureAwait(false); + else throw new MySqlException("Unexpected password format: " + password.GetType()); + } + + internal async Task ReadPacketAsync(bool execAsync) + { + try + { + MySqlPacket p = await _driver.ReadPacketAsync(execAsync).ConfigureAwait(false); + return p; + } + catch (MySqlException ex) + { + // Make sure this is an auth failed ex + AuthenticationFailed(ex); + return null; + } + } + + private async Task HandleMFAAsync(MySqlPacket packet, bool execAsync) + { + byte b = packet.ReadByte(); + Debug.Assert(b == 0x02); + + var nextPlugin = await NextPluginAsync(packet, execAsync).ConfigureAwait(false); + nextPlugin.CheckConstraints(); + await nextPlugin.ContinueAuthenticationAsync(execAsync).ConfigureAwait(false); + } + + private async Task HandleAuthChangeAsync(MySqlPacket packet, bool execAsync) + { + byte b = packet.ReadByte(); + Debug.Assert(b == 0xfe); + + var nextPlugin = await NextPluginAsync(packet, execAsync).ConfigureAwait(false); + nextPlugin.CheckConstraints(); + await nextPlugin.ContinueAuthenticationAsync(execAsync).ConfigureAwait(false); + } + + private async Task NextPluginAsync(MySqlPacket packet, bool execAsync) + { + string method = packet.ReadString(); + SwitchedPlugin = method; + byte[] authData = new byte[packet.Length - packet.Position]; + Array.Copy(packet.Buffer, packet.Position, authData, 0, authData.Length); + + MySqlAuthenticationPlugin plugin = await GetPluginAsync(method, _driver, authData, execAsync, _mfaIteration).ConfigureAwait(false); + return plugin; + } + + private async Task ContinueAuthenticationAsync(bool execAsync, byte[] data = null) + { + MySqlPacket packet = _driver.Packet; + packet.Clear(); + + byte[] moreData = await MoreDataAsync(data, execAsync).ConfigureAwait(false); + + while (moreData != null) + { + packet.Clear(); + await packet.WriteAsync(moreData, execAsync).ConfigureAwait(false); + await _driver.SendPacketAsync(packet, execAsync).ConfigureAwait(false); + + packet = await ReadPacketAsync(execAsync).ConfigureAwait(false); + byte prefixByte = packet.Buffer[0]; + if (prefixByte != 1) return; + + // A prefix of 0x01 means need more auth data. + byte[] responseData = new byte[packet.Length - 1]; + Array.Copy(packet.Buffer, 1, responseData, 0, responseData.Length); + moreData = await MoreDataAsync(responseData, execAsync).ConfigureAwait(false); + } + // We get here if MoreData returned null but the last packet read was a more data packet. + await ReadPacketAsync(execAsync).ConfigureAwait(false); + } + + /// + /// Gets the password for the iteration of the multifactor authentication + /// + /// A password + protected string GetMFAPassword() + { + switch (_mfaIteration) + { + case 2: + return Settings.Password2; + case 3: + return Settings.Password3; + default: + return Settings.Password; + } + } + + /// + /// Gets the plugin name based on the authentication plugin type defined during the creation of this object. + /// + public abstract string PluginName { get; } + + /// + /// Gets the user name associated to the connection settings. + /// + /// The user name associated to the connection settings. + public virtual string GetUsername() + { + return !string.IsNullOrWhiteSpace(Settings.UserID) ? Settings.UserID : Environment.UserName; + } + + /// + /// Gets the encoded, encrypted, or converted password based on the authentication plugin type defined during the creation of this object. + /// This method is intended to be overriden. + /// + /// An object containing the encoded, encrypted, or converted password. + public virtual object GetPassword() + { + return null; + } + } +} diff --git a/MySQL.Data/src/Authentication/MySqlPemReader.cs b/MySQL.Data/src/Authentication/MySqlPemReader.cs index 9de5044ac..95a0bc7a4 100644 --- a/MySQL.Data/src/Authentication/MySqlPemReader.cs +++ b/MySQL.Data/src/Authentication/MySqlPemReader.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2017, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -231,4 +231,4 @@ private static bool EndsWith(byte[] array, byte[] containedArray) return true; } } -} \ No newline at end of file +} diff --git a/MySQL.Data/src/Authentication/MySqlSASLPlugin.cs b/MySQL.Data/src/Authentication/MySqlSASLPlugin.cs index 81a7424ab..12dbdc569 100644 --- a/MySQL.Data/src/Authentication/MySqlSASLPlugin.cs +++ b/MySQL.Data/src/Authentication/MySqlSASLPlugin.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2020, 2022, Oracle and/or its affiliates. +// Copyright © 2020, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -256,4 +256,4 @@ internal static string GetRandomBytes(int n) return Convert.ToBase64String(bytes); } } -} \ No newline at end of file +} diff --git a/MySQL.Data/src/Authentication/NativePasswordPlugins.cs b/MySQL.Data/src/Authentication/NativePasswordPlugins.cs index 47eab4890..53329e090 100644 --- a/MySQL.Data/src/Authentication/NativePasswordPlugins.cs +++ b/MySQL.Data/src/Authentication/NativePasswordPlugins.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2012, 2022, Oracle and/or its affiliates. +// Copyright © 2012, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/Authentication/OciAuthenticationPlugin.cs b/MySQL.Data/src/Authentication/OciAuthenticationPlugin.cs index 6d060352c..66c89dac9 100644 --- a/MySQL.Data/src/Authentication/OciAuthenticationPlugin.cs +++ b/MySQL.Data/src/Authentication/OciAuthenticationPlugin.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/Authentication/SSPI/Const.cs b/MySQL.Data/src/Authentication/SSPI/Const.cs index f4c96688b..ec34d26e7 100644 --- a/MySQL.Data/src/Authentication/SSPI/Const.cs +++ b/MySQL.Data/src/Authentication/SSPI/Const.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/Authentication/SSPI/NativeMethods.cs b/MySQL.Data/src/Authentication/SSPI/NativeMethods.cs index d081ac083..8c22c275e 100644 --- a/MySQL.Data/src/Authentication/SSPI/NativeMethods.cs +++ b/MySQL.Data/src/Authentication/SSPI/NativeMethods.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/Authentication/SSPI/SspiCredentials.cs b/MySQL.Data/src/Authentication/SSPI/SspiCredentials.cs index 5084a2296..82674876e 100644 --- a/MySQL.Data/src/Authentication/SSPI/SspiCredentials.cs +++ b/MySQL.Data/src/Authentication/SSPI/SspiCredentials.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/Authentication/SSPI/SspiSecurityContext.cs b/MySQL.Data/src/Authentication/SSPI/SspiSecurityContext.cs index 061e71d46..fb7add722 100644 --- a/MySQL.Data/src/Authentication/SSPI/SspiSecurityContext.cs +++ b/MySQL.Data/src/Authentication/SSPI/SspiSecurityContext.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/Authentication/SSPI/Structs.cs b/MySQL.Data/src/Authentication/SSPI/Structs.cs index da1a80d31..4a4d9b2d2 100644 --- a/MySQL.Data/src/Authentication/SSPI/Structs.cs +++ b/MySQL.Data/src/Authentication/SSPI/Structs.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/Authentication/ScramBase.cs b/MySQL.Data/src/Authentication/ScramBase.cs index c5ebdf68a..5d985667b 100644 --- a/MySQL.Data/src/Authentication/ScramBase.cs +++ b/MySQL.Data/src/Authentication/ScramBase.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2020, Oracle and/or its affiliates. +// Copyright © 2020, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -279,4 +279,4 @@ static Dictionary ParseServerChallenge(string challenge) return results; } } -} \ No newline at end of file +} diff --git a/MySQL.Data/src/Authentication/ScramSha1Mechanism.cs b/MySQL.Data/src/Authentication/ScramSha1Mechanism.cs index f4d9ab8bb..e6c63a7eb 100644 --- a/MySQL.Data/src/Authentication/ScramSha1Mechanism.cs +++ b/MySQL.Data/src/Authentication/ScramSha1Mechanism.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2020, Oracle and/or its affiliates. +// Copyright © 2020, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -69,4 +69,4 @@ protected override byte[] Hash(byte[] str) return sha1.ComputeHash(str); } } -} \ No newline at end of file +} diff --git a/MySQL.Data/src/Authentication/ScramSha256Mechanism.cs b/MySQL.Data/src/Authentication/ScramSha256Mechanism.cs index 3fed845d3..367d3ec63 100644 --- a/MySQL.Data/src/Authentication/ScramSha256Mechanism.cs +++ b/MySQL.Data/src/Authentication/ScramSha256Mechanism.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2020, Oracle and/or its affiliates. +// Copyright © 2020, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -69,4 +69,4 @@ protected override byte[] Hash(byte[] str) return sha256.ComputeHash(str); } } -} \ No newline at end of file +} diff --git a/MySQL.Data/src/Authentication/Sha256AuthenticationPlugin.cs b/MySQL.Data/src/Authentication/Sha256AuthenticationPlugin.cs index ec0e2f94b..86364bdeb 100644 --- a/MySQL.Data/src/Authentication/Sha256AuthenticationPlugin.cs +++ b/MySQL.Data/src/Authentication/Sha256AuthenticationPlugin.cs @@ -1,126 +1,126 @@ -// Copyright (c) 2013, 2022, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using System; -using System.Security.Cryptography; -using System.Text; -using System.Threading.Tasks; - -namespace MySql.Data.MySqlClient.Authentication -{ - /// - /// The implementation of the sha256_password authentication plugin. - /// - internal class Sha256AuthenticationPlugin : MySqlAuthenticationPlugin - { - /// - /// The byte array representation of the public key provided by the server. - /// - protected byte[] rawPubkey; - - public override string PluginName => "sha256_password"; - - protected override Task MoreDataAsync(byte[] data, bool execAsync) - { - rawPubkey = data; - byte[] buffer = GetNonLengthEncodedPassword(); - return Task.FromResult(buffer); - } - - public override object GetPassword() - { - if (Settings.SslMode != MySqlSslMode.Disabled) - { - // send as clear text, since the channel is already encrypted - byte[] passBytes = Encoding.GetBytes(GetMFAPassword()); - byte[] buffer = new byte[passBytes.Length + 2]; - Array.Copy(passBytes, 0, buffer, 1, passBytes.Length); - buffer[0] = (byte)(passBytes.Length + 1); - buffer[buffer.Length - 1] = 0x00; - return buffer; - } - else - { - if (GetMFAPassword().Length == 0) return new byte[1]; - // send RSA encrypted, since the channel is not protected - else if (rawPubkey == null) return new byte[] { 0x01 }; - else if (!Settings.AllowPublicKeyRetrieval) - throw new MySqlException(Resources.RSAPublicKeyRetrievalNotEnabled); - else - { - byte[] bytes = GetRsaPassword(GetMFAPassword(), AuthenticationData, rawPubkey); - if (bytes != null && bytes.Length == 1 && bytes[0] == 0) return null; - return bytes; - } - } - } - - private byte[] GetNonLengthEncodedPassword() - { - // Required for AuthChange requests. - if (Settings.SslMode != MySqlSslMode.Disabled) - { - // Send as clear text, since the channel is already encrypted. - byte[] passBytes = Encoding.GetBytes(GetMFAPassword()); - byte[] buffer = new byte[passBytes.Length + 1]; - Array.Copy(passBytes, 0, buffer, 0, passBytes.Length); - buffer[passBytes.Length] = 0; - return buffer; - } - else return GetPassword() as byte[]; - } - - private byte[] GetRsaPassword(string password, byte[] seedBytes, byte[] rawPublicKey) - { - if (password.Length == 0) return new byte[1]; - // Obfuscate the plain text password with the session scramble - byte[] obfuscated = GetXor(Encoding.Default.GetBytes(password), seedBytes); - // Encrypt the password and send it to the server - RSACryptoServiceProvider rsa = MySqlPemReader.ConvertPemToRSAProvider(rawPublicKey); - if (rsa == null) throw new MySqlException(Resources.UnableToReadRSAKey); - return rsa.Encrypt(obfuscated, true); - } - - /// - /// Applies XOR to the byte arrays provided as input. - /// - /// A byte array that contains the results of the XOR operation. - protected byte[] GetXor(byte[] src, byte[] pattern) - { - byte[] src2 = new byte[src.Length + 1]; - Array.Copy(src, 0, src2, 0, src.Length); - src2[src.Length] = 0; - byte[] result = new byte[src2.Length]; - for (int i = 0; i < src2.Length; i++) - { - result[i] = (byte)(src2[i] ^ (pattern[i % pattern.Length])); - } - return result; - } - } -} +// Copyright © 2013, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using System; +using System.Security.Cryptography; +using System.Text; +using System.Threading.Tasks; + +namespace MySql.Data.MySqlClient.Authentication +{ + /// + /// The implementation of the sha256_password authentication plugin. + /// + internal class Sha256AuthenticationPlugin : MySqlAuthenticationPlugin + { + /// + /// The byte array representation of the public key provided by the server. + /// + protected byte[] rawPubkey; + + public override string PluginName => "sha256_password"; + + protected override Task MoreDataAsync(byte[] data, bool execAsync) + { + rawPubkey = data; + byte[] buffer = GetNonLengthEncodedPassword(); + return Task.FromResult(buffer); + } + + public override object GetPassword() + { + if (Settings.SslMode != MySqlSslMode.Disabled) + { + // send as clear text, since the channel is already encrypted + byte[] passBytes = Encoding.GetBytes(GetMFAPassword()); + byte[] buffer = new byte[passBytes.Length + 2]; + Array.Copy(passBytes, 0, buffer, 1, passBytes.Length); + buffer[0] = (byte)(passBytes.Length + 1); + buffer[buffer.Length - 1] = 0x00; + return buffer; + } + else + { + if (GetMFAPassword().Length == 0) return new byte[1]; + // send RSA encrypted, since the channel is not protected + else if (rawPubkey == null) return new byte[] { 0x01 }; + else if (!Settings.AllowPublicKeyRetrieval) + throw new MySqlException(Resources.RSAPublicKeyRetrievalNotEnabled); + else + { + byte[] bytes = GetRsaPassword(GetMFAPassword(), AuthenticationData, rawPubkey); + if (bytes != null && bytes.Length == 1 && bytes[0] == 0) return null; + return bytes; + } + } + } + + private byte[] GetNonLengthEncodedPassword() + { + // Required for AuthChange requests. + if (Settings.SslMode != MySqlSslMode.Disabled) + { + // Send as clear text, since the channel is already encrypted. + byte[] passBytes = Encoding.GetBytes(GetMFAPassword()); + byte[] buffer = new byte[passBytes.Length + 1]; + Array.Copy(passBytes, 0, buffer, 0, passBytes.Length); + buffer[passBytes.Length] = 0; + return buffer; + } + else return GetPassword() as byte[]; + } + + private byte[] GetRsaPassword(string password, byte[] seedBytes, byte[] rawPublicKey) + { + if (password.Length == 0) return new byte[1]; + // Obfuscate the plain text password with the session scramble + byte[] obfuscated = GetXor(Encoding.Default.GetBytes(password), seedBytes); + // Encrypt the password and send it to the server + RSACryptoServiceProvider rsa = MySqlPemReader.ConvertPemToRSAProvider(rawPublicKey); + if (rsa == null) throw new MySqlException(Resources.UnableToReadRSAKey); + return rsa.Encrypt(obfuscated, true); + } + + /// + /// Applies XOR to the byte arrays provided as input. + /// + /// A byte array that contains the results of the XOR operation. + protected byte[] GetXor(byte[] src, byte[] pattern) + { + byte[] src2 = new byte[src.Length + 1]; + Array.Copy(src, 0, src2, 0, src.Length); + src2[src.Length] = 0; + byte[] result = new byte[src2.Length]; + for (int i = 0; i < src2.Length; i++) + { + result[i] = (byte)(src2[i] ^ (pattern[i % pattern.Length])); + } + return result; + } + } +} diff --git a/MySQL.Data/src/Authentication/Sha256MemoryAuthenticationPlugin.cs b/MySQL.Data/src/Authentication/Sha256MemoryAuthenticationPlugin.cs index 8a079b919..f278178e9 100644 --- a/MySQL.Data/src/Authentication/Sha256MemoryAuthenticationPlugin.cs +++ b/MySQL.Data/src/Authentication/Sha256MemoryAuthenticationPlugin.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2018, 2021, Oracle and/or its affiliates. +// Copyright © 2018, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/Authentication/WebAuthnAuthenticationPlugin.cs b/MySQL.Data/src/Authentication/WebAuthnAuthenticationPlugin.cs index 51b790d0b..2e3487a02 100644 --- a/MySQL.Data/src/Authentication/WebAuthnAuthenticationPlugin.cs +++ b/MySQL.Data/src/Authentication/WebAuthnAuthenticationPlugin.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2023, Oracle and/or its affiliates. +// Copyright © 2023, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/Authentication/WindowsAuthenticationPlugin.cs b/MySQL.Data/src/Authentication/WindowsAuthenticationPlugin.cs index a9ff97542..af668f091 100644 --- a/MySQL.Data/src/Authentication/WindowsAuthenticationPlugin.cs +++ b/MySQL.Data/src/Authentication/WindowsAuthenticationPlugin.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2012, 2022, Oracle and/or its affiliates. +// Copyright © 2012, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/BulkLoader.cs b/MySQL.Data/src/BulkLoader.cs index 97dd6d869..c211d53e4 100644 --- a/MySQL.Data/src/BulkLoader.cs +++ b/MySQL.Data/src/BulkLoader.cs @@ -1,365 +1,365 @@ -// Copyright (c) 2006, 2023, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using System; -using System.Collections.Generic; -using System.Data; -using System.IO; -using System.Text; -using System.Threading; -using System.Threading.Tasks; - -namespace MySql.Data.MySqlClient -{ - /// - /// Allows importing large amounts of data into a database with bulk loading. - /// - public class MySqlBulkLoader - { - // constant values - private const string defaultFieldTerminator = "\t"; - private const string defaultLineTerminator = "\n"; - private const char defaultEscapeCharacter = '\\'; - - /// - /// Initializes a new instance of the class using the specified instance of . - /// - /// The that will be used to perform the bulk operation. - public MySqlBulkLoader(MySqlConnection connection) - { - Connection = connection; - Local = false; - FieldTerminator = defaultFieldTerminator; - LineTerminator = defaultLineTerminator; - FieldQuotationCharacter = Char.MinValue; - ConflictOption = MySqlBulkLoaderConflictOption.None; - Columns = new List(); - Expressions = new List(); - } - - #region Properties - - /// - /// Gets or sets the connection. - /// - /// The connection. - public MySqlConnection Connection { get; set; } - - /// - /// Gets or sets the field terminator. - /// - /// The field terminator. - public string FieldTerminator { get; set; } - - /// - /// Gets or sets the line terminator. - /// - /// The line terminator. - public string LineTerminator { get; set; } - - /// - /// Gets or sets the name of the table. - /// - /// The name of the table. - public string TableName { get; set; } - - /// - /// Gets or sets the character set. - /// - /// The character set. - public string CharacterSet { get; set; } - - /// - /// Gets or sets the name of the file. - /// - /// The name of the file. - public string FileName { get; set; } - - /// - /// Gets or sets the timeout. - /// - /// The timeout. - public int Timeout { get; set; } - - /// - /// Gets or sets a value indicating whether the file name that is to be loaded - /// is local to the client or not. The default value is false. - /// - /// true if local; otherwise, false. - public bool Local { get; set; } - - /// - /// Gets or sets the number of lines to skip. - /// - /// The number of lines to skip. - public int NumberOfLinesToSkip { get; set; } - - /// - /// Gets or sets the line prefix. - /// - /// The line prefix. - public string LinePrefix { get; set; } - - /// - /// Gets or sets the field quotation character. - /// - /// The field quotation character. - public char FieldQuotationCharacter { get; set; } - - /// - /// Gets or sets a value indicating whether [field quotation optional]. - /// - /// - /// true if [field quotation optional]; otherwise, false. - /// - public bool FieldQuotationOptional { get; set; } - - /// - /// Gets or sets the escape character. - /// - /// The escape character. - public char EscapeCharacter { get; set; } - - /// - /// Gets or sets the conflict option. - /// - /// The conflict option. - public MySqlBulkLoaderConflictOption ConflictOption { get; set; } - - /// - /// Gets or sets the priority. - /// - /// The priority. - public MySqlBulkLoaderPriority Priority { get; set; } - - /// - /// Gets the columns. - /// - /// The columns. - public List Columns { get; } - - /// - /// Gets the expressions. - /// - /// The expressions. - public List Expressions { get; } - - #endregion - - /// - /// Executes the load operation. - /// - /// The number of rows inserted. - public int Load() - { - if (string.IsNullOrWhiteSpace(FileName)) - throw new MySqlException("FileName property of MySqlBulkLoader cannot be null or an empty string."); - - return LoadAsync(null, false).GetAwaiter().GetResult(); - } - - /// - /// Executes the load operation. - /// - /// A object containing the data to be loaded. - /// The number of rows inserted. - public int Load(Stream stream) => LoadAsync(stream, false).GetAwaiter().GetResult(); - - /// - /// Asynchronous version of the load operation. - /// - /// The number of rows inserted. - public Task LoadAsync() => LoadAsync(null, true); - - /// - /// Asynchronous version of the load operation that accepts a data stream. - /// - /// A containing the data to be loaded. - /// The number of rows inserted. - public Task LoadAsync(Stream stream) => LoadAsync(stream, true); - - /// - /// Executes the load operation asynchronously while the cancellation isn't requested. - /// - /// The cancellation token. - /// A containing the data to be loaded. - /// The number of rows inserted. - public Task LoadAsync(Stream stream, CancellationToken cancellationToken) => LoadAsync(stream, true, cancellationToken); - - private async Task LoadAsync(Stream stream, bool execAsync, CancellationToken cancellationToken = default) - { - bool openedConnection = false; - - if (Connection == null) - throw new InvalidOperationException(Resources.ConnectionNotSet); - - // next we open up the connetion if it is not already open - if (Connection.State != ConnectionState.Open) - { - await Connection.OpenAsync(execAsync, cancellationToken).ConfigureAwait(false); - openedConnection = true; - } - - try - { - string sql = BuildSqlCommand(stream is not null); - Connection.driver.BulkLoaderStream = stream; - using MySqlCommand cmd = new MySqlCommand(sql, Connection) { CommandTimeout = Timeout }; - return await cmd.ExecuteNonQueryAsync(execAsync, cancellationToken).ConfigureAwait(false); - } - finally - { - if (stream is not null) - Connection.driver.BulkLoaderStream.Dispose(); - - if (openedConnection) - await Connection.CloseAsync(execAsync).ConfigureAwait(false); - } - } - - private string BuildSqlCommand(bool useStream) - { - StringBuilder sql = new StringBuilder("LOAD DATA "); - if (Priority == MySqlBulkLoaderPriority.Low) - sql.Append("LOW_PRIORITY "); - else if (Priority == MySqlBulkLoaderPriority.Concurrent) - sql.Append("CONCURRENT "); - - if (useStream) - sql.Append("LOCAL INFILE 'MySQLTempFile' "); - else - { - if (Local) - sql.Append("LOCAL "); - - sql.Append("INFILE "); - - if (Path.DirectorySeparatorChar == '\\') - sql.AppendFormat("'{0}' ", FileName.Replace(@"\", @"\\")); - else - sql.AppendFormat("'{0}' ", FileName); - } - - if (ConflictOption == MySqlBulkLoaderConflictOption.Ignore) - sql.Append("IGNORE "); - else if (ConflictOption == MySqlBulkLoaderConflictOption.Replace) - sql.Append("REPLACE "); - - sql.AppendFormat("INTO TABLE {0} ", TableName); - - if (CharacterSet != null) - sql.AppendFormat("CHARACTER SET {0} ", CharacterSet); - - StringBuilder optionSql = new StringBuilder(String.Empty); - if (FieldTerminator != defaultFieldTerminator) - optionSql.AppendFormat("TERMINATED BY '{0}' ", FieldTerminator); - if (FieldQuotationCharacter != Char.MinValue) - optionSql.AppendFormat("{0} ENCLOSED BY '{1}' ", - FieldQuotationOptional ? "OPTIONALLY" : "", FieldQuotationCharacter); - if (EscapeCharacter != defaultEscapeCharacter && - EscapeCharacter != Char.MinValue) - optionSql.AppendFormat("ESCAPED BY '{0}' ", EscapeCharacter); - if (optionSql.Length > 0) - sql.AppendFormat("FIELDS {0}", optionSql.ToString()); - - optionSql = new StringBuilder(String.Empty); - if (!string.IsNullOrEmpty(LinePrefix)) - optionSql.AppendFormat("STARTING BY '{0}' ", LinePrefix); - if (LineTerminator != defaultLineTerminator) - optionSql.AppendFormat("TERMINATED BY '{0}' ", LineTerminator); - if (optionSql.Length > 0) - sql.AppendFormat("LINES {0}", optionSql.ToString()); - - if (NumberOfLinesToSkip > 0) - sql.AppendFormat("IGNORE {0} LINES ", NumberOfLinesToSkip); - - if (Columns.Count > 0) - { - sql.Append("("); - sql.Append(Columns[0]); - for (int i = 1; i < Columns.Count; i++) - sql.AppendFormat(",{0}", Columns[i]); - sql.Append(") "); - } - - if (Expressions.Count > 0) - { - sql.Append("SET "); - sql.Append(Expressions[0]); - for (int i = 1; i < Expressions.Count; i++) - sql.AppendFormat(",{0}", Expressions[i]); - } - - return sql.ToString(); - } - } - - /// - /// Represents the priority set for bulk loading operations. - /// - public enum MySqlBulkLoaderPriority - { - /// - /// This is the default and indicates normal priority - /// - None, - /// - /// Low priority will cause the load operation to wait until all readers of the table - /// have finished. This only affects storage engines that use only table-level locking - /// such as MyISAM, Memory, and Merge. - /// - Low, - /// - /// Concurrent priority is only relevant for MyISAM tables and signals that if the table - /// has no free blocks in the middle that other readers can retrieve data from the table - /// while the load operation is happening. - /// - Concurrent - } - - /// - /// Represents the behavior when conflicts arise during bulk loading operations. - /// - public enum MySqlBulkLoaderConflictOption - { - /// - /// This is the default and indicates normal operation. In the event of a LOCAL load, this - /// is the same as ignore. When the data file is on the server, then a key conflict will - /// cause an error to be thrown and the rest of the data file ignored. - /// - None, - /// - /// Replace column values when a key conflict occurs. - /// - Replace, - /// - /// Ignore any rows where the primary key conflicts. - /// - Ignore - } -} +// Copyright © 2006, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using System; +using System.Collections.Generic; +using System.Data; +using System.IO; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace MySql.Data.MySqlClient +{ + /// + /// Allows importing large amounts of data into a database with bulk loading. + /// + public class MySqlBulkLoader + { + // constant values + private const string defaultFieldTerminator = "\t"; + private const string defaultLineTerminator = "\n"; + private const char defaultEscapeCharacter = '\\'; + + /// + /// Initializes a new instance of the class using the specified instance of . + /// + /// The that will be used to perform the bulk operation. + public MySqlBulkLoader(MySqlConnection connection) + { + Connection = connection; + Local = false; + FieldTerminator = defaultFieldTerminator; + LineTerminator = defaultLineTerminator; + FieldQuotationCharacter = Char.MinValue; + ConflictOption = MySqlBulkLoaderConflictOption.None; + Columns = new List(); + Expressions = new List(); + } + + #region Properties + + /// + /// Gets or sets the connection. + /// + /// The connection. + public MySqlConnection Connection { get; set; } + + /// + /// Gets or sets the field terminator. + /// + /// The field terminator. + public string FieldTerminator { get; set; } + + /// + /// Gets or sets the line terminator. + /// + /// The line terminator. + public string LineTerminator { get; set; } + + /// + /// Gets or sets the name of the table. + /// + /// The name of the table. + public string TableName { get; set; } + + /// + /// Gets or sets the character set. + /// + /// The character set. + public string CharacterSet { get; set; } + + /// + /// Gets or sets the name of the file. + /// + /// The name of the file. + public string FileName { get; set; } + + /// + /// Gets or sets the timeout. + /// + /// The timeout. + public int Timeout { get; set; } + + /// + /// Gets or sets a value indicating whether the file name that is to be loaded + /// is local to the client or not. The default value is false. + /// + /// true if local; otherwise, false. + public bool Local { get; set; } + + /// + /// Gets or sets the number of lines to skip. + /// + /// The number of lines to skip. + public int NumberOfLinesToSkip { get; set; } + + /// + /// Gets or sets the line prefix. + /// + /// The line prefix. + public string LinePrefix { get; set; } + + /// + /// Gets or sets the field quotation character. + /// + /// The field quotation character. + public char FieldQuotationCharacter { get; set; } + + /// + /// Gets or sets a value indicating whether [field quotation optional]. + /// + /// + /// true if [field quotation optional]; otherwise, false. + /// + public bool FieldQuotationOptional { get; set; } + + /// + /// Gets or sets the escape character. + /// + /// The escape character. + public char EscapeCharacter { get; set; } + + /// + /// Gets or sets the conflict option. + /// + /// The conflict option. + public MySqlBulkLoaderConflictOption ConflictOption { get; set; } + + /// + /// Gets or sets the priority. + /// + /// The priority. + public MySqlBulkLoaderPriority Priority { get; set; } + + /// + /// Gets the columns. + /// + /// The columns. + public List Columns { get; } + + /// + /// Gets the expressions. + /// + /// The expressions. + public List Expressions { get; } + + #endregion + + /// + /// Executes the load operation. + /// + /// The number of rows inserted. + public int Load() + { + if (string.IsNullOrWhiteSpace(FileName)) + throw new MySqlException("FileName property of MySqlBulkLoader cannot be null or an empty string."); + + return LoadAsync(null, false).GetAwaiter().GetResult(); + } + + /// + /// Executes the load operation. + /// + /// A object containing the data to be loaded. + /// The number of rows inserted. + public int Load(Stream stream) => LoadAsync(stream, false).GetAwaiter().GetResult(); + + /// + /// Asynchronous version of the load operation. + /// + /// The number of rows inserted. + public Task LoadAsync() => LoadAsync(null, true); + + /// + /// Asynchronous version of the load operation that accepts a data stream. + /// + /// A containing the data to be loaded. + /// The number of rows inserted. + public Task LoadAsync(Stream stream) => LoadAsync(stream, true); + + /// + /// Executes the load operation asynchronously while the cancellation isn't requested. + /// + /// The cancellation token. + /// A containing the data to be loaded. + /// The number of rows inserted. + public Task LoadAsync(Stream stream, CancellationToken cancellationToken) => LoadAsync(stream, true, cancellationToken); + + private async Task LoadAsync(Stream stream, bool execAsync, CancellationToken cancellationToken = default) + { + bool openedConnection = false; + + if (Connection == null) + throw new InvalidOperationException(Resources.ConnectionNotSet); + + // next we open up the connetion if it is not already open + if (Connection.State != ConnectionState.Open) + { + await Connection.OpenAsync(execAsync, cancellationToken).ConfigureAwait(false); + openedConnection = true; + } + + try + { + string sql = BuildSqlCommand(stream is not null); + Connection.driver.BulkLoaderStream = stream; + using MySqlCommand cmd = new MySqlCommand(sql, Connection) { CommandTimeout = Timeout }; + return await cmd.ExecuteNonQueryAsync(execAsync, cancellationToken).ConfigureAwait(false); + } + finally + { + if (stream is not null) + Connection.driver.BulkLoaderStream.Dispose(); + + if (openedConnection) + await Connection.CloseAsync(execAsync).ConfigureAwait(false); + } + } + + private string BuildSqlCommand(bool useStream) + { + StringBuilder sql = new StringBuilder("LOAD DATA "); + if (Priority == MySqlBulkLoaderPriority.Low) + sql.Append("LOW_PRIORITY "); + else if (Priority == MySqlBulkLoaderPriority.Concurrent) + sql.Append("CONCURRENT "); + + if (useStream) + sql.Append("LOCAL INFILE 'MySQLTempFile' "); + else + { + if (Local) + sql.Append("LOCAL "); + + sql.Append("INFILE "); + + if (Path.DirectorySeparatorChar == '\\') + sql.AppendFormat("'{0}' ", FileName.Replace(@"\", @"\\")); + else + sql.AppendFormat("'{0}' ", FileName); + } + + if (ConflictOption == MySqlBulkLoaderConflictOption.Ignore) + sql.Append("IGNORE "); + else if (ConflictOption == MySqlBulkLoaderConflictOption.Replace) + sql.Append("REPLACE "); + + sql.AppendFormat("INTO TABLE {0} ", TableName); + + if (CharacterSet != null) + sql.AppendFormat("CHARACTER SET {0} ", CharacterSet); + + StringBuilder optionSql = new StringBuilder(String.Empty); + if (FieldTerminator != defaultFieldTerminator) + optionSql.AppendFormat("TERMINATED BY '{0}' ", FieldTerminator); + if (FieldQuotationCharacter != Char.MinValue) + optionSql.AppendFormat("{0} ENCLOSED BY '{1}' ", + FieldQuotationOptional ? "OPTIONALLY" : "", FieldQuotationCharacter); + if (EscapeCharacter != defaultEscapeCharacter && + EscapeCharacter != Char.MinValue) + optionSql.AppendFormat("ESCAPED BY '{0}' ", EscapeCharacter); + if (optionSql.Length > 0) + sql.AppendFormat("FIELDS {0}", optionSql.ToString()); + + optionSql = new StringBuilder(String.Empty); + if (!string.IsNullOrEmpty(LinePrefix)) + optionSql.AppendFormat("STARTING BY '{0}' ", LinePrefix); + if (LineTerminator != defaultLineTerminator) + optionSql.AppendFormat("TERMINATED BY '{0}' ", LineTerminator); + if (optionSql.Length > 0) + sql.AppendFormat("LINES {0}", optionSql.ToString()); + + if (NumberOfLinesToSkip > 0) + sql.AppendFormat("IGNORE {0} LINES ", NumberOfLinesToSkip); + + if (Columns.Count > 0) + { + sql.Append("("); + sql.Append(Columns[0]); + for (int i = 1; i < Columns.Count; i++) + sql.AppendFormat(",{0}", Columns[i]); + sql.Append(") "); + } + + if (Expressions.Count > 0) + { + sql.Append("SET "); + sql.Append(Expressions[0]); + for (int i = 1; i < Expressions.Count; i++) + sql.AppendFormat(",{0}", Expressions[i]); + } + + return sql.ToString(); + } + } + + /// + /// Represents the priority set for bulk loading operations. + /// + public enum MySqlBulkLoaderPriority + { + /// + /// This is the default and indicates normal priority + /// + None, + /// + /// Low priority will cause the load operation to wait until all readers of the table + /// have finished. This only affects storage engines that use only table-level locking + /// such as MyISAM, Memory, and Merge. + /// + Low, + /// + /// Concurrent priority is only relevant for MyISAM tables and signals that if the table + /// has no free blocks in the middle that other readers can retrieve data from the table + /// while the load operation is happening. + /// + Concurrent + } + + /// + /// Represents the behavior when conflicts arise during bulk loading operations. + /// + public enum MySqlBulkLoaderConflictOption + { + /// + /// This is the default and indicates normal operation. In the event of a LOCAL load, this + /// is the same as ignore. When the data file is on the server, then a key conflict will + /// cause an error to be thrown and the rest of the data file ignored. + /// + None, + /// + /// Replace column values when a key conflict occurs. + /// + Replace, + /// + /// Ignore any rows where the primary key conflicts. + /// + Ignore + } +} diff --git a/MySQL.Data/src/CharSetMap.cs b/MySQL.Data/src/CharSetMap.cs index 553ca4160..8775e9e3a 100644 --- a/MySQL.Data/src/CharSetMap.cs +++ b/MySQL.Data/src/CharSetMap.cs @@ -1,230 +1,230 @@ -// Copyright (c) 2004, 2022, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using System; -using System.Collections.Generic; -using System.Text; -using System.Threading; -using System.Threading.Tasks; - -namespace MySql.Data.MySqlClient -{ - /// - /// Summary description for CharSetMap. - /// - internal class CharSetMap - { - private static Dictionary _defaultCollations; - private static Dictionary _maxLengths; - private static Dictionary _mapping; - private static readonly object LockObject; - - // we use a static constructor here since we only want to init - // the mapping once - static CharSetMap() - { - LockObject = new Object(); - InitializeMapping(); - } - - public static CharacterSet GetCharacterSet(string charSetName) - { - if (charSetName == null) - throw new ArgumentNullException("CharSetName is null"); - CharacterSet cs = null; - if (_mapping.ContainsKey(charSetName)) - cs = _mapping[charSetName]; - - if (cs == null) - throw new NotSupportedException("Character set '" + charSetName + "' is not supported by .Net Framework."); - return cs; - } - - /// - /// Returns the text encoding for a given MySQL character set name - /// - /// Name of the character set to get the encoding for - /// Encoding object for the given character set name - public static Encoding GetEncoding(string charSetName) - { - try - { - CharacterSet cs = GetCharacterSet(charSetName); - - return Encoding.GetEncoding(cs.name); - } - catch (ArgumentException) - { - return Encoding.GetEncoding("utf-8"); - } - catch (NotSupportedException) - { - return Encoding.GetEncoding("utf-8"); - } - } - - /// - /// Initializes the mapping. - /// - private static void InitializeMapping() - { - LoadCharsetMap(); - } - - private static void LoadCharsetMap() - { - _mapping = new Dictionary(); - - _mapping.Add("latin1", new CharacterSet("windows-1252", 1)); - _mapping.Add("big5", new CharacterSet("big5", 2)); - _mapping.Add("dec8", _mapping["latin1"]); - _mapping.Add("cp850", new CharacterSet("ibm850", 1)); - _mapping.Add("hp8", _mapping["latin1"]); - _mapping.Add("koi8r", new CharacterSet("koi8-u", 1)); - _mapping.Add("latin2", new CharacterSet("latin2", 1)); - _mapping.Add("swe7", _mapping["latin1"]); - _mapping.Add("ujis", new CharacterSet("EUC-JP", 3)); - _mapping.Add("eucjpms", _mapping["ujis"]); - _mapping.Add("sjis", new CharacterSet("sjis", 2)); - _mapping.Add("cp932", _mapping["sjis"]); - _mapping.Add("hebrew", new CharacterSet("hebrew", 1)); - _mapping.Add("tis620", new CharacterSet("windows-874", 1)); - _mapping.Add("euckr", new CharacterSet("euc-kr", 2)); - _mapping.Add("euc_kr", _mapping["euckr"]); - _mapping.Add("koi8u", new CharacterSet("koi8-u", 1)); - _mapping.Add("koi8_ru", _mapping["koi8u"]); - _mapping.Add("gb2312", new CharacterSet("gb2312", 2)); - _mapping.Add("gbk", _mapping["gb2312"]); - _mapping.Add("greek", new CharacterSet("greek", 1)); - _mapping.Add("cp1250", new CharacterSet("windows-1250", 1)); - _mapping.Add("win1250", _mapping["cp1250"]); - _mapping.Add("latin5", new CharacterSet("latin5", 1)); - _mapping.Add("armscii8", _mapping["latin1"]); - _mapping.Add("utf8", new CharacterSet("utf-8", 3)); - _mapping.Add("ucs2", new CharacterSet("UTF-16BE", 2)); - _mapping.Add("cp866", new CharacterSet("cp866", 1)); - _mapping.Add("keybcs2", _mapping["latin1"]); - _mapping.Add("macce", new CharacterSet("x-mac-ce", 1)); - _mapping.Add("macroman", new CharacterSet("x-mac-romanian", 1)); - _mapping.Add("cp852", new CharacterSet("ibm852", 2)); - _mapping.Add("latin7", new CharacterSet("iso-8859-7", 1)); - _mapping.Add("cp1251", new CharacterSet("windows-1251", 1)); - _mapping.Add("win1251ukr", _mapping["cp1251"]); - _mapping.Add("cp1251csas", _mapping["cp1251"]); - _mapping.Add("cp1251cias", _mapping["cp1251"]); - _mapping.Add("win1251", _mapping["cp1251"]); - _mapping.Add("cp1256", new CharacterSet("cp1256", 1)); - _mapping.Add("cp1257", new CharacterSet("windows-1257", 1)); - _mapping.Add("ascii", new CharacterSet("us-ascii", 1)); - _mapping.Add("usa7", _mapping["ascii"]); - _mapping.Add("binary", _mapping["ascii"]); - _mapping.Add("latin3", new CharacterSet("latin3", 1)); - _mapping.Add("latin4", new CharacterSet("latin4", 1)); - _mapping.Add("latin1_de", new CharacterSet("iso-8859-1", 1)); - _mapping.Add("german1", new CharacterSet("iso-8859-1", 1)); - _mapping.Add("danish", new CharacterSet("iso-8859-1", 1)); - _mapping.Add("czech", new CharacterSet("iso-8859-2", 1)); - _mapping.Add("hungarian", new CharacterSet("iso-8859-2", 1)); - _mapping.Add("croat", new CharacterSet("iso-8859-2", 1)); - _mapping.Add("latvian", new CharacterSet("iso-8859-13", 1)); - _mapping.Add("latvian1", new CharacterSet("iso-8859-13", 1)); - _mapping.Add("estonia", new CharacterSet("iso-8859-13", 1)); - _mapping.Add("dos", new CharacterSet("ibm437", 1)); - _mapping.Add("utf8mb3", _mapping["utf8"]); - _mapping.Add("utf8mb4", new CharacterSet("utf-8", 4)); - _mapping.Add("utf16", new CharacterSet("utf-16BE", 2)); - _mapping.Add("utf16le", new CharacterSet("utf-16", 2)); - _mapping.Add("utf32", new CharacterSet("utf-32BE", 4)); - _mapping.Add("gb18030", new CharacterSet("gb18030", 4)); - } - - internal static async Task InitCollectionsAsync(MySqlConnection connection, bool execAsync, CancellationToken cancellationToken = default) - { - _defaultCollations = new Dictionary(); - _maxLengths = new Dictionary(); - - MySqlCommand cmd = new MySqlCommand("SHOW CHARSET", connection); - using (MySqlDataReader reader = await cmd.ExecuteReaderAsync(default, execAsync, cancellationToken).ConfigureAwait(false)) - { - while (await reader.ReadAsync(execAsync, cancellationToken).ConfigureAwait(false)) - { - _defaultCollations.Add(reader.GetString(0), reader.GetString(2)); - _maxLengths.Add(reader.GetString(0), Convert.ToInt32(reader.GetValue(3))); - } - } - } - - internal static async Task GetDefaultCollationAsync(string charset, MySqlConnection connection, bool execAsync, CancellationToken cancellationToken = default) - { - SemaphoreSlim semaphoreSlim = new SemaphoreSlim(1); - semaphoreSlim.Wait(); - - if (_defaultCollations == null) - await InitCollectionsAsync(connection, execAsync, cancellationToken).ConfigureAwait(false); - - semaphoreSlim.Release(); - return !_defaultCollations.ContainsKey(charset) ? null : _defaultCollations[charset]; - } - - internal static async Task GetMaxLengthAsync(string charset, MySqlConnection connection, bool execAsync, CancellationToken cancellationToken = default) - { - SemaphoreSlim semaphoreSlim = new SemaphoreSlim(1); - semaphoreSlim.Wait(); - - if (_maxLengths == null) - await InitCollectionsAsync(connection, execAsync, cancellationToken).ConfigureAwait(false); - - semaphoreSlim.Release(); - - return !_maxLengths.ContainsKey(charset) ? 1 : _maxLengths[charset]; - } - } - - /// - /// Represents a character set object. - /// - public class CharacterSet - { - public string name; - public int byteCount; - - public CharacterSet(string name, int byteCount) - { - this.name = name; - this.byteCount = byteCount; - } - - public override int GetHashCode() - { - unchecked - { - return ((name != null ? name.GetHashCode() : 0) * 397) ^ byteCount; - } - } - } -} \ No newline at end of file +// Copyright © 2004, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace MySql.Data.MySqlClient +{ + /// + /// Summary description for CharSetMap. + /// + internal class CharSetMap + { + private static Dictionary _defaultCollations; + private static Dictionary _maxLengths; + private static Dictionary _mapping; + private static readonly object LockObject; + + // we use a static constructor here since we only want to init + // the mapping once + static CharSetMap() + { + LockObject = new Object(); + InitializeMapping(); + } + + public static CharacterSet GetCharacterSet(string charSetName) + { + if (charSetName == null) + throw new ArgumentNullException("CharSetName is null"); + CharacterSet cs = null; + if (_mapping.ContainsKey(charSetName)) + cs = _mapping[charSetName]; + + if (cs == null) + throw new NotSupportedException("Character set '" + charSetName + "' is not supported by .Net Framework."); + return cs; + } + + /// + /// Returns the text encoding for a given MySQL character set name + /// + /// Name of the character set to get the encoding for + /// Encoding object for the given character set name + public static Encoding GetEncoding(string charSetName) + { + try + { + CharacterSet cs = GetCharacterSet(charSetName); + + return Encoding.GetEncoding(cs.name); + } + catch (ArgumentException) + { + return Encoding.GetEncoding("utf-8"); + } + catch (NotSupportedException) + { + return Encoding.GetEncoding("utf-8"); + } + } + + /// + /// Initializes the mapping. + /// + private static void InitializeMapping() + { + LoadCharsetMap(); + } + + private static void LoadCharsetMap() + { + _mapping = new Dictionary(); + + _mapping.Add("latin1", new CharacterSet("windows-1252", 1)); + _mapping.Add("big5", new CharacterSet("big5", 2)); + _mapping.Add("dec8", _mapping["latin1"]); + _mapping.Add("cp850", new CharacterSet("ibm850", 1)); + _mapping.Add("hp8", _mapping["latin1"]); + _mapping.Add("koi8r", new CharacterSet("koi8-u", 1)); + _mapping.Add("latin2", new CharacterSet("latin2", 1)); + _mapping.Add("swe7", _mapping["latin1"]); + _mapping.Add("ujis", new CharacterSet("EUC-JP", 3)); + _mapping.Add("eucjpms", _mapping["ujis"]); + _mapping.Add("sjis", new CharacterSet("sjis", 2)); + _mapping.Add("cp932", _mapping["sjis"]); + _mapping.Add("hebrew", new CharacterSet("hebrew", 1)); + _mapping.Add("tis620", new CharacterSet("windows-874", 1)); + _mapping.Add("euckr", new CharacterSet("euc-kr", 2)); + _mapping.Add("euc_kr", _mapping["euckr"]); + _mapping.Add("koi8u", new CharacterSet("koi8-u", 1)); + _mapping.Add("koi8_ru", _mapping["koi8u"]); + _mapping.Add("gb2312", new CharacterSet("gb2312", 2)); + _mapping.Add("gbk", _mapping["gb2312"]); + _mapping.Add("greek", new CharacterSet("greek", 1)); + _mapping.Add("cp1250", new CharacterSet("windows-1250", 1)); + _mapping.Add("win1250", _mapping["cp1250"]); + _mapping.Add("latin5", new CharacterSet("latin5", 1)); + _mapping.Add("armscii8", _mapping["latin1"]); + _mapping.Add("utf8", new CharacterSet("utf-8", 3)); + _mapping.Add("ucs2", new CharacterSet("UTF-16BE", 2)); + _mapping.Add("cp866", new CharacterSet("cp866", 1)); + _mapping.Add("keybcs2", _mapping["latin1"]); + _mapping.Add("macce", new CharacterSet("x-mac-ce", 1)); + _mapping.Add("macroman", new CharacterSet("x-mac-romanian", 1)); + _mapping.Add("cp852", new CharacterSet("ibm852", 2)); + _mapping.Add("latin7", new CharacterSet("iso-8859-7", 1)); + _mapping.Add("cp1251", new CharacterSet("windows-1251", 1)); + _mapping.Add("win1251ukr", _mapping["cp1251"]); + _mapping.Add("cp1251csas", _mapping["cp1251"]); + _mapping.Add("cp1251cias", _mapping["cp1251"]); + _mapping.Add("win1251", _mapping["cp1251"]); + _mapping.Add("cp1256", new CharacterSet("cp1256", 1)); + _mapping.Add("cp1257", new CharacterSet("windows-1257", 1)); + _mapping.Add("ascii", new CharacterSet("us-ascii", 1)); + _mapping.Add("usa7", _mapping["ascii"]); + _mapping.Add("binary", _mapping["ascii"]); + _mapping.Add("latin3", new CharacterSet("latin3", 1)); + _mapping.Add("latin4", new CharacterSet("latin4", 1)); + _mapping.Add("latin1_de", new CharacterSet("iso-8859-1", 1)); + _mapping.Add("german1", new CharacterSet("iso-8859-1", 1)); + _mapping.Add("danish", new CharacterSet("iso-8859-1", 1)); + _mapping.Add("czech", new CharacterSet("iso-8859-2", 1)); + _mapping.Add("hungarian", new CharacterSet("iso-8859-2", 1)); + _mapping.Add("croat", new CharacterSet("iso-8859-2", 1)); + _mapping.Add("latvian", new CharacterSet("iso-8859-13", 1)); + _mapping.Add("latvian1", new CharacterSet("iso-8859-13", 1)); + _mapping.Add("estonia", new CharacterSet("iso-8859-13", 1)); + _mapping.Add("dos", new CharacterSet("ibm437", 1)); + _mapping.Add("utf8mb3", _mapping["utf8"]); + _mapping.Add("utf8mb4", new CharacterSet("utf-8", 4)); + _mapping.Add("utf16", new CharacterSet("utf-16BE", 2)); + _mapping.Add("utf16le", new CharacterSet("utf-16", 2)); + _mapping.Add("utf32", new CharacterSet("utf-32BE", 4)); + _mapping.Add("gb18030", new CharacterSet("gb18030", 4)); + } + + internal static async Task InitCollectionsAsync(MySqlConnection connection, bool execAsync, CancellationToken cancellationToken = default) + { + _defaultCollations = new Dictionary(); + _maxLengths = new Dictionary(); + + MySqlCommand cmd = new MySqlCommand("SHOW CHARSET", connection); + using (MySqlDataReader reader = await cmd.ExecuteReaderAsync(default, execAsync, cancellationToken).ConfigureAwait(false)) + { + while (await reader.ReadAsync(execAsync, cancellationToken).ConfigureAwait(false)) + { + _defaultCollations.Add(reader.GetString(0), reader.GetString(2)); + _maxLengths.Add(reader.GetString(0), Convert.ToInt32(reader.GetValue(3))); + } + } + } + + internal static async Task GetDefaultCollationAsync(string charset, MySqlConnection connection, bool execAsync, CancellationToken cancellationToken = default) + { + SemaphoreSlim semaphoreSlim = new SemaphoreSlim(1); + semaphoreSlim.Wait(); + + if (_defaultCollations == null) + await InitCollectionsAsync(connection, execAsync, cancellationToken).ConfigureAwait(false); + + semaphoreSlim.Release(); + return !_defaultCollations.ContainsKey(charset) ? null : _defaultCollations[charset]; + } + + internal static async Task GetMaxLengthAsync(string charset, MySqlConnection connection, bool execAsync, CancellationToken cancellationToken = default) + { + SemaphoreSlim semaphoreSlim = new SemaphoreSlim(1); + semaphoreSlim.Wait(); + + if (_maxLengths == null) + await InitCollectionsAsync(connection, execAsync, cancellationToken).ConfigureAwait(false); + + semaphoreSlim.Release(); + + return !_maxLengths.ContainsKey(charset) ? 1 : _maxLengths[charset]; + } + } + + /// + /// Represents a character set object. + /// + public class CharacterSet + { + public string name; + public int byteCount; + + public CharacterSet(string name, int byteCount) + { + this.name = name; + this.byteCount = byteCount; + } + + public override int GetHashCode() + { + unchecked + { + return ((name != null ? name.GetHashCode() : 0) * 397) ^ byteCount; + } + } + } +} diff --git a/MySQL.Data/src/CompressedStream.cs b/MySQL.Data/src/CompressedStream.cs index b48c5c156..5a100569d 100644 --- a/MySQL.Data/src/CompressedStream.cs +++ b/MySQL.Data/src/CompressedStream.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2004, 2022, Oracle and/or its affiliates. +// Copyright © 2004, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/Crypt.cs b/MySQL.Data/src/Crypt.cs index d93f0396c..ab13a858c 100644 --- a/MySQL.Data/src/Crypt.cs +++ b/MySQL.Data/src/Crypt.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2004, 2019, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2004, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -184,4 +184,4 @@ private static long[] Hash(String P) return hash; } } -} \ No newline at end of file +} diff --git a/MySQL.Data/src/Driver.cs b/MySQL.Data/src/Driver.cs index 6e96c9f23..51db1aeb8 100644 --- a/MySQL.Data/src/Driver.cs +++ b/MySQL.Data/src/Driver.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2004, 2023, Oracle and/or its affiliates. +// Copyright © 2004, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/Exception.cs b/MySQL.Data/src/Exception.cs index d3be7037d..121d8cf58 100644 --- a/MySQL.Data/src/Exception.cs +++ b/MySQL.Data/src/Exception.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2004, 2022, Oracle and/or its affiliates. +// Copyright © 2004, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/Failover/FailoverGroup.cs b/MySQL.Data/src/Failover/FailoverGroup.cs index c9198d8ab..f708ce12b 100644 --- a/MySQL.Data/src/Failover/FailoverGroup.cs +++ b/MySQL.Data/src/Failover/FailoverGroup.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2017, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/Failover/FailoverManager.cs b/MySQL.Data/src/Failover/FailoverManager.cs index 1c2711b3e..236a52f26 100644 --- a/MySQL.Data/src/Failover/FailoverManager.cs +++ b/MySQL.Data/src/Failover/FailoverManager.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2017, 2022, Oracle and/or its affiliates. +// Copyright © 2017, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/Failover/FailoverServer.cs b/MySQL.Data/src/Failover/FailoverServer.cs index 3f23ef604..6081159f3 100644 --- a/MySQL.Data/src/Failover/FailoverServer.cs +++ b/MySQL.Data/src/Failover/FailoverServer.cs @@ -1,16 +1,16 @@ -// Copyright © 2017, 2019, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2017, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/Failover/RandomFailoverGroup.cs b/MySQL.Data/src/Failover/RandomFailoverGroup.cs index 137c5475e..e2af1ebc4 100644 --- a/MySQL.Data/src/Failover/RandomFailoverGroup.cs +++ b/MySQL.Data/src/Failover/RandomFailoverGroup.cs @@ -1,16 +1,16 @@ -// Copyright © 2019, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2019, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -96,4 +96,4 @@ protected internal override FailoverServer GetNextHost() return _activeHost; } } -} \ No newline at end of file +} diff --git a/MySQL.Data/src/Failover/SequentialFailoverGroup.cs b/MySQL.Data/src/Failover/SequentialFailoverGroup.cs index af64c3800..3214fcbf4 100644 --- a/MySQL.Data/src/Failover/SequentialFailoverGroup.cs +++ b/MySQL.Data/src/Failover/SequentialFailoverGroup.cs @@ -1,16 +1,16 @@ -// Copyright © 2017, 2019, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2017, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -94,4 +94,4 @@ protected internal override FailoverServer GetNextHost() return _activeHost; } } -} \ No newline at end of file +} diff --git a/MySQL.Data/src/Field.cs b/MySQL.Data/src/Field.cs index 2202b07e3..7715ef83a 100644 --- a/MySQL.Data/src/Field.cs +++ b/MySQL.Data/src/Field.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2004, 2022, Oracle and/or its affiliates. +// Copyright © 2004, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/Framework/net462/SystemPerformanceMonitor.cs b/MySQL.Data/src/Framework/net462/SystemPerformanceMonitor.cs index f92324d66..8795311f6 100644 --- a/MySQL.Data/src/Framework/net462/SystemPerformanceMonitor.cs +++ b/MySQL.Data/src/Framework/net462/SystemPerformanceMonitor.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2004, 2023, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2004, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -89,4 +89,4 @@ public override void AddSoftProcedureQuery() } } #endif -} \ No newline at end of file +} diff --git a/MySQL.Data/src/Framework/netstandard2_0/AuthenticationManager.cs b/MySQL.Data/src/Framework/netstandard2_0/AuthenticationManager.cs index eb3a6a54e..f1672c2a3 100644 --- a/MySQL.Data/src/Framework/netstandard2_0/AuthenticationManager.cs +++ b/MySQL.Data/src/Framework/netstandard2_0/AuthenticationManager.cs @@ -1,16 +1,16 @@ -// Copyright © 2012, 2016, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2012, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -47,4 +47,4 @@ static partial void AuthenticationManagerCtorConfiguration() } } } -} \ No newline at end of file +} diff --git a/MySQL.Data/src/Framework/netstandard2_0/CommandBuilder.cs b/MySQL.Data/src/Framework/netstandard2_0/CommandBuilder.cs index 4b01bfb8a..1d3c2fb5b 100644 --- a/MySQL.Data/src/Framework/netstandard2_0/CommandBuilder.cs +++ b/MySQL.Data/src/Framework/netstandard2_0/CommandBuilder.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2004, 2022, Oracle and/or its affiliates. +// Copyright © 2004, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/Framework/netstandard2_0/MySqlClientPermission.cs b/MySQL.Data/src/Framework/netstandard2_0/MySqlClientPermission.cs index 42edca767..c2892661c 100644 --- a/MySQL.Data/src/Framework/netstandard2_0/MySqlClientPermission.cs +++ b/MySQL.Data/src/Framework/netstandard2_0/MySqlClientPermission.cs @@ -1,102 +1,102 @@ -// Copyright � 2004, 2018, Oracle and/or its affiliates. All rights reserved. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using System; -using System.Collections.Generic; -using System.Data; -using System.Data.Common; -using System.Security; -using System.Security.Permissions; - -namespace MySql.Data.MySqlClient -{ - /// - /// Enables the provider to help ensure that a user has a security level adequate for accessing data. - /// - [Serializable] - public sealed class MySqlClientPermission : DBDataPermission - { - - #region Contructors - - public MySqlClientPermission(PermissionState permissionState) - : base(permissionState) - { - } - - private MySqlClientPermission(MySqlClientPermission permission):base(permission) - { - } - - internal MySqlClientPermission(MySqlClientPermissionAttribute permissionAttribute):base(permissionAttribute) - { - } - - internal MySqlClientPermission (DBDataPermission permission) - : base (permission) - { - } - - internal MySqlClientPermission(string connectionString) - : base(PermissionState.None) - { - if ((connectionString == null) || connectionString.Length == 0) - base.Add(string.Empty, string.Empty, KeyRestrictionBehavior.AllowOnly); - else - base.Add(connectionString, string.Empty, KeyRestrictionBehavior.AllowOnly); - } - - - #endregion - - #region Methods - - /// - /// Adds a new connection string with set of restricted keywords to the MySqlClientPermission object - /// - ///Settings to be used for the connection - ///Keywords to define the restrictions - ///KeyRestrictionBehavior to be used - public override void Add(string connectionString, string restrictions, KeyRestrictionBehavior behavior) - { - base.Add(connectionString, restrictions, behavior); - } - - /// - /// Returns MySqlClientPermission as an IPermission - /// - /// - public override IPermission Copy() - { - return new MySqlClientPermission(this); - } - - #endregion - - } -} +// Copyright © 2004, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using System; +using System.Collections.Generic; +using System.Data; +using System.Data.Common; +using System.Security; +using System.Security.Permissions; + +namespace MySql.Data.MySqlClient +{ + /// + /// Enables the provider to help ensure that a user has a security level adequate for accessing data. + /// + [Serializable] + public sealed class MySqlClientPermission : DBDataPermission + { + + #region Contructors + + public MySqlClientPermission(PermissionState permissionState) + : base(permissionState) + { + } + + private MySqlClientPermission(MySqlClientPermission permission):base(permission) + { + } + + internal MySqlClientPermission(MySqlClientPermissionAttribute permissionAttribute):base(permissionAttribute) + { + } + + internal MySqlClientPermission (DBDataPermission permission) + : base (permission) + { + } + + internal MySqlClientPermission(string connectionString) + : base(PermissionState.None) + { + if ((connectionString == null) || connectionString.Length == 0) + base.Add(string.Empty, string.Empty, KeyRestrictionBehavior.AllowOnly); + else + base.Add(connectionString, string.Empty, KeyRestrictionBehavior.AllowOnly); + } + + + #endregion + + #region Methods + + /// + /// Adds a new connection string with set of restricted keywords to the MySqlClientPermission object + /// + ///Settings to be used for the connection + ///Keywords to define the restrictions + ///KeyRestrictionBehavior to be used + public override void Add(string connectionString, string restrictions, KeyRestrictionBehavior behavior) + { + base.Add(connectionString, restrictions, behavior); + } + + /// + /// Returns MySqlClientPermission as an IPermission + /// + /// + public override IPermission Copy() + { + return new MySqlClientPermission(this); + } + + #endregion + + } +} diff --git a/MySQL.Data/src/Framework/netstandard2_0/MySqlClientPermissionAttribute.cs b/MySQL.Data/src/Framework/netstandard2_0/MySqlClientPermissionAttribute.cs index b5ac3263a..9ebcf2a96 100644 --- a/MySQL.Data/src/Framework/netstandard2_0/MySqlClientPermissionAttribute.cs +++ b/MySQL.Data/src/Framework/netstandard2_0/MySqlClientPermissionAttribute.cs @@ -1,53 +1,53 @@ -// Copyright � 2004, 2018, Oracle and/or its affiliates. All rights reserved. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using System; -using System.Collections.Generic; -using System.Data.Common; -using System.Security; -using System.Security.Permissions; - -namespace MySql.Data.MySqlClient -{ - /// - /// Associates a security action with a custom security attribute. - /// - [Serializable, AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Struct | AttributeTargets.Class | AttributeTargets.Assembly, AllowMultiple = true, Inherited = false)] - public sealed class MySqlClientPermissionAttribute : DBDataPermissionAttribute - { - // Methods - public MySqlClientPermissionAttribute(SecurityAction action) : base(action) - { - } - - public override IPermission CreatePermission() - { - return new MySqlClientPermission(this); - } - } -} +// Copyright © 2004, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using System; +using System.Collections.Generic; +using System.Data.Common; +using System.Security; +using System.Security.Permissions; + +namespace MySql.Data.MySqlClient +{ + /// + /// Associates a security action with a custom security attribute. + /// + [Serializable, AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Struct | AttributeTargets.Class | AttributeTargets.Assembly, AllowMultiple = true, Inherited = false)] + public sealed class MySqlClientPermissionAttribute : DBDataPermissionAttribute + { + // Methods + public MySqlClientPermissionAttribute(SecurityAction action) : base(action) + { + } + + public override IPermission CreatePermission() + { + return new MySqlClientPermission(this); + } + } +} diff --git a/MySQL.Data/src/Framework/netstandard2_0/MySqlConfiguration.cs b/MySQL.Data/src/Framework/netstandard2_0/MySqlConfiguration.cs index 1dddfc35e..8a2882b6f 100644 --- a/MySQL.Data/src/Framework/netstandard2_0/MySqlConfiguration.cs +++ b/MySQL.Data/src/Framework/netstandard2_0/MySqlConfiguration.cs @@ -1,205 +1,205 @@ -// Copyright � 2013, 2018, Oracle and/or its affiliates. All rights reserved. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using System; -using System.Collections.Generic; -using System.Text; -using System.Configuration; - -namespace MySql.Data.MySqlClient -{ - /// - /// Represents a section within a configuration file. - /// - public sealed class MySqlConfiguration : ConfigurationSection - { - private static MySqlConfiguration settings - = ConfigurationManager.GetSection("MySQL") as MySqlConfiguration; - - /// - /// Gets the MySQL configuations associated to the current configuration. - /// - public static MySqlConfiguration Settings - { - get { return settings; } - } - - /// - /// Gets a collection of the exception interceptors available in the current configuration. - /// - [ConfigurationProperty("ExceptionInterceptors", IsRequired = false)] - [ConfigurationCollection(typeof(InterceptorConfigurationElement), AddItemName = "add", ClearItemsName = "clear", RemoveItemName = "remove")] - public GenericConfigurationElementCollection ExceptionInterceptors - { - get { return (GenericConfigurationElementCollection)this["ExceptionInterceptors"]; } - } - - /// - /// Gets a collection of the command interceptors available in the current configuration. - /// - [ConfigurationProperty("CommandInterceptors", IsRequired = false)] - [ConfigurationCollection(typeof(InterceptorConfigurationElement), AddItemName = "add", ClearItemsName = "clear", RemoveItemName = "remove")] - public GenericConfigurationElementCollection CommandInterceptors - { - get { return (GenericConfigurationElementCollection)this["CommandInterceptors"]; } - } - - /// - /// Gets a collection of the authentication plugins available in the current configuration. - /// - [ConfigurationProperty("AuthenticationPlugins", IsRequired = false)] - [ConfigurationCollection(typeof(AuthenticationPluginConfigurationElement), AddItemName = "add", ClearItemsName = "clear", RemoveItemName = "remove")] - public GenericConfigurationElementCollection AuthenticationPlugins - { - get { return (GenericConfigurationElementCollection)this["AuthenticationPlugins"]; } - } - - /// - /// Gets or sets the replication configurations. - /// - [ConfigurationProperty("Replication", IsRequired = true)] - public ReplicationConfigurationElement Replication - { - get - { - return (ReplicationConfigurationElement)this["Replication"]; - } - set - { - this["Replication"] = value; - } - } - - } - - /// - /// Defines the configurations allowed for an authentication plugin. - /// - public sealed class AuthenticationPluginConfigurationElement : ConfigurationElement - { - /// - /// Gets or sets the name of the authentication plugin. - /// - [ConfigurationProperty("name", IsRequired = true)] - public string Name - { - get - { - return (string)this["name"]; - } - set - { - this["name"] = value; - } - } - - /// - /// Gets or sets the type of the authentication plugin. - /// - [ConfigurationProperty("type", IsRequired = true)] - public string Type - { - get - { - return (string)this["type"]; - } - set - { - this["type"] = value; - } - } - } - - /// - /// Defines the configurations allowed for an interceptor. - /// - public sealed class InterceptorConfigurationElement : ConfigurationElement - { - /// - /// Gets or sets the name of the interceptor. - /// - [ConfigurationProperty("name", IsRequired = true)] - public string Name - { - get - { - return (string)this["name"]; - } - set - { - this["name"] = value; - } - } - - /// - /// Gets or sets the type of the interceptor. - /// - [ConfigurationProperty("type", IsRequired = true)] - public string Type - { - get - { - return (string)this["type"]; - } - set - { - this["type"] = value; - } - } - } - - /// - /// Represents a generic configuration element. - /// - /// - public sealed class GenericConfigurationElementCollection : ConfigurationElementCollection, IEnumerable where T : ConfigurationElement, new() - { - List _elements = new List(); - - protected override ConfigurationElement CreateNewElement() - { - T newElement = new T(); - _elements.Add(newElement); - return newElement; - } - - protected override object GetElementKey(ConfigurationElement element) - { - return _elements.Find(e => e.Equals(element)); - } - - /// - /// Gets an enumerator that iterates through the returned list. - /// - /// An enumerator that iterates through the returned list. - public new IEnumerator GetEnumerator() - { - return _elements.GetEnumerator(); - } - } -} +// Copyright © 2013, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using System; +using System.Collections.Generic; +using System.Text; +using System.Configuration; + +namespace MySql.Data.MySqlClient +{ + /// + /// Represents a section within a configuration file. + /// + public sealed class MySqlConfiguration : ConfigurationSection + { + private static MySqlConfiguration settings + = ConfigurationManager.GetSection("MySQL") as MySqlConfiguration; + + /// + /// Gets the MySQL configuations associated to the current configuration. + /// + public static MySqlConfiguration Settings + { + get { return settings; } + } + + /// + /// Gets a collection of the exception interceptors available in the current configuration. + /// + [ConfigurationProperty("ExceptionInterceptors", IsRequired = false)] + [ConfigurationCollection(typeof(InterceptorConfigurationElement), AddItemName = "add", ClearItemsName = "clear", RemoveItemName = "remove")] + public GenericConfigurationElementCollection ExceptionInterceptors + { + get { return (GenericConfigurationElementCollection)this["ExceptionInterceptors"]; } + } + + /// + /// Gets a collection of the command interceptors available in the current configuration. + /// + [ConfigurationProperty("CommandInterceptors", IsRequired = false)] + [ConfigurationCollection(typeof(InterceptorConfigurationElement), AddItemName = "add", ClearItemsName = "clear", RemoveItemName = "remove")] + public GenericConfigurationElementCollection CommandInterceptors + { + get { return (GenericConfigurationElementCollection)this["CommandInterceptors"]; } + } + + /// + /// Gets a collection of the authentication plugins available in the current configuration. + /// + [ConfigurationProperty("AuthenticationPlugins", IsRequired = false)] + [ConfigurationCollection(typeof(AuthenticationPluginConfigurationElement), AddItemName = "add", ClearItemsName = "clear", RemoveItemName = "remove")] + public GenericConfigurationElementCollection AuthenticationPlugins + { + get { return (GenericConfigurationElementCollection)this["AuthenticationPlugins"]; } + } + + /// + /// Gets or sets the replication configurations. + /// + [ConfigurationProperty("Replication", IsRequired = true)] + public ReplicationConfigurationElement Replication + { + get + { + return (ReplicationConfigurationElement)this["Replication"]; + } + set + { + this["Replication"] = value; + } + } + + } + + /// + /// Defines the configurations allowed for an authentication plugin. + /// + public sealed class AuthenticationPluginConfigurationElement : ConfigurationElement + { + /// + /// Gets or sets the name of the authentication plugin. + /// + [ConfigurationProperty("name", IsRequired = true)] + public string Name + { + get + { + return (string)this["name"]; + } + set + { + this["name"] = value; + } + } + + /// + /// Gets or sets the type of the authentication plugin. + /// + [ConfigurationProperty("type", IsRequired = true)] + public string Type + { + get + { + return (string)this["type"]; + } + set + { + this["type"] = value; + } + } + } + + /// + /// Defines the configurations allowed for an interceptor. + /// + public sealed class InterceptorConfigurationElement : ConfigurationElement + { + /// + /// Gets or sets the name of the interceptor. + /// + [ConfigurationProperty("name", IsRequired = true)] + public string Name + { + get + { + return (string)this["name"]; + } + set + { + this["name"] = value; + } + } + + /// + /// Gets or sets the type of the interceptor. + /// + [ConfigurationProperty("type", IsRequired = true)] + public string Type + { + get + { + return (string)this["type"]; + } + set + { + this["type"] = value; + } + } + } + + /// + /// Represents a generic configuration element. + /// + /// + public sealed class GenericConfigurationElementCollection : ConfigurationElementCollection, IEnumerable where T : ConfigurationElement, new() + { + List _elements = new List(); + + protected override ConfigurationElement CreateNewElement() + { + T newElement = new T(); + _elements.Add(newElement); + return newElement; + } + + protected override object GetElementKey(ConfigurationElement element) + { + return _elements.Find(e => e.Equals(element)); + } + + /// + /// Gets an enumerator that iterates through the returned list. + /// + /// An enumerator that iterates through the returned list. + public new IEnumerator GetEnumerator() + { + return _elements.GetEnumerator(); + } + } +} diff --git a/MySQL.Data/src/Framework/netstandard2_0/MySqlHelper.cs b/MySQL.Data/src/Framework/netstandard2_0/MySqlHelper.cs index 7bd6f07de..8049e040c 100644 --- a/MySQL.Data/src/Framework/netstandard2_0/MySqlHelper.cs +++ b/MySQL.Data/src/Framework/netstandard2_0/MySqlHelper.cs @@ -1,16 +1,16 @@ -// Copyright © 2004, 2018, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2004, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/Framework/netstandard2_0/MySqlPromotableTransaction.cs b/MySQL.Data/src/Framework/netstandard2_0/MySqlPromotableTransaction.cs index cbafb651b..fcb67ee3f 100644 --- a/MySQL.Data/src/Framework/netstandard2_0/MySqlPromotableTransaction.cs +++ b/MySQL.Data/src/Framework/netstandard2_0/MySqlPromotableTransaction.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2004, 2022, Oracle and/or its affiliates. +// Copyright © 2004, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/Framework/netstandard2_0/MySqlSecurityPermission.cs b/MySQL.Data/src/Framework/netstandard2_0/MySqlSecurityPermission.cs index 329f1e4d7..17c20ded6 100644 --- a/MySQL.Data/src/Framework/netstandard2_0/MySqlSecurityPermission.cs +++ b/MySQL.Data/src/Framework/netstandard2_0/MySqlSecurityPermission.cs @@ -1,65 +1,65 @@ -// Copyright (c) 2011, 2022, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using System; -using System.Net; -using System.Security; -using System.Security.Permissions; - -namespace MySql.Data.MySqlClient -{ - /// - /// Defines security permissions assigned to a MySQL object. - /// - public sealed class MySqlSecurityPermission : MarshalByRefObject - { - private MySqlSecurityPermission() - { - } - - /// - /// Creates a set of permissions. - /// - /// A flag indicating if the reflection permission should be included. - /// A object representing a collection of permissions. - public static PermissionSet CreatePermissionSet(bool includeReflectionPermission) - { - PermissionSet permissionsSet = new PermissionSet(null); - permissionsSet.AddPermission(new SecurityPermission(SecurityPermissionFlag.Execution)); - permissionsSet.AddPermission(new SocketPermission(PermissionState.Unrestricted)); - permissionsSet.AddPermission(new SecurityPermission(SecurityPermissionFlag.UnmanagedCode)); - permissionsSet.AddPermission(new DnsPermission(PermissionState.Unrestricted)); - permissionsSet.AddPermission(new FileIOPermission(PermissionState.Unrestricted)); - permissionsSet.AddPermission(new EnvironmentPermission(PermissionState.Unrestricted)); - - if (includeReflectionPermission) permissionsSet.AddPermission(new ReflectionPermission(PermissionState.Unrestricted)); - - return permissionsSet; - } - } -} +// Copyright © 2011, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using System; +using System.Net; +using System.Security; +using System.Security.Permissions; + +namespace MySql.Data.MySqlClient +{ + /// + /// Defines security permissions assigned to a MySQL object. + /// + public sealed class MySqlSecurityPermission : MarshalByRefObject + { + private MySqlSecurityPermission() + { + } + + /// + /// Creates a set of permissions. + /// + /// A flag indicating if the reflection permission should be included. + /// A object representing a collection of permissions. + public static PermissionSet CreatePermissionSet(bool includeReflectionPermission) + { + PermissionSet permissionsSet = new PermissionSet(null); + permissionsSet.AddPermission(new SecurityPermission(SecurityPermissionFlag.Execution)); + permissionsSet.AddPermission(new SocketPermission(PermissionState.Unrestricted)); + permissionsSet.AddPermission(new SecurityPermission(SecurityPermissionFlag.UnmanagedCode)); + permissionsSet.AddPermission(new DnsPermission(PermissionState.Unrestricted)); + permissionsSet.AddPermission(new FileIOPermission(PermissionState.Unrestricted)); + permissionsSet.AddPermission(new EnvironmentPermission(PermissionState.Unrestricted)); + + if (includeReflectionPermission) permissionsSet.AddPermission(new ReflectionPermission(PermissionState.Unrestricted)); + + return permissionsSet; + } + } +} diff --git a/MySQL.Data/src/Framework/netstandard2_0/dataadapter.cs b/MySQL.Data/src/Framework/netstandard2_0/dataadapter.cs index f2f2f9073..e704af69f 100644 --- a/MySQL.Data/src/Framework/netstandard2_0/dataadapter.cs +++ b/MySQL.Data/src/Framework/netstandard2_0/dataadapter.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2004, 2023, Oracle and/or its affiliates. +// Copyright © 2004, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/ISSchemaProvider.cs b/MySQL.Data/src/ISSchemaProvider.cs index 4a4bb5d77..decfa7016 100644 --- a/MySQL.Data/src/ISSchemaProvider.cs +++ b/MySQL.Data/src/ISSchemaProvider.cs @@ -1,397 +1,397 @@ -// Copyright (c) 2004, 2023, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySql.Data.Common; -using MySql.Data.Types; -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Text; -using System.Threading; -using System.Threading.Tasks; - -namespace MySql.Data.MySqlClient -{ - internal class ISSchemaProvider : SchemaProvider - { - public ISSchemaProvider(MySqlConnection connection) - : base(connection) - { - } - - protected override MySqlSchemaCollection GetCollections() - { - MySqlSchemaCollection dt = base.GetCollections(); - - object[][] collections = { - new object[] {"Views", 2, 3}, - new object[] {"ViewColumns", 3, 4}, - new object[] {"Procedure Parameters", 5, 1}, - new object[] {"Procedures", 4, 3}, - new object[] {"Triggers", 2, 4} - }; - - FillTable(dt, collections); - return dt; - } - - protected override MySqlSchemaCollection GetRestrictions() - { - MySqlSchemaCollection dt = base.GetRestrictions(); - - object[][] restrictions = new object[][] - { - new object[] {"Procedure Parameters", "Database", "", 0}, - new object[] {"Procedure Parameters", "Schema", "", 1}, - new object[] {"Procedure Parameters", "Name", "", 2}, - new object[] {"Procedure Parameters", "Type", "", 3}, - new object[] {"Procedure Parameters", "Parameter", "", 4}, - new object[] {"Procedures", "Database", "", 0}, - new object[] {"Procedures", "Schema", "", 1}, - new object[] {"Procedures", "Name", "", 2}, - new object[] {"Procedures", "Type", "", 3}, - new object[] {"Views", "Database", "", 0}, - new object[] {"Views", "Schema", "", 1}, - new object[] {"Views", "Table", "", 2}, - new object[] {"ViewColumns", "Database", "", 0}, - new object[] {"ViewColumns", "Schema", "", 1}, - new object[] {"ViewColumns", "Table", "", 2}, - new object[] {"ViewColumns", "Column", "", 3}, - new object[] {"Triggers", "Database", "", 0}, - new object[] {"Triggers", "Schema", "", 1}, - new object[] {"Triggers", "Name", "", 2}, - new object[] {"Triggers", "EventObjectTable", "", 3}, - }; - FillTable(dt, restrictions); - return dt; - } - - public override async Task GetDatabasesAsync(string[] restrictions, bool execAsync, CancellationToken cancellationToken = default) - { - string[] keys = new string[1]; - keys[0] = "SCHEMA_NAME"; - MySqlSchemaCollection dt = await QueryAsync("SCHEMATA", "", keys, restrictions, execAsync, cancellationToken).ConfigureAwait(false); - dt.Columns[1].Name = "database_name"; - dt.Name = "Databases"; - return dt; - } - - public override async Task GetTablesAsync(string[] restrictions, bool execAsync, CancellationToken cancellationToken = default) - { - string[] keys = new string[4]; - keys[0] = "TABLE_CATALOG"; - keys[1] = "TABLE_SCHEMA"; - keys[2] = "TABLE_NAME"; - keys[3] = "TABLE_TYPE"; - MySqlSchemaCollection dt = await QueryAsync("TABLES", "TABLE_TYPE != 'VIEW'", keys, restrictions, execAsync, cancellationToken).ConfigureAwait(false); - dt.Name = "Tables"; - return dt; - } - - public override async Task GetColumnsAsync(string[] restrictions, bool execAsync, CancellationToken cancellationToken = default) - { - string[] keys = new string[4]; - keys[0] = "TABLE_CATALOG"; - keys[1] = "TABLE_SCHEMA"; - keys[2] = "TABLE_NAME"; - keys[3] = "COLUMN_NAME"; - MySqlSchemaCollection dt = await QueryAsync("COLUMNS", null, keys, restrictions, execAsync, cancellationToken).ConfigureAwait(false); - dt.RemoveColumn("CHARACTER_OCTET_LENGTH"); - dt.Name = "Columns"; - QuoteDefaultValues(dt); - return dt; - } - - private async Task GetViewsAsync(string[] restrictions, bool execAsync, CancellationToken cancellationToken = default) - { - string[] keys = new string[3]; - keys[0] = "TABLE_CATALOG"; - keys[1] = "TABLE_SCHEMA"; - keys[2] = "TABLE_NAME"; - MySqlSchemaCollection dt = await QueryAsync("VIEWS", null, keys, restrictions, execAsync, cancellationToken).ConfigureAwait(false); - dt.Name = "Views"; - return dt; - } - - private async Task GetViewColumnsAsync(string[] restrictions, bool execAsync, CancellationToken cancellationToken = default) - { - StringBuilder where = new StringBuilder(); - StringBuilder sql = new StringBuilder( - "SELECT C.* FROM information_schema.columns C"); - sql.Append(" JOIN information_schema.views V "); - sql.Append("ON C.table_schema=V.table_schema AND C.table_name=V.table_name "); - if (restrictions != null && restrictions.Length >= 2 && - restrictions[1] != null) - where.AppendFormat(CultureInfo.InvariantCulture, "C.table_schema='{0}' ", restrictions[1]); - if (restrictions != null && restrictions.Length >= 3 && - restrictions[2] != null) - { - if (where.Length > 0) - where.Append("AND "); - where.AppendFormat(CultureInfo.InvariantCulture, "C.table_name='{0}' ", restrictions[2]); - } - if (restrictions != null && restrictions.Length == 4 && - restrictions[3] != null) - { - if (where.Length > 0) - where.Append("AND "); - where.AppendFormat(CultureInfo.InvariantCulture, "C.column_name='{0}' ", restrictions[3]); - } - if (where.Length > 0) - sql.AppendFormat(CultureInfo.InvariantCulture, " WHERE {0}", where); - MySqlSchemaCollection dt = await GetTableAsync(sql.ToString(), execAsync, cancellationToken).ConfigureAwait(false); - dt.Name = "ViewColumns"; - dt.Columns[0].Name = "VIEW_CATALOG"; - dt.Columns[1].Name = "VIEW_SCHEMA"; - dt.Columns[2].Name = "VIEW_NAME"; - QuoteDefaultValues(dt); - return dt; - } - - private async Task GetTriggersAsync(string[] restrictions, bool execAsync, CancellationToken cancellationToken = default) - { - string[] keys = new string[4]; - keys[0] = "TRIGGER_CATALOG"; - keys[1] = "TRIGGER_SCHEMA"; - keys[2] = "EVENT_OBJECT_TABLE"; - keys[3] = "TRIGGER_NAME"; - MySqlSchemaCollection dt = await QueryAsync("TRIGGERS", null, keys, restrictions, execAsync, cancellationToken).ConfigureAwait(false); - dt.Name = "Triggers"; - return dt; - } - - /// - /// Return schema information about procedures and functions - /// Restrictions supported are: - /// schema, name, type - /// - /// - /// Boolean that indicates if the function will be executed asynchronously. - /// The cancellation token. - public async Task GetProceduresAsync(string[] restrictions, bool execAsync, CancellationToken cancellationToken = default) - { - string[] keys = new string[4]; - keys[0] = "ROUTINE_CATALOG"; - keys[1] = "ROUTINE_SCHEMA"; - keys[2] = "ROUTINE_NAME"; - keys[3] = "ROUTINE_TYPE"; - - MySqlSchemaCollection dt = await QueryAsync("ROUTINES", null, keys, restrictions, execAsync, cancellationToken).ConfigureAwait(false); - dt.Name = "Procedures"; - return dt; - } - - private async Task GetParametersForRoutineFromexecAsync(string[] restrictions, bool execAsync, CancellationToken cancellationToken = default) - { - string[] keys = new string[5]; - keys[0] = "SPECIFIC_CATALOG"; - keys[1] = "SPECIFIC_SCHEMA"; - keys[2] = "SPECIFIC_NAME"; - keys[3] = "ROUTINE_TYPE"; - keys[4] = "PARAMETER_NAME"; - - StringBuilder sql = new StringBuilder(@"SELECT * FROM INFORMATION_SCHEMA.PARAMETERS"); - // now get our where clause and append it if there is one - string where = GetWhereClause(null, keys, restrictions); - if (!String.IsNullOrEmpty(where)) - sql.AppendFormat(CultureInfo.InvariantCulture, " WHERE {0}", where); - - MySqlSchemaCollection coll = await QueryCollectionAsync("parameters", sql.ToString(), execAsync, cancellationToken).ConfigureAwait(false); - - if ((coll.Rows.Count != 0) && ((string)coll.Rows[0]["routine_type"] == "FUNCTION")) - { - // update missing data for the first row (function return value). - // (using sames valus than GetParametersFromShowCreate). - coll.Rows[0]["parameter_mode"] = "IN"; - coll.Rows[0]["parameter_name"] = "return_value"; // "FUNCTION"; - } - return coll; - } - - /// - /// Return schema information about parameters for procedures and functions - /// Restrictions supported are: - /// schema, name, type, parameter name - /// - public virtual async Task GetProcedureParametersAsync(string[] restrictions, - MySqlSchemaCollection routines, bool execAsync, CancellationToken cancellationToken = default) - { - MySqlSchemaCollection parms = null; - - if (routines == null || routines.Rows.Count == 0) - { - parms = await GetParametersForRoutineFromexecAsync(restrictions, execAsync, cancellationToken).ConfigureAwait(false); - } - else foreach (MySqlSchemaRow routine in routines.Rows) - { - if (restrictions != null && restrictions.Length >= 3) - restrictions[2] = routine["ROUTINE_NAME"].ToString(); - - parms = await GetParametersForRoutineFromexecAsync(restrictions, execAsync, cancellationToken).ConfigureAwait(false); - } - parms.Name = "Procedure Parameters"; - return parms; - } - - protected override async Task GetSchemaInternalAsync(string collection, string[] restrictions, bool execAsync, CancellationToken cancellationToken = default) - { - MySqlSchemaCollection dt = await base.GetSchemaInternalAsync(collection, restrictions, execAsync, cancellationToken).ConfigureAwait(false); - if (dt != null) - return dt; - - switch (collection) - { - case "VIEWS": - return await GetViewsAsync(restrictions, execAsync, cancellationToken).ConfigureAwait(false); - case "PROCEDURES": - return await GetProceduresAsync(restrictions, execAsync, cancellationToken).ConfigureAwait(false); - case "PROCEDURE PARAMETERS": - return await GetProcedureParametersAsync(restrictions, null, execAsync, cancellationToken).ConfigureAwait(false); - case "TRIGGERS": - return await GetTriggersAsync(restrictions, execAsync, cancellationToken).ConfigureAwait(false); - case "VIEWCOLUMNS": - return await GetViewColumnsAsync(restrictions, execAsync, cancellationToken).ConfigureAwait(false); - } - return null; - } - - private static string GetWhereClause(string initial_where, string[] keys, string[] values) - { - StringBuilder where = new StringBuilder(initial_where); - if (values != null) - { - for (int i = 0; i < keys.Length; i++) - { - if (i >= values.Length) break; - if (values[i] == null || values[i] == String.Empty) continue; - if (where.Length > 0) - where.Append(" AND "); - where.AppendFormat(CultureInfo.InvariantCulture, - "{0} LIKE '{1}'", keys[i], values[i]); - } - } - return where.ToString(); - } - - private async Task QueryAsync(string tableName, string initialWhere, string[] keys, string[] values, bool execAsync, CancellationToken cancellationToken = default) - { - StringBuilder query = new StringBuilder("SELECT * FROM INFORMATION_SCHEMA."); - query.Append(tableName); - - string where = GetWhereClause(initialWhere, keys, values); - - if (where.Length > 0) - query.AppendFormat(CultureInfo.InvariantCulture, " WHERE {0}", where); - - if (tableName.Equals("COLUMNS", StringComparison.OrdinalIgnoreCase)) - query.Append(" ORDER BY ORDINAL_POSITION"); - - return await GetTableAsync(query.ToString(), execAsync, cancellationToken).ConfigureAwait(false); - } - - private async Task GetTableAsync(string sql, bool execAsync, CancellationToken cancellationToken = default) - { - MySqlSchemaCollection c = new MySqlSchemaCollection(); - using MySqlCommand cmd = new MySqlCommand(sql, connection); - MySqlDataReader reader = await cmd.ExecuteReaderAsync(default, execAsync, cancellationToken).ConfigureAwait(false); - - // add columns - for (int i = 0; i < reader.FieldCount; i++) - c.AddColumn(reader.GetName(i), reader.GetFieldType(i)); - - using (reader) - { - while (await reader.ReadAsync(execAsync, cancellationToken).ConfigureAwait(false)) - { - MySqlSchemaRow row = c.AddRow(); - for (int i = 0; i < reader.FieldCount; i++) - row[i] = reader.GetValue(i); - } - } - - return c; - } - - public override async Task GetForeignKeysAsync(string[] restrictions, bool execAsync, CancellationToken cancellationToken = default) - { - if (!connection.driver.Version.isAtLeast(5, 1, 16)) - return await base.GetForeignKeysAsync(restrictions, execAsync, cancellationToken).ConfigureAwait(false); - - string sql = @"SELECT rc.constraint_catalog, rc.constraint_schema, - rc.constraint_name, kcu.table_catalog, kcu.table_schema, rc.table_name, - rc.match_option, rc.update_rule, rc.delete_rule, - NULL as referenced_table_catalog, - kcu.referenced_table_schema, rc.referenced_table_name - FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS rc - LEFT JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE kcu ON - kcu.constraint_catalog <=> rc.constraint_catalog AND - kcu.constraint_schema <=> rc.constraint_schema AND - kcu.constraint_name <=> rc.constraint_name - WHERE 1=1 AND kcu.ORDINAL_POSITION=1"; - - StringBuilder where = new StringBuilder(); - if (restrictions.Length >= 2 && !String.IsNullOrEmpty(restrictions[1])) - where.AppendFormat(CultureInfo.InvariantCulture, - " AND rc.constraint_schema LIKE '{0}'", restrictions[1]); - if (restrictions.Length >= 3 && !String.IsNullOrEmpty(restrictions[2])) - where.AppendFormat(CultureInfo.InvariantCulture, - " AND rc.table_name LIKE '{0}'", restrictions[2]); - if (restrictions.Length >= 4 && !String.IsNullOrEmpty(restrictions[3])) - where.AppendFormat(CultureInfo.InvariantCulture, - " AND rc.constraint_name LIKE '{0}'", restrictions[2]); - - sql += where.ToString(); - - return await GetTableAsync(sql, execAsync, cancellationToken).ConfigureAwait(false); - } - - public override async Task GetForeignKeyColumnsAsync(string[] restrictions, bool execAsync, CancellationToken cancellationToken = default) - { - if (!connection.driver.Version.isAtLeast(5, 0, 6)) - return await base.GetForeignKeyColumnsAsync(restrictions, execAsync, cancellationToken).ConfigureAwait(false); - - string sql = @"SELECT kcu.* FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE kcu - WHERE kcu.referenced_table_name IS NOT NULL"; - - StringBuilder where = new StringBuilder(); - if (restrictions.Length >= 2 && !String.IsNullOrEmpty(restrictions[1])) - where.AppendFormat(CultureInfo.InvariantCulture, - " AND kcu.constraint_schema LIKE '{0}'", restrictions[1]); - if (restrictions.Length >= 3 && !String.IsNullOrEmpty(restrictions[2])) - where.AppendFormat(CultureInfo.InvariantCulture, - " AND kcu.table_name LIKE '{0}'", restrictions[2]); - if (restrictions.Length >= 4 && !String.IsNullOrEmpty(restrictions[3])) - where.AppendFormat(CultureInfo.InvariantCulture, - " AND kcu.constraint_name LIKE '{0}'", restrictions[3]); - - sql += where.ToString(); - - return await GetTableAsync(sql, execAsync, cancellationToken).ConfigureAwait(false); - } - } -} +// Copyright © 2004, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySql.Data.Common; +using MySql.Data.Types; +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace MySql.Data.MySqlClient +{ + internal class ISSchemaProvider : SchemaProvider + { + public ISSchemaProvider(MySqlConnection connection) + : base(connection) + { + } + + protected override MySqlSchemaCollection GetCollections() + { + MySqlSchemaCollection dt = base.GetCollections(); + + object[][] collections = { + new object[] {"Views", 2, 3}, + new object[] {"ViewColumns", 3, 4}, + new object[] {"Procedure Parameters", 5, 1}, + new object[] {"Procedures", 4, 3}, + new object[] {"Triggers", 2, 4} + }; + + FillTable(dt, collections); + return dt; + } + + protected override MySqlSchemaCollection GetRestrictions() + { + MySqlSchemaCollection dt = base.GetRestrictions(); + + object[][] restrictions = new object[][] + { + new object[] {"Procedure Parameters", "Database", "", 0}, + new object[] {"Procedure Parameters", "Schema", "", 1}, + new object[] {"Procedure Parameters", "Name", "", 2}, + new object[] {"Procedure Parameters", "Type", "", 3}, + new object[] {"Procedure Parameters", "Parameter", "", 4}, + new object[] {"Procedures", "Database", "", 0}, + new object[] {"Procedures", "Schema", "", 1}, + new object[] {"Procedures", "Name", "", 2}, + new object[] {"Procedures", "Type", "", 3}, + new object[] {"Views", "Database", "", 0}, + new object[] {"Views", "Schema", "", 1}, + new object[] {"Views", "Table", "", 2}, + new object[] {"ViewColumns", "Database", "", 0}, + new object[] {"ViewColumns", "Schema", "", 1}, + new object[] {"ViewColumns", "Table", "", 2}, + new object[] {"ViewColumns", "Column", "", 3}, + new object[] {"Triggers", "Database", "", 0}, + new object[] {"Triggers", "Schema", "", 1}, + new object[] {"Triggers", "Name", "", 2}, + new object[] {"Triggers", "EventObjectTable", "", 3}, + }; + FillTable(dt, restrictions); + return dt; + } + + public override async Task GetDatabasesAsync(string[] restrictions, bool execAsync, CancellationToken cancellationToken = default) + { + string[] keys = new string[1]; + keys[0] = "SCHEMA_NAME"; + MySqlSchemaCollection dt = await QueryAsync("SCHEMATA", "", keys, restrictions, execAsync, cancellationToken).ConfigureAwait(false); + dt.Columns[1].Name = "database_name"; + dt.Name = "Databases"; + return dt; + } + + public override async Task GetTablesAsync(string[] restrictions, bool execAsync, CancellationToken cancellationToken = default) + { + string[] keys = new string[4]; + keys[0] = "TABLE_CATALOG"; + keys[1] = "TABLE_SCHEMA"; + keys[2] = "TABLE_NAME"; + keys[3] = "TABLE_TYPE"; + MySqlSchemaCollection dt = await QueryAsync("TABLES", "TABLE_TYPE != 'VIEW'", keys, restrictions, execAsync, cancellationToken).ConfigureAwait(false); + dt.Name = "Tables"; + return dt; + } + + public override async Task GetColumnsAsync(string[] restrictions, bool execAsync, CancellationToken cancellationToken = default) + { + string[] keys = new string[4]; + keys[0] = "TABLE_CATALOG"; + keys[1] = "TABLE_SCHEMA"; + keys[2] = "TABLE_NAME"; + keys[3] = "COLUMN_NAME"; + MySqlSchemaCollection dt = await QueryAsync("COLUMNS", null, keys, restrictions, execAsync, cancellationToken).ConfigureAwait(false); + dt.RemoveColumn("CHARACTER_OCTET_LENGTH"); + dt.Name = "Columns"; + QuoteDefaultValues(dt); + return dt; + } + + private async Task GetViewsAsync(string[] restrictions, bool execAsync, CancellationToken cancellationToken = default) + { + string[] keys = new string[3]; + keys[0] = "TABLE_CATALOG"; + keys[1] = "TABLE_SCHEMA"; + keys[2] = "TABLE_NAME"; + MySqlSchemaCollection dt = await QueryAsync("VIEWS", null, keys, restrictions, execAsync, cancellationToken).ConfigureAwait(false); + dt.Name = "Views"; + return dt; + } + + private async Task GetViewColumnsAsync(string[] restrictions, bool execAsync, CancellationToken cancellationToken = default) + { + StringBuilder where = new StringBuilder(); + StringBuilder sql = new StringBuilder( + "SELECT C.* FROM information_schema.columns C"); + sql.Append(" JOIN information_schema.views V "); + sql.Append("ON C.table_schema=V.table_schema AND C.table_name=V.table_name "); + if (restrictions != null && restrictions.Length >= 2 && + restrictions[1] != null) + where.AppendFormat(CultureInfo.InvariantCulture, "C.table_schema='{0}' ", restrictions[1]); + if (restrictions != null && restrictions.Length >= 3 && + restrictions[2] != null) + { + if (where.Length > 0) + where.Append("AND "); + where.AppendFormat(CultureInfo.InvariantCulture, "C.table_name='{0}' ", restrictions[2]); + } + if (restrictions != null && restrictions.Length == 4 && + restrictions[3] != null) + { + if (where.Length > 0) + where.Append("AND "); + where.AppendFormat(CultureInfo.InvariantCulture, "C.column_name='{0}' ", restrictions[3]); + } + if (where.Length > 0) + sql.AppendFormat(CultureInfo.InvariantCulture, " WHERE {0}", where); + MySqlSchemaCollection dt = await GetTableAsync(sql.ToString(), execAsync, cancellationToken).ConfigureAwait(false); + dt.Name = "ViewColumns"; + dt.Columns[0].Name = "VIEW_CATALOG"; + dt.Columns[1].Name = "VIEW_SCHEMA"; + dt.Columns[2].Name = "VIEW_NAME"; + QuoteDefaultValues(dt); + return dt; + } + + private async Task GetTriggersAsync(string[] restrictions, bool execAsync, CancellationToken cancellationToken = default) + { + string[] keys = new string[4]; + keys[0] = "TRIGGER_CATALOG"; + keys[1] = "TRIGGER_SCHEMA"; + keys[2] = "EVENT_OBJECT_TABLE"; + keys[3] = "TRIGGER_NAME"; + MySqlSchemaCollection dt = await QueryAsync("TRIGGERS", null, keys, restrictions, execAsync, cancellationToken).ConfigureAwait(false); + dt.Name = "Triggers"; + return dt; + } + + /// + /// Return schema information about procedures and functions + /// Restrictions supported are: + /// schema, name, type + /// + /// + /// Boolean that indicates if the function will be executed asynchronously. + /// The cancellation token. + public async Task GetProceduresAsync(string[] restrictions, bool execAsync, CancellationToken cancellationToken = default) + { + string[] keys = new string[4]; + keys[0] = "ROUTINE_CATALOG"; + keys[1] = "ROUTINE_SCHEMA"; + keys[2] = "ROUTINE_NAME"; + keys[3] = "ROUTINE_TYPE"; + + MySqlSchemaCollection dt = await QueryAsync("ROUTINES", null, keys, restrictions, execAsync, cancellationToken).ConfigureAwait(false); + dt.Name = "Procedures"; + return dt; + } + + private async Task GetParametersForRoutineFromexecAsync(string[] restrictions, bool execAsync, CancellationToken cancellationToken = default) + { + string[] keys = new string[5]; + keys[0] = "SPECIFIC_CATALOG"; + keys[1] = "SPECIFIC_SCHEMA"; + keys[2] = "SPECIFIC_NAME"; + keys[3] = "ROUTINE_TYPE"; + keys[4] = "PARAMETER_NAME"; + + StringBuilder sql = new StringBuilder(@"SELECT * FROM INFORMATION_SCHEMA.PARAMETERS"); + // now get our where clause and append it if there is one + string where = GetWhereClause(null, keys, restrictions); + if (!String.IsNullOrEmpty(where)) + sql.AppendFormat(CultureInfo.InvariantCulture, " WHERE {0}", where); + + MySqlSchemaCollection coll = await QueryCollectionAsync("parameters", sql.ToString(), execAsync, cancellationToken).ConfigureAwait(false); + + if ((coll.Rows.Count != 0) && ((string)coll.Rows[0]["routine_type"] == "FUNCTION")) + { + // update missing data for the first row (function return value). + // (using sames valus than GetParametersFromShowCreate). + coll.Rows[0]["parameter_mode"] = "IN"; + coll.Rows[0]["parameter_name"] = "return_value"; // "FUNCTION"; + } + return coll; + } + + /// + /// Return schema information about parameters for procedures and functions + /// Restrictions supported are: + /// schema, name, type, parameter name + /// + public virtual async Task GetProcedureParametersAsync(string[] restrictions, + MySqlSchemaCollection routines, bool execAsync, CancellationToken cancellationToken = default) + { + MySqlSchemaCollection parms = null; + + if (routines == null || routines.Rows.Count == 0) + { + parms = await GetParametersForRoutineFromexecAsync(restrictions, execAsync, cancellationToken).ConfigureAwait(false); + } + else foreach (MySqlSchemaRow routine in routines.Rows) + { + if (restrictions != null && restrictions.Length >= 3) + restrictions[2] = routine["ROUTINE_NAME"].ToString(); + + parms = await GetParametersForRoutineFromexecAsync(restrictions, execAsync, cancellationToken).ConfigureAwait(false); + } + parms.Name = "Procedure Parameters"; + return parms; + } + + protected override async Task GetSchemaInternalAsync(string collection, string[] restrictions, bool execAsync, CancellationToken cancellationToken = default) + { + MySqlSchemaCollection dt = await base.GetSchemaInternalAsync(collection, restrictions, execAsync, cancellationToken).ConfigureAwait(false); + if (dt != null) + return dt; + + switch (collection) + { + case "VIEWS": + return await GetViewsAsync(restrictions, execAsync, cancellationToken).ConfigureAwait(false); + case "PROCEDURES": + return await GetProceduresAsync(restrictions, execAsync, cancellationToken).ConfigureAwait(false); + case "PROCEDURE PARAMETERS": + return await GetProcedureParametersAsync(restrictions, null, execAsync, cancellationToken).ConfigureAwait(false); + case "TRIGGERS": + return await GetTriggersAsync(restrictions, execAsync, cancellationToken).ConfigureAwait(false); + case "VIEWCOLUMNS": + return await GetViewColumnsAsync(restrictions, execAsync, cancellationToken).ConfigureAwait(false); + } + return null; + } + + private static string GetWhereClause(string initial_where, string[] keys, string[] values) + { + StringBuilder where = new StringBuilder(initial_where); + if (values != null) + { + for (int i = 0; i < keys.Length; i++) + { + if (i >= values.Length) break; + if (values[i] == null || values[i] == String.Empty) continue; + if (where.Length > 0) + where.Append(" AND "); + where.AppendFormat(CultureInfo.InvariantCulture, + "{0} LIKE '{1}'", keys[i], values[i]); + } + } + return where.ToString(); + } + + private async Task QueryAsync(string tableName, string initialWhere, string[] keys, string[] values, bool execAsync, CancellationToken cancellationToken = default) + { + StringBuilder query = new StringBuilder("SELECT * FROM INFORMATION_SCHEMA."); + query.Append(tableName); + + string where = GetWhereClause(initialWhere, keys, values); + + if (where.Length > 0) + query.AppendFormat(CultureInfo.InvariantCulture, " WHERE {0}", where); + + if (tableName.Equals("COLUMNS", StringComparison.OrdinalIgnoreCase)) + query.Append(" ORDER BY ORDINAL_POSITION"); + + return await GetTableAsync(query.ToString(), execAsync, cancellationToken).ConfigureAwait(false); + } + + private async Task GetTableAsync(string sql, bool execAsync, CancellationToken cancellationToken = default) + { + MySqlSchemaCollection c = new MySqlSchemaCollection(); + using MySqlCommand cmd = new MySqlCommand(sql, connection); + MySqlDataReader reader = await cmd.ExecuteReaderAsync(default, execAsync, cancellationToken).ConfigureAwait(false); + + // add columns + for (int i = 0; i < reader.FieldCount; i++) + c.AddColumn(reader.GetName(i), reader.GetFieldType(i)); + + using (reader) + { + while (await reader.ReadAsync(execAsync, cancellationToken).ConfigureAwait(false)) + { + MySqlSchemaRow row = c.AddRow(); + for (int i = 0; i < reader.FieldCount; i++) + row[i] = reader.GetValue(i); + } + } + + return c; + } + + public override async Task GetForeignKeysAsync(string[] restrictions, bool execAsync, CancellationToken cancellationToken = default) + { + if (!connection.driver.Version.isAtLeast(5, 1, 16)) + return await base.GetForeignKeysAsync(restrictions, execAsync, cancellationToken).ConfigureAwait(false); + + string sql = @"SELECT rc.constraint_catalog, rc.constraint_schema, + rc.constraint_name, kcu.table_catalog, kcu.table_schema, rc.table_name, + rc.match_option, rc.update_rule, rc.delete_rule, + NULL as referenced_table_catalog, + kcu.referenced_table_schema, rc.referenced_table_name + FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS rc + LEFT JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE kcu ON + kcu.constraint_catalog <=> rc.constraint_catalog AND + kcu.constraint_schema <=> rc.constraint_schema AND + kcu.constraint_name <=> rc.constraint_name + WHERE 1=1 AND kcu.ORDINAL_POSITION=1"; + + StringBuilder where = new StringBuilder(); + if (restrictions.Length >= 2 && !String.IsNullOrEmpty(restrictions[1])) + where.AppendFormat(CultureInfo.InvariantCulture, + " AND rc.constraint_schema LIKE '{0}'", restrictions[1]); + if (restrictions.Length >= 3 && !String.IsNullOrEmpty(restrictions[2])) + where.AppendFormat(CultureInfo.InvariantCulture, + " AND rc.table_name LIKE '{0}'", restrictions[2]); + if (restrictions.Length >= 4 && !String.IsNullOrEmpty(restrictions[3])) + where.AppendFormat(CultureInfo.InvariantCulture, + " AND rc.constraint_name LIKE '{0}'", restrictions[2]); + + sql += where.ToString(); + + return await GetTableAsync(sql, execAsync, cancellationToken).ConfigureAwait(false); + } + + public override async Task GetForeignKeyColumnsAsync(string[] restrictions, bool execAsync, CancellationToken cancellationToken = default) + { + if (!connection.driver.Version.isAtLeast(5, 0, 6)) + return await base.GetForeignKeyColumnsAsync(restrictions, execAsync, cancellationToken).ConfigureAwait(false); + + string sql = @"SELECT kcu.* FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE kcu + WHERE kcu.referenced_table_name IS NOT NULL"; + + StringBuilder where = new StringBuilder(); + if (restrictions.Length >= 2 && !String.IsNullOrEmpty(restrictions[1])) + where.AppendFormat(CultureInfo.InvariantCulture, + " AND kcu.constraint_schema LIKE '{0}'", restrictions[1]); + if (restrictions.Length >= 3 && !String.IsNullOrEmpty(restrictions[2])) + where.AppendFormat(CultureInfo.InvariantCulture, + " AND kcu.table_name LIKE '{0}'", restrictions[2]); + if (restrictions.Length >= 4 && !String.IsNullOrEmpty(restrictions[3])) + where.AppendFormat(CultureInfo.InvariantCulture, + " AND kcu.constraint_name LIKE '{0}'", restrictions[3]); + + sql += where.ToString(); + + return await GetTableAsync(sql, execAsync, cancellationToken).ConfigureAwait(false); + } + } +} diff --git a/MySQL.Data/src/Interceptors/CommandInterceptor.cs b/MySQL.Data/src/Interceptors/CommandInterceptor.cs index f705c1d23..655801fef 100644 --- a/MySQL.Data/src/Interceptors/CommandInterceptor.cs +++ b/MySQL.Data/src/Interceptors/CommandInterceptor.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2004, 2019, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2004, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/Interceptors/ExceptionInterceptor.cs b/MySQL.Data/src/Interceptors/ExceptionInterceptor.cs index 2ffca486e..332283c35 100644 --- a/MySQL.Data/src/Interceptors/ExceptionInterceptor.cs +++ b/MySQL.Data/src/Interceptors/ExceptionInterceptor.cs @@ -1,16 +1,16 @@ -// Copyright � 2004, 2018, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2004, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/Interceptors/Interceptor.cs b/MySQL.Data/src/Interceptors/Interceptor.cs index c5ee4b76d..1c4f99843 100644 --- a/MySQL.Data/src/Interceptors/Interceptor.cs +++ b/MySQL.Data/src/Interceptors/Interceptor.cs @@ -1,64 +1,64 @@ -// Copyright (c) 2004, 2019, Oracle and/or its affiliates. All rights reserved. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using System; - -namespace MySql.Data.MySqlClient -{ - /// - /// Interceptor is the base class for the "manager" classes such as ExceptionInterceptor, - /// CommandInterceptor, etc - /// - internal abstract class Interceptor - { - protected MySqlConnection Connection; - - protected void LoadInterceptors(string interceptorList) - { - if (String.IsNullOrEmpty(interceptorList)) return; - - string[] interceptors = interceptorList.Split('|'); - foreach (string interceptorType in interceptors) - { - if (String.IsNullOrEmpty(interceptorType)) continue; - - string type = ResolveType(interceptorType); - Type t = Type.GetType(type); - object interceptorObject = Activator.CreateInstance(t); - AddInterceptor(interceptorObject); - } - } - - protected abstract void AddInterceptor(object o); - - protected virtual string ResolveType(string nameOrType) - { - return nameOrType; - } - } -} +// Copyright © 2004, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using System; + +namespace MySql.Data.MySqlClient +{ + /// + /// Interceptor is the base class for the "manager" classes such as ExceptionInterceptor, + /// CommandInterceptor, etc + /// + internal abstract class Interceptor + { + protected MySqlConnection Connection; + + protected void LoadInterceptors(string interceptorList) + { + if (String.IsNullOrEmpty(interceptorList)) return; + + string[] interceptors = interceptorList.Split('|'); + foreach (string interceptorType in interceptors) + { + if (String.IsNullOrEmpty(interceptorType)) continue; + + string type = ResolveType(interceptorType); + Type t = Type.GetType(type); + object interceptorObject = Activator.CreateInstance(t); + AddInterceptor(interceptorObject); + } + } + + protected abstract void AddInterceptor(object o); + + protected virtual string ResolveType(string nameOrType) + { + return nameOrType; + } + } +} diff --git a/MySQL.Data/src/MySQLActivitySource.cs b/MySQL.Data/src/MySQLActivitySource.cs index 069a3bc3d..d156fc6aa 100644 --- a/MySQL.Data/src/MySQLActivitySource.cs +++ b/MySQL.Data/src/MySQLActivitySource.cs @@ -1,4 +1,32 @@ -using System; +// Copyright © 2023, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using System; using System.Data; using System.Diagnostics; using System.Reflection; diff --git a/MySQL.Data/src/MySqlAttribute.cs b/MySQL.Data/src/MySqlAttribute.cs index 298724f9c..f37930b3e 100644 --- a/MySQL.Data/src/MySqlAttribute.cs +++ b/MySQL.Data/src/MySqlAttribute.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2022, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/MySqlAttributeCollection.cs b/MySQL.Data/src/MySqlAttributeCollection.cs index fb6c518c4..a98bed023 100644 --- a/MySQL.Data/src/MySqlAttributeCollection.cs +++ b/MySQL.Data/src/MySqlAttributeCollection.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2022, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/MySqlBaseConnectionStringBuilder.cs b/MySQL.Data/src/MySqlBaseConnectionStringBuilder.cs index b23f80b8c..e3cf80f6d 100644 --- a/MySQL.Data/src/MySqlBaseConnectionStringBuilder.cs +++ b/MySQL.Data/src/MySqlBaseConnectionStringBuilder.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2018, 2023, Oracle and/or its affiliates. +// Copyright © 2018, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -524,4 +524,4 @@ internal void SetValue(string keyword, object value, [CallerMemberName] string c public abstract override bool TryGetValue(string keyword, out object value); } -} \ No newline at end of file +} diff --git a/MySQL.Data/src/MySqlClientFactory.cs b/MySQL.Data/src/MySqlClientFactory.cs index d361c44ce..236f77b24 100644 --- a/MySQL.Data/src/MySqlClientFactory.cs +++ b/MySQL.Data/src/MySqlClientFactory.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2004, 2019, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2004, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/MySqlCommand.cs b/MySQL.Data/src/MySqlCommand.cs index c3b5a241b..bf0ea1633 100644 --- a/MySQL.Data/src/MySqlCommand.cs +++ b/MySQL.Data/src/MySqlCommand.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2004, 2023, Oracle and/or its affiliates. +// Copyright (c) 2004, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/MySqlConnection.cs b/MySQL.Data/src/MySqlConnection.cs index f2a7f5851..23376a4c9 100644 --- a/MySQL.Data/src/MySqlConnection.cs +++ b/MySQL.Data/src/MySqlConnection.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2004, 2023, Oracle and/or its affiliates. +// Copyright (c) 2004, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/MySqlConnectionStringBuilder.cs b/MySQL.Data/src/MySqlConnectionStringBuilder.cs index 8f6245f6d..e12a4ab22 100644 --- a/MySQL.Data/src/MySqlConnectionStringBuilder.cs +++ b/MySQL.Data/src/MySqlConnectionStringBuilder.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2013, 2023, Oracle and/or its affiliates. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/MySqlDataReader.cs b/MySQL.Data/src/MySqlDataReader.cs index 87d122fc6..b878c56d8 100644 --- a/MySQL.Data/src/MySqlDataReader.cs +++ b/MySQL.Data/src/MySqlDataReader.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2004, 2023, Oracle and/or its affiliates. +// Copyright © 2004, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/MySqlError.cs b/MySQL.Data/src/MySqlError.cs index b98cfc1bd..219b14854 100644 --- a/MySQL.Data/src/MySqlError.cs +++ b/MySQL.Data/src/MySqlError.cs @@ -1,2010 +1,2010 @@ -// Copyright (c) 2004, 2021, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -namespace MySql.Data.MySqlClient -{ - /// - /// Collection of error codes that can be returned by the server - /// - public class MySqlError - { - /// - /// - /// - /// - public MySqlError(string level, int code, string message) - { - this.Level = level; - this.Code = code; - this.Message = message; - } - - /// - /// Error level - /// - public string Level { get; } - - /// - /// Error code - /// - public int Code { get; } - - /// - /// Error message - /// - public string Message { get; } - }; - - /// - /// Provides a reference to error codes returned by MySQL. - /// - public enum MySqlErrorCode - { - None = 0, - /// - ///ER_HASHCHK - HashCheck = 1000, - /// - ///ER_NISAMCHK - ISAMCheck = 1001, - /// - ///ER_NO - No = 1002, - /// - ///ER_YES - Yes = 1003, - ///The file couldn't be created. - ///ER_CANT_CREATE_FILE - CannotCreateFile = 1004, - ///The table couldn't be created. - ///ER_CANT_CREATE_TABLE - CannotCreateTable = 1005, - ///The database couldn't be created. - ///ER_CANT_CREATE_DB - CannotCreateDatabase = 1006, - ///The database couldn't be created, it already exists. - ///ER_DB_CREATE_EXISTS - DatabaseCreateExists = 1007, - ///The database couldn't be dropped, it doesn't exist. - ///ER_DB_DROP_EXISTS - DatabaseDropExists = 1008, - ///The database couldn't be dropped, the file can't be deleted. - ///ER_DB_DROP_DELETE - DatabaseDropDelete = 1009, - ///The database couldn't be dropped, the directory can't be deleted. - ///ER_DB_DROP_RMDIR - DatabaseDropRemoveDir = 1010, - ///The file couldn't be deleted. - ///ER_CANT_DELETE_FILE - CannotDeleteFile = 1011, - ///The record couldn't be read from the system table. - ///ER_CANT_FIND_SYSTEM_REC - CannotFindSystemRecord = 1012, - ///The status couldn't be retrieved. - ///ER_CANT_GET_STAT - CannotGetStatus = 1013, - ///The working directory couldn't be retrieved. - ///ER_CANT_GET_WD - CannotGetWorkingDirectory = 1014, - ///The file couldn't be locked. - ///ER_CANT_LOCK - CannotLock = 1015, - ///The file couldn't be opened. - ///ER_CANT_OPEN_FILE - CannotOpenFile = 1016, - ///The file couldn't be found. - ///ER_FILE_NOT_FOUND - FileNotFound = 1017, - ///The directory couldn't be read. - ///ER_CANT_READ_DIR - CannotReadDirectory = 1018, - ///The working directory couldn't be entered. - ///ER_CANT_SET_WD - CannotSetWorkingDirectory = 1019, - ///The record changed since it was last read. - ///ER_CHECKREAD - CheckRead = 1020, - ///The disk is full. - ///ER_DISK_FULL - DiskFull = 1021, - /// - /// There is already a key with the given values. - /// - DuplicateKey = 1022, - ///An error occurred when closing the file. - ///ER_ERROR_ON_CLOSE - ErrorOnClose = 1023, - ///An error occurred when reading from the file. - ///ER_ERROR_ON_READ - ErrorOnRead = 1024, - ///An error occurred when renaming then file. - ///ER_ERROR_ON_RENAME - ErrorOnRename = 1025, - ///An error occurred when writing to the file. - ///ER_ERROR_ON_WRITE - ErrorOnWrite = 1026, - ///The file is in use. - ///ER_FILE_USED - FileUsed = 1027, - ///Sorting has been aborted. - ///ER_FILSORT_ABORT - FileSortAborted = 1028, - ///The view doesn't exist. - ///ER_FORM_NOT_FOUND - FormNotFound = 1029, - ///Got the specified error from the table storage engine. - ///ER_GET_ERRNO - GetErrorNumber = 1030, - ///The table storage engine doesn't support the specified option. - ///ER_ILLEGAL_HA - IllegalHA = 1031, - /// - /// The specified key was not found. - /// - KeyNotFound = 1032, - ///The file contains incorrect information. - ///ER_NOT_FORM_FILE - NotFormFile = 1033, - ///The key file is incorrect for the table, it should be repaired. - ///ER_NOT_KEYFILE - NotKeyFile = 1034, - ///The key file is old for the table, it should be repaired. - ///ER_OLD_KEYFILE - OldKeyFile = 1035, - ///The table is read-only - ///ER_OPEN_AS_READONLY - OpenAsReadOnly = 1036, - ///The server is out of memory, it should be restarted. - ///ER_OUTOFMEMORY - OutOfMemory = 1037, - ///The server is out of sort-memory, the sort buffer size should be increased. - ///ER_OUT_OF_SORTMEMORY - OutOfSortMemory = 1038, - ///An unexpected EOF was found when reading from the file. - ///ER_UNEXPECTED_EOF - UnexepectedEOF = 1039, - ///Too many connections are open. - ///ER_CON_COUNT_ERROR - ConnectionCountError = 1040, - ///The server is out of resources, check if MySql or some other process is using all available memory. - ///ER_OUT_OF_RESOURCES - OutOfResources = 1041, - /// - /// Given when the connection is unable to successfully connect to host. - /// - UnableToConnectToHost = 1042, - ///The handshake was invalid. - ///ER_HANDSHAKE_ERROR - HandshakeError = 1043, - ///Access was denied for the specified user using the specified database. - ///ER_DBACCESS_DENIED_ERROR - DatabaseAccessDenied = 1044, - /// - /// Normally returned when an incorrect password is given - /// - AccessDenied = 1045, - ///No database has been selected. - ///ER_NO_DB_ERROR - NoDatabaseSelected = 1046, - ///The command is unknown. - ///ER_UNKNOWN_COM_ERROR - UnknownCommand = 1047, - ///The specified column cannot be NULL. - ///ER_BAD_NULL_ERROR - ColumnCannotBeNull = 1048, - /// The specified database is not known. - UnknownDatabase = 1049, - ///The specified table already exists. - ///ER_TABLE_EXISTS_ERROR - TableExists = 1050, - ///The specified table is unknown. - ///ER_BAD_TABLE_ERROR - BadTable = 1051, - ///The specified column is ambiguous. - ///ER_NON_UNIQ_ERROR - NonUnique = 1052, - ///The server is currently being shutdown. - ///ER_SERVER_SHUTDOWN - ServerShutdown = 1053, - ///The specified columns is unknown. - ///ER_BAD_FIELD_ERROR - BadFieldError = 1054, - ///The specified column isn't in GROUP BY. - ///ER_WRONG_FIELD_WITH_GROUP - WrongFieldWithGroup = 1055, - ///The specified columns cannot be grouped on. - ///ER_WRONG_GROUP_FIELD - WrongGroupField = 1056, - ///There are sum functions and columns in the same statement. - ///ER_WRONG_SUM_SELECT - WrongSumSelected = 1057, - ///The column count doesn't match the value count. - ///ER_WRONG_VALUE_COUNT - WrongValueCount = 1058, - ///The identifier name is too long. - ///ER_TOO_LONG_IDENT - TooLongIdentifier = 1059, - ///The column name is duplicated. - ///ER_DUP_FIELDNAME - DuplicateFieldName = 1060, - /// - /// Duplicate Key Name - /// - DuplicateKeyName = 1061, - /// - /// Duplicate Key Entry - /// - DuplicateKeyEntry = 1062, - ///The column specifier is incorrect. - ///ER_WRONG_FIELD_SPEC - WrongFieldSpecifier = 1063, - ///An error occurred when parsing the statement. - ///ER_PARSE_ERROR - ParseError = 1064, - ///The statement is empty. - ///ER_EMPTY_QUERY - EmptyQuery = 1065, - ///The table alias isn't unique. - ///ER_NONUNIQ_TABLE - NonUniqueTable = 1066, - ///The default value is invalid for the specified field. - ///ER_INVALID_DEFAULT - InvalidDefault = 1067, - ///The table has multiple primary keys defined. - ///ER_MULTIPLE_PRI_KEY - MultiplePrimaryKey = 1068, - ///Too many keys were defined for the table. - ///ER_TOO_MANY_KEYS - TooManyKeys = 1069, - ///Too many parts to the keys were defined for the table. - ///ER_TOO_MANY_KEY_PARTS - TooManyKeysParts = 1070, - ///The specified key is too long - ///ER_TOO_LONG_KEY - TooLongKey = 1071, - ///The specified key column doesn't exist in the table. - ///ER_KEY_COLUMN_DOES_NOT_EXITS - KeyColumnDoesNotExist = 1072, - ///The BLOB column was used as a key, this can't be done. - ///ER_BLOB_USED_AS_KEY - BlobUsedAsKey = 1073, - ///The column length is too big for the specified column type. - ///ER_TOO_BIG_FIELDLENGTH - TooBigFieldLength = 1074, - ///There can only be one auto-column, and it must be defined as a PK. - ///ER_WRONG_AUTO_KEY - WrongAutoKey = 1075, - ///The server is ready to accept connections. - ///ER_READY - Ready = 1076, - /// - ///ER_NORMAL_SHUTDOWN - NormalShutdown = 1077, - ///The server received the specified signal and is aborting. - ///ER_GOT_SIGNAL - GotSignal = 1078, - ///The server shutdown is complete. - ///ER_SHUTDOWN_COMPLETE - ShutdownComplete = 1079, - ///The server is forcing close of the specified thread. - ///ER_FORCING_CLOSE - ForcingClose = 1080, - ///An error occurred when creating the IP socket. - ///ER_IPSOCK_ERROR - IPSocketError = 1081, - ///The table has no index like the one used in CREATE INDEX. - ///ER_NO_SUCH_INDEX - NoSuchIndex = 1082, - ///The field separator argument is not what is expected, check the manual. - ///ER_WRONG_FIELD_TERMINATORS - WrongFieldTerminators = 1083, - ///The BLOB columns must terminated, fixed row lengths cannot be used. - ///ER_BLOBS_AND_NO_TERMINATED - BlobsAndNoTerminated = 1084, - ///The text file cannot be read. - ///ER_TEXTFILE_NOT_READABLE - TextFileNotReadable = 1085, - ///The specified file already exists. - ///ER_FILE_EXISTS_ERROR - FileExists = 1086, - ///Information returned by the LOAD statement. - ///ER_LOAD_INFO - LoadInfo = 1087, - ///Information returned by an UPDATE statement. - ///ER_ALTER_INFO - AlterInfo = 1088, - ///The prefix key is incorrect. - ///ER_WRONG_SUB_KEY - WrongSubKey = 1089, - ///All columns cannot be removed from a table, use DROP TABLE instead. - ///ER_CANT_REMOVE_ALL_FIELDS - CannotRemoveAllFields = 1090, - ///Cannot DROP, check that the column or key exists. - ///ER_CANT_DROP_FIELD_OR_KEY - CannotDropFieldOrKey = 1091, - ///Information returned by an INSERT statement. - ///ER_INSERT_INFO - InsertInfo = 1092, - ///The target table cannot be specified for update in FROM clause. - ///ER_UPDATE_TABLE_USED - UpdateTableUsed = 1093, - ///The specified thread ID is unknown. - ///ER_NO_SUCH_THREAD - NoSuchThread = 1094, - ///The thread cannot be killed, the current user is not the owner. - ///ER_KILL_DENIED_ERROR - KillDenied = 1095, - ///No tables used in the statement. - ///ER_NO_TABLES_USED - NoTablesUsed = 1096, - ///Too many string have been used for the specified column and SET. - ///ER_TOO_BIG_SET - TooBigSet = 1097, - ///A unique filename couldn't be generated. - ///ER_NO_UNIQUE_LOGFILE - NoUniqueLogFile = 1098, - ///The specified table was locked with a READ lock, and can't be updated. - ///ER_TABLE_NOT_LOCKED_FOR_WRITE - TableNotLockedForWrite = 1099, - ///The specified table was not locked with LOCK TABLES. - ///ER_TABLE_NOT_LOCKED - TableNotLocked = 1100, - ///BLOB and Text columns cannot have a default value. - ///ER_BLOB_CANT_HAVE_DEFAULT - BlobCannotHaveDefault = 1101, - ///The specified database name is incorrect. - ///ER_WRONG_DB_NAME - WrongDatabaseName = 1102, - ///The specified table name is incorrect. - ///ER_WRONG_TABLE_NAME - WrongTableName = 1103, - ///The SELECT command would examine more than MAX_JOIN_SIZE rows, check the WHERE clause and use SET SQL_BIG_SELECTS=1 or SET SQL_MAX_JOIN_SIZE=# if the SELECT is ok. - ///ER_TOO_BIG_SELECT - TooBigSelect = 1104, - ///An unknown error occurred. - ///ER_UNKNOWN_ERROR - UnknownError = 1105, - ///The specified procedure is unknown. - ///ER_UNKNOWN_PROCEDURE - UnknownProcedure = 1106, - ///The number of parameters provided for the specified procedure is incorrect. - ///ER_WRONG_PARAMCOUNT_TO_PROCEDURE - WrongParameterCountToProcedure = 1107, - ///The parameters provided for the specified procedure are incorrect. - ///ER_WRONG_PARAMETERS_TO_PROCEDURE - WrongParametersToProcedure = 1108, - ///The specified table is unknown. - ///ER_UNKNOWN_TABLE - UnknownTable = 1109, - ///The specified column has been specified twice. - ///ER_FIELD_SPECIFIED_TWICE - FieldSpecifiedTwice = 1110, - ///The group function has been incorrectly used. - ///ER_INVALID_GROUP_FUNC_USE - InvalidGroupFunctionUse = 1111, - ///The specified table uses an extension that doesn't exist in this MySQL version. - ///ER_UNSUPPORTED_EXTENSION - UnsupportedExtenstion = 1112, - ///The table must have at least one column. - ///ER_TABLE_MUST_HAVE_COLUMNS - TableMustHaveColumns = 1113, - ///The specified table is full. - ///ER_RECORD_FILE_FULL - RecordFileFull = 1114, - ///The specified character set is unknown. - ///ER_UNKNOWN_CHARACTER_SET - UnknownCharacterSet = 1115, - ///Too many tables, MySQL can only use the specified number of tables in a JOIN. - ///ER_TOO_MANY_TABLES - TooManyTables = 1116, - ///Too many columns - ///ER_TOO_MANY_FIELDS - TooManyFields = 1117, - ///The row size is too large, the maximum row size for the used tables (not counting BLOBS) is specified, change some columns or BLOBS. - ///ER_TOO_BIG_ROWSIZE - TooBigRowSize = 1118, - ///A thread stack overrun occurred. Stack statistics are specified. - ///ER_STACK_OVERRUN - StackOverrun = 1119, - ///A cross dependency was found in the OUTER JOIN, examine the ON conditions. - ///ER_WRONG_OUTER_JOIN - WrongOuterJoin = 1120, - ///The table handler doesn't support NULL in the given index, change specified column to be NOT NULL or use another handler. - ///ER_NULL_COLUMN_IN_INDEX - NullColumnInIndex = 1121, - ///The specified user defined function cannot be loaded. - ///ER_CANT_FIND_UDF - CannotFindUDF = 1122, - ///The specified user defined function cannot be initialised. - ///ER_CANT_INITIALIZE_UDF - CannotInitializeUDF = 1123, - ///No paths are allowed for the shared library. - ///ER_UDF_NO_PATHS - UDFNoPaths = 1124, - ///The specified user defined function already exists. - ///ER_UDF_EXISTS - UDFExists = 1125, - ///The specified shared library cannot be opened. - ///ER_CANT_OPEN_LIBRARY - CannotOpenLibrary = 1126, - ///The specified symbol cannot be found in the library. - ///ER_CANT_FIND_DL_ENTRY - CannotFindDLEntry = 1127, - ///The specified function is not defined. - ///ER_FUNCTION_NOT_DEFINED - FunctionNotDefined = 1128, - ///The specified host is blocked because of too many connection errors, unblock with 'mysqladmin flush-hosts'. - ///ER_HOST_IS_BLOCKED - HostIsBlocked = 1129, - /// - /// The given host is not allowed to connect - /// - HostNotPrivileged = 1130, - /// - /// The anonymous user is not allowed to connect - /// - AnonymousUser = 1131, - /// - /// The given password is not allowed - /// - PasswordNotAllowed = 1132, - /// - /// The given password does not match - /// - PasswordNoMatch = 1133, - ///Information returned by an UPDATE statement. - ///ER_UPDATE_INFO - UpdateInfo = 1134, - ///A new thread couldn't be created. - ///ER_CANT_CREATE_THREAD - CannotCreateThread = 1135, - ///The column count doesn't match the value count. - ///ER_WRONG_VALUE_COUNT_ON_ROW - WrongValueCountOnRow = 1136, - ///The specified table can't be re-opened. - ///ER_CANT_REOPEN_TABLE - CannotReopenTable = 1137, - ///The NULL value has been used incorrectly. - ///ER_INVALID_USE_OF_NULL - InvalidUseOfNull = 1138, - ///The regular expression contains an error. - ///ER_REGEXP_ERROR - RegExpError = 1139, - ///GROUP columns (MIN(), MAX(), COUNT(), ...) cannot be mixes with no GROUP columns if there is not GROUP BY clause. - ///ER_MIX_OF_GROUP_FUNC_AND_FIELDS - MixOfGroupFunctionAndFields = 1140, - /// - ///ER_NONEXISTING_GRANT - NonExistingGrant = 1141, - /// - ///ER_TABLEACCESS_DENIED_ERROR - TableAccessDenied = 1142, - /// - ///ER_COLUMNACCESS_DENIED_ERROR - ColumnAccessDenied = 1143, - /// - ///ER_ILLEGAL_GRANT_FOR_TABLE - IllegalGrantForTable = 1144, - /// - ///ER_GRANT_WRONG_HOST_OR_USER - GrantWrongHostOrUser = 1145, - /// - ///ER_NO_SUCH_TABLE - NoSuchTable = 1146, - /// - ///ER_NONEXISTING_TABLE_GRANT - NonExistingTableGrant = 1147, - /// - ///ER_NOT_ALLOWED_COMMAND - NotAllowedCommand = 1148, - /// - ///ER_SYNTAX_ERROR - SyntaxError = 1149, - /// - ///ER_DELAYED_CANT_CHANGE_LOCK - DelayedCannotChangeLock = 1150, - /// - ///ER_TOO_MANY_DELAYED_THREADS - TooManyDelayedThreads = 1151, - /// - ///ER_ABORTING_CONNECTION - AbortingConnection = 1152, - /// - /// An attempt was made to send or receive a packet larger than - /// max_allowed_packet_size - /// - PacketTooLarge = 1153, - /// - ///ER_NET_READ_ERROR_FROM_PIPE - NetReadErrorFromPipe = 1154, - /// - ///ER_NET_FCNTL_ERROR - NetFCntlError = 1155, - /// - ///ER_NET_PACKETS_OUT_OF_ORDER - NetPacketsOutOfOrder = 1156, - /// - ///ER_NET_UNCOMPRESS_ERROR - NetUncompressError = 1157, - /// - ///ER_NET_READ_ERROR - NetReadError = 1158, - /// - ///ER_NET_READ_INTERRUPTED - NetReadInterrupted = 1159, - /// - ///ER_NET_ERROR_ON_WRITE - NetErrorOnWrite = 1160, - /// - ///ER_NET_WRITE_INTERRUPTED - NetWriteInterrupted = 1161, - /// - ///ER_TOO_LONG_STRING - TooLongString = 1162, - /// - ///ER_TABLE_CANT_HANDLE_BLOB - TableCannotHandleBlob = 1163, - /// - ///ER_TABLE_CANT_HANDLE_AUTO_INCREMENT - TableCannotHandleAutoIncrement = 1164, - /// - ///ER_DELAYED_INSERT_TABLE_LOCKED - DelayedInsertTableLocked = 1165, - /// - ///ER_WRONG_COLUMN_NAME - WrongColumnName = 1166, - /// - ///ER_WRONG_KEY_COLUMN - WrongKeyColumn = 1167, - /// - ///ER_WRONG_MRG_TABLE - WrongMergeTable = 1168, - /// - ///ER_DUP_UNIQUE - DuplicateUnique = 1169, - /// - ///ER_BLOB_KEY_WITHOUT_LENGTH - BlobKeyWithoutLength = 1170, - /// - ///ER_PRIMARY_CANT_HAVE_NULL - PrimaryCannotHaveNull = 1171, - /// - ///ER_TOO_MANY_ROWS - TooManyRows = 1172, - /// - ///ER_REQUIRES_PRIMARY_KEY - RequiresPrimaryKey = 1173, - /// - ///ER_NO_RAID_COMPILED - NoRAIDCompiled = 1174, - /// - ///ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE - UpdateWithoutKeysInSafeMode = 1175, - /// - ///ER_KEY_DOES_NOT_EXITS - KeyDoesNotExist = 1176, - /// - ///ER_CHECK_NO_SUCH_TABLE - CheckNoSuchTable = 1177, - /// - ///ER_CHECK_NOT_IMPLEMENTED - CheckNotImplemented = 1178, - /// - ///ER_CANT_DO_THIS_DURING_AN_TRANSACTION - CannotDoThisDuringATransaction = 1179, - /// - ///ER_ERROR_DURING_COMMIT - ErrorDuringCommit = 1180, - /// - ///ER_ERROR_DURING_ROLLBACK - ErrorDuringRollback = 1181, - /// - ///ER_ERROR_DURING_FLUSH_LOGS - ErrorDuringFlushLogs = 1182, - /// - ///ER_ERROR_DURING_CHECKPOINT - ErrorDuringCheckpoint = 1183, - /// - ///ER_NEW_ABORTING_CONNECTION - NewAbortingConnection = 1184, - /// - ///ER_DUMP_NOT_IMPLEMENTED - DumpNotImplemented = 1185, - /// - ///ER_FLUSH_SOURCE_BINLOG_CLOSED - FlushSourceBinLogClosed = 1186, - /// - ///ER_INDEX_REBUILD - IndexRebuild = 1187, - /// - ///ER_SOURCE - SourceError = 1188, - /// - ///ER_SOURCE_NET_READ - SourceNetRead = 1189, - /// - ///ER_SOURCE_NET_WRITE - SourceNetWrite = 1190, - /// - ///ER_FT_MATCHING_KEY_NOT_FOUND - FullTextMatchingKeyNotFound = 1191, - /// - ///ER_LOCK_OR_ACTIVE_TRANSACTION - LockOrActiveTransaction = 1192, - /// - ///ER_UNKNOWN_SYSTEM_VARIABLE - UnknownSystemVariable = 1193, - /// - ///ER_CRASHED_ON_USAGE - CrashedOnUsage = 1194, - /// - ///ER_CRASHED_ON_REPAIR - CrashedOnRepair = 1195, - /// - ///ER_WARNING_NOT_COMPLETE_ROLLBACK - WarningNotCompleteRollback = 1196, - /// - ///ER_TRANS_CACHE_FULL - TransactionCacheFull = 1197, - /// - ///ER_REPLICA_MUST_STOP - ReplicaMustStop = 1198, - /// - ///ER_REPLICA_NOT_RUNNING - ReplicaNotRunning = 1199, - /// - ///ER_BAD_REPLICA - BadReplica = 1200, - /// - ///ER_SOURCE_INFO - SourceInfo = 1201, - /// - ///ER_REPLICA_THREAD - ReplicaThread = 1202, - /// - ///ER_TOO_MANY_USER_CONNECTIONS - TooManyUserConnections = 1203, - /// - ///ER_SET_CONSTANTS_ONLY - SetConstantsOnly = 1204, - /// - ///ER_LOCK_WAIT_TIMEOUT - LockWaitTimeout = 1205, - /// - ///ER_LOCK_TABLE_FULL - LockTableFull = 1206, - /// - ///ER_READ_ONLY_TRANSACTION - ReadOnlyTransaction = 1207, - /// - ///ER_DROP_DB_WITH_READ_LOCK - DropDatabaseWithReadLock = 1208, - /// - ///ER_CREATE_DB_WITH_READ_LOCK - CreateDatabaseWithReadLock = 1209, - /// - ///ER_WRONG_ARGUMENTS - WrongArguments = 1210, - /// - ///ER_NO_PERMISSION_TO_CREATE_USER - NoPermissionToCreateUser = 1211, - /// - ///ER_UNION_TABLES_IN_DIFFERENT_DIR - UnionTablesInDifferentDirectory = 1212, - /// - ///ER_LOCK_DEADLOCK - LockDeadlock = 1213, - /// - ///ER_TABLE_CANT_HANDLE_FT - TableCannotHandleFullText = 1214, - /// - ///ER_CANNOT_ADD_FOREIGN - CannotAddForeignConstraint = 1215, - /// - ///ER_NO_REFERENCED_ROW - NoReferencedRow = 1216, - /// - ///ER_ROW_IS_REFERENCED - RowIsReferenced = 1217, - /// - ///ER_CONNECT_TO_SOURCE - ConnectToSource = 1218, - /// - ///ER_QUERY_ON_SOURCE - QueryOnSource = 1219, - /// - ///ER_ERROR_WHEN_EXECUTING_COMMAND - ErrorWhenExecutingCommand = 1220, - /// - ///ER_WRONG_USAGE - WrongUsage = 1221, - /// - ///ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT - WrongNumberOfColumnsInSelect = 1222, - /// - ///ER_CANT_UPDATE_WITH_READLOCK - CannotUpdateWithReadLock = 1223, - /// - ///ER_MIXING_NOT_ALLOWED - MixingNotAllowed = 1224, - /// - ///ER_DUP_ARGUMENT - DuplicateArgument = 1225, - /// - ///ER_USER_LIMIT_REACHED - UserLimitReached = 1226, - /// - ///ER_SPECIFIC_ACCESS_DENIED_ERROR - SpecifiedAccessDeniedError = 1227, - /// - ///ER_LOCAL_VARIABLE - LocalVariableError = 1228, - /// - ///ER_GLOBAL_VARIABLE - GlobalVariableError = 1229, - /// - ///ER_NO_DEFAULT - NotDefaultError = 1230, - /// - ///ER_WRONG_VALUE_FOR_VAR - WrongValueForVariable = 1231, - /// - ///ER_WRONG_TYPE_FOR_VAR - WrongTypeForVariable = 1232, - /// - ///ER_VAR_CANT_BE_READ - VariableCannotBeRead = 1233, - /// - ///ER_CANT_USE_OPTION_HERE - CannotUseOptionHere = 1234, - /// - ///ER_NOT_SUPPORTED_YET - NotSupportedYet = 1235, - /// - ///ER_SOURCE_FATAL_ERROR_READING_BINLOG - SourceFatalErrorReadingBinLog = 1236, - /// - ///ER_REPLICA_IGNORED_TABLE - ReplicaIgnoredTable = 1237, - /// - ///ER_INCORRECT_GLOBAL_LOCAL_VAR - IncorrectGlobalLocalVariable = 1238, - /// - ///ER_WRONG_FK_DEF - WrongForeignKeyDefinition = 1239, - /// - ///ER_KEY_REF_DO_NOT_MATCH_TABLE_REF - KeyReferenceDoesNotMatchTableReference = 1240, - /// - ///ER_OPERAND_COLUMNS - OpearnColumnsError = 1241, - /// - ///ER_SUBQUERY_NO_1_ROW - SubQueryNoOneRow = 1242, - /// - ///ER_UNKNOWN_STMT_HANDLER - UnknownStatementHandler = 1243, - /// - ///ER_CORRUPT_HELP_DB - CorruptHelpDatabase = 1244, - /// - ///ER_CYCLIC_REFERENCE - CyclicReference = 1245, - /// - ///ER_AUTO_CONVERT - AutoConvert = 1246, - /// - ///ER_ILLEGAL_REFERENCE - IllegalReference = 1247, - /// - ///ER_DERIVED_MUST_HAVE_ALIAS - DerivedMustHaveAlias = 1248, - /// - ///ER_SELECT_REDUCED - SelectReduced = 1249, - /// - ///ER_TABLENAME_NOT_ALLOWED_HERE - TableNameNotAllowedHere = 1250, - /// - ///ER_NOT_SUPPORTED_AUTH_MODE - NotSupportedAuthMode = 1251, - /// - ///ER_SPATIAL_CANT_HAVE_NULL - SpatialCannotHaveNull = 1252, - /// - ///ER_COLLATION_CHARSET_MISMATCH - CollationCharsetMismatch = 1253, - /// - ///ER_REPLICA_WAS_RUNNING - ReplicaWasRunning = 1254, - /// - ///ER_REPLICA_WAS_NOT_RUNNING - ReplicaWasNotRunning = 1255, - /// - ///ER_TOO_BIG_FOR_UNCOMPRESS - TooBigForUncompress = 1256, - /// - ///ER_ZLIB_Z_MEM_ERROR - ZipLibMemoryError = 1257, - /// - ///ER_ZLIB_Z_BUF_ERROR - ZipLibBufferError = 1258, - /// - ///ER_ZLIB_Z_DATA_ERROR - ZipLibDataError = 1259, - /// - ///ER_CUT_VALUE_GROUP_CONCAT - CutValueGroupConcat = 1260, - /// - ///ER_WARN_TOO_FEW_RECORDS - WarningTooFewRecords = 1261, - /// - ///ER_WARN_TOO_MANY_RECORDS - WarningTooManyRecords = 1262, - /// - ///ER_WARN_NULL_TO_NOTNULL - WarningNullToNotNull = 1263, - /// - ///ER_WARN_DATA_OUT_OF_RANGE - WarningDataOutOfRange = 1264, - /// - ///WARN_DATA_TRUNCATED - WaningDataTruncated = 1265, - /// - ///ER_WARN_USING_OTHER_HANDLER - WaningUsingOtherHandler = 1266, - /// - ///ER_CANT_AGGREGATE_2COLLATIONS - CannotAggregateTwoCollations = 1267, - /// - ///ER_DROP_USER - DropUserError = 1268, - /// - ///ER_REVOKE_GRANTS - RevokeGrantsError = 1269, - /// - ///ER_CANT_AGGREGATE_3COLLATIONS - CannotAggregateThreeCollations = 1270, - /// - ///ER_CANT_AGGREGATE_NCOLLATIONS - CannotAggregateNCollations = 1271, - /// - ///ER_VARIABLE_IS_NOT_STRUCT - VariableIsNotStructure = 1272, - /// - ///ER_UNKNOWN_COLLATION - UnknownCollation = 1273, - /// - ///ER_REPLICA_IGNORED_SSL_PARAMS - ReplicaIgnoreSSLParameters = 1274, - /// - ///ER_SERVER_IS_IN_SECURE_AUTH_MODE - ServerIsInSecureAuthMode = 1275, - /// - ///ER_WARN_FIELD_RESOLVED - WaningFieldResolved = 1276, - /// - ///ER_BAD_REPLICA_UNTIL_COND - BadReplicaUntilCondition = 1277, - /// - ///ER_MISSING_SKIP_REPLICA - MissingSkipReplica = 1278, - /// - ///ER_UNTIL_COND_IGNORED - ErrorUntilConditionIgnored = 1279, - /// - ///ER_WRONG_NAME_FOR_INDEX - WrongNameForIndex = 1280, - /// - ///ER_WRONG_NAME_FOR_CATALOG - WrongNameForCatalog = 1281, - /// - ///ER_WARN_QC_RESIZE - WarningQueryCacheResize = 1282, - /// - ///ER_BAD_FT_COLUMN - BadFullTextColumn = 1283, - /// - ///ER_UNKNOWN_KEY_CACHE - UnknownKeyCache = 1284, - /// - ///ER_WARN_HOSTNAME_WONT_WORK - WarningHostnameWillNotWork = 1285, - /// - ///ER_UNKNOWN_STORAGE_ENGINE - UnknownStorageEngine = 1286, - /// - ///ER_WARN_DEPRECATED_SYNTAX - WaningDeprecatedSyntax = 1287, - /// - ///ER_NON_UPDATABLE_TABLE - NonUpdateableTable = 1288, - /// - ///ER_FEATURE_DISABLED - FeatureDisabled = 1289, - /// - ///ER_OPTION_PREVENTS_STATEMENT - OptionPreventsStatement = 1290, - /// - ///ER_DUPLICATED_VALUE_IN_TYPE - DuplicatedValueInType = 1291, - /// - ///ER_TRUNCATED_WRONG_VALUE - TruncatedWrongValue = 1292, - /// - ///ER_TOO_MUCH_AUTO_TIMESTAMP_COLS - TooMuchAutoTimestampColumns = 1293, - /// - ///ER_INVALID_ON_UPDATE - InvalidOnUpdate = 1294, - /// - ///ER_UNSUPPORTED_PS - UnsupportedPreparedStatement = 1295, - /// - ///ER_GET_ERRMSG - GetErroMessage = 1296, - /// - ///ER_GET_TEMPORARY_ERRMSG - GetTemporaryErrorMessage = 1297, - /// - ///ER_UNKNOWN_TIME_ZONE - UnknownTimeZone = 1298, - /// - ///ER_WARN_INVALID_TIMESTAMP - WarningInvalidTimestamp = 1299, - /// - ///ER_INVALID_CHARACTER_STRING - InvalidCharacterString = 1300, - /// - ///ER_WARN_ALLOWED_PACKET_OVERFLOWED - WarningAllowedPacketOverflowed = 1301, - /// - ///ER_CONFLICTING_DECLARATIONS - ConflictingDeclarations = 1302, - /// - ///ER_SP_NO_RECURSIVE_CREATE - StoredProcedureNoRecursiveCreate = 1303, - /// - ///ER_SP_ALREADY_EXISTS - StoredProcedureAlreadyExists = 1304, - /// - ///ER_SP_DOES_NOT_EXIST - StoredProcedureDoesNotExist = 1305, - /// - ///ER_SP_DROP_FAILED - StoredProcedureDropFailed = 1306, - /// - ///ER_SP_STORE_FAILED - StoredProcedureStoreFailed = 1307, - /// - ///ER_SP_LILABEL_MISMATCH - StoredProcedureLiLabelMismatch = 1308, - /// - ///ER_SP_LABEL_REDEFINE - StoredProcedureLabelRedefine = 1309, - /// - ///ER_SP_LABEL_MISMATCH - StoredProcedureLabelMismatch = 1310, - /// - ///ER_SP_UNINIT_VAR - StoredProcedureUninitializedVariable = 1311, - /// - ///ER_SP_BADSELECT - StoredProcedureBadSelect = 1312, - /// - ///ER_SP_BADRETURN - StoredProcedureBadReturn = 1313, - /// - ///ER_SP_BADSTATEMENT - StoredProcedureBadStatement = 1314, - /// - ///ER_UPDATE_LOG_DEPRECATED_IGNORED - UpdateLogDeprecatedIgnored = 1315, - /// - ///ER_UPDATE_LOG_DEPRECATED_TRANSLATED - UpdateLogDeprecatedTranslated = 1316, - /// - ///ER_QUERY_INTERRUPTED - QueryInterrupted = 1317, - /// - ///ER_SP_WRONG_NO_OF_ARGS - StoredProcedureNumberOfArguments = 1318, - /// - ///ER_SP_COND_MISMATCH - StoredProcedureConditionMismatch = 1319, - /// - ///ER_SP_NORETURN - StoredProcedureNoReturn = 1320, - /// - ///ER_SP_NORETURNEND - StoredProcedureNoReturnEnd = 1321, - /// - ///ER_SP_BAD_CURSOR_QUERY - StoredProcedureBadCursorQuery = 1322, - /// - ///ER_SP_BAD_CURSOR_SELECT - StoredProcedureBadCursorSelect = 1323, - /// - ///ER_SP_CURSOR_MISMATCH - StoredProcedureCursorMismatch = 1324, - /// - ///ER_SP_CURSOR_ALREADY_OPEN - StoredProcedureAlreadyOpen = 1325, - /// - ///ER_SP_CURSOR_NOT_OPEN - StoredProcedureCursorNotOpen = 1326, - /// - ///ER_SP_UNDECLARED_VAR - StoredProcedureUndeclaredVariabel = 1327, - /// - ///ER_SP_WRONG_NO_OF_FETCH_ARGS - StoredProcedureWrongNumberOfFetchArguments = 1328, - /// - ///ER_SP_FETCH_NO_DATA - StoredProcedureFetchNoData = 1329, - /// - ///ER_SP_DUP_PARAM - StoredProcedureDuplicateParameter = 1330, - /// - ///ER_SP_DUP_VAR - StoredProcedureDuplicateVariable = 1331, - /// - ///ER_SP_DUP_COND - StoredProcedureDuplicateCondition = 1332, - /// - ///ER_SP_DUP_CURS - StoredProcedureDuplicateCursor = 1333, - /// - ///ER_SP_CANT_ALTER - StoredProcedureCannotAlter = 1334, - /// - ///ER_SP_SUBSELECT_NYI - StoredProcedureSubSelectNYI = 1335, - /// - ///ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG - StatementNotAllowedInStoredFunctionOrTrigger = 1336, - /// - ///ER_SP_VARCOND_AFTER_CURSHNDLR - StoredProcedureVariableConditionAfterCursorHandler = 1337, - /// - ///ER_SP_CURSOR_AFTER_HANDLER - StoredProcedureCursorAfterHandler = 1338, - /// - ///ER_SP_CASE_NOT_FOUND - StoredProcedureCaseNotFound = 1339, - /// - ///ER_FPARSER_TOO_BIG_FILE - FileParserTooBigFile = 1340, - /// - ///ER_FPARSER_BAD_HEADER - FileParserBadHeader = 1341, - /// - ///ER_FPARSER_EOF_IN_COMMENT - FileParserEOFInComment = 1342, - /// - ///ER_FPARSER_ERROR_IN_PARAMETER - FileParserErrorInParameter = 1343, - /// - ///ER_FPARSER_EOF_IN_UNKNOWN_PARAMETER - FileParserEOFInUnknownParameter = 1344, - /// - ///ER_VIEW_NO_EXPLAIN - ViewNoExplain = 1345, - /// - ///ER_FRM_UNKNOWN_TYPE - FrmUnknownType = 1346, - /// - ///ER_WRONG_OBJECT - WrongObject = 1347, - /// - ///ER_NONUPDATEABLE_COLUMN - NonUpdateableColumn = 1348, - /// - ///ER_VIEW_SELECT_DERIVED - ViewSelectDerived = 1349, - /// - ///ER_VIEW_SELECT_CLAUSE - ViewSelectClause = 1350, - /// - ///ER_VIEW_SELECT_VARIABLE - ViewSelectVariable = 1351, - /// - ///ER_VIEW_SELECT_TMPTABLE - ViewSelectTempTable = 1352, - /// - ///ER_VIEW_WRONG_LIST - ViewWrongList = 1353, - /// - ///ER_WARN_VIEW_MERGE - WarningViewMerge = 1354, - /// - ///ER_WARN_VIEW_WITHOUT_KEY - WarningViewWithoutKey = 1355, - /// - ///ER_VIEW_INVALID - ViewInvalid = 1356, - /// - ///ER_SP_NO_DROP_SP - StoredProcedureNoDropStoredProcedure = 1357, - /// - ///ER_SP_GOTO_IN_HNDLR - StoredProcedureGotoInHandler = 1358, - /// - ///ER_TRG_ALREADY_EXISTS - TriggerAlreadyExists = 1359, - /// - ///ER_TRG_DOES_NOT_EXIST - TriggerDoesNotExist = 1360, - /// - ///ER_TRG_ON_VIEW_OR_TEMP_TABLE - TriggerOnViewOrTempTable = 1361, - /// - ///ER_TRG_CANT_CHANGE_ROW - TriggerCannotChangeRow = 1362, - /// - ///ER_TRG_NO_SUCH_ROW_IN_TRG - TriggerNoSuchRowInTrigger = 1363, - /// - ///ER_NO_DEFAULT_FOR_FIELD - NoDefaultForField = 1364, - /// - ///ER_DIVISION_BY_ZERO - DivisionByZero = 1365, - /// - ///ER_TRUNCATED_WRONG_VALUE_FOR_FIELD - TruncatedWrongValueForField = 1366, - /// - ///ER_ILLEGAL_VALUE_FOR_TYPE - IllegalValueForType = 1367, - /// - ///ER_VIEW_NONUPD_CHECK - ViewNonUpdatableCheck = 1368, - /// - ///ER_VIEW_CHECK_FAILED - ViewCheckFailed = 1369, - /// - ///ER_PROCACCESS_DENIED_ERROR - PrecedureAccessDenied = 1370, - /// - ///ER_RELAY_LOG_FAIL - RelayLogFail = 1371, - /// - ///ER_PASSWD_LENGTH - PasswordLength = 1372, - /// - ///ER_UNKNOWN_TARGET_BINLOG - UnknownTargetBinLog = 1373, - /// - ///ER_IO_ERR_LOG_INDEX_READ - IOErrorLogIndexRead = 1374, - /// - ///ER_BINLOG_PURGE_PROHIBITED - BinLogPurgeProhibited = 1375, - /// - ///ER_FSEEK_FAIL - FSeekFail = 1376, - /// - ///ER_BINLOG_PURGE_FATAL_ERR - BinLogPurgeFatalError = 1377, - /// - ///ER_LOG_IN_USE - LogInUse = 1378, - /// - ///ER_LOG_PURGE_UNKNOWN_ERR - LogPurgeUnknownError = 1379, - /// - ///ER_RELAY_LOG_INIT - RelayLogInit = 1380, - /// - ///ER_NO_BINARY_LOGGING - NoBinaryLogging = 1381, - /// - ///ER_RESERVED_SYNTAX - ReservedSyntax = 1382, - /// - ///ER_WSAS_FAILED - WSAStartupFailed = 1383, - /// - ///ER_DIFF_GROUPS_PROC - DifferentGroupsProcedure = 1384, - /// - ///ER_NO_GROUP_FOR_PROC - NoGroupForProcedure = 1385, - /// - ///ER_ORDER_WITH_PROC - OrderWithProcedure = 1386, - /// - ///ER_LOGGING_PROHIBIT_CHANGING_OF - LoggingProhibitsChangingOf = 1387, - /// - ///ER_NO_FILE_MAPPING - NoFileMapping = 1388, - /// - ///ER_WRONG_MAGIC - WrongMagic = 1389, - /// - ///ER_PS_MANY_PARAM - PreparedStatementManyParameters = 1390, - /// - ///ER_KEY_PART_0 - KeyPartZero = 1391, - /// - ///ER_VIEW_CHECKSUM - ViewChecksum = 1392, - /// - ///ER_VIEW_MULTIUPDATE - ViewMultiUpdate = 1393, - /// - ///ER_VIEW_NO_INSERT_FIELD_LIST - ViewNoInsertFieldList = 1394, - /// - ///ER_VIEW_DELETE_MERGE_VIEW - ViewDeleteMergeView = 1395, - /// - ///ER_CANNOT_USER - CannotUser = 1396, - /// - ///ER_XAER_NOTA - XAERNotA = 1397, - /// - ///ER_XAER_INVAL - XAERInvalid = 1398, - /// - ///ER_XAER_RMFAIL - XAERRemoveFail = 1399, - /// - ///ER_XAER_OUTSIDE - XAEROutside = 1400, - /// - ///ER_XAER_RMERR - XAERRemoveError = 1401, - /// - ///ER_XA_RBROLLBACK - XARBRollback = 1402, - /// - ///ER_NONEXISTING_PROC_GRANT - NonExistingProcedureGrant = 1403, - /// - ///ER_PROC_AUTO_GRANT_FAIL - ProcedureAutoGrantFail = 1404, - /// - ///ER_PROC_AUTO_REVOKE_FAIL - ProcedureAutoRevokeFail = 1405, - /// - ///ER_DATA_TOO_LONG - DataTooLong = 1406, - /// - ///ER_SP_BAD_SQLSTATE - StoredProcedureSQLState = 1407, - /// - ///ER_STARTUP - StartupError = 1408, - /// - ///ER_LOAD_FROM_FIXED_SIZE_ROWS_TO_VAR - LoadFromFixedSizeRowsToVariable = 1409, - /// - ///ER_CANT_CREATE_USER_WITH_GRANT - CannotCreateUserWithGrant = 1410, - /// - ///ER_WRONG_VALUE_FOR_TYPE - WrongValueForType = 1411, - /// - ///ER_TABLE_DEF_CHANGED - TableDefinitionChanged = 1412, - /// - ///ER_SP_DUP_HANDLER - StoredProcedureDuplicateHandler = 1413, - /// - ///ER_SP_NOT_VAR_ARG - StoredProcedureNotVariableArgument = 1414, - /// - ///ER_SP_NO_RETSET - StoredProcedureNoReturnSet = 1415, - /// - ///ER_CANT_CREATE_GEOMETRY_OBJECT - CannotCreateGeometryObject = 1416, - /// - ///ER_FAILED_ROUTINE_BREAK_BINLOG - FailedRoutineBreaksBinLog = 1417, - /// - ///ER_BINLOG_UNSAFE_ROUTINE - BinLogUnsafeRoutine = 1418, - /// - ///ER_BINLOG_CREATE_ROUTINE_NEED_SUPER - BinLogCreateRoutineNeedSuper = 1419, - /// - ///ER_EXEC_STMT_WITH_OPEN_CURSOR - ExecuteStatementWithOpenCursor = 1420, - /// - ///ER_STMT_HAS_NO_OPEN_CURSOR - StatementHasNoOpenCursor = 1421, - /// - ///ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG - CommitNotAllowedIfStoredFunctionOrTrigger = 1422, - /// - ///ER_NO_DEFAULT_FOR_VIEW_FIELD - NoDefaultForViewField = 1423, - /// - ///ER_SP_NO_RECURSION - StoredProcedureNoRecursion = 1424, - /// - ///ER_TOO_BIG_SCALE - TooBigScale = 1425, - /// - ///ER_TOO_BIG_PRECISION - TooBigPrecision = 1426, - /// - ///ER_M_BIGGER_THAN_D - MBiggerThanD = 1427, - /// - ///ER_WRONG_LOCK_OF_SYSTEM_TABLE - WrongLockOfSystemTable = 1428, - /// - ///ER_CONNECT_TO_FOREIGN_DATA_SOURCE - ConnectToForeignDataSource = 1429, - /// - ///ER_QUERY_ON_FOREIGN_DATA_SOURCE - QueryOnForeignDataSource = 1430, - /// - ///ER_FOREIGN_DATA_SOURCE_DOESNT_EXIST - ForeignDataSourceDoesNotExist = 1431, - /// - ///ER_FOREIGN_DATA_STRING_INVALID_CANT_CREATE - ForeignDataStringInvalidCannotCreate = 1432, - /// - ///ER_FOREIGN_DATA_STRING_INVALID - ForeignDataStringInvalid = 1433, - /// - ///ER_CANT_CREATE_FEDERATED_TABLE - CannotCreateFederatedTable = 1434, - /// - ///ER_TRG_IN_WRONG_SCHEMA - TriggerInWrongSchema = 1435, - /// - ///ER_STACK_OVERRUN_NEED_MORE - StackOverrunNeedMore = 1436, - /// - ///ER_TOO_LONG_BODY - TooLongBody = 1437, - /// - ///ER_WARN_CANT_DROP_DEFAULT_KEYCACHE - WarningCannotDropDefaultKeyCache = 1438, - /// - ///ER_TOO_BIG_DISPLAYWIDTH - TooBigDisplayWidth = 1439, - /// - ///ER_XAER_DUPID - XAERDuplicateID = 1440, - /// - ///ER_DATETIME_FUNCTION_OVERFLOW - DateTimeFunctionOverflow = 1441, - /// - ///ER_CANT_UPDATE_USED_TABLE_IN_SF_OR_TRG - CannotUpdateUsedTableInStoredFunctionOrTrigger = 1442, - /// - ///ER_VIEW_PREVENT_UPDATE - ViewPreventUpdate = 1443, - /// - ///ER_PS_NO_RECURSION - PreparedStatementNoRecursion = 1444, - /// - ///ER_SP_CANT_SET_AUTOCOMMIT - StoredProcedureCannotSetAutoCommit = 1445, - /// - ///ER_MALFORMED_DEFINER - MalformedDefiner = 1446, - /// - ///ER_VIEW_FRM_NO_USER - ViewFrmNoUser = 1447, - /// - ///ER_VIEW_OTHER_USER - ViewOtherUser = 1448, - /// - ///ER_NO_SUCH_USER - NoSuchUser = 1449, - /// - ///ER_FORBID_SCHEMA_CHANGE - ForbidSchemaChange = 1450, - /// - ///ER_ROW_IS_REFERENCED_2 - RowIsReferenced2 = 1451, - /// - ///ER_NO_REFERENCED_ROW_2 - NoReferencedRow2 = 1452, - /// - ///ER_SP_BAD_VAR_SHADOW - StoredProcedureBadVariableShadow = 1453, - /// - ///ER_TRG_NO_DEFINER - TriggerNoDefiner = 1454, - /// - ///ER_OLD_FILE_FORMAT - OldFileFormat = 1455, - /// - ///ER_SP_RECURSION_LIMIT - StoredProcedureRecursionLimit = 1456, - /// - ///ER_SP_PROC_TABLE_CORRUPT - StoredProcedureTableCorrupt = 1457, - /// - ///ER_SP_WRONG_NAME - StoredProcedureWrongName = 1458, - /// - ///ER_TABLE_NEEDS_UPGRADE - TableNeedsUpgrade = 1459, - /// - ///ER_SP_NO_AGGREGATE - StoredProcedureNoAggregate = 1460, - /// - ///ER_MAX_PREPARED_STMT_COUNT_REACHED - MaxPreparedStatementCountReached = 1461, - /// - ///ER_VIEW_RECURSIVE - ViewRecursive = 1462, - /// - ///ER_NON_GROUPING_FIELD_USED - NonGroupingFieldUsed = 1463, - /// - ///ER_TABLE_CANT_HANDLE_SPKEYS - TableCannotHandleSpatialKeys = 1464, - /// - ///ER_NO_TRIGGERS_ON_SYSTEM_SCHEMA - NoTriggersOnSystemSchema = 1465, - /// - ///ER_REMOVED_SPACES - RemovedSpaces = 1466, - /// - ///ER_AUTOINC_READ_FAILED - AutoIncrementReadFailed = 1467, - /// - ///ER_USERNAME - UserNameError = 1468, - /// - ///ER_HOSTNAME - HostNameError = 1469, - /// - ///ER_WRONG_STRING_LENGTH - WrongStringLength = 1470, - /// - ///ER_NON_INSERTABLE_TABLE - NonInsertableTable = 1471, - /// - ///ER_ADMIN_WRONG_MRG_TABLE - AdminWrongMergeTable = 1472, - /// - ///ER_TOO_HIGH_LEVEL_OF_NESTING_FOR_SELECT - TooHighLevelOfNestingForSelect = 1473, - /// - ///ER_NAME_BECOMES_EMPTY - NameBecomesEmpty = 1474, - /// - ///ER_AMBIGUOUS_FIELD_TERM - AmbiguousFieldTerm = 1475, - /// - ///ER_FOREIGN_SERVER_EXISTS - ForeignServerExists = 1476, - /// - ///ER_FOREIGN_SERVER_DOESNT_EXIST - ForeignServerDoesNotExist = 1477, - /// - ///ER_ILLEGAL_HA_CREATE_OPTION - IllegalHACreateOption = 1478, - /// - ///ER_PARTITION_REQUIRES_VALUES_ERROR - PartitionRequiresValues = 1479, - /// - ///ER_PARTITION_WRONG_VALUES_ERROR - PartitionWrongValues = 1480, - /// - ///ER_PARTITION_MAXVALUE_ERROR - PartitionMaxValue = 1481, - /// - ///ER_PARTITION_SUBPARTITION_ERROR - PartitionSubPartition = 1482, - /// - ///ER_PARTITION_SUBPART_MIX_ERROR - PartitionSubPartMix = 1483, - /// - ///ER_PARTITION_WRONG_NO_PART_ERROR - PartitionWrongNoPart = 1484, - /// - ///ER_PARTITION_WRONG_NO_SUBPART_ERROR - PartitionWrongNoSubPart = 1485, - /// - ///ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR - WrongExpressionInParitionFunction = 1486, - /// - ///ER_NO_CONST_EXPR_IN_RANGE_OR_LIST_ERROR - NoConstantExpressionInRangeOrListError = 1487, - /// - ///ER_FIELD_NOT_FOUND_PART_ERROR - FieldNotFoundPartitionErrror = 1488, - /// - ///ER_LIST_OF_FIELDS_ONLY_IN_HASH_ERROR - ListOfFieldsOnlyInHash = 1489, - /// - ///ER_INCONSISTENT_PARTITION_INFO_ERROR - InconsistentPartitionInfo = 1490, - /// - ///ER_PARTITION_FUNC_NOT_ALLOWED_ERROR - PartitionFunctionNotAllowed = 1491, - /// - ///ER_PARTITIONS_MUST_BE_DEFINED_ERROR - PartitionsMustBeDefined = 1492, - /// - ///ER_RANGE_NOT_INCREASING_ERROR - RangeNotIncreasing = 1493, - /// - ///ER_INCONSISTENT_TYPE_OF_FUNCTIONS_ERROR - InconsistentTypeOfFunctions = 1494, - /// - ///ER_MULTIPLE_DEF_CONST_IN_LIST_PART_ERROR - MultipleDefinitionsConstantInListPartition = 1495, - /// - ///ER_PARTITION_ENTRY_ERROR - PartitionEntryError = 1496, - /// - ///ER_MIX_HANDLER_ERROR - MixHandlerError = 1497, - /// - ///ER_PARTITION_NOT_DEFINED_ERROR - PartitionNotDefined = 1498, - /// - ///ER_TOO_MANY_PARTITIONS_ERROR - TooManyPartitions = 1499, - /// - ///ER_SUBPARTITION_ERROR - SubPartitionError = 1500, - /// - ///ER_CANT_CREATE_HANDLER_FILE - CannotCreateHandlerFile = 1501, - /// - ///ER_BLOB_FIELD_IN_PART_FUNC_ERROR - BlobFieldInPartitionFunction = 1502, - /// - ///ER_UNIQUE_KEY_NEED_ALL_FIELDS_IN_PF - UniqueKeyNeedAllFieldsInPartitioningFunction = 1503, - /// - ///ER_NO_PARTS_ERROR - NoPartitions = 1504, - /// - ///ER_PARTITION_MGMT_ON_NONPARTITIONED - PartitionManagementOnNoPartitioned = 1505, - /// - ///ER_FOREIGN_KEY_ON_PARTITIONED - ForeignKeyOnPartitioned = 1506, - /// - ///ER_DROP_PARTITION_NON_EXISTENT - DropPartitionNonExistent = 1507, - /// - ///ER_DROP_LAST_PARTITION - DropLastPartition = 1508, - /// - ///ER_COALESCE_ONLY_ON_HASH_PARTITION - CoalesceOnlyOnHashPartition = 1509, - /// - ///ER_REORG_HASH_ONLY_ON_SAME_NO - ReorganizeHashOnlyOnSameNumber = 1510, - /// - ///ER_REORG_NO_PARAM_ERROR - ReorganizeNoParameter = 1511, - /// - ///ER_ONLY_ON_RANGE_LIST_PARTITION - OnlyOnRangeListPartition = 1512, - /// - ///ER_ADD_PARTITION_SUBPART_ERROR - AddPartitionSubPartition = 1513, - /// - ///ER_ADD_PARTITION_NO_NEW_PARTITION - AddPartitionNoNewPartition = 1514, - /// - ///ER_COALESCE_PARTITION_NO_PARTITION - CoalescePartitionNoPartition = 1515, - /// - ///ER_REORG_PARTITION_NOT_EXIST - ReorganizePartitionNotExist = 1516, - /// - ///ER_SAME_NAME_PARTITION - SameNamePartition = 1517, - /// - ///ER_NO_BINLOG_ERROR - NoBinLog = 1518, - /// - ///ER_CONSECUTIVE_REORG_PARTITIONS - ConsecutiveReorganizePartitions = 1519, - /// - ///ER_REORG_OUTSIDE_RANGE - ReorganizeOutsideRange = 1520, - /// - ///ER_PARTITION_FUNCTION_FAILURE - PartitionFunctionFailure = 1521, - /// - ///ER_PART_STATE_ERROR - PartitionStateError = 1522, - /// - ///ER_LIMITED_PART_RANGE - LimitedPartitionRange = 1523, - /// - ///ER_PLUGIN_IS_NOT_LOADED - PluginIsNotLoaded = 1524, - /// - ///ER_WRONG_VALUE - WrongValue = 1525, - /// - ///ER_NO_PARTITION_FOR_GIVEN_VALUE - NoPartitionForGivenValue = 1526, - /// - ///ER_FILEGROUP_OPTION_ONLY_ONCE - FileGroupOptionOnlyOnce = 1527, - /// - ///ER_CREATE_FILEGROUP_FAILED - CreateFileGroupFailed = 1528, - /// - ///ER_DROP_FILEGROUP_FAILED - DropFileGroupFailed = 1529, - /// - ///ER_TABLESPACE_AUTO_EXTEND_ERROR - TableSpaceAutoExtend = 1530, - /// - ///ER_WRONG_SIZE_NUMBER - WrongSizeNumber = 1531, - /// - ///ER_SIZE_OVERFLOW_ERROR - SizeOverflow = 1532, - /// - ///ER_ALTER_FILEGROUP_FAILED - AlterFileGroupFailed = 1533, - /// - ///ER_BINLOG_ROW_LOGGING_FAILED - BinLogRowLogginFailed = 1534, - /// - ///ER_BINLOG_ROW_WRONG_TABLE_DEF - BinLogRowWrongTableDefinition = 1535, - /// - ///ER_BINLOG_ROW_RBR_TO_SBR - BinLogRowRBRToSBR = 1536, - /// - ///ER_EVENT_ALREADY_EXISTS - EventAlreadyExists = 1537, - /// - ///ER_EVENT_STORE_FAILED - EventStoreFailed = 1538, - /// - ///ER_EVENT_DOES_NOT_EXIST - EventDoesNotExist = 1539, - /// - ///ER_EVENT_CANT_ALTER - EventCannotAlter = 1540, - /// - ///ER_EVENT_DROP_FAILED - EventDropFailed = 1541, - /// - ///ER_EVENT_INTERVAL_NOT_POSITIVE_OR_TOO_BIG - EventIntervalNotPositiveOrTooBig = 1542, - /// - ///ER_EVENT_ENDS_BEFORE_STARTS - EventEndsBeforeStarts = 1543, - /// - ///ER_EVENT_EXEC_TIME_IN_THE_PAST - EventExecTimeInThePast = 1544, - /// - ///ER_EVENT_OPEN_TABLE_FAILED - EventOpenTableFailed = 1545, - /// - ///ER_EVENT_NEITHER_M_EXPR_NOR_M_AT - EventNeitherMExpresssionNorMAt = 1546, - /// - ///ER_COL_COUNT_DOESNT_MATCH_CORRUPTED - ColumnCountDoesNotMatchCorrupted = 1547, - /// - ///ER_CANNOT_LOAD_FROM_TABLE - CannotLoadFromTable = 1548, - /// - ///ER_EVENT_CANNOT_DELETE - EventCannotDelete = 1549, - /// - ///ER_EVENT_COMPILE_ERROR - EventCompileError = 1550, - /// - ///ER_EVENT_SAME_NAME - EventSameName = 1551, - /// - ///ER_EVENT_DATA_TOO_LONG - EventDataTooLong = 1552, - /// - ///ER_DROP_INDEX_FK - DropIndexForeignKey = 1553, - /// - ///ER_WARN_DEPRECATED_SYNTAX_WITH_VER - WarningDeprecatedSyntaxWithVersion = 1554, - /// - ///ER_CANT_WRITE_LOCK_LOG_TABLE - CannotWriteLockLogTable = 1555, - /// - ///ER_CANT_LOCK_LOG_TABLE - CannotLockLogTable = 1556, - /// - ///ER_FOREIGN_DUPLICATE_KEY - ForeignDuplicateKey = 1557, - /// - ///ER_COL_COUNT_DOESNT_MATCH_PLEASE_UPDATE - ColumnCountDoesNotMatchPleaseUpdate = 1558, - /// - ///ER_TEMP_TABLE_PREVENTS_SWITCH_OUT_OF_RBR - TemoraryTablePreventSwitchOutOfRBR = 1559, - /// - ///ER_STORED_FUNCTION_PREVENTS_SWITCH_BINLOG_FORMAT - StoredFunctionPreventsSwitchBinLogFormat = 1560, - /// - ///ER_NDB_CANT_SWITCH_BINLOG_FORMAT - NDBCannotSwitchBinLogFormat = 1561, - /// - ///ER_PARTITION_NO_TEMPORARY - PartitionNoTemporary = 1562, - /// - ///ER_PARTITION_CONST_DOMAIN_ERROR - PartitionConstantDomain = 1563, - /// - ///ER_PARTITION_FUNCTION_IS_NOT_ALLOWED - PartitionFunctionIsNotAllowed = 1564, - /// - ///ER_DDL_LOG_ERROR - DDLLogError = 1565, - /// - ///ER_NULL_IN_VALUES_LESS_THAN - NullInValuesLessThan = 1566, - /// - ///ER_WRONG_PARTITION_NAME - WrongPartitionName = 1567, - /// - ///ER_CANT_CHANGE_TRANSACTION_ISOLATION - CannotChangeTransactionIsolation = 1568, - /// - ///ER_DUP_ENTRY_AUTOINCREMENT_CASE - DuplicateEntryAutoIncrementCase = 1569, - /// - ///ER_EVENT_MODIFY_QUEUE_ERROR - EventModifyQueueError = 1570, - /// - ///ER_EVENT_SET_VAR_ERROR - EventSetVariableError = 1571, - /// - ///ER_PARTITION_MERGE_ERROR - PartitionMergeError = 1572, - /// - ///ER_CANT_ACTIVATE_LOG - CannotActivateLog = 1573, - /// - ///ER_RBR_NOT_AVAILABLE - RBRNotAvailable = 1574, - /// - ///ER_BASE64_DECODE_ERROR - Base64DecodeError = 1575, - /// - ///ER_EVENT_RECURSION_FORBIDDEN - EventRecursionForbidden = 1576, - /// - ///ER_EVENTS_DB_ERROR - EventsDatabaseError = 1577, - /// - ///ER_ONLY_INTEGERS_ALLOWED - OnlyIntegersAllowed = 1578, - /// - ///ER_UNSUPORTED_LOG_ENGINE - UnsupportedLogEngine = 1579, - /// - ///ER_BAD_LOG_STATEMENT - BadLogStatement = 1580, - /// - ///ER_CANT_RENAME_LOG_TABLE - CannotRenameLogTable = 1581, - /// - ///ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT - WrongParameterCountToNativeFCT = 1582, - /// - ///ER_WRONG_PARAMETERS_TO_NATIVE_FCT - WrongParametersToNativeFCT = 1583, - /// - ///ER_WRONG_PARAMETERS_TO_STORED_FCT - WrongParametersToStoredFCT = 1584, - /// - ///ER_NATIVE_FCT_NAME_COLLISION - NativeFCTNameCollision = 1585, - /// - ///ER_DUP_ENTRY_WITH_KEY_NAME - DuplicateEntryWithKeyName = 1586, - /// - ///ER_BINLOG_PURGE_EMFILE - BinLogPurgeEMFile = 1587, - /// - ///ER_EVENT_CANNOT_CREATE_IN_THE_PAST - EventCannotCreateInThePast = 1588, - /// - ///ER_EVENT_CANNOT_ALTER_IN_THE_PAST - EventCannotAlterInThePast = 1589, - /// - ///ER_REPLICA_INCIDENT - ReplicaIncident = 1590, - /// - ///ER_NO_PARTITION_FOR_GIVEN_VALUE_SILENT - NoPartitionForGivenValueSilent = 1591, - /// - ///ER_BINLOG_UNSAFE_STATEMENT - BinLogUnsafeStatement = 1592, - /// - ///ER_REPLICA_FATAL_ERROR - ReplicaFatalError = 1593, - /// - ///ER_REPLICA_RELAY_LOG_READ_FAILURE - ReplicaRelayLogReadFailure = 1594, - /// - ///ER_REPLICA_RELAY_LOG_WRITE_FAILURE - ReplicaRelayLogWriteFailure = 1595, - /// - ///ER_REPLICA_CREATE_EVENT_FAILURE - ReplicaCreateEventFailure = 1596, - /// - ///ER_REPLICA_SOURCE_COM_FAILURE - ReplicaSourceComFailure = 1597, - /// - ///ER_BINLOG_LOGGING_IMPOSSIBLE - BinLogLoggingImpossible = 1598, - /// - ///ER_VIEW_NO_CREATION_CTX - ViewNoCreationContext = 1599, - /// - ///ER_VIEW_INVALID_CREATION_CTX - ViewInvalidCreationContext = 1600, - /// - ///ER_SR_INVALID_CREATION_CTX - StoredRoutineInvalidCreateionContext = 1601, - /// - ///ER_TRG_CORRUPTED_FILE - TiggerCorruptedFile = 1602, - /// - ///ER_TRG_NO_CREATION_CTX - TriggerNoCreationContext = 1603, - /// - ///ER_TRG_INVALID_CREATION_CTX - TriggerInvalidCreationContext = 1604, - /// - ///ER_EVENT_INVALID_CREATION_CTX - EventInvalidCreationContext = 1605, - /// - ///ER_TRG_CANT_OPEN_TABLE - TriggerCannotOpenTable = 1606, - /// - ///ER_CANT_CREATE_SROUTINE - CannoCreateSubRoutine = 1607, - /// - ///ER_REPLICA_AMBIGOUS_EXEC_MODE - ReplicaAmbiguousExecMode = 1608, - /// - ///ER_NO_FORMAT_DESCRIPTION_EVENT_BEFORE_BINLOG_STATEMENT - NoFormatDescriptionEventBeforeBinLogStatement = 1609, - /// - ///ER_REPLICA_CORRUPT_EVENT - ReplicaCorruptEvent = 1610, - /// - ///ER_LOAD_DATA_INVALID_COLUMN - LoadDataInvalidColumn = 1611, - /// - ///ER_LOG_PURGE_NO_FILE - LogPurgeNoFile = 1612, - /// - ///ER_XA_RBTIMEOUT - XARBTimeout = 1613, - /// - ///ER_XA_RBDEADLOCK - XARBDeadlock = 1614, - /// - ///ER_NEED_REPREPARE - NeedRePrepare = 1615, - /// - ///ER_DELAYED_NOT_SUPPORTED - DelayedNotSupported = 1616, - /// - ///WARN_NO_SOURCE_INFO - WarningNoSourceInfo = 1617, - /// - ///WARN_OPTION_IGNORED - WarningOptionIgnored = 1618, - /// - ///WARN_PLUGIN_DELETE_BUILTIN - WarningPluginDeleteBuiltIn = 1619, - /// - ///WARN_PLUGIN_BUSY - WarningPluginBusy = 1620, - /// - ///ER_VARIABLE_IS_READONLY - VariableIsReadonly = 1621, - /// - ///ER_WARN_ENGINE_TRANSACTION_ROLLBACK - WarningEngineTransactionRollback = 1622, - /// - ///ER_REPLICA_HEARTBEAT_FAILURE - ReplicaHeartbeatFailure = 1623, - /// - ///ER_REPLICA_HEARTBEAT_VALUE_OUT_OF_RANGE - ReplicaHeartbeatValueOutOfRange = 1624, - /// - ///ER_NDB_REPLICATION_SCHEMA_ERROR - NDBReplicationSchemaError = 1625, - /// - ///ER_CONFLICT_FN_PARSE_ERROR - ConflictFunctionParseError = 1626, - /// - ///ER_EXCEPTIONS_WRITE_ERROR - ExcepionsWriteError = 1627, - /// - ///ER_TOO_LONG_TABLE_COMMENT - TooLongTableComment = 1628, - /// - ///ER_TOO_LONG_FIELD_COMMENT - TooLongFieldComment = 1629, - /// - ///ER_FUNC_INEXISTENT_NAME_COLLISION - FunctionInExistentNameCollision = 1630, - /// - ///ER_DATABASE_NAME - DatabaseNameError = 1631, - /// - ///ER_TABLE_NAME - TableNameErrror = 1632, - /// - ///ER_PARTITION_NAME - PartitionNameError = 1633, - /// - ///ER_SUBPARTITION_NAME - SubPartitionNameError = 1634, - /// - ///ER_TEMPORARY_NAME - TemporaryNameError = 1635, - /// - ///ER_RENAMED_NAME - RenamedNameError = 1636, - /// - ///ER_TOO_MANY_CONCURRENT_TRXS - TooManyConcurrentTransactions = 1637, - /// - ///WARN_NON_ASCII_SEPARATOR_NOT_IMPLEMENTED - WarningNonASCIISeparatorNotImplemented = 1638, - /// - ///ER_DEBUG_SYNC_TIMEOUT - DebugSyncTimeout = 1639, - /// - ///ER_DEBUG_SYNC_HIT_LIMIT - DebugSyncHitLimit = 1640, - /// - ///ER_ERROR_LAST - ErrorLast = 1640, - /// - ///ER_CLIENT_INTERACTION_TIMEOUT - ErrorClientInteractionTimeout = 4031 - } -} +// Copyright © 2004, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +namespace MySql.Data.MySqlClient +{ + /// + /// Collection of error codes that can be returned by the server + /// + public class MySqlError + { + /// + /// + /// + /// + public MySqlError(string level, int code, string message) + { + this.Level = level; + this.Code = code; + this.Message = message; + } + + /// + /// Error level + /// + public string Level { get; } + + /// + /// Error code + /// + public int Code { get; } + + /// + /// Error message + /// + public string Message { get; } + }; + + /// + /// Provides a reference to error codes returned by MySQL. + /// + public enum MySqlErrorCode + { + None = 0, + /// + ///ER_HASHCHK + HashCheck = 1000, + /// + ///ER_NISAMCHK + ISAMCheck = 1001, + /// + ///ER_NO + No = 1002, + /// + ///ER_YES + Yes = 1003, + ///The file couldn't be created. + ///ER_CANT_CREATE_FILE + CannotCreateFile = 1004, + ///The table couldn't be created. + ///ER_CANT_CREATE_TABLE + CannotCreateTable = 1005, + ///The database couldn't be created. + ///ER_CANT_CREATE_DB + CannotCreateDatabase = 1006, + ///The database couldn't be created, it already exists. + ///ER_DB_CREATE_EXISTS + DatabaseCreateExists = 1007, + ///The database couldn't be dropped, it doesn't exist. + ///ER_DB_DROP_EXISTS + DatabaseDropExists = 1008, + ///The database couldn't be dropped, the file can't be deleted. + ///ER_DB_DROP_DELETE + DatabaseDropDelete = 1009, + ///The database couldn't be dropped, the directory can't be deleted. + ///ER_DB_DROP_RMDIR + DatabaseDropRemoveDir = 1010, + ///The file couldn't be deleted. + ///ER_CANT_DELETE_FILE + CannotDeleteFile = 1011, + ///The record couldn't be read from the system table. + ///ER_CANT_FIND_SYSTEM_REC + CannotFindSystemRecord = 1012, + ///The status couldn't be retrieved. + ///ER_CANT_GET_STAT + CannotGetStatus = 1013, + ///The working directory couldn't be retrieved. + ///ER_CANT_GET_WD + CannotGetWorkingDirectory = 1014, + ///The file couldn't be locked. + ///ER_CANT_LOCK + CannotLock = 1015, + ///The file couldn't be opened. + ///ER_CANT_OPEN_FILE + CannotOpenFile = 1016, + ///The file couldn't be found. + ///ER_FILE_NOT_FOUND + FileNotFound = 1017, + ///The directory couldn't be read. + ///ER_CANT_READ_DIR + CannotReadDirectory = 1018, + ///The working directory couldn't be entered. + ///ER_CANT_SET_WD + CannotSetWorkingDirectory = 1019, + ///The record changed since it was last read. + ///ER_CHECKREAD + CheckRead = 1020, + ///The disk is full. + ///ER_DISK_FULL + DiskFull = 1021, + /// + /// There is already a key with the given values. + /// + DuplicateKey = 1022, + ///An error occurred when closing the file. + ///ER_ERROR_ON_CLOSE + ErrorOnClose = 1023, + ///An error occurred when reading from the file. + ///ER_ERROR_ON_READ + ErrorOnRead = 1024, + ///An error occurred when renaming then file. + ///ER_ERROR_ON_RENAME + ErrorOnRename = 1025, + ///An error occurred when writing to the file. + ///ER_ERROR_ON_WRITE + ErrorOnWrite = 1026, + ///The file is in use. + ///ER_FILE_USED + FileUsed = 1027, + ///Sorting has been aborted. + ///ER_FILSORT_ABORT + FileSortAborted = 1028, + ///The view doesn't exist. + ///ER_FORM_NOT_FOUND + FormNotFound = 1029, + ///Got the specified error from the table storage engine. + ///ER_GET_ERRNO + GetErrorNumber = 1030, + ///The table storage engine doesn't support the specified option. + ///ER_ILLEGAL_HA + IllegalHA = 1031, + /// + /// The specified key was not found. + /// + KeyNotFound = 1032, + ///The file contains incorrect information. + ///ER_NOT_FORM_FILE + NotFormFile = 1033, + ///The key file is incorrect for the table, it should be repaired. + ///ER_NOT_KEYFILE + NotKeyFile = 1034, + ///The key file is old for the table, it should be repaired. + ///ER_OLD_KEYFILE + OldKeyFile = 1035, + ///The table is read-only + ///ER_OPEN_AS_READONLY + OpenAsReadOnly = 1036, + ///The server is out of memory, it should be restarted. + ///ER_OUTOFMEMORY + OutOfMemory = 1037, + ///The server is out of sort-memory, the sort buffer size should be increased. + ///ER_OUT_OF_SORTMEMORY + OutOfSortMemory = 1038, + ///An unexpected EOF was found when reading from the file. + ///ER_UNEXPECTED_EOF + UnexepectedEOF = 1039, + ///Too many connections are open. + ///ER_CON_COUNT_ERROR + ConnectionCountError = 1040, + ///The server is out of resources, check if MySql or some other process is using all available memory. + ///ER_OUT_OF_RESOURCES + OutOfResources = 1041, + /// + /// Given when the connection is unable to successfully connect to host. + /// + UnableToConnectToHost = 1042, + ///The handshake was invalid. + ///ER_HANDSHAKE_ERROR + HandshakeError = 1043, + ///Access was denied for the specified user using the specified database. + ///ER_DBACCESS_DENIED_ERROR + DatabaseAccessDenied = 1044, + /// + /// Normally returned when an incorrect password is given + /// + AccessDenied = 1045, + ///No database has been selected. + ///ER_NO_DB_ERROR + NoDatabaseSelected = 1046, + ///The command is unknown. + ///ER_UNKNOWN_COM_ERROR + UnknownCommand = 1047, + ///The specified column cannot be NULL. + ///ER_BAD_NULL_ERROR + ColumnCannotBeNull = 1048, + /// The specified database is not known. + UnknownDatabase = 1049, + ///The specified table already exists. + ///ER_TABLE_EXISTS_ERROR + TableExists = 1050, + ///The specified table is unknown. + ///ER_BAD_TABLE_ERROR + BadTable = 1051, + ///The specified column is ambiguous. + ///ER_NON_UNIQ_ERROR + NonUnique = 1052, + ///The server is currently being shutdown. + ///ER_SERVER_SHUTDOWN + ServerShutdown = 1053, + ///The specified columns is unknown. + ///ER_BAD_FIELD_ERROR + BadFieldError = 1054, + ///The specified column isn't in GROUP BY. + ///ER_WRONG_FIELD_WITH_GROUP + WrongFieldWithGroup = 1055, + ///The specified columns cannot be grouped on. + ///ER_WRONG_GROUP_FIELD + WrongGroupField = 1056, + ///There are sum functions and columns in the same statement. + ///ER_WRONG_SUM_SELECT + WrongSumSelected = 1057, + ///The column count doesn't match the value count. + ///ER_WRONG_VALUE_COUNT + WrongValueCount = 1058, + ///The identifier name is too long. + ///ER_TOO_LONG_IDENT + TooLongIdentifier = 1059, + ///The column name is duplicated. + ///ER_DUP_FIELDNAME + DuplicateFieldName = 1060, + /// + /// Duplicate Key Name + /// + DuplicateKeyName = 1061, + /// + /// Duplicate Key Entry + /// + DuplicateKeyEntry = 1062, + ///The column specifier is incorrect. + ///ER_WRONG_FIELD_SPEC + WrongFieldSpecifier = 1063, + ///An error occurred when parsing the statement. + ///ER_PARSE_ERROR + ParseError = 1064, + ///The statement is empty. + ///ER_EMPTY_QUERY + EmptyQuery = 1065, + ///The table alias isn't unique. + ///ER_NONUNIQ_TABLE + NonUniqueTable = 1066, + ///The default value is invalid for the specified field. + ///ER_INVALID_DEFAULT + InvalidDefault = 1067, + ///The table has multiple primary keys defined. + ///ER_MULTIPLE_PRI_KEY + MultiplePrimaryKey = 1068, + ///Too many keys were defined for the table. + ///ER_TOO_MANY_KEYS + TooManyKeys = 1069, + ///Too many parts to the keys were defined for the table. + ///ER_TOO_MANY_KEY_PARTS + TooManyKeysParts = 1070, + ///The specified key is too long + ///ER_TOO_LONG_KEY + TooLongKey = 1071, + ///The specified key column doesn't exist in the table. + ///ER_KEY_COLUMN_DOES_NOT_EXITS + KeyColumnDoesNotExist = 1072, + ///The BLOB column was used as a key, this can't be done. + ///ER_BLOB_USED_AS_KEY + BlobUsedAsKey = 1073, + ///The column length is too big for the specified column type. + ///ER_TOO_BIG_FIELDLENGTH + TooBigFieldLength = 1074, + ///There can only be one auto-column, and it must be defined as a PK. + ///ER_WRONG_AUTO_KEY + WrongAutoKey = 1075, + ///The server is ready to accept connections. + ///ER_READY + Ready = 1076, + /// + ///ER_NORMAL_SHUTDOWN + NormalShutdown = 1077, + ///The server received the specified signal and is aborting. + ///ER_GOT_SIGNAL + GotSignal = 1078, + ///The server shutdown is complete. + ///ER_SHUTDOWN_COMPLETE + ShutdownComplete = 1079, + ///The server is forcing close of the specified thread. + ///ER_FORCING_CLOSE + ForcingClose = 1080, + ///An error occurred when creating the IP socket. + ///ER_IPSOCK_ERROR + IPSocketError = 1081, + ///The table has no index like the one used in CREATE INDEX. + ///ER_NO_SUCH_INDEX + NoSuchIndex = 1082, + ///The field separator argument is not what is expected, check the manual. + ///ER_WRONG_FIELD_TERMINATORS + WrongFieldTerminators = 1083, + ///The BLOB columns must terminated, fixed row lengths cannot be used. + ///ER_BLOBS_AND_NO_TERMINATED + BlobsAndNoTerminated = 1084, + ///The text file cannot be read. + ///ER_TEXTFILE_NOT_READABLE + TextFileNotReadable = 1085, + ///The specified file already exists. + ///ER_FILE_EXISTS_ERROR + FileExists = 1086, + ///Information returned by the LOAD statement. + ///ER_LOAD_INFO + LoadInfo = 1087, + ///Information returned by an UPDATE statement. + ///ER_ALTER_INFO + AlterInfo = 1088, + ///The prefix key is incorrect. + ///ER_WRONG_SUB_KEY + WrongSubKey = 1089, + ///All columns cannot be removed from a table, use DROP TABLE instead. + ///ER_CANT_REMOVE_ALL_FIELDS + CannotRemoveAllFields = 1090, + ///Cannot DROP, check that the column or key exists. + ///ER_CANT_DROP_FIELD_OR_KEY + CannotDropFieldOrKey = 1091, + ///Information returned by an INSERT statement. + ///ER_INSERT_INFO + InsertInfo = 1092, + ///The target table cannot be specified for update in FROM clause. + ///ER_UPDATE_TABLE_USED + UpdateTableUsed = 1093, + ///The specified thread ID is unknown. + ///ER_NO_SUCH_THREAD + NoSuchThread = 1094, + ///The thread cannot be killed, the current user is not the owner. + ///ER_KILL_DENIED_ERROR + KillDenied = 1095, + ///No tables used in the statement. + ///ER_NO_TABLES_USED + NoTablesUsed = 1096, + ///Too many string have been used for the specified column and SET. + ///ER_TOO_BIG_SET + TooBigSet = 1097, + ///A unique filename couldn't be generated. + ///ER_NO_UNIQUE_LOGFILE + NoUniqueLogFile = 1098, + ///The specified table was locked with a READ lock, and can't be updated. + ///ER_TABLE_NOT_LOCKED_FOR_WRITE + TableNotLockedForWrite = 1099, + ///The specified table was not locked with LOCK TABLES. + ///ER_TABLE_NOT_LOCKED + TableNotLocked = 1100, + ///BLOB and Text columns cannot have a default value. + ///ER_BLOB_CANT_HAVE_DEFAULT + BlobCannotHaveDefault = 1101, + ///The specified database name is incorrect. + ///ER_WRONG_DB_NAME + WrongDatabaseName = 1102, + ///The specified table name is incorrect. + ///ER_WRONG_TABLE_NAME + WrongTableName = 1103, + ///The SELECT command would examine more than MAX_JOIN_SIZE rows, check the WHERE clause and use SET SQL_BIG_SELECTS=1 or SET SQL_MAX_JOIN_SIZE=# if the SELECT is ok. + ///ER_TOO_BIG_SELECT + TooBigSelect = 1104, + ///An unknown error occurred. + ///ER_UNKNOWN_ERROR + UnknownError = 1105, + ///The specified procedure is unknown. + ///ER_UNKNOWN_PROCEDURE + UnknownProcedure = 1106, + ///The number of parameters provided for the specified procedure is incorrect. + ///ER_WRONG_PARAMCOUNT_TO_PROCEDURE + WrongParameterCountToProcedure = 1107, + ///The parameters provided for the specified procedure are incorrect. + ///ER_WRONG_PARAMETERS_TO_PROCEDURE + WrongParametersToProcedure = 1108, + ///The specified table is unknown. + ///ER_UNKNOWN_TABLE + UnknownTable = 1109, + ///The specified column has been specified twice. + ///ER_FIELD_SPECIFIED_TWICE + FieldSpecifiedTwice = 1110, + ///The group function has been incorrectly used. + ///ER_INVALID_GROUP_FUNC_USE + InvalidGroupFunctionUse = 1111, + ///The specified table uses an extension that doesn't exist in this MySQL version. + ///ER_UNSUPPORTED_EXTENSION + UnsupportedExtenstion = 1112, + ///The table must have at least one column. + ///ER_TABLE_MUST_HAVE_COLUMNS + TableMustHaveColumns = 1113, + ///The specified table is full. + ///ER_RECORD_FILE_FULL + RecordFileFull = 1114, + ///The specified character set is unknown. + ///ER_UNKNOWN_CHARACTER_SET + UnknownCharacterSet = 1115, + ///Too many tables, MySQL can only use the specified number of tables in a JOIN. + ///ER_TOO_MANY_TABLES + TooManyTables = 1116, + ///Too many columns + ///ER_TOO_MANY_FIELDS + TooManyFields = 1117, + ///The row size is too large, the maximum row size for the used tables (not counting BLOBS) is specified, change some columns or BLOBS. + ///ER_TOO_BIG_ROWSIZE + TooBigRowSize = 1118, + ///A thread stack overrun occurred. Stack statistics are specified. + ///ER_STACK_OVERRUN + StackOverrun = 1119, + ///A cross dependency was found in the OUTER JOIN, examine the ON conditions. + ///ER_WRONG_OUTER_JOIN + WrongOuterJoin = 1120, + ///The table handler doesn't support NULL in the given index, change specified column to be NOT NULL or use another handler. + ///ER_NULL_COLUMN_IN_INDEX + NullColumnInIndex = 1121, + ///The specified user defined function cannot be loaded. + ///ER_CANT_FIND_UDF + CannotFindUDF = 1122, + ///The specified user defined function cannot be initialised. + ///ER_CANT_INITIALIZE_UDF + CannotInitializeUDF = 1123, + ///No paths are allowed for the shared library. + ///ER_UDF_NO_PATHS + UDFNoPaths = 1124, + ///The specified user defined function already exists. + ///ER_UDF_EXISTS + UDFExists = 1125, + ///The specified shared library cannot be opened. + ///ER_CANT_OPEN_LIBRARY + CannotOpenLibrary = 1126, + ///The specified symbol cannot be found in the library. + ///ER_CANT_FIND_DL_ENTRY + CannotFindDLEntry = 1127, + ///The specified function is not defined. + ///ER_FUNCTION_NOT_DEFINED + FunctionNotDefined = 1128, + ///The specified host is blocked because of too many connection errors, unblock with 'mysqladmin flush-hosts'. + ///ER_HOST_IS_BLOCKED + HostIsBlocked = 1129, + /// + /// The given host is not allowed to connect + /// + HostNotPrivileged = 1130, + /// + /// The anonymous user is not allowed to connect + /// + AnonymousUser = 1131, + /// + /// The given password is not allowed + /// + PasswordNotAllowed = 1132, + /// + /// The given password does not match + /// + PasswordNoMatch = 1133, + ///Information returned by an UPDATE statement. + ///ER_UPDATE_INFO + UpdateInfo = 1134, + ///A new thread couldn't be created. + ///ER_CANT_CREATE_THREAD + CannotCreateThread = 1135, + ///The column count doesn't match the value count. + ///ER_WRONG_VALUE_COUNT_ON_ROW + WrongValueCountOnRow = 1136, + ///The specified table can't be re-opened. + ///ER_CANT_REOPEN_TABLE + CannotReopenTable = 1137, + ///The NULL value has been used incorrectly. + ///ER_INVALID_USE_OF_NULL + InvalidUseOfNull = 1138, + ///The regular expression contains an error. + ///ER_REGEXP_ERROR + RegExpError = 1139, + ///GROUP columns (MIN(), MAX(), COUNT(), ...) cannot be mixes with no GROUP columns if there is not GROUP BY clause. + ///ER_MIX_OF_GROUP_FUNC_AND_FIELDS + MixOfGroupFunctionAndFields = 1140, + /// + ///ER_NONEXISTING_GRANT + NonExistingGrant = 1141, + /// + ///ER_TABLEACCESS_DENIED_ERROR + TableAccessDenied = 1142, + /// + ///ER_COLUMNACCESS_DENIED_ERROR + ColumnAccessDenied = 1143, + /// + ///ER_ILLEGAL_GRANT_FOR_TABLE + IllegalGrantForTable = 1144, + /// + ///ER_GRANT_WRONG_HOST_OR_USER + GrantWrongHostOrUser = 1145, + /// + ///ER_NO_SUCH_TABLE + NoSuchTable = 1146, + /// + ///ER_NONEXISTING_TABLE_GRANT + NonExistingTableGrant = 1147, + /// + ///ER_NOT_ALLOWED_COMMAND + NotAllowedCommand = 1148, + /// + ///ER_SYNTAX_ERROR + SyntaxError = 1149, + /// + ///ER_DELAYED_CANT_CHANGE_LOCK + DelayedCannotChangeLock = 1150, + /// + ///ER_TOO_MANY_DELAYED_THREADS + TooManyDelayedThreads = 1151, + /// + ///ER_ABORTING_CONNECTION + AbortingConnection = 1152, + /// + /// An attempt was made to send or receive a packet larger than + /// max_allowed_packet_size + /// + PacketTooLarge = 1153, + /// + ///ER_NET_READ_ERROR_FROM_PIPE + NetReadErrorFromPipe = 1154, + /// + ///ER_NET_FCNTL_ERROR + NetFCntlError = 1155, + /// + ///ER_NET_PACKETS_OUT_OF_ORDER + NetPacketsOutOfOrder = 1156, + /// + ///ER_NET_UNCOMPRESS_ERROR + NetUncompressError = 1157, + /// + ///ER_NET_READ_ERROR + NetReadError = 1158, + /// + ///ER_NET_READ_INTERRUPTED + NetReadInterrupted = 1159, + /// + ///ER_NET_ERROR_ON_WRITE + NetErrorOnWrite = 1160, + /// + ///ER_NET_WRITE_INTERRUPTED + NetWriteInterrupted = 1161, + /// + ///ER_TOO_LONG_STRING + TooLongString = 1162, + /// + ///ER_TABLE_CANT_HANDLE_BLOB + TableCannotHandleBlob = 1163, + /// + ///ER_TABLE_CANT_HANDLE_AUTO_INCREMENT + TableCannotHandleAutoIncrement = 1164, + /// + ///ER_DELAYED_INSERT_TABLE_LOCKED + DelayedInsertTableLocked = 1165, + /// + ///ER_WRONG_COLUMN_NAME + WrongColumnName = 1166, + /// + ///ER_WRONG_KEY_COLUMN + WrongKeyColumn = 1167, + /// + ///ER_WRONG_MRG_TABLE + WrongMergeTable = 1168, + /// + ///ER_DUP_UNIQUE + DuplicateUnique = 1169, + /// + ///ER_BLOB_KEY_WITHOUT_LENGTH + BlobKeyWithoutLength = 1170, + /// + ///ER_PRIMARY_CANT_HAVE_NULL + PrimaryCannotHaveNull = 1171, + /// + ///ER_TOO_MANY_ROWS + TooManyRows = 1172, + /// + ///ER_REQUIRES_PRIMARY_KEY + RequiresPrimaryKey = 1173, + /// + ///ER_NO_RAID_COMPILED + NoRAIDCompiled = 1174, + /// + ///ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE + UpdateWithoutKeysInSafeMode = 1175, + /// + ///ER_KEY_DOES_NOT_EXITS + KeyDoesNotExist = 1176, + /// + ///ER_CHECK_NO_SUCH_TABLE + CheckNoSuchTable = 1177, + /// + ///ER_CHECK_NOT_IMPLEMENTED + CheckNotImplemented = 1178, + /// + ///ER_CANT_DO_THIS_DURING_AN_TRANSACTION + CannotDoThisDuringATransaction = 1179, + /// + ///ER_ERROR_DURING_COMMIT + ErrorDuringCommit = 1180, + /// + ///ER_ERROR_DURING_ROLLBACK + ErrorDuringRollback = 1181, + /// + ///ER_ERROR_DURING_FLUSH_LOGS + ErrorDuringFlushLogs = 1182, + /// + ///ER_ERROR_DURING_CHECKPOINT + ErrorDuringCheckpoint = 1183, + /// + ///ER_NEW_ABORTING_CONNECTION + NewAbortingConnection = 1184, + /// + ///ER_DUMP_NOT_IMPLEMENTED + DumpNotImplemented = 1185, + /// + ///ER_FLUSH_SOURCE_BINLOG_CLOSED + FlushSourceBinLogClosed = 1186, + /// + ///ER_INDEX_REBUILD + IndexRebuild = 1187, + /// + ///ER_SOURCE + SourceError = 1188, + /// + ///ER_SOURCE_NET_READ + SourceNetRead = 1189, + /// + ///ER_SOURCE_NET_WRITE + SourceNetWrite = 1190, + /// + ///ER_FT_MATCHING_KEY_NOT_FOUND + FullTextMatchingKeyNotFound = 1191, + /// + ///ER_LOCK_OR_ACTIVE_TRANSACTION + LockOrActiveTransaction = 1192, + /// + ///ER_UNKNOWN_SYSTEM_VARIABLE + UnknownSystemVariable = 1193, + /// + ///ER_CRASHED_ON_USAGE + CrashedOnUsage = 1194, + /// + ///ER_CRASHED_ON_REPAIR + CrashedOnRepair = 1195, + /// + ///ER_WARNING_NOT_COMPLETE_ROLLBACK + WarningNotCompleteRollback = 1196, + /// + ///ER_TRANS_CACHE_FULL + TransactionCacheFull = 1197, + /// + ///ER_REPLICA_MUST_STOP + ReplicaMustStop = 1198, + /// + ///ER_REPLICA_NOT_RUNNING + ReplicaNotRunning = 1199, + /// + ///ER_BAD_REPLICA + BadReplica = 1200, + /// + ///ER_SOURCE_INFO + SourceInfo = 1201, + /// + ///ER_REPLICA_THREAD + ReplicaThread = 1202, + /// + ///ER_TOO_MANY_USER_CONNECTIONS + TooManyUserConnections = 1203, + /// + ///ER_SET_CONSTANTS_ONLY + SetConstantsOnly = 1204, + /// + ///ER_LOCK_WAIT_TIMEOUT + LockWaitTimeout = 1205, + /// + ///ER_LOCK_TABLE_FULL + LockTableFull = 1206, + /// + ///ER_READ_ONLY_TRANSACTION + ReadOnlyTransaction = 1207, + /// + ///ER_DROP_DB_WITH_READ_LOCK + DropDatabaseWithReadLock = 1208, + /// + ///ER_CREATE_DB_WITH_READ_LOCK + CreateDatabaseWithReadLock = 1209, + /// + ///ER_WRONG_ARGUMENTS + WrongArguments = 1210, + /// + ///ER_NO_PERMISSION_TO_CREATE_USER + NoPermissionToCreateUser = 1211, + /// + ///ER_UNION_TABLES_IN_DIFFERENT_DIR + UnionTablesInDifferentDirectory = 1212, + /// + ///ER_LOCK_DEADLOCK + LockDeadlock = 1213, + /// + ///ER_TABLE_CANT_HANDLE_FT + TableCannotHandleFullText = 1214, + /// + ///ER_CANNOT_ADD_FOREIGN + CannotAddForeignConstraint = 1215, + /// + ///ER_NO_REFERENCED_ROW + NoReferencedRow = 1216, + /// + ///ER_ROW_IS_REFERENCED + RowIsReferenced = 1217, + /// + ///ER_CONNECT_TO_SOURCE + ConnectToSource = 1218, + /// + ///ER_QUERY_ON_SOURCE + QueryOnSource = 1219, + /// + ///ER_ERROR_WHEN_EXECUTING_COMMAND + ErrorWhenExecutingCommand = 1220, + /// + ///ER_WRONG_USAGE + WrongUsage = 1221, + /// + ///ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT + WrongNumberOfColumnsInSelect = 1222, + /// + ///ER_CANT_UPDATE_WITH_READLOCK + CannotUpdateWithReadLock = 1223, + /// + ///ER_MIXING_NOT_ALLOWED + MixingNotAllowed = 1224, + /// + ///ER_DUP_ARGUMENT + DuplicateArgument = 1225, + /// + ///ER_USER_LIMIT_REACHED + UserLimitReached = 1226, + /// + ///ER_SPECIFIC_ACCESS_DENIED_ERROR + SpecifiedAccessDeniedError = 1227, + /// + ///ER_LOCAL_VARIABLE + LocalVariableError = 1228, + /// + ///ER_GLOBAL_VARIABLE + GlobalVariableError = 1229, + /// + ///ER_NO_DEFAULT + NotDefaultError = 1230, + /// + ///ER_WRONG_VALUE_FOR_VAR + WrongValueForVariable = 1231, + /// + ///ER_WRONG_TYPE_FOR_VAR + WrongTypeForVariable = 1232, + /// + ///ER_VAR_CANT_BE_READ + VariableCannotBeRead = 1233, + /// + ///ER_CANT_USE_OPTION_HERE + CannotUseOptionHere = 1234, + /// + ///ER_NOT_SUPPORTED_YET + NotSupportedYet = 1235, + /// + ///ER_SOURCE_FATAL_ERROR_READING_BINLOG + SourceFatalErrorReadingBinLog = 1236, + /// + ///ER_REPLICA_IGNORED_TABLE + ReplicaIgnoredTable = 1237, + /// + ///ER_INCORRECT_GLOBAL_LOCAL_VAR + IncorrectGlobalLocalVariable = 1238, + /// + ///ER_WRONG_FK_DEF + WrongForeignKeyDefinition = 1239, + /// + ///ER_KEY_REF_DO_NOT_MATCH_TABLE_REF + KeyReferenceDoesNotMatchTableReference = 1240, + /// + ///ER_OPERAND_COLUMNS + OpearnColumnsError = 1241, + /// + ///ER_SUBQUERY_NO_1_ROW + SubQueryNoOneRow = 1242, + /// + ///ER_UNKNOWN_STMT_HANDLER + UnknownStatementHandler = 1243, + /// + ///ER_CORRUPT_HELP_DB + CorruptHelpDatabase = 1244, + /// + ///ER_CYCLIC_REFERENCE + CyclicReference = 1245, + /// + ///ER_AUTO_CONVERT + AutoConvert = 1246, + /// + ///ER_ILLEGAL_REFERENCE + IllegalReference = 1247, + /// + ///ER_DERIVED_MUST_HAVE_ALIAS + DerivedMustHaveAlias = 1248, + /// + ///ER_SELECT_REDUCED + SelectReduced = 1249, + /// + ///ER_TABLENAME_NOT_ALLOWED_HERE + TableNameNotAllowedHere = 1250, + /// + ///ER_NOT_SUPPORTED_AUTH_MODE + NotSupportedAuthMode = 1251, + /// + ///ER_SPATIAL_CANT_HAVE_NULL + SpatialCannotHaveNull = 1252, + /// + ///ER_COLLATION_CHARSET_MISMATCH + CollationCharsetMismatch = 1253, + /// + ///ER_REPLICA_WAS_RUNNING + ReplicaWasRunning = 1254, + /// + ///ER_REPLICA_WAS_NOT_RUNNING + ReplicaWasNotRunning = 1255, + /// + ///ER_TOO_BIG_FOR_UNCOMPRESS + TooBigForUncompress = 1256, + /// + ///ER_ZLIB_Z_MEM_ERROR + ZipLibMemoryError = 1257, + /// + ///ER_ZLIB_Z_BUF_ERROR + ZipLibBufferError = 1258, + /// + ///ER_ZLIB_Z_DATA_ERROR + ZipLibDataError = 1259, + /// + ///ER_CUT_VALUE_GROUP_CONCAT + CutValueGroupConcat = 1260, + /// + ///ER_WARN_TOO_FEW_RECORDS + WarningTooFewRecords = 1261, + /// + ///ER_WARN_TOO_MANY_RECORDS + WarningTooManyRecords = 1262, + /// + ///ER_WARN_NULL_TO_NOTNULL + WarningNullToNotNull = 1263, + /// + ///ER_WARN_DATA_OUT_OF_RANGE + WarningDataOutOfRange = 1264, + /// + ///WARN_DATA_TRUNCATED + WaningDataTruncated = 1265, + /// + ///ER_WARN_USING_OTHER_HANDLER + WaningUsingOtherHandler = 1266, + /// + ///ER_CANT_AGGREGATE_2COLLATIONS + CannotAggregateTwoCollations = 1267, + /// + ///ER_DROP_USER + DropUserError = 1268, + /// + ///ER_REVOKE_GRANTS + RevokeGrantsError = 1269, + /// + ///ER_CANT_AGGREGATE_3COLLATIONS + CannotAggregateThreeCollations = 1270, + /// + ///ER_CANT_AGGREGATE_NCOLLATIONS + CannotAggregateNCollations = 1271, + /// + ///ER_VARIABLE_IS_NOT_STRUCT + VariableIsNotStructure = 1272, + /// + ///ER_UNKNOWN_COLLATION + UnknownCollation = 1273, + /// + ///ER_REPLICA_IGNORED_SSL_PARAMS + ReplicaIgnoreSSLParameters = 1274, + /// + ///ER_SERVER_IS_IN_SECURE_AUTH_MODE + ServerIsInSecureAuthMode = 1275, + /// + ///ER_WARN_FIELD_RESOLVED + WaningFieldResolved = 1276, + /// + ///ER_BAD_REPLICA_UNTIL_COND + BadReplicaUntilCondition = 1277, + /// + ///ER_MISSING_SKIP_REPLICA + MissingSkipReplica = 1278, + /// + ///ER_UNTIL_COND_IGNORED + ErrorUntilConditionIgnored = 1279, + /// + ///ER_WRONG_NAME_FOR_INDEX + WrongNameForIndex = 1280, + /// + ///ER_WRONG_NAME_FOR_CATALOG + WrongNameForCatalog = 1281, + /// + ///ER_WARN_QC_RESIZE + WarningQueryCacheResize = 1282, + /// + ///ER_BAD_FT_COLUMN + BadFullTextColumn = 1283, + /// + ///ER_UNKNOWN_KEY_CACHE + UnknownKeyCache = 1284, + /// + ///ER_WARN_HOSTNAME_WONT_WORK + WarningHostnameWillNotWork = 1285, + /// + ///ER_UNKNOWN_STORAGE_ENGINE + UnknownStorageEngine = 1286, + /// + ///ER_WARN_DEPRECATED_SYNTAX + WaningDeprecatedSyntax = 1287, + /// + ///ER_NON_UPDATABLE_TABLE + NonUpdateableTable = 1288, + /// + ///ER_FEATURE_DISABLED + FeatureDisabled = 1289, + /// + ///ER_OPTION_PREVENTS_STATEMENT + OptionPreventsStatement = 1290, + /// + ///ER_DUPLICATED_VALUE_IN_TYPE + DuplicatedValueInType = 1291, + /// + ///ER_TRUNCATED_WRONG_VALUE + TruncatedWrongValue = 1292, + /// + ///ER_TOO_MUCH_AUTO_TIMESTAMP_COLS + TooMuchAutoTimestampColumns = 1293, + /// + ///ER_INVALID_ON_UPDATE + InvalidOnUpdate = 1294, + /// + ///ER_UNSUPPORTED_PS + UnsupportedPreparedStatement = 1295, + /// + ///ER_GET_ERRMSG + GetErroMessage = 1296, + /// + ///ER_GET_TEMPORARY_ERRMSG + GetTemporaryErrorMessage = 1297, + /// + ///ER_UNKNOWN_TIME_ZONE + UnknownTimeZone = 1298, + /// + ///ER_WARN_INVALID_TIMESTAMP + WarningInvalidTimestamp = 1299, + /// + ///ER_INVALID_CHARACTER_STRING + InvalidCharacterString = 1300, + /// + ///ER_WARN_ALLOWED_PACKET_OVERFLOWED + WarningAllowedPacketOverflowed = 1301, + /// + ///ER_CONFLICTING_DECLARATIONS + ConflictingDeclarations = 1302, + /// + ///ER_SP_NO_RECURSIVE_CREATE + StoredProcedureNoRecursiveCreate = 1303, + /// + ///ER_SP_ALREADY_EXISTS + StoredProcedureAlreadyExists = 1304, + /// + ///ER_SP_DOES_NOT_EXIST + StoredProcedureDoesNotExist = 1305, + /// + ///ER_SP_DROP_FAILED + StoredProcedureDropFailed = 1306, + /// + ///ER_SP_STORE_FAILED + StoredProcedureStoreFailed = 1307, + /// + ///ER_SP_LILABEL_MISMATCH + StoredProcedureLiLabelMismatch = 1308, + /// + ///ER_SP_LABEL_REDEFINE + StoredProcedureLabelRedefine = 1309, + /// + ///ER_SP_LABEL_MISMATCH + StoredProcedureLabelMismatch = 1310, + /// + ///ER_SP_UNINIT_VAR + StoredProcedureUninitializedVariable = 1311, + /// + ///ER_SP_BADSELECT + StoredProcedureBadSelect = 1312, + /// + ///ER_SP_BADRETURN + StoredProcedureBadReturn = 1313, + /// + ///ER_SP_BADSTATEMENT + StoredProcedureBadStatement = 1314, + /// + ///ER_UPDATE_LOG_DEPRECATED_IGNORED + UpdateLogDeprecatedIgnored = 1315, + /// + ///ER_UPDATE_LOG_DEPRECATED_TRANSLATED + UpdateLogDeprecatedTranslated = 1316, + /// + ///ER_QUERY_INTERRUPTED + QueryInterrupted = 1317, + /// + ///ER_SP_WRONG_NO_OF_ARGS + StoredProcedureNumberOfArguments = 1318, + /// + ///ER_SP_COND_MISMATCH + StoredProcedureConditionMismatch = 1319, + /// + ///ER_SP_NORETURN + StoredProcedureNoReturn = 1320, + /// + ///ER_SP_NORETURNEND + StoredProcedureNoReturnEnd = 1321, + /// + ///ER_SP_BAD_CURSOR_QUERY + StoredProcedureBadCursorQuery = 1322, + /// + ///ER_SP_BAD_CURSOR_SELECT + StoredProcedureBadCursorSelect = 1323, + /// + ///ER_SP_CURSOR_MISMATCH + StoredProcedureCursorMismatch = 1324, + /// + ///ER_SP_CURSOR_ALREADY_OPEN + StoredProcedureAlreadyOpen = 1325, + /// + ///ER_SP_CURSOR_NOT_OPEN + StoredProcedureCursorNotOpen = 1326, + /// + ///ER_SP_UNDECLARED_VAR + StoredProcedureUndeclaredVariabel = 1327, + /// + ///ER_SP_WRONG_NO_OF_FETCH_ARGS + StoredProcedureWrongNumberOfFetchArguments = 1328, + /// + ///ER_SP_FETCH_NO_DATA + StoredProcedureFetchNoData = 1329, + /// + ///ER_SP_DUP_PARAM + StoredProcedureDuplicateParameter = 1330, + /// + ///ER_SP_DUP_VAR + StoredProcedureDuplicateVariable = 1331, + /// + ///ER_SP_DUP_COND + StoredProcedureDuplicateCondition = 1332, + /// + ///ER_SP_DUP_CURS + StoredProcedureDuplicateCursor = 1333, + /// + ///ER_SP_CANT_ALTER + StoredProcedureCannotAlter = 1334, + /// + ///ER_SP_SUBSELECT_NYI + StoredProcedureSubSelectNYI = 1335, + /// + ///ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG + StatementNotAllowedInStoredFunctionOrTrigger = 1336, + /// + ///ER_SP_VARCOND_AFTER_CURSHNDLR + StoredProcedureVariableConditionAfterCursorHandler = 1337, + /// + ///ER_SP_CURSOR_AFTER_HANDLER + StoredProcedureCursorAfterHandler = 1338, + /// + ///ER_SP_CASE_NOT_FOUND + StoredProcedureCaseNotFound = 1339, + /// + ///ER_FPARSER_TOO_BIG_FILE + FileParserTooBigFile = 1340, + /// + ///ER_FPARSER_BAD_HEADER + FileParserBadHeader = 1341, + /// + ///ER_FPARSER_EOF_IN_COMMENT + FileParserEOFInComment = 1342, + /// + ///ER_FPARSER_ERROR_IN_PARAMETER + FileParserErrorInParameter = 1343, + /// + ///ER_FPARSER_EOF_IN_UNKNOWN_PARAMETER + FileParserEOFInUnknownParameter = 1344, + /// + ///ER_VIEW_NO_EXPLAIN + ViewNoExplain = 1345, + /// + ///ER_FRM_UNKNOWN_TYPE + FrmUnknownType = 1346, + /// + ///ER_WRONG_OBJECT + WrongObject = 1347, + /// + ///ER_NONUPDATEABLE_COLUMN + NonUpdateableColumn = 1348, + /// + ///ER_VIEW_SELECT_DERIVED + ViewSelectDerived = 1349, + /// + ///ER_VIEW_SELECT_CLAUSE + ViewSelectClause = 1350, + /// + ///ER_VIEW_SELECT_VARIABLE + ViewSelectVariable = 1351, + /// + ///ER_VIEW_SELECT_TMPTABLE + ViewSelectTempTable = 1352, + /// + ///ER_VIEW_WRONG_LIST + ViewWrongList = 1353, + /// + ///ER_WARN_VIEW_MERGE + WarningViewMerge = 1354, + /// + ///ER_WARN_VIEW_WITHOUT_KEY + WarningViewWithoutKey = 1355, + /// + ///ER_VIEW_INVALID + ViewInvalid = 1356, + /// + ///ER_SP_NO_DROP_SP + StoredProcedureNoDropStoredProcedure = 1357, + /// + ///ER_SP_GOTO_IN_HNDLR + StoredProcedureGotoInHandler = 1358, + /// + ///ER_TRG_ALREADY_EXISTS + TriggerAlreadyExists = 1359, + /// + ///ER_TRG_DOES_NOT_EXIST + TriggerDoesNotExist = 1360, + /// + ///ER_TRG_ON_VIEW_OR_TEMP_TABLE + TriggerOnViewOrTempTable = 1361, + /// + ///ER_TRG_CANT_CHANGE_ROW + TriggerCannotChangeRow = 1362, + /// + ///ER_TRG_NO_SUCH_ROW_IN_TRG + TriggerNoSuchRowInTrigger = 1363, + /// + ///ER_NO_DEFAULT_FOR_FIELD + NoDefaultForField = 1364, + /// + ///ER_DIVISION_BY_ZERO + DivisionByZero = 1365, + /// + ///ER_TRUNCATED_WRONG_VALUE_FOR_FIELD + TruncatedWrongValueForField = 1366, + /// + ///ER_ILLEGAL_VALUE_FOR_TYPE + IllegalValueForType = 1367, + /// + ///ER_VIEW_NONUPD_CHECK + ViewNonUpdatableCheck = 1368, + /// + ///ER_VIEW_CHECK_FAILED + ViewCheckFailed = 1369, + /// + ///ER_PROCACCESS_DENIED_ERROR + PrecedureAccessDenied = 1370, + /// + ///ER_RELAY_LOG_FAIL + RelayLogFail = 1371, + /// + ///ER_PASSWD_LENGTH + PasswordLength = 1372, + /// + ///ER_UNKNOWN_TARGET_BINLOG + UnknownTargetBinLog = 1373, + /// + ///ER_IO_ERR_LOG_INDEX_READ + IOErrorLogIndexRead = 1374, + /// + ///ER_BINLOG_PURGE_PROHIBITED + BinLogPurgeProhibited = 1375, + /// + ///ER_FSEEK_FAIL + FSeekFail = 1376, + /// + ///ER_BINLOG_PURGE_FATAL_ERR + BinLogPurgeFatalError = 1377, + /// + ///ER_LOG_IN_USE + LogInUse = 1378, + /// + ///ER_LOG_PURGE_UNKNOWN_ERR + LogPurgeUnknownError = 1379, + /// + ///ER_RELAY_LOG_INIT + RelayLogInit = 1380, + /// + ///ER_NO_BINARY_LOGGING + NoBinaryLogging = 1381, + /// + ///ER_RESERVED_SYNTAX + ReservedSyntax = 1382, + /// + ///ER_WSAS_FAILED + WSAStartupFailed = 1383, + /// + ///ER_DIFF_GROUPS_PROC + DifferentGroupsProcedure = 1384, + /// + ///ER_NO_GROUP_FOR_PROC + NoGroupForProcedure = 1385, + /// + ///ER_ORDER_WITH_PROC + OrderWithProcedure = 1386, + /// + ///ER_LOGGING_PROHIBIT_CHANGING_OF + LoggingProhibitsChangingOf = 1387, + /// + ///ER_NO_FILE_MAPPING + NoFileMapping = 1388, + /// + ///ER_WRONG_MAGIC + WrongMagic = 1389, + /// + ///ER_PS_MANY_PARAM + PreparedStatementManyParameters = 1390, + /// + ///ER_KEY_PART_0 + KeyPartZero = 1391, + /// + ///ER_VIEW_CHECKSUM + ViewChecksum = 1392, + /// + ///ER_VIEW_MULTIUPDATE + ViewMultiUpdate = 1393, + /// + ///ER_VIEW_NO_INSERT_FIELD_LIST + ViewNoInsertFieldList = 1394, + /// + ///ER_VIEW_DELETE_MERGE_VIEW + ViewDeleteMergeView = 1395, + /// + ///ER_CANNOT_USER + CannotUser = 1396, + /// + ///ER_XAER_NOTA + XAERNotA = 1397, + /// + ///ER_XAER_INVAL + XAERInvalid = 1398, + /// + ///ER_XAER_RMFAIL + XAERRemoveFail = 1399, + /// + ///ER_XAER_OUTSIDE + XAEROutside = 1400, + /// + ///ER_XAER_RMERR + XAERRemoveError = 1401, + /// + ///ER_XA_RBROLLBACK + XARBRollback = 1402, + /// + ///ER_NONEXISTING_PROC_GRANT + NonExistingProcedureGrant = 1403, + /// + ///ER_PROC_AUTO_GRANT_FAIL + ProcedureAutoGrantFail = 1404, + /// + ///ER_PROC_AUTO_REVOKE_FAIL + ProcedureAutoRevokeFail = 1405, + /// + ///ER_DATA_TOO_LONG + DataTooLong = 1406, + /// + ///ER_SP_BAD_SQLSTATE + StoredProcedureSQLState = 1407, + /// + ///ER_STARTUP + StartupError = 1408, + /// + ///ER_LOAD_FROM_FIXED_SIZE_ROWS_TO_VAR + LoadFromFixedSizeRowsToVariable = 1409, + /// + ///ER_CANT_CREATE_USER_WITH_GRANT + CannotCreateUserWithGrant = 1410, + /// + ///ER_WRONG_VALUE_FOR_TYPE + WrongValueForType = 1411, + /// + ///ER_TABLE_DEF_CHANGED + TableDefinitionChanged = 1412, + /// + ///ER_SP_DUP_HANDLER + StoredProcedureDuplicateHandler = 1413, + /// + ///ER_SP_NOT_VAR_ARG + StoredProcedureNotVariableArgument = 1414, + /// + ///ER_SP_NO_RETSET + StoredProcedureNoReturnSet = 1415, + /// + ///ER_CANT_CREATE_GEOMETRY_OBJECT + CannotCreateGeometryObject = 1416, + /// + ///ER_FAILED_ROUTINE_BREAK_BINLOG + FailedRoutineBreaksBinLog = 1417, + /// + ///ER_BINLOG_UNSAFE_ROUTINE + BinLogUnsafeRoutine = 1418, + /// + ///ER_BINLOG_CREATE_ROUTINE_NEED_SUPER + BinLogCreateRoutineNeedSuper = 1419, + /// + ///ER_EXEC_STMT_WITH_OPEN_CURSOR + ExecuteStatementWithOpenCursor = 1420, + /// + ///ER_STMT_HAS_NO_OPEN_CURSOR + StatementHasNoOpenCursor = 1421, + /// + ///ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG + CommitNotAllowedIfStoredFunctionOrTrigger = 1422, + /// + ///ER_NO_DEFAULT_FOR_VIEW_FIELD + NoDefaultForViewField = 1423, + /// + ///ER_SP_NO_RECURSION + StoredProcedureNoRecursion = 1424, + /// + ///ER_TOO_BIG_SCALE + TooBigScale = 1425, + /// + ///ER_TOO_BIG_PRECISION + TooBigPrecision = 1426, + /// + ///ER_M_BIGGER_THAN_D + MBiggerThanD = 1427, + /// + ///ER_WRONG_LOCK_OF_SYSTEM_TABLE + WrongLockOfSystemTable = 1428, + /// + ///ER_CONNECT_TO_FOREIGN_DATA_SOURCE + ConnectToForeignDataSource = 1429, + /// + ///ER_QUERY_ON_FOREIGN_DATA_SOURCE + QueryOnForeignDataSource = 1430, + /// + ///ER_FOREIGN_DATA_SOURCE_DOESNT_EXIST + ForeignDataSourceDoesNotExist = 1431, + /// + ///ER_FOREIGN_DATA_STRING_INVALID_CANT_CREATE + ForeignDataStringInvalidCannotCreate = 1432, + /// + ///ER_FOREIGN_DATA_STRING_INVALID + ForeignDataStringInvalid = 1433, + /// + ///ER_CANT_CREATE_FEDERATED_TABLE + CannotCreateFederatedTable = 1434, + /// + ///ER_TRG_IN_WRONG_SCHEMA + TriggerInWrongSchema = 1435, + /// + ///ER_STACK_OVERRUN_NEED_MORE + StackOverrunNeedMore = 1436, + /// + ///ER_TOO_LONG_BODY + TooLongBody = 1437, + /// + ///ER_WARN_CANT_DROP_DEFAULT_KEYCACHE + WarningCannotDropDefaultKeyCache = 1438, + /// + ///ER_TOO_BIG_DISPLAYWIDTH + TooBigDisplayWidth = 1439, + /// + ///ER_XAER_DUPID + XAERDuplicateID = 1440, + /// + ///ER_DATETIME_FUNCTION_OVERFLOW + DateTimeFunctionOverflow = 1441, + /// + ///ER_CANT_UPDATE_USED_TABLE_IN_SF_OR_TRG + CannotUpdateUsedTableInStoredFunctionOrTrigger = 1442, + /// + ///ER_VIEW_PREVENT_UPDATE + ViewPreventUpdate = 1443, + /// + ///ER_PS_NO_RECURSION + PreparedStatementNoRecursion = 1444, + /// + ///ER_SP_CANT_SET_AUTOCOMMIT + StoredProcedureCannotSetAutoCommit = 1445, + /// + ///ER_MALFORMED_DEFINER + MalformedDefiner = 1446, + /// + ///ER_VIEW_FRM_NO_USER + ViewFrmNoUser = 1447, + /// + ///ER_VIEW_OTHER_USER + ViewOtherUser = 1448, + /// + ///ER_NO_SUCH_USER + NoSuchUser = 1449, + /// + ///ER_FORBID_SCHEMA_CHANGE + ForbidSchemaChange = 1450, + /// + ///ER_ROW_IS_REFERENCED_2 + RowIsReferenced2 = 1451, + /// + ///ER_NO_REFERENCED_ROW_2 + NoReferencedRow2 = 1452, + /// + ///ER_SP_BAD_VAR_SHADOW + StoredProcedureBadVariableShadow = 1453, + /// + ///ER_TRG_NO_DEFINER + TriggerNoDefiner = 1454, + /// + ///ER_OLD_FILE_FORMAT + OldFileFormat = 1455, + /// + ///ER_SP_RECURSION_LIMIT + StoredProcedureRecursionLimit = 1456, + /// + ///ER_SP_PROC_TABLE_CORRUPT + StoredProcedureTableCorrupt = 1457, + /// + ///ER_SP_WRONG_NAME + StoredProcedureWrongName = 1458, + /// + ///ER_TABLE_NEEDS_UPGRADE + TableNeedsUpgrade = 1459, + /// + ///ER_SP_NO_AGGREGATE + StoredProcedureNoAggregate = 1460, + /// + ///ER_MAX_PREPARED_STMT_COUNT_REACHED + MaxPreparedStatementCountReached = 1461, + /// + ///ER_VIEW_RECURSIVE + ViewRecursive = 1462, + /// + ///ER_NON_GROUPING_FIELD_USED + NonGroupingFieldUsed = 1463, + /// + ///ER_TABLE_CANT_HANDLE_SPKEYS + TableCannotHandleSpatialKeys = 1464, + /// + ///ER_NO_TRIGGERS_ON_SYSTEM_SCHEMA + NoTriggersOnSystemSchema = 1465, + /// + ///ER_REMOVED_SPACES + RemovedSpaces = 1466, + /// + ///ER_AUTOINC_READ_FAILED + AutoIncrementReadFailed = 1467, + /// + ///ER_USERNAME + UserNameError = 1468, + /// + ///ER_HOSTNAME + HostNameError = 1469, + /// + ///ER_WRONG_STRING_LENGTH + WrongStringLength = 1470, + /// + ///ER_NON_INSERTABLE_TABLE + NonInsertableTable = 1471, + /// + ///ER_ADMIN_WRONG_MRG_TABLE + AdminWrongMergeTable = 1472, + /// + ///ER_TOO_HIGH_LEVEL_OF_NESTING_FOR_SELECT + TooHighLevelOfNestingForSelect = 1473, + /// + ///ER_NAME_BECOMES_EMPTY + NameBecomesEmpty = 1474, + /// + ///ER_AMBIGUOUS_FIELD_TERM + AmbiguousFieldTerm = 1475, + /// + ///ER_FOREIGN_SERVER_EXISTS + ForeignServerExists = 1476, + /// + ///ER_FOREIGN_SERVER_DOESNT_EXIST + ForeignServerDoesNotExist = 1477, + /// + ///ER_ILLEGAL_HA_CREATE_OPTION + IllegalHACreateOption = 1478, + /// + ///ER_PARTITION_REQUIRES_VALUES_ERROR + PartitionRequiresValues = 1479, + /// + ///ER_PARTITION_WRONG_VALUES_ERROR + PartitionWrongValues = 1480, + /// + ///ER_PARTITION_MAXVALUE_ERROR + PartitionMaxValue = 1481, + /// + ///ER_PARTITION_SUBPARTITION_ERROR + PartitionSubPartition = 1482, + /// + ///ER_PARTITION_SUBPART_MIX_ERROR + PartitionSubPartMix = 1483, + /// + ///ER_PARTITION_WRONG_NO_PART_ERROR + PartitionWrongNoPart = 1484, + /// + ///ER_PARTITION_WRONG_NO_SUBPART_ERROR + PartitionWrongNoSubPart = 1485, + /// + ///ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR + WrongExpressionInParitionFunction = 1486, + /// + ///ER_NO_CONST_EXPR_IN_RANGE_OR_LIST_ERROR + NoConstantExpressionInRangeOrListError = 1487, + /// + ///ER_FIELD_NOT_FOUND_PART_ERROR + FieldNotFoundPartitionErrror = 1488, + /// + ///ER_LIST_OF_FIELDS_ONLY_IN_HASH_ERROR + ListOfFieldsOnlyInHash = 1489, + /// + ///ER_INCONSISTENT_PARTITION_INFO_ERROR + InconsistentPartitionInfo = 1490, + /// + ///ER_PARTITION_FUNC_NOT_ALLOWED_ERROR + PartitionFunctionNotAllowed = 1491, + /// + ///ER_PARTITIONS_MUST_BE_DEFINED_ERROR + PartitionsMustBeDefined = 1492, + /// + ///ER_RANGE_NOT_INCREASING_ERROR + RangeNotIncreasing = 1493, + /// + ///ER_INCONSISTENT_TYPE_OF_FUNCTIONS_ERROR + InconsistentTypeOfFunctions = 1494, + /// + ///ER_MULTIPLE_DEF_CONST_IN_LIST_PART_ERROR + MultipleDefinitionsConstantInListPartition = 1495, + /// + ///ER_PARTITION_ENTRY_ERROR + PartitionEntryError = 1496, + /// + ///ER_MIX_HANDLER_ERROR + MixHandlerError = 1497, + /// + ///ER_PARTITION_NOT_DEFINED_ERROR + PartitionNotDefined = 1498, + /// + ///ER_TOO_MANY_PARTITIONS_ERROR + TooManyPartitions = 1499, + /// + ///ER_SUBPARTITION_ERROR + SubPartitionError = 1500, + /// + ///ER_CANT_CREATE_HANDLER_FILE + CannotCreateHandlerFile = 1501, + /// + ///ER_BLOB_FIELD_IN_PART_FUNC_ERROR + BlobFieldInPartitionFunction = 1502, + /// + ///ER_UNIQUE_KEY_NEED_ALL_FIELDS_IN_PF + UniqueKeyNeedAllFieldsInPartitioningFunction = 1503, + /// + ///ER_NO_PARTS_ERROR + NoPartitions = 1504, + /// + ///ER_PARTITION_MGMT_ON_NONPARTITIONED + PartitionManagementOnNoPartitioned = 1505, + /// + ///ER_FOREIGN_KEY_ON_PARTITIONED + ForeignKeyOnPartitioned = 1506, + /// + ///ER_DROP_PARTITION_NON_EXISTENT + DropPartitionNonExistent = 1507, + /// + ///ER_DROP_LAST_PARTITION + DropLastPartition = 1508, + /// + ///ER_COALESCE_ONLY_ON_HASH_PARTITION + CoalesceOnlyOnHashPartition = 1509, + /// + ///ER_REORG_HASH_ONLY_ON_SAME_NO + ReorganizeHashOnlyOnSameNumber = 1510, + /// + ///ER_REORG_NO_PARAM_ERROR + ReorganizeNoParameter = 1511, + /// + ///ER_ONLY_ON_RANGE_LIST_PARTITION + OnlyOnRangeListPartition = 1512, + /// + ///ER_ADD_PARTITION_SUBPART_ERROR + AddPartitionSubPartition = 1513, + /// + ///ER_ADD_PARTITION_NO_NEW_PARTITION + AddPartitionNoNewPartition = 1514, + /// + ///ER_COALESCE_PARTITION_NO_PARTITION + CoalescePartitionNoPartition = 1515, + /// + ///ER_REORG_PARTITION_NOT_EXIST + ReorganizePartitionNotExist = 1516, + /// + ///ER_SAME_NAME_PARTITION + SameNamePartition = 1517, + /// + ///ER_NO_BINLOG_ERROR + NoBinLog = 1518, + /// + ///ER_CONSECUTIVE_REORG_PARTITIONS + ConsecutiveReorganizePartitions = 1519, + /// + ///ER_REORG_OUTSIDE_RANGE + ReorganizeOutsideRange = 1520, + /// + ///ER_PARTITION_FUNCTION_FAILURE + PartitionFunctionFailure = 1521, + /// + ///ER_PART_STATE_ERROR + PartitionStateError = 1522, + /// + ///ER_LIMITED_PART_RANGE + LimitedPartitionRange = 1523, + /// + ///ER_PLUGIN_IS_NOT_LOADED + PluginIsNotLoaded = 1524, + /// + ///ER_WRONG_VALUE + WrongValue = 1525, + /// + ///ER_NO_PARTITION_FOR_GIVEN_VALUE + NoPartitionForGivenValue = 1526, + /// + ///ER_FILEGROUP_OPTION_ONLY_ONCE + FileGroupOptionOnlyOnce = 1527, + /// + ///ER_CREATE_FILEGROUP_FAILED + CreateFileGroupFailed = 1528, + /// + ///ER_DROP_FILEGROUP_FAILED + DropFileGroupFailed = 1529, + /// + ///ER_TABLESPACE_AUTO_EXTEND_ERROR + TableSpaceAutoExtend = 1530, + /// + ///ER_WRONG_SIZE_NUMBER + WrongSizeNumber = 1531, + /// + ///ER_SIZE_OVERFLOW_ERROR + SizeOverflow = 1532, + /// + ///ER_ALTER_FILEGROUP_FAILED + AlterFileGroupFailed = 1533, + /// + ///ER_BINLOG_ROW_LOGGING_FAILED + BinLogRowLogginFailed = 1534, + /// + ///ER_BINLOG_ROW_WRONG_TABLE_DEF + BinLogRowWrongTableDefinition = 1535, + /// + ///ER_BINLOG_ROW_RBR_TO_SBR + BinLogRowRBRToSBR = 1536, + /// + ///ER_EVENT_ALREADY_EXISTS + EventAlreadyExists = 1537, + /// + ///ER_EVENT_STORE_FAILED + EventStoreFailed = 1538, + /// + ///ER_EVENT_DOES_NOT_EXIST + EventDoesNotExist = 1539, + /// + ///ER_EVENT_CANT_ALTER + EventCannotAlter = 1540, + /// + ///ER_EVENT_DROP_FAILED + EventDropFailed = 1541, + /// + ///ER_EVENT_INTERVAL_NOT_POSITIVE_OR_TOO_BIG + EventIntervalNotPositiveOrTooBig = 1542, + /// + ///ER_EVENT_ENDS_BEFORE_STARTS + EventEndsBeforeStarts = 1543, + /// + ///ER_EVENT_EXEC_TIME_IN_THE_PAST + EventExecTimeInThePast = 1544, + /// + ///ER_EVENT_OPEN_TABLE_FAILED + EventOpenTableFailed = 1545, + /// + ///ER_EVENT_NEITHER_M_EXPR_NOR_M_AT + EventNeitherMExpresssionNorMAt = 1546, + /// + ///ER_COL_COUNT_DOESNT_MATCH_CORRUPTED + ColumnCountDoesNotMatchCorrupted = 1547, + /// + ///ER_CANNOT_LOAD_FROM_TABLE + CannotLoadFromTable = 1548, + /// + ///ER_EVENT_CANNOT_DELETE + EventCannotDelete = 1549, + /// + ///ER_EVENT_COMPILE_ERROR + EventCompileError = 1550, + /// + ///ER_EVENT_SAME_NAME + EventSameName = 1551, + /// + ///ER_EVENT_DATA_TOO_LONG + EventDataTooLong = 1552, + /// + ///ER_DROP_INDEX_FK + DropIndexForeignKey = 1553, + /// + ///ER_WARN_DEPRECATED_SYNTAX_WITH_VER + WarningDeprecatedSyntaxWithVersion = 1554, + /// + ///ER_CANT_WRITE_LOCK_LOG_TABLE + CannotWriteLockLogTable = 1555, + /// + ///ER_CANT_LOCK_LOG_TABLE + CannotLockLogTable = 1556, + /// + ///ER_FOREIGN_DUPLICATE_KEY + ForeignDuplicateKey = 1557, + /// + ///ER_COL_COUNT_DOESNT_MATCH_PLEASE_UPDATE + ColumnCountDoesNotMatchPleaseUpdate = 1558, + /// + ///ER_TEMP_TABLE_PREVENTS_SWITCH_OUT_OF_RBR + TemoraryTablePreventSwitchOutOfRBR = 1559, + /// + ///ER_STORED_FUNCTION_PREVENTS_SWITCH_BINLOG_FORMAT + StoredFunctionPreventsSwitchBinLogFormat = 1560, + /// + ///ER_NDB_CANT_SWITCH_BINLOG_FORMAT + NDBCannotSwitchBinLogFormat = 1561, + /// + ///ER_PARTITION_NO_TEMPORARY + PartitionNoTemporary = 1562, + /// + ///ER_PARTITION_CONST_DOMAIN_ERROR + PartitionConstantDomain = 1563, + /// + ///ER_PARTITION_FUNCTION_IS_NOT_ALLOWED + PartitionFunctionIsNotAllowed = 1564, + /// + ///ER_DDL_LOG_ERROR + DDLLogError = 1565, + /// + ///ER_NULL_IN_VALUES_LESS_THAN + NullInValuesLessThan = 1566, + /// + ///ER_WRONG_PARTITION_NAME + WrongPartitionName = 1567, + /// + ///ER_CANT_CHANGE_TRANSACTION_ISOLATION + CannotChangeTransactionIsolation = 1568, + /// + ///ER_DUP_ENTRY_AUTOINCREMENT_CASE + DuplicateEntryAutoIncrementCase = 1569, + /// + ///ER_EVENT_MODIFY_QUEUE_ERROR + EventModifyQueueError = 1570, + /// + ///ER_EVENT_SET_VAR_ERROR + EventSetVariableError = 1571, + /// + ///ER_PARTITION_MERGE_ERROR + PartitionMergeError = 1572, + /// + ///ER_CANT_ACTIVATE_LOG + CannotActivateLog = 1573, + /// + ///ER_RBR_NOT_AVAILABLE + RBRNotAvailable = 1574, + /// + ///ER_BASE64_DECODE_ERROR + Base64DecodeError = 1575, + /// + ///ER_EVENT_RECURSION_FORBIDDEN + EventRecursionForbidden = 1576, + /// + ///ER_EVENTS_DB_ERROR + EventsDatabaseError = 1577, + /// + ///ER_ONLY_INTEGERS_ALLOWED + OnlyIntegersAllowed = 1578, + /// + ///ER_UNSUPORTED_LOG_ENGINE + UnsupportedLogEngine = 1579, + /// + ///ER_BAD_LOG_STATEMENT + BadLogStatement = 1580, + /// + ///ER_CANT_RENAME_LOG_TABLE + CannotRenameLogTable = 1581, + /// + ///ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT + WrongParameterCountToNativeFCT = 1582, + /// + ///ER_WRONG_PARAMETERS_TO_NATIVE_FCT + WrongParametersToNativeFCT = 1583, + /// + ///ER_WRONG_PARAMETERS_TO_STORED_FCT + WrongParametersToStoredFCT = 1584, + /// + ///ER_NATIVE_FCT_NAME_COLLISION + NativeFCTNameCollision = 1585, + /// + ///ER_DUP_ENTRY_WITH_KEY_NAME + DuplicateEntryWithKeyName = 1586, + /// + ///ER_BINLOG_PURGE_EMFILE + BinLogPurgeEMFile = 1587, + /// + ///ER_EVENT_CANNOT_CREATE_IN_THE_PAST + EventCannotCreateInThePast = 1588, + /// + ///ER_EVENT_CANNOT_ALTER_IN_THE_PAST + EventCannotAlterInThePast = 1589, + /// + ///ER_REPLICA_INCIDENT + ReplicaIncident = 1590, + /// + ///ER_NO_PARTITION_FOR_GIVEN_VALUE_SILENT + NoPartitionForGivenValueSilent = 1591, + /// + ///ER_BINLOG_UNSAFE_STATEMENT + BinLogUnsafeStatement = 1592, + /// + ///ER_REPLICA_FATAL_ERROR + ReplicaFatalError = 1593, + /// + ///ER_REPLICA_RELAY_LOG_READ_FAILURE + ReplicaRelayLogReadFailure = 1594, + /// + ///ER_REPLICA_RELAY_LOG_WRITE_FAILURE + ReplicaRelayLogWriteFailure = 1595, + /// + ///ER_REPLICA_CREATE_EVENT_FAILURE + ReplicaCreateEventFailure = 1596, + /// + ///ER_REPLICA_SOURCE_COM_FAILURE + ReplicaSourceComFailure = 1597, + /// + ///ER_BINLOG_LOGGING_IMPOSSIBLE + BinLogLoggingImpossible = 1598, + /// + ///ER_VIEW_NO_CREATION_CTX + ViewNoCreationContext = 1599, + /// + ///ER_VIEW_INVALID_CREATION_CTX + ViewInvalidCreationContext = 1600, + /// + ///ER_SR_INVALID_CREATION_CTX + StoredRoutineInvalidCreateionContext = 1601, + /// + ///ER_TRG_CORRUPTED_FILE + TiggerCorruptedFile = 1602, + /// + ///ER_TRG_NO_CREATION_CTX + TriggerNoCreationContext = 1603, + /// + ///ER_TRG_INVALID_CREATION_CTX + TriggerInvalidCreationContext = 1604, + /// + ///ER_EVENT_INVALID_CREATION_CTX + EventInvalidCreationContext = 1605, + /// + ///ER_TRG_CANT_OPEN_TABLE + TriggerCannotOpenTable = 1606, + /// + ///ER_CANT_CREATE_SROUTINE + CannoCreateSubRoutine = 1607, + /// + ///ER_REPLICA_AMBIGOUS_EXEC_MODE + ReplicaAmbiguousExecMode = 1608, + /// + ///ER_NO_FORMAT_DESCRIPTION_EVENT_BEFORE_BINLOG_STATEMENT + NoFormatDescriptionEventBeforeBinLogStatement = 1609, + /// + ///ER_REPLICA_CORRUPT_EVENT + ReplicaCorruptEvent = 1610, + /// + ///ER_LOAD_DATA_INVALID_COLUMN + LoadDataInvalidColumn = 1611, + /// + ///ER_LOG_PURGE_NO_FILE + LogPurgeNoFile = 1612, + /// + ///ER_XA_RBTIMEOUT + XARBTimeout = 1613, + /// + ///ER_XA_RBDEADLOCK + XARBDeadlock = 1614, + /// + ///ER_NEED_REPREPARE + NeedRePrepare = 1615, + /// + ///ER_DELAYED_NOT_SUPPORTED + DelayedNotSupported = 1616, + /// + ///WARN_NO_SOURCE_INFO + WarningNoSourceInfo = 1617, + /// + ///WARN_OPTION_IGNORED + WarningOptionIgnored = 1618, + /// + ///WARN_PLUGIN_DELETE_BUILTIN + WarningPluginDeleteBuiltIn = 1619, + /// + ///WARN_PLUGIN_BUSY + WarningPluginBusy = 1620, + /// + ///ER_VARIABLE_IS_READONLY + VariableIsReadonly = 1621, + /// + ///ER_WARN_ENGINE_TRANSACTION_ROLLBACK + WarningEngineTransactionRollback = 1622, + /// + ///ER_REPLICA_HEARTBEAT_FAILURE + ReplicaHeartbeatFailure = 1623, + /// + ///ER_REPLICA_HEARTBEAT_VALUE_OUT_OF_RANGE + ReplicaHeartbeatValueOutOfRange = 1624, + /// + ///ER_NDB_REPLICATION_SCHEMA_ERROR + NDBReplicationSchemaError = 1625, + /// + ///ER_CONFLICT_FN_PARSE_ERROR + ConflictFunctionParseError = 1626, + /// + ///ER_EXCEPTIONS_WRITE_ERROR + ExcepionsWriteError = 1627, + /// + ///ER_TOO_LONG_TABLE_COMMENT + TooLongTableComment = 1628, + /// + ///ER_TOO_LONG_FIELD_COMMENT + TooLongFieldComment = 1629, + /// + ///ER_FUNC_INEXISTENT_NAME_COLLISION + FunctionInExistentNameCollision = 1630, + /// + ///ER_DATABASE_NAME + DatabaseNameError = 1631, + /// + ///ER_TABLE_NAME + TableNameErrror = 1632, + /// + ///ER_PARTITION_NAME + PartitionNameError = 1633, + /// + ///ER_SUBPARTITION_NAME + SubPartitionNameError = 1634, + /// + ///ER_TEMPORARY_NAME + TemporaryNameError = 1635, + /// + ///ER_RENAMED_NAME + RenamedNameError = 1636, + /// + ///ER_TOO_MANY_CONCURRENT_TRXS + TooManyConcurrentTransactions = 1637, + /// + ///WARN_NON_ASCII_SEPARATOR_NOT_IMPLEMENTED + WarningNonASCIISeparatorNotImplemented = 1638, + /// + ///ER_DEBUG_SYNC_TIMEOUT + DebugSyncTimeout = 1639, + /// + ///ER_DEBUG_SYNC_HIT_LIMIT + DebugSyncHitLimit = 1640, + /// + ///ER_ERROR_LAST + ErrorLast = 1640, + /// + ///ER_CLIENT_INTERACTION_TIMEOUT + ErrorClientInteractionTimeout = 4031 + } +} diff --git a/MySQL.Data/src/MySqlHelper.cs b/MySQL.Data/src/MySqlHelper.cs index b1891556e..9545a44f4 100644 --- a/MySQL.Data/src/MySqlHelper.cs +++ b/MySQL.Data/src/MySqlHelper.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2004, 2023, Oracle and/or its affiliates. +// Copyright (c) 2004, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/MySqlPacket.cs b/MySQL.Data/src/MySqlPacket.cs index cfe054174..70d4f7c45 100644 --- a/MySQL.Data/src/MySqlPacket.cs +++ b/MySQL.Data/src/MySqlPacket.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2004, 2023, Oracle and/or its affiliates. +// Copyright © 2004, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/MySqlParameter.cs b/MySQL.Data/src/MySqlParameter.cs index 1170afb30..5e9b95c88 100644 --- a/MySQL.Data/src/MySqlParameter.cs +++ b/MySQL.Data/src/MySqlParameter.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2004, 2022, Oracle and/or its affiliates. +// Copyright © 2004, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/MySqlParameterCollection.cs b/MySQL.Data/src/MySqlParameterCollection.cs index 5a530a597..54a1792a3 100644 --- a/MySQL.Data/src/MySqlParameterCollection.cs +++ b/MySQL.Data/src/MySqlParameterCollection.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2004, 2022, Oracle and/or its affiliates. +// Copyright © 2004, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/MySqlPool.cs b/MySQL.Data/src/MySqlPool.cs index a92dc0625..98f28750f 100644 --- a/MySQL.Data/src/MySqlPool.cs +++ b/MySQL.Data/src/MySqlPool.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2004, 2022, Oracle and/or its affiliates. +// Copyright © 2004, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/MySqlPoolManager.cs b/MySQL.Data/src/MySqlPoolManager.cs index 7ee452d25..0ad123d06 100644 --- a/MySQL.Data/src/MySqlPoolManager.cs +++ b/MySQL.Data/src/MySqlPoolManager.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2004, 2023, Oracle and/or its affiliates. +// Copyright © 2004, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -281,4 +281,4 @@ internal static void ReleaseDemotedHosts(object state) DemotedServersTimer.Change(DEMOTED_TIMEOUT, Timeout.Infinite); } } -} \ No newline at end of file +} diff --git a/MySQL.Data/src/MySqlScript.cs b/MySQL.Data/src/MySqlScript.cs index acd54537d..ec116addf 100644 --- a/MySQL.Data/src/MySqlScript.cs +++ b/MySQL.Data/src/MySqlScript.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2004, 2019, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2004, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/MySqlStream.cs b/MySQL.Data/src/MySqlStream.cs index cb2e2726f..f8de9c65d 100644 --- a/MySQL.Data/src/MySqlStream.cs +++ b/MySQL.Data/src/MySqlStream.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2004, 2023, Oracle and/or its affiliates. +// Copyright © 2004, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/MySqlTrace.cs b/MySQL.Data/src/MySqlTrace.cs index 2a10dd575..bd35cdff9 100644 --- a/MySQL.Data/src/MySqlTrace.cs +++ b/MySQL.Data/src/MySqlTrace.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2009, 2022, Oracle and/or its affiliates. +// Copyright © 2009, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/MySqlTransaction.cs b/MySQL.Data/src/MySqlTransaction.cs index bfbd1fca0..d550763dc 100644 --- a/MySQL.Data/src/MySqlTransaction.cs +++ b/MySQL.Data/src/MySqlTransaction.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2004, 2022, Oracle and/or its affiliates. +// Copyright © 2004, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/MysqlDefs.cs b/MySQL.Data/src/MysqlDefs.cs index 4e25e56e2..a81c20711 100644 --- a/MySQL.Data/src/MysqlDefs.cs +++ b/MySQL.Data/src/MysqlDefs.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2004, 2022, Oracle and/or its affiliates. +// Copyright © 2004, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/NativeDriver.cs b/MySQL.Data/src/NativeDriver.cs index c7f518b19..b6d6f860b 100644 --- a/MySQL.Data/src/NativeDriver.cs +++ b/MySQL.Data/src/NativeDriver.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2004, 2023, Oracle and/or its affiliates. +// Copyright © 2004, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/OkPacket.cs b/MySQL.Data/src/OkPacket.cs index 0a8d101cf..57e07a360 100644 --- a/MySQL.Data/src/OkPacket.cs +++ b/MySQL.Data/src/OkPacket.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/PerformanceMonitor.cs b/MySQL.Data/src/PerformanceMonitor.cs index eeb239c7c..b4d93afc6 100644 --- a/MySQL.Data/src/PerformanceMonitor.cs +++ b/MySQL.Data/src/PerformanceMonitor.cs @@ -1,52 +1,52 @@ -// Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using System; -using System.Diagnostics; - - -namespace MySql.Data.MySqlClient -{ - internal class PerformanceMonitor - { - public PerformanceMonitor(MySqlConnection connection) - { - Connection = connection; - } - - public MySqlConnection Connection { get; private set; } - - public virtual void AddHardProcedureQuery() - { - } - - public virtual void AddSoftProcedureQuery() - { - } - } -} \ No newline at end of file +// Copyright © 2004, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using System; +using System.Diagnostics; + + +namespace MySql.Data.MySqlClient +{ + internal class PerformanceMonitor + { + public PerformanceMonitor(MySqlConnection connection) + { + Connection = connection; + } + + public MySqlConnection Connection { get; private set; } + + public virtual void AddHardProcedureQuery() + { + } + + public virtual void AddSoftProcedureQuery() + { + } + } +} diff --git a/MySQL.Data/src/PreparableStatement.cs b/MySQL.Data/src/PreparableStatement.cs index 68565114a..02a7762e8 100644 --- a/MySQL.Data/src/PreparableStatement.cs +++ b/MySQL.Data/src/PreparableStatement.cs @@ -1,258 +1,258 @@ -// Copyright (c) 2004, 2022, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySql.Data.Common; -using System; -using System.Collections; -using System.Collections.Generic; -using System.Data; -using System.Text; -using System.Threading.Tasks; - -namespace MySql.Data.MySqlClient -{ - /// - /// Summary description for PreparedStatement. - /// - internal class PreparableStatement : Statement - { - BitArray _nullMap; - readonly List _parametersToSend = new List(); - MySqlPacket _packet; - int _dataPosition; - int _nullMapPosition; - - const int PARAMETER_COUNT_AVAILABLE = 0x08; // QueryAttributes should be sent to the server - - public PreparableStatement(MySqlCommand command, string text) - : base(command, text) - { - } - - #region Properties - - public int ExecutionCount { get; set; } - - public bool IsPrepared => StatementId > 0; - - public int StatementId { get; private set; } - - #endregion - - public async Task PrepareAsync(bool execAsync) - { - // strip out names from parameter markers - string text; - List parameterNames = PrepareCommandText(out text); - - // ask our connection to send the prepare command - var result = await Driver.PrepareStatementAsync(text, execAsync).ConfigureAwait(false); - StatementId = result.Item1; - MySqlField[] paramList = result.Item2; - - // now we need to assign our field names since we stripped them out - // for the prepare - for (int i = 0; i < parameterNames.Count; i++) - { - string parameterName = (string)parameterNames[i]; - MySqlParameter p = Parameters.GetParameterFlexible(parameterName, false); - if (p == null) - throw new InvalidOperationException( - String.Format(Resources.ParameterNotFoundDuringPrepare, parameterName)); - p.Encoding = paramList[i].Encoding; - _parametersToSend.Add(p); - } - - if (Attributes.Count > 0 && !Driver.SupportsQueryAttributes) - MySqlTrace.LogWarning(Connection.ServerThread, string.Format(Resources.QueryAttributesNotSupported, Driver.Version)); - - _packet = new MySqlPacket(Driver.Encoding); - - // write out some values that do not change run to run - _packet.WriteByte(0); - await _packet.WriteIntegerAsync(StatementId, 4, execAsync).ConfigureAwait(false); - // flags; if server supports query attributes, then set PARAMETER_COUNT_AVAILABLE (0x08) in the flags block - int flags = Driver.SupportsQueryAttributes && Driver.Version.isAtLeast(8, 0, 26) ? PARAMETER_COUNT_AVAILABLE : 0; - await _packet.WriteIntegerAsync(flags, 1, execAsync).ConfigureAwait(false); - await _packet.WriteIntegerAsync(1, 4, execAsync).ConfigureAwait(false); // iteration count; 1 for 4.1 - int num_params = paramList != null ? paramList.Length : 0; - // we don't send QA with PS when MySQL Server is not at least 8.0.26 - if (!Driver.Version.isAtLeast(8, 0, 26) && Attributes.Count > 0) - { - MySqlTrace.LogWarning(Connection.ServerThread, Resources.QueryAttributesNotSupportedByCnet); - Attributes.Clear(); - } - - if (num_params > 0 || - (Driver.SupportsQueryAttributes && flags == PARAMETER_COUNT_AVAILABLE)) // if num_params > 0 - { - int paramCount = num_params; - - if (Driver.SupportsQueryAttributes) // if CLIENT_QUERY_ATTRIBUTES is on - { - paramCount += Attributes.Count; - await _packet.WriteLengthAsync(paramCount, execAsync).ConfigureAwait(false); - } - - if (paramCount > 0) - { - // now prepare our null map - _nullMap = new BitArray(paramCount); - int numNullBytes = (_nullMap.Length + 7) / 8; - _nullMapPosition = _packet.Position; - _packet.Position += numNullBytes; // leave room for our null map - _packet.WriteByte(1); // new_params_bind_flag - - // write out the parameter types and names - foreach (MySqlParameter p in _parametersToSend) - { - // parameter type - await _packet.WriteIntegerAsync(p.GetPSType(), 2, execAsync).ConfigureAwait(false); - - // parameter name - if (Driver.SupportsQueryAttributes) // if CLIENT_QUERY_ATTRIBUTES is on - await _packet.WriteLenStringAsync(String.Empty, execAsync).ConfigureAwait(false); - } - - // write out the attributes types and names - foreach (MySqlAttribute a in Attributes) - { - // attribute type - await _packet.WriteIntegerAsync(a.GetPSType(), 2, execAsync).ConfigureAwait(false); - - // attribute name - if (Driver.SupportsQueryAttributes) // if CLIENT_QUERY_ATTRIBUTES is on - await _packet.WriteLenStringAsync(a.AttributeName, execAsync).ConfigureAwait(false); - } - } - } - - _dataPosition = _packet.Position; - } - - public override async Task ExecuteAsync(bool execAsync) - { - // if we are not prepared, then call down to our base - if (!IsPrepared) - { - await base.ExecuteAsync(execAsync).ConfigureAwait(false); - return; - } - - // now write out all non-null values - _packet.Position = _dataPosition; - - // set value for each parameter - for (int i = 0; i < _parametersToSend.Count; i++) - { - MySqlParameter p = _parametersToSend[i]; - _nullMap[i] = (p.Value == DBNull.Value || p.Value == null) || - p.Direction == ParameterDirection.Output; - if (_nullMap[i]) continue; - _packet.Encoding = p.Encoding; - await p.SerializeAsync(_packet, true, Connection.Settings, execAsync).ConfigureAwait(false); - } - - // // set value for each attribute - for (int i = 0; i < Attributes.Count; i++) - { - MySqlAttribute attr = Attributes[i]; - _nullMap[i] = (attr.Value == DBNull.Value || attr.Value == null); - if (_nullMap[i]) continue; - await attr.SerializeAsync(_packet, true, Connection.Settings, execAsync).ConfigureAwait(false); - } - - if (_nullMap != null) - { - byte[] tempByteArray = new byte[(_nullMap.Length + 7) >> 3]; - _nullMap.CopyTo(tempByteArray, 0); - - Array.Copy(tempByteArray, 0, _packet.Buffer, _nullMapPosition, tempByteArray.Length); - } - - ExecutionCount++; - - await Driver.ExecuteStatementAsync(_packet, execAsync).ConfigureAwait(false); - } - - public override async Task ExecuteNextAsync(bool execAsync) - { - if (!IsPrepared) - return await base.ExecuteNextAsync(execAsync).ConfigureAwait(false); - return false; - } - - /// - /// Prepares CommandText for use with the Prepare method - /// - /// Command text stripped of all paramter names - /// - /// Takes the output of TokenizeSql and creates a single string of SQL - /// that only contains '?' markers for each parameter. It also creates - /// the parameterMap array list that includes all the paramter names in the - /// order they appeared in the SQL - /// - private List PrepareCommandText(out string stripped_sql) - { - StringBuilder newSQL = new StringBuilder(); - List parameterMap = new List(); - - int startPos = 0; - string sql = ResolvedCommandText; - MySqlTokenizer tokenizer = new MySqlTokenizer(sql); - string parameter = tokenizer.NextParameter(); - int paramIndex = 0; - while (parameter != null) - { - if (parameter.IndexOf(StoredProcedure.ParameterPrefix) == -1) - { - newSQL.Append(sql.Substring(startPos, tokenizer.StartIndex - startPos)); - newSQL.Append("?"); - if (parameter.Length == 1 && tokenizer.IsParameterMarker(parameter.ToCharArray()[0])) - parameterMap.Add(Parameters[paramIndex].ParameterName); - else - parameterMap.Add(parameter); - startPos = tokenizer.StopIndex; - } - parameter = tokenizer.NextParameter(); - paramIndex++; - } - newSQL.Append(sql.Substring(startPos)); - stripped_sql = newSQL.ToString(); - return parameterMap; - } - - public virtual async Task CloseStatementAsync(bool execAsync) - { - if (!IsPrepared) return; - - await Driver.CloseStatementAsync(StatementId, execAsync).ConfigureAwait(false); - StatementId = 0; - } - } -} +// Copyright © 2004, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySql.Data.Common; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Data; +using System.Text; +using System.Threading.Tasks; + +namespace MySql.Data.MySqlClient +{ + /// + /// Summary description for PreparedStatement. + /// + internal class PreparableStatement : Statement + { + BitArray _nullMap; + readonly List _parametersToSend = new List(); + MySqlPacket _packet; + int _dataPosition; + int _nullMapPosition; + + const int PARAMETER_COUNT_AVAILABLE = 0x08; // QueryAttributes should be sent to the server + + public PreparableStatement(MySqlCommand command, string text) + : base(command, text) + { + } + + #region Properties + + public int ExecutionCount { get; set; } + + public bool IsPrepared => StatementId > 0; + + public int StatementId { get; private set; } + + #endregion + + public async Task PrepareAsync(bool execAsync) + { + // strip out names from parameter markers + string text; + List parameterNames = PrepareCommandText(out text); + + // ask our connection to send the prepare command + var result = await Driver.PrepareStatementAsync(text, execAsync).ConfigureAwait(false); + StatementId = result.Item1; + MySqlField[] paramList = result.Item2; + + // now we need to assign our field names since we stripped them out + // for the prepare + for (int i = 0; i < parameterNames.Count; i++) + { + string parameterName = (string)parameterNames[i]; + MySqlParameter p = Parameters.GetParameterFlexible(parameterName, false); + if (p == null) + throw new InvalidOperationException( + String.Format(Resources.ParameterNotFoundDuringPrepare, parameterName)); + p.Encoding = paramList[i].Encoding; + _parametersToSend.Add(p); + } + + if (Attributes.Count > 0 && !Driver.SupportsQueryAttributes) + MySqlTrace.LogWarning(Connection.ServerThread, string.Format(Resources.QueryAttributesNotSupported, Driver.Version)); + + _packet = new MySqlPacket(Driver.Encoding); + + // write out some values that do not change run to run + _packet.WriteByte(0); + await _packet.WriteIntegerAsync(StatementId, 4, execAsync).ConfigureAwait(false); + // flags; if server supports query attributes, then set PARAMETER_COUNT_AVAILABLE (0x08) in the flags block + int flags = Driver.SupportsQueryAttributes && Driver.Version.isAtLeast(8, 0, 26) ? PARAMETER_COUNT_AVAILABLE : 0; + await _packet.WriteIntegerAsync(flags, 1, execAsync).ConfigureAwait(false); + await _packet.WriteIntegerAsync(1, 4, execAsync).ConfigureAwait(false); // iteration count; 1 for 4.1 + int num_params = paramList != null ? paramList.Length : 0; + // we don't send QA with PS when MySQL Server is not at least 8.0.26 + if (!Driver.Version.isAtLeast(8, 0, 26) && Attributes.Count > 0) + { + MySqlTrace.LogWarning(Connection.ServerThread, Resources.QueryAttributesNotSupportedByCnet); + Attributes.Clear(); + } + + if (num_params > 0 || + (Driver.SupportsQueryAttributes && flags == PARAMETER_COUNT_AVAILABLE)) // if num_params > 0 + { + int paramCount = num_params; + + if (Driver.SupportsQueryAttributes) // if CLIENT_QUERY_ATTRIBUTES is on + { + paramCount += Attributes.Count; + await _packet.WriteLengthAsync(paramCount, execAsync).ConfigureAwait(false); + } + + if (paramCount > 0) + { + // now prepare our null map + _nullMap = new BitArray(paramCount); + int numNullBytes = (_nullMap.Length + 7) / 8; + _nullMapPosition = _packet.Position; + _packet.Position += numNullBytes; // leave room for our null map + _packet.WriteByte(1); // new_params_bind_flag + + // write out the parameter types and names + foreach (MySqlParameter p in _parametersToSend) + { + // parameter type + await _packet.WriteIntegerAsync(p.GetPSType(), 2, execAsync).ConfigureAwait(false); + + // parameter name + if (Driver.SupportsQueryAttributes) // if CLIENT_QUERY_ATTRIBUTES is on + await _packet.WriteLenStringAsync(String.Empty, execAsync).ConfigureAwait(false); + } + + // write out the attributes types and names + foreach (MySqlAttribute a in Attributes) + { + // attribute type + await _packet.WriteIntegerAsync(a.GetPSType(), 2, execAsync).ConfigureAwait(false); + + // attribute name + if (Driver.SupportsQueryAttributes) // if CLIENT_QUERY_ATTRIBUTES is on + await _packet.WriteLenStringAsync(a.AttributeName, execAsync).ConfigureAwait(false); + } + } + } + + _dataPosition = _packet.Position; + } + + public override async Task ExecuteAsync(bool execAsync) + { + // if we are not prepared, then call down to our base + if (!IsPrepared) + { + await base.ExecuteAsync(execAsync).ConfigureAwait(false); + return; + } + + // now write out all non-null values + _packet.Position = _dataPosition; + + // set value for each parameter + for (int i = 0; i < _parametersToSend.Count; i++) + { + MySqlParameter p = _parametersToSend[i]; + _nullMap[i] = (p.Value == DBNull.Value || p.Value == null) || + p.Direction == ParameterDirection.Output; + if (_nullMap[i]) continue; + _packet.Encoding = p.Encoding; + await p.SerializeAsync(_packet, true, Connection.Settings, execAsync).ConfigureAwait(false); + } + + // // set value for each attribute + for (int i = 0; i < Attributes.Count; i++) + { + MySqlAttribute attr = Attributes[i]; + _nullMap[i] = (attr.Value == DBNull.Value || attr.Value == null); + if (_nullMap[i]) continue; + await attr.SerializeAsync(_packet, true, Connection.Settings, execAsync).ConfigureAwait(false); + } + + if (_nullMap != null) + { + byte[] tempByteArray = new byte[(_nullMap.Length + 7) >> 3]; + _nullMap.CopyTo(tempByteArray, 0); + + Array.Copy(tempByteArray, 0, _packet.Buffer, _nullMapPosition, tempByteArray.Length); + } + + ExecutionCount++; + + await Driver.ExecuteStatementAsync(_packet, execAsync).ConfigureAwait(false); + } + + public override async Task ExecuteNextAsync(bool execAsync) + { + if (!IsPrepared) + return await base.ExecuteNextAsync(execAsync).ConfigureAwait(false); + return false; + } + + /// + /// Prepares CommandText for use with the Prepare method + /// + /// Command text stripped of all paramter names + /// + /// Takes the output of TokenizeSql and creates a single string of SQL + /// that only contains '?' markers for each parameter. It also creates + /// the parameterMap array list that includes all the paramter names in the + /// order they appeared in the SQL + /// + private List PrepareCommandText(out string stripped_sql) + { + StringBuilder newSQL = new StringBuilder(); + List parameterMap = new List(); + + int startPos = 0; + string sql = ResolvedCommandText; + MySqlTokenizer tokenizer = new MySqlTokenizer(sql); + string parameter = tokenizer.NextParameter(); + int paramIndex = 0; + while (parameter != null) + { + if (parameter.IndexOf(StoredProcedure.ParameterPrefix) == -1) + { + newSQL.Append(sql.Substring(startPos, tokenizer.StartIndex - startPos)); + newSQL.Append("?"); + if (parameter.Length == 1 && tokenizer.IsParameterMarker(parameter.ToCharArray()[0])) + parameterMap.Add(Parameters[paramIndex].ParameterName); + else + parameterMap.Add(parameter); + startPos = tokenizer.StopIndex; + } + parameter = tokenizer.NextParameter(); + paramIndex++; + } + newSQL.Append(sql.Substring(startPos)); + stripped_sql = newSQL.ToString(); + return parameterMap; + } + + public virtual async Task CloseStatementAsync(bool execAsync) + { + if (!IsPrepared) return; + + await Driver.CloseStatementAsync(StatementId, execAsync).ConfigureAwait(false); + StatementId = 0; + } + } +} diff --git a/MySQL.Data/src/ProcedureCache.cs b/MySQL.Data/src/ProcedureCache.cs index 968808608..0a5662f41 100644 --- a/MySQL.Data/src/ProcedureCache.cs +++ b/MySQL.Data/src/ProcedureCache.cs @@ -1,230 +1,230 @@ -// Copyright (c) 2004, 2022, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace MySql.Data.MySqlClient -{ - internal class ProcedureCacheEntry - { - public MySqlSchemaCollection procedure; - public MySqlSchemaCollection parameters; - } - - internal class ProcedureCache - { - private readonly Dictionary _procHash; - private readonly Queue _hashQueue; - private readonly int _maxSize; - - public ProcedureCache(int size) - { - _maxSize = size; - _hashQueue = new Queue(_maxSize); - _procHash = new Dictionary(_maxSize); - } - - public async Task GetProcedureAsync(MySqlConnection conn, string spName, string cacheKey, bool execAsync) - { - ProcedureCacheEntry proc = null; - - if (cacheKey != null) - { - int hash = cacheKey.GetHashCode(); - - lock (_procHash) - { - _procHash.TryGetValue(hash, out proc); - } - } - if (proc == null) - { - proc = await AddNewAsync(conn, spName, execAsync).ConfigureAwait(false); - conn.PerfMonitor.AddHardProcedureQuery(); - if (conn.Settings.Logging) - MySqlTrace.LogInformation(conn.ServerThread, - String.Format(Resources.HardProcQuery, spName)); - } - else - { - conn.PerfMonitor.AddSoftProcedureQuery(); - if (conn.Settings.Logging) - MySqlTrace.LogInformation(conn.ServerThread, - String.Format(Resources.SoftProcQuery, spName)); - } - return proc; - } - - internal string GetCacheKey(string spName, ProcedureCacheEntry proc) - { - string retValue = String.Empty; - StringBuilder key = new StringBuilder(spName); - key.Append("("); - string delimiter = ""; - if (proc.parameters != null) - { - foreach (MySqlSchemaRow row in proc.parameters.Rows) - { - if (row["ORDINAL_POSITION"].Equals(0)) - retValue = "?="; - else - { - key.AppendFormat(CultureInfo.InvariantCulture, "{0}?", delimiter); - delimiter = ","; - } - } - } - key.Append(")"); - return retValue + key.ToString(); - } - - private async Task AddNewAsync(MySqlConnection connection, string spName, bool execAsync) - { - ProcedureCacheEntry procData = await GetProcDataAsync(connection, spName, execAsync).ConfigureAwait(false); - - if (_maxSize <= 0) return procData; - - string cacheKey = GetCacheKey(spName, procData); - int hash = cacheKey.GetHashCode(); - lock (_procHash) - { - if (_procHash.Keys.Count >= _maxSize) - TrimHash(); - if (!_procHash.ContainsKey(hash)) - { - _procHash[hash] = procData; - _hashQueue.Enqueue(hash); - } - } - return procData; - } - - private void TrimHash() - { - int oldestHash = _hashQueue.Dequeue(); - _procHash.Remove(oldestHash); - } - - private static async Task GetProcDataAsync(MySqlConnection connection, string spName, bool execAsync) - { - SplitSchemaAndEntity(spName, out string schema, out string entity); - - string[] restrictions = new string[4]; - restrictions[1] = string.IsNullOrEmpty(schema) ? connection.CurrentDatabase() : Utils.UnquoteString(schema); - restrictions[2] = Utils.UnquoteString(entity); - MySqlSchemaCollection proc = connection.GetSchemaCollection("procedures", restrictions); - if (proc.Rows.Count > 1) - throw new MySqlException(Resources.ProcAndFuncSameName); - if (proc.Rows.Count == 0) - { - string msg = string.Format(Resources.InvalidProcName, entity, schema) + " " + - string.Format(Resources.ExecuteProcedureUnauthorized, connection.Settings.UserID, connection.Settings.Server); - throw new MySqlException(msg); - } - - ProcedureCacheEntry entry = new ProcedureCacheEntry(); - entry.procedure = proc; - - // we don't use GetSchema here because that would cause another - // query of procedures and we don't need that since we already - // know the procedure we care about. - ISSchemaProvider isp = new ISSchemaProvider(connection); - string[] rest = isp.CleanRestrictions(restrictions); - MySqlSchemaCollection parameters = await isp.GetProcedureParametersAsync(rest, proc, execAsync).ConfigureAwait(false); - entry.parameters = parameters; - - return entry; - } - - /// - /// Splits the schema and the entity from a syntactically correct "spName"; - /// if there's no schema, then schema will be an empty string. - /// - /// string to inspect. - /// The schema. - /// The entity. - private static void SplitSchemaAndEntity(string spName, out string schema, out string entity) - { - int dotIndex = ExtractDotIndex(spName); - - if (dotIndex != -1) - { - schema = spName.Substring(0, dotIndex); - entity = spName.Substring(dotIndex + 1); - } - else - { - schema = string.Empty; - entity = spName; - } - } - - /// - /// Obtains the dot index that separates the schema from the entity if there's one; - /// otherwise, returns -1. It expects a syntactically correct "spName". - /// - /// string to inspect. - /// Value of the dot index. - /// The dot index. - private static int ExtractDotIndex(string spName, int dotIndex = -1) - { - int backticks, _dotIndexTemp; - _dotIndexTemp = spName.IndexOf('.'); // looks for a '.' in the string passed as argument - string subString; - - if (_dotIndexTemp != -1) - { - subString = spName.Substring(_dotIndexTemp + 1); // gets a substring from the found '.' to the end of the string - backticks = subString.Count(c => c == '`'); // counts backticks in the substring - - // if the count of backticks in the substring is an odd number, - // that means that this '.' is part of the schema or entity and will continue looking; - // otherwise, returns the index. - if (backticks % 2 == 0) - dotIndex = dotIndex == -1 ? _dotIndexTemp : dotIndex + _dotIndexTemp; - else - dotIndex = ExtractDotIndex(subString, _dotIndexTemp + 1); - } - else if (_dotIndexTemp == -1 && dotIndex != -1) - dotIndex = -1; - - return dotIndex; - } - - internal void Clear() - { - _procHash.Clear(); - _hashQueue.Clear(); - } - } -} \ No newline at end of file +// Copyright © 2004, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace MySql.Data.MySqlClient +{ + internal class ProcedureCacheEntry + { + public MySqlSchemaCollection procedure; + public MySqlSchemaCollection parameters; + } + + internal class ProcedureCache + { + private readonly Dictionary _procHash; + private readonly Queue _hashQueue; + private readonly int _maxSize; + + public ProcedureCache(int size) + { + _maxSize = size; + _hashQueue = new Queue(_maxSize); + _procHash = new Dictionary(_maxSize); + } + + public async Task GetProcedureAsync(MySqlConnection conn, string spName, string cacheKey, bool execAsync) + { + ProcedureCacheEntry proc = null; + + if (cacheKey != null) + { + int hash = cacheKey.GetHashCode(); + + lock (_procHash) + { + _procHash.TryGetValue(hash, out proc); + } + } + if (proc == null) + { + proc = await AddNewAsync(conn, spName, execAsync).ConfigureAwait(false); + conn.PerfMonitor.AddHardProcedureQuery(); + if (conn.Settings.Logging) + MySqlTrace.LogInformation(conn.ServerThread, + String.Format(Resources.HardProcQuery, spName)); + } + else + { + conn.PerfMonitor.AddSoftProcedureQuery(); + if (conn.Settings.Logging) + MySqlTrace.LogInformation(conn.ServerThread, + String.Format(Resources.SoftProcQuery, spName)); + } + return proc; + } + + internal string GetCacheKey(string spName, ProcedureCacheEntry proc) + { + string retValue = String.Empty; + StringBuilder key = new StringBuilder(spName); + key.Append("("); + string delimiter = ""; + if (proc.parameters != null) + { + foreach (MySqlSchemaRow row in proc.parameters.Rows) + { + if (row["ORDINAL_POSITION"].Equals(0)) + retValue = "?="; + else + { + key.AppendFormat(CultureInfo.InvariantCulture, "{0}?", delimiter); + delimiter = ","; + } + } + } + key.Append(")"); + return retValue + key.ToString(); + } + + private async Task AddNewAsync(MySqlConnection connection, string spName, bool execAsync) + { + ProcedureCacheEntry procData = await GetProcDataAsync(connection, spName, execAsync).ConfigureAwait(false); + + if (_maxSize <= 0) return procData; + + string cacheKey = GetCacheKey(spName, procData); + int hash = cacheKey.GetHashCode(); + lock (_procHash) + { + if (_procHash.Keys.Count >= _maxSize) + TrimHash(); + if (!_procHash.ContainsKey(hash)) + { + _procHash[hash] = procData; + _hashQueue.Enqueue(hash); + } + } + return procData; + } + + private void TrimHash() + { + int oldestHash = _hashQueue.Dequeue(); + _procHash.Remove(oldestHash); + } + + private static async Task GetProcDataAsync(MySqlConnection connection, string spName, bool execAsync) + { + SplitSchemaAndEntity(spName, out string schema, out string entity); + + string[] restrictions = new string[4]; + restrictions[1] = string.IsNullOrEmpty(schema) ? connection.CurrentDatabase() : Utils.UnquoteString(schema); + restrictions[2] = Utils.UnquoteString(entity); + MySqlSchemaCollection proc = connection.GetSchemaCollection("procedures", restrictions); + if (proc.Rows.Count > 1) + throw new MySqlException(Resources.ProcAndFuncSameName); + if (proc.Rows.Count == 0) + { + string msg = string.Format(Resources.InvalidProcName, entity, schema) + " " + + string.Format(Resources.ExecuteProcedureUnauthorized, connection.Settings.UserID, connection.Settings.Server); + throw new MySqlException(msg); + } + + ProcedureCacheEntry entry = new ProcedureCacheEntry(); + entry.procedure = proc; + + // we don't use GetSchema here because that would cause another + // query of procedures and we don't need that since we already + // know the procedure we care about. + ISSchemaProvider isp = new ISSchemaProvider(connection); + string[] rest = isp.CleanRestrictions(restrictions); + MySqlSchemaCollection parameters = await isp.GetProcedureParametersAsync(rest, proc, execAsync).ConfigureAwait(false); + entry.parameters = parameters; + + return entry; + } + + /// + /// Splits the schema and the entity from a syntactically correct "spName"; + /// if there's no schema, then schema will be an empty string. + /// + /// string to inspect. + /// The schema. + /// The entity. + private static void SplitSchemaAndEntity(string spName, out string schema, out string entity) + { + int dotIndex = ExtractDotIndex(spName); + + if (dotIndex != -1) + { + schema = spName.Substring(0, dotIndex); + entity = spName.Substring(dotIndex + 1); + } + else + { + schema = string.Empty; + entity = spName; + } + } + + /// + /// Obtains the dot index that separates the schema from the entity if there's one; + /// otherwise, returns -1. It expects a syntactically correct "spName". + /// + /// string to inspect. + /// Value of the dot index. + /// The dot index. + private static int ExtractDotIndex(string spName, int dotIndex = -1) + { + int backticks, _dotIndexTemp; + _dotIndexTemp = spName.IndexOf('.'); // looks for a '.' in the string passed as argument + string subString; + + if (_dotIndexTemp != -1) + { + subString = spName.Substring(_dotIndexTemp + 1); // gets a substring from the found '.' to the end of the string + backticks = subString.Count(c => c == '`'); // counts backticks in the substring + + // if the count of backticks in the substring is an odd number, + // that means that this '.' is part of the schema or entity and will continue looking; + // otherwise, returns the index. + if (backticks % 2 == 0) + dotIndex = dotIndex == -1 ? _dotIndexTemp : dotIndex + _dotIndexTemp; + else + dotIndex = ExtractDotIndex(subString, _dotIndexTemp + 1); + } + else if (_dotIndexTemp == -1 && dotIndex != -1) + dotIndex = -1; + + return dotIndex; + } + + internal void Clear() + { + _procHash.Clear(); + _hashQueue.Clear(); + } + } +} diff --git a/MySQL.Data/src/Properties/AssemblyInfo.cs b/MySQL.Data/src/Properties/AssemblyInfo.cs index 6a4877d13..96592b0c2 100644 --- a/MySQL.Data/src/Properties/AssemblyInfo.cs +++ b/MySQL.Data/src/Properties/AssemblyInfo.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2004, 2023, Oracle and/or its affiliates. +// Copyright © 2004, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -88,4 +88,4 @@ [assembly: InternalsVisibleTo("MySql.Data.EntityFrameworkCore, PublicKey = 0024000004800000940000000602000000240000525341310004000001000100d973bda91f71752c78294126974a41a08643168271f65fc0fb3cd45f658da01fbca75ac74067d18e7afbf1467d7a519ce0248b13719717281bb4ddd4ecd71a580dfe0912dfc3690b1d24c7e1975bf7eed90e4ab14e10501eedf763bff8ac204f955c9c15c2cf4ebf6563d8320b6ea8d1ea3807623141f4b81ae30a6c886b3ee1")] [assembly: InternalsVisibleTo("MySql.EntityFrameworkCore.Basic.Tests, PublicKey = 0024000004800000940000000602000000240000525341310004000001000100d973bda91f71752c78294126974a41a08643168271f65fc0fb3cd45f658da01fbca75ac74067d18e7afbf1467d7a519ce0248b13719717281bb4ddd4ecd71a580dfe0912dfc3690b1d24c7e1975bf7eed90e4ab14e10501eedf763bff8ac204f955c9c15c2cf4ebf6563d8320b6ea8d1ea3807623141f4b81ae30a6c886b3ee1")] [assembly: InternalsVisibleTo("MySql.Data.EntityFramework, PublicKey = 0024000004800000940000000602000000240000525341310004000001000100d973bda91f71752c78294126974a41a08643168271f65fc0fb3cd45f658da01fbca75ac74067d18e7afbf1467d7a519ce0248b13719717281bb4ddd4ecd71a580dfe0912dfc3690b1d24c7e1975bf7eed90e4ab14e10501eedf763bff8ac204f955c9c15c2cf4ebf6563d8320b6ea8d1ea3807623141f4b81ae30a6c886b3ee1")] -[assembly: InternalsVisibleTo("MySql.Web.Tests, PublicKey = 0024000004800000940000000602000000240000525341310004000001000100d973bda91f71752c78294126974a41a08643168271f65fc0fb3cd45f658da01fbca75ac74067d18e7afbf1467d7a519ce0248b13719717281bb4ddd4ecd71a580dfe0912dfc3690b1d24c7e1975bf7eed90e4ab14e10501eedf763bff8ac204f955c9c15c2cf4ebf6563d8320b6ea8d1ea3807623141f4b81ae30a6c886b3ee1")] \ No newline at end of file +[assembly: InternalsVisibleTo("MySql.Web.Tests, PublicKey = 0024000004800000940000000602000000240000525341310004000001000100d973bda91f71752c78294126974a41a08643168271f65fc0fb3cd45f658da01fbca75ac74067d18e7afbf1467d7a519ce0248b13719717281bb4ddd4ecd71a580dfe0912dfc3690b1d24c7e1975bf7eed90e4ab14e10501eedf763bff8ac204f955c9c15c2cf4ebf6563d8320b6ea8d1ea3807623141f4b81ae30a6c886b3ee1")] diff --git a/MySQL.Data/src/Properties/VersionInfo.cs b/MySQL.Data/src/Properties/VersionInfo.cs index 3316e3581..ee702c60b 100644 --- a/MySQL.Data/src/Properties/VersionInfo.cs +++ b/MySQL.Data/src/Properties/VersionInfo.cs @@ -1,45 +1,45 @@ -// Copyright (c) 2004, 2023, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using System.Reflection; -using System.Resources; - -// -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Revision and Build Numbers -// by using the '*' as shown below: - -[assembly: AssemblyVersion("8.4.0")] -[assembly: AssemblyInformationalVersion("8.4.0")] -[assembly: NeutralResourcesLanguage("en-US")] \ No newline at end of file +// Copyright © 2004, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using System.Reflection; +using System.Resources; + +// +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Revision and Build Numbers +// by using the '*' as shown below: + +[assembly: AssemblyVersion("8.4.0")] +[assembly: AssemblyInformationalVersion("8.4.0")] +[assembly: NeutralResourcesLanguage("en-US")] diff --git a/MySQL.Data/src/Replication/ReplicationConfiguration.cs b/MySQL.Data/src/Replication/ReplicationConfiguration.cs index 9229717ec..767d1b179 100644 --- a/MySQL.Data/src/Replication/ReplicationConfiguration.cs +++ b/MySQL.Data/src/Replication/ReplicationConfiguration.cs @@ -1,146 +1,146 @@ -// Copyright © 2013, 2020, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using System; -using System.Collections.Generic; -using System.Configuration; -using System.Text; - -namespace MySql.Data.MySqlClient -{ - /// - /// Defines a replication configurarion element in the configuration file. - /// - public sealed class ReplicationConfigurationElement : ConfigurationElement - { - /// - /// Gets a collection of objects representing the server groups. - /// - [ConfigurationProperty("ServerGroups", IsRequired = true)] - [ConfigurationCollection(typeof(ReplicationServerGroupConfigurationElement), AddItemName = "Group")] - public GenericConfigurationElementCollection ServerGroups - { - get { return (GenericConfigurationElementCollection)this["ServerGroups"]; } - } - } - - /// - /// Defines a replication server group in the configuration file. - /// - public sealed class ReplicationServerGroupConfigurationElement : ConfigurationElement - { - /// - /// Gets or sets the name of the replication server group configuration. - /// - [ConfigurationProperty("name", IsRequired = true)] - public string Name - { - get { return (string)this["name"]; } - set { this["name"] = value; } - } - - /// - /// Gets or sets the group type of the replication server group configuration. - /// - [ConfigurationProperty("groupType", IsRequired = false)] - public string GroupType - { - get { return (string)this["groupType"]; } - set { this["groupType"] = value; } - } - - /// - /// Gets or sets the number of seconds to wait for retry. - /// - [ConfigurationProperty("retryTime", IsRequired = false, DefaultValue = 60)] - public int RetryTime - { - get { return (int)this["retryTime"]; } - set { this["retryTime"] = value; } - } - - /// - /// Gets a collection of objects representing the - /// server configurations associated to this group configuration. - /// - [ConfigurationProperty("Servers")] - [ConfigurationCollection(typeof(ReplicationServerConfigurationElement), AddItemName = "Server")] - public GenericConfigurationElementCollection Servers - { - get { return (GenericConfigurationElementCollection)this["Servers"]; } - } - } - - /// - /// Defines a replication server in configuration file. - /// - public sealed class ReplicationServerConfigurationElement : ConfigurationElement - { - /// - /// Gets or sets the name of the replication server configuration. - /// - [ConfigurationProperty("name", IsRequired = true)] - public string Name - { - get { return (string)this["name"]; } - set { this["name"] = value; } - } - - /// - /// Gets or sets whether the replication server is configured as source. - /// - [ConfigurationProperty("IsMaster", IsRequired = false, DefaultValue = false)] - [Obsolete("This property is deprecated, please use IsSource instead.")] - public bool IsMaster - { - get { return (bool)this["IsMaster"]; } - set { this["IsMaster"] = value; } - } - - /// - /// Gets or sets whether the replication server is configured as source. - /// - [ConfigurationProperty("IsSource", IsRequired = false, DefaultValue = false)] - public bool IsSource - { - get { return (bool)this["IsSource"]; } - set { this["IsSource"] = value; } - } - - - /// - /// Gets or sets the connection string associated to this replication server. - /// - [ConfigurationProperty("connectionstring", IsRequired = true)] - public string ConnectionString - { - get { return (string)this["connectionstring"]; } - set { this["connectionstring"] = value; } - } - } -} +// Copyright © 2013, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using System; +using System.Collections.Generic; +using System.Configuration; +using System.Text; + +namespace MySql.Data.MySqlClient +{ + /// + /// Defines a replication configurarion element in the configuration file. + /// + public sealed class ReplicationConfigurationElement : ConfigurationElement + { + /// + /// Gets a collection of objects representing the server groups. + /// + [ConfigurationProperty("ServerGroups", IsRequired = true)] + [ConfigurationCollection(typeof(ReplicationServerGroupConfigurationElement), AddItemName = "Group")] + public GenericConfigurationElementCollection ServerGroups + { + get { return (GenericConfigurationElementCollection)this["ServerGroups"]; } + } + } + + /// + /// Defines a replication server group in the configuration file. + /// + public sealed class ReplicationServerGroupConfigurationElement : ConfigurationElement + { + /// + /// Gets or sets the name of the replication server group configuration. + /// + [ConfigurationProperty("name", IsRequired = true)] + public string Name + { + get { return (string)this["name"]; } + set { this["name"] = value; } + } + + /// + /// Gets or sets the group type of the replication server group configuration. + /// + [ConfigurationProperty("groupType", IsRequired = false)] + public string GroupType + { + get { return (string)this["groupType"]; } + set { this["groupType"] = value; } + } + + /// + /// Gets or sets the number of seconds to wait for retry. + /// + [ConfigurationProperty("retryTime", IsRequired = false, DefaultValue = 60)] + public int RetryTime + { + get { return (int)this["retryTime"]; } + set { this["retryTime"] = value; } + } + + /// + /// Gets a collection of objects representing the + /// server configurations associated to this group configuration. + /// + [ConfigurationProperty("Servers")] + [ConfigurationCollection(typeof(ReplicationServerConfigurationElement), AddItemName = "Server")] + public GenericConfigurationElementCollection Servers + { + get { return (GenericConfigurationElementCollection)this["Servers"]; } + } + } + + /// + /// Defines a replication server in configuration file. + /// + public sealed class ReplicationServerConfigurationElement : ConfigurationElement + { + /// + /// Gets or sets the name of the replication server configuration. + /// + [ConfigurationProperty("name", IsRequired = true)] + public string Name + { + get { return (string)this["name"]; } + set { this["name"] = value; } + } + + /// + /// Gets or sets whether the replication server is configured as source. + /// + [ConfigurationProperty("IsMaster", IsRequired = false, DefaultValue = false)] + [Obsolete("This property is deprecated, please use IsSource instead.")] + public bool IsMaster + { + get { return (bool)this["IsMaster"]; } + set { this["IsMaster"] = value; } + } + + /// + /// Gets or sets whether the replication server is configured as source. + /// + [ConfigurationProperty("IsSource", IsRequired = false, DefaultValue = false)] + public bool IsSource + { + get { return (bool)this["IsSource"]; } + set { this["IsSource"] = value; } + } + + + /// + /// Gets or sets the connection string associated to this replication server. + /// + [ConfigurationProperty("connectionstring", IsRequired = true)] + public string ConnectionString + { + get { return (string)this["connectionstring"]; } + set { this["connectionstring"] = value; } + } + } +} diff --git a/MySQL.Data/src/Replication/ReplicationManager.cs b/MySQL.Data/src/Replication/ReplicationManager.cs index 4c43f44fc..5c0fb0dd1 100644 --- a/MySQL.Data/src/Replication/ReplicationManager.cs +++ b/MySQL.Data/src/Replication/ReplicationManager.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2014, 2023, Oracle and/or its affiliates. +// Copyright © 2014, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/Replication/ReplicationRoundRobinServerGroup.cs b/MySQL.Data/src/Replication/ReplicationRoundRobinServerGroup.cs index 3128beddb..b66a7a2e7 100644 --- a/MySQL.Data/src/Replication/ReplicationRoundRobinServerGroup.cs +++ b/MySQL.Data/src/Replication/ReplicationRoundRobinServerGroup.cs @@ -1,67 +1,67 @@ -// Copyright � 2013, 2020, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using System; -using System.Collections.Generic; -using System.Text; - -namespace MySql.Data.MySqlClient.Replication -{ - /// - /// Class that implements Round Robing Load Balancing technique. - /// - public class ReplicationRoundRobinServerGroup : ReplicationServerGroup - { - private int nextServer; - - public ReplicationRoundRobinServerGroup(string name, int retryTime) : base(name, retryTime) - { - nextServer = -1; - } - - /// - /// Gets an available server based on Round Robin load balancing. - /// - /// Flag indicating if the server to return must be a source. - /// A object representing the next available server. - internal protected override ReplicationServer GetServer(bool isSource) - { - for (int i = 0; i < Servers.Count; i++) - { - nextServer++; - if (nextServer == Servers.Count) - nextServer = 0; - ReplicationServer s = Servers[nextServer]; - if (!s.IsAvailable) continue; - if (isSource && !s.IsSource) continue; - return s; - } - return null; - } - } -} +// Copyright © 2013, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using System; +using System.Collections.Generic; +using System.Text; + +namespace MySql.Data.MySqlClient.Replication +{ + /// + /// Class that implements Round Robing Load Balancing technique. + /// + public class ReplicationRoundRobinServerGroup : ReplicationServerGroup + { + private int nextServer; + + public ReplicationRoundRobinServerGroup(string name, int retryTime) : base(name, retryTime) + { + nextServer = -1; + } + + /// + /// Gets an available server based on Round Robin load balancing. + /// + /// Flag indicating if the server to return must be a source. + /// A object representing the next available server. + internal protected override ReplicationServer GetServer(bool isSource) + { + for (int i = 0; i < Servers.Count; i++) + { + nextServer++; + if (nextServer == Servers.Count) + nextServer = 0; + ReplicationServer s = Servers[nextServer]; + if (!s.IsAvailable) continue; + if (isSource && !s.IsSource) continue; + return s; + } + return null; + } + } +} diff --git a/MySQL.Data/src/Replication/ReplicationServer.cs b/MySQL.Data/src/Replication/ReplicationServer.cs index 07c062bf7..23b616853 100644 --- a/MySQL.Data/src/Replication/ReplicationServer.cs +++ b/MySQL.Data/src/Replication/ReplicationServer.cs @@ -1,70 +1,70 @@ -// Copyright � 2014, 2020, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using System; -using System.Collections.Generic; -using System.Text; - -namespace MySql.Data.MySqlClient.Replication -{ - /// - /// Represents a server in a Replication environment. - /// - public class ReplicationServer - { - public ReplicationServer(string name, bool isSource, string connectionString) - { - Name = name; - IsSource = isSource; - ConnectionString = connectionString; - IsAvailable = true; - } - - /// - /// Gets the server name. - /// - public string Name { get; private set; } - /// - /// Gets a value indicating whether the server is source or replica. - /// - [Obsolete("This property is deprecated please use IsSource instead.")] - public bool IsMaster { get; private set; } - /// - /// Gets a value indicating whether the server is source or replica. - /// - public bool IsSource { get; private set; } - /// - /// Gets the connection string used to connect to the server. - /// - public string ConnectionString { get; internal set; } - /// - /// Gets a flag indicating if the server is available to be considered in load balancing. - /// - public bool IsAvailable { get; set; } - } -} +// Copyright © 2014, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using System; +using System.Collections.Generic; +using System.Text; + +namespace MySql.Data.MySqlClient.Replication +{ + /// + /// Represents a server in a Replication environment. + /// + public class ReplicationServer + { + public ReplicationServer(string name, bool isSource, string connectionString) + { + Name = name; + IsSource = isSource; + ConnectionString = connectionString; + IsAvailable = true; + } + + /// + /// Gets the server name. + /// + public string Name { get; private set; } + /// + /// Gets a value indicating whether the server is source or replica. + /// + [Obsolete("This property is deprecated please use IsSource instead.")] + public bool IsMaster { get; private set; } + /// + /// Gets a value indicating whether the server is source or replica. + /// + public bool IsSource { get; private set; } + /// + /// Gets the connection string used to connect to the server. + /// + public string ConnectionString { get; internal set; } + /// + /// Gets a flag indicating if the server is available to be considered in load balancing. + /// + public bool IsAvailable { get; set; } + } +} diff --git a/MySQL.Data/src/Replication/ReplicationServerGroup.cs b/MySQL.Data/src/Replication/ReplicationServerGroup.cs index 3a23ec27d..cb3e843a5 100644 --- a/MySQL.Data/src/Replication/ReplicationServerGroup.cs +++ b/MySQL.Data/src/Replication/ReplicationServerGroup.cs @@ -1,185 +1,185 @@ -// Copyright (c) 2014, 2020, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - - - -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Text; - -namespace MySql.Data.MySqlClient.Replication -{ - /// - /// Base class used to implement load balancing features. - /// - public abstract class ReplicationServerGroup - { - /// - /// List of servers available for replication. - /// - protected List servers = new List(); - - /// The group name. - /// The number of seconds to perform a retry. - public ReplicationServerGroup(string name, int retryTime) - { - Servers = servers; - Name = name; - RetryTime = retryTime; - } - - /// - /// Gets the group name. - /// - public string Name { get; protected set; } - /// - /// Gets the retry time between connections to failed servers. - /// - public int RetryTime { get; protected set; } - /// - /// Gets the server list in the group. - /// - protected IList Servers { get; private set; } - - /// - /// Adds a server into the group. - /// - /// The server name. - /// A flag indicating if the server to add is source or replica. - /// The connection string used by this server. - /// A object representing the recently added object. - internal protected ReplicationServer AddServer(string name, bool isSource, string connectionString) - { - ReplicationServer server = new ReplicationServer(name, isSource, connectionString); - servers.Add(server); - return server; - } - - /// - /// Removes a server from the group. - /// - /// The server name. - internal protected void RemoveServer(string name) - { - ReplicationServer serverToRemove = GetServer(name); - if (serverToRemove == null) - throw new MySqlException(String.Format(Resources.ReplicationServerNotFound, name)); - servers.Remove(serverToRemove); - } - - /// - /// Gets a server by name. - /// - /// The server name. - /// The replication server. - internal protected ReplicationServer GetServer(string name) - { - foreach (var server in servers) - if (String.Compare(name, server.Name, StringComparison.OrdinalIgnoreCase) == 0) return server; - return null; - } - - /// - /// Must be implemented. Defines the next server for a custom load balancing implementation. - /// - /// Defines if the server to return is a source or any. - /// The next server based on the load balancing implementation. - /// Null if no available server is found. - /// - internal protected abstract ReplicationServer GetServer(bool isSource); - - /// - /// Defines the next server for a custom load balancing implementation. - /// - /// Defines if the server to return is a source or any. - /// Currently not being used. - /// The next server based on the load balancing implementation. - /// Null if no available server is found. - /// - internal protected virtual ReplicationServer GetServer(bool isSource, MySqlConnectionStringBuilder settings) - { - return GetServer(isSource); - } - - /// - /// Handles a failed connection to a server. - /// - /// The failed server. - /// This method can be overrided to implement a custom failover handling. - internal protected virtual void HandleFailover(ReplicationServer server) - { - BackgroundWorker worker = new BackgroundWorker(); - worker.DoWork += delegate(object sender, DoWorkEventArgs e) - { - bool isRunning = false; - ReplicationServer server1 = e.Argument as ReplicationServer; - System.Timers.Timer timer = new System.Timers.Timer(RetryTime * 1000.0); - - System.Timers.ElapsedEventHandler elapsedEvent = delegate(object sender1, System.Timers.ElapsedEventArgs e1) - { - if (isRunning) return; - try - { - isRunning = true; - using (MySqlConnection connectionFailed = new MySqlConnection(server.ConnectionString)) - { - connectionFailed.Open(); - server1.IsAvailable = true; - timer.Stop(); - } - } - catch - { - MySqlTrace.LogWarning(0, - string.Format(Resources.Replication_ConnectionAttemptFailed, server1.Name)); - } - finally - { - isRunning = false; - } - }; - timer.Elapsed += elapsedEvent; - timer.Start(); - elapsedEvent(sender, null); - }; - - worker.RunWorkerAsync(server); - } - - /// - /// Handles a failed connection to a server. - /// - /// The failed server. - /// The exception that caused the failover. - internal protected virtual void HandleFailover(ReplicationServer server, Exception exception) - { - HandleFailover(server); - } - } -} +// Copyright © 2014, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Text; + +namespace MySql.Data.MySqlClient.Replication +{ + /// + /// Base class used to implement load balancing features. + /// + public abstract class ReplicationServerGroup + { + /// + /// List of servers available for replication. + /// + protected List servers = new List(); + + /// The group name. + /// The number of seconds to perform a retry. + public ReplicationServerGroup(string name, int retryTime) + { + Servers = servers; + Name = name; + RetryTime = retryTime; + } + + /// + /// Gets the group name. + /// + public string Name { get; protected set; } + /// + /// Gets the retry time between connections to failed servers. + /// + public int RetryTime { get; protected set; } + /// + /// Gets the server list in the group. + /// + protected IList Servers { get; private set; } + + /// + /// Adds a server into the group. + /// + /// The server name. + /// A flag indicating if the server to add is source or replica. + /// The connection string used by this server. + /// A object representing the recently added object. + internal protected ReplicationServer AddServer(string name, bool isSource, string connectionString) + { + ReplicationServer server = new ReplicationServer(name, isSource, connectionString); + servers.Add(server); + return server; + } + + /// + /// Removes a server from the group. + /// + /// The server name. + internal protected void RemoveServer(string name) + { + ReplicationServer serverToRemove = GetServer(name); + if (serverToRemove == null) + throw new MySqlException(String.Format(Resources.ReplicationServerNotFound, name)); + servers.Remove(serverToRemove); + } + + /// + /// Gets a server by name. + /// + /// The server name. + /// The replication server. + internal protected ReplicationServer GetServer(string name) + { + foreach (var server in servers) + if (String.Compare(name, server.Name, StringComparison.OrdinalIgnoreCase) == 0) return server; + return null; + } + + /// + /// Must be implemented. Defines the next server for a custom load balancing implementation. + /// + /// Defines if the server to return is a source or any. + /// The next server based on the load balancing implementation. + /// Null if no available server is found. + /// + internal protected abstract ReplicationServer GetServer(bool isSource); + + /// + /// Defines the next server for a custom load balancing implementation. + /// + /// Defines if the server to return is a source or any. + /// Currently not being used. + /// The next server based on the load balancing implementation. + /// Null if no available server is found. + /// + internal protected virtual ReplicationServer GetServer(bool isSource, MySqlConnectionStringBuilder settings) + { + return GetServer(isSource); + } + + /// + /// Handles a failed connection to a server. + /// + /// The failed server. + /// This method can be overrided to implement a custom failover handling. + internal protected virtual void HandleFailover(ReplicationServer server) + { + BackgroundWorker worker = new BackgroundWorker(); + worker.DoWork += delegate(object sender, DoWorkEventArgs e) + { + bool isRunning = false; + ReplicationServer server1 = e.Argument as ReplicationServer; + System.Timers.Timer timer = new System.Timers.Timer(RetryTime * 1000.0); + + System.Timers.ElapsedEventHandler elapsedEvent = delegate(object sender1, System.Timers.ElapsedEventArgs e1) + { + if (isRunning) return; + try + { + isRunning = true; + using (MySqlConnection connectionFailed = new MySqlConnection(server.ConnectionString)) + { + connectionFailed.Open(); + server1.IsAvailable = true; + timer.Stop(); + } + } + catch + { + MySqlTrace.LogWarning(0, + string.Format(Resources.Replication_ConnectionAttemptFailed, server1.Name)); + } + finally + { + isRunning = false; + } + }; + timer.Elapsed += elapsedEvent; + timer.Start(); + elapsedEvent(sender, null); + }; + + worker.RunWorkerAsync(server); + } + + /// + /// Handles a failed connection to a server. + /// + /// The failed server. + /// The exception that caused the failover. + internal protected virtual void HandleFailover(ReplicationServer server, Exception exception) + { + HandleFailover(server); + } + } +} diff --git a/MySQL.Data/src/ResourcesX.Designer.cs b/MySQL.Data/src/ResourcesX.Designer.cs index 2802d4afa..86b984d69 100644 --- a/MySQL.Data/src/ResourcesX.Designer.cs +++ b/MySQL.Data/src/ResourcesX.Designer.cs @@ -1,721 +1,721 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.42000 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace MySql.Data { - using System; - - - /// - /// A strongly-typed resource class, for looking up localized strings, etc. - /// - // This class was auto-generated by the StronglyTypedResourceBuilder - // class via a tool like ResGen or Visual Studio. - // To add or remove a member, edit your .ResX file then rerun ResGen - // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class ResourcesX { - - private static global::System.Resources.ResourceManager resourceMan; - - private static global::System.Globalization.CultureInfo resourceCulture; - - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal ResourcesX() { - } - - /// - /// Returns the cached ResourceManager instance used by this class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager { - get { - if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("MySql.Data.ResourcesX", typeof(ResourcesX).Assembly); - resourceMan = temp; - } - return resourceMan; - } - } - - /// - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture { - get { - return resourceCulture; - } - set { - resourceCulture = value; - } - } - - /// - /// Looks up a localized string similar to Appdata path is not defined.. - /// - internal static string AppdataNotDefined { - get { - return ResourceManager.GetString("AppdataNotDefined", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Authentication failed using MYSQL41 and SHA256_MEMORY. Check the user name and password or try using a secure connection.. - /// - internal static string AuthenticationFailed { - get { - return ResourceManager.GetString("AuthenticationFailed", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to You can't get more sessions because Client is closed.. - /// - internal static string ClientIsClosed { - get { - return ResourceManager.GetString("ClientIsClosed", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Client option '{0}' does not support value '{1}'.. - /// - internal static string ClientOptionInvalidValue { - get { - return ResourceManager.GetString("ClientOptionInvalidValue", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Client option '{0}' is not recognized as valid.. - /// - internal static string ClientOptionNotValid { - get { - return ResourceManager.GetString("ClientOptionNotValid", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to {0} '{1}' does not exist in schema '{2}'.. - /// - internal static string CollectionTableDoesNotExist { - get { - return ResourceManager.GetString("CollectionTableDoesNotExist", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Compression requested but the compression algorithm negotiation failed.. - /// - internal static string CompressionAlgorithmNegotiationFailed { - get { - return ResourceManager.GetString("CompressionAlgorithmNegotiationFailed", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Compression using {0} is not supported.. - /// - internal static string CompressionAlgorithmNotSupported { - get { - return ResourceManager.GetString("CompressionAlgorithmNotSupported", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Compression using {0} is not supported in .NET Framework.. - /// - internal static string CompressionForSpecificAlgorithmNotSupportedInNetFramework { - get { - return ResourceManager.GetString("CompressionForSpecificAlgorithmNotSupportedInNetFramework", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The connection property 'compression' acceptable values are: 'preferred', 'required' or 'disabled'. The value '{0}' is not acceptable.. - /// - internal static string CompressionInvalidValue { - get { - return ResourceManager.GetString("CompressionInvalidValue", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Compression is not enabled.. - /// - internal static string CompressionNotEnabled { - get { - return ResourceManager.GetString("CompressionNotEnabled", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Compression requested but the server does not support it.. - /// - internal static string CompressionNotSupportedByServer { - get { - return ResourceManager.GetString("CompressionNotSupportedByServer", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to There are still decompressed messages pending to be processed.. - /// - internal static string CompressionPendingMessagesToProcess { - get { - return ResourceManager.GetString("CompressionPendingMessagesToProcess", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Custom type mapping is only supported from .NET Core 3.1 and later.. - /// - internal static string CustomTypeNotSupported { - get { - return ResourceManager.GetString("CustomTypeNotSupported", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to '{0}' cannot be set to false with DNS SRV lookup enabled.. - /// - internal static string DnsSrvConflictingOptions { - get { - return ResourceManager.GetString("DnsSrvConflictingOptions", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Scheme '{0}' is not valid.. - /// - internal static string DnsSrvInvalidScheme { - get { - return ResourceManager.GetString("DnsSrvInvalidScheme", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The document path cannot be null or an empty string.. - /// - internal static string DocPathNullOrEmpty { - get { - return ResourceManager.GetString("DocPathNullOrEmpty", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Duplicate key '{0}' used in "connection-attributes".. - /// - internal static string DuplicateUserDefinedAttribute { - get { - return ResourceManager.GetString("DuplicateUserDefinedAttribute", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Key name in connection attribute cannot be an empty string.. - /// - internal static string EmptyKeyConnectionAttribute { - get { - return ResourceManager.GetString("EmptyKeyConnectionAttribute", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to At least one option must be specified.. - /// - internal static string EmptyOptions { - get { - return ResourceManager.GetString("EmptyOptions", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to This feature is currently not supported.. - /// - internal static string FeatureNotSupported { - get { - return ResourceManager.GetString("FeatureNotSupported", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to This functionality is only supported in MySQL {0} and higher.. - /// - internal static string FunctionalityNotSupported { - get { - return ResourceManager.GetString("FunctionalityNotSupported", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Collation with id '{0}' not found.. - /// - internal static string InvalidCollationId { - get { - return ResourceManager.GetString("InvalidCollationId", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The value of "connection-attributes" must be either a boolean or a list of key-value pairs.. - /// - internal static string InvalidConnectionAttributes { - get { - return ResourceManager.GetString("InvalidConnectionAttributes", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Connection Data is incorrect.. - /// - internal static string InvalidConnectionData { - get { - return ResourceManager.GetString("InvalidConnectionData", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The connection string is invalid.. - /// - internal static string InvalidConnectionString { - get { - return ResourceManager.GetString("InvalidConnectionString", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to '{0}' is not a valid connection string attribute.. - /// - internal static string InvalidConnectionStringAttribute { - get { - return ResourceManager.GetString("InvalidConnectionStringAttribute", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The connection timeout value must be a positive integer (including 0).. - /// - internal static string InvalidConnectionTimeoutValue { - get { - return ResourceManager.GetString("InvalidConnectionTimeoutValue", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Decimal (BCD) format is invalid.. - /// - internal static string InvalidDecimalFormat { - get { - return ResourceManager.GetString("InvalidDecimalFormat", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Field type with name '{0}' not found.. - /// - internal static string InvalidFieldType { - get { - return ResourceManager.GetString("InvalidFieldType", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Index type with name '{0}' not found.. - /// - internal static string InvalidIndexType { - get { - return ResourceManager.GetString("InvalidIndexType", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The value provided is not a valid JSON document. {0}. - /// - internal static string InvalidJsonDocument { - get { - return ResourceManager.GetString("InvalidJsonDocument", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to {0} is not a valid column name in the row.. - /// - internal static string InvalidNameIndex { - get { - return ResourceManager.GetString("InvalidNameIndex", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to {0} is not a valid index for the row.. - /// - internal static string InvalidRowIndex { - get { - return ResourceManager.GetString("InvalidRowIndex", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Session state is not valid.. - /// - internal static string InvalidSession { - get { - return ResourceManager.GetString("InvalidSession", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Invalid Uri . - /// - internal static string InvalidUriData { - get { - return ResourceManager.GetString("InvalidUriData", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Invalid uri query value. - /// - internal static string InvalidUriQuery { - get { - return ResourceManager.GetString("InvalidUriQuery", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Key names in "connection-attributes" cannot start with "_".. - /// - internal static string InvalidUserDefinedAttribute { - get { - return ResourceManager.GetString("InvalidUserDefinedAttribute", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Json configuration must contain 'uri' or 'host' but not both.. - /// - internal static string JsonUriOrHost { - get { - return ResourceManager.GetString("JsonUriOrHost", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Keyword '{0}' not found.. - /// - internal static string KeywordNotFound { - get { - return ResourceManager.GetString("KeywordNotFound", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Keyword not supported.. - /// - internal static string KeywordNotSupported { - get { - return ResourceManager.GetString("KeywordNotSupported", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Field '{0}' is mandatory.. - /// - internal static string MandatoryFieldNotFound { - get { - return ResourceManager.GetString("MandatoryFieldNotFound", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Missed required schema option.. - /// - internal static string MissingSchemaOption { - get { - return ResourceManager.GetString("MissingSchemaOption", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to More than one document id was generated. Please use the DocumentIds property instead.. - /// - internal static string MoreThanOneDocumentId { - get { - return ResourceManager.GetString("MoreThanOneDocumentId", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to There is no data at index {0}. - /// - internal static string NoDataAtIndex { - get { - return ResourceManager.GetString("NoDataAtIndex", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to No 'host' has been specified.. - /// - internal static string NoHost { - get { - return ResourceManager.GetString("NoHost", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to No more data in resultset.. - /// - internal static string NoMoreData { - get { - return ResourceManager.GetString("NoMoreData", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Object '{0}' not found. - /// - internal static string NoObjectFound { - get { - return ResourceManager.GetString("NoObjectFound", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to No placeholders.. - /// - internal static string NoPlaceholders { - get { - return ResourceManager.GetString("NoPlaceholders", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Connection closed. Reason: connection idle was too long. - /// - internal static string NoticeIdleConnection { - get { - return ResourceManager.GetString("NoticeIdleConnection", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Connection closed. Reason: connection was killed by a different session. - /// - internal static string NoticeKilledConnection { - get { - return ResourceManager.GetString("NoticeKilledConnection", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Connection closed. Reason: server was shutdown. - /// - internal static string NoticeServerShutdown { - get { - return ResourceManager.GetString("NoticeServerShutdown", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to {0} must be a value greater than 0.. - /// - internal static string NumberNotGreaterThanZero { - get { - return ResourceManager.GetString("NumberNotGreaterThanZero", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Path not found '{0}'.. - /// - internal static string PathNotFound { - get { - return ResourceManager.GetString("PathNotFound", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Queue timeout expired. The timeout period elapsed prior to getting a session from the pool.. - /// - internal static string PoolingQueueTimeout { - get { - return ResourceManager.GetString("PoolingQueueTimeout", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Providing a port number as part of the host address isn't supported when using connection strings in basic format or anonymous objects. Use URI format instead.. - /// - internal static string PortNotSupported { - get { - return ResourceManager.GetString("PortNotSupported", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to You must either assign no priority to any of the hosts or give a priority for every host.. - /// - internal static string PriorityForAllOrNoHosts { - get { - return ResourceManager.GetString("PriorityForAllOrNoHosts", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The priority must be between 0 and 100.. - /// - internal static string PriorityOutOfLimits { - get { - return ResourceManager.GetString("PriorityOutOfLimits", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to ProgramData path is not defined.. - /// - internal static string ProgramDataNotDefined { - get { - return ResourceManager.GetString("ProgramDataNotDefined", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Replacement document has an '_id' that is - ///different from the matched document.. - /// - internal static string ReplaceWithNoMatchingId { - get { - return ResourceManager.GetString("ReplaceWithNoMatchingId", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The server doesn't support the requested operation. Please update the MySQL Server, client library, or both.. - /// - internal static string SchemaCreateCollectionMsg { - get { - return ResourceManager.GetString("SchemaCreateCollectionMsg", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The process of closing the resultset and resulted in results being lost.. - /// - internal static string ThrowingAwayResults { - get { - return ResourceManager.GetString("ThrowingAwayResults", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to All server connection attempts were aborted. Timeout of {0} milliseconds was exceeded for each selected server.. - /// - internal static string TimeOutMultipleHost { - get { - return ResourceManager.GetString("TimeOutMultipleHost", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to All server connection attempts were aborted. Timeout was exceeded for each selected server.. - /// - internal static string TimeOutMultipleHost0ms { - get { - return ResourceManager.GetString("TimeOutMultipleHost0ms", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Connection attempt to the server was aborted. Timeout of {0} milliseconds was exceeded.. - /// - internal static string TimeOutSingleHost { - get { - return ResourceManager.GetString("TimeOutSingleHost", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Connection attempt to the server was aborted. Timeout was exceeded.. - /// - internal static string TimeOutSingleHost0ms { - get { - return ResourceManager.GetString("TimeOutSingleHost0ms", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Unable to connect to any specified host.. - /// - internal static string UnableToConnect { - get { - return ResourceManager.GetString("UnableToConnect", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Unable to read or decode data value.. - /// - internal static string UnableToDecodeDataValue { - get { - return ResourceManager.GetString("UnableToDecodeDataValue", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Unable to open a session.. - /// - internal static string UnableToOpenSession { - get { - return ResourceManager.GetString("UnableToOpenSession", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Unexpected end of packet found while reading data values. - /// - internal static string UnexpectedEndOfPacketFound { - get { - return ResourceManager.GetString("UnexpectedEndOfPacketFound", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Field name '{0}' is not allowed.. - /// - internal static string UnexpectedField { - get { - return ResourceManager.GetString("UnexpectedField", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Unknown placeholder :{0}. - /// - internal static string UnknownPlaceholder { - get { - return ResourceManager.GetString("UnknownPlaceholder", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Value '{0}' is not of the correct type.. - /// - internal static string ValueNotCorrectType { - get { - return ResourceManager.GetString("ValueNotCorrectType", resourceCulture); - } - } - } -} +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace MySql.Data { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class ResourcesX { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal ResourcesX() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("MySql.Data.ResourcesX", typeof(ResourcesX).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to Appdata path is not defined.. + /// + internal static string AppdataNotDefined { + get { + return ResourceManager.GetString("AppdataNotDefined", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Authentication failed using MYSQL41 and SHA256_MEMORY. Check the user name and password or try using a secure connection.. + /// + internal static string AuthenticationFailed { + get { + return ResourceManager.GetString("AuthenticationFailed", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You can't get more sessions because Client is closed.. + /// + internal static string ClientIsClosed { + get { + return ResourceManager.GetString("ClientIsClosed", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Client option '{0}' does not support value '{1}'.. + /// + internal static string ClientOptionInvalidValue { + get { + return ResourceManager.GetString("ClientOptionInvalidValue", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Client option '{0}' is not recognized as valid.. + /// + internal static string ClientOptionNotValid { + get { + return ResourceManager.GetString("ClientOptionNotValid", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to {0} '{1}' does not exist in schema '{2}'.. + /// + internal static string CollectionTableDoesNotExist { + get { + return ResourceManager.GetString("CollectionTableDoesNotExist", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Compression requested but the compression algorithm negotiation failed.. + /// + internal static string CompressionAlgorithmNegotiationFailed { + get { + return ResourceManager.GetString("CompressionAlgorithmNegotiationFailed", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Compression using {0} is not supported.. + /// + internal static string CompressionAlgorithmNotSupported { + get { + return ResourceManager.GetString("CompressionAlgorithmNotSupported", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Compression using {0} is not supported in .NET Framework.. + /// + internal static string CompressionForSpecificAlgorithmNotSupportedInNetFramework { + get { + return ResourceManager.GetString("CompressionForSpecificAlgorithmNotSupportedInNetFramework", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The connection property 'compression' acceptable values are: 'preferred', 'required' or 'disabled'. The value '{0}' is not acceptable.. + /// + internal static string CompressionInvalidValue { + get { + return ResourceManager.GetString("CompressionInvalidValue", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Compression is not enabled.. + /// + internal static string CompressionNotEnabled { + get { + return ResourceManager.GetString("CompressionNotEnabled", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Compression requested but the server does not support it.. + /// + internal static string CompressionNotSupportedByServer { + get { + return ResourceManager.GetString("CompressionNotSupportedByServer", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to There are still decompressed messages pending to be processed.. + /// + internal static string CompressionPendingMessagesToProcess { + get { + return ResourceManager.GetString("CompressionPendingMessagesToProcess", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Custom type mapping is only supported from .NET Core 3.1 and later.. + /// + internal static string CustomTypeNotSupported { + get { + return ResourceManager.GetString("CustomTypeNotSupported", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to '{0}' cannot be set to false with DNS SRV lookup enabled.. + /// + internal static string DnsSrvConflictingOptions { + get { + return ResourceManager.GetString("DnsSrvConflictingOptions", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Scheme '{0}' is not valid.. + /// + internal static string DnsSrvInvalidScheme { + get { + return ResourceManager.GetString("DnsSrvInvalidScheme", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The document path cannot be null or an empty string.. + /// + internal static string DocPathNullOrEmpty { + get { + return ResourceManager.GetString("DocPathNullOrEmpty", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Duplicate key '{0}' used in "connection-attributes".. + /// + internal static string DuplicateUserDefinedAttribute { + get { + return ResourceManager.GetString("DuplicateUserDefinedAttribute", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Key name in connection attribute cannot be an empty string.. + /// + internal static string EmptyKeyConnectionAttribute { + get { + return ResourceManager.GetString("EmptyKeyConnectionAttribute", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to At least one option must be specified.. + /// + internal static string EmptyOptions { + get { + return ResourceManager.GetString("EmptyOptions", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to This feature is currently not supported.. + /// + internal static string FeatureNotSupported { + get { + return ResourceManager.GetString("FeatureNotSupported", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to This functionality is only supported in MySQL {0} and higher.. + /// + internal static string FunctionalityNotSupported { + get { + return ResourceManager.GetString("FunctionalityNotSupported", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Collation with id '{0}' not found.. + /// + internal static string InvalidCollationId { + get { + return ResourceManager.GetString("InvalidCollationId", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The value of "connection-attributes" must be either a boolean or a list of key-value pairs.. + /// + internal static string InvalidConnectionAttributes { + get { + return ResourceManager.GetString("InvalidConnectionAttributes", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Connection Data is incorrect.. + /// + internal static string InvalidConnectionData { + get { + return ResourceManager.GetString("InvalidConnectionData", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The connection string is invalid.. + /// + internal static string InvalidConnectionString { + get { + return ResourceManager.GetString("InvalidConnectionString", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to '{0}' is not a valid connection string attribute.. + /// + internal static string InvalidConnectionStringAttribute { + get { + return ResourceManager.GetString("InvalidConnectionStringAttribute", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The connection timeout value must be a positive integer (including 0).. + /// + internal static string InvalidConnectionTimeoutValue { + get { + return ResourceManager.GetString("InvalidConnectionTimeoutValue", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Decimal (BCD) format is invalid.. + /// + internal static string InvalidDecimalFormat { + get { + return ResourceManager.GetString("InvalidDecimalFormat", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Field type with name '{0}' not found.. + /// + internal static string InvalidFieldType { + get { + return ResourceManager.GetString("InvalidFieldType", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Index type with name '{0}' not found.. + /// + internal static string InvalidIndexType { + get { + return ResourceManager.GetString("InvalidIndexType", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The value provided is not a valid JSON document. {0}. + /// + internal static string InvalidJsonDocument { + get { + return ResourceManager.GetString("InvalidJsonDocument", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to {0} is not a valid column name in the row.. + /// + internal static string InvalidNameIndex { + get { + return ResourceManager.GetString("InvalidNameIndex", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to {0} is not a valid index for the row.. + /// + internal static string InvalidRowIndex { + get { + return ResourceManager.GetString("InvalidRowIndex", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Session state is not valid.. + /// + internal static string InvalidSession { + get { + return ResourceManager.GetString("InvalidSession", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Invalid Uri . + /// + internal static string InvalidUriData { + get { + return ResourceManager.GetString("InvalidUriData", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Invalid uri query value. + /// + internal static string InvalidUriQuery { + get { + return ResourceManager.GetString("InvalidUriQuery", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Key names in "connection-attributes" cannot start with "_".. + /// + internal static string InvalidUserDefinedAttribute { + get { + return ResourceManager.GetString("InvalidUserDefinedAttribute", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Json configuration must contain 'uri' or 'host' but not both.. + /// + internal static string JsonUriOrHost { + get { + return ResourceManager.GetString("JsonUriOrHost", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Keyword '{0}' not found.. + /// + internal static string KeywordNotFound { + get { + return ResourceManager.GetString("KeywordNotFound", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Keyword not supported.. + /// + internal static string KeywordNotSupported { + get { + return ResourceManager.GetString("KeywordNotSupported", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Field '{0}' is mandatory.. + /// + internal static string MandatoryFieldNotFound { + get { + return ResourceManager.GetString("MandatoryFieldNotFound", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Missed required schema option.. + /// + internal static string MissingSchemaOption { + get { + return ResourceManager.GetString("MissingSchemaOption", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to More than one document id was generated. Please use the DocumentIds property instead.. + /// + internal static string MoreThanOneDocumentId { + get { + return ResourceManager.GetString("MoreThanOneDocumentId", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to There is no data at index {0}. + /// + internal static string NoDataAtIndex { + get { + return ResourceManager.GetString("NoDataAtIndex", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to No 'host' has been specified.. + /// + internal static string NoHost { + get { + return ResourceManager.GetString("NoHost", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to No more data in resultset.. + /// + internal static string NoMoreData { + get { + return ResourceManager.GetString("NoMoreData", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Object '{0}' not found. + /// + internal static string NoObjectFound { + get { + return ResourceManager.GetString("NoObjectFound", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to No placeholders.. + /// + internal static string NoPlaceholders { + get { + return ResourceManager.GetString("NoPlaceholders", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Connection closed. Reason: connection idle was too long. + /// + internal static string NoticeIdleConnection { + get { + return ResourceManager.GetString("NoticeIdleConnection", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Connection closed. Reason: connection was killed by a different session. + /// + internal static string NoticeKilledConnection { + get { + return ResourceManager.GetString("NoticeKilledConnection", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Connection closed. Reason: server was shutdown. + /// + internal static string NoticeServerShutdown { + get { + return ResourceManager.GetString("NoticeServerShutdown", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to {0} must be a value greater than 0.. + /// + internal static string NumberNotGreaterThanZero { + get { + return ResourceManager.GetString("NumberNotGreaterThanZero", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Path not found '{0}'.. + /// + internal static string PathNotFound { + get { + return ResourceManager.GetString("PathNotFound", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Queue timeout expired. The timeout period elapsed prior to getting a session from the pool.. + /// + internal static string PoolingQueueTimeout { + get { + return ResourceManager.GetString("PoolingQueueTimeout", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Providing a port number as part of the host address isn't supported when using connection strings in basic format or anonymous objects. Use URI format instead.. + /// + internal static string PortNotSupported { + get { + return ResourceManager.GetString("PortNotSupported", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You must either assign no priority to any of the hosts or give a priority for every host.. + /// + internal static string PriorityForAllOrNoHosts { + get { + return ResourceManager.GetString("PriorityForAllOrNoHosts", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The priority must be between 0 and 100.. + /// + internal static string PriorityOutOfLimits { + get { + return ResourceManager.GetString("PriorityOutOfLimits", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to ProgramData path is not defined.. + /// + internal static string ProgramDataNotDefined { + get { + return ResourceManager.GetString("ProgramDataNotDefined", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Replacement document has an '_id' that is + ///different from the matched document.. + /// + internal static string ReplaceWithNoMatchingId { + get { + return ResourceManager.GetString("ReplaceWithNoMatchingId", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The server doesn't support the requested operation. Please update the MySQL Server, client library, or both.. + /// + internal static string SchemaCreateCollectionMsg { + get { + return ResourceManager.GetString("SchemaCreateCollectionMsg", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The process of closing the resultset and resulted in results being lost.. + /// + internal static string ThrowingAwayResults { + get { + return ResourceManager.GetString("ThrowingAwayResults", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to All server connection attempts were aborted. Timeout of {0} milliseconds was exceeded for each selected server.. + /// + internal static string TimeOutMultipleHost { + get { + return ResourceManager.GetString("TimeOutMultipleHost", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to All server connection attempts were aborted. Timeout was exceeded for each selected server.. + /// + internal static string TimeOutMultipleHost0ms { + get { + return ResourceManager.GetString("TimeOutMultipleHost0ms", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Connection attempt to the server was aborted. Timeout of {0} milliseconds was exceeded.. + /// + internal static string TimeOutSingleHost { + get { + return ResourceManager.GetString("TimeOutSingleHost", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Connection attempt to the server was aborted. Timeout was exceeded.. + /// + internal static string TimeOutSingleHost0ms { + get { + return ResourceManager.GetString("TimeOutSingleHost0ms", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unable to connect to any specified host.. + /// + internal static string UnableToConnect { + get { + return ResourceManager.GetString("UnableToConnect", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unable to read or decode data value.. + /// + internal static string UnableToDecodeDataValue { + get { + return ResourceManager.GetString("UnableToDecodeDataValue", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unable to open a session.. + /// + internal static string UnableToOpenSession { + get { + return ResourceManager.GetString("UnableToOpenSession", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unexpected end of packet found while reading data values. + /// + internal static string UnexpectedEndOfPacketFound { + get { + return ResourceManager.GetString("UnexpectedEndOfPacketFound", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Field name '{0}' is not allowed.. + /// + internal static string UnexpectedField { + get { + return ResourceManager.GetString("UnexpectedField", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unknown placeholder :{0}. + /// + internal static string UnknownPlaceholder { + get { + return ResourceManager.GetString("UnknownPlaceholder", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Value '{0}' is not of the correct type.. + /// + internal static string ValueNotCorrectType { + get { + return ResourceManager.GetString("ValueNotCorrectType", resourceCulture); + } + } + } +} diff --git a/MySQL.Data/src/ResultSet.cs b/MySQL.Data/src/ResultSet.cs index 99d41d9ec..0de428e0e 100644 --- a/MySQL.Data/src/ResultSet.cs +++ b/MySQL.Data/src/ResultSet.cs @@ -1,339 +1,339 @@ -// Copyright (c) 2009, 2022, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySql.Data.Types; -using System; -using System.Collections.Generic; -using System.Data; -using System.Diagnostics; -using System.Threading.Tasks; - -namespace MySql.Data.MySqlClient -{ - internal class ResultSet - { - private Driver _driver; - private bool[] _uaFieldsUsed; - private Dictionary _fieldHashCi; - private int _rowIndex; - private bool _readDone; - private bool _isSequential; - private int _seqIndex; - private readonly int _statementId; - private bool _cached; - private List _cachedValues; - - public ResultSet(int affectedRows, long insertedId) - { - AffectedRows = affectedRows; - InsertedId = insertedId; - _readDone = true; - } - - public static async Task CreateResultSetAsync(Driver d, int statementId, int numCols, bool execAsync) - { - ResultSet resultSet = new ResultSet(d, statementId); - await resultSet.InitializeAsync(numCols, execAsync).ConfigureAwait(false); - return resultSet; - } - - private ResultSet(Driver d, int statementId) - { - AffectedRows = -1; - InsertedId = -1; - _driver = d; - _statementId = statementId; - _rowIndex = -1; - } - - private async Task InitializeAsync(int numCols, bool execAsync) - { - await LoadColumnsAsync(numCols, execAsync).ConfigureAwait(false); - IsOutputParameters = IsOutputParameterResultSet(); - HasRows = await GetNextRowAsync(execAsync).ConfigureAwait(false); - _readDone = !HasRows; - } - - #region Properties - - public bool HasRows { get; private set; } - - public int Size => Fields?.Length ?? 0; - - public MySqlField[] Fields { get; private set; } - - public IMySqlValue[] Values { get; private set; } - - public bool IsOutputParameters { get; set; } - - public int AffectedRows { get; private set; } - - public long InsertedId { get; private set; } - - public int TotalRows { get; private set; } - - public int SkippedRows { get; private set; } - - public bool Cached - { - get { return _cached; } - set - { - _cached = value; - if (_cached && _cachedValues == null) - _cachedValues = new List(); - } - } - - #endregion - - /// - /// return the ordinal for the given column name - /// - /// - /// - public int GetOrdinal(string name) - { - int ordinal; - - // quick hash lookup using CI hash - if (_fieldHashCi.TryGetValue(name, out ordinal)) - return ordinal; - - // Throw an exception if the ordinal cannot be found. - throw new IndexOutOfRangeException( - String.Format(Resources.CouldNotFindColumnName, name)); - } - - /// - /// Retrieve the value as the given column index - /// - /// The column value to retrieve - /// The value as the given column - public IMySqlValue this[int index] - { - get - { - if (_rowIndex < 0) - throw new MySqlException(Resources.AttemptToAccessBeforeRead); - - // keep count of how many columns we have left to access - _uaFieldsUsed[index] = true; - - if (_isSequential && index != _seqIndex) - { - if (index < _seqIndex) - throw new MySqlException(Resources.ReadingPriorColumnUsingSeqAccess); - while (_seqIndex < (index - 1)) - _driver.SkipColumnValue(Values[++_seqIndex]); - Values[index] = _driver.ReadColumnValueAsync(index, Fields[index], Values[index], false).GetAwaiter().GetResult(); - _seqIndex = index; - } - - return Values[index]; - } - } - - private async Task GetNextRowAsync(bool execAsync) - { - bool fetched = await _driver.FetchDataRowAsync(_statementId, Size, execAsync).ConfigureAwait(false); - - if (fetched) - TotalRows++; - - return fetched; - } - - public async Task NextRowAsync(CommandBehavior behavior, bool execAsync) - { - if (_readDone) - { - if (Cached) return CachedNextRow(behavior); - return false; - } - - if ((behavior & CommandBehavior.SingleRow) != 0 && _rowIndex == 0) - return false; - - _isSequential = (behavior & CommandBehavior.SequentialAccess) != 0; - _seqIndex = -1; - - // if we are at row index >= 0 then we need to fetch the data row and load it - if (_rowIndex >= 0) - { - bool fetched; - try - { - fetched = await GetNextRowAsync(execAsync).ConfigureAwait(false); - } - catch (MySqlException ex) - { - if (ex.IsQueryAborted) - { - // avoid hanging on Close() - _readDone = true; - } - throw; - } - - if (!fetched) - { - _readDone = true; - return false; - } - } - - if (!_isSequential) - await ReadColumnDataAsync(false, execAsync).ConfigureAwait(false); - - _rowIndex++; - return true; - } - - private bool CachedNextRow(CommandBehavior behavior) - { - if ((behavior & CommandBehavior.SingleRow) != 0 && _rowIndex == 0) - return false; - if (_rowIndex == (TotalRows - 1)) return false; - _rowIndex++; - Values = _cachedValues[_rowIndex]; - return true; - } - - /// - /// Closes the current resultset, dumping any data still on the wire - /// - public async Task CloseAsync(bool execAsync) - { - if (!_readDone) - { - - // if we have rows but the user didn't read the first one then mark it as skipped - if (HasRows && _rowIndex == -1) - SkippedRows++; - try - { - while (_driver.IsOpen && await _driver.SkipDataRowAsync(execAsync).ConfigureAwait(false)) - { - TotalRows++; - SkippedRows++; - } - } - catch (System.IO.IOException) - { - // it is ok to eat IO exceptions here, we just want to - // close the result set - } - _readDone = true; - } - else if (_driver == null) - CacheClose(); - - _driver = null; - if (Cached) CacheReset(); - } - - private void CacheClose() - { - SkippedRows = TotalRows - _rowIndex - 1; - } - - private void CacheReset() - { - if (!Cached) return; - _rowIndex = -1; - AffectedRows = -1; - InsertedId = -1; - SkippedRows = 0; - } - - public bool FieldRead(int index) - { - Debug.Assert(Size > index); - return _uaFieldsUsed[index]; - } - - public void SetValueObject(int i, IMySqlValue valueObject) - { - Debug.Assert(Values != null); - Debug.Assert(i < Values.Length); - Values[i] = valueObject; - } - - private bool IsOutputParameterResultSet() - { - if (_driver.HasStatus(ServerStatusFlags.OutputParameters)) return true; - - if (Fields.Length == 0) return false; - - for (int x = 0; x < Fields.Length; x++) - if (!Fields[x].ColumnName.StartsWith("@" + StoredProcedure.ParameterPrefix, StringComparison.OrdinalIgnoreCase)) return false; - return true; - } - - /// - /// Loads the column metadata for the current resultset - /// - private async Task LoadColumnsAsync(int numCols, bool execAsync) - { - Fields = await _driver.GetColumnsAsync(numCols, execAsync).ConfigureAwait(false); - - Values = new IMySqlValue[numCols]; - _uaFieldsUsed = new bool[numCols]; - _fieldHashCi = new Dictionary(StringComparer.OrdinalIgnoreCase); - - for (int i = 0; i < Fields.Length; i++) - { - string columnName = Fields[i].ColumnName; - if (!_fieldHashCi.ContainsKey(columnName)) - _fieldHashCi.Add(columnName, i); - Values[i] = Fields[i].GetValueObject(); - } - } - - private async Task ReadColumnDataAsync(bool outputParms, bool execAsync) - { - for (int i = 0; i < Size; i++) - Values[i] = await _driver.ReadColumnValueAsync(i, Fields[i], Values[i], execAsync).ConfigureAwait(false); - - // if we are caching then we need to save a copy of this row of data values - if (Cached) - _cachedValues.Add((IMySqlValue[])Values.Clone()); - - // we don't need to worry about caching the following since you won't have output - // params with TableDirect commands - if (!outputParms) return; - - bool rowExists = await _driver.FetchDataRowAsync(_statementId, Fields.Length, execAsync).ConfigureAwait(false); - _rowIndex = 0; - - if (rowExists) - throw new MySqlException(Resources.MoreThanOneOPRow); - } - } -} +// Copyright © 2009, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySql.Data.Types; +using System; +using System.Collections.Generic; +using System.Data; +using System.Diagnostics; +using System.Threading.Tasks; + +namespace MySql.Data.MySqlClient +{ + internal class ResultSet + { + private Driver _driver; + private bool[] _uaFieldsUsed; + private Dictionary _fieldHashCi; + private int _rowIndex; + private bool _readDone; + private bool _isSequential; + private int _seqIndex; + private readonly int _statementId; + private bool _cached; + private List _cachedValues; + + public ResultSet(int affectedRows, long insertedId) + { + AffectedRows = affectedRows; + InsertedId = insertedId; + _readDone = true; + } + + public static async Task CreateResultSetAsync(Driver d, int statementId, int numCols, bool execAsync) + { + ResultSet resultSet = new ResultSet(d, statementId); + await resultSet.InitializeAsync(numCols, execAsync).ConfigureAwait(false); + return resultSet; + } + + private ResultSet(Driver d, int statementId) + { + AffectedRows = -1; + InsertedId = -1; + _driver = d; + _statementId = statementId; + _rowIndex = -1; + } + + private async Task InitializeAsync(int numCols, bool execAsync) + { + await LoadColumnsAsync(numCols, execAsync).ConfigureAwait(false); + IsOutputParameters = IsOutputParameterResultSet(); + HasRows = await GetNextRowAsync(execAsync).ConfigureAwait(false); + _readDone = !HasRows; + } + + #region Properties + + public bool HasRows { get; private set; } + + public int Size => Fields?.Length ?? 0; + + public MySqlField[] Fields { get; private set; } + + public IMySqlValue[] Values { get; private set; } + + public bool IsOutputParameters { get; set; } + + public int AffectedRows { get; private set; } + + public long InsertedId { get; private set; } + + public int TotalRows { get; private set; } + + public int SkippedRows { get; private set; } + + public bool Cached + { + get { return _cached; } + set + { + _cached = value; + if (_cached && _cachedValues == null) + _cachedValues = new List(); + } + } + + #endregion + + /// + /// return the ordinal for the given column name + /// + /// + /// + public int GetOrdinal(string name) + { + int ordinal; + + // quick hash lookup using CI hash + if (_fieldHashCi.TryGetValue(name, out ordinal)) + return ordinal; + + // Throw an exception if the ordinal cannot be found. + throw new IndexOutOfRangeException( + String.Format(Resources.CouldNotFindColumnName, name)); + } + + /// + /// Retrieve the value as the given column index + /// + /// The column value to retrieve + /// The value as the given column + public IMySqlValue this[int index] + { + get + { + if (_rowIndex < 0) + throw new MySqlException(Resources.AttemptToAccessBeforeRead); + + // keep count of how many columns we have left to access + _uaFieldsUsed[index] = true; + + if (_isSequential && index != _seqIndex) + { + if (index < _seqIndex) + throw new MySqlException(Resources.ReadingPriorColumnUsingSeqAccess); + while (_seqIndex < (index - 1)) + _driver.SkipColumnValue(Values[++_seqIndex]); + Values[index] = _driver.ReadColumnValueAsync(index, Fields[index], Values[index], false).GetAwaiter().GetResult(); + _seqIndex = index; + } + + return Values[index]; + } + } + + private async Task GetNextRowAsync(bool execAsync) + { + bool fetched = await _driver.FetchDataRowAsync(_statementId, Size, execAsync).ConfigureAwait(false); + + if (fetched) + TotalRows++; + + return fetched; + } + + public async Task NextRowAsync(CommandBehavior behavior, bool execAsync) + { + if (_readDone) + { + if (Cached) return CachedNextRow(behavior); + return false; + } + + if ((behavior & CommandBehavior.SingleRow) != 0 && _rowIndex == 0) + return false; + + _isSequential = (behavior & CommandBehavior.SequentialAccess) != 0; + _seqIndex = -1; + + // if we are at row index >= 0 then we need to fetch the data row and load it + if (_rowIndex >= 0) + { + bool fetched; + try + { + fetched = await GetNextRowAsync(execAsync).ConfigureAwait(false); + } + catch (MySqlException ex) + { + if (ex.IsQueryAborted) + { + // avoid hanging on Close() + _readDone = true; + } + throw; + } + + if (!fetched) + { + _readDone = true; + return false; + } + } + + if (!_isSequential) + await ReadColumnDataAsync(false, execAsync).ConfigureAwait(false); + + _rowIndex++; + return true; + } + + private bool CachedNextRow(CommandBehavior behavior) + { + if ((behavior & CommandBehavior.SingleRow) != 0 && _rowIndex == 0) + return false; + if (_rowIndex == (TotalRows - 1)) return false; + _rowIndex++; + Values = _cachedValues[_rowIndex]; + return true; + } + + /// + /// Closes the current resultset, dumping any data still on the wire + /// + public async Task CloseAsync(bool execAsync) + { + if (!_readDone) + { + + // if we have rows but the user didn't read the first one then mark it as skipped + if (HasRows && _rowIndex == -1) + SkippedRows++; + try + { + while (_driver.IsOpen && await _driver.SkipDataRowAsync(execAsync).ConfigureAwait(false)) + { + TotalRows++; + SkippedRows++; + } + } + catch (System.IO.IOException) + { + // it is ok to eat IO exceptions here, we just want to + // close the result set + } + _readDone = true; + } + else if (_driver == null) + CacheClose(); + + _driver = null; + if (Cached) CacheReset(); + } + + private void CacheClose() + { + SkippedRows = TotalRows - _rowIndex - 1; + } + + private void CacheReset() + { + if (!Cached) return; + _rowIndex = -1; + AffectedRows = -1; + InsertedId = -1; + SkippedRows = 0; + } + + public bool FieldRead(int index) + { + Debug.Assert(Size > index); + return _uaFieldsUsed[index]; + } + + public void SetValueObject(int i, IMySqlValue valueObject) + { + Debug.Assert(Values != null); + Debug.Assert(i < Values.Length); + Values[i] = valueObject; + } + + private bool IsOutputParameterResultSet() + { + if (_driver.HasStatus(ServerStatusFlags.OutputParameters)) return true; + + if (Fields.Length == 0) return false; + + for (int x = 0; x < Fields.Length; x++) + if (!Fields[x].ColumnName.StartsWith("@" + StoredProcedure.ParameterPrefix, StringComparison.OrdinalIgnoreCase)) return false; + return true; + } + + /// + /// Loads the column metadata for the current resultset + /// + private async Task LoadColumnsAsync(int numCols, bool execAsync) + { + Fields = await _driver.GetColumnsAsync(numCols, execAsync).ConfigureAwait(false); + + Values = new IMySqlValue[numCols]; + _uaFieldsUsed = new bool[numCols]; + _fieldHashCi = new Dictionary(StringComparer.OrdinalIgnoreCase); + + for (int i = 0; i < Fields.Length; i++) + { + string columnName = Fields[i].ColumnName; + if (!_fieldHashCi.ContainsKey(columnName)) + _fieldHashCi.Add(columnName, i); + Values[i] = Fields[i].GetValueObject(); + } + } + + private async Task ReadColumnDataAsync(bool outputParms, bool execAsync) + { + for (int i = 0; i < Size; i++) + Values[i] = await _driver.ReadColumnValueAsync(i, Fields[i], Values[i], execAsync).ConfigureAwait(false); + + // if we are caching then we need to save a copy of this row of data values + if (Cached) + _cachedValues.Add((IMySqlValue[])Values.Clone()); + + // we don't need to worry about caching the following since you won't have output + // params with TableDirect commands + if (!outputParms) return; + + bool rowExists = await _driver.FetchDataRowAsync(_statementId, Fields.Length, execAsync).ConfigureAwait(false); + _rowIndex = 0; + + if (rowExists) + throw new MySqlException(Resources.MoreThanOneOPRow); + } + } +} diff --git a/MySQL.Data/src/Runtime.cs b/MySQL.Data/src/Runtime.cs index dba59e3ae..089f1ec05 100644 --- a/MySQL.Data/src/Runtime.cs +++ b/MySQL.Data/src/Runtime.cs @@ -1,56 +1,56 @@ -// Copyright © 2014, 2016, Oracle and/or its affiliates. All rights reserved. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - - -using System; - -namespace MySql.Web.Security -{ - internal static class Runtime - { - private static bool inited; - private static bool isMono; - - public static bool IsMono - { - get - { - if (!inited) - Init(); - return isMono; - } - } - - private static void Init() - { - Type t = Type.GetType("Mono.Runtime"); - isMono = t != null; - inited = true; - } - } -} +// Copyright © 2014, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + +using System; + +namespace MySql.Web.Security +{ + internal static class Runtime + { + private static bool inited; + private static bool isMono; + + public static bool IsMono + { + get + { + if (!inited) + Init(); + return isMono; + } + } + + private static void Init() + { + Type t = Type.GetType("Mono.Runtime"); + isMono = t != null; + inited = true; + } + } +} diff --git a/MySQL.Data/src/Schema.cs b/MySQL.Data/src/Schema.cs index 0f04fcfb5..4401cfec4 100644 --- a/MySQL.Data/src/Schema.cs +++ b/MySQL.Data/src/Schema.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/SchemaProvider.cs b/MySQL.Data/src/SchemaProvider.cs index eae7efdc6..f56b8a78d 100644 --- a/MySQL.Data/src/SchemaProvider.cs +++ b/MySQL.Data/src/SchemaProvider.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2004, 2023, Oracle and/or its affiliates. +// Copyright © 2004, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/Statement.cs b/MySQL.Data/src/Statement.cs index e847a3f03..bdddc47b9 100644 --- a/MySQL.Data/src/Statement.cs +++ b/MySQL.Data/src/Statement.cs @@ -1,351 +1,351 @@ -// Copyright (c) 2004, 2023, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySql.Data.Common; -using System; -using System.Collections; -using System.Collections.Generic; -using System.Data; -using System.Globalization; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace MySql.Data.MySqlClient -{ - internal abstract class Statement - { - protected MySqlCommand command; - private readonly List _buffers; - protected string commandText; - protected int paramsPosition; - - internal const string ParameterPrefix = "_cnet_param_"; - public virtual bool ServerProvidingOutputParameters { get; internal set; } - - private Statement(MySqlCommand cmd) - { - command = cmd; - _buffers = new List(); - } - - protected Statement(MySqlCommand cmd, string text) - : this(cmd) - { - commandText = text; - } - - #region Properties - - public virtual string ResolvedCommandText - { - get { return commandText; } - } - - protected Driver Driver => command.Connection.driver; - - protected MySqlConnection Connection => command.Connection; - - protected MySqlParameterCollection Parameters => command.Parameters; - - protected MySqlAttributeCollection Attributes => command.Attributes; - - #endregion - - public virtual void Close(MySqlDataReader reader) { } - - public virtual void Resolve(bool preparing) - { - if (!command.InternallyCreated || !(ResolvedCommandText != null && Parameters.Count == 0)) - { - ServerProvidingOutputParameters = Driver.SupportsOutputParameters && preparing; - if (Parameters.Cast().Where(x => x.Direction == ParameterDirection.Output).Any()) - { - string setSql = SetSql(Parameters, preparing); - string outSql = CreateOutputSelect(Parameters, preparing); - commandText = String.Format("{0}{1}", setSql, outSql); - } - } - } - - private string SetSql(MySqlParameterCollection parms, bool preparing) - { - StringBuilder setSql = new StringBuilder(); - setSql.Append(commandText); - foreach (MySqlParameter p in parms) - { - if (p.Direction != ParameterDirection.Output) continue; - - string uName = "@" + ParameterPrefix + p.BaseName; - setSql.Replace(p.ParameterName, uName); - } - return setSql.ToString(); - } - - private string CreateOutputSelect(MySqlParameterCollection parms, bool preparing) - { - StringBuilder outputSql = new StringBuilder(); - string delimiter = string.Empty; - - foreach (MySqlParameter p in parms) - { - if (p.Direction == ParameterDirection.Output) - { - string uName = "@" + ParameterPrefix + p.BaseName; - outputSql.AppendFormat(CultureInfo.InvariantCulture, "{0}{1}", delimiter, uName); - delimiter = ", "; - } - } - - if (outputSql.Length == 0) return String.Empty; - - else if (command.Connection.Settings.AllowBatch && !preparing) - return String.Format("; SELECT {0}", outputSql.ToString()); - else - { - command.OutSql = String.Format("SELECT {0}", outputSql.ToString()); - return String.Empty; - } - } - - public virtual async Task ExecuteAsync(bool execAsync) - { - // we keep a reference to this until we are done - await BindParametersAsync(execAsync).ConfigureAwait(false); - await ExecuteNextAsync(execAsync).ConfigureAwait(false); - } - - public virtual async Task ExecuteNextAsync(bool execAsync) - { - if (_buffers.Count == 0) - return false; - - MySqlPacket packet = _buffers[0]; - await Driver.SendQueryAsync(packet, paramsPosition, execAsync).ConfigureAwait(false); - _buffers.RemoveAt(0); - return true; - } - - protected async Task BindParametersAsync(bool execAsync) - { - MySqlParameterCollection parameters = command.Parameters; - MySqlAttributeCollection attributes = command.Attributes; - int index = 0; - - while (true) - { - MySqlPacket packet = await BuildQueryAttributesPacketAsync(attributes, execAsync).ConfigureAwait(false); - await InternalBindParametersAsync(ResolvedCommandText, parameters, packet, execAsync).ConfigureAwait(false); - - // if we are not batching, then we are done. This is only really relevant the - // first time through - if (command.Batch == null) return; - while (index < command.Batch.Count) - { - MySqlCommand batchedCmd = command.Batch[index++]; - packet = (MySqlPacket)_buffers[_buffers.Count - 1]; - - // now we make a guess if this statement will fit in our current stream - long estimatedCmdSize = batchedCmd.EstimatedSize(); - if (((packet.Length - 4) + estimatedCmdSize) > Connection.driver.MaxPacketSize) - // it won't, so we raise an exception to avoid a partial batch - throw new MySqlException(Resources.QueryTooLarge, (int)MySqlErrorCode.PacketTooLarge); - - // looks like we might have room for it so we remember the current end of the stream - _buffers.RemoveAt(_buffers.Count - 1); - //long originalLength = packet.Length - 4; - - // and attempt to stream the next command - string text = ResolvedCommandText; - if (text.StartsWith("(", StringComparison.Ordinal)) - await packet.WriteStringNoNullAsync(", ", execAsync).ConfigureAwait(false); - else - await packet.WriteStringNoNullAsync("; ", execAsync).ConfigureAwait(false); - - await InternalBindParametersAsync(text, batchedCmd.Parameters, packet, execAsync).ConfigureAwait(false); - if ((packet.Length - 4) > Connection.driver.MaxPacketSize) - { - //TODO - //stream.InternalBuffer.SetLength(originalLength); - parameters = batchedCmd.Parameters; - break; - } - } - if (index == command.Batch.Count) - return; - } - } - - /// - /// Builds the initial part of the COM_QUERY packet - /// - /// Collection of attributes - /// A - /// Boolean that indicates if the function will be executed asynchronously. - private async Task BuildQueryAttributesPacketAsync(MySqlAttributeCollection attributes, bool execAsync) - { - MySqlPacket packet; - packet = new MySqlPacket(Driver.Encoding) { Version = Driver.Version }; - packet.WriteByte(0); - - if (attributes.Count > 0 && !Driver.SupportsQueryAttributes) - MySqlTrace.LogWarning(Connection.ServerThread, string.Format(Resources.QueryAttributesNotSupported, Driver.Version)); - else if (Driver.SupportsQueryAttributes) - { - int paramCount = attributes.Count; - await packet.WriteLengthAsync(paramCount, execAsync).ConfigureAwait(false); // int parameter_count - Number of parameters - packet.WriteByte(1); // int parameter_set_count - Number of parameter sets. Currently always 1 - - if (paramCount > 0) - { - // now prepare our null map - BitArray _nullMap = new BitArray(paramCount); - int numNullBytes = (_nullMap.Length + 7) / 8; - int _nullMapPosition = packet.Position; - packet.Position += numNullBytes; // leave room for our null map - packet.WriteByte((byte)1); // new_params_bind_flag - Always 1. Malformed packet error if not 1 - - // set type and name for each attribute - foreach (MySqlAttribute attribute in attributes) - { - await packet.WriteIntegerAsync(attribute.GetPSType(), 2, execAsync).ConfigureAwait(false); - await packet.WriteLenStringAsync(attribute.AttributeName, execAsync).ConfigureAwait(false); - } - - // set value for each attribute - for (int i = 0; i < attributes.Count; i++) - { - MySqlAttribute attr = attributes[i]; - _nullMap[i] = (attr.Value == DBNull.Value || attr.Value == null); - if (_nullMap[i]) continue; - await attr.SerializeAsync(packet, true, Connection.Settings, execAsync).ConfigureAwait(false); - } - - byte[] tempByteArray = new byte[(_nullMap.Length + 7) >> 3]; - _nullMap.CopyTo(tempByteArray, 0); - - Array.Copy(tempByteArray, 0, packet.Buffer, _nullMapPosition, tempByteArray.Length); - } - } - - paramsPosition = packet.Position; - return packet; - } - - private async Task InternalBindParametersAsync(string sql, MySqlParameterCollection parameters, MySqlPacket packet, bool execAsync) - { - bool sqlServerMode = command.Connection.Settings.SqlServerMode; - - MySqlTokenizer tokenizer = new MySqlTokenizer(sql) - { - ReturnComments = true, - SqlServerMode = sqlServerMode - }; - - int pos = 0; - string token = tokenizer.NextToken(); - int parameterCount = 0; - while (token != null) - { - // serialize everything that came before the token (i.e. whitespace) - await packet.WriteStringNoNullAsync(sql.Substring(pos, tokenizer.StartIndex - pos), execAsync).ConfigureAwait(false); - pos = tokenizer.StopIndex; - - if (MySqlTokenizer.IsParameter(token)) - { - if ((!parameters.containsUnnamedParameters && token.Length == 1 && parameterCount > 0) || parameters.containsUnnamedParameters && token.Length > 1) - throw new MySqlException(Resources.MixedParameterNamingNotAllowed); - - parameters.containsUnnamedParameters = token.Length == 1; - if (await SerializeParameterAsync(parameters, packet, token, parameterCount, execAsync).ConfigureAwait(false)) - token = null; - parameterCount++; - } - - if (token != null) - { - if (sqlServerMode && tokenizer.Quoted && token.StartsWith("[", StringComparison.Ordinal)) - token = String.Format("`{0}`", token.Substring(1, token.Length - 2)); - - await packet.WriteStringNoNullAsync(token, execAsync).ConfigureAwait(false); - } - token = tokenizer.NextToken(); - } - _buffers.Add(packet); - } - - protected virtual bool ShouldIgnoreMissingParameter(string parameterName) - { - if (Connection.Settings.AllowUserVariables) - return true; - if (parameterName.StartsWith("@" + StoredProcedure.ParameterPrefix, StringComparison.OrdinalIgnoreCase)) - return true; - if (parameterName.Length > 1 && - (parameterName[1] == '`' || parameterName[1] == '\'')) - return true; - return false; - } - - /// - /// Serializes the given parameter to the given memory stream - /// - /// - /// This method is called by PrepareSqlBuffers to convert the given - /// parameter to bytes and write those bytes to the given memory stream. - /// - /// - /// True if the parameter was successfully serialized, false otherwise. - private async Task SerializeParameterAsync(MySqlParameterCollection parameters, MySqlPacket packet, string parmName, int parameterIndex, bool execAsync) - { - MySqlParameter parameter = null; - - if (!parameters.containsUnnamedParameters) - parameter = parameters.GetParameterFlexible(parmName, false); - else - { - if (parameterIndex <= parameters.Count) - parameter = parameters[parameterIndex]; - else - throw new MySqlException(Resources.ParameterIndexNotFound); - } - - if (parameter == null) - { - // if we are allowing user variables and the parameter name starts with @ - // then we can't throw an exception - if (parmName.StartsWith("@", StringComparison.Ordinal) && ShouldIgnoreMissingParameter(parmName)) - return false; - throw new MySqlException( - String.Format(Resources.ParameterMustBeDefined, parmName)); - } - - await parameter.SerializeAsync(packet, false, Connection.Settings, execAsync).ConfigureAwait(false); - return true; - } - } -} +// Copyright © 2004, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySql.Data.Common; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Data; +using System.Globalization; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace MySql.Data.MySqlClient +{ + internal abstract class Statement + { + protected MySqlCommand command; + private readonly List _buffers; + protected string commandText; + protected int paramsPosition; + + internal const string ParameterPrefix = "_cnet_param_"; + public virtual bool ServerProvidingOutputParameters { get; internal set; } + + private Statement(MySqlCommand cmd) + { + command = cmd; + _buffers = new List(); + } + + protected Statement(MySqlCommand cmd, string text) + : this(cmd) + { + commandText = text; + } + + #region Properties + + public virtual string ResolvedCommandText + { + get { return commandText; } + } + + protected Driver Driver => command.Connection.driver; + + protected MySqlConnection Connection => command.Connection; + + protected MySqlParameterCollection Parameters => command.Parameters; + + protected MySqlAttributeCollection Attributes => command.Attributes; + + #endregion + + public virtual void Close(MySqlDataReader reader) { } + + public virtual void Resolve(bool preparing) + { + if (!command.InternallyCreated || !(ResolvedCommandText != null && Parameters.Count == 0)) + { + ServerProvidingOutputParameters = Driver.SupportsOutputParameters && preparing; + if (Parameters.Cast().Where(x => x.Direction == ParameterDirection.Output).Any()) + { + string setSql = SetSql(Parameters, preparing); + string outSql = CreateOutputSelect(Parameters, preparing); + commandText = String.Format("{0}{1}", setSql, outSql); + } + } + } + + private string SetSql(MySqlParameterCollection parms, bool preparing) + { + StringBuilder setSql = new StringBuilder(); + setSql.Append(commandText); + foreach (MySqlParameter p in parms) + { + if (p.Direction != ParameterDirection.Output) continue; + + string uName = "@" + ParameterPrefix + p.BaseName; + setSql.Replace(p.ParameterName, uName); + } + return setSql.ToString(); + } + + private string CreateOutputSelect(MySqlParameterCollection parms, bool preparing) + { + StringBuilder outputSql = new StringBuilder(); + string delimiter = string.Empty; + + foreach (MySqlParameter p in parms) + { + if (p.Direction == ParameterDirection.Output) + { + string uName = "@" + ParameterPrefix + p.BaseName; + outputSql.AppendFormat(CultureInfo.InvariantCulture, "{0}{1}", delimiter, uName); + delimiter = ", "; + } + } + + if (outputSql.Length == 0) return String.Empty; + + else if (command.Connection.Settings.AllowBatch && !preparing) + return String.Format("; SELECT {0}", outputSql.ToString()); + else + { + command.OutSql = String.Format("SELECT {0}", outputSql.ToString()); + return String.Empty; + } + } + + public virtual async Task ExecuteAsync(bool execAsync) + { + // we keep a reference to this until we are done + await BindParametersAsync(execAsync).ConfigureAwait(false); + await ExecuteNextAsync(execAsync).ConfigureAwait(false); + } + + public virtual async Task ExecuteNextAsync(bool execAsync) + { + if (_buffers.Count == 0) + return false; + + MySqlPacket packet = _buffers[0]; + await Driver.SendQueryAsync(packet, paramsPosition, execAsync).ConfigureAwait(false); + _buffers.RemoveAt(0); + return true; + } + + protected async Task BindParametersAsync(bool execAsync) + { + MySqlParameterCollection parameters = command.Parameters; + MySqlAttributeCollection attributes = command.Attributes; + int index = 0; + + while (true) + { + MySqlPacket packet = await BuildQueryAttributesPacketAsync(attributes, execAsync).ConfigureAwait(false); + await InternalBindParametersAsync(ResolvedCommandText, parameters, packet, execAsync).ConfigureAwait(false); + + // if we are not batching, then we are done. This is only really relevant the + // first time through + if (command.Batch == null) return; + while (index < command.Batch.Count) + { + MySqlCommand batchedCmd = command.Batch[index++]; + packet = (MySqlPacket)_buffers[_buffers.Count - 1]; + + // now we make a guess if this statement will fit in our current stream + long estimatedCmdSize = batchedCmd.EstimatedSize(); + if (((packet.Length - 4) + estimatedCmdSize) > Connection.driver.MaxPacketSize) + // it won't, so we raise an exception to avoid a partial batch + throw new MySqlException(Resources.QueryTooLarge, (int)MySqlErrorCode.PacketTooLarge); + + // looks like we might have room for it so we remember the current end of the stream + _buffers.RemoveAt(_buffers.Count - 1); + //long originalLength = packet.Length - 4; + + // and attempt to stream the next command + string text = ResolvedCommandText; + if (text.StartsWith("(", StringComparison.Ordinal)) + await packet.WriteStringNoNullAsync(", ", execAsync).ConfigureAwait(false); + else + await packet.WriteStringNoNullAsync("; ", execAsync).ConfigureAwait(false); + + await InternalBindParametersAsync(text, batchedCmd.Parameters, packet, execAsync).ConfigureAwait(false); + if ((packet.Length - 4) > Connection.driver.MaxPacketSize) + { + //TODO + //stream.InternalBuffer.SetLength(originalLength); + parameters = batchedCmd.Parameters; + break; + } + } + if (index == command.Batch.Count) + return; + } + } + + /// + /// Builds the initial part of the COM_QUERY packet + /// + /// Collection of attributes + /// A + /// Boolean that indicates if the function will be executed asynchronously. + private async Task BuildQueryAttributesPacketAsync(MySqlAttributeCollection attributes, bool execAsync) + { + MySqlPacket packet; + packet = new MySqlPacket(Driver.Encoding) { Version = Driver.Version }; + packet.WriteByte(0); + + if (attributes.Count > 0 && !Driver.SupportsQueryAttributes) + MySqlTrace.LogWarning(Connection.ServerThread, string.Format(Resources.QueryAttributesNotSupported, Driver.Version)); + else if (Driver.SupportsQueryAttributes) + { + int paramCount = attributes.Count; + await packet.WriteLengthAsync(paramCount, execAsync).ConfigureAwait(false); // int parameter_count - Number of parameters + packet.WriteByte(1); // int parameter_set_count - Number of parameter sets. Currently always 1 + + if (paramCount > 0) + { + // now prepare our null map + BitArray _nullMap = new BitArray(paramCount); + int numNullBytes = (_nullMap.Length + 7) / 8; + int _nullMapPosition = packet.Position; + packet.Position += numNullBytes; // leave room for our null map + packet.WriteByte((byte)1); // new_params_bind_flag - Always 1. Malformed packet error if not 1 + + // set type and name for each attribute + foreach (MySqlAttribute attribute in attributes) + { + await packet.WriteIntegerAsync(attribute.GetPSType(), 2, execAsync).ConfigureAwait(false); + await packet.WriteLenStringAsync(attribute.AttributeName, execAsync).ConfigureAwait(false); + } + + // set value for each attribute + for (int i = 0; i < attributes.Count; i++) + { + MySqlAttribute attr = attributes[i]; + _nullMap[i] = (attr.Value == DBNull.Value || attr.Value == null); + if (_nullMap[i]) continue; + await attr.SerializeAsync(packet, true, Connection.Settings, execAsync).ConfigureAwait(false); + } + + byte[] tempByteArray = new byte[(_nullMap.Length + 7) >> 3]; + _nullMap.CopyTo(tempByteArray, 0); + + Array.Copy(tempByteArray, 0, packet.Buffer, _nullMapPosition, tempByteArray.Length); + } + } + + paramsPosition = packet.Position; + return packet; + } + + private async Task InternalBindParametersAsync(string sql, MySqlParameterCollection parameters, MySqlPacket packet, bool execAsync) + { + bool sqlServerMode = command.Connection.Settings.SqlServerMode; + + MySqlTokenizer tokenizer = new MySqlTokenizer(sql) + { + ReturnComments = true, + SqlServerMode = sqlServerMode + }; + + int pos = 0; + string token = tokenizer.NextToken(); + int parameterCount = 0; + while (token != null) + { + // serialize everything that came before the token (i.e. whitespace) + await packet.WriteStringNoNullAsync(sql.Substring(pos, tokenizer.StartIndex - pos), execAsync).ConfigureAwait(false); + pos = tokenizer.StopIndex; + + if (MySqlTokenizer.IsParameter(token)) + { + if ((!parameters.containsUnnamedParameters && token.Length == 1 && parameterCount > 0) || parameters.containsUnnamedParameters && token.Length > 1) + throw new MySqlException(Resources.MixedParameterNamingNotAllowed); + + parameters.containsUnnamedParameters = token.Length == 1; + if (await SerializeParameterAsync(parameters, packet, token, parameterCount, execAsync).ConfigureAwait(false)) + token = null; + parameterCount++; + } + + if (token != null) + { + if (sqlServerMode && tokenizer.Quoted && token.StartsWith("[", StringComparison.Ordinal)) + token = String.Format("`{0}`", token.Substring(1, token.Length - 2)); + + await packet.WriteStringNoNullAsync(token, execAsync).ConfigureAwait(false); + } + token = tokenizer.NextToken(); + } + _buffers.Add(packet); + } + + protected virtual bool ShouldIgnoreMissingParameter(string parameterName) + { + if (Connection.Settings.AllowUserVariables) + return true; + if (parameterName.StartsWith("@" + StoredProcedure.ParameterPrefix, StringComparison.OrdinalIgnoreCase)) + return true; + if (parameterName.Length > 1 && + (parameterName[1] == '`' || parameterName[1] == '\'')) + return true; + return false; + } + + /// + /// Serializes the given parameter to the given memory stream + /// + /// + /// This method is called by PrepareSqlBuffers to convert the given + /// parameter to bytes and write those bytes to the given memory stream. + /// + /// + /// True if the parameter was successfully serialized, false otherwise. + private async Task SerializeParameterAsync(MySqlParameterCollection parameters, MySqlPacket packet, string parmName, int parameterIndex, bool execAsync) + { + MySqlParameter parameter = null; + + if (!parameters.containsUnnamedParameters) + parameter = parameters.GetParameterFlexible(parmName, false); + else + { + if (parameterIndex <= parameters.Count) + parameter = parameters[parameterIndex]; + else + throw new MySqlException(Resources.ParameterIndexNotFound); + } + + if (parameter == null) + { + // if we are allowing user variables and the parameter name starts with @ + // then we can't throw an exception + if (parmName.StartsWith("@", StringComparison.Ordinal) && ShouldIgnoreMissingParameter(parmName)) + return false; + throw new MySqlException( + String.Format(Resources.ParameterMustBeDefined, parmName)); + } + + await parameter.SerializeAsync(packet, false, Connection.Settings, execAsync).ConfigureAwait(false); + return true; + } + } +} diff --git a/MySQL.Data/src/StoredProcedure.cs b/MySQL.Data/src/StoredProcedure.cs index 80a56d1d7..96da29eda 100644 --- a/MySQL.Data/src/StoredProcedure.cs +++ b/MySQL.Data/src/StoredProcedure.cs @@ -1,377 +1,377 @@ -// Copyright (c) 2004, 2023, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySql.Data.Common; -using MySql.Data.Types; -using System; -using System.Data; -using System.Globalization; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace MySql.Data.MySqlClient -{ - /// - /// Summary description for StoredProcedure. - /// - internal class StoredProcedure : PreparableStatement - { - private string _outSelect; - private string resolvedCommandText; - - public StoredProcedure(MySqlCommand cmd, string text) - : base(cmd, text) - { - } - - private MySqlParameter GetReturnParameter() - { - return Parameters?.Cast().FirstOrDefault(p => p.Direction == ParameterDirection.ReturnValue); - } - - public override string ResolvedCommandText - { - get { return resolvedCommandText; } - } - - internal string GetCacheKey(string spName) - { - string retValue = String.Empty; - StringBuilder key = new StringBuilder(spName); - key.Append("("); - string delimiter = ""; - foreach (MySqlParameter p in command.Parameters) - { - if (p.Direction == ParameterDirection.ReturnValue) - retValue = "?="; - else - { - key.AppendFormat(CultureInfo.InvariantCulture, "{0}?", delimiter); - delimiter = ","; - } - } - key.Append(")"); - return retValue + key.ToString(); - } - - private async Task GetParametersAsync(string procName, bool execAsync) - { - string procCacheKey = GetCacheKey(procName); - ProcedureCacheEntry entry = await Connection.ProcedureCache.GetProcedureAsync(Connection, procName, procCacheKey, execAsync).ConfigureAwait(false); - return entry; - } - - public static string GetFlags(string dtd) - { - int x = dtd.Length - 1; - while (x > 0 && (Char.IsLetterOrDigit(dtd[x]) || dtd[x] == ' ')) - x--; - string dtdSubstring = dtd.Substring(x); - return StringUtility.ToUpperInvariant(dtdSubstring); - } - - internal static string FixProcedureName(string spName) - { - if (IsSyntacticallyCorrect(spName)) return spName; - - return $"`{spName.Replace("`", "``")}`"; - } - - /// - /// Verify if the string passed as argument is syntactically correct. - /// - /// String to be analyzed - /// true if is correct; otherwise, false. - internal static bool IsSyntacticallyCorrect(string spName) - { - const char backtick = '`', dot = '.'; - - char[] spNameArray = spName.ToArray(); - bool quoted = spName.StartsWith("`"); - bool splittingDot = false; - - for (int i = 1; i < spNameArray.Length; i++) - { - if (spNameArray[i] == backtick) - { - // We are in quoted mode. - if (quoted) - { - // we are not in the last char of the string. - if (i < spNameArray.Length - 1) - { - // Get the next char. - char nextChar = spNameArray[i + 1]; - - // If the next char are neither a dot nor a backtick, - // it means the input string is not well quoted and exits the loop. - if (nextChar != dot && nextChar != backtick) - return false; - - // If the next char is a backtick, move forward 2 positions. - if (nextChar == backtick) - i++; - - // If the next char is a dot, that means we are not in quoted mode anymore. - if (nextChar == dot) - { - quoted = false; - splittingDot = true; - i++; - } - } - } - // Not quoted mode - else - { - // If the previous char is not a dot or the string does not end with a backtick, - // it means the input string is not well quoted and exits the loop; - // otherwise, enter quoted mode. - if (spNameArray[i - 1] != dot || !spName.EndsWith("`")) - return false; - - quoted = true; - } - } - else if (spNameArray[i] == dot && !quoted) - if (splittingDot) - return false; - else - splittingDot = true; - } - - // If we reach to the very last char of the string, it means the string is well written. - return true; - } - - private MySqlParameter GetAndFixParameter(string spName, MySqlSchemaRow param, bool realAsFloat, MySqlParameter returnParameter) - { - string mode = (string)param["PARAMETER_MODE"]; - string pName = (string)param["PARAMETER_NAME"]; - string datatype = (string)param["DATA_TYPE"]; - bool unsigned = GetFlags(param["DTD_IDENTIFIER"].ToString()).IndexOf("UNSIGNED") != -1; - - if (Convert.ToUInt64(param["ORDINAL_POSITION"]) == 0) - { - if (returnParameter == null) - throw new InvalidOperationException(String.Format(Resources.RoutineRequiresReturnParameter, spName)); - pName = returnParameter.ParameterName; - } - - // make sure the parameters given to us have an appropriate type set if it's not already - MySqlParameter p = command.Parameters.GetParameterFlexible(pName, true); - if (!p.TypeHasBeenSet) - p.MySqlDbType = MetaData.NameToType(datatype, unsigned, realAsFloat, Connection); - - return p; - } - - private async Task CheckParametersAsync(string spName, bool execAsync) - { - MySqlParameterCollection newParms = new MySqlParameterCollection(command); - MySqlParameter returnParameter = GetReturnParameter(); - - ProcedureCacheEntry entry = await GetParametersAsync(spName, execAsync).ConfigureAwait(false); - if (entry.procedure == null || entry.procedure.Rows.Count == 0) - throw new InvalidOperationException(String.Format(Resources.RoutineNotFound, spName)); - - bool realAsFloat = entry.procedure.Rows[0]["SQL_MODE"].ToString().IndexOf("REAL_AS_FLOAT") != -1; - - foreach (MySqlSchemaRow param in entry.parameters.Rows) - newParms.Add(GetAndFixParameter(spName, param, realAsFloat, returnParameter)); - return newParms; - } - - public override void Resolve(bool preparing) - { - // check to see if we are already resolved - if (ResolvedCommandText != null) return; - - ServerProvidingOutputParameters = Driver.SupportsOutputParameters && preparing; - - // first retrieve the procedure definition from our - // procedure cache - string spName = commandText; - spName = FixProcedureName(spName); - - MySqlParameter returnParameter = GetReturnParameter(); - - MySqlParameterCollection parms = command.Connection.Settings.CheckParameters ? - CheckParametersAsync(spName, false).GetAwaiter().GetResult() : Parameters; - - string setSql = SetUserVariables(parms, preparing); - string callSql = CreateCallStatement(spName, returnParameter, parms); - string outSql = CreateOutputSelect(parms, preparing); - resolvedCommandText = String.Format("{0}{1}{2}", setSql, callSql, outSql); - } - - private string SetUserVariables(MySqlParameterCollection parms, bool preparing) - { - StringBuilder setSql = new StringBuilder(); - - if (ServerProvidingOutputParameters) return setSql.ToString(); - - string delimiter = String.Empty; - foreach (MySqlParameter p in parms) - { - if (p.Direction != ParameterDirection.InputOutput) continue; - - string pName = "@" + p.BaseName; - string uName = "@" + ParameterPrefix + p.BaseName; - string sql = String.Format("SET {0}={1}", uName, pName); - - if (command.Connection.Settings.AllowBatch && !preparing) - { - setSql.AppendFormat(CultureInfo.InvariantCulture, "{0}{1}", delimiter, sql); - delimiter = "; "; - } - else - { - MySqlCommand cmd = new MySqlCommand(sql, command.Connection); - cmd.Parameters.Add(p); - cmd.ExecuteNonQuery(); - } - } - if (setSql.Length > 0) - setSql.Append("; "); - return setSql.ToString(); - } - - private string CreateCallStatement(string spName, MySqlParameter returnParameter, MySqlParameterCollection parms) - { - StringBuilder callSql = new StringBuilder(); - - string delimiter = String.Empty; - foreach (MySqlParameter p in parms) - { - if (p.Direction == ParameterDirection.ReturnValue) continue; - - string pName = "@" + p.BaseName; - string uName = "@" + ParameterPrefix + p.BaseName; - - bool useRealVar = p.Direction == ParameterDirection.Input || ServerProvidingOutputParameters; - callSql.AppendFormat(CultureInfo.InvariantCulture, "{0}{1}", delimiter, useRealVar ? pName : uName); - delimiter = ", "; - } - - if (returnParameter == null) - return String.Format("CALL {0}({1})", spName, callSql.ToString()); - else - return String.Format("SET @{0}{1}={2}({3})", ParameterPrefix, returnParameter.BaseName, spName, callSql.ToString()); - } - - private string CreateOutputSelect(MySqlParameterCollection parms, bool preparing) - { - StringBuilder outSql = new StringBuilder(); - - string delimiter = String.Empty; - foreach (MySqlParameter p in parms) - { - if (p.Direction == ParameterDirection.Input) continue; - if ((p.Direction == ParameterDirection.InputOutput || - p.Direction == ParameterDirection.Output) && - ServerProvidingOutputParameters) continue; - string pName = "@" + p.BaseName; - string uName = "@" + ParameterPrefix + p.BaseName; - - outSql.AppendFormat(CultureInfo.InvariantCulture, "{0}{1}", delimiter, uName); - delimiter = ", "; - } - - if (outSql.Length == 0) return String.Empty; - - if (command.Connection.Settings.AllowBatch && !preparing) - return String.Format(";SELECT {0}", outSql.ToString()); - - _outSelect = String.Format("SELECT {0}", outSql.ToString()); - return String.Empty; - } - - internal void ProcessOutputParameters(MySqlDataReader reader) - { - // We apparently need to always adjust our output types since the server - // provided data types are not always right - AdjustOutputTypes(reader); - - if ((reader.CommandBehavior & CommandBehavior.SchemaOnly) != 0) - return; - - // now read the output parameters data row - reader.Read(); - - string prefix = "@" + StoredProcedure.ParameterPrefix; - - for (int i = 0; i < reader.FieldCount; i++) - { - string fieldName = reader.GetName(i); - if (fieldName.StartsWith(prefix, StringComparison.OrdinalIgnoreCase)) - fieldName = fieldName.Remove(0, prefix.Length); - MySqlParameter parameter = command.Parameters.GetParameterFlexible(fieldName, true); - parameter.Value = reader.GetValue(i); - } - } - - private void AdjustOutputTypes(MySqlDataReader reader) - { - // since MySQL likes to return user variables as strings - // we reset the types of the readers internal value objects - // this will allow those value objects to parse the string based - // return values - for (int i = 0; i < reader.FieldCount; i++) - { - string fieldName = reader.GetName(i); - if (fieldName.IndexOf(StoredProcedure.ParameterPrefix) != -1) - fieldName = fieldName.Remove(0, StoredProcedure.ParameterPrefix.Length + 1); - MySqlParameter parameter = command.Parameters.GetParameterFlexible(fieldName, true); - - IMySqlValue v = MySqlField.GetIMySqlValue(parameter.MySqlDbType); - if (v is MySqlBit) - { - MySqlBit bit = (MySqlBit)v; - bit.ReadAsString = true; - reader.ResultSet.SetValueObject(i, bit); - } - else - reader.ResultSet.SetValueObject(i, v); - } - } - - public override void Close(MySqlDataReader reader) - { - if (String.IsNullOrEmpty(_outSelect)) return; - if ((reader.CommandBehavior & CommandBehavior.SchemaOnly) != 0) return; - - MySqlCommand cmd = new MySqlCommand(_outSelect, command.Connection); - cmd.InternallyCreated = true; - - using (MySqlDataReader rdr = cmd.ExecuteReader(reader.CommandBehavior)) - ProcessOutputParameters(rdr); - } - } -} +// Copyright © 2004, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySql.Data.Common; +using MySql.Data.Types; +using System; +using System.Data; +using System.Globalization; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace MySql.Data.MySqlClient +{ + /// + /// Summary description for StoredProcedure. + /// + internal class StoredProcedure : PreparableStatement + { + private string _outSelect; + private string resolvedCommandText; + + public StoredProcedure(MySqlCommand cmd, string text) + : base(cmd, text) + { + } + + private MySqlParameter GetReturnParameter() + { + return Parameters?.Cast().FirstOrDefault(p => p.Direction == ParameterDirection.ReturnValue); + } + + public override string ResolvedCommandText + { + get { return resolvedCommandText; } + } + + internal string GetCacheKey(string spName) + { + string retValue = String.Empty; + StringBuilder key = new StringBuilder(spName); + key.Append("("); + string delimiter = ""; + foreach (MySqlParameter p in command.Parameters) + { + if (p.Direction == ParameterDirection.ReturnValue) + retValue = "?="; + else + { + key.AppendFormat(CultureInfo.InvariantCulture, "{0}?", delimiter); + delimiter = ","; + } + } + key.Append(")"); + return retValue + key.ToString(); + } + + private async Task GetParametersAsync(string procName, bool execAsync) + { + string procCacheKey = GetCacheKey(procName); + ProcedureCacheEntry entry = await Connection.ProcedureCache.GetProcedureAsync(Connection, procName, procCacheKey, execAsync).ConfigureAwait(false); + return entry; + } + + public static string GetFlags(string dtd) + { + int x = dtd.Length - 1; + while (x > 0 && (Char.IsLetterOrDigit(dtd[x]) || dtd[x] == ' ')) + x--; + string dtdSubstring = dtd.Substring(x); + return StringUtility.ToUpperInvariant(dtdSubstring); + } + + internal static string FixProcedureName(string spName) + { + if (IsSyntacticallyCorrect(spName)) return spName; + + return $"`{spName.Replace("`", "``")}`"; + } + + /// + /// Verify if the string passed as argument is syntactically correct. + /// + /// String to be analyzed + /// true if is correct; otherwise, false. + internal static bool IsSyntacticallyCorrect(string spName) + { + const char backtick = '`', dot = '.'; + + char[] spNameArray = spName.ToArray(); + bool quoted = spName.StartsWith("`"); + bool splittingDot = false; + + for (int i = 1; i < spNameArray.Length; i++) + { + if (spNameArray[i] == backtick) + { + // We are in quoted mode. + if (quoted) + { + // we are not in the last char of the string. + if (i < spNameArray.Length - 1) + { + // Get the next char. + char nextChar = spNameArray[i + 1]; + + // If the next char are neither a dot nor a backtick, + // it means the input string is not well quoted and exits the loop. + if (nextChar != dot && nextChar != backtick) + return false; + + // If the next char is a backtick, move forward 2 positions. + if (nextChar == backtick) + i++; + + // If the next char is a dot, that means we are not in quoted mode anymore. + if (nextChar == dot) + { + quoted = false; + splittingDot = true; + i++; + } + } + } + // Not quoted mode + else + { + // If the previous char is not a dot or the string does not end with a backtick, + // it means the input string is not well quoted and exits the loop; + // otherwise, enter quoted mode. + if (spNameArray[i - 1] != dot || !spName.EndsWith("`")) + return false; + + quoted = true; + } + } + else if (spNameArray[i] == dot && !quoted) + if (splittingDot) + return false; + else + splittingDot = true; + } + + // If we reach to the very last char of the string, it means the string is well written. + return true; + } + + private MySqlParameter GetAndFixParameter(string spName, MySqlSchemaRow param, bool realAsFloat, MySqlParameter returnParameter) + { + string mode = (string)param["PARAMETER_MODE"]; + string pName = (string)param["PARAMETER_NAME"]; + string datatype = (string)param["DATA_TYPE"]; + bool unsigned = GetFlags(param["DTD_IDENTIFIER"].ToString()).IndexOf("UNSIGNED") != -1; + + if (Convert.ToUInt64(param["ORDINAL_POSITION"]) == 0) + { + if (returnParameter == null) + throw new InvalidOperationException(String.Format(Resources.RoutineRequiresReturnParameter, spName)); + pName = returnParameter.ParameterName; + } + + // make sure the parameters given to us have an appropriate type set if it's not already + MySqlParameter p = command.Parameters.GetParameterFlexible(pName, true); + if (!p.TypeHasBeenSet) + p.MySqlDbType = MetaData.NameToType(datatype, unsigned, realAsFloat, Connection); + + return p; + } + + private async Task CheckParametersAsync(string spName, bool execAsync) + { + MySqlParameterCollection newParms = new MySqlParameterCollection(command); + MySqlParameter returnParameter = GetReturnParameter(); + + ProcedureCacheEntry entry = await GetParametersAsync(spName, execAsync).ConfigureAwait(false); + if (entry.procedure == null || entry.procedure.Rows.Count == 0) + throw new InvalidOperationException(String.Format(Resources.RoutineNotFound, spName)); + + bool realAsFloat = entry.procedure.Rows[0]["SQL_MODE"].ToString().IndexOf("REAL_AS_FLOAT") != -1; + + foreach (MySqlSchemaRow param in entry.parameters.Rows) + newParms.Add(GetAndFixParameter(spName, param, realAsFloat, returnParameter)); + return newParms; + } + + public override void Resolve(bool preparing) + { + // check to see if we are already resolved + if (ResolvedCommandText != null) return; + + ServerProvidingOutputParameters = Driver.SupportsOutputParameters && preparing; + + // first retrieve the procedure definition from our + // procedure cache + string spName = commandText; + spName = FixProcedureName(spName); + + MySqlParameter returnParameter = GetReturnParameter(); + + MySqlParameterCollection parms = command.Connection.Settings.CheckParameters ? + CheckParametersAsync(spName, false).GetAwaiter().GetResult() : Parameters; + + string setSql = SetUserVariables(parms, preparing); + string callSql = CreateCallStatement(spName, returnParameter, parms); + string outSql = CreateOutputSelect(parms, preparing); + resolvedCommandText = String.Format("{0}{1}{2}", setSql, callSql, outSql); + } + + private string SetUserVariables(MySqlParameterCollection parms, bool preparing) + { + StringBuilder setSql = new StringBuilder(); + + if (ServerProvidingOutputParameters) return setSql.ToString(); + + string delimiter = String.Empty; + foreach (MySqlParameter p in parms) + { + if (p.Direction != ParameterDirection.InputOutput) continue; + + string pName = "@" + p.BaseName; + string uName = "@" + ParameterPrefix + p.BaseName; + string sql = String.Format("SET {0}={1}", uName, pName); + + if (command.Connection.Settings.AllowBatch && !preparing) + { + setSql.AppendFormat(CultureInfo.InvariantCulture, "{0}{1}", delimiter, sql); + delimiter = "; "; + } + else + { + MySqlCommand cmd = new MySqlCommand(sql, command.Connection); + cmd.Parameters.Add(p); + cmd.ExecuteNonQuery(); + } + } + if (setSql.Length > 0) + setSql.Append("; "); + return setSql.ToString(); + } + + private string CreateCallStatement(string spName, MySqlParameter returnParameter, MySqlParameterCollection parms) + { + StringBuilder callSql = new StringBuilder(); + + string delimiter = String.Empty; + foreach (MySqlParameter p in parms) + { + if (p.Direction == ParameterDirection.ReturnValue) continue; + + string pName = "@" + p.BaseName; + string uName = "@" + ParameterPrefix + p.BaseName; + + bool useRealVar = p.Direction == ParameterDirection.Input || ServerProvidingOutputParameters; + callSql.AppendFormat(CultureInfo.InvariantCulture, "{0}{1}", delimiter, useRealVar ? pName : uName); + delimiter = ", "; + } + + if (returnParameter == null) + return String.Format("CALL {0}({1})", spName, callSql.ToString()); + else + return String.Format("SET @{0}{1}={2}({3})", ParameterPrefix, returnParameter.BaseName, spName, callSql.ToString()); + } + + private string CreateOutputSelect(MySqlParameterCollection parms, bool preparing) + { + StringBuilder outSql = new StringBuilder(); + + string delimiter = String.Empty; + foreach (MySqlParameter p in parms) + { + if (p.Direction == ParameterDirection.Input) continue; + if ((p.Direction == ParameterDirection.InputOutput || + p.Direction == ParameterDirection.Output) && + ServerProvidingOutputParameters) continue; + string pName = "@" + p.BaseName; + string uName = "@" + ParameterPrefix + p.BaseName; + + outSql.AppendFormat(CultureInfo.InvariantCulture, "{0}{1}", delimiter, uName); + delimiter = ", "; + } + + if (outSql.Length == 0) return String.Empty; + + if (command.Connection.Settings.AllowBatch && !preparing) + return String.Format(";SELECT {0}", outSql.ToString()); + + _outSelect = String.Format("SELECT {0}", outSql.ToString()); + return String.Empty; + } + + internal void ProcessOutputParameters(MySqlDataReader reader) + { + // We apparently need to always adjust our output types since the server + // provided data types are not always right + AdjustOutputTypes(reader); + + if ((reader.CommandBehavior & CommandBehavior.SchemaOnly) != 0) + return; + + // now read the output parameters data row + reader.Read(); + + string prefix = "@" + StoredProcedure.ParameterPrefix; + + for (int i = 0; i < reader.FieldCount; i++) + { + string fieldName = reader.GetName(i); + if (fieldName.StartsWith(prefix, StringComparison.OrdinalIgnoreCase)) + fieldName = fieldName.Remove(0, prefix.Length); + MySqlParameter parameter = command.Parameters.GetParameterFlexible(fieldName, true); + parameter.Value = reader.GetValue(i); + } + } + + private void AdjustOutputTypes(MySqlDataReader reader) + { + // since MySQL likes to return user variables as strings + // we reset the types of the readers internal value objects + // this will allow those value objects to parse the string based + // return values + for (int i = 0; i < reader.FieldCount; i++) + { + string fieldName = reader.GetName(i); + if (fieldName.IndexOf(StoredProcedure.ParameterPrefix) != -1) + fieldName = fieldName.Remove(0, StoredProcedure.ParameterPrefix.Length + 1); + MySqlParameter parameter = command.Parameters.GetParameterFlexible(fieldName, true); + + IMySqlValue v = MySqlField.GetIMySqlValue(parameter.MySqlDbType); + if (v is MySqlBit) + { + MySqlBit bit = (MySqlBit)v; + bit.ReadAsString = true; + reader.ResultSet.SetValueObject(i, bit); + } + else + reader.ResultSet.SetValueObject(i, v); + } + } + + public override void Close(MySqlDataReader reader) + { + if (String.IsNullOrEmpty(_outSelect)) return; + if ((reader.CommandBehavior & CommandBehavior.SchemaOnly) != 0) return; + + MySqlCommand cmd = new MySqlCommand(_outSelect, command.Connection); + cmd.InternallyCreated = true; + + using (MySqlDataReader rdr = cmd.ExecuteReader(reader.CommandBehavior)) + ProcessOutputParameters(rdr); + } + } +} diff --git a/MySQL.Data/src/TableCache.cs b/MySQL.Data/src/TableCache.cs index 5d54a9e16..3928a3ec3 100644 --- a/MySQL.Data/src/TableCache.cs +++ b/MySQL.Data/src/TableCache.cs @@ -1,164 +1,164 @@ -// Copyright � 2016, 2018, Oracle and/or its affiliates. All rights reserved. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using System; -using System.Collections.Generic; -using System.Linq; - -namespace MySql.Data.MySqlClient -{ - internal class TableCache - { - private static readonly BaseTableCache cache; - - static TableCache() - { - cache = new BaseTableCache(480 /* 8 hour max by default */); - } - - public static void AddToCache(string commandText, ResultSet resultSet) - { - cache.AddToCache(commandText, resultSet); - } - - public static ResultSet RetrieveFromCache(string commandText, int cacheAge) - { - return (ResultSet)cache.RetrieveFromCache(commandText, cacheAge); - } - - public static void RemoveFromCache(string commandText) - { - cache.RemoveFromCache(commandText); - } - - public static void DumpCache() - { - cache.Dump(); - } - } - - /// - /// Defines the basic operations to be performed on the table cache. - /// - public class BaseTableCache - { - /// - /// The maximum age allowed for cache entries. - /// - protected int MaxCacheAge; - - private Dictionary cache = new Dictionary(); - - public BaseTableCache(int maxCacheAge) - { - MaxCacheAge = maxCacheAge; - } - - /// - /// Adds the given command and result set to the cache. - /// - /// The command to store in the cache. - /// The resultset associated to the stored command. - public virtual void AddToCache(string commandText, object resultSet) - { - CleanCache(); - CacheEntry entry = new CacheEntry(); - entry.CacheTime = DateTime.Now; - entry.CacheElement = resultSet; - lock (cache) - { - if (cache.ContainsKey(commandText)) return; - cache.Add(commandText, entry); - } - } - - /// - /// Retrieves the specified command from the cache. - /// - /// The command to retrieve. - /// The allowed age for the cache entry. - /// - public virtual object RetrieveFromCache(string commandText, int cacheAge) - { - CleanCache(); - lock (cache) - { - if (!cache.ContainsKey(commandText)) return null; - CacheEntry entry = cache[commandText]; - if (DateTime.Now.Subtract(entry.CacheTime).TotalSeconds > cacheAge) return null; - return entry.CacheElement; - } - } - - /// - /// Removes the specified command from the cache. - /// - /// The command to remove from the cache. - public void RemoveFromCache(string commandText) - { - lock (cache) - { - if (!cache.ContainsKey(commandText)) return; - cache.Remove(commandText); - } - } - - /// - /// Clears the cache. - /// - public virtual void Dump() - { - lock (cache) - cache.Clear(); - } - - /// - /// Removes cache entries older than the value defined by . - /// - protected virtual void CleanCache() - { - DateTime now = DateTime.Now; - List keysToRemove = new List(); - - lock (cache) - { - keysToRemove.AddRange(from key in cache.Keys let diff = now.Subtract(cache[key].CacheTime) where diff.TotalSeconds > MaxCacheAge select key); - - foreach (string key in keysToRemove) - cache.Remove(key); - } - } - - private struct CacheEntry - { - public DateTime CacheTime; - public object CacheElement; - } - } - +// Copyright © 2016, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using System; +using System.Collections.Generic; +using System.Linq; + +namespace MySql.Data.MySqlClient +{ + internal class TableCache + { + private static readonly BaseTableCache cache; + + static TableCache() + { + cache = new BaseTableCache(480 /* 8 hour max by default */); + } + + public static void AddToCache(string commandText, ResultSet resultSet) + { + cache.AddToCache(commandText, resultSet); + } + + public static ResultSet RetrieveFromCache(string commandText, int cacheAge) + { + return (ResultSet)cache.RetrieveFromCache(commandText, cacheAge); + } + + public static void RemoveFromCache(string commandText) + { + cache.RemoveFromCache(commandText); + } + + public static void DumpCache() + { + cache.Dump(); + } + } + + /// + /// Defines the basic operations to be performed on the table cache. + /// + public class BaseTableCache + { + /// + /// The maximum age allowed for cache entries. + /// + protected int MaxCacheAge; + + private Dictionary cache = new Dictionary(); + + public BaseTableCache(int maxCacheAge) + { + MaxCacheAge = maxCacheAge; + } + + /// + /// Adds the given command and result set to the cache. + /// + /// The command to store in the cache. + /// The resultset associated to the stored command. + public virtual void AddToCache(string commandText, object resultSet) + { + CleanCache(); + CacheEntry entry = new CacheEntry(); + entry.CacheTime = DateTime.Now; + entry.CacheElement = resultSet; + lock (cache) + { + if (cache.ContainsKey(commandText)) return; + cache.Add(commandText, entry); + } + } + + /// + /// Retrieves the specified command from the cache. + /// + /// The command to retrieve. + /// The allowed age for the cache entry. + /// + public virtual object RetrieveFromCache(string commandText, int cacheAge) + { + CleanCache(); + lock (cache) + { + if (!cache.ContainsKey(commandText)) return null; + CacheEntry entry = cache[commandText]; + if (DateTime.Now.Subtract(entry.CacheTime).TotalSeconds > cacheAge) return null; + return entry.CacheElement; + } + } + + /// + /// Removes the specified command from the cache. + /// + /// The command to remove from the cache. + public void RemoveFromCache(string commandText) + { + lock (cache) + { + if (!cache.ContainsKey(commandText)) return; + cache.Remove(commandText); + } + } + + /// + /// Clears the cache. + /// + public virtual void Dump() + { + lock (cache) + cache.Clear(); + } + + /// + /// Removes cache entries older than the value defined by . + /// + protected virtual void CleanCache() + { + DateTime now = DateTime.Now; + List keysToRemove = new List(); + + lock (cache) + { + keysToRemove.AddRange(from key in cache.Keys let diff = now.Subtract(cache[key].CacheTime) where diff.TotalSeconds > MaxCacheAge select key); + + foreach (string key in keysToRemove) + cache.Remove(key); + } + } + + private struct CacheEntry + { + public DateTime CacheTime; + public object CacheElement; + } + } + } \ No newline at end of file diff --git a/MySQL.Data/src/TimedStream.cs b/MySQL.Data/src/TimedStream.cs index f8853b795..d622c4126 100644 --- a/MySQL.Data/src/TimedStream.cs +++ b/MySQL.Data/src/TimedStream.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2009, 2022, Oracle and/or its affiliates. +// Copyright © 2009, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/TracingDriver.cs b/MySQL.Data/src/TracingDriver.cs index 300fccf02..22fb996cd 100644 --- a/MySQL.Data/src/TracingDriver.cs +++ b/MySQL.Data/src/TracingDriver.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2009, 2022, Oracle and/or its affiliates. +// Copyright © 2009, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/Types/IMySqlValue.cs b/MySQL.Data/src/Types/IMySqlValue.cs index e545560af..891e62bb1 100644 --- a/MySQL.Data/src/Types/IMySqlValue.cs +++ b/MySQL.Data/src/Types/IMySqlValue.cs @@ -1,47 +1,47 @@ -// Copyright (c) 2004, 2022, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySql.Data.MySqlClient; -using System; -using System.Threading.Tasks; - -namespace MySql.Data.Types -{ - internal interface IMySqlValue - { - bool IsNull { get; } - MySqlDbType MySqlDbType { get; } - object Value { get; /*set;*/ } - Type SystemType { get; } - string MySqlTypeName { get; } - - Task WriteValueAsync(MySqlPacket packet, bool binary, object value, int length, bool execAsync); - Task ReadValueAsync(MySqlPacket packet, long length, bool isNull, bool execAsync); - void SkipValue(MySqlPacket packet); - } -} +// Copyright © 2004, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySql.Data.MySqlClient; +using System; +using System.Threading.Tasks; + +namespace MySql.Data.Types +{ + internal interface IMySqlValue + { + bool IsNull { get; } + MySqlDbType MySqlDbType { get; } + object Value { get; /*set;*/ } + Type SystemType { get; } + string MySqlTypeName { get; } + + Task WriteValueAsync(MySqlPacket packet, bool binary, object value, int length, bool execAsync); + Task ReadValueAsync(MySqlPacket packet, long length, bool isNull, bool execAsync); + void SkipValue(MySqlPacket packet); + } +} diff --git a/MySQL.Data/src/Types/MetaData.cs b/MySQL.Data/src/Types/MetaData.cs index 59a39f286..9d3df15a6 100644 --- a/MySQL.Data/src/Types/MetaData.cs +++ b/MySQL.Data/src/Types/MetaData.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2004, 2020, Oracle and/or its affiliates. +// Copyright © 2004, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -162,4 +162,4 @@ public static MySqlDbType NameToType(string typeName, bool unsigned, throw new MySqlException("Unhandled type encountered"); } } -} \ No newline at end of file +} diff --git a/MySQL.Data/src/Types/MySqlBinary.cs b/MySQL.Data/src/Types/MySqlBinary.cs index 0ff7c5387..7704b7671 100644 --- a/MySQL.Data/src/Types/MySqlBinary.cs +++ b/MySQL.Data/src/Types/MySqlBinary.cs @@ -1,209 +1,209 @@ -// Copyright (c) 2004, 2022, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySql.Data.MySqlClient; -using System; -using System.Threading.Tasks; - -namespace MySql.Data.Types -{ - - internal struct MySqlBinary : IMySqlValue - { - private readonly MySqlDbType _type; - private readonly byte[] _mValue; - - public MySqlBinary(MySqlDbType type, bool isNull) - { - _type = type; - IsNull = isNull; - _mValue = null; - } - - public MySqlBinary(MySqlDbType type, byte[] val) - { - _type = type; - IsNull = false; - _mValue = val; - } - - #region IMySqlValue Members - - public bool IsNull { get; } - - MySqlDbType IMySqlValue.MySqlDbType => _type; - - object IMySqlValue.Value => _mValue; - - public byte[] Value => _mValue; - - Type IMySqlValue.SystemType => typeof(byte[]); - - string IMySqlValue.MySqlTypeName - { - get - { - switch (_type) - { - case MySqlDbType.TinyBlob: return "TINY_BLOB"; - case MySqlDbType.MediumBlob: return "MEDIUM_BLOB"; - case MySqlDbType.LongBlob: return "LONG_BLOB"; - default: - return "BLOB"; - } - } - } - - async Task IMySqlValue.WriteValueAsync(MySqlPacket packet, bool binary, object val, int length, bool execAsync) - { - byte[] buffToWrite = (val as byte[]); - if (buffToWrite == null) - { - char[] valAsChar = (val as Char[]); - if (valAsChar != null) - buffToWrite = packet.Encoding.GetBytes(valAsChar); - else - { - string s = val.ToString(); - if (length == 0) - length = s.Length; - else - s = s.Substring(0, length); - buffToWrite = packet.Encoding.GetBytes(s); - } - } - - // we assume zero or maxsize length means write all of the value - if (length == 0 || buffToWrite.Length < length) - length = buffToWrite.Length; - - if (buffToWrite == null) - throw new MySqlException("Only byte arrays and strings can be serialized by MySqlBinary"); - - if (binary) - { - await packet.WriteLengthAsync(length, execAsync).ConfigureAwait(false); - await packet.WriteAsync(buffToWrite, 0, length, execAsync).ConfigureAwait(false); - } - else - { - await packet.WriteStringNoNullAsync("_binary ", execAsync).ConfigureAwait(false); - packet.WriteByte((byte)'\''); - EscapeByteArray(buffToWrite, length, packet); - packet.WriteByte((byte)'\''); - } - } - - private static void EscapeByteArray(byte[] bytes, int length, MySqlPacket packet) - { - for (int x = 0; x < length; x++) - { - byte b = bytes[x]; - if (b == '\0') - { - packet.WriteByte((byte)'\\'); - packet.WriteByte((byte)'0'); - } - - else if (b == '\\' || b == '\'' || b == '\"') - { - packet.WriteByte((byte)'\\'); - packet.WriteByte(b); - } - else - packet.WriteByte(b); - } - } - - async Task IMySqlValue.ReadValueAsync(MySqlPacket packet, long length, bool nullVal, bool execAsync) - { - MySqlBinary b; - if (nullVal) - b = new MySqlBinary(_type, true); - else - { - if (length == -1) - length = (long)packet.ReadFieldLength(); - - byte[] newBuff = new byte[length]; - await packet.ReadAsync(newBuff, 0, (int)length, execAsync).ConfigureAwait(false); - b = new MySqlBinary(_type, newBuff); - } - return b; - } - - void IMySqlValue.SkipValue(MySqlPacket packet) - { - int len = (int)packet.ReadFieldLength(); - packet.Position += len; - } - - #endregion - - public static void SetDSInfo(MySqlSchemaCollection sc) - { - string[] types = new string[] { "BLOB", "TINYBLOB", "MEDIUMBLOB", "LONGBLOB", "BINARY", "VARBINARY" }; - MySqlDbType[] dbtype = new MySqlDbType[] { MySqlDbType.Blob, - MySqlDbType.TinyBlob, MySqlDbType.MediumBlob, MySqlDbType.LongBlob, MySqlDbType.Binary, MySqlDbType.VarBinary }; - long[] sizes = new long[] { 65535L, 255L, 16777215L, 4294967295L, 255L, 65535L }; - string[] format = new string[] { null, null, null, null, "binary({0})", "varbinary({0})" }; - string[] parms = new string[] { null, null, null, null, "length", "length" }; - - // we use name indexing because this method will only be called - // when GetSchema is called for the DataSourceInformation - // collection and then it wil be cached. - for (int x = 0; x < types.Length; x++) - { - MySqlSchemaRow row = sc.AddRow(); - row["TypeName"] = types[x]; - row["ProviderDbType"] = dbtype[x]; - row["ColumnSize"] = sizes[x]; - row["CreateFormat"] = format[x]; - row["CreateParameters"] = parms[x]; - row["DataType"] = "System.Byte[]"; - row["IsAutoincrementable"] = false; - row["IsBestMatch"] = true; - row["IsCaseSensitive"] = false; - row["IsFixedLength"] = x < 4 ? false : true; - row["IsFixedPrecisionScale"] = false; - row["IsLong"] = sizes[x] > 255; - row["IsNullable"] = true; - row["IsSearchable"] = false; - row["IsSearchableWithLike"] = false; - row["IsUnsigned"] = DBNull.Value; - row["MaximumScale"] = DBNull.Value; - row["MinimumScale"] = DBNull.Value; - row["IsConcurrencyType"] = DBNull.Value; - row["IsLiteralSupported"] = false; - row["LiteralPrefix"] = "0x"; - row["LiteralSuffix"] = DBNull.Value; - row["NativeDataType"] = DBNull.Value; - } - } - } -} +// Copyright © 2004, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySql.Data.MySqlClient; +using System; +using System.Threading.Tasks; + +namespace MySql.Data.Types +{ + + internal struct MySqlBinary : IMySqlValue + { + private readonly MySqlDbType _type; + private readonly byte[] _mValue; + + public MySqlBinary(MySqlDbType type, bool isNull) + { + _type = type; + IsNull = isNull; + _mValue = null; + } + + public MySqlBinary(MySqlDbType type, byte[] val) + { + _type = type; + IsNull = false; + _mValue = val; + } + + #region IMySqlValue Members + + public bool IsNull { get; } + + MySqlDbType IMySqlValue.MySqlDbType => _type; + + object IMySqlValue.Value => _mValue; + + public byte[] Value => _mValue; + + Type IMySqlValue.SystemType => typeof(byte[]); + + string IMySqlValue.MySqlTypeName + { + get + { + switch (_type) + { + case MySqlDbType.TinyBlob: return "TINY_BLOB"; + case MySqlDbType.MediumBlob: return "MEDIUM_BLOB"; + case MySqlDbType.LongBlob: return "LONG_BLOB"; + default: + return "BLOB"; + } + } + } + + async Task IMySqlValue.WriteValueAsync(MySqlPacket packet, bool binary, object val, int length, bool execAsync) + { + byte[] buffToWrite = (val as byte[]); + if (buffToWrite == null) + { + char[] valAsChar = (val as Char[]); + if (valAsChar != null) + buffToWrite = packet.Encoding.GetBytes(valAsChar); + else + { + string s = val.ToString(); + if (length == 0) + length = s.Length; + else + s = s.Substring(0, length); + buffToWrite = packet.Encoding.GetBytes(s); + } + } + + // we assume zero or maxsize length means write all of the value + if (length == 0 || buffToWrite.Length < length) + length = buffToWrite.Length; + + if (buffToWrite == null) + throw new MySqlException("Only byte arrays and strings can be serialized by MySqlBinary"); + + if (binary) + { + await packet.WriteLengthAsync(length, execAsync).ConfigureAwait(false); + await packet.WriteAsync(buffToWrite, 0, length, execAsync).ConfigureAwait(false); + } + else + { + await packet.WriteStringNoNullAsync("_binary ", execAsync).ConfigureAwait(false); + packet.WriteByte((byte)'\''); + EscapeByteArray(buffToWrite, length, packet); + packet.WriteByte((byte)'\''); + } + } + + private static void EscapeByteArray(byte[] bytes, int length, MySqlPacket packet) + { + for (int x = 0; x < length; x++) + { + byte b = bytes[x]; + if (b == '\0') + { + packet.WriteByte((byte)'\\'); + packet.WriteByte((byte)'0'); + } + + else if (b == '\\' || b == '\'' || b == '\"') + { + packet.WriteByte((byte)'\\'); + packet.WriteByte(b); + } + else + packet.WriteByte(b); + } + } + + async Task IMySqlValue.ReadValueAsync(MySqlPacket packet, long length, bool nullVal, bool execAsync) + { + MySqlBinary b; + if (nullVal) + b = new MySqlBinary(_type, true); + else + { + if (length == -1) + length = (long)packet.ReadFieldLength(); + + byte[] newBuff = new byte[length]; + await packet.ReadAsync(newBuff, 0, (int)length, execAsync).ConfigureAwait(false); + b = new MySqlBinary(_type, newBuff); + } + return b; + } + + void IMySqlValue.SkipValue(MySqlPacket packet) + { + int len = (int)packet.ReadFieldLength(); + packet.Position += len; + } + + #endregion + + public static void SetDSInfo(MySqlSchemaCollection sc) + { + string[] types = new string[] { "BLOB", "TINYBLOB", "MEDIUMBLOB", "LONGBLOB", "BINARY", "VARBINARY" }; + MySqlDbType[] dbtype = new MySqlDbType[] { MySqlDbType.Blob, + MySqlDbType.TinyBlob, MySqlDbType.MediumBlob, MySqlDbType.LongBlob, MySqlDbType.Binary, MySqlDbType.VarBinary }; + long[] sizes = new long[] { 65535L, 255L, 16777215L, 4294967295L, 255L, 65535L }; + string[] format = new string[] { null, null, null, null, "binary({0})", "varbinary({0})" }; + string[] parms = new string[] { null, null, null, null, "length", "length" }; + + // we use name indexing because this method will only be called + // when GetSchema is called for the DataSourceInformation + // collection and then it wil be cached. + for (int x = 0; x < types.Length; x++) + { + MySqlSchemaRow row = sc.AddRow(); + row["TypeName"] = types[x]; + row["ProviderDbType"] = dbtype[x]; + row["ColumnSize"] = sizes[x]; + row["CreateFormat"] = format[x]; + row["CreateParameters"] = parms[x]; + row["DataType"] = "System.Byte[]"; + row["IsAutoincrementable"] = false; + row["IsBestMatch"] = true; + row["IsCaseSensitive"] = false; + row["IsFixedLength"] = x < 4 ? false : true; + row["IsFixedPrecisionScale"] = false; + row["IsLong"] = sizes[x] > 255; + row["IsNullable"] = true; + row["IsSearchable"] = false; + row["IsSearchableWithLike"] = false; + row["IsUnsigned"] = DBNull.Value; + row["MaximumScale"] = DBNull.Value; + row["MinimumScale"] = DBNull.Value; + row["IsConcurrencyType"] = DBNull.Value; + row["IsLiteralSupported"] = false; + row["LiteralPrefix"] = "0x"; + row["LiteralSuffix"] = DBNull.Value; + row["NativeDataType"] = DBNull.Value; + } + } + } +} diff --git a/MySQL.Data/src/Types/MySqlBit.cs b/MySQL.Data/src/Types/MySqlBit.cs index b43efa13b..9ca6fbfcc 100644 --- a/MySQL.Data/src/Types/MySqlBit.cs +++ b/MySQL.Data/src/Types/MySqlBit.cs @@ -1,124 +1,124 @@ -// Copyright (c) 2004, 2022, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySql.Data.MySqlClient; -using System; -using System.Globalization; -using System.Threading.Tasks; - -namespace MySql.Data.Types -{ - /// - /// Summary description for MySqlUInt64. - /// - internal struct MySqlBit : IMySqlValue - { - private ulong _value; - - public MySqlBit(bool isnull) - { - _value = 0; - IsNull = isnull; - ReadAsString = false; - } - - public bool ReadAsString { get; set; } - - public bool IsNull { get; private set; } - - MySqlDbType IMySqlValue.MySqlDbType => MySqlDbType.Bit; - - object IMySqlValue.Value => _value; - - Type IMySqlValue.SystemType => typeof(ulong); - - string IMySqlValue.MySqlTypeName => "BIT"; - - async Task IMySqlValue.WriteValueAsync(MySqlPacket packet, bool binary, object value, int length, bool execAsync) - { - ulong v = value as ulong? ?? Convert.ToUInt64(value); - if (binary) - await packet.WriteIntegerAsync((long)v, 8, execAsync).ConfigureAwait(false); - else - await packet.WriteStringNoNullAsync(v.ToString(CultureInfo.InvariantCulture), execAsync).ConfigureAwait(false); - } - - async Task IMySqlValue.ReadValueAsync(MySqlPacket packet, long length, bool isNull, bool execAsync) - { - this.IsNull = isNull; - if (isNull) - return this; - - if (length == -1) - length = packet.ReadFieldLength(); - - if (ReadAsString) - _value = UInt64.Parse(await packet.ReadStringAsync(length, execAsync).ConfigureAwait(false), CultureInfo.InvariantCulture); - else - _value = (UInt64)packet.ReadBitValue((int)length); - return this; - } - - public void SkipValue(MySqlPacket packet) - { - int len = (int)packet.ReadFieldLength(); - packet.Position += len; - } - - internal static void SetDSInfo(MySqlSchemaCollection sc) - { - // we use name indexing because this method will only be called - // when GetSchema is called for the DataSourceInformation - // collection and then it wil be cached. - MySqlSchemaRow row = sc.AddRow(); - row["TypeName"] = "BIT"; - row["ProviderDbType"] = MySqlDbType.Bit; - row["ColumnSize"] = 64; - row["CreateFormat"] = "BIT"; - row["CreateParameters"] = DBNull.Value; - row["DataType"] = typeof(ulong).ToString(); - row["IsAutoincrementable"] = false; - row["IsBestMatch"] = true; - row["IsCaseSensitive"] = false; - row["IsFixedLength"] = false; - row["IsFixedPrecisionScale"] = true; - row["IsLong"] = false; - row["IsNullable"] = true; - row["IsSearchable"] = true; - row["IsSearchableWithLike"] = false; - row["IsUnsigned"] = false; - row["MaximumScale"] = 0; - row["MinimumScale"] = 0; - row["IsConcurrencyType"] = DBNull.Value; - row["IsLiteralSupported"] = false; - row["LiteralPrefix"] = DBNull.Value; - row["LiteralSuffix"] = DBNull.Value; - row["NativeDataType"] = DBNull.Value; - } - } -} +// Copyright © 2004, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySql.Data.MySqlClient; +using System; +using System.Globalization; +using System.Threading.Tasks; + +namespace MySql.Data.Types +{ + /// + /// Summary description for MySqlUInt64. + /// + internal struct MySqlBit : IMySqlValue + { + private ulong _value; + + public MySqlBit(bool isnull) + { + _value = 0; + IsNull = isnull; + ReadAsString = false; + } + + public bool ReadAsString { get; set; } + + public bool IsNull { get; private set; } + + MySqlDbType IMySqlValue.MySqlDbType => MySqlDbType.Bit; + + object IMySqlValue.Value => _value; + + Type IMySqlValue.SystemType => typeof(ulong); + + string IMySqlValue.MySqlTypeName => "BIT"; + + async Task IMySqlValue.WriteValueAsync(MySqlPacket packet, bool binary, object value, int length, bool execAsync) + { + ulong v = value as ulong? ?? Convert.ToUInt64(value); + if (binary) + await packet.WriteIntegerAsync((long)v, 8, execAsync).ConfigureAwait(false); + else + await packet.WriteStringNoNullAsync(v.ToString(CultureInfo.InvariantCulture), execAsync).ConfigureAwait(false); + } + + async Task IMySqlValue.ReadValueAsync(MySqlPacket packet, long length, bool isNull, bool execAsync) + { + this.IsNull = isNull; + if (isNull) + return this; + + if (length == -1) + length = packet.ReadFieldLength(); + + if (ReadAsString) + _value = UInt64.Parse(await packet.ReadStringAsync(length, execAsync).ConfigureAwait(false), CultureInfo.InvariantCulture); + else + _value = (UInt64)packet.ReadBitValue((int)length); + return this; + } + + public void SkipValue(MySqlPacket packet) + { + int len = (int)packet.ReadFieldLength(); + packet.Position += len; + } + + internal static void SetDSInfo(MySqlSchemaCollection sc) + { + // we use name indexing because this method will only be called + // when GetSchema is called for the DataSourceInformation + // collection and then it wil be cached. + MySqlSchemaRow row = sc.AddRow(); + row["TypeName"] = "BIT"; + row["ProviderDbType"] = MySqlDbType.Bit; + row["ColumnSize"] = 64; + row["CreateFormat"] = "BIT"; + row["CreateParameters"] = DBNull.Value; + row["DataType"] = typeof(ulong).ToString(); + row["IsAutoincrementable"] = false; + row["IsBestMatch"] = true; + row["IsCaseSensitive"] = false; + row["IsFixedLength"] = false; + row["IsFixedPrecisionScale"] = true; + row["IsLong"] = false; + row["IsNullable"] = true; + row["IsSearchable"] = true; + row["IsSearchableWithLike"] = false; + row["IsUnsigned"] = false; + row["MaximumScale"] = 0; + row["MinimumScale"] = 0; + row["IsConcurrencyType"] = DBNull.Value; + row["IsLiteralSupported"] = false; + row["LiteralPrefix"] = DBNull.Value; + row["LiteralSuffix"] = DBNull.Value; + row["NativeDataType"] = DBNull.Value; + } + } +} diff --git a/MySQL.Data/src/Types/MySqlByte.cs b/MySQL.Data/src/Types/MySqlByte.cs index cda104293..35fcbb28b 100644 --- a/MySQL.Data/src/Types/MySqlByte.cs +++ b/MySQL.Data/src/Types/MySqlByte.cs @@ -1,141 +1,141 @@ -// Copyright (c) 2004, 2022, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySql.Data.MySqlClient; -using System; -using System.Globalization; -using System.Threading.Tasks; - -namespace MySql.Data.Types -{ - internal struct MySqlByte : IMySqlValue - { - public MySqlByte(bool isNull) - { - IsNull = isNull; - Value = 0; - TreatAsBoolean = false; - } - - public MySqlByte(sbyte val) - { - IsNull = false; - Value = val; - TreatAsBoolean = false; - } - - #region IMySqlValue Members - - public bool IsNull { get; } - - MySqlDbType IMySqlValue.MySqlDbType => MySqlDbType.Byte; - - object IMySqlValue.Value - { - get - { - if (TreatAsBoolean) - return Convert.ToBoolean(Value); - return Value; - } - } - - public sbyte Value { get; set; } - - Type IMySqlValue.SystemType => TreatAsBoolean ? typeof(bool) : typeof(sbyte); - - string IMySqlValue.MySqlTypeName => "TINYINT"; - - async Task IMySqlValue.WriteValueAsync(MySqlPacket packet, bool binary, object val, int length, bool execAsync) - { - sbyte v = val as sbyte? ?? Convert.ToSByte(val); - if (binary) - packet.WriteByte((byte)v); - else - await packet.WriteStringNoNullAsync(v.ToString(CultureInfo.InvariantCulture), execAsync).ConfigureAwait(false); - } - - async Task IMySqlValue.ReadValueAsync(MySqlPacket packet, long length, bool nullVal, bool execAsync) - { - if (nullVal) - return new MySqlByte(true) { TreatAsBoolean = TreatAsBoolean }; - - MySqlByte b; - if (length == -1) - b = new MySqlByte((sbyte)packet.ReadByte()); - else - { - string s = await packet.ReadStringAsync(length, execAsync).ConfigureAwait(false); - b = new MySqlByte(SByte.Parse(s, NumberStyles.Any, CultureInfo.InvariantCulture)); - } - - b.TreatAsBoolean = TreatAsBoolean; - return b; - } - - void IMySqlValue.SkipValue(MySqlPacket packet) - { - packet.ReadByte(); - } - - #endregion - - internal bool TreatAsBoolean { get; set; } - - internal static void SetDSInfo(MySqlSchemaCollection sc) - { - // we use name indexing because this method will only be called - // when GetSchema is called for the DataSourceInformation - // collection and then it wil be cached. - MySqlSchemaRow row = sc.AddRow(); - row["TypeName"] = "TINYINT"; - row["ProviderDbType"] = MySqlDbType.Byte; - row["ColumnSize"] = 0; - row["CreateFormat"] = "TINYINT"; - row["CreateParameters"] = null; - row["DataType"] = "System.SByte"; - row["IsAutoincrementable"] = true; - row["IsBestMatch"] = true; - row["IsCaseSensitive"] = false; - row["IsFixedLength"] = true; - row["IsFixedPrecisionScale"] = true; - row["IsLong"] = false; - row["IsNullable"] = true; - row["IsSearchable"] = true; - row["IsSearchableWithLike"] = false; - row["IsUnsigned"] = false; - row["MaximumScale"] = 0; - row["MinimumScale"] = 0; - row["IsConcurrencyType"] = DBNull.Value; - row["IsLiteralSupported"] = false; - row["LiteralPrefix"] = null; - row["LiteralSuffix"] = null; - row["NativeDataType"] = null; - } - } -} +// Copyright © 2004, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySql.Data.MySqlClient; +using System; +using System.Globalization; +using System.Threading.Tasks; + +namespace MySql.Data.Types +{ + internal struct MySqlByte : IMySqlValue + { + public MySqlByte(bool isNull) + { + IsNull = isNull; + Value = 0; + TreatAsBoolean = false; + } + + public MySqlByte(sbyte val) + { + IsNull = false; + Value = val; + TreatAsBoolean = false; + } + + #region IMySqlValue Members + + public bool IsNull { get; } + + MySqlDbType IMySqlValue.MySqlDbType => MySqlDbType.Byte; + + object IMySqlValue.Value + { + get + { + if (TreatAsBoolean) + return Convert.ToBoolean(Value); + return Value; + } + } + + public sbyte Value { get; set; } + + Type IMySqlValue.SystemType => TreatAsBoolean ? typeof(bool) : typeof(sbyte); + + string IMySqlValue.MySqlTypeName => "TINYINT"; + + async Task IMySqlValue.WriteValueAsync(MySqlPacket packet, bool binary, object val, int length, bool execAsync) + { + sbyte v = val as sbyte? ?? Convert.ToSByte(val); + if (binary) + packet.WriteByte((byte)v); + else + await packet.WriteStringNoNullAsync(v.ToString(CultureInfo.InvariantCulture), execAsync).ConfigureAwait(false); + } + + async Task IMySqlValue.ReadValueAsync(MySqlPacket packet, long length, bool nullVal, bool execAsync) + { + if (nullVal) + return new MySqlByte(true) { TreatAsBoolean = TreatAsBoolean }; + + MySqlByte b; + if (length == -1) + b = new MySqlByte((sbyte)packet.ReadByte()); + else + { + string s = await packet.ReadStringAsync(length, execAsync).ConfigureAwait(false); + b = new MySqlByte(SByte.Parse(s, NumberStyles.Any, CultureInfo.InvariantCulture)); + } + + b.TreatAsBoolean = TreatAsBoolean; + return b; + } + + void IMySqlValue.SkipValue(MySqlPacket packet) + { + packet.ReadByte(); + } + + #endregion + + internal bool TreatAsBoolean { get; set; } + + internal static void SetDSInfo(MySqlSchemaCollection sc) + { + // we use name indexing because this method will only be called + // when GetSchema is called for the DataSourceInformation + // collection and then it wil be cached. + MySqlSchemaRow row = sc.AddRow(); + row["TypeName"] = "TINYINT"; + row["ProviderDbType"] = MySqlDbType.Byte; + row["ColumnSize"] = 0; + row["CreateFormat"] = "TINYINT"; + row["CreateParameters"] = null; + row["DataType"] = "System.SByte"; + row["IsAutoincrementable"] = true; + row["IsBestMatch"] = true; + row["IsCaseSensitive"] = false; + row["IsFixedLength"] = true; + row["IsFixedPrecisionScale"] = true; + row["IsLong"] = false; + row["IsNullable"] = true; + row["IsSearchable"] = true; + row["IsSearchableWithLike"] = false; + row["IsUnsigned"] = false; + row["MaximumScale"] = 0; + row["MinimumScale"] = 0; + row["IsConcurrencyType"] = DBNull.Value; + row["IsLiteralSupported"] = false; + row["LiteralPrefix"] = null; + row["LiteralSuffix"] = null; + row["NativeDataType"] = null; + } + } +} diff --git a/MySQL.Data/src/Types/MySqlConversionException.cs b/MySQL.Data/src/Types/MySqlConversionException.cs index 427bcdbbc..3ca0deaa8 100644 --- a/MySQL.Data/src/Types/MySqlConversionException.cs +++ b/MySQL.Data/src/Types/MySqlConversionException.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2004, 2017, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2004, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/Types/MySqlDateTime.cs b/MySQL.Data/src/Types/MySqlDateTime.cs index 478596996..e8984f0da 100644 --- a/MySQL.Data/src/Types/MySqlDateTime.cs +++ b/MySQL.Data/src/Types/MySqlDateTime.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2004, 2022, Oracle and/or its affiliates. +// Copyright © 2004, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/Types/MySqlDecimal.cs b/MySQL.Data/src/Types/MySqlDecimal.cs index 13205b85e..fa679f63e 100644 --- a/MySQL.Data/src/Types/MySqlDecimal.cs +++ b/MySQL.Data/src/Types/MySqlDecimal.cs @@ -1,162 +1,162 @@ -// Copyright (c) 2004, 2022, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySql.Data.MySqlClient; -using System; -using System.Globalization; -using System.Threading.Tasks; - -namespace MySql.Data.Types -{ - /// - /// Represents a decimal data type object in a MySql database. - /// - public struct MySqlDecimal : IMySqlValue - { - private readonly string _value; - - internal MySqlDecimal(bool isNull) - { - IsNull = isNull; - _value = null; - Precision = Scale = 0; - } - - internal MySqlDecimal(string val) - { - this.IsNull = false; - Precision = Scale = 0; - _value = val; - } - - #region IMySqlValue Members - - /// - /// Gets a boolean value signaling if the type is null. - /// - public bool IsNull { get; } - - MySqlDbType IMySqlValue.MySqlDbType => MySqlDbType.Decimal; - - /// - /// Gets or sets the decimal precision of the type. - /// - public byte Precision { get; set; } - - /// - /// Gets or sets the scale of the type. - /// - public byte Scale { get; set; } - - - object IMySqlValue.Value => Value; - - /// - /// Gets the decimal value associated to this type. - /// - public decimal Value => Convert.ToDecimal(_value, CultureInfo.InvariantCulture); - - /// - /// Converts this decimal value to a double value. - /// - /// The value of this type converted to a dobule value. - public double ToDouble() - { - return Double.Parse(_value, CultureInfo.InvariantCulture); - } - - public override string ToString() - { - return _value; - } - - Type IMySqlValue.SystemType => typeof(decimal); - - string IMySqlValue.MySqlTypeName => "DECIMAL"; - - async Task IMySqlValue.WriteValueAsync(MySqlPacket packet, bool binary, object val, int length, bool execAsync) - { - decimal v = val as decimal? ?? Convert.ToDecimal(val); - string valStr = v.ToString(CultureInfo.InvariantCulture); - - if (binary) - await packet.WriteLenStringAsync(valStr, execAsync).ConfigureAwait(false); - else - await packet.WriteStringNoNullAsync(valStr, execAsync).ConfigureAwait(false); - } - - async Task IMySqlValue.ReadValueAsync(MySqlPacket packet, long length, bool nullVal, bool execAsync) - { - if (nullVal) - return new MySqlDecimal(true); - - string s = String.Empty; - s = length == -1 ? await packet.ReadLenStringAsync(execAsync).ConfigureAwait(false) : await packet.ReadStringAsync(length, execAsync).ConfigureAwait(false); - return new MySqlDecimal(s); - } - - void IMySqlValue.SkipValue(MySqlPacket packet) - { - int len = (int)packet.ReadFieldLength(); - packet.Position += len; - } - - #endregion - - internal static void SetDSInfo(MySqlSchemaCollection sc) - { - // we use name indexing because this method will only be called - // when GetSchema is called for the DataSourceInformation - // collection and then it wil be cached. - MySqlSchemaRow row = sc.AddRow(); - row["TypeName"] = "DECIMAL"; - row["ProviderDbType"] = MySqlDbType.NewDecimal; - row["ColumnSize"] = 0; - row["CreateFormat"] = "DECIMAL({0},{1})"; - row["CreateParameters"] = "precision,scale"; - row["DataType"] = "System.Decimal"; - row["IsAutoincrementable"] = false; - row["IsBestMatch"] = true; - row["IsCaseSensitive"] = false; - row["IsFixedLength"] = true; - row["IsFixedPrecisionScale"] = true; - row["IsLong"] = false; - row["IsNullable"] = true; - row["IsSearchable"] = true; - row["IsSearchableWithLike"] = false; - row["IsUnsigned"] = false; - row["MaximumScale"] = 0; - row["MinimumScale"] = 0; - row["IsConcurrencyType"] = DBNull.Value; - row["IsLiteralSupported"] = false; - row["LiteralPrefix"] = null; - row["LiteralSuffix"] = null; - row["NativeDataType"] = null; - } - } -} +// Copyright © 2004, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySql.Data.MySqlClient; +using System; +using System.Globalization; +using System.Threading.Tasks; + +namespace MySql.Data.Types +{ + /// + /// Represents a decimal data type object in a MySql database. + /// + public struct MySqlDecimal : IMySqlValue + { + private readonly string _value; + + internal MySqlDecimal(bool isNull) + { + IsNull = isNull; + _value = null; + Precision = Scale = 0; + } + + internal MySqlDecimal(string val) + { + this.IsNull = false; + Precision = Scale = 0; + _value = val; + } + + #region IMySqlValue Members + + /// + /// Gets a boolean value signaling if the type is null. + /// + public bool IsNull { get; } + + MySqlDbType IMySqlValue.MySqlDbType => MySqlDbType.Decimal; + + /// + /// Gets or sets the decimal precision of the type. + /// + public byte Precision { get; set; } + + /// + /// Gets or sets the scale of the type. + /// + public byte Scale { get; set; } + + + object IMySqlValue.Value => Value; + + /// + /// Gets the decimal value associated to this type. + /// + public decimal Value => Convert.ToDecimal(_value, CultureInfo.InvariantCulture); + + /// + /// Converts this decimal value to a double value. + /// + /// The value of this type converted to a dobule value. + public double ToDouble() + { + return Double.Parse(_value, CultureInfo.InvariantCulture); + } + + public override string ToString() + { + return _value; + } + + Type IMySqlValue.SystemType => typeof(decimal); + + string IMySqlValue.MySqlTypeName => "DECIMAL"; + + async Task IMySqlValue.WriteValueAsync(MySqlPacket packet, bool binary, object val, int length, bool execAsync) + { + decimal v = val as decimal? ?? Convert.ToDecimal(val); + string valStr = v.ToString(CultureInfo.InvariantCulture); + + if (binary) + await packet.WriteLenStringAsync(valStr, execAsync).ConfigureAwait(false); + else + await packet.WriteStringNoNullAsync(valStr, execAsync).ConfigureAwait(false); + } + + async Task IMySqlValue.ReadValueAsync(MySqlPacket packet, long length, bool nullVal, bool execAsync) + { + if (nullVal) + return new MySqlDecimal(true); + + string s = String.Empty; + s = length == -1 ? await packet.ReadLenStringAsync(execAsync).ConfigureAwait(false) : await packet.ReadStringAsync(length, execAsync).ConfigureAwait(false); + return new MySqlDecimal(s); + } + + void IMySqlValue.SkipValue(MySqlPacket packet) + { + int len = (int)packet.ReadFieldLength(); + packet.Position += len; + } + + #endregion + + internal static void SetDSInfo(MySqlSchemaCollection sc) + { + // we use name indexing because this method will only be called + // when GetSchema is called for the DataSourceInformation + // collection and then it wil be cached. + MySqlSchemaRow row = sc.AddRow(); + row["TypeName"] = "DECIMAL"; + row["ProviderDbType"] = MySqlDbType.NewDecimal; + row["ColumnSize"] = 0; + row["CreateFormat"] = "DECIMAL({0},{1})"; + row["CreateParameters"] = "precision,scale"; + row["DataType"] = "System.Decimal"; + row["IsAutoincrementable"] = false; + row["IsBestMatch"] = true; + row["IsCaseSensitive"] = false; + row["IsFixedLength"] = true; + row["IsFixedPrecisionScale"] = true; + row["IsLong"] = false; + row["IsNullable"] = true; + row["IsSearchable"] = true; + row["IsSearchableWithLike"] = false; + row["IsUnsigned"] = false; + row["MaximumScale"] = 0; + row["MinimumScale"] = 0; + row["IsConcurrencyType"] = DBNull.Value; + row["IsLiteralSupported"] = false; + row["LiteralPrefix"] = null; + row["LiteralSuffix"] = null; + row["NativeDataType"] = null; + } + } +} diff --git a/MySQL.Data/src/Types/MySqlDouble.cs b/MySQL.Data/src/Types/MySqlDouble.cs index 4e8989569..150dda727 100644 --- a/MySQL.Data/src/Types/MySqlDouble.cs +++ b/MySQL.Data/src/Types/MySqlDouble.cs @@ -1,145 +1,145 @@ -// Copyright (c) 2004, 2022, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySql.Data.MySqlClient; -using System; -using System.Globalization; -using System.Threading.Tasks; - -namespace MySql.Data.Types -{ - - internal struct MySqlDouble : IMySqlValue - { - public MySqlDouble(bool isNull) - { - IsNull = isNull; - Value = 0.0; - } - - public MySqlDouble(double val) - { - IsNull = false; - Value = val; - } - - #region IMySqlValue Members - - public bool IsNull { get; } - - MySqlDbType IMySqlValue.MySqlDbType => MySqlDbType.Double; - - object IMySqlValue.Value => Value; - - public double Value { get; } - - Type IMySqlValue.SystemType => typeof(double); - - string IMySqlValue.MySqlTypeName => "DOUBLE"; - - async Task IMySqlValue.WriteValueAsync(MySqlPacket packet, bool binary, object val, int length, bool execAsync) - { - double v = val as double? ?? Convert.ToDouble(val); - if (binary) - await packet.WriteAsync(BitConverter.GetBytes(v), execAsync).ConfigureAwait(false); - else - await packet.WriteStringNoNullAsync(v.ToString("R", CultureInfo.InvariantCulture), execAsync).ConfigureAwait(false); - } - - async Task IMySqlValue.ReadValueAsync(MySqlPacket packet, long length, bool nullVal, bool execAsync) - { - if (nullVal) - return new MySqlDouble(true); - - if (length == -1) - { - byte[] b = new byte[8]; - await packet.ReadAsync(b, 0, 8, execAsync).ConfigureAwait(false); - return new MySqlDouble(BitConverter.ToDouble(b, 0)); - } - - string s = await packet.ReadStringAsync(length, execAsync).ConfigureAwait(false); - double d; - - try - { - d = Double.Parse(s, CultureInfo.InvariantCulture); - } - catch (OverflowException) - { - // MySQL server < 5.5 can return values not compatible with - // Double.Parse(), i.e out of range for double. - - if (s.StartsWith("-", StringComparison.Ordinal)) - d = double.MinValue; - else - d = double.MaxValue; - } - - return new MySqlDouble(d); - } - - void IMySqlValue.SkipValue(MySqlPacket packet) - { - packet.Position += 8; - } - - #endregion - - internal static void SetDSInfo(MySqlSchemaCollection sc) - { - // we use name indexing because this method will only be called - // when GetSchema is called for the DataSourceInformation - // collection and then it wil be cached. - MySqlSchemaRow row = sc.AddRow(); - row["TypeName"] = "DOUBLE"; - row["ProviderDbType"] = MySqlDbType.Double; - row["ColumnSize"] = 0; - row["CreateFormat"] = "DOUBLE"; - row["CreateParameters"] = null; - row["DataType"] = "System.Double"; - row["IsAutoincrementable"] = false; - row["IsBestMatch"] = true; - row["IsCaseSensitive"] = false; - row["IsFixedLength"] = true; - row["IsFixedPrecisionScale"] = true; - row["IsLong"] = false; - row["IsNullable"] = true; - row["IsSearchable"] = true; - row["IsSearchableWithLike"] = false; - row["IsUnsigned"] = false; - row["MaximumScale"] = 0; - row["MinimumScale"] = 0; - row["IsConcurrencyType"] = DBNull.Value; - row["IsLiteralSupported"] = false; - row["LiteralPrefix"] = null; - row["LiteralSuffix"] = null; - row["NativeDataType"] = null; - } - } -} \ No newline at end of file +// Copyright © 2004, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySql.Data.MySqlClient; +using System; +using System.Globalization; +using System.Threading.Tasks; + +namespace MySql.Data.Types +{ + + internal struct MySqlDouble : IMySqlValue + { + public MySqlDouble(bool isNull) + { + IsNull = isNull; + Value = 0.0; + } + + public MySqlDouble(double val) + { + IsNull = false; + Value = val; + } + + #region IMySqlValue Members + + public bool IsNull { get; } + + MySqlDbType IMySqlValue.MySqlDbType => MySqlDbType.Double; + + object IMySqlValue.Value => Value; + + public double Value { get; } + + Type IMySqlValue.SystemType => typeof(double); + + string IMySqlValue.MySqlTypeName => "DOUBLE"; + + async Task IMySqlValue.WriteValueAsync(MySqlPacket packet, bool binary, object val, int length, bool execAsync) + { + double v = val as double? ?? Convert.ToDouble(val); + if (binary) + await packet.WriteAsync(BitConverter.GetBytes(v), execAsync).ConfigureAwait(false); + else + await packet.WriteStringNoNullAsync(v.ToString("R", CultureInfo.InvariantCulture), execAsync).ConfigureAwait(false); + } + + async Task IMySqlValue.ReadValueAsync(MySqlPacket packet, long length, bool nullVal, bool execAsync) + { + if (nullVal) + return new MySqlDouble(true); + + if (length == -1) + { + byte[] b = new byte[8]; + await packet.ReadAsync(b, 0, 8, execAsync).ConfigureAwait(false); + return new MySqlDouble(BitConverter.ToDouble(b, 0)); + } + + string s = await packet.ReadStringAsync(length, execAsync).ConfigureAwait(false); + double d; + + try + { + d = Double.Parse(s, CultureInfo.InvariantCulture); + } + catch (OverflowException) + { + // MySQL server < 5.5 can return values not compatible with + // Double.Parse(), i.e out of range for double. + + if (s.StartsWith("-", StringComparison.Ordinal)) + d = double.MinValue; + else + d = double.MaxValue; + } + + return new MySqlDouble(d); + } + + void IMySqlValue.SkipValue(MySqlPacket packet) + { + packet.Position += 8; + } + + #endregion + + internal static void SetDSInfo(MySqlSchemaCollection sc) + { + // we use name indexing because this method will only be called + // when GetSchema is called for the DataSourceInformation + // collection and then it wil be cached. + MySqlSchemaRow row = sc.AddRow(); + row["TypeName"] = "DOUBLE"; + row["ProviderDbType"] = MySqlDbType.Double; + row["ColumnSize"] = 0; + row["CreateFormat"] = "DOUBLE"; + row["CreateParameters"] = null; + row["DataType"] = "System.Double"; + row["IsAutoincrementable"] = false; + row["IsBestMatch"] = true; + row["IsCaseSensitive"] = false; + row["IsFixedLength"] = true; + row["IsFixedPrecisionScale"] = true; + row["IsLong"] = false; + row["IsNullable"] = true; + row["IsSearchable"] = true; + row["IsSearchableWithLike"] = false; + row["IsUnsigned"] = false; + row["MaximumScale"] = 0; + row["MinimumScale"] = 0; + row["IsConcurrencyType"] = DBNull.Value; + row["IsLiteralSupported"] = false; + row["LiteralPrefix"] = null; + row["LiteralSuffix"] = null; + row["NativeDataType"] = null; + } + } +} diff --git a/MySQL.Data/src/Types/MySqlGeometry.cs b/MySQL.Data/src/Types/MySqlGeometry.cs index cb56723fc..9b71626d9 100644 --- a/MySQL.Data/src/Types/MySqlGeometry.cs +++ b/MySQL.Data/src/Types/MySqlGeometry.cs @@ -1,395 +1,395 @@ -// Copyright (c) 2013, 2022, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySql.Data.MySqlClient; -using System; -using System.Globalization; -using System.Threading.Tasks; - -namespace MySql.Data.Types -{ - //Bytes structure is: - //SRID [0 - 3] - //Byte order [4] - //WKB type [5 - 8] - //X [9 - 16] - //Y [17 - 24] - //The byte order may be either 1 or 0 to indicate little-endian or - //big-endian storage. The little-endian and big-endian byte orders - //are also known as Network Data Representation (NDR) and External - //Data Representation (XDR), respectively. - - //The WKB type is a code that indicates the geometry type. Values - //from 1 through 7 indicate Point, LineString, Polygon, MultiPoint, - //MultiLineString, MultiPolygon, and GeometryCollection. - - /// - /// Represents a geometry data type object in a MySql database. - /// - public struct MySqlGeometry : IMySqlValue - { - private readonly MySqlDbType _type; - private readonly Double _xValue; - private readonly Double _yValue; - private readonly int _srid; - - private const int GEOMETRY_LENGTH = 25; - - /// - /// Gets the x coordinate. - /// - public Double? XCoordinate => _xValue; - - /// - /// Gets the y coordinate. - /// - public Double? YCoordinate => _yValue; - - /// - /// Gets the SRID value. - /// - public int? SRID => _srid; - - public MySqlGeometry(bool isNull) : this(MySqlDbType.Geometry, isNull) - { - } - - public MySqlGeometry(Double xValue, Double yValue) - : this(MySqlDbType.Geometry, xValue, yValue, 0) - { } - - public MySqlGeometry(Double xValue, Double yValue, int srid) - : this(MySqlDbType.Geometry, xValue, yValue, srid) - { } - - - internal MySqlGeometry(MySqlDbType type, bool isNull) - { - this._type = type; - isNull = true; - _xValue = 0; - _yValue = 0; - _srid = 0; - Value = null; - this.IsNull = isNull; - } - - - internal MySqlGeometry(MySqlDbType type, Double xValue, Double yValue, int srid) - { - this._type = type; - this._xValue = xValue; - this._yValue = yValue; - this.IsNull = false; - this._srid = srid; - this.Value = new byte[GEOMETRY_LENGTH]; - - byte[] sridBinary = BitConverter.GetBytes(srid); - - for (int i = 0; i < sridBinary.Length; i++) - Value[i] = sridBinary[i]; - - long xVal = BitConverter.DoubleToInt64Bits(xValue); - long yVal = BitConverter.DoubleToInt64Bits(yValue); - - Value[4] = 1; - Value[5] = 1; - - for (int i = 0; i < 8; i++) - { - Value[i + 9] = (byte)(xVal & 0xff); - xVal >>= 8; - } - - for (int i = 0; i < 8; i++) - { - Value[i + 17] = (byte)(yVal & 0xff); - yVal >>= 8; - } - } - - public MySqlGeometry(MySqlDbType type, byte[] val) - { - - if (val == null) - throw new ArgumentNullException(nameof(val)); - - byte[] buffValue = new byte[val.Length]; - - for (int i = 0; i < val.Length; i++) - buffValue[i] = val[i]; - - var xIndex = val.Length == GEOMETRY_LENGTH ? 9 : 5; - var yIndex = val.Length == GEOMETRY_LENGTH ? 17 : 13; - - Value = buffValue; - _xValue = val.Length >= xIndex + 8 ? BitConverter.ToDouble(val, xIndex) : 0; - _yValue = val.Length >= yIndex + 8 ? BitConverter.ToDouble(val, yIndex) : 0; - this._srid = val.Length == GEOMETRY_LENGTH ? BitConverter.ToInt32(val, 0) : 0; - this.IsNull = false; - this._type = type; - } - - #region IMySqlValue Members - - - MySqlDbType IMySqlValue.MySqlDbType => _type; - - /// - /// Gets a boolean value that signals if the type is null. - /// - public bool IsNull { get; } - - /// - /// Gets the value associated to this type. - /// - object IMySqlValue.Value => Value; - - /// - /// Gets the value associated to this type. - /// - public byte[] Value { get; } - - Type IMySqlValue.SystemType => typeof(byte[]); - - string IMySqlValue.MySqlTypeName => "GEOMETRY"; - - async Task IMySqlValue.WriteValueAsync(MySqlPacket packet, bool binary, object val, int length, bool execAsync) - { - byte[] buffToWrite = null; - - try - { - buffToWrite = ((MySqlGeometry)val).Value; - } - catch - { - buffToWrite = val as Byte[]; - } - - if (buffToWrite == null) - { - MySqlGeometry v = new MySqlGeometry(0, 0); - MySqlGeometry.TryParse(val.ToString(), out v); - buffToWrite = v.Value; - } - - byte[] result = new byte[GEOMETRY_LENGTH]; - - for (int i = 0; i < buffToWrite.Length; i++) - { - if (buffToWrite.Length < GEOMETRY_LENGTH) - result[i + 4] = buffToWrite[i]; - else - result[i] = buffToWrite[i]; - } - - if (!binary) - { - await packet.WriteStringNoNullAsync("_binary ", execAsync).ConfigureAwait(false); - packet.WriteByte((byte)'\''); - EscapeByteArray(result, GEOMETRY_LENGTH, packet); - packet.WriteByte((byte)'\''); - } - else - await packet.WriteLenStringAsync(val.ToString(), execAsync).ConfigureAwait(false); - } - - private static void EscapeByteArray(byte[] bytes, int length, MySqlPacket packet) - { - for (int x = 0; x < length; x++) - { - byte b = bytes[x]; - if (b == '\0') - { - packet.WriteByte((byte)'\\'); - packet.WriteByte((byte)'0'); - } - - else if (b == '\\' || b == '\'' || b == '\"') - { - packet.WriteByte((byte)'\\'); - packet.WriteByte(b); - } - else - packet.WriteByte(b); - } - } - - async Task IMySqlValue.ReadValueAsync(MySqlPacket packet, long length, bool nullVal, bool execAsync) - { - MySqlGeometry g; - if (nullVal) - g = new MySqlGeometry(_type, true); - else - { - if (length == -1) - length = (long)packet.ReadFieldLength(); - - byte[] newBuff = new byte[length]; - await packet.ReadAsync(newBuff, 0, (int)length, execAsync).ConfigureAwait(false); - g = new MySqlGeometry(_type, newBuff); - } - return g; - } - - void IMySqlValue.SkipValue(MySqlPacket packet) - { - int len = (int)packet.ReadFieldLength(); - packet.Position += len; - } - - #endregion - - - /// Returns the Well-Known Text representation of this value - /// POINT({0} {1})", longitude, latitude - /// http://dev.mysql.com/doc/refman/4.1/en/gis-wkt-format.html - public override string ToString() - { - if (!this.IsNull) - return _srid != 0 ? string.Format(CultureInfo.InvariantCulture.NumberFormat, "SRID={2};POINT({0} {1})", _xValue, _yValue, _srid) : string.Format(CultureInfo.InvariantCulture.NumberFormat, "POINT({0} {1})", _xValue, _yValue); - - return String.Empty; - } - - /// - /// Get value from WKT format - /// SRID=0;POINT (x y) or POINT (x y) - /// - /// WKT string format - public static MySqlGeometry Parse(string value) - { - if (String.IsNullOrEmpty(value)) - throw new ArgumentNullException(nameof(value)); - - if (!(value.Contains("SRID") || value.Contains("POINT(") || value.Contains("POINT ("))) - throw new FormatException("String does not contain a valid geometry value"); - - MySqlGeometry result = new MySqlGeometry(0, 0); - MySqlGeometry.TryParse(value, out result); - - return result; - } - - /// - /// Try to get value from WKT format - /// SRID=0;POINT (x y) or POINT (x y) - /// - /// WKT string format - /// Out mysqlGeometryValue - public static bool TryParse(string value, out MySqlGeometry mySqlGeometryValue) - { - string[] arrayResult = new string[0]; - string strResult = string.Empty; - bool hasX = false; - bool hasY = false; - Double xVal = 0; - Double yVal = 0; - int sridValue = 0; - - try - { - if (value.Contains(";")) - arrayResult = value.Split(';'); - else - strResult = value; - - if (arrayResult.Length > 1 || strResult != String.Empty) - { - string point = strResult != String.Empty ? strResult : arrayResult[1]; - point = point.Replace("POINT (", "").Replace("POINT(", "").Replace(")", ""); - var coord = point.Split(' '); - if (coord.Length > 1) - { - hasX = Double.TryParse(coord[0], out xVal); - hasY = Double.TryParse(coord[1], out yVal); - } - if (arrayResult.Length >= 1) - Int32.TryParse(arrayResult[0].Replace("SRID=", ""), out sridValue); - } - if (hasX && hasY) - { - mySqlGeometryValue = new MySqlGeometry(xVal, yVal, sridValue); - return true; - } - } - catch - { } - - mySqlGeometryValue = new MySqlGeometry(true); - return false; - } - - /// - /// Sets the DSInfo when GetSchema is called for the DataSourceInformation collection. - /// - public static void SetDSInfo(MySqlSchemaCollection dsTable) - { - // we use name indexing because this method will only be called - // when GetSchema is called for the DataSourceInformation - // collection and then it wil be cached. - MySqlSchemaRow row = dsTable.AddRow(); - row["TypeName"] = "GEOMETRY"; - row["ProviderDbType"] = MySqlDbType.Geometry; - row["ColumnSize"] = GEOMETRY_LENGTH; - row["CreateFormat"] = "GEOMETRY"; - row["CreateParameters"] = DBNull.Value; ; - row["DataType"] = "System.Byte[]"; - row["IsAutoincrementable"] = false; - row["IsBestMatch"] = true; - row["IsCaseSensitive"] = false; - row["IsFixedLength"] = false; - row["IsFixedPrecisionScale"] = true; - row["IsLong"] = false; - row["IsNullable"] = true; - row["IsSearchable"] = true; - row["IsSearchableWithLike"] = false; - row["IsUnsigned"] = false; - row["MaximumScale"] = 0; - row["MinimumScale"] = 0; - row["IsConcurrencyType"] = DBNull.Value; - row["IsLiteralSupported"] = false; - row["LiteralPrefix"] = DBNull.Value; - row["LiteralSuffix"] = DBNull.Value; - row["NativeDataType"] = DBNull.Value; - } - - /// - /// Gets the well-known text representation of the geomtry object. - /// - /// A string representation of the WKT. - public string GetWKT() - { - if (!this.IsNull) - return string.Format(CultureInfo.InvariantCulture.NumberFormat, "POINT({0} {1})", _xValue, _yValue); - - return String.Empty; - } - } -} +// Copyright © 2013, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySql.Data.MySqlClient; +using System; +using System.Globalization; +using System.Threading.Tasks; + +namespace MySql.Data.Types +{ + //Bytes structure is: + //SRID [0 - 3] + //Byte order [4] + //WKB type [5 - 8] + //X [9 - 16] + //Y [17 - 24] + //The byte order may be either 1 or 0 to indicate little-endian or + //big-endian storage. The little-endian and big-endian byte orders + //are also known as Network Data Representation (NDR) and External + //Data Representation (XDR), respectively. + + //The WKB type is a code that indicates the geometry type. Values + //from 1 through 7 indicate Point, LineString, Polygon, MultiPoint, + //MultiLineString, MultiPolygon, and GeometryCollection. + + /// + /// Represents a geometry data type object in a MySql database. + /// + public struct MySqlGeometry : IMySqlValue + { + private readonly MySqlDbType _type; + private readonly Double _xValue; + private readonly Double _yValue; + private readonly int _srid; + + private const int GEOMETRY_LENGTH = 25; + + /// + /// Gets the x coordinate. + /// + public Double? XCoordinate => _xValue; + + /// + /// Gets the y coordinate. + /// + public Double? YCoordinate => _yValue; + + /// + /// Gets the SRID value. + /// + public int? SRID => _srid; + + public MySqlGeometry(bool isNull) : this(MySqlDbType.Geometry, isNull) + { + } + + public MySqlGeometry(Double xValue, Double yValue) + : this(MySqlDbType.Geometry, xValue, yValue, 0) + { } + + public MySqlGeometry(Double xValue, Double yValue, int srid) + : this(MySqlDbType.Geometry, xValue, yValue, srid) + { } + + + internal MySqlGeometry(MySqlDbType type, bool isNull) + { + this._type = type; + isNull = true; + _xValue = 0; + _yValue = 0; + _srid = 0; + Value = null; + this.IsNull = isNull; + } + + + internal MySqlGeometry(MySqlDbType type, Double xValue, Double yValue, int srid) + { + this._type = type; + this._xValue = xValue; + this._yValue = yValue; + this.IsNull = false; + this._srid = srid; + this.Value = new byte[GEOMETRY_LENGTH]; + + byte[] sridBinary = BitConverter.GetBytes(srid); + + for (int i = 0; i < sridBinary.Length; i++) + Value[i] = sridBinary[i]; + + long xVal = BitConverter.DoubleToInt64Bits(xValue); + long yVal = BitConverter.DoubleToInt64Bits(yValue); + + Value[4] = 1; + Value[5] = 1; + + for (int i = 0; i < 8; i++) + { + Value[i + 9] = (byte)(xVal & 0xff); + xVal >>= 8; + } + + for (int i = 0; i < 8; i++) + { + Value[i + 17] = (byte)(yVal & 0xff); + yVal >>= 8; + } + } + + public MySqlGeometry(MySqlDbType type, byte[] val) + { + + if (val == null) + throw new ArgumentNullException(nameof(val)); + + byte[] buffValue = new byte[val.Length]; + + for (int i = 0; i < val.Length; i++) + buffValue[i] = val[i]; + + var xIndex = val.Length == GEOMETRY_LENGTH ? 9 : 5; + var yIndex = val.Length == GEOMETRY_LENGTH ? 17 : 13; + + Value = buffValue; + _xValue = val.Length >= xIndex + 8 ? BitConverter.ToDouble(val, xIndex) : 0; + _yValue = val.Length >= yIndex + 8 ? BitConverter.ToDouble(val, yIndex) : 0; + this._srid = val.Length == GEOMETRY_LENGTH ? BitConverter.ToInt32(val, 0) : 0; + this.IsNull = false; + this._type = type; + } + + #region IMySqlValue Members + + + MySqlDbType IMySqlValue.MySqlDbType => _type; + + /// + /// Gets a boolean value that signals if the type is null. + /// + public bool IsNull { get; } + + /// + /// Gets the value associated to this type. + /// + object IMySqlValue.Value => Value; + + /// + /// Gets the value associated to this type. + /// + public byte[] Value { get; } + + Type IMySqlValue.SystemType => typeof(byte[]); + + string IMySqlValue.MySqlTypeName => "GEOMETRY"; + + async Task IMySqlValue.WriteValueAsync(MySqlPacket packet, bool binary, object val, int length, bool execAsync) + { + byte[] buffToWrite = null; + + try + { + buffToWrite = ((MySqlGeometry)val).Value; + } + catch + { + buffToWrite = val as Byte[]; + } + + if (buffToWrite == null) + { + MySqlGeometry v = new MySqlGeometry(0, 0); + MySqlGeometry.TryParse(val.ToString(), out v); + buffToWrite = v.Value; + } + + byte[] result = new byte[GEOMETRY_LENGTH]; + + for (int i = 0; i < buffToWrite.Length; i++) + { + if (buffToWrite.Length < GEOMETRY_LENGTH) + result[i + 4] = buffToWrite[i]; + else + result[i] = buffToWrite[i]; + } + + if (!binary) + { + await packet.WriteStringNoNullAsync("_binary ", execAsync).ConfigureAwait(false); + packet.WriteByte((byte)'\''); + EscapeByteArray(result, GEOMETRY_LENGTH, packet); + packet.WriteByte((byte)'\''); + } + else + await packet.WriteLenStringAsync(val.ToString(), execAsync).ConfigureAwait(false); + } + + private static void EscapeByteArray(byte[] bytes, int length, MySqlPacket packet) + { + for (int x = 0; x < length; x++) + { + byte b = bytes[x]; + if (b == '\0') + { + packet.WriteByte((byte)'\\'); + packet.WriteByte((byte)'0'); + } + + else if (b == '\\' || b == '\'' || b == '\"') + { + packet.WriteByte((byte)'\\'); + packet.WriteByte(b); + } + else + packet.WriteByte(b); + } + } + + async Task IMySqlValue.ReadValueAsync(MySqlPacket packet, long length, bool nullVal, bool execAsync) + { + MySqlGeometry g; + if (nullVal) + g = new MySqlGeometry(_type, true); + else + { + if (length == -1) + length = (long)packet.ReadFieldLength(); + + byte[] newBuff = new byte[length]; + await packet.ReadAsync(newBuff, 0, (int)length, execAsync).ConfigureAwait(false); + g = new MySqlGeometry(_type, newBuff); + } + return g; + } + + void IMySqlValue.SkipValue(MySqlPacket packet) + { + int len = (int)packet.ReadFieldLength(); + packet.Position += len; + } + + #endregion + + + /// Returns the Well-Known Text representation of this value + /// POINT({0} {1})", longitude, latitude + /// http://dev.mysql.com/doc/refman/4.1/en/gis-wkt-format.html + public override string ToString() + { + if (!this.IsNull) + return _srid != 0 ? string.Format(CultureInfo.InvariantCulture.NumberFormat, "SRID={2};POINT({0} {1})", _xValue, _yValue, _srid) : string.Format(CultureInfo.InvariantCulture.NumberFormat, "POINT({0} {1})", _xValue, _yValue); + + return String.Empty; + } + + /// + /// Get value from WKT format + /// SRID=0;POINT (x y) or POINT (x y) + /// + /// WKT string format + public static MySqlGeometry Parse(string value) + { + if (String.IsNullOrEmpty(value)) + throw new ArgumentNullException(nameof(value)); + + if (!(value.Contains("SRID") || value.Contains("POINT(") || value.Contains("POINT ("))) + throw new FormatException("String does not contain a valid geometry value"); + + MySqlGeometry result = new MySqlGeometry(0, 0); + MySqlGeometry.TryParse(value, out result); + + return result; + } + + /// + /// Try to get value from WKT format + /// SRID=0;POINT (x y) or POINT (x y) + /// + /// WKT string format + /// Out mysqlGeometryValue + public static bool TryParse(string value, out MySqlGeometry mySqlGeometryValue) + { + string[] arrayResult = new string[0]; + string strResult = string.Empty; + bool hasX = false; + bool hasY = false; + Double xVal = 0; + Double yVal = 0; + int sridValue = 0; + + try + { + if (value.Contains(";")) + arrayResult = value.Split(';'); + else + strResult = value; + + if (arrayResult.Length > 1 || strResult != String.Empty) + { + string point = strResult != String.Empty ? strResult : arrayResult[1]; + point = point.Replace("POINT (", "").Replace("POINT(", "").Replace(")", ""); + var coord = point.Split(' '); + if (coord.Length > 1) + { + hasX = Double.TryParse(coord[0], out xVal); + hasY = Double.TryParse(coord[1], out yVal); + } + if (arrayResult.Length >= 1) + Int32.TryParse(arrayResult[0].Replace("SRID=", ""), out sridValue); + } + if (hasX && hasY) + { + mySqlGeometryValue = new MySqlGeometry(xVal, yVal, sridValue); + return true; + } + } + catch + { } + + mySqlGeometryValue = new MySqlGeometry(true); + return false; + } + + /// + /// Sets the DSInfo when GetSchema is called for the DataSourceInformation collection. + /// + public static void SetDSInfo(MySqlSchemaCollection dsTable) + { + // we use name indexing because this method will only be called + // when GetSchema is called for the DataSourceInformation + // collection and then it wil be cached. + MySqlSchemaRow row = dsTable.AddRow(); + row["TypeName"] = "GEOMETRY"; + row["ProviderDbType"] = MySqlDbType.Geometry; + row["ColumnSize"] = GEOMETRY_LENGTH; + row["CreateFormat"] = "GEOMETRY"; + row["CreateParameters"] = DBNull.Value; ; + row["DataType"] = "System.Byte[]"; + row["IsAutoincrementable"] = false; + row["IsBestMatch"] = true; + row["IsCaseSensitive"] = false; + row["IsFixedLength"] = false; + row["IsFixedPrecisionScale"] = true; + row["IsLong"] = false; + row["IsNullable"] = true; + row["IsSearchable"] = true; + row["IsSearchableWithLike"] = false; + row["IsUnsigned"] = false; + row["MaximumScale"] = 0; + row["MinimumScale"] = 0; + row["IsConcurrencyType"] = DBNull.Value; + row["IsLiteralSupported"] = false; + row["LiteralPrefix"] = DBNull.Value; + row["LiteralSuffix"] = DBNull.Value; + row["NativeDataType"] = DBNull.Value; + } + + /// + /// Gets the well-known text representation of the geomtry object. + /// + /// A string representation of the WKT. + public string GetWKT() + { + if (!this.IsNull) + return string.Format(CultureInfo.InvariantCulture.NumberFormat, "POINT({0} {1})", _xValue, _yValue); + + return String.Empty; + } + } +} diff --git a/MySQL.Data/src/Types/MySqlGuid.cs b/MySQL.Data/src/Types/MySqlGuid.cs index eb8606bf9..7e2fa5129 100644 --- a/MySQL.Data/src/Types/MySqlGuid.cs +++ b/MySQL.Data/src/Types/MySqlGuid.cs @@ -1,209 +1,209 @@ -// Copyright (c) 2004, 2022, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySql.Data.MySqlClient; -using System; -using System.Threading.Tasks; - -namespace MySql.Data.Types -{ - internal struct MySqlGuid : IMySqlValue - { - public MySqlGuid(byte[] buff) - { - OldGuids = false; - Value = new Guid(buff); - IsNull = false; - Bytes = buff; - } - - public byte[] Bytes { get; } - - public bool OldGuids { get; set; } - - #region IMySqlValue Members - - public bool IsNull { get; private set; } - - MySqlDbType IMySqlValue.MySqlDbType => MySqlDbType.Guid; - - object IMySqlValue.Value => Value; - - public Guid Value { get; private set; } - - Type IMySqlValue.SystemType => typeof(Guid); - - string IMySqlValue.MySqlTypeName => OldGuids ? "BINARY(16)" : "CHAR(36)"; - - async Task IMySqlValue.WriteValueAsync(MySqlPacket packet, bool binary, object val, int length, bool execAsync) - { - Guid guid = Guid.Empty; - string valAsString = val as string; - byte[] valAsByte = val as byte[]; - - if (val is Guid) - guid = (Guid)val; - else - { - try - { - if (valAsString != null) - guid = new Guid(valAsString); - else if (valAsByte != null) - guid = new Guid(valAsByte); - } - catch (Exception ex) - { - throw new MySqlException(Resources.DataNotInSupportedFormat, ex); - } - } - - if (OldGuids) - await WriteOldGuidAsync(packet, guid, binary, execAsync).ConfigureAwait(false); - else - { - guid.ToString("D"); - - if (binary) - await packet.WriteLenStringAsync(guid.ToString("D"), execAsync).ConfigureAwait(false); - else - await packet.WriteStringNoNullAsync("'" + MySqlHelper.EscapeString(guid.ToString("D")) + "'", execAsync).ConfigureAwait(false); - } - } - - private async Task WriteOldGuidAsync(MySqlPacket packet, Guid guid, bool binary, bool execAsync) - { - byte[] bytes = guid.ToByteArray(); - - if (binary) - { - await packet.WriteLengthAsync(bytes.Length, execAsync).ConfigureAwait(false); - await packet.WriteAsync(bytes, execAsync).ConfigureAwait(false); - } - else - { - await packet.WriteStringNoNullAsync("_binary ", execAsync).ConfigureAwait(false); - packet.WriteByte((byte)'\''); - EscapeByteArray(bytes, bytes.Length, packet); - packet.WriteByte((byte)'\''); - } - } - - private static void EscapeByteArray(byte[] bytes, int length, MySqlPacket packet) - { - for (int x = 0; x < length; x++) - { - byte b = bytes[x]; - if (b == '\0') - { - packet.WriteByte((byte)'\\'); - packet.WriteByte((byte)'0'); - } - - else if (b == '\\' || b == '\'' || b == '\"') - { - packet.WriteByte((byte)'\\'); - packet.WriteByte(b); - } - else - packet.WriteByte(b); - } - } - - private async Task ReadOldGuidAsync(MySqlPacket packet, long length, bool execAsync) - { - if (length == -1) - length = (long)packet.ReadFieldLength(); - - byte[] buff = new byte[length]; - await packet.ReadAsync(buff, 0, (int)length, execAsync).ConfigureAwait(false); - MySqlGuid g = new MySqlGuid(buff); - g.OldGuids = OldGuids; - return g; - } - - async Task IMySqlValue.ReadValueAsync(MySqlPacket packet, long length, bool nullVal, bool execAsync) - { - MySqlGuid g = new MySqlGuid(); - g.IsNull = true; - g.OldGuids = OldGuids; - if (!nullVal) - { - if (OldGuids) - return await ReadOldGuidAsync(packet, length, execAsync).ConfigureAwait(false); - string s = String.Empty; - if (length == -1) - s = await packet.ReadLenStringAsync(execAsync).ConfigureAwait(false); - else - s = await packet.ReadStringAsync(length, execAsync).ConfigureAwait(false); - g.Value = new Guid(s); - g.IsNull = false; - } - return g; - } - - void IMySqlValue.SkipValue(MySqlPacket packet) - { - int len = (int)packet.ReadFieldLength(); - packet.Position += len; - } - - #endregion - - public static void SetDSInfo(MySqlSchemaCollection sc) - { - // we use name indexing because this method will only be called - // when GetSchema is called for the DataSourceInformation - // collection and then it wil be cached. - MySqlSchemaRow row = sc.AddRow(); - row["TypeName"] = "GUID"; - row["ProviderDbType"] = MySqlDbType.Guid; - row["ColumnSize"] = 0; - row["CreateFormat"] = "BINARY(16)"; - row["CreateParameters"] = null; - row["DataType"] = "System.Guid"; - row["IsAutoincrementable"] = false; - row["IsBestMatch"] = true; - row["IsCaseSensitive"] = false; - row["IsFixedLength"] = true; - row["IsFixedPrecisionScale"] = true; - row["IsLong"] = false; - row["IsNullable"] = true; - row["IsSearchable"] = false; - row["IsSearchableWithLike"] = false; - row["IsUnsigned"] = false; - row["MaximumScale"] = 0; - row["MinimumScale"] = 0; - row["IsConcurrencyType"] = DBNull.Value; - row["IsLiteralSupported"] = false; - row["LiteralPrefix"] = null; - row["LiteralSuffix"] = null; - row["NativeDataType"] = null; - } - } -} +// Copyright © 2004, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySql.Data.MySqlClient; +using System; +using System.Threading.Tasks; + +namespace MySql.Data.Types +{ + internal struct MySqlGuid : IMySqlValue + { + public MySqlGuid(byte[] buff) + { + OldGuids = false; + Value = new Guid(buff); + IsNull = false; + Bytes = buff; + } + + public byte[] Bytes { get; } + + public bool OldGuids { get; set; } + + #region IMySqlValue Members + + public bool IsNull { get; private set; } + + MySqlDbType IMySqlValue.MySqlDbType => MySqlDbType.Guid; + + object IMySqlValue.Value => Value; + + public Guid Value { get; private set; } + + Type IMySqlValue.SystemType => typeof(Guid); + + string IMySqlValue.MySqlTypeName => OldGuids ? "BINARY(16)" : "CHAR(36)"; + + async Task IMySqlValue.WriteValueAsync(MySqlPacket packet, bool binary, object val, int length, bool execAsync) + { + Guid guid = Guid.Empty; + string valAsString = val as string; + byte[] valAsByte = val as byte[]; + + if (val is Guid) + guid = (Guid)val; + else + { + try + { + if (valAsString != null) + guid = new Guid(valAsString); + else if (valAsByte != null) + guid = new Guid(valAsByte); + } + catch (Exception ex) + { + throw new MySqlException(Resources.DataNotInSupportedFormat, ex); + } + } + + if (OldGuids) + await WriteOldGuidAsync(packet, guid, binary, execAsync).ConfigureAwait(false); + else + { + guid.ToString("D"); + + if (binary) + await packet.WriteLenStringAsync(guid.ToString("D"), execAsync).ConfigureAwait(false); + else + await packet.WriteStringNoNullAsync("'" + MySqlHelper.EscapeString(guid.ToString("D")) + "'", execAsync).ConfigureAwait(false); + } + } + + private async Task WriteOldGuidAsync(MySqlPacket packet, Guid guid, bool binary, bool execAsync) + { + byte[] bytes = guid.ToByteArray(); + + if (binary) + { + await packet.WriteLengthAsync(bytes.Length, execAsync).ConfigureAwait(false); + await packet.WriteAsync(bytes, execAsync).ConfigureAwait(false); + } + else + { + await packet.WriteStringNoNullAsync("_binary ", execAsync).ConfigureAwait(false); + packet.WriteByte((byte)'\''); + EscapeByteArray(bytes, bytes.Length, packet); + packet.WriteByte((byte)'\''); + } + } + + private static void EscapeByteArray(byte[] bytes, int length, MySqlPacket packet) + { + for (int x = 0; x < length; x++) + { + byte b = bytes[x]; + if (b == '\0') + { + packet.WriteByte((byte)'\\'); + packet.WriteByte((byte)'0'); + } + + else if (b == '\\' || b == '\'' || b == '\"') + { + packet.WriteByte((byte)'\\'); + packet.WriteByte(b); + } + else + packet.WriteByte(b); + } + } + + private async Task ReadOldGuidAsync(MySqlPacket packet, long length, bool execAsync) + { + if (length == -1) + length = (long)packet.ReadFieldLength(); + + byte[] buff = new byte[length]; + await packet.ReadAsync(buff, 0, (int)length, execAsync).ConfigureAwait(false); + MySqlGuid g = new MySqlGuid(buff); + g.OldGuids = OldGuids; + return g; + } + + async Task IMySqlValue.ReadValueAsync(MySqlPacket packet, long length, bool nullVal, bool execAsync) + { + MySqlGuid g = new MySqlGuid(); + g.IsNull = true; + g.OldGuids = OldGuids; + if (!nullVal) + { + if (OldGuids) + return await ReadOldGuidAsync(packet, length, execAsync).ConfigureAwait(false); + string s = String.Empty; + if (length == -1) + s = await packet.ReadLenStringAsync(execAsync).ConfigureAwait(false); + else + s = await packet.ReadStringAsync(length, execAsync).ConfigureAwait(false); + g.Value = new Guid(s); + g.IsNull = false; + } + return g; + } + + void IMySqlValue.SkipValue(MySqlPacket packet) + { + int len = (int)packet.ReadFieldLength(); + packet.Position += len; + } + + #endregion + + public static void SetDSInfo(MySqlSchemaCollection sc) + { + // we use name indexing because this method will only be called + // when GetSchema is called for the DataSourceInformation + // collection and then it wil be cached. + MySqlSchemaRow row = sc.AddRow(); + row["TypeName"] = "GUID"; + row["ProviderDbType"] = MySqlDbType.Guid; + row["ColumnSize"] = 0; + row["CreateFormat"] = "BINARY(16)"; + row["CreateParameters"] = null; + row["DataType"] = "System.Guid"; + row["IsAutoincrementable"] = false; + row["IsBestMatch"] = true; + row["IsCaseSensitive"] = false; + row["IsFixedLength"] = true; + row["IsFixedPrecisionScale"] = true; + row["IsLong"] = false; + row["IsNullable"] = true; + row["IsSearchable"] = false; + row["IsSearchableWithLike"] = false; + row["IsUnsigned"] = false; + row["MaximumScale"] = 0; + row["MinimumScale"] = 0; + row["IsConcurrencyType"] = DBNull.Value; + row["IsLiteralSupported"] = false; + row["LiteralPrefix"] = null; + row["LiteralSuffix"] = null; + row["NativeDataType"] = null; + } + } +} diff --git a/MySQL.Data/src/Types/MySqlInt16.cs b/MySQL.Data/src/Types/MySqlInt16.cs index 42f32947f..805e296b1 100644 --- a/MySQL.Data/src/Types/MySqlInt16.cs +++ b/MySQL.Data/src/Types/MySqlInt16.cs @@ -1,123 +1,123 @@ -// Copyright (c) 2004, 2022, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySql.Data.MySqlClient; -using System; -using System.Globalization; -using System.Threading.Tasks; - -namespace MySql.Data.Types -{ - internal struct MySqlInt16 : IMySqlValue - { - public MySqlInt16(bool isNull) - { - IsNull = isNull; - Value = 0; - } - - public MySqlInt16(short val) - { - IsNull = false; - Value = val; - } - - #region IMySqlValue Members - - public bool IsNull { get; } - - MySqlDbType IMySqlValue.MySqlDbType => MySqlDbType.Int16; - - object IMySqlValue.Value => Value; - - public short Value { get; } - - Type IMySqlValue.SystemType => typeof(short); - - string IMySqlValue.MySqlTypeName => "SMALLINT"; - - async Task IMySqlValue.WriteValueAsync(MySqlPacket packet, bool binary, object val, int length, bool execAsync) - { - int v = val as int? ?? Convert.ToInt32(val); - - if (binary) - await packet.WriteIntegerAsync((long)v, 2, execAsync).ConfigureAwait(false); - else - await packet.WriteStringNoNullAsync(v.ToString(CultureInfo.InvariantCulture), execAsync).ConfigureAwait(false); - } - - async Task IMySqlValue.ReadValueAsync(MySqlPacket packet, long length, bool nullVal, bool execAsync) - { - if (nullVal) - return new MySqlInt16(true); - - if (length == -1) - return new MySqlInt16((short)packet.ReadInteger(2)); - else - return new MySqlInt16(Int16.Parse(await packet.ReadStringAsync(length, execAsync).ConfigureAwait(false), CultureInfo.InvariantCulture)); - } - - void IMySqlValue.SkipValue(MySqlPacket packet) - { - packet.Position += 2; - } - - #endregion - - internal static void SetDSInfo(MySqlSchemaCollection sc) - { - // we use name indexing because this method will only be called - // when GetSchema is called for the DataSourceInformation - // collection and then it wil be cached. - MySqlSchemaRow row = sc.AddRow(); - row["TypeName"] = "SMALLINT"; - row["ProviderDbType"] = MySqlDbType.Int16; - row["ColumnSize"] = 0; - row["CreateFormat"] = "SMALLINT"; - row["CreateParameters"] = null; - row["DataType"] = "System.Int16"; - row["IsAutoincrementable"] = true; - row["IsBestMatch"] = true; - row["IsCaseSensitive"] = false; - row["IsFixedLength"] = true; - row["IsFixedPrecisionScale"] = true; - row["IsLong"] = false; - row["IsNullable"] = true; - row["IsSearchable"] = true; - row["IsSearchableWithLike"] = false; - row["IsUnsigned"] = false; - row["MaximumScale"] = 0; - row["MinimumScale"] = 0; - row["IsConcurrencyType"] = DBNull.Value; - row["IsLiteralSupported"] = false; - row["LiteralPrefix"] = null; - row["LiteralSuffix"] = null; - row["NativeDataType"] = null; - } - } -} +// Copyright © 2004, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySql.Data.MySqlClient; +using System; +using System.Globalization; +using System.Threading.Tasks; + +namespace MySql.Data.Types +{ + internal struct MySqlInt16 : IMySqlValue + { + public MySqlInt16(bool isNull) + { + IsNull = isNull; + Value = 0; + } + + public MySqlInt16(short val) + { + IsNull = false; + Value = val; + } + + #region IMySqlValue Members + + public bool IsNull { get; } + + MySqlDbType IMySqlValue.MySqlDbType => MySqlDbType.Int16; + + object IMySqlValue.Value => Value; + + public short Value { get; } + + Type IMySqlValue.SystemType => typeof(short); + + string IMySqlValue.MySqlTypeName => "SMALLINT"; + + async Task IMySqlValue.WriteValueAsync(MySqlPacket packet, bool binary, object val, int length, bool execAsync) + { + int v = val as int? ?? Convert.ToInt32(val); + + if (binary) + await packet.WriteIntegerAsync((long)v, 2, execAsync).ConfigureAwait(false); + else + await packet.WriteStringNoNullAsync(v.ToString(CultureInfo.InvariantCulture), execAsync).ConfigureAwait(false); + } + + async Task IMySqlValue.ReadValueAsync(MySqlPacket packet, long length, bool nullVal, bool execAsync) + { + if (nullVal) + return new MySqlInt16(true); + + if (length == -1) + return new MySqlInt16((short)packet.ReadInteger(2)); + else + return new MySqlInt16(Int16.Parse(await packet.ReadStringAsync(length, execAsync).ConfigureAwait(false), CultureInfo.InvariantCulture)); + } + + void IMySqlValue.SkipValue(MySqlPacket packet) + { + packet.Position += 2; + } + + #endregion + + internal static void SetDSInfo(MySqlSchemaCollection sc) + { + // we use name indexing because this method will only be called + // when GetSchema is called for the DataSourceInformation + // collection and then it wil be cached. + MySqlSchemaRow row = sc.AddRow(); + row["TypeName"] = "SMALLINT"; + row["ProviderDbType"] = MySqlDbType.Int16; + row["ColumnSize"] = 0; + row["CreateFormat"] = "SMALLINT"; + row["CreateParameters"] = null; + row["DataType"] = "System.Int16"; + row["IsAutoincrementable"] = true; + row["IsBestMatch"] = true; + row["IsCaseSensitive"] = false; + row["IsFixedLength"] = true; + row["IsFixedPrecisionScale"] = true; + row["IsLong"] = false; + row["IsNullable"] = true; + row["IsSearchable"] = true; + row["IsSearchableWithLike"] = false; + row["IsUnsigned"] = false; + row["MaximumScale"] = 0; + row["MinimumScale"] = 0; + row["IsConcurrencyType"] = DBNull.Value; + row["IsLiteralSupported"] = false; + row["LiteralPrefix"] = null; + row["LiteralSuffix"] = null; + row["NativeDataType"] = null; + } + } +} diff --git a/MySQL.Data/src/Types/MySqlInt32.cs b/MySQL.Data/src/Types/MySqlInt32.cs index a4ca91846..6cda1fa52 100644 --- a/MySQL.Data/src/Types/MySqlInt32.cs +++ b/MySQL.Data/src/Types/MySqlInt32.cs @@ -1,143 +1,143 @@ -// Copyright (c) 2004, 2022, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySql.Data.MySqlClient; -using System; -using System.Globalization; -using System.Threading.Tasks; - -namespace MySql.Data.Types -{ - internal struct MySqlInt32 : IMySqlValue - { - private readonly int _value; - private readonly bool _is24Bit; - - private MySqlInt32(MySqlDbType type) - { - _is24Bit = type == MySqlDbType.Int24; - IsNull = true; - _value = 0; - } - - public MySqlInt32(MySqlDbType type, bool isNull) - : this(type) - { - IsNull = isNull; - } - - public MySqlInt32(MySqlDbType type, int val) - : this(type) - { - IsNull = false; - _value = val; - } - - #region IMySqlValue Members - - public bool IsNull { get; } - - MySqlDbType IMySqlValue.MySqlDbType => MySqlDbType.Int32; - - object IMySqlValue.Value => _value; - - public int Value => _value; - - Type IMySqlValue.SystemType => typeof(Int32); - - string IMySqlValue.MySqlTypeName => _is24Bit ? "MEDIUMINT" : "INT"; - - async Task IMySqlValue.WriteValueAsync(MySqlPacket packet, bool binary, object val, int length, bool execAsync) - { - int v = val as int? ?? Convert.ToInt32(val); - - if (binary) - await packet.WriteIntegerAsync(v, 4, execAsync).ConfigureAwait(false); - else - await packet.WriteStringNoNullAsync(v.ToString(CultureInfo.InvariantCulture), execAsync).ConfigureAwait(false); - } - - async Task IMySqlValue.ReadValueAsync(MySqlPacket packet, long length, bool nullVal, bool execAsync) - { - if (nullVal) - return new MySqlInt32((this as IMySqlValue).MySqlDbType, true); - - if (length == -1) - return new MySqlInt32((this as IMySqlValue).MySqlDbType, - packet.ReadInteger(4)); - else - return new MySqlInt32((this as IMySqlValue).MySqlDbType, Int32.Parse(await packet.ReadStringAsync(length, execAsync).ConfigureAwait(false), - CultureInfo.InvariantCulture)); - } - - void IMySqlValue.SkipValue(MySqlPacket packet) - { - packet.Position += 4; - } - - #endregion - - internal static void SetDSInfo(MySqlSchemaCollection sc) - { - string[] types = new string[] { "INT", "YEAR", "MEDIUMINT" }; - MySqlDbType[] dbtype = new MySqlDbType[] { MySqlDbType.Int32, - MySqlDbType.Year, MySqlDbType.Int24 }; - - // we use name indexing because this method will only be called - // when GetSchema is called for the DataSourceInformation - // collection and then it wil be cached. - for (int x = 0; x < types.Length; x++) - { - MySqlSchemaRow row = sc.AddRow(); - row["TypeName"] = types[x]; - row["ProviderDbType"] = dbtype[x]; - row["ColumnSize"] = 0; - row["CreateFormat"] = types[x]; - row["CreateParameters"] = null; - row["DataType"] = "System.Int32"; - row["IsAutoincrementable"] = dbtype[x] != MySqlDbType.Year; - row["IsBestMatch"] = true; - row["IsCaseSensitive"] = false; - row["IsFixedLength"] = true; - row["IsFixedPrecisionScale"] = true; - row["IsLong"] = false; - row["IsNullable"] = true; - row["IsSearchable"] = true; - row["IsSearchableWithLike"] = false; - row["IsUnsigned"] = false; - row["MaximumScale"] = 0; - row["MinimumScale"] = 0; - row["IsConcurrencyType"] = DBNull.Value; - row["IsLiteralSupported"] = false; - row["LiteralPrefix"] = null; - row["LiteralSuffix"] = null; - row["NativeDataType"] = null; - } - } - } -} +// Copyright © 2004, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySql.Data.MySqlClient; +using System; +using System.Globalization; +using System.Threading.Tasks; + +namespace MySql.Data.Types +{ + internal struct MySqlInt32 : IMySqlValue + { + private readonly int _value; + private readonly bool _is24Bit; + + private MySqlInt32(MySqlDbType type) + { + _is24Bit = type == MySqlDbType.Int24; + IsNull = true; + _value = 0; + } + + public MySqlInt32(MySqlDbType type, bool isNull) + : this(type) + { + IsNull = isNull; + } + + public MySqlInt32(MySqlDbType type, int val) + : this(type) + { + IsNull = false; + _value = val; + } + + #region IMySqlValue Members + + public bool IsNull { get; } + + MySqlDbType IMySqlValue.MySqlDbType => MySqlDbType.Int32; + + object IMySqlValue.Value => _value; + + public int Value => _value; + + Type IMySqlValue.SystemType => typeof(Int32); + + string IMySqlValue.MySqlTypeName => _is24Bit ? "MEDIUMINT" : "INT"; + + async Task IMySqlValue.WriteValueAsync(MySqlPacket packet, bool binary, object val, int length, bool execAsync) + { + int v = val as int? ?? Convert.ToInt32(val); + + if (binary) + await packet.WriteIntegerAsync(v, 4, execAsync).ConfigureAwait(false); + else + await packet.WriteStringNoNullAsync(v.ToString(CultureInfo.InvariantCulture), execAsync).ConfigureAwait(false); + } + + async Task IMySqlValue.ReadValueAsync(MySqlPacket packet, long length, bool nullVal, bool execAsync) + { + if (nullVal) + return new MySqlInt32((this as IMySqlValue).MySqlDbType, true); + + if (length == -1) + return new MySqlInt32((this as IMySqlValue).MySqlDbType, + packet.ReadInteger(4)); + else + return new MySqlInt32((this as IMySqlValue).MySqlDbType, Int32.Parse(await packet.ReadStringAsync(length, execAsync).ConfigureAwait(false), + CultureInfo.InvariantCulture)); + } + + void IMySqlValue.SkipValue(MySqlPacket packet) + { + packet.Position += 4; + } + + #endregion + + internal static void SetDSInfo(MySqlSchemaCollection sc) + { + string[] types = new string[] { "INT", "YEAR", "MEDIUMINT" }; + MySqlDbType[] dbtype = new MySqlDbType[] { MySqlDbType.Int32, + MySqlDbType.Year, MySqlDbType.Int24 }; + + // we use name indexing because this method will only be called + // when GetSchema is called for the DataSourceInformation + // collection and then it wil be cached. + for (int x = 0; x < types.Length; x++) + { + MySqlSchemaRow row = sc.AddRow(); + row["TypeName"] = types[x]; + row["ProviderDbType"] = dbtype[x]; + row["ColumnSize"] = 0; + row["CreateFormat"] = types[x]; + row["CreateParameters"] = null; + row["DataType"] = "System.Int32"; + row["IsAutoincrementable"] = dbtype[x] != MySqlDbType.Year; + row["IsBestMatch"] = true; + row["IsCaseSensitive"] = false; + row["IsFixedLength"] = true; + row["IsFixedPrecisionScale"] = true; + row["IsLong"] = false; + row["IsNullable"] = true; + row["IsSearchable"] = true; + row["IsSearchableWithLike"] = false; + row["IsUnsigned"] = false; + row["MaximumScale"] = 0; + row["MinimumScale"] = 0; + row["IsConcurrencyType"] = DBNull.Value; + row["IsLiteralSupported"] = false; + row["LiteralPrefix"] = null; + row["LiteralSuffix"] = null; + row["NativeDataType"] = null; + } + } + } +} diff --git a/MySQL.Data/src/Types/MySqlInt64.cs b/MySQL.Data/src/Types/MySqlInt64.cs index 3c14ac0a7..8fea63889 100644 --- a/MySQL.Data/src/Types/MySqlInt64.cs +++ b/MySQL.Data/src/Types/MySqlInt64.cs @@ -1,125 +1,125 @@ -// Copyright (c) 2004, 2022, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySql.Data.MySqlClient; -using System; -using System.Globalization; -using System.Threading.Tasks; - -namespace MySql.Data.Types -{ - internal struct MySqlInt64 : IMySqlValue - { - public MySqlInt64(bool isNull) - { - IsNull = isNull; - Value = 0; - } - - public MySqlInt64(long val) - { - IsNull = false; - Value = val; - } - - #region IMySqlValue Members - - public bool IsNull { get; } - - MySqlDbType IMySqlValue.MySqlDbType => MySqlDbType.Int64; - - object IMySqlValue.Value => Value; - - public long Value { get; } - - Type IMySqlValue.SystemType => typeof(long); - - string IMySqlValue.MySqlTypeName - { - get { return "BIGINT"; } - } - - async Task IMySqlValue.WriteValueAsync(MySqlPacket packet, bool binary, object val, int length, bool execAsync) - { - long v = val as Int64? ?? Convert.ToInt64(val); - if (binary) - await packet.WriteIntegerAsync(v, 8, execAsync).ConfigureAwait(false); - else - await packet.WriteStringNoNullAsync(v.ToString(CultureInfo.InvariantCulture), execAsync).ConfigureAwait(false); - } - - async Task IMySqlValue.ReadValueAsync(MySqlPacket packet, long length, bool nullVal, bool execAsync) - { - if (nullVal) - return new MySqlInt64(true); - - if (length == -1) - return new MySqlInt64((long)packet.ReadULong(8)); - else - return new MySqlInt64(Int64.Parse(await packet.ReadStringAsync(length, execAsync).ConfigureAwait(false), CultureInfo.InvariantCulture)); - } - - void IMySqlValue.SkipValue(MySqlPacket packet) - { - packet.Position += 8; - } - - #endregion - - internal static void SetDSInfo(MySqlSchemaCollection sc) - { - // we use name indexing because this method will only be called - // when GetSchema is called for the DataSourceInformation - // collection and then it wil be cached. - MySqlSchemaRow row = sc.AddRow(); - row["TypeName"] = "BIGINT"; - row["ProviderDbType"] = MySqlDbType.Int64; - row["ColumnSize"] = 0; - row["CreateFormat"] = "BIGINT"; - row["CreateParameters"] = null; - row["DataType"] = "System.Int64"; - row["IsAutoincrementable"] = true; - row["IsBestMatch"] = true; - row["IsCaseSensitive"] = false; - row["IsFixedLength"] = true; - row["IsFixedPrecisionScale"] = true; - row["IsLong"] = false; - row["IsNullable"] = true; - row["IsSearchable"] = true; - row["IsSearchableWithLike"] = false; - row["IsUnsigned"] = false; - row["MaximumScale"] = 0; - row["MinimumScale"] = 0; - row["IsConcurrencyType"] = DBNull.Value; - row["IsLiteralSupported"] = false; - row["LiteralPrefix"] = null; - row["LiteralSuffix"] = null; - row["NativeDataType"] = null; - } - } -} +// Copyright © 2004, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySql.Data.MySqlClient; +using System; +using System.Globalization; +using System.Threading.Tasks; + +namespace MySql.Data.Types +{ + internal struct MySqlInt64 : IMySqlValue + { + public MySqlInt64(bool isNull) + { + IsNull = isNull; + Value = 0; + } + + public MySqlInt64(long val) + { + IsNull = false; + Value = val; + } + + #region IMySqlValue Members + + public bool IsNull { get; } + + MySqlDbType IMySqlValue.MySqlDbType => MySqlDbType.Int64; + + object IMySqlValue.Value => Value; + + public long Value { get; } + + Type IMySqlValue.SystemType => typeof(long); + + string IMySqlValue.MySqlTypeName + { + get { return "BIGINT"; } + } + + async Task IMySqlValue.WriteValueAsync(MySqlPacket packet, bool binary, object val, int length, bool execAsync) + { + long v = val as Int64? ?? Convert.ToInt64(val); + if (binary) + await packet.WriteIntegerAsync(v, 8, execAsync).ConfigureAwait(false); + else + await packet.WriteStringNoNullAsync(v.ToString(CultureInfo.InvariantCulture), execAsync).ConfigureAwait(false); + } + + async Task IMySqlValue.ReadValueAsync(MySqlPacket packet, long length, bool nullVal, bool execAsync) + { + if (nullVal) + return new MySqlInt64(true); + + if (length == -1) + return new MySqlInt64((long)packet.ReadULong(8)); + else + return new MySqlInt64(Int64.Parse(await packet.ReadStringAsync(length, execAsync).ConfigureAwait(false), CultureInfo.InvariantCulture)); + } + + void IMySqlValue.SkipValue(MySqlPacket packet) + { + packet.Position += 8; + } + + #endregion + + internal static void SetDSInfo(MySqlSchemaCollection sc) + { + // we use name indexing because this method will only be called + // when GetSchema is called for the DataSourceInformation + // collection and then it wil be cached. + MySqlSchemaRow row = sc.AddRow(); + row["TypeName"] = "BIGINT"; + row["ProviderDbType"] = MySqlDbType.Int64; + row["ColumnSize"] = 0; + row["CreateFormat"] = "BIGINT"; + row["CreateParameters"] = null; + row["DataType"] = "System.Int64"; + row["IsAutoincrementable"] = true; + row["IsBestMatch"] = true; + row["IsCaseSensitive"] = false; + row["IsFixedLength"] = true; + row["IsFixedPrecisionScale"] = true; + row["IsLong"] = false; + row["IsNullable"] = true; + row["IsSearchable"] = true; + row["IsSearchableWithLike"] = false; + row["IsUnsigned"] = false; + row["MaximumScale"] = 0; + row["MinimumScale"] = 0; + row["IsConcurrencyType"] = DBNull.Value; + row["IsLiteralSupported"] = false; + row["LiteralPrefix"] = null; + row["LiteralSuffix"] = null; + row["NativeDataType"] = null; + } + } +} diff --git a/MySQL.Data/src/Types/MySqlSingle.cs b/MySQL.Data/src/Types/MySqlSingle.cs index 1cb2d544c..ff04eedee 100644 --- a/MySQL.Data/src/Types/MySqlSingle.cs +++ b/MySQL.Data/src/Types/MySqlSingle.cs @@ -1,130 +1,130 @@ -// Copyright (c) 2004, 2022, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySql.Data.MySqlClient; -using System; -using System.Globalization; -using System.Threading.Tasks; - -namespace MySql.Data.Types -{ - internal struct MySqlSingle : IMySqlValue - { - public MySqlSingle(bool isNull) - { - IsNull = isNull; - Value = 0.0f; - } - - public MySqlSingle(float val) - { - IsNull = false; - Value = val; - } - - #region IMySqlValue Members - - public bool IsNull { get; } - - MySqlDbType IMySqlValue.MySqlDbType => MySqlDbType.Float; - - object IMySqlValue.Value => Value; - - public float Value { get; } - - Type IMySqlValue.SystemType => typeof(float); - - string IMySqlValue.MySqlTypeName - { - get { return "FLOAT"; } - } - - async Task IMySqlValue.WriteValueAsync(MySqlPacket packet, bool binary, object val, int length, bool execAsync) - { - Single v = val as Single? ?? Convert.ToSingle(val); - if (binary) - await packet.WriteAsync(BitConverter.GetBytes(v), execAsync).ConfigureAwait(false); - else - await packet.WriteStringNoNullAsync(v.ToString("R", CultureInfo.InvariantCulture), execAsync).ConfigureAwait(false); - } - - async Task IMySqlValue.ReadValueAsync(MySqlPacket packet, long length, bool nullVal, bool execAsync) - { - if (nullVal) - return new MySqlSingle(true); - - if (length == -1) - { - byte[] b = new byte[4]; - await packet.ReadAsync(b, 0, 4, execAsync).ConfigureAwait(false); - return new MySqlSingle(BitConverter.ToSingle(b, 0)); - } - - return new MySqlSingle(Single.Parse(await packet.ReadStringAsync(length, execAsync).ConfigureAwait(false), - CultureInfo.InvariantCulture)); - } - - void IMySqlValue.SkipValue(MySqlPacket packet) - { - packet.Position += 4; - } - - #endregion - - internal static void SetDSInfo(MySqlSchemaCollection sc) - { - // we use name indexing because this method will only be called - // when GetSchema is called for the DataSourceInformation - // collection and then it wil be cached. - MySqlSchemaRow row = sc.AddRow(); - row["TypeName"] = "FLOAT"; - row["ProviderDbType"] = MySqlDbType.Float; - row["ColumnSize"] = 0; - row["CreateFormat"] = "FLOAT"; - row["CreateParameters"] = null; - row["DataType"] = "System.Single"; - row["IsAutoincrementable"] = false; - row["IsBestMatch"] = true; - row["IsCaseSensitive"] = false; - row["IsFixedLength"] = true; - row["IsFixedPrecisionScale"] = true; - row["IsLong"] = false; - row["IsNullable"] = true; - row["IsSearchable"] = true; - row["IsSearchableWithLike"] = false; - row["IsUnsigned"] = false; - row["MaximumScale"] = 0; - row["MinimumScale"] = 0; - row["IsConcurrencyType"] = DBNull.Value; - row["IsLiteralSupported"] = false; - row["LiteralPrefix"] = null; - row["LiteralSuffix"] = null; - row["NativeDataType"] = null; - } - } -} \ No newline at end of file +// Copyright © 2004, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySql.Data.MySqlClient; +using System; +using System.Globalization; +using System.Threading.Tasks; + +namespace MySql.Data.Types +{ + internal struct MySqlSingle : IMySqlValue + { + public MySqlSingle(bool isNull) + { + IsNull = isNull; + Value = 0.0f; + } + + public MySqlSingle(float val) + { + IsNull = false; + Value = val; + } + + #region IMySqlValue Members + + public bool IsNull { get; } + + MySqlDbType IMySqlValue.MySqlDbType => MySqlDbType.Float; + + object IMySqlValue.Value => Value; + + public float Value { get; } + + Type IMySqlValue.SystemType => typeof(float); + + string IMySqlValue.MySqlTypeName + { + get { return "FLOAT"; } + } + + async Task IMySqlValue.WriteValueAsync(MySqlPacket packet, bool binary, object val, int length, bool execAsync) + { + Single v = val as Single? ?? Convert.ToSingle(val); + if (binary) + await packet.WriteAsync(BitConverter.GetBytes(v), execAsync).ConfigureAwait(false); + else + await packet.WriteStringNoNullAsync(v.ToString("R", CultureInfo.InvariantCulture), execAsync).ConfigureAwait(false); + } + + async Task IMySqlValue.ReadValueAsync(MySqlPacket packet, long length, bool nullVal, bool execAsync) + { + if (nullVal) + return new MySqlSingle(true); + + if (length == -1) + { + byte[] b = new byte[4]; + await packet.ReadAsync(b, 0, 4, execAsync).ConfigureAwait(false); + return new MySqlSingle(BitConverter.ToSingle(b, 0)); + } + + return new MySqlSingle(Single.Parse(await packet.ReadStringAsync(length, execAsync).ConfigureAwait(false), + CultureInfo.InvariantCulture)); + } + + void IMySqlValue.SkipValue(MySqlPacket packet) + { + packet.Position += 4; + } + + #endregion + + internal static void SetDSInfo(MySqlSchemaCollection sc) + { + // we use name indexing because this method will only be called + // when GetSchema is called for the DataSourceInformation + // collection and then it wil be cached. + MySqlSchemaRow row = sc.AddRow(); + row["TypeName"] = "FLOAT"; + row["ProviderDbType"] = MySqlDbType.Float; + row["ColumnSize"] = 0; + row["CreateFormat"] = "FLOAT"; + row["CreateParameters"] = null; + row["DataType"] = "System.Single"; + row["IsAutoincrementable"] = false; + row["IsBestMatch"] = true; + row["IsCaseSensitive"] = false; + row["IsFixedLength"] = true; + row["IsFixedPrecisionScale"] = true; + row["IsLong"] = false; + row["IsNullable"] = true; + row["IsSearchable"] = true; + row["IsSearchableWithLike"] = false; + row["IsUnsigned"] = false; + row["MaximumScale"] = 0; + row["MinimumScale"] = 0; + row["IsConcurrencyType"] = DBNull.Value; + row["IsLiteralSupported"] = false; + row["LiteralPrefix"] = null; + row["LiteralSuffix"] = null; + row["NativeDataType"] = null; + } + } +} diff --git a/MySQL.Data/src/Types/MySqlString.cs b/MySQL.Data/src/Types/MySqlString.cs index a442a4256..f9bd06d6d 100644 --- a/MySQL.Data/src/Types/MySqlString.cs +++ b/MySQL.Data/src/Types/MySqlString.cs @@ -1,145 +1,145 @@ -// Copyright (c) 2004, 2022, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySql.Data.MySqlClient; -using System; -using System.Threading.Tasks; - -namespace MySql.Data.Types -{ - internal struct MySqlString : IMySqlValue - { - private readonly MySqlDbType _type; - - public MySqlString(MySqlDbType type, bool isNull) - { - _type = type; - IsNull = isNull; - Value = String.Empty; - } - - public MySqlString(MySqlDbType type, string val) - { - _type = type; - IsNull = false; - Value = val; - } - - #region IMySqlValue Members - - public bool IsNull { get; } - - MySqlDbType IMySqlValue.MySqlDbType => _type; - - object IMySqlValue.Value => Value; - - public string Value { get; } - - Type IMySqlValue.SystemType => typeof(string); - - string IMySqlValue.MySqlTypeName => _type == MySqlDbType.Set ? "SET" : _type == MySqlDbType.Enum ? "ENUM" : "VARCHAR"; - - async Task IMySqlValue.WriteValueAsync(MySqlPacket packet, bool binary, object val, int length, bool execAsync) - { - string v = val.ToString(); - if (length > 0) - { - length = Math.Min(length, v.Length); - v = v.Substring(0, length); - } - - if (binary) - await packet.WriteLenStringAsync(v, execAsync).ConfigureAwait(false); - else - await packet.WriteStringNoNullAsync("'" + MySqlHelper.EscapeString(v) + "'", execAsync).ConfigureAwait(false); - } - - async Task IMySqlValue.ReadValueAsync(MySqlPacket packet, long length, bool nullVal, bool execAsync) - { - if (nullVal) - return new MySqlString(_type, true); - - string s = String.Empty; - if (length == -1) - s = await packet.ReadLenStringAsync(execAsync).ConfigureAwait(false); - else - s = await packet.ReadStringAsync(length, execAsync).ConfigureAwait(false); - MySqlString str = new MySqlString(_type, s); - return str; - } - - void IMySqlValue.SkipValue(MySqlPacket packet) - { - int len = (int)packet.ReadFieldLength(); - packet.Position += len; - } - - #endregion - - internal static void SetDSInfo(MySqlSchemaCollection sc) - { - string[] types = new string[] { "CHAR", "NCHAR", "VARCHAR", "NVARCHAR", "SET", - "ENUM", "TINYTEXT", "TEXT", "MEDIUMTEXT", "LONGTEXT" }; - MySqlDbType[] dbtype = new MySqlDbType[] { MySqlDbType.String, MySqlDbType.String, - MySqlDbType.VarChar, MySqlDbType.VarChar, MySqlDbType.Set, MySqlDbType.Enum, - MySqlDbType.TinyText, MySqlDbType.Text, MySqlDbType.MediumText, - MySqlDbType.LongText }; - - // we use name indexing because this method will only be called - // when GetSchema is called for the DataSourceInformation - // collection and then it wil be cached. - for (int x = 0; x < types.Length; x++) - { - MySqlSchemaRow row = sc.AddRow(); - row["TypeName"] = types[x]; - row["ProviderDbType"] = dbtype[x]; - row["ColumnSize"] = 0; - row["CreateFormat"] = x < 4 ? types[x] + "({0})" : types[x]; - row["CreateParameters"] = x < 4 ? "size" : null; - row["DataType"] = "System.String"; - row["IsAutoincrementable"] = false; - row["IsBestMatch"] = true; - row["IsCaseSensitive"] = false; - row["IsFixedLength"] = false; - row["IsFixedPrecisionScale"] = true; - row["IsLong"] = false; - row["IsNullable"] = true; - row["IsSearchable"] = true; - row["IsSearchableWithLike"] = true; - row["IsUnsigned"] = false; - row["MaximumScale"] = 0; - row["MinimumScale"] = 0; - row["IsConcurrencyType"] = DBNull.Value; - row["IsLiteralSupported"] = false; - row["LiteralPrefix"] = null; - row["LiteralSuffix"] = null; - row["NativeDataType"] = null; - } - } - } -} \ No newline at end of file +// Copyright © 2004, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySql.Data.MySqlClient; +using System; +using System.Threading.Tasks; + +namespace MySql.Data.Types +{ + internal struct MySqlString : IMySqlValue + { + private readonly MySqlDbType _type; + + public MySqlString(MySqlDbType type, bool isNull) + { + _type = type; + IsNull = isNull; + Value = String.Empty; + } + + public MySqlString(MySqlDbType type, string val) + { + _type = type; + IsNull = false; + Value = val; + } + + #region IMySqlValue Members + + public bool IsNull { get; } + + MySqlDbType IMySqlValue.MySqlDbType => _type; + + object IMySqlValue.Value => Value; + + public string Value { get; } + + Type IMySqlValue.SystemType => typeof(string); + + string IMySqlValue.MySqlTypeName => _type == MySqlDbType.Set ? "SET" : _type == MySqlDbType.Enum ? "ENUM" : "VARCHAR"; + + async Task IMySqlValue.WriteValueAsync(MySqlPacket packet, bool binary, object val, int length, bool execAsync) + { + string v = val.ToString(); + if (length > 0) + { + length = Math.Min(length, v.Length); + v = v.Substring(0, length); + } + + if (binary) + await packet.WriteLenStringAsync(v, execAsync).ConfigureAwait(false); + else + await packet.WriteStringNoNullAsync("'" + MySqlHelper.EscapeString(v) + "'", execAsync).ConfigureAwait(false); + } + + async Task IMySqlValue.ReadValueAsync(MySqlPacket packet, long length, bool nullVal, bool execAsync) + { + if (nullVal) + return new MySqlString(_type, true); + + string s = String.Empty; + if (length == -1) + s = await packet.ReadLenStringAsync(execAsync).ConfigureAwait(false); + else + s = await packet.ReadStringAsync(length, execAsync).ConfigureAwait(false); + MySqlString str = new MySqlString(_type, s); + return str; + } + + void IMySqlValue.SkipValue(MySqlPacket packet) + { + int len = (int)packet.ReadFieldLength(); + packet.Position += len; + } + + #endregion + + internal static void SetDSInfo(MySqlSchemaCollection sc) + { + string[] types = new string[] { "CHAR", "NCHAR", "VARCHAR", "NVARCHAR", "SET", + "ENUM", "TINYTEXT", "TEXT", "MEDIUMTEXT", "LONGTEXT" }; + MySqlDbType[] dbtype = new MySqlDbType[] { MySqlDbType.String, MySqlDbType.String, + MySqlDbType.VarChar, MySqlDbType.VarChar, MySqlDbType.Set, MySqlDbType.Enum, + MySqlDbType.TinyText, MySqlDbType.Text, MySqlDbType.MediumText, + MySqlDbType.LongText }; + + // we use name indexing because this method will only be called + // when GetSchema is called for the DataSourceInformation + // collection and then it wil be cached. + for (int x = 0; x < types.Length; x++) + { + MySqlSchemaRow row = sc.AddRow(); + row["TypeName"] = types[x]; + row["ProviderDbType"] = dbtype[x]; + row["ColumnSize"] = 0; + row["CreateFormat"] = x < 4 ? types[x] + "({0})" : types[x]; + row["CreateParameters"] = x < 4 ? "size" : null; + row["DataType"] = "System.String"; + row["IsAutoincrementable"] = false; + row["IsBestMatch"] = true; + row["IsCaseSensitive"] = false; + row["IsFixedLength"] = false; + row["IsFixedPrecisionScale"] = true; + row["IsLong"] = false; + row["IsNullable"] = true; + row["IsSearchable"] = true; + row["IsSearchableWithLike"] = true; + row["IsUnsigned"] = false; + row["MaximumScale"] = 0; + row["MinimumScale"] = 0; + row["IsConcurrencyType"] = DBNull.Value; + row["IsLiteralSupported"] = false; + row["LiteralPrefix"] = null; + row["LiteralSuffix"] = null; + row["NativeDataType"] = null; + } + } + } +} diff --git a/MySQL.Data/src/Types/MySqlTime.cs b/MySQL.Data/src/Types/MySqlTime.cs index 4df93332f..8ef8fb77e 100644 --- a/MySQL.Data/src/Types/MySqlTime.cs +++ b/MySQL.Data/src/Types/MySqlTime.cs @@ -1,218 +1,218 @@ -// Copyright (c) 2004, 2022, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySql.Data.MySqlClient; -using System; -using System.Globalization; -using System.Threading.Tasks; - -namespace MySql.Data.Types -{ - internal struct MySqlTimeSpan : IMySqlValue - { - public MySqlTimeSpan(bool isNull) - { - IsNull = isNull; - Value = TimeSpan.MinValue; - } - - public MySqlTimeSpan(TimeSpan val) - { - IsNull = false; - Value = val; - } - - #region IMySqlValue Members - - public bool IsNull { get; private set; } - - MySqlDbType IMySqlValue.MySqlDbType => MySqlDbType.Time; - - object IMySqlValue.Value => Value; - - public TimeSpan Value { get; private set; } - - Type IMySqlValue.SystemType => typeof(TimeSpan); - - string IMySqlValue.MySqlTypeName => "TIME"; - - async Task IMySqlValue.WriteValueAsync(MySqlPacket packet, bool binary, object val, int length, bool execAsync) - { -#if NET6_0_OR_GREATER - if (val is TimeOnly) - val = ((TimeOnly)val).ToTimeSpan(); -#endif - if (!(val is TimeSpan)) - throw new MySqlException("Only TimeSpan objects can be serialized by MySqlTimeSpan"); - - TimeSpan ts = (TimeSpan)val; - bool negative = ts.TotalMilliseconds < 0; - ts = ts.Duration(); - - if (binary) - { - if (ts.Milliseconds > 0) - packet.WriteByte(12); - else - packet.WriteByte(8); - - packet.WriteByte((byte)(negative ? 1 : 0)); - await packet.WriteIntegerAsync(ts.Days, 4, execAsync).ConfigureAwait(false); - packet.WriteByte((byte)ts.Hours); - packet.WriteByte((byte)ts.Minutes); - packet.WriteByte((byte)ts.Seconds); - var microseconds = (int)(ts.Ticks % 10_000_000) / 10; - - if (microseconds != 0) - await packet.WriteIntegerAsync(microseconds, 4, execAsync).ConfigureAwait(false); - } - else - { - String s = $"'{(negative ? "-" : "")}{ts.Days} {ts.Hours:00}:{ts.Minutes:00}:{ts.Seconds:00}.{ts.Ticks % 10000000 / 10:000000}'"; - - await packet.WriteStringNoNullAsync(s, execAsync).ConfigureAwait(false); - } - } - - - async Task IMySqlValue.ReadValueAsync(MySqlPacket packet, long length, bool nullVal, bool execAsync) - { - if (nullVal) return new MySqlTimeSpan(true); - - if (length >= 0) - { - string value = await packet.ReadStringAsync(length, execAsync).ConfigureAwait(false); - ParseMySql(value); - return this; - } - - long bufLength = packet.ReadByte(); - int negate = 0; - if (bufLength > 0) - negate = packet.ReadByte(); - - IsNull = false; - if (bufLength == 0) - { - IsNull = true; - Value = new MySqlTimeSpan().Value; - } - else if (bufLength == 5) - Value = new TimeSpan(packet.ReadInteger(4), 0, 0, 0); - else if (bufLength == 8) - Value = new TimeSpan(packet.ReadInteger(4), - packet.ReadByte(), packet.ReadByte(), packet.ReadByte()); - else - { - var days = (int)packet.ReadInteger(4); - var hours = (int)packet.ReadByte(); - var minutes = (int)packet.ReadByte(); - var seconds = (int)packet.ReadByte(); - var microseconds = (int)packet.ReadInteger(4); - Value = new TimeSpan(days, hours, minutes, seconds) + TimeSpan.FromTicks(microseconds * 10); - } - - if (negate == 1) - Value = Value.Negate(); - return this; - } - - void IMySqlValue.SkipValue(MySqlPacket packet) - { - int len = packet.ReadByte(); - packet.Position += len; - } - - #endregion - - internal static void SetDSInfo(MySqlSchemaCollection sc) - { - // we use name indexing because this method will only be called - // when GetSchema is called for the DataSourceInformation - // collection and then it wil be cached. - MySqlSchemaRow row = sc.AddRow(); - row["TypeName"] = "TIME"; - row["ProviderDbType"] = MySqlDbType.Time; - row["ColumnSize"] = 0; - row["CreateFormat"] = "TIME"; - row["CreateParameters"] = null; - row["DataType"] = "System.TimeSpan"; - row["IsAutoincrementable"] = false; - row["IsBestMatch"] = true; - row["IsCaseSensitive"] = false; - row["IsFixedLength"] = true; - row["IsFixedPrecisionScale"] = true; - row["IsLong"] = false; - row["IsNullable"] = true; - row["IsSearchable"] = true; - row["IsSearchableWithLike"] = false; - row["IsUnsigned"] = false; - row["MaximumScale"] = 0; - row["MinimumScale"] = 0; - row["IsConcurrencyType"] = DBNull.Value; - row["IsLiteralSupported"] = false; - row["LiteralPrefix"] = null; - row["LiteralSuffix"] = null; - row["NativeDataType"] = null; - } - - public override string ToString() - { - return $"{Value.Days} {Value.Hours:00}:{Value.Minutes:00}:{Value.Seconds:00}"; - } - - private void ParseMySql(string s) - { - - string[] parts = s.Split(':', '.'); - int hours = Int32.Parse(parts[0], CultureInfo.InvariantCulture); - int mins = Int32.Parse(parts[1], CultureInfo.InvariantCulture); - int secs = Int32.Parse(parts[2], CultureInfo.InvariantCulture); - int nanoseconds = 0; - - if (parts.Length > 3) - { - //if the data is saved in MySql as Time(3) the division by 1000 always returns 0, but handling the data as Time(6) the result is the expected - parts[3] = parts[3].PadRight(7, '0'); - nanoseconds = int.Parse(parts[3], CultureInfo.InvariantCulture); - } - - - if (hours < 0 || parts[0].StartsWith("-", StringComparison.Ordinal)) - { - mins *= -1; - secs *= -1; - nanoseconds *= -1; - } - int days = hours / 24; - hours = hours - (days * 24); - Value = new TimeSpan(days, hours, mins, secs).Add(new TimeSpan(nanoseconds)); - IsNull = false; - } - } -} +// Copyright © 2004, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySql.Data.MySqlClient; +using System; +using System.Globalization; +using System.Threading.Tasks; + +namespace MySql.Data.Types +{ + internal struct MySqlTimeSpan : IMySqlValue + { + public MySqlTimeSpan(bool isNull) + { + IsNull = isNull; + Value = TimeSpan.MinValue; + } + + public MySqlTimeSpan(TimeSpan val) + { + IsNull = false; + Value = val; + } + + #region IMySqlValue Members + + public bool IsNull { get; private set; } + + MySqlDbType IMySqlValue.MySqlDbType => MySqlDbType.Time; + + object IMySqlValue.Value => Value; + + public TimeSpan Value { get; private set; } + + Type IMySqlValue.SystemType => typeof(TimeSpan); + + string IMySqlValue.MySqlTypeName => "TIME"; + + async Task IMySqlValue.WriteValueAsync(MySqlPacket packet, bool binary, object val, int length, bool execAsync) + { +#if NET6_0_OR_GREATER + if (val is TimeOnly) + val = ((TimeOnly)val).ToTimeSpan(); +#endif + if (!(val is TimeSpan)) + throw new MySqlException("Only TimeSpan objects can be serialized by MySqlTimeSpan"); + + TimeSpan ts = (TimeSpan)val; + bool negative = ts.TotalMilliseconds < 0; + ts = ts.Duration(); + + if (binary) + { + if (ts.Milliseconds > 0) + packet.WriteByte(12); + else + packet.WriteByte(8); + + packet.WriteByte((byte)(negative ? 1 : 0)); + await packet.WriteIntegerAsync(ts.Days, 4, execAsync).ConfigureAwait(false); + packet.WriteByte((byte)ts.Hours); + packet.WriteByte((byte)ts.Minutes); + packet.WriteByte((byte)ts.Seconds); + var microseconds = (int)(ts.Ticks % 10_000_000) / 10; + + if (microseconds != 0) + await packet.WriteIntegerAsync(microseconds, 4, execAsync).ConfigureAwait(false); + } + else + { + String s = $"'{(negative ? "-" : "")}{ts.Days} {ts.Hours:00}:{ts.Minutes:00}:{ts.Seconds:00}.{ts.Ticks % 10000000 / 10:000000}'"; + + await packet.WriteStringNoNullAsync(s, execAsync).ConfigureAwait(false); + } + } + + + async Task IMySqlValue.ReadValueAsync(MySqlPacket packet, long length, bool nullVal, bool execAsync) + { + if (nullVal) return new MySqlTimeSpan(true); + + if (length >= 0) + { + string value = await packet.ReadStringAsync(length, execAsync).ConfigureAwait(false); + ParseMySql(value); + return this; + } + + long bufLength = packet.ReadByte(); + int negate = 0; + if (bufLength > 0) + negate = packet.ReadByte(); + + IsNull = false; + if (bufLength == 0) + { + IsNull = true; + Value = new MySqlTimeSpan().Value; + } + else if (bufLength == 5) + Value = new TimeSpan(packet.ReadInteger(4), 0, 0, 0); + else if (bufLength == 8) + Value = new TimeSpan(packet.ReadInteger(4), + packet.ReadByte(), packet.ReadByte(), packet.ReadByte()); + else + { + var days = (int)packet.ReadInteger(4); + var hours = (int)packet.ReadByte(); + var minutes = (int)packet.ReadByte(); + var seconds = (int)packet.ReadByte(); + var microseconds = (int)packet.ReadInteger(4); + Value = new TimeSpan(days, hours, minutes, seconds) + TimeSpan.FromTicks(microseconds * 10); + } + + if (negate == 1) + Value = Value.Negate(); + return this; + } + + void IMySqlValue.SkipValue(MySqlPacket packet) + { + int len = packet.ReadByte(); + packet.Position += len; + } + + #endregion + + internal static void SetDSInfo(MySqlSchemaCollection sc) + { + // we use name indexing because this method will only be called + // when GetSchema is called for the DataSourceInformation + // collection and then it wil be cached. + MySqlSchemaRow row = sc.AddRow(); + row["TypeName"] = "TIME"; + row["ProviderDbType"] = MySqlDbType.Time; + row["ColumnSize"] = 0; + row["CreateFormat"] = "TIME"; + row["CreateParameters"] = null; + row["DataType"] = "System.TimeSpan"; + row["IsAutoincrementable"] = false; + row["IsBestMatch"] = true; + row["IsCaseSensitive"] = false; + row["IsFixedLength"] = true; + row["IsFixedPrecisionScale"] = true; + row["IsLong"] = false; + row["IsNullable"] = true; + row["IsSearchable"] = true; + row["IsSearchableWithLike"] = false; + row["IsUnsigned"] = false; + row["MaximumScale"] = 0; + row["MinimumScale"] = 0; + row["IsConcurrencyType"] = DBNull.Value; + row["IsLiteralSupported"] = false; + row["LiteralPrefix"] = null; + row["LiteralSuffix"] = null; + row["NativeDataType"] = null; + } + + public override string ToString() + { + return $"{Value.Days} {Value.Hours:00}:{Value.Minutes:00}:{Value.Seconds:00}"; + } + + private void ParseMySql(string s) + { + + string[] parts = s.Split(':', '.'); + int hours = Int32.Parse(parts[0], CultureInfo.InvariantCulture); + int mins = Int32.Parse(parts[1], CultureInfo.InvariantCulture); + int secs = Int32.Parse(parts[2], CultureInfo.InvariantCulture); + int nanoseconds = 0; + + if (parts.Length > 3) + { + //if the data is saved in MySql as Time(3) the division by 1000 always returns 0, but handling the data as Time(6) the result is the expected + parts[3] = parts[3].PadRight(7, '0'); + nanoseconds = int.Parse(parts[3], CultureInfo.InvariantCulture); + } + + + if (hours < 0 || parts[0].StartsWith("-", StringComparison.Ordinal)) + { + mins *= -1; + secs *= -1; + nanoseconds *= -1; + } + int days = hours / 24; + hours = hours - (days * 24); + Value = new TimeSpan(days, hours, mins, secs).Add(new TimeSpan(nanoseconds)); + IsNull = false; + } + } +} diff --git a/MySQL.Data/src/Types/MySqlUByte.cs b/MySQL.Data/src/Types/MySqlUByte.cs index 30022d805..e773d6d03 100644 --- a/MySQL.Data/src/Types/MySqlUByte.cs +++ b/MySQL.Data/src/Types/MySqlUByte.cs @@ -1,122 +1,122 @@ -// Copyright (c) 2004, 2022, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySql.Data.MySqlClient; -using System; -using System.Globalization; -using System.Threading.Tasks; - -namespace MySql.Data.Types -{ - internal struct MySqlUByte : IMySqlValue - { - public MySqlUByte(bool isNull) - { - IsNull = isNull; - Value = 0; - } - - public MySqlUByte(byte val) - { - IsNull = false; - Value = val; - } - - #region IMySqlValue Members - - public bool IsNull { get; } - - MySqlDbType IMySqlValue.MySqlDbType => MySqlDbType.UByte; - - object IMySqlValue.Value => Value; - - public byte Value { get; } - - Type IMySqlValue.SystemType => typeof(byte); - - string IMySqlValue.MySqlTypeName => "TINYINT"; - - async Task IMySqlValue.WriteValueAsync(MySqlPacket packet, bool binary, object val, int length, bool execAsync) - { - byte v = val as byte? ?? Convert.ToByte(val); - if (binary) - packet.WriteByte(v); - else - await packet.WriteStringNoNullAsync(v.ToString(CultureInfo.InvariantCulture), execAsync).ConfigureAwait(false); - } - - async Task IMySqlValue.ReadValueAsync(MySqlPacket packet, long length, bool nullVal, bool execAsync) - { - if (nullVal) - return new MySqlUByte(true); - - if (length == -1) - return new MySqlUByte((byte)packet.ReadByte()); - else - return new MySqlUByte(Byte.Parse(await packet.ReadStringAsync(length, execAsync).ConfigureAwait(false), CultureInfo.InvariantCulture)); - } - - void IMySqlValue.SkipValue(MySqlPacket packet) - { - packet.ReadByte(); - } - - #endregion - - internal static void SetDSInfo(MySqlSchemaCollection sc) - { - // we use name indexing because this method will only be called - // when GetSchema is called for the DataSourceInformation - // collection and then it wil be cached. - MySqlSchemaRow row = sc.AddRow(); - row["TypeName"] = "TINYINT"; - row["ProviderDbType"] = MySqlDbType.UByte; - row["ColumnSize"] = 0; - row["CreateFormat"] = "TINYINT UNSIGNED"; - row["CreateParameters"] = null; - row["DataType"] = "System.Byte"; - row["IsAutoincrementable"] = true; - row["IsBestMatch"] = true; - row["IsCaseSensitive"] = false; - row["IsFixedLength"] = true; - row["IsFixedPrecisionScale"] = true; - row["IsLong"] = false; - row["IsNullable"] = true; - row["IsSearchable"] = true; - row["IsSearchableWithLike"] = false; - row["IsUnsigned"] = true; - row["MaximumScale"] = 0; - row["MinimumScale"] = 0; - row["IsConcurrencyType"] = DBNull.Value; - row["IsLiteralSupported"] = false; - row["LiteralPrefix"] = null; - row["LiteralSuffix"] = null; - row["NativeDataType"] = null; - } - } -} +// Copyright © 2004, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySql.Data.MySqlClient; +using System; +using System.Globalization; +using System.Threading.Tasks; + +namespace MySql.Data.Types +{ + internal struct MySqlUByte : IMySqlValue + { + public MySqlUByte(bool isNull) + { + IsNull = isNull; + Value = 0; + } + + public MySqlUByte(byte val) + { + IsNull = false; + Value = val; + } + + #region IMySqlValue Members + + public bool IsNull { get; } + + MySqlDbType IMySqlValue.MySqlDbType => MySqlDbType.UByte; + + object IMySqlValue.Value => Value; + + public byte Value { get; } + + Type IMySqlValue.SystemType => typeof(byte); + + string IMySqlValue.MySqlTypeName => "TINYINT"; + + async Task IMySqlValue.WriteValueAsync(MySqlPacket packet, bool binary, object val, int length, bool execAsync) + { + byte v = val as byte? ?? Convert.ToByte(val); + if (binary) + packet.WriteByte(v); + else + await packet.WriteStringNoNullAsync(v.ToString(CultureInfo.InvariantCulture), execAsync).ConfigureAwait(false); + } + + async Task IMySqlValue.ReadValueAsync(MySqlPacket packet, long length, bool nullVal, bool execAsync) + { + if (nullVal) + return new MySqlUByte(true); + + if (length == -1) + return new MySqlUByte((byte)packet.ReadByte()); + else + return new MySqlUByte(Byte.Parse(await packet.ReadStringAsync(length, execAsync).ConfigureAwait(false), CultureInfo.InvariantCulture)); + } + + void IMySqlValue.SkipValue(MySqlPacket packet) + { + packet.ReadByte(); + } + + #endregion + + internal static void SetDSInfo(MySqlSchemaCollection sc) + { + // we use name indexing because this method will only be called + // when GetSchema is called for the DataSourceInformation + // collection and then it wil be cached. + MySqlSchemaRow row = sc.AddRow(); + row["TypeName"] = "TINYINT"; + row["ProviderDbType"] = MySqlDbType.UByte; + row["ColumnSize"] = 0; + row["CreateFormat"] = "TINYINT UNSIGNED"; + row["CreateParameters"] = null; + row["DataType"] = "System.Byte"; + row["IsAutoincrementable"] = true; + row["IsBestMatch"] = true; + row["IsCaseSensitive"] = false; + row["IsFixedLength"] = true; + row["IsFixedPrecisionScale"] = true; + row["IsLong"] = false; + row["IsNullable"] = true; + row["IsSearchable"] = true; + row["IsSearchableWithLike"] = false; + row["IsUnsigned"] = true; + row["MaximumScale"] = 0; + row["MinimumScale"] = 0; + row["IsConcurrencyType"] = DBNull.Value; + row["IsLiteralSupported"] = false; + row["LiteralPrefix"] = null; + row["LiteralSuffix"] = null; + row["NativeDataType"] = null; + } + } +} diff --git a/MySQL.Data/src/Types/MySqlUInt16.cs b/MySQL.Data/src/Types/MySqlUInt16.cs index e0a344f2c..e407f95cd 100644 --- a/MySQL.Data/src/Types/MySqlUInt16.cs +++ b/MySQL.Data/src/Types/MySqlUInt16.cs @@ -1,122 +1,122 @@ -// Copyright (c) 2004, 2022, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySql.Data.MySqlClient; -using System; -using System.Globalization; -using System.Threading.Tasks; - -namespace MySql.Data.Types -{ - internal struct MySqlUInt16 : IMySqlValue - { - public MySqlUInt16(bool isNull) - { - IsNull = isNull; - Value = 0; - } - - public MySqlUInt16(ushort val) - { - IsNull = false; - Value = val; - } - - #region IMySqlValue Members - - public bool IsNull { get; } - - MySqlDbType IMySqlValue.MySqlDbType => MySqlDbType.UInt16; - - object IMySqlValue.Value => Value; - - public ushort Value { get; } - - Type IMySqlValue.SystemType => typeof(ushort); - - string IMySqlValue.MySqlTypeName => "SMALLINT"; - - async Task IMySqlValue.WriteValueAsync(MySqlPacket packet, bool binary, object val, int length, bool execAsync) - { - int v = (val is UInt16) ? (UInt16)val : Convert.ToUInt16(val); - if (binary) - await packet.WriteIntegerAsync(v, 2, execAsync).ConfigureAwait(false); - else - await packet.WriteStringNoNullAsync(v.ToString(CultureInfo.InvariantCulture), execAsync).ConfigureAwait(false); - } - - async Task IMySqlValue.ReadValueAsync(MySqlPacket packet, long length, bool nullVal, bool execAsync) - { - if (nullVal) - return new MySqlUInt16(true); - - if (length == -1) - return new MySqlUInt16((ushort)packet.ReadInteger(2)); - else - return new MySqlUInt16(UInt16.Parse(await packet.ReadStringAsync(length, execAsync).ConfigureAwait(false), CultureInfo.InvariantCulture)); - } - - void IMySqlValue.SkipValue(MySqlPacket packet) - { - packet.Position += 2; - } - - #endregion - - internal static void SetDSInfo(MySqlSchemaCollection sc) - { - // we use name indexing because this method will only be called - // when GetSchema is called for the DataSourceInformation - // collection and then it wil be cached. - MySqlSchemaRow row = sc.AddRow(); - row["TypeName"] = "SMALLINT"; - row["ProviderDbType"] = MySqlDbType.UInt16; - row["ColumnSize"] = 0; - row["CreateFormat"] = "SMALLINT UNSIGNED"; - row["CreateParameters"] = null; - row["DataType"] = "System.UInt16"; - row["IsAutoincrementable"] = true; - row["IsBestMatch"] = true; - row["IsCaseSensitive"] = false; - row["IsFixedLength"] = true; - row["IsFixedPrecisionScale"] = true; - row["IsLong"] = false; - row["IsNullable"] = true; - row["IsSearchable"] = true; - row["IsSearchableWithLike"] = false; - row["IsUnsigned"] = true; - row["MaximumScale"] = 0; - row["MinimumScale"] = 0; - row["IsConcurrencyType"] = DBNull.Value; - row["IsLiteralSupported"] = false; - row["LiteralPrefix"] = null; - row["LiteralSuffix"] = null; - row["NativeDataType"] = null; - } - } -} +// Copyright © 2004, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySql.Data.MySqlClient; +using System; +using System.Globalization; +using System.Threading.Tasks; + +namespace MySql.Data.Types +{ + internal struct MySqlUInt16 : IMySqlValue + { + public MySqlUInt16(bool isNull) + { + IsNull = isNull; + Value = 0; + } + + public MySqlUInt16(ushort val) + { + IsNull = false; + Value = val; + } + + #region IMySqlValue Members + + public bool IsNull { get; } + + MySqlDbType IMySqlValue.MySqlDbType => MySqlDbType.UInt16; + + object IMySqlValue.Value => Value; + + public ushort Value { get; } + + Type IMySqlValue.SystemType => typeof(ushort); + + string IMySqlValue.MySqlTypeName => "SMALLINT"; + + async Task IMySqlValue.WriteValueAsync(MySqlPacket packet, bool binary, object val, int length, bool execAsync) + { + int v = (val is UInt16) ? (UInt16)val : Convert.ToUInt16(val); + if (binary) + await packet.WriteIntegerAsync(v, 2, execAsync).ConfigureAwait(false); + else + await packet.WriteStringNoNullAsync(v.ToString(CultureInfo.InvariantCulture), execAsync).ConfigureAwait(false); + } + + async Task IMySqlValue.ReadValueAsync(MySqlPacket packet, long length, bool nullVal, bool execAsync) + { + if (nullVal) + return new MySqlUInt16(true); + + if (length == -1) + return new MySqlUInt16((ushort)packet.ReadInteger(2)); + else + return new MySqlUInt16(UInt16.Parse(await packet.ReadStringAsync(length, execAsync).ConfigureAwait(false), CultureInfo.InvariantCulture)); + } + + void IMySqlValue.SkipValue(MySqlPacket packet) + { + packet.Position += 2; + } + + #endregion + + internal static void SetDSInfo(MySqlSchemaCollection sc) + { + // we use name indexing because this method will only be called + // when GetSchema is called for the DataSourceInformation + // collection and then it wil be cached. + MySqlSchemaRow row = sc.AddRow(); + row["TypeName"] = "SMALLINT"; + row["ProviderDbType"] = MySqlDbType.UInt16; + row["ColumnSize"] = 0; + row["CreateFormat"] = "SMALLINT UNSIGNED"; + row["CreateParameters"] = null; + row["DataType"] = "System.UInt16"; + row["IsAutoincrementable"] = true; + row["IsBestMatch"] = true; + row["IsCaseSensitive"] = false; + row["IsFixedLength"] = true; + row["IsFixedPrecisionScale"] = true; + row["IsLong"] = false; + row["IsNullable"] = true; + row["IsSearchable"] = true; + row["IsSearchableWithLike"] = false; + row["IsUnsigned"] = true; + row["MaximumScale"] = 0; + row["MinimumScale"] = 0; + row["IsConcurrencyType"] = DBNull.Value; + row["IsLiteralSupported"] = false; + row["LiteralPrefix"] = null; + row["LiteralSuffix"] = null; + row["NativeDataType"] = null; + } + } +} diff --git a/MySQL.Data/src/Types/MySqlUInt32.cs b/MySQL.Data/src/Types/MySqlUInt32.cs index af0b147c8..612ec6383 100644 --- a/MySQL.Data/src/Types/MySqlUInt32.cs +++ b/MySQL.Data/src/Types/MySqlUInt32.cs @@ -1,144 +1,144 @@ -// Copyright (c) 2004, 2022, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySql.Data.MySqlClient; -using System; -using System.Globalization; -using System.Threading.Tasks; - -namespace MySql.Data.Types -{ - internal struct MySqlUInt32 : IMySqlValue - { - private readonly bool _is24Bit; - - private MySqlUInt32(MySqlDbType type) - { - _is24Bit = type == MySqlDbType.UInt24; - IsNull = true; - Value = 0; - } - - public MySqlUInt32(MySqlDbType type, bool isNull) - : this(type) - { - IsNull = isNull; - } - - public MySqlUInt32(MySqlDbType type, uint val) - : this(type) - { - IsNull = false; - Value = val; - } - - #region IMySqlValue Members - - public bool IsNull { get; } - - MySqlDbType IMySqlValue.MySqlDbType => MySqlDbType.UInt32; - - object IMySqlValue.Value => Value; - - public uint Value { get; } - - Type IMySqlValue.SystemType => typeof(UInt32); - - string IMySqlValue.MySqlTypeName - { - get { return _is24Bit ? "MEDIUMINT" : "INT"; } - } - - async Task IMySqlValue.WriteValueAsync(MySqlPacket packet, bool binary, object v, int length, bool execAsync) - { - uint val = v as uint? ?? Convert.ToUInt32(v); - if (binary) - await packet.WriteIntegerAsync((long)val, 4, execAsync).ConfigureAwait(false); - else - await packet.WriteStringNoNullAsync(val.ToString(CultureInfo.InvariantCulture), execAsync).ConfigureAwait(false); - } - - async Task IMySqlValue.ReadValueAsync(MySqlPacket packet, long length, bool nullVal, bool execAsync) - { - if (nullVal) - return new MySqlUInt32((this as IMySqlValue).MySqlDbType, true); - - if (length == -1) - return new MySqlUInt32((this as IMySqlValue).MySqlDbType, - (uint)packet.ReadInteger(4)); - else - return new MySqlUInt32((this as IMySqlValue).MySqlDbType, - UInt32.Parse(await packet.ReadStringAsync(length, execAsync).ConfigureAwait(false), NumberStyles.Any, CultureInfo.InvariantCulture)); - } - - void IMySqlValue.SkipValue(MySqlPacket packet) - { - packet.Position += 4; - } - - #endregion - - internal static void SetDSInfo(MySqlSchemaCollection sc) - { - string[] types = new string[] { "MEDIUMINT", "INT" }; - MySqlDbType[] dbtype = new MySqlDbType[] { MySqlDbType.UInt24, - MySqlDbType.UInt32 }; - - // we use name indexing because this method will only be called - // when GetSchema is called for the DataSourceInformation - // collection and then it will be cached. - for (int x = 0; x < types.Length; x++) - { - MySqlSchemaRow row = sc.AddRow(); - row["TypeName"] = types[x]; - row["ProviderDbType"] = dbtype[x]; - row["ColumnSize"] = 0; - row["CreateFormat"] = types[x] + " UNSIGNED"; - row["CreateParameters"] = null; - row["DataType"] = "System.UInt32"; - row["IsAutoincrementable"] = true; - row["IsBestMatch"] = true; - row["IsCaseSensitive"] = false; - row["IsFixedLength"] = true; - row["IsFixedPrecisionScale"] = true; - row["IsLong"] = false; - row["IsNullable"] = true; - row["IsSearchable"] = true; - row["IsSearchableWithLike"] = false; - row["IsUnsigned"] = true; - row["MaximumScale"] = 0; - row["MinimumScale"] = 0; - row["IsConcurrencyType"] = DBNull.Value; - row["IsLiteralSupported"] = false; - row["LiteralPrefix"] = null; - row["LiteralSuffix"] = null; - row["NativeDataType"] = null; - } - } - } -} +// Copyright © 2004, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySql.Data.MySqlClient; +using System; +using System.Globalization; +using System.Threading.Tasks; + +namespace MySql.Data.Types +{ + internal struct MySqlUInt32 : IMySqlValue + { + private readonly bool _is24Bit; + + private MySqlUInt32(MySqlDbType type) + { + _is24Bit = type == MySqlDbType.UInt24; + IsNull = true; + Value = 0; + } + + public MySqlUInt32(MySqlDbType type, bool isNull) + : this(type) + { + IsNull = isNull; + } + + public MySqlUInt32(MySqlDbType type, uint val) + : this(type) + { + IsNull = false; + Value = val; + } + + #region IMySqlValue Members + + public bool IsNull { get; } + + MySqlDbType IMySqlValue.MySqlDbType => MySqlDbType.UInt32; + + object IMySqlValue.Value => Value; + + public uint Value { get; } + + Type IMySqlValue.SystemType => typeof(UInt32); + + string IMySqlValue.MySqlTypeName + { + get { return _is24Bit ? "MEDIUMINT" : "INT"; } + } + + async Task IMySqlValue.WriteValueAsync(MySqlPacket packet, bool binary, object v, int length, bool execAsync) + { + uint val = v as uint? ?? Convert.ToUInt32(v); + if (binary) + await packet.WriteIntegerAsync((long)val, 4, execAsync).ConfigureAwait(false); + else + await packet.WriteStringNoNullAsync(val.ToString(CultureInfo.InvariantCulture), execAsync).ConfigureAwait(false); + } + + async Task IMySqlValue.ReadValueAsync(MySqlPacket packet, long length, bool nullVal, bool execAsync) + { + if (nullVal) + return new MySqlUInt32((this as IMySqlValue).MySqlDbType, true); + + if (length == -1) + return new MySqlUInt32((this as IMySqlValue).MySqlDbType, + (uint)packet.ReadInteger(4)); + else + return new MySqlUInt32((this as IMySqlValue).MySqlDbType, + UInt32.Parse(await packet.ReadStringAsync(length, execAsync).ConfigureAwait(false), NumberStyles.Any, CultureInfo.InvariantCulture)); + } + + void IMySqlValue.SkipValue(MySqlPacket packet) + { + packet.Position += 4; + } + + #endregion + + internal static void SetDSInfo(MySqlSchemaCollection sc) + { + string[] types = new string[] { "MEDIUMINT", "INT" }; + MySqlDbType[] dbtype = new MySqlDbType[] { MySqlDbType.UInt24, + MySqlDbType.UInt32 }; + + // we use name indexing because this method will only be called + // when GetSchema is called for the DataSourceInformation + // collection and then it will be cached. + for (int x = 0; x < types.Length; x++) + { + MySqlSchemaRow row = sc.AddRow(); + row["TypeName"] = types[x]; + row["ProviderDbType"] = dbtype[x]; + row["ColumnSize"] = 0; + row["CreateFormat"] = types[x] + " UNSIGNED"; + row["CreateParameters"] = null; + row["DataType"] = "System.UInt32"; + row["IsAutoincrementable"] = true; + row["IsBestMatch"] = true; + row["IsCaseSensitive"] = false; + row["IsFixedLength"] = true; + row["IsFixedPrecisionScale"] = true; + row["IsLong"] = false; + row["IsNullable"] = true; + row["IsSearchable"] = true; + row["IsSearchableWithLike"] = false; + row["IsUnsigned"] = true; + row["MaximumScale"] = 0; + row["MinimumScale"] = 0; + row["IsConcurrencyType"] = DBNull.Value; + row["IsLiteralSupported"] = false; + row["LiteralPrefix"] = null; + row["LiteralSuffix"] = null; + row["NativeDataType"] = null; + } + } + } +} diff --git a/MySQL.Data/src/Types/MySqlUInt64.cs b/MySQL.Data/src/Types/MySqlUInt64.cs index 0b7375571..15ebc5146 100644 --- a/MySQL.Data/src/Types/MySqlUInt64.cs +++ b/MySQL.Data/src/Types/MySqlUInt64.cs @@ -1,125 +1,125 @@ -// Copyright (c) 2004, 2022, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySql.Data.MySqlClient; -using System; -using System.Globalization; -using System.Threading.Tasks; - -namespace MySql.Data.Types -{ - internal struct MySqlUInt64 : IMySqlValue - { - public MySqlUInt64(bool isNull) - { - IsNull = isNull; - Value = 0; - } - - public MySqlUInt64(ulong val) - { - IsNull = false; - Value = val; - } - - #region IMySqlValue Members - - public bool IsNull { get; } - - MySqlDbType IMySqlValue.MySqlDbType => MySqlDbType.UInt64; - - object IMySqlValue.Value => Value; - - public ulong Value { get; } - - Type IMySqlValue.SystemType => typeof(ulong); - - string IMySqlValue.MySqlTypeName - { - get { return "BIGINT"; } - } - - async Task IMySqlValue.WriteValueAsync(MySqlPacket packet, bool binary, object val, int length, bool execAsync) - { - ulong v = val as ulong? ?? Convert.ToUInt64(val); - if (binary) - await packet.WriteIntegerAsync((long)v, 8, execAsync).ConfigureAwait(false); - else - await packet.WriteStringNoNullAsync(v.ToString(CultureInfo.InvariantCulture), execAsync).ConfigureAwait(false); - } - - async Task IMySqlValue.ReadValueAsync(MySqlPacket packet, long length, bool nullVal, bool execAsync) - { - if (nullVal) - return new MySqlUInt64(true); - - if (length == -1) - return new MySqlUInt64(packet.ReadULong(8)); - else - return new MySqlUInt64(UInt64.Parse(await packet.ReadStringAsync(length, execAsync).ConfigureAwait(false), CultureInfo.InvariantCulture)); - } - - void IMySqlValue.SkipValue(MySqlPacket packet) - { - packet.Position += 8; - } - - #endregion - - internal static void SetDSInfo(MySqlSchemaCollection sc) - { - // we use name indexing because this method will only be called - // when GetSchema is called for the DataSourceInformation - // collection and then it wil be cached. - MySqlSchemaRow row = sc.AddRow(); - row["TypeName"] = "BIGINT"; - row["ProviderDbType"] = MySqlDbType.UInt64; - row["ColumnSize"] = 0; - row["CreateFormat"] = "BIGINT UNSIGNED"; - row["CreateParameters"] = null; - row["DataType"] = "System.UInt64"; - row["IsAutoincrementable"] = true; - row["IsBestMatch"] = true; - row["IsCaseSensitive"] = false; - row["IsFixedLength"] = true; - row["IsFixedPrecisionScale"] = true; - row["IsLong"] = false; - row["IsNullable"] = true; - row["IsSearchable"] = true; - row["IsSearchableWithLike"] = false; - row["IsUnsigned"] = true; - row["MaximumScale"] = 0; - row["MinimumScale"] = 0; - row["IsConcurrencyType"] = DBNull.Value; - row["IsLiteralSupported"] = false; - row["LiteralPrefix"] = null; - row["LiteralSuffix"] = null; - row["NativeDataType"] = null; - } - } -} +// Copyright © 2004, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySql.Data.MySqlClient; +using System; +using System.Globalization; +using System.Threading.Tasks; + +namespace MySql.Data.Types +{ + internal struct MySqlUInt64 : IMySqlValue + { + public MySqlUInt64(bool isNull) + { + IsNull = isNull; + Value = 0; + } + + public MySqlUInt64(ulong val) + { + IsNull = false; + Value = val; + } + + #region IMySqlValue Members + + public bool IsNull { get; } + + MySqlDbType IMySqlValue.MySqlDbType => MySqlDbType.UInt64; + + object IMySqlValue.Value => Value; + + public ulong Value { get; } + + Type IMySqlValue.SystemType => typeof(ulong); + + string IMySqlValue.MySqlTypeName + { + get { return "BIGINT"; } + } + + async Task IMySqlValue.WriteValueAsync(MySqlPacket packet, bool binary, object val, int length, bool execAsync) + { + ulong v = val as ulong? ?? Convert.ToUInt64(val); + if (binary) + await packet.WriteIntegerAsync((long)v, 8, execAsync).ConfigureAwait(false); + else + await packet.WriteStringNoNullAsync(v.ToString(CultureInfo.InvariantCulture), execAsync).ConfigureAwait(false); + } + + async Task IMySqlValue.ReadValueAsync(MySqlPacket packet, long length, bool nullVal, bool execAsync) + { + if (nullVal) + return new MySqlUInt64(true); + + if (length == -1) + return new MySqlUInt64(packet.ReadULong(8)); + else + return new MySqlUInt64(UInt64.Parse(await packet.ReadStringAsync(length, execAsync).ConfigureAwait(false), CultureInfo.InvariantCulture)); + } + + void IMySqlValue.SkipValue(MySqlPacket packet) + { + packet.Position += 8; + } + + #endregion + + internal static void SetDSInfo(MySqlSchemaCollection sc) + { + // we use name indexing because this method will only be called + // when GetSchema is called for the DataSourceInformation + // collection and then it wil be cached. + MySqlSchemaRow row = sc.AddRow(); + row["TypeName"] = "BIGINT"; + row["ProviderDbType"] = MySqlDbType.UInt64; + row["ColumnSize"] = 0; + row["CreateFormat"] = "BIGINT UNSIGNED"; + row["CreateParameters"] = null; + row["DataType"] = "System.UInt64"; + row["IsAutoincrementable"] = true; + row["IsBestMatch"] = true; + row["IsCaseSensitive"] = false; + row["IsFixedLength"] = true; + row["IsFixedPrecisionScale"] = true; + row["IsLong"] = false; + row["IsNullable"] = true; + row["IsSearchable"] = true; + row["IsSearchableWithLike"] = false; + row["IsUnsigned"] = true; + row["MaximumScale"] = 0; + row["MinimumScale"] = 0; + row["IsConcurrencyType"] = DBNull.Value; + row["IsLiteralSupported"] = false; + row["LiteralPrefix"] = null; + row["LiteralSuffix"] = null; + row["NativeDataType"] = null; + } + } +} diff --git a/MySQL.Data/src/Utils.cs b/MySQL.Data/src/Utils.cs index 2ba51d04d..e023de66b 100644 --- a/MySQL.Data/src/Utils.cs +++ b/MySQL.Data/src/Utils.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2004, 2023, Oracle and/or its affiliates. +// Copyright © 2004, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/X/Authentication/ExternalAuthenticationPlugin.cs b/MySQL.Data/src/X/Authentication/ExternalAuthenticationPlugin.cs index 33dec2cfb..ef7916205 100644 --- a/MySQL.Data/src/X/Authentication/ExternalAuthenticationPlugin.cs +++ b/MySQL.Data/src/X/Authentication/ExternalAuthenticationPlugin.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2017, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -61,4 +61,4 @@ public string AuthName } } } -} \ No newline at end of file +} diff --git a/MySQL.Data/src/X/Authentication/MySQL41AuthenticationPlugin.cs b/MySQL.Data/src/X/Authentication/MySQL41AuthenticationPlugin.cs index b42fae652..a64f8cbf3 100644 --- a/MySQL.Data/src/X/Authentication/MySQL41AuthenticationPlugin.cs +++ b/MySQL.Data/src/X/Authentication/MySQL41AuthenticationPlugin.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2015, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -90,4 +90,4 @@ public byte[] Continue(byte[] salt) return response; } } -} \ No newline at end of file +} diff --git a/MySQL.Data/src/X/Authentication/PlainAuthenticationPlugin.cs b/MySQL.Data/src/X/Authentication/PlainAuthenticationPlugin.cs index b318a48fd..f0ca78138 100644 --- a/MySQL.Data/src/X/Authentication/PlainAuthenticationPlugin.cs +++ b/MySQL.Data/src/X/Authentication/PlainAuthenticationPlugin.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2017, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -70,4 +70,4 @@ public byte[] GetAuthData() )); } } -} \ No newline at end of file +} diff --git a/MySQL.Data/src/X/Common/Tools.cs b/MySQL.Data/src/X/Common/Tools.cs index 7e962eccc..b74fab9e4 100644 --- a/MySQL.Data/src/X/Common/Tools.cs +++ b/MySQL.Data/src/X/Common/Tools.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2014, 2020 Oracle and/or its affiliates. +// Copyright © 2014, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/X/Common/UnmanagedLibraryLoader.cs b/MySQL.Data/src/X/Common/UnmanagedLibraryLoader.cs index 10e6829e6..8f0f6e419 100644 --- a/MySQL.Data/src/X/Common/UnmanagedLibraryLoader.cs +++ b/MySQL.Data/src/X/Common/UnmanagedLibraryLoader.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2020 Oracle and/or its affiliates. +// Copyright © 2022, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/X/Communication/CommunicationPacket.cs b/MySQL.Data/src/X/Communication/CommunicationPacket.cs index 63c612636..930593c45 100644 --- a/MySQL.Data/src/X/Communication/CommunicationPacket.cs +++ b/MySQL.Data/src/X/Communication/CommunicationPacket.cs @@ -1,96 +1,96 @@ -// Copyright © 2015, 2019, Oracle and/or its affiliates. All rights reserved. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -namespace MySqlX.Communication -{ - internal class CommunicationPacket - { - - public CommunicationPacket(int messageType, int length, byte[] data) - { - MessageType = messageType; - Length = length; - Buffer = data; - } - - public byte[] Buffer; - public int MessageType; - public int Length; - } - - internal enum ClientMessageId - { - CON_CAPABILITIES_GET = 1, - CON_CAPABILITIES_SET = 2, - CON_CLOSE = 3, - - SESS_AUTHENTICATE_START = 4, - SESS_AUTHENTICATE_CONTINUE = 5, - SESS_RESET = 6, - SESS_CLOSE = 7, - - SQL_STMT_EXECUTE = 12, - - CRUD_FIND = 17, - CRUD_INSERT = 18, - CRUD_UPDATE = 19, - CRUD_DELETE = 20, - - EXPECT_OPEN = 24, - EXPECT_CLOSE = 25, - - COMPRESSION = 46 - } - - - internal enum ServerMessageId - { - OK = 0, - ERROR = 1, - - CONN_CAPABILITIES = 2, - - SESS_AUTHENTICATE_CONTINUE = 3, - SESS_AUTHENTICATE_OK = 4, - - // NOTICE has to stay at 11 forever - NOTICE = 11, - - RESULTSET_COLUMN_META_DATA = 12, - RESULTSET_ROW = 13, - RESULTSET_FETCH_DONE = 14, - RESULTSET_FETCH_SUSPENDED = 15, - RESULTSET_FETCH_DONE_MORE_RESULTSETS = 16, - - SQL_STMT_EXECUTE_OK = 17, - RESULTSET_FETCH_DONE_MORE_OUT_PARAMS = 18, - - COMPRESSION = 19 - } - -} +// Copyright © 2015, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +namespace MySqlX.Communication +{ + internal class CommunicationPacket + { + + public CommunicationPacket(int messageType, int length, byte[] data) + { + MessageType = messageType; + Length = length; + Buffer = data; + } + + public byte[] Buffer; + public int MessageType; + public int Length; + } + + internal enum ClientMessageId + { + CON_CAPABILITIES_GET = 1, + CON_CAPABILITIES_SET = 2, + CON_CLOSE = 3, + + SESS_AUTHENTICATE_START = 4, + SESS_AUTHENTICATE_CONTINUE = 5, + SESS_RESET = 6, + SESS_CLOSE = 7, + + SQL_STMT_EXECUTE = 12, + + CRUD_FIND = 17, + CRUD_INSERT = 18, + CRUD_UPDATE = 19, + CRUD_DELETE = 20, + + EXPECT_OPEN = 24, + EXPECT_CLOSE = 25, + + COMPRESSION = 46 + } + + + internal enum ServerMessageId + { + OK = 0, + ERROR = 1, + + CONN_CAPABILITIES = 2, + + SESS_AUTHENTICATE_CONTINUE = 3, + SESS_AUTHENTICATE_OK = 4, + + // NOTICE has to stay at 11 forever + NOTICE = 11, + + RESULTSET_COLUMN_META_DATA = 12, + RESULTSET_ROW = 13, + RESULTSET_FETCH_DONE = 14, + RESULTSET_FETCH_SUSPENDED = 15, + RESULTSET_FETCH_DONE_MORE_RESULTSETS = 16, + + SQL_STMT_EXECUTE_OK = 17, + RESULTSET_FETCH_DONE_MORE_OUT_PARAMS = 18, + + COMPRESSION = 19 + } + +} diff --git a/MySQL.Data/src/X/Communication/XCompressionController.cs b/MySQL.Data/src/X/Communication/XCompressionController.cs index 8701b0262..fd55c5dc9 100644 --- a/MySQL.Data/src/X/Communication/XCompressionController.cs +++ b/MySQL.Data/src/X/Communication/XCompressionController.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2019, 2023, Oracle and/or its affiliates. +// Copyright © 2019, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/X/Communication/XPacketProcessor.cs b/MySQL.Data/src/X/Communication/XPacketProcessor.cs index 9d19da8a8..df411e154 100644 --- a/MySQL.Data/src/X/Communication/XPacketProcessor.cs +++ b/MySQL.Data/src/X/Communication/XPacketProcessor.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2023, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/X/Communication/XPacketReaderWriter.cs b/MySQL.Data/src/X/Communication/XPacketReaderWriter.cs index b962a7b6f..4002b7f36 100644 --- a/MySQL.Data/src/X/Communication/XPacketReaderWriter.cs +++ b/MySQL.Data/src/X/Communication/XPacketReaderWriter.cs @@ -1,151 +1,151 @@ -// Copyright (c) 2015, 2023, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using Google.Protobuf; -using MySql.Data.Common; -using MySql.Data.X.Communication; -using Mysqlx; -using Mysqlx.Connection; -using System; -using System.IO; -using System.Net.Sockets; - -namespace MySqlX.Communication -{ - internal class XPacketReaderWriter - { - private Stream _stream; - private Socket _socket; - private XPacketProcessor _packetProcessor; - - /// - /// Constructor that sets the stream used to read or write data. - /// - /// The stream used to read or write data. - /// The socket to use. - public XPacketReaderWriter(Stream stream, Socket socket) - { - _stream = stream; - _socket = socket; - _packetProcessor = new XPacketProcessor(stream); - } - - /// - /// Constructor that sets the stream used to read or write data and the compression controller. - /// - /// The stream used to read or write data. - /// The compression controller for reading. - /// The compression controller for writing. - /// The socket to use. - public XPacketReaderWriter(Stream stream, XCompressionController compressionReadController, XCompressionController compressionWriteController, Socket socket) - { - _stream = stream; - _socket = socket; - CompressionReadController = compressionReadController; - CompressionWriteController = compressionWriteController; - _packetProcessor = new XPacketProcessor(stream, CompressionReadController); - } - - /// - /// Gets or sets the compression controller uses to manage compression operations. - /// - public XCompressionController CompressionReadController { get; private set; } - public XCompressionController CompressionWriteController { get; private set; } - - /// - /// Writes X Protocol frames to the X Plugin. - /// - /// The integer representation of the client message identifier used for the message. - /// The message to include in the X Protocol frame. - public void Write(int id, IMessage message) - { - var messageSize = message.CalculateSize(); - _packetProcessor.ProcessPendingPackets(_socket); - if (CompressionWriteController != null - && CompressionWriteController.IsCompressionEnabled - && messageSize > XCompressionController.COMPRESSION_THRESHOLD - && CompressionWriteController.ClientSupportedCompressedMessages.Contains((ClientMessageId)id) - ) - { - // Build the compression protobuf message. - var messageHeader = new byte[5]; - var messageBytes = message.ToByteArray(); - byte[] payload = new byte[messageHeader.Length + messageBytes.Length]; - var sizeArray = BitConverter.GetBytes(messageSize + 1); - Buffer.BlockCopy(sizeArray, 0, messageHeader, 0, sizeArray.Length); - messageHeader[4] = (byte)id; - Buffer.BlockCopy(messageHeader, 0, payload, 0, messageHeader.Length); - Buffer.BlockCopy(messageBytes, 0, payload, messageHeader.Length, messageBytes.Length); - - var compression = new Compression(); - compression.UncompressedSize = (ulong)(messageSize + messageHeader.Length); - compression.ClientMessages = (ClientMessages.Types.Type)id; - compression.Payload = ByteString.CopyFrom(CompressionWriteController.Compress(payload)); - - // Build the X Protocol frame. - _stream.Write(BitConverter.GetBytes(compression.CalculateSize() + 1), 0, 4); - _stream.WriteByte((byte)(ClientMessageId.COMPRESSION)); - if (messageSize > 0) - { - compression.WriteTo(_stream); - } - } - else - { - _stream.Write(BitConverter.GetBytes(messageSize + 1), 0, 4); - _stream.WriteByte((byte)id); - if (messageSize > 0) - { - message.WriteTo(_stream); - } - } - - _stream.Flush(); - } - - /// - /// Writes X Protocol frames to the X Plugin. - /// - /// The client message identifier used for the message. - /// The message to include in the X Protocol frame. - public void Write(ClientMessageId id, IMessage message) - { - Write((int)id, message); - } - - /// - /// Reads X Protocol frames incoming from the X Plugin. - /// - /// A instance representing the X Protocol frame that was read. - public CommunicationPacket Read() - { - return _packetProcessor.GetPacketFromNetworkStream(true); - } - - } -} +// Copyright © 2015, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using Google.Protobuf; +using MySql.Data.Common; +using MySql.Data.X.Communication; +using Mysqlx; +using Mysqlx.Connection; +using System; +using System.IO; +using System.Net.Sockets; + +namespace MySqlX.Communication +{ + internal class XPacketReaderWriter + { + private Stream _stream; + private Socket _socket; + private XPacketProcessor _packetProcessor; + + /// + /// Constructor that sets the stream used to read or write data. + /// + /// The stream used to read or write data. + /// The socket to use. + public XPacketReaderWriter(Stream stream, Socket socket) + { + _stream = stream; + _socket = socket; + _packetProcessor = new XPacketProcessor(stream); + } + + /// + /// Constructor that sets the stream used to read or write data and the compression controller. + /// + /// The stream used to read or write data. + /// The compression controller for reading. + /// The compression controller for writing. + /// The socket to use. + public XPacketReaderWriter(Stream stream, XCompressionController compressionReadController, XCompressionController compressionWriteController, Socket socket) + { + _stream = stream; + _socket = socket; + CompressionReadController = compressionReadController; + CompressionWriteController = compressionWriteController; + _packetProcessor = new XPacketProcessor(stream, CompressionReadController); + } + + /// + /// Gets or sets the compression controller uses to manage compression operations. + /// + public XCompressionController CompressionReadController { get; private set; } + public XCompressionController CompressionWriteController { get; private set; } + + /// + /// Writes X Protocol frames to the X Plugin. + /// + /// The integer representation of the client message identifier used for the message. + /// The message to include in the X Protocol frame. + public void Write(int id, IMessage message) + { + var messageSize = message.CalculateSize(); + _packetProcessor.ProcessPendingPackets(_socket); + if (CompressionWriteController != null + && CompressionWriteController.IsCompressionEnabled + && messageSize > XCompressionController.COMPRESSION_THRESHOLD + && CompressionWriteController.ClientSupportedCompressedMessages.Contains((ClientMessageId)id) + ) + { + // Build the compression protobuf message. + var messageHeader = new byte[5]; + var messageBytes = message.ToByteArray(); + byte[] payload = new byte[messageHeader.Length + messageBytes.Length]; + var sizeArray = BitConverter.GetBytes(messageSize + 1); + Buffer.BlockCopy(sizeArray, 0, messageHeader, 0, sizeArray.Length); + messageHeader[4] = (byte)id; + Buffer.BlockCopy(messageHeader, 0, payload, 0, messageHeader.Length); + Buffer.BlockCopy(messageBytes, 0, payload, messageHeader.Length, messageBytes.Length); + + var compression = new Compression(); + compression.UncompressedSize = (ulong)(messageSize + messageHeader.Length); + compression.ClientMessages = (ClientMessages.Types.Type)id; + compression.Payload = ByteString.CopyFrom(CompressionWriteController.Compress(payload)); + + // Build the X Protocol frame. + _stream.Write(BitConverter.GetBytes(compression.CalculateSize() + 1), 0, 4); + _stream.WriteByte((byte)(ClientMessageId.COMPRESSION)); + if (messageSize > 0) + { + compression.WriteTo(_stream); + } + } + else + { + _stream.Write(BitConverter.GetBytes(messageSize + 1), 0, 4); + _stream.WriteByte((byte)id); + if (messageSize > 0) + { + message.WriteTo(_stream); + } + } + + _stream.Flush(); + } + + /// + /// Writes X Protocol frames to the X Plugin. + /// + /// The client message identifier used for the message. + /// The message to include in the X Protocol frame. + public void Write(ClientMessageId id, IMessage message) + { + Write((int)id, message); + } + + /// + /// Reads X Protocol frames incoming from the X Plugin. + /// + /// A instance representing the X Protocol frame that was read. + public CommunicationPacket Read() + { + return _packetProcessor.GetPacketFromNetworkStream(true); + } + + } +} diff --git a/MySQL.Data/src/X/Data/CollationMap.cs b/MySQL.Data/src/X/Data/CollationMap.cs index 6b8330115..7f717f079 100644 --- a/MySQL.Data/src/X/Data/CollationMap.cs +++ b/MySQL.Data/src/X/Data/CollationMap.cs @@ -1,342 +1,342 @@ -// Copyright © 2016, 2019, Oracle and/or its affiliates. All rights reserved. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySql.Data; -using System; -using System.Collections.Generic; - -namespace MySqlX.Data -{ - internal class CollationMap - { - private static Dictionary collations = new Dictionary(); - - static CollationMap() - { - Load(); - } - - public static string GetCollationName(int collation) - { - if (!collations.ContainsKey(collation)) - throw new KeyNotFoundException(String.Format(ResourcesX.InvalidCollationId, collation)); - return collations[collation]; - } - - private static void Load() - { - collations.Add(0, "utf8mb3_general_ci"); - collations.Add(1, "big5_chinese_ci"); - collations.Add(2, "latin2_czech_cs"); - collations.Add(3, "dec8_swedish_ci"); - collations.Add(4, "cp850_general_ci"); - collations.Add(5, "latin1_german1_ci"); - collations.Add(6, "hp8_english_ci"); - collations.Add(7, "koi8r_general_ci"); - collations.Add(8, "latin1_swedish_ci"); - collations.Add(9, "latin2_general_ci"); - collations.Add(10, "swe7_swedish_ci"); - collations.Add(11, "ascii_general_ci"); - collations.Add(12, "ujis_japanese_ci"); - collations.Add(13, "sjis_japanese_ci"); - collations.Add(14, "cp1251_bulgarian_ci"); - collations.Add(15, "latin1_danish_ci"); - collations.Add(16, "hebrew_general_ci"); - collations.Add(18, "tis620_thai_ci"); - collations.Add(19, "euckr_korean_ci"); - collations.Add(20, "latin7_estonian_cs"); - collations.Add(21, "latin2_hungarian_ci"); - collations.Add(22, "koi8u_general_ci"); - collations.Add(23, "cp1251_ukrainian_ci"); - collations.Add(24, "gb2312_chinese_ci"); - collations.Add(25, "greek_general_ci"); - collations.Add(26, "cp1250_general_ci"); - collations.Add(27, "latin2_croatian_ci"); - collations.Add(28, "gbk_chinese_ci"); - collations.Add(29, "cp1257_lithuanian_ci"); - collations.Add(30, "latin5_turkish_ci"); - collations.Add(31, "latin1_german2_ci"); - collations.Add(32, "armscii8_general_ci"); - collations.Add(33, "utf8mb3_general_ci"); - collations.Add(34, "cp1250_czech_cs"); - collations.Add(35, "ucs2_general_ci"); - collations.Add(36, "cp866_general_ci"); - collations.Add(37, "keybcs2_general_ci"); - collations.Add(38, "macce_general_ci"); - collations.Add(39, "macroman_general_ci"); - collations.Add(40, "cp852_general_ci"); - collations.Add(41, "latin7_general_ci"); - collations.Add(42, "latin7_general_cs"); - collations.Add(43, "macce_bin"); - collations.Add(44, "cp1250_croatian_ci"); - collations.Add(45, "utf8mb4_general_ci"); - collations.Add(46, "utf8mb4_bin"); - collations.Add(47, "latin1_bin"); - collations.Add(48, "latin1_general_ci"); - collations.Add(49, "latin1_general_cs"); - collations.Add(50, "cp1251_bin"); - collations.Add(51, "cp1251_general_ci"); - collations.Add(52, "cp1251_general_cs"); - collations.Add(53, "macroman_bin"); - collations.Add(54, "utf16_general_ci"); - collations.Add(55, "utf16_bin"); - collations.Add(56, "utf16le_general_ci"); - collations.Add(57, "cp1256_general_ci"); - collations.Add(58, "cp1257_bin"); - collations.Add(59, "cp1257_general_ci"); - collations.Add(60, "utf32_general_ci"); - collations.Add(61, "utf32_bin"); - collations.Add(62, "utf16le_bin"); - collations.Add(63, "binary"); - collations.Add(64, "armscii8_bin"); - collations.Add(65, "ascii_bin"); - collations.Add(66, "cp1250_bin"); - collations.Add(67, "cp1256_bin"); - collations.Add(68, "cp866_bin"); - collations.Add(69, "dec8_bin"); - collations.Add(70, "greek_bin"); - collations.Add(71, "hebrew_bin"); - collations.Add(72, "hp8_bin"); - collations.Add(73, "keybcs2_bin"); - collations.Add(74, "koi8r_bin"); - collations.Add(75, "koi8u_bin"); - collations.Add(76, "utf8mb3_tolower_ci"); - collations.Add(77, "latin2_bin"); - collations.Add(78, "latin5_bin"); - collations.Add(79, "latin7_bin"); - collations.Add(80, "cp850_bin"); - collations.Add(81, "cp852_bin"); - collations.Add(82, "swe7_bin"); - collations.Add(83, "utf8mb3_bin"); - collations.Add(84, "big5_bin"); - collations.Add(85, "euckr_bin"); - collations.Add(86, "gb2312_bin"); - collations.Add(87, "gbk_bin"); - collations.Add(88, "sjis_bin"); - collations.Add(89, "tis620_bin"); - collations.Add(90, "ucs2_bin"); - collations.Add(91, "ujis_bin"); - collations.Add(92, "geostd8_general_ci"); - collations.Add(93, "geostd8_bin"); - collations.Add(94, "latin1_spanish_ci"); - collations.Add(95, "cp932_japanese_ci"); - collations.Add(96, "cp932_bin"); - collations.Add(97, "eucjpms_japanese_ci"); - collations.Add(98, "eucjpms_bin"); - collations.Add(99, "cp1250_polish_ci"); - collations.Add(101, "utf16_unicode_ci"); - collations.Add(102, "utf16_icelandic_ci"); - collations.Add(103, "utf16_latvian_ci"); - collations.Add(104, "utf16_romanian_ci"); - collations.Add(105, "utf16_slovenian_ci"); - collations.Add(106, "utf16_polish_ci"); - collations.Add(107, "utf16_estonian_ci"); - collations.Add(108, "utf16_spanish_ci"); - collations.Add(109, "utf16_swedish_ci"); - collations.Add(110, "utf16_turkish_ci"); - collations.Add(111, "utf16_czech_ci"); - collations.Add(112, "utf16_danish_ci"); - collations.Add(113, "utf16_lithuanian_ci"); - collations.Add(114, "utf16_slovak_ci"); - collations.Add(115, "utf16_spanish2_ci"); - collations.Add(116, "utf16_roman_ci"); - collations.Add(117, "utf16_persian_ci"); - collations.Add(118, "utf16_esperanto_ci"); - collations.Add(119, "utf16_hungarian_ci"); - collations.Add(120, "utf16_sinhala_ci"); - collations.Add(121, "utf16_german2_ci"); - collations.Add(122, "utf16_croatian_ci"); - collations.Add(123, "utf16_unicode_520_ci"); - collations.Add(124, "utf16_vietnamese_ci"); - collations.Add(128, "ucs2_unicode_ci"); - collations.Add(129, "ucs2_icelandic_ci"); - collations.Add(130, "ucs2_latvian_ci"); - collations.Add(131, "ucs2_romanian_ci"); - collations.Add(132, "ucs2_slovenian_ci"); - collations.Add(133, "ucs2_polish_ci"); - collations.Add(134, "ucs2_estonian_ci"); - collations.Add(135, "ucs2_spanish_ci"); - collations.Add(136, "ucs2_swedish_ci"); - collations.Add(137, "ucs2_turkish_ci"); - collations.Add(138, "ucs2_czech_ci"); - collations.Add(139, "ucs2_danish_ci"); - collations.Add(140, "ucs2_lithuanian_ci"); - collations.Add(141, "ucs2_slovak_ci"); - collations.Add(142, "ucs2_spanish2_ci"); - collations.Add(143, "ucs2_roman_ci"); - collations.Add(144, "ucs2_persian_ci"); - collations.Add(145, "ucs2_esperanto_ci"); - collations.Add(146, "ucs2_hungarian_ci"); - collations.Add(147, "ucs2_sinhala_ci"); - collations.Add(148, "ucs2_german2_ci"); - collations.Add(149, "ucs2_croatian_ci"); - collations.Add(150, "ucs2_unicode_520_ci"); - collations.Add(151, "ucs2_vietnamese_ci"); - collations.Add(159, "ucs2_general_mysql500_ci"); - collations.Add(160, "utf32_unicode_ci"); - collations.Add(161, "utf32_icelandic_ci"); - collations.Add(162, "utf32_latvian_ci"); - collations.Add(163, "utf32_romanian_ci"); - collations.Add(164, "utf32_slovenian_ci"); - collations.Add(165, "utf32_polish_ci"); - collations.Add(166, "utf32_estonian_ci"); - collations.Add(167, "utf32_spanish_ci"); - collations.Add(168, "utf32_swedish_ci"); - collations.Add(169, "utf32_turkish_ci"); - collations.Add(170, "utf32_czech_ci"); - collations.Add(171, "utf32_danish_ci"); - collations.Add(172, "utf32_lithuanian_ci"); - collations.Add(173, "utf32_slovak_ci"); - collations.Add(174, "utf32_spanish2_ci"); - collations.Add(175, "utf32_roman_ci"); - collations.Add(176, "utf32_persian_ci"); - collations.Add(177, "utf32_esperanto_ci"); - collations.Add(178, "utf32_hungarian_ci"); - collations.Add(179, "utf32_sinhala_ci"); - collations.Add(180, "utf32_german2_ci"); - collations.Add(181, "utf32_croatian_ci"); - collations.Add(182, "utf32_unicode_520_ci"); - collations.Add(183, "utf32_vietnamese_ci"); - collations.Add(192, "utf8mb3_unicode_ci"); - collations.Add(193, "utf8mb3_icelandic_ci"); - collations.Add(194, "utf8mb3_latvian_ci"); - collations.Add(195, "utf8mb3_romanian_ci"); - collations.Add(196, "utf8mb3_slovenian_ci"); - collations.Add(197, "utf8mb3_polish_ci"); - collations.Add(198, "utf8mb3_estonian_ci"); - collations.Add(199, "utf8mb3_spanish_ci"); - collations.Add(200, "utf8mb3_swedish_ci"); - collations.Add(201, "utf8mb3_turkish_ci"); - collations.Add(202, "utf8mb3_czech_ci"); - collations.Add(203, "utf8mb3_danish_ci"); - collations.Add(204, "utf8mb3_lithuanian_ci"); - collations.Add(205, "utf8mb3_slovak_ci"); - collations.Add(206, "utf8mb3_spanish2_ci"); - collations.Add(207, "utf8mb3_roman_ci"); - collations.Add(208, "utf8mb3_persian_ci"); - collations.Add(209, "utf8mb3_esperanto_ci"); - collations.Add(210, "utf8mb3_hungarian_ci"); - collations.Add(211, "utf8mb3_sinhala_ci"); - collations.Add(212, "utf8mb3_german2_ci"); - collations.Add(213, "utf8mb3_croatian_ci"); - collations.Add(214, "utf8mb3_unicode_520_ci"); - collations.Add(215, "utf8mb3_vietnamese_ci"); - collations.Add(223, "utf8mb3_general_mysql500_ci"); - collations.Add(224, "utf8mb4_unicode_ci"); - collations.Add(225, "utf8mb4_icelandic_ci"); - collations.Add(226, "utf8mb4_latvian_ci"); - collations.Add(227, "utf8mb4_romanian_ci"); - collations.Add(228, "utf8mb4_slovenian_ci"); - collations.Add(229, "utf8mb4_polish_ci"); - collations.Add(230, "utf8mb4_estonian_ci"); - collations.Add(231, "utf8mb4_spanish_ci"); - collations.Add(232, "utf8mb4_swedish_ci"); - collations.Add(233, "utf8mb4_turkish_ci"); - collations.Add(234, "utf8mb4_czech_ci"); - collations.Add(235, "utf8mb4_danish_ci"); - collations.Add(236, "utf8mb4_lithuanian_ci"); - collations.Add(237, "utf8mb4_slovak_ci"); - collations.Add(238, "utf8mb4_spanish2_ci"); - collations.Add(239, "utf8mb4_roman_ci"); - collations.Add(240, "utf8mb4_persian_ci"); - collations.Add(241, "utf8mb4_esperanto_ci"); - collations.Add(242, "utf8mb4_hungarian_ci"); - collations.Add(243, "utf8mb4_sinhala_ci"); - collations.Add(244, "utf8mb4_german2_ci"); - collations.Add(245, "utf8mb4_croatian_ci"); - collations.Add(246, "utf8mb4_unicode_520_ci"); - collations.Add(247, "utf8mb4_vietnamese_ci"); - collations.Add(248, "gb18030_chinese_ci"); - collations.Add(249, "gb18030_bin"); - collations.Add(250, "gb18030_unicode_520_ci"); - collations.Add(255, "utf8mb4_0900_ai_ci"); - collations.Add(256, "utf8mb4_de_pb_0900_ai_ci"); - collations.Add(257, "utf8mb4_is_0900_ai_ci"); - collations.Add(258, "utf8mb4_lv_0900_ai_ci"); - collations.Add(259, "utf8mb4_ro_0900_ai_ci"); - collations.Add(260, "utf8mb4_sl_0900_ai_ci"); - collations.Add(261, "utf8mb4_pl_0900_ai_ci"); - collations.Add(262, "utf8mb4_et_0900_ai_ci"); - collations.Add(263, "utf8mb4_es_0900_ai_ci"); - collations.Add(264, "utf8mb4_sv_0900_ai_ci"); - collations.Add(265, "utf8mb4_tr_0900_ai_ci"); - collations.Add(266, "utf8mb4_cs_0900_ai_ci"); - collations.Add(267, "utf8mb4_da_0900_ai_ci"); - collations.Add(268, "utf8mb4_lt_0900_ai_ci"); - collations.Add(269, "utf8mb4_sk_0900_ai_ci"); - collations.Add(270, "utf8mb4_es_trad_0900_ai_ci"); - collations.Add(271, "utf8mb4_la_0900_ai_ci"); - collations.Add(273, "utf8mb4_eo_0900_ai_ci"); - collations.Add(274, "utf8mb4_hu_0900_ai_ci"); - collations.Add(275, "utf8mb4_hr_0900_ai_ci"); - collations.Add(277, "utf8mb4_vi_0900_ai_ci"); - collations.Add(278, "utf8mb4_0900_as_cs"); - collations.Add(279, "utf8mb4_de_pb_0900_as_cs"); - collations.Add(280, "utf8mb4_is_0900_as_cs"); - collations.Add(281, "utf8mb4_lv_0900_as_cs"); - collations.Add(282, "utf8mb4_ro_0900_as_cs"); - collations.Add(283, "utf8mb4_sl_0900_as_cs"); - collations.Add(284, "utf8mb4_pl_0900_as_cs"); - collations.Add(285, "utf8mb4_et_0900_as_cs"); - collations.Add(286, "utf8mb4_es_0900_as_cs"); - collations.Add(287, "utf8mb4_sv_0900_as_cs"); - collations.Add(288, "utf8mb4_tr_0900_as_cs"); - collations.Add(289, "utf8mb4_cs_0900_as_cs"); - collations.Add(290, "utf8mb4_da_0900_as_cs"); - collations.Add(291, "utf8mb4_lt_0900_as_cs"); - collations.Add(292, "utf8mb4_sk_0900_as_cs"); - collations.Add(293, "utf8mb4_es_trad_0900_as_cs"); - collations.Add(294, "utf8mb4_la_0900_as_cs"); - collations.Add(296, "utf8mb4_eo_0900_as_cs"); - collations.Add(297, "utf8mb4_hu_0900_as_cs"); - collations.Add(298, "utf8mb4_hr_0900_as_cs"); - collations.Add(300, "utf8mb4_vi_0900_as_cs"); - collations.Add(303, "utf8mb4_ja_0900_as_cs"); - collations.Add(304, "utf8mb4_ja_0900_as_cs_ks"); - collations.Add(305, "utf8mb4_0900_as_ci"); - collations.Add(306, "utf8mb4_ru_0900_ai_ci"); - collations.Add(307, "utf8mb4_ru_0900_as_cs"); - collations.Add(308, "utf8mb4_zh_0900_as_cs"); - collations.Add(309, "utf8mb4_0900_bin"); - collations.Add(310, "utf8mb4_nb_0900_ai_ci"); - collations.Add(311, "utf8mb4_nb_0900_as_cs"); - collations.Add(312, "utf8mb4_nn_0900_ai_ci"); - collations.Add(313, "utf8mb4_nn_0900_as_cs"); - collations.Add(314, "utf8mb4_sr_latn_0900_ai_ci"); - collations.Add(315, "utf8mb4_sr_latn_0900_as_cs"); - collations.Add(316, "utf8mb4_bs_0900_ai_ci"); - collations.Add(317, "utf8mb4_bs_0900_as_cs"); - collations.Add(318, "utf8mb4_bg_0900_ai_ci"); - collations.Add(319, "utf8mb4_bg_0900_as_cs"); - collations.Add(320, "utf8mb4_gl_0900_ai_ci"); - collations.Add(321, "utf8mb4_gl_0900_as_cs"); - collations.Add(322, "utf8mb4_mn_cyrl_0900_ai_ci"); - collations.Add(323, "utf8mb4_mn_cyrl_0900_as_cs"); - } - } -} +// Copyright © 2016, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySql.Data; +using System; +using System.Collections.Generic; + +namespace MySqlX.Data +{ + internal class CollationMap + { + private static Dictionary collations = new Dictionary(); + + static CollationMap() + { + Load(); + } + + public static string GetCollationName(int collation) + { + if (!collations.ContainsKey(collation)) + throw new KeyNotFoundException(String.Format(ResourcesX.InvalidCollationId, collation)); + return collations[collation]; + } + + private static void Load() + { + collations.Add(0, "utf8mb3_general_ci"); + collations.Add(1, "big5_chinese_ci"); + collations.Add(2, "latin2_czech_cs"); + collations.Add(3, "dec8_swedish_ci"); + collations.Add(4, "cp850_general_ci"); + collations.Add(5, "latin1_german1_ci"); + collations.Add(6, "hp8_english_ci"); + collations.Add(7, "koi8r_general_ci"); + collations.Add(8, "latin1_swedish_ci"); + collations.Add(9, "latin2_general_ci"); + collations.Add(10, "swe7_swedish_ci"); + collations.Add(11, "ascii_general_ci"); + collations.Add(12, "ujis_japanese_ci"); + collations.Add(13, "sjis_japanese_ci"); + collations.Add(14, "cp1251_bulgarian_ci"); + collations.Add(15, "latin1_danish_ci"); + collations.Add(16, "hebrew_general_ci"); + collations.Add(18, "tis620_thai_ci"); + collations.Add(19, "euckr_korean_ci"); + collations.Add(20, "latin7_estonian_cs"); + collations.Add(21, "latin2_hungarian_ci"); + collations.Add(22, "koi8u_general_ci"); + collations.Add(23, "cp1251_ukrainian_ci"); + collations.Add(24, "gb2312_chinese_ci"); + collations.Add(25, "greek_general_ci"); + collations.Add(26, "cp1250_general_ci"); + collations.Add(27, "latin2_croatian_ci"); + collations.Add(28, "gbk_chinese_ci"); + collations.Add(29, "cp1257_lithuanian_ci"); + collations.Add(30, "latin5_turkish_ci"); + collations.Add(31, "latin1_german2_ci"); + collations.Add(32, "armscii8_general_ci"); + collations.Add(33, "utf8mb3_general_ci"); + collations.Add(34, "cp1250_czech_cs"); + collations.Add(35, "ucs2_general_ci"); + collations.Add(36, "cp866_general_ci"); + collations.Add(37, "keybcs2_general_ci"); + collations.Add(38, "macce_general_ci"); + collations.Add(39, "macroman_general_ci"); + collations.Add(40, "cp852_general_ci"); + collations.Add(41, "latin7_general_ci"); + collations.Add(42, "latin7_general_cs"); + collations.Add(43, "macce_bin"); + collations.Add(44, "cp1250_croatian_ci"); + collations.Add(45, "utf8mb4_general_ci"); + collations.Add(46, "utf8mb4_bin"); + collations.Add(47, "latin1_bin"); + collations.Add(48, "latin1_general_ci"); + collations.Add(49, "latin1_general_cs"); + collations.Add(50, "cp1251_bin"); + collations.Add(51, "cp1251_general_ci"); + collations.Add(52, "cp1251_general_cs"); + collations.Add(53, "macroman_bin"); + collations.Add(54, "utf16_general_ci"); + collations.Add(55, "utf16_bin"); + collations.Add(56, "utf16le_general_ci"); + collations.Add(57, "cp1256_general_ci"); + collations.Add(58, "cp1257_bin"); + collations.Add(59, "cp1257_general_ci"); + collations.Add(60, "utf32_general_ci"); + collations.Add(61, "utf32_bin"); + collations.Add(62, "utf16le_bin"); + collations.Add(63, "binary"); + collations.Add(64, "armscii8_bin"); + collations.Add(65, "ascii_bin"); + collations.Add(66, "cp1250_bin"); + collations.Add(67, "cp1256_bin"); + collations.Add(68, "cp866_bin"); + collations.Add(69, "dec8_bin"); + collations.Add(70, "greek_bin"); + collations.Add(71, "hebrew_bin"); + collations.Add(72, "hp8_bin"); + collations.Add(73, "keybcs2_bin"); + collations.Add(74, "koi8r_bin"); + collations.Add(75, "koi8u_bin"); + collations.Add(76, "utf8mb3_tolower_ci"); + collations.Add(77, "latin2_bin"); + collations.Add(78, "latin5_bin"); + collations.Add(79, "latin7_bin"); + collations.Add(80, "cp850_bin"); + collations.Add(81, "cp852_bin"); + collations.Add(82, "swe7_bin"); + collations.Add(83, "utf8mb3_bin"); + collations.Add(84, "big5_bin"); + collations.Add(85, "euckr_bin"); + collations.Add(86, "gb2312_bin"); + collations.Add(87, "gbk_bin"); + collations.Add(88, "sjis_bin"); + collations.Add(89, "tis620_bin"); + collations.Add(90, "ucs2_bin"); + collations.Add(91, "ujis_bin"); + collations.Add(92, "geostd8_general_ci"); + collations.Add(93, "geostd8_bin"); + collations.Add(94, "latin1_spanish_ci"); + collations.Add(95, "cp932_japanese_ci"); + collations.Add(96, "cp932_bin"); + collations.Add(97, "eucjpms_japanese_ci"); + collations.Add(98, "eucjpms_bin"); + collations.Add(99, "cp1250_polish_ci"); + collations.Add(101, "utf16_unicode_ci"); + collations.Add(102, "utf16_icelandic_ci"); + collations.Add(103, "utf16_latvian_ci"); + collations.Add(104, "utf16_romanian_ci"); + collations.Add(105, "utf16_slovenian_ci"); + collations.Add(106, "utf16_polish_ci"); + collations.Add(107, "utf16_estonian_ci"); + collations.Add(108, "utf16_spanish_ci"); + collations.Add(109, "utf16_swedish_ci"); + collations.Add(110, "utf16_turkish_ci"); + collations.Add(111, "utf16_czech_ci"); + collations.Add(112, "utf16_danish_ci"); + collations.Add(113, "utf16_lithuanian_ci"); + collations.Add(114, "utf16_slovak_ci"); + collations.Add(115, "utf16_spanish2_ci"); + collations.Add(116, "utf16_roman_ci"); + collations.Add(117, "utf16_persian_ci"); + collations.Add(118, "utf16_esperanto_ci"); + collations.Add(119, "utf16_hungarian_ci"); + collations.Add(120, "utf16_sinhala_ci"); + collations.Add(121, "utf16_german2_ci"); + collations.Add(122, "utf16_croatian_ci"); + collations.Add(123, "utf16_unicode_520_ci"); + collations.Add(124, "utf16_vietnamese_ci"); + collations.Add(128, "ucs2_unicode_ci"); + collations.Add(129, "ucs2_icelandic_ci"); + collations.Add(130, "ucs2_latvian_ci"); + collations.Add(131, "ucs2_romanian_ci"); + collations.Add(132, "ucs2_slovenian_ci"); + collations.Add(133, "ucs2_polish_ci"); + collations.Add(134, "ucs2_estonian_ci"); + collations.Add(135, "ucs2_spanish_ci"); + collations.Add(136, "ucs2_swedish_ci"); + collations.Add(137, "ucs2_turkish_ci"); + collations.Add(138, "ucs2_czech_ci"); + collations.Add(139, "ucs2_danish_ci"); + collations.Add(140, "ucs2_lithuanian_ci"); + collations.Add(141, "ucs2_slovak_ci"); + collations.Add(142, "ucs2_spanish2_ci"); + collations.Add(143, "ucs2_roman_ci"); + collations.Add(144, "ucs2_persian_ci"); + collations.Add(145, "ucs2_esperanto_ci"); + collations.Add(146, "ucs2_hungarian_ci"); + collations.Add(147, "ucs2_sinhala_ci"); + collations.Add(148, "ucs2_german2_ci"); + collations.Add(149, "ucs2_croatian_ci"); + collations.Add(150, "ucs2_unicode_520_ci"); + collations.Add(151, "ucs2_vietnamese_ci"); + collations.Add(159, "ucs2_general_mysql500_ci"); + collations.Add(160, "utf32_unicode_ci"); + collations.Add(161, "utf32_icelandic_ci"); + collations.Add(162, "utf32_latvian_ci"); + collations.Add(163, "utf32_romanian_ci"); + collations.Add(164, "utf32_slovenian_ci"); + collations.Add(165, "utf32_polish_ci"); + collations.Add(166, "utf32_estonian_ci"); + collations.Add(167, "utf32_spanish_ci"); + collations.Add(168, "utf32_swedish_ci"); + collations.Add(169, "utf32_turkish_ci"); + collations.Add(170, "utf32_czech_ci"); + collations.Add(171, "utf32_danish_ci"); + collations.Add(172, "utf32_lithuanian_ci"); + collations.Add(173, "utf32_slovak_ci"); + collations.Add(174, "utf32_spanish2_ci"); + collations.Add(175, "utf32_roman_ci"); + collations.Add(176, "utf32_persian_ci"); + collations.Add(177, "utf32_esperanto_ci"); + collations.Add(178, "utf32_hungarian_ci"); + collations.Add(179, "utf32_sinhala_ci"); + collations.Add(180, "utf32_german2_ci"); + collations.Add(181, "utf32_croatian_ci"); + collations.Add(182, "utf32_unicode_520_ci"); + collations.Add(183, "utf32_vietnamese_ci"); + collations.Add(192, "utf8mb3_unicode_ci"); + collations.Add(193, "utf8mb3_icelandic_ci"); + collations.Add(194, "utf8mb3_latvian_ci"); + collations.Add(195, "utf8mb3_romanian_ci"); + collations.Add(196, "utf8mb3_slovenian_ci"); + collations.Add(197, "utf8mb3_polish_ci"); + collations.Add(198, "utf8mb3_estonian_ci"); + collations.Add(199, "utf8mb3_spanish_ci"); + collations.Add(200, "utf8mb3_swedish_ci"); + collations.Add(201, "utf8mb3_turkish_ci"); + collations.Add(202, "utf8mb3_czech_ci"); + collations.Add(203, "utf8mb3_danish_ci"); + collations.Add(204, "utf8mb3_lithuanian_ci"); + collations.Add(205, "utf8mb3_slovak_ci"); + collations.Add(206, "utf8mb3_spanish2_ci"); + collations.Add(207, "utf8mb3_roman_ci"); + collations.Add(208, "utf8mb3_persian_ci"); + collations.Add(209, "utf8mb3_esperanto_ci"); + collations.Add(210, "utf8mb3_hungarian_ci"); + collations.Add(211, "utf8mb3_sinhala_ci"); + collations.Add(212, "utf8mb3_german2_ci"); + collations.Add(213, "utf8mb3_croatian_ci"); + collations.Add(214, "utf8mb3_unicode_520_ci"); + collations.Add(215, "utf8mb3_vietnamese_ci"); + collations.Add(223, "utf8mb3_general_mysql500_ci"); + collations.Add(224, "utf8mb4_unicode_ci"); + collations.Add(225, "utf8mb4_icelandic_ci"); + collations.Add(226, "utf8mb4_latvian_ci"); + collations.Add(227, "utf8mb4_romanian_ci"); + collations.Add(228, "utf8mb4_slovenian_ci"); + collations.Add(229, "utf8mb4_polish_ci"); + collations.Add(230, "utf8mb4_estonian_ci"); + collations.Add(231, "utf8mb4_spanish_ci"); + collations.Add(232, "utf8mb4_swedish_ci"); + collations.Add(233, "utf8mb4_turkish_ci"); + collations.Add(234, "utf8mb4_czech_ci"); + collations.Add(235, "utf8mb4_danish_ci"); + collations.Add(236, "utf8mb4_lithuanian_ci"); + collations.Add(237, "utf8mb4_slovak_ci"); + collations.Add(238, "utf8mb4_spanish2_ci"); + collations.Add(239, "utf8mb4_roman_ci"); + collations.Add(240, "utf8mb4_persian_ci"); + collations.Add(241, "utf8mb4_esperanto_ci"); + collations.Add(242, "utf8mb4_hungarian_ci"); + collations.Add(243, "utf8mb4_sinhala_ci"); + collations.Add(244, "utf8mb4_german2_ci"); + collations.Add(245, "utf8mb4_croatian_ci"); + collations.Add(246, "utf8mb4_unicode_520_ci"); + collations.Add(247, "utf8mb4_vietnamese_ci"); + collations.Add(248, "gb18030_chinese_ci"); + collations.Add(249, "gb18030_bin"); + collations.Add(250, "gb18030_unicode_520_ci"); + collations.Add(255, "utf8mb4_0900_ai_ci"); + collations.Add(256, "utf8mb4_de_pb_0900_ai_ci"); + collations.Add(257, "utf8mb4_is_0900_ai_ci"); + collations.Add(258, "utf8mb4_lv_0900_ai_ci"); + collations.Add(259, "utf8mb4_ro_0900_ai_ci"); + collations.Add(260, "utf8mb4_sl_0900_ai_ci"); + collations.Add(261, "utf8mb4_pl_0900_ai_ci"); + collations.Add(262, "utf8mb4_et_0900_ai_ci"); + collations.Add(263, "utf8mb4_es_0900_ai_ci"); + collations.Add(264, "utf8mb4_sv_0900_ai_ci"); + collations.Add(265, "utf8mb4_tr_0900_ai_ci"); + collations.Add(266, "utf8mb4_cs_0900_ai_ci"); + collations.Add(267, "utf8mb4_da_0900_ai_ci"); + collations.Add(268, "utf8mb4_lt_0900_ai_ci"); + collations.Add(269, "utf8mb4_sk_0900_ai_ci"); + collations.Add(270, "utf8mb4_es_trad_0900_ai_ci"); + collations.Add(271, "utf8mb4_la_0900_ai_ci"); + collations.Add(273, "utf8mb4_eo_0900_ai_ci"); + collations.Add(274, "utf8mb4_hu_0900_ai_ci"); + collations.Add(275, "utf8mb4_hr_0900_ai_ci"); + collations.Add(277, "utf8mb4_vi_0900_ai_ci"); + collations.Add(278, "utf8mb4_0900_as_cs"); + collations.Add(279, "utf8mb4_de_pb_0900_as_cs"); + collations.Add(280, "utf8mb4_is_0900_as_cs"); + collations.Add(281, "utf8mb4_lv_0900_as_cs"); + collations.Add(282, "utf8mb4_ro_0900_as_cs"); + collations.Add(283, "utf8mb4_sl_0900_as_cs"); + collations.Add(284, "utf8mb4_pl_0900_as_cs"); + collations.Add(285, "utf8mb4_et_0900_as_cs"); + collations.Add(286, "utf8mb4_es_0900_as_cs"); + collations.Add(287, "utf8mb4_sv_0900_as_cs"); + collations.Add(288, "utf8mb4_tr_0900_as_cs"); + collations.Add(289, "utf8mb4_cs_0900_as_cs"); + collations.Add(290, "utf8mb4_da_0900_as_cs"); + collations.Add(291, "utf8mb4_lt_0900_as_cs"); + collations.Add(292, "utf8mb4_sk_0900_as_cs"); + collations.Add(293, "utf8mb4_es_trad_0900_as_cs"); + collations.Add(294, "utf8mb4_la_0900_as_cs"); + collations.Add(296, "utf8mb4_eo_0900_as_cs"); + collations.Add(297, "utf8mb4_hu_0900_as_cs"); + collations.Add(298, "utf8mb4_hr_0900_as_cs"); + collations.Add(300, "utf8mb4_vi_0900_as_cs"); + collations.Add(303, "utf8mb4_ja_0900_as_cs"); + collations.Add(304, "utf8mb4_ja_0900_as_cs_ks"); + collations.Add(305, "utf8mb4_0900_as_ci"); + collations.Add(306, "utf8mb4_ru_0900_ai_ci"); + collations.Add(307, "utf8mb4_ru_0900_as_cs"); + collations.Add(308, "utf8mb4_zh_0900_as_cs"); + collations.Add(309, "utf8mb4_0900_bin"); + collations.Add(310, "utf8mb4_nb_0900_ai_ci"); + collations.Add(311, "utf8mb4_nb_0900_as_cs"); + collations.Add(312, "utf8mb4_nn_0900_ai_ci"); + collations.Add(313, "utf8mb4_nn_0900_as_cs"); + collations.Add(314, "utf8mb4_sr_latn_0900_ai_ci"); + collations.Add(315, "utf8mb4_sr_latn_0900_as_cs"); + collations.Add(316, "utf8mb4_bs_0900_ai_ci"); + collations.Add(317, "utf8mb4_bs_0900_as_cs"); + collations.Add(318, "utf8mb4_bg_0900_ai_ci"); + collations.Add(319, "utf8mb4_bg_0900_as_cs"); + collations.Add(320, "utf8mb4_gl_0900_ai_ci"); + collations.Add(321, "utf8mb4_gl_0900_as_cs"); + collations.Add(322, "utf8mb4_mn_cyrl_0900_ai_ci"); + collations.Add(323, "utf8mb4_mn_cyrl_0900_as_cs"); + } + } +} diff --git a/MySQL.Data/src/X/Data/Enums.cs b/MySQL.Data/src/X/Data/Enums.cs index 3cc4a1727..2cb0f2f56 100644 --- a/MySQL.Data/src/X/Data/Enums.cs +++ b/MySQL.Data/src/X/Data/Enums.cs @@ -1,16 +1,16 @@ -// Copyright © 2015, 2018, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2015, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/X/Protocol/ProtocolBase.cs b/MySQL.Data/src/X/Protocol/ProtocolBase.cs index c06aaef83..cf96b6a9b 100644 --- a/MySQL.Data/src/X/Protocol/ProtocolBase.cs +++ b/MySQL.Data/src/X/Protocol/ProtocolBase.cs @@ -1,53 +1,53 @@ -// Copyright © 2015, 2016, Oracle and/or its affiliates. All rights reserved. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - - -using System.Collections.Generic; -using MySqlX.XDevAPI; -using MySqlX.XDevAPI.Common; -using MySqlX.XDevAPI.Relational; - -namespace MySqlX.Protocol -{ - - /// - /// Abstract class for the protocol base operations in client/server communication. - /// - /// - public abstract class ProtocolBase - { - public abstract List ReadRow(BaseResult rs); - public abstract void SendSQL(string sql, params object[] args); - - public abstract bool HasData(BaseResult rs); - - public abstract List LoadColumnMetadata(); - - public abstract void CloseResult(BaseResult rs); - } -} +// Copyright © 2015, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + +using System.Collections.Generic; +using MySqlX.XDevAPI; +using MySqlX.XDevAPI.Common; +using MySqlX.XDevAPI.Relational; + +namespace MySqlX.Protocol +{ + + /// + /// Abstract class for the protocol base operations in client/server communication. + /// + /// + public abstract class ProtocolBase + { + public abstract List ReadRow(BaseResult rs); + public abstract void SendSQL(string sql, params object[] args); + + public abstract bool HasData(BaseResult rs); + + public abstract List LoadColumnMetadata(); + + public abstract void CloseResult(BaseResult rs); + } +} diff --git a/MySQL.Data/src/X/Protocol/ValueDecoder.cs b/MySQL.Data/src/X/Protocol/ValueDecoder.cs index 1dc1a07aa..aff72fb26 100644 --- a/MySQL.Data/src/X/Protocol/ValueDecoder.cs +++ b/MySQL.Data/src/X/Protocol/ValueDecoder.cs @@ -1,48 +1,48 @@ -// Copyright © 2015, 2016, Oracle and/or its affiliates. All rights reserved. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySqlX.XDevAPI; -using MySqlX.XDevAPI.Relational; - -namespace MySqlX.Protocol -{ - internal abstract class ValueDecoder - { - - public delegate object ClrDecoderDelegate(byte[] bytes); - - - public Column Column { get; set; } - - public uint Flags { get; set; } - public uint ContentType { get; set; } - - public abstract void SetMetadata(); - public ClrDecoderDelegate ClrValueDecoder; - } -} +// Copyright © 2015, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySqlX.XDevAPI; +using MySqlX.XDevAPI.Relational; + +namespace MySqlX.Protocol +{ + internal abstract class ValueDecoder + { + + public delegate object ClrDecoderDelegate(byte[] bytes); + + + public Column Column { get; set; } + + public uint Flags { get; set; } + public uint ContentType { get; set; } + + public abstract void SetMetadata(); + public ClrDecoderDelegate ClrValueDecoder; + } +} diff --git a/MySQL.Data/src/X/Protocol/X/BitDecoder.cs b/MySQL.Data/src/X/Protocol/X/BitDecoder.cs index 0651f99d4..55796cb1f 100644 --- a/MySQL.Data/src/X/Protocol/X/BitDecoder.cs +++ b/MySQL.Data/src/X/Protocol/X/BitDecoder.cs @@ -1,16 +1,16 @@ -// Copyright © 2016, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2016, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -52,4 +52,4 @@ private object BitValueDecoder(byte[] bytes) return ReadUInt(bytes); } } -} \ No newline at end of file +} diff --git a/MySQL.Data/src/X/Protocol/X/ByteDecoder.cs b/MySQL.Data/src/X/Protocol/X/ByteDecoder.cs index af93900d1..c85f49668 100644 --- a/MySQL.Data/src/X/Protocol/X/ByteDecoder.cs +++ b/MySQL.Data/src/X/Protocol/X/ByteDecoder.cs @@ -1,100 +1,100 @@ -// Copyright (c) 2015, 2022, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySql.Data.MySqlClient; -using MySql.Data.MySqlClient.X.XDevAPI.Common; -using System; -using System.Text; - -namespace MySqlX.Protocol.X -{ - internal class ByteDecoder : ValueDecoder - { - private Encoding _encoding; - private bool _isEnum; - - public ByteDecoder(bool isEnum) - { - _isEnum = isEnum; - } - - public override void SetMetadata() - { - Column.Type = GetDbType(); - Column.ClrType = GetClrType(Column.Type); - Column.IsPadded = (Flags & 1) != 0; - ClrValueDecoder = GetClrValueDecoder(); - } - - private ColumnType GetDbType() - { - if (_isEnum) - return ColumnType.Enum; - if (ContentType == (uint)ColumnContentType.Geometry) - return ColumnType.Geometry; - if (ContentType == (uint)ColumnContentType.Json) - return ColumnType.Json; - if ((Column.CollationName ?? "").Equals("binary", StringComparison.OrdinalIgnoreCase)) - return ColumnType.Bytes; - return ColumnType.String; - } - - private Type GetClrType(ColumnType dbType) - { - if (dbType == ColumnType.String || dbType == ColumnType.Json - || dbType == ColumnType.Enum) - return typeof(string); - return typeof(byte[]); - } - - private ClrDecoderDelegate GetClrValueDecoder() - { - if (Column.ClrType == typeof(String)) return StringValueDecoder; - return ByteValueDecoder; - } - - private object StringValueDecoder(byte[] bytes) - { - if (bytes.Length == 0) return null; - - if (_encoding == null) - { - string charset = Column.CharacterSetName ?? string.Empty; - _encoding = CharSetMap.GetEncoding(charset); - } - return _encoding.GetString(bytes, 0, bytes.Length - 1); - } - - private object ByteValueDecoder(byte[] bytes) - { - byte[] newValue = new byte[bytes.Length - 1]; - Array.Copy(bytes, newValue, newValue.Length); - return newValue; - } - } -} +// Copyright © 2015, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySql.Data.MySqlClient; +using MySql.Data.MySqlClient.X.XDevAPI.Common; +using System; +using System.Text; + +namespace MySqlX.Protocol.X +{ + internal class ByteDecoder : ValueDecoder + { + private Encoding _encoding; + private bool _isEnum; + + public ByteDecoder(bool isEnum) + { + _isEnum = isEnum; + } + + public override void SetMetadata() + { + Column.Type = GetDbType(); + Column.ClrType = GetClrType(Column.Type); + Column.IsPadded = (Flags & 1) != 0; + ClrValueDecoder = GetClrValueDecoder(); + } + + private ColumnType GetDbType() + { + if (_isEnum) + return ColumnType.Enum; + if (ContentType == (uint)ColumnContentType.Geometry) + return ColumnType.Geometry; + if (ContentType == (uint)ColumnContentType.Json) + return ColumnType.Json; + if ((Column.CollationName ?? "").Equals("binary", StringComparison.OrdinalIgnoreCase)) + return ColumnType.Bytes; + return ColumnType.String; + } + + private Type GetClrType(ColumnType dbType) + { + if (dbType == ColumnType.String || dbType == ColumnType.Json + || dbType == ColumnType.Enum) + return typeof(string); + return typeof(byte[]); + } + + private ClrDecoderDelegate GetClrValueDecoder() + { + if (Column.ClrType == typeof(String)) return StringValueDecoder; + return ByteValueDecoder; + } + + private object StringValueDecoder(byte[] bytes) + { + if (bytes.Length == 0) return null; + + if (_encoding == null) + { + string charset = Column.CharacterSetName ?? string.Empty; + _encoding = CharSetMap.GetEncoding(charset); + } + return _encoding.GetString(bytes, 0, bytes.Length - 1); + } + + private object ByteValueDecoder(byte[] bytes) + { + byte[] newValue = new byte[bytes.Length - 1]; + Array.Copy(bytes, newValue, newValue.Length); + return newValue; + } + } +} diff --git a/MySQL.Data/src/X/Protocol/X/DecimalDecoder.cs b/MySQL.Data/src/X/Protocol/X/DecimalDecoder.cs index 850cdb6f2..a064eb2e1 100644 --- a/MySQL.Data/src/X/Protocol/X/DecimalDecoder.cs +++ b/MySQL.Data/src/X/Protocol/X/DecimalDecoder.cs @@ -1,35 +1,35 @@ -// Copyright © 2016, Oracle and/or its affiliates. All rights reserved. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - +// Copyright © 2016, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + using MySql.Data; using MySql.Data.MySqlClient.X.XDevAPI.Common; -using MySqlX.Data; +using MySqlX.Data; using System; namespace MySqlX.Protocol.X @@ -78,4 +78,4 @@ private object DecimalValueDecoder(byte[] bytes) return Decimal.Parse(stringValue); } } -} \ No newline at end of file +} diff --git a/MySQL.Data/src/X/Protocol/X/Enum.cs b/MySQL.Data/src/X/Protocol/X/Enum.cs index 94a88b741..1cffe1f21 100644 --- a/MySQL.Data/src/X/Protocol/X/Enum.cs +++ b/MySQL.Data/src/X/Protocol/X/Enum.cs @@ -1,68 +1,68 @@ -// Copyright © 2015, 2019, Oracle and/or its affiliates. All rights reserved. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace MySqlX.Protocol.X -{ - internal enum NoticeType : int - { - Warning = 1, - SessionVariableChanged = 2, - SessionStateChanged = 3, - } - - internal enum RowLock : int - { - SharedLock = 1, - ExclusiveLock = 2 - } - - internal static class XpluginStatementCommand - { - public static readonly string XPLUGIN_STMT_CREATE_COLLECTION = "create_collection"; - public static readonly string XPLUGIN_STMT_CREATE_COLLECTION_INDEX = "create_collection_index"; - public static readonly string XPLUGIN_STMT_DROP_COLLECTION = - "drop_collection"; - //Added to support schema validation, store the name of the command used by MySQL Server to modify collections - public static readonly string XPLUGIN_STMT_MODIFY_COLLECTION = "modify_collection_options"; - - public static readonly string XPLUGIN_STMT_DROP_COLLECTION_INDEX = "drop_collection_index"; - public static readonly string XPLUGIN_STMT_PING = "ping"; - public static readonly string XPLUGIN_STMT_LIST_OBJECTS = - "list_objects"; - public static readonly string XPLUGIN_STMT_ENABLE_NOTICES = "enable_notices"; - public static readonly string XPLUGIN_STMT_DISABLE_NOTICES = "disable_notices"; - public static readonly string XPLUGIN_STMT_LIST_NOTICES = - "list_notices"; - } -} +// Copyright © 2015, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace MySqlX.Protocol.X +{ + internal enum NoticeType : int + { + Warning = 1, + SessionVariableChanged = 2, + SessionStateChanged = 3, + } + + internal enum RowLock : int + { + SharedLock = 1, + ExclusiveLock = 2 + } + + internal static class XpluginStatementCommand + { + public static readonly string XPLUGIN_STMT_CREATE_COLLECTION = "create_collection"; + public static readonly string XPLUGIN_STMT_CREATE_COLLECTION_INDEX = "create_collection_index"; + public static readonly string XPLUGIN_STMT_DROP_COLLECTION = + "drop_collection"; + //Added to support schema validation, store the name of the command used by MySQL Server to modify collections + public static readonly string XPLUGIN_STMT_MODIFY_COLLECTION = "modify_collection_options"; + + public static readonly string XPLUGIN_STMT_DROP_COLLECTION_INDEX = "drop_collection_index"; + public static readonly string XPLUGIN_STMT_PING = "ping"; + public static readonly string XPLUGIN_STMT_LIST_OBJECTS = + "list_objects"; + public static readonly string XPLUGIN_STMT_ENABLE_NOTICES = "enable_notices"; + public static readonly string XPLUGIN_STMT_DISABLE_NOTICES = "disable_notices"; + public static readonly string XPLUGIN_STMT_LIST_NOTICES = + "list_notices"; + } +} diff --git a/MySQL.Data/src/X/Protocol/X/ExpUnparser.cs b/MySQL.Data/src/X/Protocol/X/ExpUnparser.cs index 9432aea03..cbcad148e 100644 --- a/MySQL.Data/src/X/Protocol/X/ExpUnparser.cs +++ b/MySQL.Data/src/X/Protocol/X/ExpUnparser.cs @@ -1,16 +1,16 @@ -// Copyright © 2015, 2016, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2015, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/X/Protocol/X/ExprParser.cs b/MySQL.Data/src/X/Protocol/X/ExprParser.cs index e77fc8f3c..fa4aab5ec 100644 --- a/MySQL.Data/src/X/Protocol/X/ExprParser.cs +++ b/MySQL.Data/src/X/Protocol/X/ExprParser.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2015, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/X/Protocol/X/ExprUtil.cs b/MySQL.Data/src/X/Protocol/X/ExprUtil.cs index 0c25a358e..101e1704c 100644 --- a/MySQL.Data/src/X/Protocol/X/ExprUtil.cs +++ b/MySQL.Data/src/X/Protocol/X/ExprUtil.cs @@ -1,270 +1,270 @@ -// Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using System; -using Mysqlx.Expr; -using Mysqlx.Datatypes; -using Mysqlx.Crud; -using Google.Protobuf; -using System.Collections.Generic; -using System.Reflection; - -namespace MySqlX.Protocol.X -{ - internal class ExprUtil - { - /** - * Proto-buf helper to build a LITERAL Expr with a Scalar NULL type. - */ - public static Expr BuildLiteralNullScalar() - { - return BuildLiteralExpr(NullScalar()); - } - - /** - * Proto-buf helper to build a LITERAL Expr with a Scalar DOUBLE type (wrapped in Any). - */ - public static Expr BuildLiteralScalar(double d) - { - return BuildLiteralExpr(ScalarOf(d)); - } - - /** - * Proto-buf helper to build a LITERAL Expr with a Scalar SINT (signed int) type (wrapped in Any). - */ - public static Expr BuildLiteralScalar(long l) - { - return BuildLiteralExpr(ScalarOf(l)); - } - - /** - * Proto-buf helper to build a LITERAL Expr with a Scalar UINT (unsigned int) type (wrapped in Any). - */ - public static Expr BuildLiteralScalar(ulong l) - { - return BuildLiteralExpr(ScalarOf(l)); - } - - /** - * Proto-buf helper to build a LITERAL Expr with a Scalar STRING type (wrapped in Any). - */ - public static Expr BuildLiteralScalar(String str) - { - return BuildLiteralExpr(ScalarOf(str)); - } - - /** - * Proto-buf helper to build a LITERAL Expr with a Scalar OCTETS type (wrapped in Any). - */ - public static Expr BuildLiteralScalar(byte[] bytes) - { - return BuildLiteralExpr(ScalarOf(bytes)); - } - - /** - * Proto-buf helper to build a LITERAL Expr with a Scalar BOOL type (wrapped in Any). - */ - public static Expr BuildLiteralScalar(Boolean b) - { - return BuildLiteralExpr(ScalarOf(b)); - } - - /** - * Wrap an Any value in a LITERAL expression. - */ - public static Expr BuildLiteralExpr(Scalar scalar) - { - return new Expr() { Type = Expr.Types.Type.Literal, Literal = scalar }; - } - - public static Scalar NullScalar() - { - return new Scalar() { Type = Scalar.Types.Type.VNull }; - } - - public static Scalar ScalarOf(double d) - { - return new Scalar() { Type = Scalar.Types.Type.VDouble, VDouble = d }; - } - - public static Scalar ScalarOf(long l) - { - return new Scalar() { Type = Scalar.Types.Type.VSint, VSignedInt = l}; - } - - public static Scalar ScalarOf(ulong ul) - { - return new Scalar() { Type = Scalar.Types.Type.VUint, VUnsignedInt = ul}; - } - - public static Scalar ScalarOf(String str) - { - Scalar.Types.String strValue = new Scalar.Types.String() { Value = ByteString.CopyFromUtf8(str) }; - return new Scalar() { Type = Scalar.Types.Type.VString, VString = strValue }; - } - - public static Scalar ScalarOf(byte[] bytes) - { - return new Scalar() { Type = Scalar.Types.Type.VOctets, VOctets = new Scalar.Types.Octets() { Value = ByteString.CopyFrom(bytes) } }; - } - - public static Scalar ScalarOf(Boolean b) - { - return new Scalar() { Type = Scalar.Types.Type.VBool, VBool = b }; - } - - /** - * Build an Any with a string value. - */ - public static Any BuildAny(String str) - { - // same as Expr - Scalar.Types.String sstr = new Scalar.Types.String(); - sstr.Value = ByteString.CopyFromUtf8(str); - Scalar s = new Scalar(); - s.Type = Scalar.Types.Type.VString; - s.VString = sstr; - Any a = new Any(); - a.Type = Any.Types.Type.Scalar; - a.Scalar = s; - return a; - } - - public static Mysqlx.Datatypes.Object.Types.ObjectField BuildObject(string key, object value, bool evaluateStringExpression) - { - Mysqlx.Datatypes.Object.Types.ObjectField item = new Mysqlx.Datatypes.Object.Types.ObjectField(); - item.Key = key; - item.Value = evaluateStringExpression ? BuildAny(value) : BuildAnyWithoutEvaluationExpression(value); - return item; - } - - public static Any BuildEmptyAny(Any.Types.Type type) - { - return new Any() { Type = type, Obj = new Mysqlx.Datatypes.Object() }; - } - - public static Any BuildAny(Boolean b) - { - return new Any() { Type = Any.Types.Type.Scalar, Scalar = ScalarOf(b) }; - } - - public static Any BuildAny(object value) - { - return new Any() { Type = Any.Types.Type.Scalar, Scalar = ExprUtil.ArgObjectToScalar(value) }; - } - - public static Any BuildAnyWithoutEvaluationExpression(object value) - { - return new Any() { Type = Any.Types.Type.Scalar, Scalar = ExprUtil.ArgObjectToScalar(value, false) }; - } - - public static Collection BuildCollection(String schemaName, String collectionName) - { - return new Collection() { Schema = schemaName, Name = collectionName }; - } - - public static Scalar ArgObjectToScalar(System.Object value, Boolean evaluateStringExpression = true) - { - return ArgObjectToExpr(value, false, evaluateStringExpression).Literal; - } - - public static Expr ArgObjectToExpr(System.Object value, Boolean allowRelationalColumns, Boolean evaluateStringExpresssion = true) - { - if (value == null) - return BuildLiteralNullScalar(); - - if (value is Dictionary) - value = new XDevAPI.DbDoc(value).ToString(); - - if (value is XDevAPI.MySqlExpression) - value = (value as XDevAPI.MySqlExpression).value; - - if (value is bool) - return BuildLiteralScalar(Convert.ToBoolean(value)); - else if (value is byte || value is short || value is int || value is long) - return BuildLiteralScalar(Convert.ToInt64(value)); - else if (value is ushort || value is uint || value is ulong) - return BuildLiteralScalar(Convert.ToUInt64(value)); - else if (value is float || value is double) - return BuildLiteralScalar(Convert.ToDouble(value)); - else if (value is string) - { - try - { - // try to parse expressions - var stringValue = (string) value; - if (!evaluateStringExpresssion) return BuildLiteralScalar((string)value); - - Expr expr = new ExprParser(stringValue).Parse(); - if (expr.Identifier != null) - return BuildLiteralScalar(stringValue); - return expr; - } - catch - { - // if can't parse, returns as literal - return BuildLiteralScalar((string)value); - } - } - else if (value is XDevAPI.DbDoc) - return (BuildLiteralScalar(value.ToString())); - - throw new NotSupportedException("Value of type " + value.GetType() + " is not currently supported."); - } - - public static string JoinString(string[] values) - { - if (values == null) return string.Empty; - return string.Join(", ", values); - } - - /// - /// Parses an anonymous object into a dictionary. - /// - /// The object to parse. - /// A dictionary if the provided object is an anonymous object; otherwise, null. - public static Dictionary ParseAnonymousObject(object value) - { - if (value == null) - return null; - - Type type = value.GetType(); - if (type.Name.Contains("Anonymous")) - { - Dictionary dictionary = new Dictionary(); - PropertyInfo[] props = type.GetProperties(); - foreach (PropertyInfo prop in props) - dictionary.Add(prop.Name, prop.GetValue(value, null)); - - return dictionary; - } - - return null; - } - } -} +// Copyright © 2015, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using System; +using Mysqlx.Expr; +using Mysqlx.Datatypes; +using Mysqlx.Crud; +using Google.Protobuf; +using System.Collections.Generic; +using System.Reflection; + +namespace MySqlX.Protocol.X +{ + internal class ExprUtil + { + /** + * Proto-buf helper to build a LITERAL Expr with a Scalar NULL type. + */ + public static Expr BuildLiteralNullScalar() + { + return BuildLiteralExpr(NullScalar()); + } + + /** + * Proto-buf helper to build a LITERAL Expr with a Scalar DOUBLE type (wrapped in Any). + */ + public static Expr BuildLiteralScalar(double d) + { + return BuildLiteralExpr(ScalarOf(d)); + } + + /** + * Proto-buf helper to build a LITERAL Expr with a Scalar SINT (signed int) type (wrapped in Any). + */ + public static Expr BuildLiteralScalar(long l) + { + return BuildLiteralExpr(ScalarOf(l)); + } + + /** + * Proto-buf helper to build a LITERAL Expr with a Scalar UINT (unsigned int) type (wrapped in Any). + */ + public static Expr BuildLiteralScalar(ulong l) + { + return BuildLiteralExpr(ScalarOf(l)); + } + + /** + * Proto-buf helper to build a LITERAL Expr with a Scalar STRING type (wrapped in Any). + */ + public static Expr BuildLiteralScalar(String str) + { + return BuildLiteralExpr(ScalarOf(str)); + } + + /** + * Proto-buf helper to build a LITERAL Expr with a Scalar OCTETS type (wrapped in Any). + */ + public static Expr BuildLiteralScalar(byte[] bytes) + { + return BuildLiteralExpr(ScalarOf(bytes)); + } + + /** + * Proto-buf helper to build a LITERAL Expr with a Scalar BOOL type (wrapped in Any). + */ + public static Expr BuildLiteralScalar(Boolean b) + { + return BuildLiteralExpr(ScalarOf(b)); + } + + /** + * Wrap an Any value in a LITERAL expression. + */ + public static Expr BuildLiteralExpr(Scalar scalar) + { + return new Expr() { Type = Expr.Types.Type.Literal, Literal = scalar }; + } + + public static Scalar NullScalar() + { + return new Scalar() { Type = Scalar.Types.Type.VNull }; + } + + public static Scalar ScalarOf(double d) + { + return new Scalar() { Type = Scalar.Types.Type.VDouble, VDouble = d }; + } + + public static Scalar ScalarOf(long l) + { + return new Scalar() { Type = Scalar.Types.Type.VSint, VSignedInt = l}; + } + + public static Scalar ScalarOf(ulong ul) + { + return new Scalar() { Type = Scalar.Types.Type.VUint, VUnsignedInt = ul}; + } + + public static Scalar ScalarOf(String str) + { + Scalar.Types.String strValue = new Scalar.Types.String() { Value = ByteString.CopyFromUtf8(str) }; + return new Scalar() { Type = Scalar.Types.Type.VString, VString = strValue }; + } + + public static Scalar ScalarOf(byte[] bytes) + { + return new Scalar() { Type = Scalar.Types.Type.VOctets, VOctets = new Scalar.Types.Octets() { Value = ByteString.CopyFrom(bytes) } }; + } + + public static Scalar ScalarOf(Boolean b) + { + return new Scalar() { Type = Scalar.Types.Type.VBool, VBool = b }; + } + + /** + * Build an Any with a string value. + */ + public static Any BuildAny(String str) + { + // same as Expr + Scalar.Types.String sstr = new Scalar.Types.String(); + sstr.Value = ByteString.CopyFromUtf8(str); + Scalar s = new Scalar(); + s.Type = Scalar.Types.Type.VString; + s.VString = sstr; + Any a = new Any(); + a.Type = Any.Types.Type.Scalar; + a.Scalar = s; + return a; + } + + public static Mysqlx.Datatypes.Object.Types.ObjectField BuildObject(string key, object value, bool evaluateStringExpression) + { + Mysqlx.Datatypes.Object.Types.ObjectField item = new Mysqlx.Datatypes.Object.Types.ObjectField(); + item.Key = key; + item.Value = evaluateStringExpression ? BuildAny(value) : BuildAnyWithoutEvaluationExpression(value); + return item; + } + + public static Any BuildEmptyAny(Any.Types.Type type) + { + return new Any() { Type = type, Obj = new Mysqlx.Datatypes.Object() }; + } + + public static Any BuildAny(Boolean b) + { + return new Any() { Type = Any.Types.Type.Scalar, Scalar = ScalarOf(b) }; + } + + public static Any BuildAny(object value) + { + return new Any() { Type = Any.Types.Type.Scalar, Scalar = ExprUtil.ArgObjectToScalar(value) }; + } + + public static Any BuildAnyWithoutEvaluationExpression(object value) + { + return new Any() { Type = Any.Types.Type.Scalar, Scalar = ExprUtil.ArgObjectToScalar(value, false) }; + } + + public static Collection BuildCollection(String schemaName, String collectionName) + { + return new Collection() { Schema = schemaName, Name = collectionName }; + } + + public static Scalar ArgObjectToScalar(System.Object value, Boolean evaluateStringExpression = true) + { + return ArgObjectToExpr(value, false, evaluateStringExpression).Literal; + } + + public static Expr ArgObjectToExpr(System.Object value, Boolean allowRelationalColumns, Boolean evaluateStringExpresssion = true) + { + if (value == null) + return BuildLiteralNullScalar(); + + if (value is Dictionary) + value = new XDevAPI.DbDoc(value).ToString(); + + if (value is XDevAPI.MySqlExpression) + value = (value as XDevAPI.MySqlExpression).value; + + if (value is bool) + return BuildLiteralScalar(Convert.ToBoolean(value)); + else if (value is byte || value is short || value is int || value is long) + return BuildLiteralScalar(Convert.ToInt64(value)); + else if (value is ushort || value is uint || value is ulong) + return BuildLiteralScalar(Convert.ToUInt64(value)); + else if (value is float || value is double) + return BuildLiteralScalar(Convert.ToDouble(value)); + else if (value is string) + { + try + { + // try to parse expressions + var stringValue = (string) value; + if (!evaluateStringExpresssion) return BuildLiteralScalar((string)value); + + Expr expr = new ExprParser(stringValue).Parse(); + if (expr.Identifier != null) + return BuildLiteralScalar(stringValue); + return expr; + } + catch + { + // if can't parse, returns as literal + return BuildLiteralScalar((string)value); + } + } + else if (value is XDevAPI.DbDoc) + return (BuildLiteralScalar(value.ToString())); + + throw new NotSupportedException("Value of type " + value.GetType() + " is not currently supported."); + } + + public static string JoinString(string[] values) + { + if (values == null) return string.Empty; + return string.Join(", ", values); + } + + /// + /// Parses an anonymous object into a dictionary. + /// + /// The object to parse. + /// A dictionary if the provided object is an anonymous object; otherwise, null. + public static Dictionary ParseAnonymousObject(object value) + { + if (value == null) + return null; + + Type type = value.GetType(); + if (type.Name.Contains("Anonymous")) + { + Dictionary dictionary = new Dictionary(); + PropertyInfo[] props = type.GetProperties(); + foreach (PropertyInfo prop in props) + dictionary.Add(prop.Name, prop.GetValue(value, null)); + + return dictionary; + } + + return null; + } + } +} diff --git a/MySQL.Data/src/X/Protocol/X/FloatDecoder.cs b/MySQL.Data/src/X/Protocol/X/FloatDecoder.cs index efd155a0b..40cee7549 100644 --- a/MySQL.Data/src/X/Protocol/X/FloatDecoder.cs +++ b/MySQL.Data/src/X/Protocol/X/FloatDecoder.cs @@ -1,69 +1,69 @@ -// Copyright © 2015, 2016, Oracle and/or its affiliates. All rights reserved. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - - - -using MySqlX.Data; -using MySqlX.XDevAPI; -using System; -using MySql.Data.MySqlClient; -using MySqlX; -using MySql.Data.MySqlClient.X.XDevAPI.Common; -using Google.Protobuf; - -namespace MySqlX.Protocol.X -{ - internal class FloatDecoder : ValueDecoder - { - bool _float; - - public FloatDecoder(bool isFloat) - { - _float = isFloat; - } - - public override void SetMetadata() - { - Column.Type = _float ? ColumnType.Float : ColumnType.Double; - Column.ClrType = _float ? typeof(float) : typeof(double); - ClrValueDecoder = FloatValueDecoder; - if (!_float) - ClrValueDecoder = DoubleValueDecoder; - } - - private object FloatValueDecoder(byte[] bytes) - { - return new CodedInputStream(bytes).ReadFloat(); - } - - private object DoubleValueDecoder(byte[] bytes) - { - return new CodedInputStream(bytes).ReadDouble(); - } - } -} +// Copyright © 2015, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + + +using MySqlX.Data; +using MySqlX.XDevAPI; +using System; +using MySql.Data.MySqlClient; +using MySqlX; +using MySql.Data.MySqlClient.X.XDevAPI.Common; +using Google.Protobuf; + +namespace MySqlX.Protocol.X +{ + internal class FloatDecoder : ValueDecoder + { + bool _float; + + public FloatDecoder(bool isFloat) + { + _float = isFloat; + } + + public override void SetMetadata() + { + Column.Type = _float ? ColumnType.Float : ColumnType.Double; + Column.ClrType = _float ? typeof(float) : typeof(double); + ClrValueDecoder = FloatValueDecoder; + if (!_float) + ClrValueDecoder = DoubleValueDecoder; + } + + private object FloatValueDecoder(byte[] bytes) + { + return new CodedInputStream(bytes).ReadFloat(); + } + + private object DoubleValueDecoder(byte[] bytes) + { + return new CodedInputStream(bytes).ReadDouble(); + } + } +} diff --git a/MySQL.Data/src/X/Protocol/X/IntegerDecoder.cs b/MySQL.Data/src/X/Protocol/X/IntegerDecoder.cs index 9bb3afb88..d3a2f4d66 100644 --- a/MySQL.Data/src/X/Protocol/X/IntegerDecoder.cs +++ b/MySQL.Data/src/X/Protocol/X/IntegerDecoder.cs @@ -1,158 +1,158 @@ -// Copyright © 2015, 2016, Oracle and/or its affiliates. All rights reserved. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - - - -using Google.Protobuf; -using MySql.Data.MySqlClient; -using MySql.Data.MySqlClient.X.XDevAPI.Common; -using MySqlX.Data; -using MySqlX.XDevAPI; -using System; - -namespace MySqlX.Protocol.X -{ - internal class IntegerDecoder : ValueDecoder - { - bool _signed; - - public IntegerDecoder(bool signed) - { - _signed = signed; - } - - public override void SetMetadata() - { - Column.Type = GetDbType(); - Column.IsNumberSigned = _signed; - Column.ClrType = _signed ? GetSignedClrType() : GetUnsignedClrType(); - ClrValueDecoder = _signed ? GetSignedValueDecoder() : GetUnsignedValueDecoder(); - Column.IsPadded = _signed ? false : (Flags & 1) != 0; - } - - private ColumnType GetDbType() - { - uint len = Column.Length + (_signed ? 0u : 1u); - if (len <= 4) return ColumnType.Tinyint; - else if (len <= 6) return ColumnType.Smallint; - else if (len <= 9) return ColumnType.Mediumint; - else if (len <= 11) return ColumnType.Int; - else return ColumnType.Bigint; - } - - private Type GetSignedClrType() - { - uint len = Column.Length; - if (len <= 4) return typeof(sbyte); - else if (len <= 6) return typeof(Int16); - else if (len <= 9) return typeof(Int32); - else if (len <= 11) return typeof(Int32); - else return typeof(Int64); - } - - private Type GetUnsignedClrType() - { - uint len = Column.Length; - if (len < 4) return typeof(byte); - else if (len < 6) return typeof(UInt16); - else if (len < 9) return typeof(UInt32); - else if (len < 11) return typeof(UInt32); - else return typeof(UInt64); - } - - private ClrDecoderDelegate GetSignedValueDecoder() - { - uint len = Column.Length; - if (len <= 4) return SByteValueDecoder; - else if (len <= 6) return Int16ValueDecoder; - else if (len <= 9) return Int32ValueDecoder; - else if (len <= 11) return Int32ValueDecoder; - else return Int64ValueDecoder; - } - - private ClrDecoderDelegate GetUnsignedValueDecoder() - { - uint len = Column.Length; - if (len < 4) return ByteValueDecoder; - else if (len < 6) return UInt16ValueDecoder; - else if (len < 9) return UInt32ValueDecoder; - else if (len < 11) return UInt32ValueDecoder; - else return UInt64ValueDecoder; - } - - private Int64 ReadInt(byte[] bytes) - { - return new CodedInputStream(bytes).ReadSInt64(); - } - - private UInt64 ReadUInt(byte[] bytes) - { - return new CodedInputStream(bytes).ReadUInt64(); - } - - public object SByteValueDecoder(byte[] bytes) - { - return (sbyte)ReadInt(bytes); - } - - public object Int16ValueDecoder(byte[] bytes) - { - return (Int16)ReadInt(bytes); - } - - public object Int32ValueDecoder(byte[] bytes) - { - return (Int32)ReadInt(bytes); - } - - public object Int64ValueDecoder(byte[] bytes) - { - return ReadInt(bytes); - } - - public object ByteValueDecoder(byte[] bytes) - { - return (byte)ReadUInt(bytes); - } - - public object UInt16ValueDecoder(byte[] bytes) - { - return (UInt16)ReadUInt(bytes); - } - - public object UInt32ValueDecoder(byte[] bytes) - { - return (UInt32)ReadUInt(bytes); - } - - public object UInt64ValueDecoder(byte[] bytes) - { - return (UInt64)ReadUInt(bytes); - } - } -} +// Copyright © 2015, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + + +using Google.Protobuf; +using MySql.Data.MySqlClient; +using MySql.Data.MySqlClient.X.XDevAPI.Common; +using MySqlX.Data; +using MySqlX.XDevAPI; +using System; + +namespace MySqlX.Protocol.X +{ + internal class IntegerDecoder : ValueDecoder + { + bool _signed; + + public IntegerDecoder(bool signed) + { + _signed = signed; + } + + public override void SetMetadata() + { + Column.Type = GetDbType(); + Column.IsNumberSigned = _signed; + Column.ClrType = _signed ? GetSignedClrType() : GetUnsignedClrType(); + ClrValueDecoder = _signed ? GetSignedValueDecoder() : GetUnsignedValueDecoder(); + Column.IsPadded = _signed ? false : (Flags & 1) != 0; + } + + private ColumnType GetDbType() + { + uint len = Column.Length + (_signed ? 0u : 1u); + if (len <= 4) return ColumnType.Tinyint; + else if (len <= 6) return ColumnType.Smallint; + else if (len <= 9) return ColumnType.Mediumint; + else if (len <= 11) return ColumnType.Int; + else return ColumnType.Bigint; + } + + private Type GetSignedClrType() + { + uint len = Column.Length; + if (len <= 4) return typeof(sbyte); + else if (len <= 6) return typeof(Int16); + else if (len <= 9) return typeof(Int32); + else if (len <= 11) return typeof(Int32); + else return typeof(Int64); + } + + private Type GetUnsignedClrType() + { + uint len = Column.Length; + if (len < 4) return typeof(byte); + else if (len < 6) return typeof(UInt16); + else if (len < 9) return typeof(UInt32); + else if (len < 11) return typeof(UInt32); + else return typeof(UInt64); + } + + private ClrDecoderDelegate GetSignedValueDecoder() + { + uint len = Column.Length; + if (len <= 4) return SByteValueDecoder; + else if (len <= 6) return Int16ValueDecoder; + else if (len <= 9) return Int32ValueDecoder; + else if (len <= 11) return Int32ValueDecoder; + else return Int64ValueDecoder; + } + + private ClrDecoderDelegate GetUnsignedValueDecoder() + { + uint len = Column.Length; + if (len < 4) return ByteValueDecoder; + else if (len < 6) return UInt16ValueDecoder; + else if (len < 9) return UInt32ValueDecoder; + else if (len < 11) return UInt32ValueDecoder; + else return UInt64ValueDecoder; + } + + private Int64 ReadInt(byte[] bytes) + { + return new CodedInputStream(bytes).ReadSInt64(); + } + + private UInt64 ReadUInt(byte[] bytes) + { + return new CodedInputStream(bytes).ReadUInt64(); + } + + public object SByteValueDecoder(byte[] bytes) + { + return (sbyte)ReadInt(bytes); + } + + public object Int16ValueDecoder(byte[] bytes) + { + return (Int16)ReadInt(bytes); + } + + public object Int32ValueDecoder(byte[] bytes) + { + return (Int32)ReadInt(bytes); + } + + public object Int64ValueDecoder(byte[] bytes) + { + return ReadInt(bytes); + } + + public object ByteValueDecoder(byte[] bytes) + { + return (byte)ReadUInt(bytes); + } + + public object UInt16ValueDecoder(byte[] bytes) + { + return (UInt16)ReadUInt(bytes); + } + + public object UInt32ValueDecoder(byte[] bytes) + { + return (UInt32)ReadUInt(bytes); + } + + public object UInt64ValueDecoder(byte[] bytes) + { + return (UInt64)ReadUInt(bytes); + } + } +} diff --git a/MySQL.Data/src/X/Protocol/X/Protobuf/Mysqlx.cs b/MySQL.Data/src/X/Protocol/X/Protobuf/Mysqlx.cs index 7231626fb..2a79fe230 100644 --- a/MySQL.Data/src/X/Protocol/X/Protobuf/Mysqlx.cs +++ b/MySQL.Data/src/X/Protocol/X/Protobuf/Mysqlx.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2022, 2023, Oracle and/or its affiliates. +// Copyright © 2022, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxConnection.cs b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxConnection.cs index 697f6e772..5c62c39a0 100644 --- a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxConnection.cs +++ b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxConnection.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2022, 2023, Oracle and/or its affiliates. +// Copyright © 2022, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxCrud.cs b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxCrud.cs index e43d0163b..ba35a32d0 100644 --- a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxCrud.cs +++ b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxCrud.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2022, 2023, Oracle and/or its affiliates. +// Copyright © 2022, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxCursor.cs b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxCursor.cs index df947e05c..45c40d3ce 100644 --- a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxCursor.cs +++ b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxCursor.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2022, 2023, Oracle and/or its affiliates. +// Copyright © 2022, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxDatatypes.cs b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxDatatypes.cs index 6ffd395a8..aa77ee2e9 100644 --- a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxDatatypes.cs +++ b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxDatatypes.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2022, 2023, Oracle and/or its affiliates. +// Copyright © 2022, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxExpect.cs b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxExpect.cs index 5903d8778..0bb7e9458 100644 --- a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxExpect.cs +++ b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxExpect.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2022, 2023, Oracle and/or its affiliates. +// Copyright © 2022, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxExpr.cs b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxExpr.cs index fb1317250..1542e6819 100644 --- a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxExpr.cs +++ b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxExpr.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2022, 2023, Oracle and/or its affiliates. +// Copyright © 2022, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxNotice.cs b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxNotice.cs index fba7e1be2..b6aaf703c 100644 --- a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxNotice.cs +++ b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxNotice.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2022, 2023, Oracle and/or its affiliates. +// Copyright © 2022, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxPrepare.cs b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxPrepare.cs index e0b207234..c912575cc 100644 --- a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxPrepare.cs +++ b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxPrepare.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2022, 2023, Oracle and/or its affiliates. +// Copyright © 2022, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxResultset.cs b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxResultset.cs index 4a3e37447..602775ded 100644 --- a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxResultset.cs +++ b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxResultset.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2022, 2023, Oracle and/or its affiliates. +// Copyright © 2022, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxSession.cs b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxSession.cs index 917d53581..a049421f7 100644 --- a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxSession.cs +++ b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxSession.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2022, 2023, Oracle and/or its affiliates. +// Copyright © 2022, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/X/Protocol/X/SetDecoder.cs b/MySQL.Data/src/X/Protocol/X/SetDecoder.cs index 0dcb395a8..c0435ce74 100644 --- a/MySQL.Data/src/X/Protocol/X/SetDecoder.cs +++ b/MySQL.Data/src/X/Protocol/X/SetDecoder.cs @@ -1,74 +1,74 @@ -// Copyright (c) 2015, 2022, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySql.Data; -using MySql.Data.MySqlClient; -using MySql.Data.MySqlClient.X.XDevAPI.Common; -using System; -using System.Text; - -namespace MySqlX.Protocol.X -{ - internal class SetDecoder : ValueDecoder - { - private Encoding _encoding; - - public override void SetMetadata() - { - Column.Type = ColumnType.Set; - Column.ClrType = typeof(string); - ClrValueDecoder = DecodeValue; - - string charset = Column.CollationName.Split('_')[0]; - _encoding = CharSetMap.GetEncoding(charset); - } - - private object DecodeValue(byte[] bytes) - { - if (bytes == null || bytes.Length == 0) return null; - if (bytes.Length == 1 && bytes[0] == 0) return String.Empty; - if (bytes.Length == 1 && bytes[0] == 1) return String.Empty; - - StringBuilder sb = new StringBuilder(); - string delim = ""; - int len = bytes.Length; - int index = 0; - while (index < len - 1) - { - sb.Append(delim); - int strLen = bytes[index++]; - if ((index + strLen) > bytes.Length) - throw new MySqlException(ResourcesX.UnexpectedEndOfPacketFound); - sb.Append(_encoding.GetString(bytes, index, strLen)); - index += strLen; - delim = ","; - } - return sb.ToString(); - } - } -} +// Copyright © 2015, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySql.Data; +using MySql.Data.MySqlClient; +using MySql.Data.MySqlClient.X.XDevAPI.Common; +using System; +using System.Text; + +namespace MySqlX.Protocol.X +{ + internal class SetDecoder : ValueDecoder + { + private Encoding _encoding; + + public override void SetMetadata() + { + Column.Type = ColumnType.Set; + Column.ClrType = typeof(string); + ClrValueDecoder = DecodeValue; + + string charset = Column.CollationName.Split('_')[0]; + _encoding = CharSetMap.GetEncoding(charset); + } + + private object DecodeValue(byte[] bytes) + { + if (bytes == null || bytes.Length == 0) return null; + if (bytes.Length == 1 && bytes[0] == 0) return String.Empty; + if (bytes.Length == 1 && bytes[0] == 1) return String.Empty; + + StringBuilder sb = new StringBuilder(); + string delim = ""; + int len = bytes.Length; + int index = 0; + while (index < len - 1) + { + sb.Append(delim); + int strLen = bytes[index++]; + if ((index + strLen) > bytes.Length) + throw new MySqlException(ResourcesX.UnexpectedEndOfPacketFound); + sb.Append(_encoding.GetString(bytes, index, strLen)); + index += strLen; + delim = ","; + } + return sb.ToString(); + } + } +} diff --git a/MySQL.Data/src/X/Protocol/X/XDateTimeDecoder.cs b/MySQL.Data/src/X/Protocol/X/XDateTimeDecoder.cs index e14136758..fb8d10677 100644 --- a/MySQL.Data/src/X/Protocol/X/XDateTimeDecoder.cs +++ b/MySQL.Data/src/X/Protocol/X/XDateTimeDecoder.cs @@ -1,77 +1,77 @@ -// Copyright © 2015, 2016, Oracle and/or its affiliates. All rights reserved. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - - -using Google.Protobuf; -using MySql.Data.MySqlClient; -using MySql.Data.MySqlClient.X.XDevAPI.Common; -using MySqlX.Data; -using MySqlX.XDevAPI; -using System; - -namespace MySqlX.Protocol.X -{ - internal class XDateTimeDecoder : ValueDecoder - { - public override void SetMetadata() - { - Column.Type = GetDbType(); - Column.ClrType = typeof(DateTime); - ClrValueDecoder = ValueDecoder; - } - - private ColumnType GetDbType() - { - if ((Flags & 1) != 0) - return ColumnType.Timestamp; - if (Column.Length == 10) - return ColumnType.Date; - return ColumnType.DateTime; - } - - public object ValueDecoder(byte[] bytes) - { - CodedInputStream input = new CodedInputStream(bytes); - UInt64 year = 0, month = 0, day = 0; - Int64 hour = 0, min = 0, sec = 0, usec = 0; - - year = input.ReadUInt64(); - month = input.ReadUInt64(); - day = input.ReadUInt64(); - if (!input.IsAtEnd) - hour = input.ReadInt64(); - if (!input.IsAtEnd) - min = input.ReadInt64(); - if (!input.IsAtEnd) - sec = input.ReadInt64(); - if (!input.IsAtEnd) - usec = input.ReadInt64(); - return new DateTime((int)year, (int)month, (int)day, (int)hour, (int)min, (int)sec).AddTicks(usec * 10); - } - } -} +// Copyright © 2015, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + +using Google.Protobuf; +using MySql.Data.MySqlClient; +using MySql.Data.MySqlClient.X.XDevAPI.Common; +using MySqlX.Data; +using MySqlX.XDevAPI; +using System; + +namespace MySqlX.Protocol.X +{ + internal class XDateTimeDecoder : ValueDecoder + { + public override void SetMetadata() + { + Column.Type = GetDbType(); + Column.ClrType = typeof(DateTime); + ClrValueDecoder = ValueDecoder; + } + + private ColumnType GetDbType() + { + if ((Flags & 1) != 0) + return ColumnType.Timestamp; + if (Column.Length == 10) + return ColumnType.Date; + return ColumnType.DateTime; + } + + public object ValueDecoder(byte[] bytes) + { + CodedInputStream input = new CodedInputStream(bytes); + UInt64 year = 0, month = 0, day = 0; + Int64 hour = 0, min = 0, sec = 0, usec = 0; + + year = input.ReadUInt64(); + month = input.ReadUInt64(); + day = input.ReadUInt64(); + if (!input.IsAtEnd) + hour = input.ReadInt64(); + if (!input.IsAtEnd) + min = input.ReadInt64(); + if (!input.IsAtEnd) + sec = input.ReadInt64(); + if (!input.IsAtEnd) + usec = input.ReadInt64(); + return new DateTime((int)year, (int)month, (int)day, (int)hour, (int)min, (int)sec).AddTicks(usec * 10); + } + } +} diff --git a/MySQL.Data/src/X/Protocol/X/XProtocol.cs b/MySQL.Data/src/X/Protocol/X/XProtocol.cs index b43e68e2a..41a5f95ba 100644 --- a/MySQL.Data/src/X/Protocol/X/XProtocol.cs +++ b/MySQL.Data/src/X/Protocol/X/XProtocol.cs @@ -1,928 +1,928 @@ -// Copyright (c) 2015, 2023, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using Google.Protobuf; -using MySql.Data; -using MySql.Data.MySqlClient; -using Mysqlx; -using Mysqlx.Connection; -using Mysqlx.Crud; -using Mysqlx.Datatypes; -using Mysqlx.Expr; -using Mysqlx.Notice; -using Mysqlx.Prepare; -using Mysqlx.Resultset; -using Mysqlx.Session; -using Mysqlx.Sql; -using MySqlX.Communication; -using MySqlX.Data; -using MySqlX.DataAccess; -using MySqlX.Protocol.X; -using MySqlX.XDevAPI; -using MySqlX.XDevAPI.Common; -using MySqlX.XDevAPI.CRUD; -using System; -using System.Collections; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -#if !NETFRAMEWORK -using System.Text.Json; -#endif -using static Mysqlx.Datatypes.Object.Types; - -namespace MySqlX.Protocol -{ - internal class XProtocol : ProtocolBase - { - private CommunicationPacket _pendingPacket; - private XPacketReaderWriter _packetReaderWriter; - - public Capabilities Capabilities { get; protected set; } - - public XProtocol(XPacketReaderWriter packetReaderWriter) - { - _packetReaderWriter = packetReaderWriter; - } - - #region Authentication - - public void SendAuthStart(string method, byte[] authData, byte[] initialResponse) - { - AuthenticateStart authStart = new AuthenticateStart(); - authStart.MechName = method; - if (authData != null) authStart.AuthData = (ByteString.CopyFrom(authData)); - if (initialResponse != null) authStart.InitialResponse = (ByteString.CopyFrom(initialResponse)); - _packetReaderWriter.Write(ClientMessageId.SESS_AUTHENTICATE_START, authStart); - } - - public byte[] ReadAuthContinue() - { - CommunicationPacket p = ReadPacket(); - if (p.MessageType != (int)ServerMessageId.SESS_AUTHENTICATE_CONTINUE) - throw new MySqlException("Unexpected message encountered during authentication handshake"); - AuthenticateContinue response = AuthenticateContinue.Parser.ParseFrom(p.Buffer); - if (!response.AuthData.IsEmpty) - return response.AuthData.ToByteArray(); - return null; - } - - public void SendAuthContinue(byte[] data) - { - Debug.Assert(data != null); - AuthenticateContinue authCont = new AuthenticateContinue(); - authCont.AuthData = (ByteString.CopyFrom(data)); - _packetReaderWriter.Write(ClientMessageId.SESS_AUTHENTICATE_CONTINUE, authCont); - } - - public void ReadAuthOk() - { - CommunicationPacket p = ReadPacket(); - switch ((ServerMessageId)p.MessageType) - { - case ServerMessageId.SESS_AUTHENTICATE_OK: - break; - - case ServerMessageId.ERROR: - var error = Error.Parser.ParseFrom(p.Buffer); - throw new MySqlException(error.Code, error.SqlState, error.Msg); - - case ServerMessageId.NOTICE: - ///TODO: fix this - //ProcessNotice(p, new Result(null)); - ReadAuthOk(); - break; - - default: - throw new MySqlException("Unexpected message encountered during authentication handshake"); - } - } - - #endregion - - public void GetServerCapabilities() - { - _packetReaderWriter.Write(ClientMessageId.CON_CAPABILITIES_GET, new CapabilitiesGet()); - CommunicationPacket packet = ReadPacket(); - - if (packet.MessageType == (int)ServerMessageId.NOTICE) - packet = ReadPacket(); - - if (packet.MessageType != (int)ServerMessageId.CONN_CAPABILITIES) - { - if (packet.MessageType == (int)ServerMessageId.ERROR) - DecodeAndThrowError(packet); - else - ThrowUnexpectedMessage(packet.MessageType, (int)ServerMessageId.CONN_CAPABILITIES); - } - Capabilities = Capabilities.Parser.ParseFrom(packet.Buffer); - } - - public void SetCapabilities(Dictionary clientCapabilities) - { - if (clientCapabilities == null || clientCapabilities.Count == 0) - return; - - var builder = new CapabilitiesSet(); - var capabilities = new Capabilities(); - foreach (var cap in clientCapabilities) - { - var value = new Any(); - - if (cap.Key == "tls") - value = ExprUtil.BuildAny(cap.Value); - else if (cap.Key == "session_connect_attrs" || cap.Key == "compression") - { - var obj = new Mysqlx.Datatypes.Object(); - - if (cap.Key == "session_connect_attrs") - { - foreach (var pair in (Dictionary)cap.Value) - obj.Fld.Add(new ObjectField { Key = pair.Key, Value = ExprUtil.BuildAny(pair.Value) }); - } - else if (cap.Key == "compression") - { - foreach (var pair in (Dictionary)cap.Value) - obj.Fld.Add(new ObjectField { Key = pair.Key, Value = ExprUtil.BuildAny(pair.Value) }); - } - - value = new Any { Type = Any.Types.Type.Object, Obj = obj }; - } - - var capabilityMsg = new Capability() { Name = cap.Key, Value = value }; - capabilities.Capabilities_.Add(capabilityMsg); - } - - builder.Capabilities = capabilities; - _packetReaderWriter.Write(ClientMessageId.CON_CAPABILITIES_SET, builder); - ReadOk(); - } - - private void ThrowUnexpectedMessage(int received, int expected) - { - if (received == 10) // Connection to XProtocol using ClassicProtocol port - throw new MySqlException("Unsupported protocol version."); - throw new MySqlException( - String.Format("Expected message id: {0}. Received message id: {1}", expected, received)); - } - - public override void SendSQL(string sql, params object[] args) - { - SendExecuteSQLStatement(sql, args); - } - - public override bool HasData(BaseResult rs) - { - while (true) - { - CommunicationPacket packet = PeekPacket(); - switch (packet.MessageType) - { - case (int)ServerMessageId.RESULTSET_COLUMN_META_DATA: - return true; - case (int)ServerMessageId.NOTICE: - ProcessNotice(packet, rs); - packet = ReadPacket(); - break; - case (int)ServerMessageId.ERROR: - packet = ReadPacket(); - DecodeAndThrowError(packet); - break; - default: - return false; - } - } - } - - private CommunicationPacket PeekPacket() - { - if (_pendingPacket != null) return _pendingPacket; - _pendingPacket = _packetReaderWriter.Read(); - return _pendingPacket; - } - - private CommunicationPacket ReadPacket() - { - while (true) - { - CommunicationPacket p = _pendingPacket != null ? _pendingPacket : _packetReaderWriter.Read(); - _pendingPacket = null; - return p; - } - } - - private void ProcessGlobalNotice(Mysqlx.Notice.Frame frame) - { - } - - private void ProcessNotice(CommunicationPacket packet, BaseResult rs) - { - Frame frame = Frame.Parser.ParseFrom(packet.Buffer); - if (frame.Scope == Frame.Types.Scope.Global) - { - ProcessGlobalNotice(frame); - return; - } - - // if we get here the notice is local - switch ((NoticeType)frame.Type) - { - case NoticeType.Warning: - ProcessWarning(rs, frame.Payload.ToByteArray()); - break; - case NoticeType.SessionStateChanged: - ProcessSessionStateChanged(rs, frame.Payload.ToByteArray()); - break; - case NoticeType.SessionVariableChanged: - break; - default: // will ignore unknown notices from the server - break; - } - } - - private void ProcessSessionStateChanged(BaseResult rs, byte[] payload) - { - SessionStateChanged state = SessionStateChanged.Parser.ParseFrom(payload); - switch (state.Param) - { - case SessionStateChanged.Types.Parameter.RowsAffected: - rs._recordsAffected = state.Value[0].VUnsignedInt; - rs._affectedItemsCount = rs._recordsAffected; - break; - case SessionStateChanged.Types.Parameter.GeneratedInsertId: - rs._autoIncrementValue = state.Value[0].VUnsignedInt; - break; - case SessionStateChanged.Types.Parameter.ProducedMessage: - rs.AddWarning(new WarningInfo(0, state.Value[0].VString.Value.ToStringUtf8())); - break; - case SessionStateChanged.Types.Parameter.GeneratedDocumentIds: - foreach (var value in state.Value) - rs._documentIds.Add(value.VOctets.Value.ToStringUtf8()); - break; - //handle the other ones - //default: SessionStateChanged(state); - } - } - - private void ProcessWarning(BaseResult rs, byte[] payload) - { - Warning w = Warning.Parser.ParseFrom(payload); - WarningInfo warning = new WarningInfo(w.Code, w.Msg); - if (w.HasLevel) - warning.Level = (uint)w.Level; - rs.AddWarning(warning); - } - - private Any CreateAny(object o) - { - if (o is string) return ExprUtil.BuildAny((string)o); - if (o is bool) return ExprUtil.BuildAny((bool)o); - return ExprUtil.BuildAny(o); - } - - private ObjectField CreateObject(string key, object value, bool evaluateStringExpression = true) - { - return ExprUtil.BuildObject(key, value, evaluateStringExpression); - } - - public void SendSessionClose() - { - _packetReaderWriter.Write(ClientMessageId.SESS_CLOSE, new Mysqlx.Session.Close()); - } - - public void SendConnectionClose() - { - Mysqlx.Connection.Close connClose = new Mysqlx.Connection.Close(); - _packetReaderWriter.Write(ClientMessageId.CON_CLOSE, connClose); - } - - internal StmtExecute CreateExecuteSQLStatement(string stmt, params object[] args) - { - StmtExecute stmtExecute = new StmtExecute(); - stmtExecute.Namespace = "sql"; - stmtExecute.Stmt = ByteString.CopyFromUtf8(stmt); - stmtExecute.CompactMetadata = false; - if (args != null) - { - foreach (object arg in args) - stmtExecute.Args.Add(CreateAny(arg)); - } - - return stmtExecute; - } - - public void SendExecuteSQLStatement(string stmt, params object[] args) - { - StmtExecute stmtExecute = CreateExecuteSQLStatement(stmt, args); - _packetReaderWriter.Write(ClientMessageId.SQL_STMT_EXECUTE, stmtExecute); - } - - public void SendExecuteStatement(string ns, string stmt, params KeyValuePair[] args) - { - StmtExecute stmtExecute = new StmtExecute(); - stmtExecute.Namespace = ns; - stmtExecute.Stmt = ByteString.CopyFromUtf8(stmt); - stmtExecute.CompactMetadata = false; - if (args != null) - { - var any = ExprUtil.BuildEmptyAny(Any.Types.Type.Object); - - foreach (var arg in args) - { - switch (stmt) - { - case "drop_collection_index": - any.Obj.Fld.Add(CreateObject(arg.Key, arg.Value, false)); - break; - default: - any.Obj.Fld.Add(CreateObject(arg.Key, arg.Value)); - break; - } - } - stmtExecute.Args.Add(any); - } - - _packetReaderWriter.Write(ClientMessageId.SQL_STMT_EXECUTE, stmtExecute); - } - - /// - /// Build the message to be sent to MySQL Server to execute statement "Create" or "Modify" collection with schema options - /// - /// The namespace - /// The name of the command to be executed on MySql Server - /// Array of KeyValuePairs with the parameters required to build the message - /// void. - public void SendExecuteStatementOptions(string ns, string stmt, params KeyValuePair[] args) - { - StmtExecute stmtExecute = new StmtExecute(); - stmtExecute.Namespace = ns; - stmtExecute.Stmt = ByteString.CopyFromUtf8(stmt); - stmtExecute.CompactMetadata = false; - if (args != null) - { - var options = new ObjectField(); - var validation = new ObjectField(); - var reuse_obj = new ObjectField(); - var optionsAny = ExprUtil.BuildEmptyAny(Any.Types.Type.Object); - var any = ExprUtil.BuildEmptyAny(Any.Types.Type.Object); - var innerAny = ExprUtil.BuildEmptyAny(Any.Types.Type.Object); - var reuse_any = ExprUtil.BuildEmptyAny(Any.Types.Type.Object); - foreach (var arg in args) - { - if (arg.Value is Dictionary && arg.Key == "options") - { - foreach (var field in arg.Value as Dictionary) - { - innerAny.Obj.Fld.Add(CreateObject(field.Key, field.Value)); - } - } - else if (arg.Key == "reuse_existing") - { - reuse_any = ExprUtil.BuildAny(arg.Value); - } - else - { - any.Obj.Fld.Add(CreateObject(arg.Key, arg.Value)); - } - } - options.Key = "options"; - validation.Key = "validation"; - validation.Value = innerAny; - reuse_obj.Key = "reuse_existing"; - reuse_obj.Value = reuse_any; - optionsAny.Obj.Fld.Add(validation); - if (stmt == "create_collection") - { - optionsAny.Obj.Fld.Add(reuse_obj); - } - options.Value = optionsAny; - any.Obj.Fld.Add(options); - stmtExecute.Args.Add(any); - } - - _packetReaderWriter.Write(ClientMessageId.SQL_STMT_EXECUTE, stmtExecute); - } - - public void SendCreateCollectionIndexStatement(string ns, string stmt, params KeyValuePair[] args) - { - StmtExecute stmtExecute = new StmtExecute(); - stmtExecute.Namespace = ns; - stmtExecute.Stmt = ByteString.CopyFromUtf8(stmt); - stmtExecute.CompactMetadata = false; - if (args != null) - { - var any = ExprUtil.BuildEmptyAny(Any.Types.Type.Object); - var array = new Mysqlx.Datatypes.Array(); - foreach (var arg in args) - { - if (arg.Value is Dictionary && arg.Key == "constraint") - { - var innerAny = ExprUtil.BuildEmptyAny(Any.Types.Type.Object); - foreach (var field in arg.Value as Dictionary) - innerAny.Obj.Fld.Add(CreateObject(field.Key, field.Value, field.Key == "member" ? true : false)); - - array.Value.Add(innerAny); - } - else - any.Obj.Fld.Add(CreateObject(arg.Key, arg.Value, false)); - } - - if (array.Value.Count > 0) - { - var constraint = new ObjectField(); - constraint.Key = "constraint"; - var constraintAny = ExprUtil.BuildEmptyAny(Any.Types.Type.Array); - constraintAny.Array = array; - constraint.Value = constraintAny; - any.Obj.Fld.Add(constraint); - } - - stmtExecute.Args.Add(any); - } - - _packetReaderWriter.Write(ClientMessageId.SQL_STMT_EXECUTE, stmtExecute); - } - - private void DecodeAndThrowError(CommunicationPacket p) - { - Error e = Error.Parser.ParseFrom(p.Buffer); - throw new MySqlException(e.Code, e.SqlState, e.Msg); - } - - public override List ReadRow(BaseResult rs) - { - CommunicationPacket packet = PeekPacket(); - if (packet.MessageType != (int)ServerMessageId.RESULTSET_ROW) - { - if (rs != null) - CloseResult(rs); - - return null; - } - - var protoRow = Row.Parser.ParseFrom(ReadPacket().Buffer); - var values = new List(protoRow.Field.Count); - for (int i = 0; i < protoRow.Field.Count; i++) - values.Add(protoRow.Field[i].ToByteArray()); - - return values; - } - - public override void CloseResult(BaseResult rs) - { - rs._hasData = false; - while (true) - { - CommunicationPacket p = PeekPacket(); - if (p.MessageType == (int)ServerMessageId.RESULTSET_FETCH_DONE_MORE_RESULTSETS) - { - rs._hasMoreResults = true; - ReadPacket(); - break; - } - if (p.MessageType == (int)ServerMessageId.OK) - { - ReadOk(); - break; - } - if (p.MessageType == (int)ServerMessageId.RESULTSET_FETCH_DONE) - ReadPacket(); - else if (p.MessageType == (int)ServerMessageId.NOTICE) - ProcessNotice(ReadPacket(), rs); - else if (p.MessageType == (int)ServerMessageId.ERROR) - { - rs._session.ActiveResult = null; - DecodeAndThrowError(ReadPacket()); - } - else if (p.MessageType == (int)ServerMessageId.SQL_STMT_EXECUTE_OK) - { - ReadPacket(); - break; - } - else - throw new MySqlException(ResourcesX.ThrowingAwayResults); - } - } - - public override List LoadColumnMetadata() - { - List columns = new List(); - // we assume our caller has already validated that metadata is there - while (true) - { - if (PeekPacket().MessageType != (int)ServerMessageId.RESULTSET_COLUMN_META_DATA) return columns; - CommunicationPacket p = ReadPacket(); - ColumnMetaData response = ColumnMetaData.Parser.ParseFrom(p.Buffer); - columns.Add(DecodeColumn(response)); - } - } - - private XDevAPI.Relational.Column DecodeColumn(ColumnMetaData colData) - { - XDevAPI.Relational.Column c = new XDevAPI.Relational.Column(); - c._decoder = XValueDecoderFactory.GetValueDecoder(c, colData.Type); - c._decoder.Column = c; - - if (!colData.Name.IsEmpty) - c.ColumnLabel = colData.Name.ToStringUtf8(); - if (!colData.OriginalName.IsEmpty) - c.ColumnName = colData.OriginalName.ToStringUtf8(); - if (!colData.Table.IsEmpty) - c.TableLabel = colData.Table.ToStringUtf8(); - if (!colData.OriginalTable.IsEmpty) - c.TableName = colData.OriginalTable.ToStringUtf8(); - if (!colData.Schema.IsEmpty) - c.SchemaName = colData.Schema.ToStringUtf8(); - if (!colData.Catalog.IsEmpty) - c.DatabaseName = colData.Catalog.ToStringUtf8(); - if (colData.Collation > 0) - { - c._collationNumber = colData.Collation; - c.CollationName = CollationMap.GetCollationName((int)colData.Collation); - c.CharacterSetName = c.CollationName.Split('_')[0]; - } - if (colData.Length > 0) - c.Length = colData.Length; - if (colData.FractionalDigits > 0) - c.FractionalDigits = colData.FractionalDigits; - if (colData.Flags > 0) - c._decoder.Flags = colData.Flags; - if (colData.ContentType > 0) - c._decoder.ContentType = colData.ContentType; - c._decoder.SetMetadata(); - return c; - } - - internal Insert CreateInsertMessage(string schema, bool isRelational, string collection, object[] rows, string[] columns, bool upsert) - { - Insert msg = new Mysqlx.Crud.Insert(); - msg.Collection = ExprUtil.BuildCollection(schema, collection); - msg.DataModel = (isRelational ? DataModel.Table : DataModel.Document); - msg.Upsert = upsert; - if (columns != null && columns.Length > 0) - { - foreach (string column in columns) - msg.Projection.Add(new ExprParser(column).ParseTableInsertField()); - } - - foreach (object row in rows) - { - Mysqlx.Crud.Insert.Types.TypedRow typedRow = new Mysqlx.Crud.Insert.Types.TypedRow(); - object[] fields = row.GetType().IsArray ? (object[])row : new object[] { row }; - foreach (object field in fields) - if (field is null) - typedRow.Field.Add(ExprUtil.BuildLiteralNullScalar()); - else - { - if (field is DbDoc || field.GetType().Namespace == "System") - typedRow.Field.Add(ExprUtil.BuildLiteralScalar(Convert.ToString(field))); - else - { -#if !NETFRAMEWORK - string jsonString = JsonSerializer.Serialize(field); - typedRow.Field.Add(ExprUtil.BuildLiteralScalar(jsonString)); -#else - throw new MySqlException(ResourcesX.CustomTypeNotSupported); -#endif - } - } - - msg.Row.Add(typedRow); - } - - return msg; - } - - public void SendInsert(string schema, bool isRelational, string collection, object[] rows, string[] columns, bool upsert) - { - Insert msg = CreateInsertMessage(schema, isRelational, collection, rows, columns, upsert); - _packetReaderWriter.Write(ClientMessageId.CRUD_INSERT, msg); - } - - private void ApplyFilter(Action setLimit, Action setCriteria, Action> setOrder, FilterParams filter, Action> addParams) - { - if (filter.HasLimit) - { - var limit = new Limit(); - limit.RowCount = (ulong)filter.Limit; - if (filter.Offset != -1) limit.Offset = (ulong)filter.Offset; - setLimit(limit); - } - if (!string.IsNullOrEmpty(filter.Condition)) - { - setCriteria(filter.GetConditionExpression(filter.IsRelational)); - if (filter.Parameters != null && filter.Parameters.Count > 0) - addParams(filter.GetArgsExpression(filter.Parameters)); - } - if (filter.OrderBy != null && filter.OrderBy.Length > 0) - setOrder(filter.GetOrderByExpressions(filter.IsRelational)); - - } - - internal Delete CreateDeleteMessage(string schema, string collection, bool isRelational, FilterParams filter) - { - var msg = new Delete(); - msg.DataModel = (isRelational ? DataModel.Table : DataModel.Document); - msg.Collection = ExprUtil.BuildCollection(schema, collection); - ApplyFilter(v => msg.Limit = v, v => msg.Criteria = v, msg.Order.Add, filter, msg.Args.Add); - - return msg; - } - - /// - /// Sends the delete documents message - /// - public void SendDelete(string schema, string collection, bool isRelational, FilterParams filter) - { - var msg = CreateDeleteMessage(schema, collection, isRelational, filter); - _packetReaderWriter.Write(ClientMessageId.CRUD_DELETE, msg); - } - - internal Update CreateUpdateMessage(string schema, string collection, bool isRelational, FilterParams filter, List updates) - { - var msg = new Update(); - msg.DataModel = (isRelational ? DataModel.Table : DataModel.Document); - msg.Collection = ExprUtil.BuildCollection(schema, collection); - ApplyFilter(v => msg.Limit = v, v => msg.Criteria = v, msg.Order.Add, filter, msg.Args.Add); - - foreach (var update in updates) - { - var updateBuilder = new UpdateOperation(); - updateBuilder.Operation = update.Type; - updateBuilder.Source = update.GetSource(isRelational); - if (update.Type != UpdateOperation.Types.UpdateType.ItemRemove - || (update.Type == UpdateOperation.Types.UpdateType.ItemRemove && update.HasValue)) - updateBuilder.Value = update.GetValue(update.Type); - msg.Operation.Add(updateBuilder); - } - - return msg; - } - - /// - /// Sends the CRUD modify message - /// - public void SendUpdate(string schema, string collection, bool isRelational, FilterParams filter, List updates) - { - var msg = CreateUpdateMessage(schema, collection, isRelational, filter, updates); - _packetReaderWriter.Write(ClientMessageId.CRUD_UPDATE, msg); - } - - internal Find CreateFindMessage(string schema, string collection, bool isRelational, FilterParams filter, FindParams findParams) - { - var builder = new Find(); - builder.Collection = ExprUtil.BuildCollection(schema, collection); - builder.DataModel = (isRelational ? DataModel.Table : DataModel.Document); - if (findParams.GroupBy != null && findParams.GroupBy.Length > 0) - builder.Grouping.AddRange(new ExprParser(ExprUtil.JoinString(findParams.GroupBy)).ParseExprList()); - if (findParams.GroupByCritieria != null) - builder.GroupingCriteria = new ExprParser(findParams.GroupByCritieria).Parse(); - if (findParams.Locking != 0) builder.Locking = (Find.Types.RowLock)findParams.Locking; - if (findParams.LockingOption != 0) builder.LockingOptions = (Find.Types.RowLockOptions)findParams.LockingOption; - if (findParams.Projection != null && findParams.Projection.Length > 0) - { - var parser = new ExprParser(ExprUtil.JoinString(findParams.Projection)); - builder.Projection.Add(builder.DataModel == DataModel.Document ? - parser.ParseDocumentProjection() : - parser.ParseTableSelectProjection()); - - if (parser.tokenPos < parser.tokens.Count) - throw new ArgumentException(string.Format("Expression has unexpected token '{0}' at position {1}.", parser.tokens[parser.tokenPos].value, parser.tokenPos)); - } - ApplyFilter(v => builder.Limit = v, v => builder.Criteria = v, builder.Order.Add, filter, builder.Args.Add); - return builder; - } - - public void SendFind(string schema, string collection, bool isRelational, FilterParams filter, FindParams findParams) - { - var builder = CreateFindMessage(schema, collection, isRelational, filter, findParams); - _packetReaderWriter.Write(ClientMessageId.CRUD_FIND, builder); - } - - public void SendExpectOpen(Mysqlx.Expect.Open.Types.Condition.Types.Key condition, object value = null) - { - var builder = new Mysqlx.Expect.Open(); - var cond = new Mysqlx.Expect.Open.Types.Condition(); - cond.ConditionKey = (uint)condition; - cond.ConditionValue = value != null ? ByteString.CopyFromUtf8((string)value) : null; - builder.Cond.Add(cond); - _packetReaderWriter.Write(ClientMessageId.EXPECT_OPEN, builder); - } - - public void SendResetSession(bool sessionResetNoReauthentication) - { - var builder = new Mysqlx.Session.Reset(); - - if (sessionResetNoReauthentication) { builder.KeepOpen = sessionResetNoReauthentication; } - _packetReaderWriter.Write(ClientMessageId.SESS_RESET, builder); - } - - internal void ReadOkClose() - { - try - { - string response = ReadOk(); - if (response.IndexOf("bye", 0, StringComparison.OrdinalIgnoreCase) < 0) - throw new ArgumentException(); - } - catch (IOException) - { - // TODO connection is closed - } - catch (Exception ex) - { - throw new MySqlException("Unexpected message encountered during closing session", ex); - } - } - - internal string ReadOk() - { - CommunicationPacket p = ReadPacket(); - if (p.MessageType == (int)ServerMessageId.ERROR) - { - var error = Error.Parser.ParseFrom(p.Buffer); - throw new MySqlException(error.Code, error.SqlState, error.Msg); - } - if (p.MessageType == (int)ServerMessageId.OK) - { - var response = Ok.Parser.ParseFrom(p.Buffer); - return response.Msg; - } - else - throw new InvalidOperationException(); - } - - internal void SetXPackets(XPacketReaderWriter readerwriter) - { - _packetReaderWriter = readerwriter; - } - - public void SendPrepareStatement(uint stmtId, - PreparedStatementType type, - string schema, - string collection, - bool isRelational, - FilterParams filter, - FindParams findParams, - List updateSpecs = null, - object[] rows = null, - string[] columns = null, - bool upsert = false, - string sql = null) - { - var builder = new Prepare(); - builder.StmtId = stmtId; - builder.Stmt = new Prepare.Types.OneOfMessage(); - switch (type) - { - case PreparedStatementType.Find: - builder.Stmt.Type = Prepare.Types.OneOfMessage.Types.Type.Find; - var message = CreateFindMessage(schema, collection, isRelational, filter, findParams); - message.Args.Clear(); - if (filter.HasLimit) - { - uint positionFind = (uint)filter.Parameters.Count; - message.Limit = null; - message.LimitExpr = new LimitExpr - { - RowCount = new Expr - { - Type = Expr.Types.Type.Placeholder, - Position = positionFind++ - }, - Offset = new Expr - { - Type = Expr.Types.Type.Placeholder, - Position = positionFind++ - } - }; - } - builder.Stmt.Find = message; - break; - - case PreparedStatementType.Update: - builder.Stmt.Type = Prepare.Types.OneOfMessage.Types.Type.Update; - var updateMessage = CreateUpdateMessage(schema, collection, isRelational, filter, updateSpecs); - updateMessage.Args.Clear(); - if (filter.HasLimit) - { - uint positionUpdate = (uint)filter.Parameters.Count; - updateMessage.Limit = null; - updateMessage.LimitExpr = new LimitExpr - { - RowCount = new Expr - { - Type = Expr.Types.Type.Placeholder, - Position = positionUpdate++ - } - }; - } - builder.Stmt.Update = updateMessage; - break; - - case PreparedStatementType.Delete: - builder.Stmt.Type = Prepare.Types.OneOfMessage.Types.Type.Delete; - var deleteMessage = CreateDeleteMessage(schema, collection, isRelational, filter); - deleteMessage.Args.Clear(); - if (filter.HasLimit) - { - uint positionDelete = (uint)filter.Parameters.Count; - deleteMessage.Limit = null; - deleteMessage.LimitExpr = new LimitExpr - { - RowCount = new Expr - { - Type = Expr.Types.Type.Placeholder, - Position = positionDelete++ - } - }; - } - builder.Stmt.Delete = deleteMessage; - break; - - case PreparedStatementType.Insert: - builder.Stmt.Type = Prepare.Types.OneOfMessage.Types.Type.Insert; - var insertMessage = CreateInsertMessage(schema, isRelational, collection, rows, columns, upsert); - insertMessage.Args.Clear(); - uint position = 0; - foreach (var row in insertMessage.Row) - { - foreach (var field in row.Field) - { - if (field.Type == Expr.Types.Type.Literal) - { - field.Type = Expr.Types.Type.Placeholder; - field.Literal = null; - field.Position = position++; - } - } - } - builder.Stmt.Insert = insertMessage; - break; - - case PreparedStatementType.SqlStatement: - builder.Stmt.Type = Prepare.Types.OneOfMessage.Types.Type.Stmt; - var sqlMessage = CreateExecuteSQLStatement(sql, rows); - sqlMessage.Args.Clear(); - builder.Stmt.StmtExecute = sqlMessage; - break; - } - - _packetReaderWriter.Write((int)ClientMessages.Types.Type.PreparePrepare, builder); - ReadOk(); - } - - public void SendExecutePreparedStatement(uint stmtId, IEnumerable args) - { - var builder = new Execute(); - builder.StmtId = stmtId; - AddArgs(builder.Args.Add, args); - - _packetReaderWriter.Write((int)ClientMessages.Types.Type.PrepareExecute, builder); - } - - public void AddArgs(Action addFunction, IEnumerable args) - { - foreach (var arg in args) - { - if (arg.GetType().IsArray) - AddArgs(addFunction, (System.Array)arg); - else - addFunction(ExprUtil.BuildAny(arg)); - } - } - - public void SendDeallocatePreparedStatement(uint stmtId) - { - var builder = new Deallocate(); - builder.StmtId = stmtId; - _packetReaderWriter.Write((int)ClientMessages.Types.Type.PrepareDeallocate, builder); - ReadOk(); - } - } -} +// Copyright © 2015, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using Google.Protobuf; +using MySql.Data; +using MySql.Data.MySqlClient; +using Mysqlx; +using Mysqlx.Connection; +using Mysqlx.Crud; +using Mysqlx.Datatypes; +using Mysqlx.Expr; +using Mysqlx.Notice; +using Mysqlx.Prepare; +using Mysqlx.Resultset; +using Mysqlx.Session; +using Mysqlx.Sql; +using MySqlX.Communication; +using MySqlX.Data; +using MySqlX.DataAccess; +using MySqlX.Protocol.X; +using MySqlX.XDevAPI; +using MySqlX.XDevAPI.Common; +using MySqlX.XDevAPI.CRUD; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +#if !NETFRAMEWORK +using System.Text.Json; +#endif +using static Mysqlx.Datatypes.Object.Types; + +namespace MySqlX.Protocol +{ + internal class XProtocol : ProtocolBase + { + private CommunicationPacket _pendingPacket; + private XPacketReaderWriter _packetReaderWriter; + + public Capabilities Capabilities { get; protected set; } + + public XProtocol(XPacketReaderWriter packetReaderWriter) + { + _packetReaderWriter = packetReaderWriter; + } + + #region Authentication + + public void SendAuthStart(string method, byte[] authData, byte[] initialResponse) + { + AuthenticateStart authStart = new AuthenticateStart(); + authStart.MechName = method; + if (authData != null) authStart.AuthData = (ByteString.CopyFrom(authData)); + if (initialResponse != null) authStart.InitialResponse = (ByteString.CopyFrom(initialResponse)); + _packetReaderWriter.Write(ClientMessageId.SESS_AUTHENTICATE_START, authStart); + } + + public byte[] ReadAuthContinue() + { + CommunicationPacket p = ReadPacket(); + if (p.MessageType != (int)ServerMessageId.SESS_AUTHENTICATE_CONTINUE) + throw new MySqlException("Unexpected message encountered during authentication handshake"); + AuthenticateContinue response = AuthenticateContinue.Parser.ParseFrom(p.Buffer); + if (!response.AuthData.IsEmpty) + return response.AuthData.ToByteArray(); + return null; + } + + public void SendAuthContinue(byte[] data) + { + Debug.Assert(data != null); + AuthenticateContinue authCont = new AuthenticateContinue(); + authCont.AuthData = (ByteString.CopyFrom(data)); + _packetReaderWriter.Write(ClientMessageId.SESS_AUTHENTICATE_CONTINUE, authCont); + } + + public void ReadAuthOk() + { + CommunicationPacket p = ReadPacket(); + switch ((ServerMessageId)p.MessageType) + { + case ServerMessageId.SESS_AUTHENTICATE_OK: + break; + + case ServerMessageId.ERROR: + var error = Error.Parser.ParseFrom(p.Buffer); + throw new MySqlException(error.Code, error.SqlState, error.Msg); + + case ServerMessageId.NOTICE: + ///TODO: fix this + //ProcessNotice(p, new Result(null)); + ReadAuthOk(); + break; + + default: + throw new MySqlException("Unexpected message encountered during authentication handshake"); + } + } + + #endregion + + public void GetServerCapabilities() + { + _packetReaderWriter.Write(ClientMessageId.CON_CAPABILITIES_GET, new CapabilitiesGet()); + CommunicationPacket packet = ReadPacket(); + + if (packet.MessageType == (int)ServerMessageId.NOTICE) + packet = ReadPacket(); + + if (packet.MessageType != (int)ServerMessageId.CONN_CAPABILITIES) + { + if (packet.MessageType == (int)ServerMessageId.ERROR) + DecodeAndThrowError(packet); + else + ThrowUnexpectedMessage(packet.MessageType, (int)ServerMessageId.CONN_CAPABILITIES); + } + Capabilities = Capabilities.Parser.ParseFrom(packet.Buffer); + } + + public void SetCapabilities(Dictionary clientCapabilities) + { + if (clientCapabilities == null || clientCapabilities.Count == 0) + return; + + var builder = new CapabilitiesSet(); + var capabilities = new Capabilities(); + foreach (var cap in clientCapabilities) + { + var value = new Any(); + + if (cap.Key == "tls") + value = ExprUtil.BuildAny(cap.Value); + else if (cap.Key == "session_connect_attrs" || cap.Key == "compression") + { + var obj = new Mysqlx.Datatypes.Object(); + + if (cap.Key == "session_connect_attrs") + { + foreach (var pair in (Dictionary)cap.Value) + obj.Fld.Add(new ObjectField { Key = pair.Key, Value = ExprUtil.BuildAny(pair.Value) }); + } + else if (cap.Key == "compression") + { + foreach (var pair in (Dictionary)cap.Value) + obj.Fld.Add(new ObjectField { Key = pair.Key, Value = ExprUtil.BuildAny(pair.Value) }); + } + + value = new Any { Type = Any.Types.Type.Object, Obj = obj }; + } + + var capabilityMsg = new Capability() { Name = cap.Key, Value = value }; + capabilities.Capabilities_.Add(capabilityMsg); + } + + builder.Capabilities = capabilities; + _packetReaderWriter.Write(ClientMessageId.CON_CAPABILITIES_SET, builder); + ReadOk(); + } + + private void ThrowUnexpectedMessage(int received, int expected) + { + if (received == 10) // Connection to XProtocol using ClassicProtocol port + throw new MySqlException("Unsupported protocol version."); + throw new MySqlException( + String.Format("Expected message id: {0}. Received message id: {1}", expected, received)); + } + + public override void SendSQL(string sql, params object[] args) + { + SendExecuteSQLStatement(sql, args); + } + + public override bool HasData(BaseResult rs) + { + while (true) + { + CommunicationPacket packet = PeekPacket(); + switch (packet.MessageType) + { + case (int)ServerMessageId.RESULTSET_COLUMN_META_DATA: + return true; + case (int)ServerMessageId.NOTICE: + ProcessNotice(packet, rs); + packet = ReadPacket(); + break; + case (int)ServerMessageId.ERROR: + packet = ReadPacket(); + DecodeAndThrowError(packet); + break; + default: + return false; + } + } + } + + private CommunicationPacket PeekPacket() + { + if (_pendingPacket != null) return _pendingPacket; + _pendingPacket = _packetReaderWriter.Read(); + return _pendingPacket; + } + + private CommunicationPacket ReadPacket() + { + while (true) + { + CommunicationPacket p = _pendingPacket != null ? _pendingPacket : _packetReaderWriter.Read(); + _pendingPacket = null; + return p; + } + } + + private void ProcessGlobalNotice(Mysqlx.Notice.Frame frame) + { + } + + private void ProcessNotice(CommunicationPacket packet, BaseResult rs) + { + Frame frame = Frame.Parser.ParseFrom(packet.Buffer); + if (frame.Scope == Frame.Types.Scope.Global) + { + ProcessGlobalNotice(frame); + return; + } + + // if we get here the notice is local + switch ((NoticeType)frame.Type) + { + case NoticeType.Warning: + ProcessWarning(rs, frame.Payload.ToByteArray()); + break; + case NoticeType.SessionStateChanged: + ProcessSessionStateChanged(rs, frame.Payload.ToByteArray()); + break; + case NoticeType.SessionVariableChanged: + break; + default: // will ignore unknown notices from the server + break; + } + } + + private void ProcessSessionStateChanged(BaseResult rs, byte[] payload) + { + SessionStateChanged state = SessionStateChanged.Parser.ParseFrom(payload); + switch (state.Param) + { + case SessionStateChanged.Types.Parameter.RowsAffected: + rs._recordsAffected = state.Value[0].VUnsignedInt; + rs._affectedItemsCount = rs._recordsAffected; + break; + case SessionStateChanged.Types.Parameter.GeneratedInsertId: + rs._autoIncrementValue = state.Value[0].VUnsignedInt; + break; + case SessionStateChanged.Types.Parameter.ProducedMessage: + rs.AddWarning(new WarningInfo(0, state.Value[0].VString.Value.ToStringUtf8())); + break; + case SessionStateChanged.Types.Parameter.GeneratedDocumentIds: + foreach (var value in state.Value) + rs._documentIds.Add(value.VOctets.Value.ToStringUtf8()); + break; + //handle the other ones + //default: SessionStateChanged(state); + } + } + + private void ProcessWarning(BaseResult rs, byte[] payload) + { + Warning w = Warning.Parser.ParseFrom(payload); + WarningInfo warning = new WarningInfo(w.Code, w.Msg); + if (w.HasLevel) + warning.Level = (uint)w.Level; + rs.AddWarning(warning); + } + + private Any CreateAny(object o) + { + if (o is string) return ExprUtil.BuildAny((string)o); + if (o is bool) return ExprUtil.BuildAny((bool)o); + return ExprUtil.BuildAny(o); + } + + private ObjectField CreateObject(string key, object value, bool evaluateStringExpression = true) + { + return ExprUtil.BuildObject(key, value, evaluateStringExpression); + } + + public void SendSessionClose() + { + _packetReaderWriter.Write(ClientMessageId.SESS_CLOSE, new Mysqlx.Session.Close()); + } + + public void SendConnectionClose() + { + Mysqlx.Connection.Close connClose = new Mysqlx.Connection.Close(); + _packetReaderWriter.Write(ClientMessageId.CON_CLOSE, connClose); + } + + internal StmtExecute CreateExecuteSQLStatement(string stmt, params object[] args) + { + StmtExecute stmtExecute = new StmtExecute(); + stmtExecute.Namespace = "sql"; + stmtExecute.Stmt = ByteString.CopyFromUtf8(stmt); + stmtExecute.CompactMetadata = false; + if (args != null) + { + foreach (object arg in args) + stmtExecute.Args.Add(CreateAny(arg)); + } + + return stmtExecute; + } + + public void SendExecuteSQLStatement(string stmt, params object[] args) + { + StmtExecute stmtExecute = CreateExecuteSQLStatement(stmt, args); + _packetReaderWriter.Write(ClientMessageId.SQL_STMT_EXECUTE, stmtExecute); + } + + public void SendExecuteStatement(string ns, string stmt, params KeyValuePair[] args) + { + StmtExecute stmtExecute = new StmtExecute(); + stmtExecute.Namespace = ns; + stmtExecute.Stmt = ByteString.CopyFromUtf8(stmt); + stmtExecute.CompactMetadata = false; + if (args != null) + { + var any = ExprUtil.BuildEmptyAny(Any.Types.Type.Object); + + foreach (var arg in args) + { + switch (stmt) + { + case "drop_collection_index": + any.Obj.Fld.Add(CreateObject(arg.Key, arg.Value, false)); + break; + default: + any.Obj.Fld.Add(CreateObject(arg.Key, arg.Value)); + break; + } + } + stmtExecute.Args.Add(any); + } + + _packetReaderWriter.Write(ClientMessageId.SQL_STMT_EXECUTE, stmtExecute); + } + + /// + /// Build the message to be sent to MySQL Server to execute statement "Create" or "Modify" collection with schema options + /// + /// The namespace + /// The name of the command to be executed on MySql Server + /// Array of KeyValuePairs with the parameters required to build the message + /// void. + public void SendExecuteStatementOptions(string ns, string stmt, params KeyValuePair[] args) + { + StmtExecute stmtExecute = new StmtExecute(); + stmtExecute.Namespace = ns; + stmtExecute.Stmt = ByteString.CopyFromUtf8(stmt); + stmtExecute.CompactMetadata = false; + if (args != null) + { + var options = new ObjectField(); + var validation = new ObjectField(); + var reuse_obj = new ObjectField(); + var optionsAny = ExprUtil.BuildEmptyAny(Any.Types.Type.Object); + var any = ExprUtil.BuildEmptyAny(Any.Types.Type.Object); + var innerAny = ExprUtil.BuildEmptyAny(Any.Types.Type.Object); + var reuse_any = ExprUtil.BuildEmptyAny(Any.Types.Type.Object); + foreach (var arg in args) + { + if (arg.Value is Dictionary && arg.Key == "options") + { + foreach (var field in arg.Value as Dictionary) + { + innerAny.Obj.Fld.Add(CreateObject(field.Key, field.Value)); + } + } + else if (arg.Key == "reuse_existing") + { + reuse_any = ExprUtil.BuildAny(arg.Value); + } + else + { + any.Obj.Fld.Add(CreateObject(arg.Key, arg.Value)); + } + } + options.Key = "options"; + validation.Key = "validation"; + validation.Value = innerAny; + reuse_obj.Key = "reuse_existing"; + reuse_obj.Value = reuse_any; + optionsAny.Obj.Fld.Add(validation); + if (stmt == "create_collection") + { + optionsAny.Obj.Fld.Add(reuse_obj); + } + options.Value = optionsAny; + any.Obj.Fld.Add(options); + stmtExecute.Args.Add(any); + } + + _packetReaderWriter.Write(ClientMessageId.SQL_STMT_EXECUTE, stmtExecute); + } + + public void SendCreateCollectionIndexStatement(string ns, string stmt, params KeyValuePair[] args) + { + StmtExecute stmtExecute = new StmtExecute(); + stmtExecute.Namespace = ns; + stmtExecute.Stmt = ByteString.CopyFromUtf8(stmt); + stmtExecute.CompactMetadata = false; + if (args != null) + { + var any = ExprUtil.BuildEmptyAny(Any.Types.Type.Object); + var array = new Mysqlx.Datatypes.Array(); + foreach (var arg in args) + { + if (arg.Value is Dictionary && arg.Key == "constraint") + { + var innerAny = ExprUtil.BuildEmptyAny(Any.Types.Type.Object); + foreach (var field in arg.Value as Dictionary) + innerAny.Obj.Fld.Add(CreateObject(field.Key, field.Value, field.Key == "member" ? true : false)); + + array.Value.Add(innerAny); + } + else + any.Obj.Fld.Add(CreateObject(arg.Key, arg.Value, false)); + } + + if (array.Value.Count > 0) + { + var constraint = new ObjectField(); + constraint.Key = "constraint"; + var constraintAny = ExprUtil.BuildEmptyAny(Any.Types.Type.Array); + constraintAny.Array = array; + constraint.Value = constraintAny; + any.Obj.Fld.Add(constraint); + } + + stmtExecute.Args.Add(any); + } + + _packetReaderWriter.Write(ClientMessageId.SQL_STMT_EXECUTE, stmtExecute); + } + + private void DecodeAndThrowError(CommunicationPacket p) + { + Error e = Error.Parser.ParseFrom(p.Buffer); + throw new MySqlException(e.Code, e.SqlState, e.Msg); + } + + public override List ReadRow(BaseResult rs) + { + CommunicationPacket packet = PeekPacket(); + if (packet.MessageType != (int)ServerMessageId.RESULTSET_ROW) + { + if (rs != null) + CloseResult(rs); + + return null; + } + + var protoRow = Row.Parser.ParseFrom(ReadPacket().Buffer); + var values = new List(protoRow.Field.Count); + for (int i = 0; i < protoRow.Field.Count; i++) + values.Add(protoRow.Field[i].ToByteArray()); + + return values; + } + + public override void CloseResult(BaseResult rs) + { + rs._hasData = false; + while (true) + { + CommunicationPacket p = PeekPacket(); + if (p.MessageType == (int)ServerMessageId.RESULTSET_FETCH_DONE_MORE_RESULTSETS) + { + rs._hasMoreResults = true; + ReadPacket(); + break; + } + if (p.MessageType == (int)ServerMessageId.OK) + { + ReadOk(); + break; + } + if (p.MessageType == (int)ServerMessageId.RESULTSET_FETCH_DONE) + ReadPacket(); + else if (p.MessageType == (int)ServerMessageId.NOTICE) + ProcessNotice(ReadPacket(), rs); + else if (p.MessageType == (int)ServerMessageId.ERROR) + { + rs._session.ActiveResult = null; + DecodeAndThrowError(ReadPacket()); + } + else if (p.MessageType == (int)ServerMessageId.SQL_STMT_EXECUTE_OK) + { + ReadPacket(); + break; + } + else + throw new MySqlException(ResourcesX.ThrowingAwayResults); + } + } + + public override List LoadColumnMetadata() + { + List columns = new List(); + // we assume our caller has already validated that metadata is there + while (true) + { + if (PeekPacket().MessageType != (int)ServerMessageId.RESULTSET_COLUMN_META_DATA) return columns; + CommunicationPacket p = ReadPacket(); + ColumnMetaData response = ColumnMetaData.Parser.ParseFrom(p.Buffer); + columns.Add(DecodeColumn(response)); + } + } + + private XDevAPI.Relational.Column DecodeColumn(ColumnMetaData colData) + { + XDevAPI.Relational.Column c = new XDevAPI.Relational.Column(); + c._decoder = XValueDecoderFactory.GetValueDecoder(c, colData.Type); + c._decoder.Column = c; + + if (!colData.Name.IsEmpty) + c.ColumnLabel = colData.Name.ToStringUtf8(); + if (!colData.OriginalName.IsEmpty) + c.ColumnName = colData.OriginalName.ToStringUtf8(); + if (!colData.Table.IsEmpty) + c.TableLabel = colData.Table.ToStringUtf8(); + if (!colData.OriginalTable.IsEmpty) + c.TableName = colData.OriginalTable.ToStringUtf8(); + if (!colData.Schema.IsEmpty) + c.SchemaName = colData.Schema.ToStringUtf8(); + if (!colData.Catalog.IsEmpty) + c.DatabaseName = colData.Catalog.ToStringUtf8(); + if (colData.Collation > 0) + { + c._collationNumber = colData.Collation; + c.CollationName = CollationMap.GetCollationName((int)colData.Collation); + c.CharacterSetName = c.CollationName.Split('_')[0]; + } + if (colData.Length > 0) + c.Length = colData.Length; + if (colData.FractionalDigits > 0) + c.FractionalDigits = colData.FractionalDigits; + if (colData.Flags > 0) + c._decoder.Flags = colData.Flags; + if (colData.ContentType > 0) + c._decoder.ContentType = colData.ContentType; + c._decoder.SetMetadata(); + return c; + } + + internal Insert CreateInsertMessage(string schema, bool isRelational, string collection, object[] rows, string[] columns, bool upsert) + { + Insert msg = new Mysqlx.Crud.Insert(); + msg.Collection = ExprUtil.BuildCollection(schema, collection); + msg.DataModel = (isRelational ? DataModel.Table : DataModel.Document); + msg.Upsert = upsert; + if (columns != null && columns.Length > 0) + { + foreach (string column in columns) + msg.Projection.Add(new ExprParser(column).ParseTableInsertField()); + } + + foreach (object row in rows) + { + Mysqlx.Crud.Insert.Types.TypedRow typedRow = new Mysqlx.Crud.Insert.Types.TypedRow(); + object[] fields = row.GetType().IsArray ? (object[])row : new object[] { row }; + foreach (object field in fields) + if (field is null) + typedRow.Field.Add(ExprUtil.BuildLiteralNullScalar()); + else + { + if (field is DbDoc || field.GetType().Namespace == "System") + typedRow.Field.Add(ExprUtil.BuildLiteralScalar(Convert.ToString(field))); + else + { +#if !NETFRAMEWORK + string jsonString = JsonSerializer.Serialize(field); + typedRow.Field.Add(ExprUtil.BuildLiteralScalar(jsonString)); +#else + throw new MySqlException(ResourcesX.CustomTypeNotSupported); +#endif + } + } + + msg.Row.Add(typedRow); + } + + return msg; + } + + public void SendInsert(string schema, bool isRelational, string collection, object[] rows, string[] columns, bool upsert) + { + Insert msg = CreateInsertMessage(schema, isRelational, collection, rows, columns, upsert); + _packetReaderWriter.Write(ClientMessageId.CRUD_INSERT, msg); + } + + private void ApplyFilter(Action setLimit, Action setCriteria, Action> setOrder, FilterParams filter, Action> addParams) + { + if (filter.HasLimit) + { + var limit = new Limit(); + limit.RowCount = (ulong)filter.Limit; + if (filter.Offset != -1) limit.Offset = (ulong)filter.Offset; + setLimit(limit); + } + if (!string.IsNullOrEmpty(filter.Condition)) + { + setCriteria(filter.GetConditionExpression(filter.IsRelational)); + if (filter.Parameters != null && filter.Parameters.Count > 0) + addParams(filter.GetArgsExpression(filter.Parameters)); + } + if (filter.OrderBy != null && filter.OrderBy.Length > 0) + setOrder(filter.GetOrderByExpressions(filter.IsRelational)); + + } + + internal Delete CreateDeleteMessage(string schema, string collection, bool isRelational, FilterParams filter) + { + var msg = new Delete(); + msg.DataModel = (isRelational ? DataModel.Table : DataModel.Document); + msg.Collection = ExprUtil.BuildCollection(schema, collection); + ApplyFilter(v => msg.Limit = v, v => msg.Criteria = v, msg.Order.Add, filter, msg.Args.Add); + + return msg; + } + + /// + /// Sends the delete documents message + /// + public void SendDelete(string schema, string collection, bool isRelational, FilterParams filter) + { + var msg = CreateDeleteMessage(schema, collection, isRelational, filter); + _packetReaderWriter.Write(ClientMessageId.CRUD_DELETE, msg); + } + + internal Update CreateUpdateMessage(string schema, string collection, bool isRelational, FilterParams filter, List updates) + { + var msg = new Update(); + msg.DataModel = (isRelational ? DataModel.Table : DataModel.Document); + msg.Collection = ExprUtil.BuildCollection(schema, collection); + ApplyFilter(v => msg.Limit = v, v => msg.Criteria = v, msg.Order.Add, filter, msg.Args.Add); + + foreach (var update in updates) + { + var updateBuilder = new UpdateOperation(); + updateBuilder.Operation = update.Type; + updateBuilder.Source = update.GetSource(isRelational); + if (update.Type != UpdateOperation.Types.UpdateType.ItemRemove + || (update.Type == UpdateOperation.Types.UpdateType.ItemRemove && update.HasValue)) + updateBuilder.Value = update.GetValue(update.Type); + msg.Operation.Add(updateBuilder); + } + + return msg; + } + + /// + /// Sends the CRUD modify message + /// + public void SendUpdate(string schema, string collection, bool isRelational, FilterParams filter, List updates) + { + var msg = CreateUpdateMessage(schema, collection, isRelational, filter, updates); + _packetReaderWriter.Write(ClientMessageId.CRUD_UPDATE, msg); + } + + internal Find CreateFindMessage(string schema, string collection, bool isRelational, FilterParams filter, FindParams findParams) + { + var builder = new Find(); + builder.Collection = ExprUtil.BuildCollection(schema, collection); + builder.DataModel = (isRelational ? DataModel.Table : DataModel.Document); + if (findParams.GroupBy != null && findParams.GroupBy.Length > 0) + builder.Grouping.AddRange(new ExprParser(ExprUtil.JoinString(findParams.GroupBy)).ParseExprList()); + if (findParams.GroupByCritieria != null) + builder.GroupingCriteria = new ExprParser(findParams.GroupByCritieria).Parse(); + if (findParams.Locking != 0) builder.Locking = (Find.Types.RowLock)findParams.Locking; + if (findParams.LockingOption != 0) builder.LockingOptions = (Find.Types.RowLockOptions)findParams.LockingOption; + if (findParams.Projection != null && findParams.Projection.Length > 0) + { + var parser = new ExprParser(ExprUtil.JoinString(findParams.Projection)); + builder.Projection.Add(builder.DataModel == DataModel.Document ? + parser.ParseDocumentProjection() : + parser.ParseTableSelectProjection()); + + if (parser.tokenPos < parser.tokens.Count) + throw new ArgumentException(string.Format("Expression has unexpected token '{0}' at position {1}.", parser.tokens[parser.tokenPos].value, parser.tokenPos)); + } + ApplyFilter(v => builder.Limit = v, v => builder.Criteria = v, builder.Order.Add, filter, builder.Args.Add); + return builder; + } + + public void SendFind(string schema, string collection, bool isRelational, FilterParams filter, FindParams findParams) + { + var builder = CreateFindMessage(schema, collection, isRelational, filter, findParams); + _packetReaderWriter.Write(ClientMessageId.CRUD_FIND, builder); + } + + public void SendExpectOpen(Mysqlx.Expect.Open.Types.Condition.Types.Key condition, object value = null) + { + var builder = new Mysqlx.Expect.Open(); + var cond = new Mysqlx.Expect.Open.Types.Condition(); + cond.ConditionKey = (uint)condition; + cond.ConditionValue = value != null ? ByteString.CopyFromUtf8((string)value) : null; + builder.Cond.Add(cond); + _packetReaderWriter.Write(ClientMessageId.EXPECT_OPEN, builder); + } + + public void SendResetSession(bool sessionResetNoReauthentication) + { + var builder = new Mysqlx.Session.Reset(); + + if (sessionResetNoReauthentication) { builder.KeepOpen = sessionResetNoReauthentication; } + _packetReaderWriter.Write(ClientMessageId.SESS_RESET, builder); + } + + internal void ReadOkClose() + { + try + { + string response = ReadOk(); + if (response.IndexOf("bye", 0, StringComparison.OrdinalIgnoreCase) < 0) + throw new ArgumentException(); + } + catch (IOException) + { + // TODO connection is closed + } + catch (Exception ex) + { + throw new MySqlException("Unexpected message encountered during closing session", ex); + } + } + + internal string ReadOk() + { + CommunicationPacket p = ReadPacket(); + if (p.MessageType == (int)ServerMessageId.ERROR) + { + var error = Error.Parser.ParseFrom(p.Buffer); + throw new MySqlException(error.Code, error.SqlState, error.Msg); + } + if (p.MessageType == (int)ServerMessageId.OK) + { + var response = Ok.Parser.ParseFrom(p.Buffer); + return response.Msg; + } + else + throw new InvalidOperationException(); + } + + internal void SetXPackets(XPacketReaderWriter readerwriter) + { + _packetReaderWriter = readerwriter; + } + + public void SendPrepareStatement(uint stmtId, + PreparedStatementType type, + string schema, + string collection, + bool isRelational, + FilterParams filter, + FindParams findParams, + List updateSpecs = null, + object[] rows = null, + string[] columns = null, + bool upsert = false, + string sql = null) + { + var builder = new Prepare(); + builder.StmtId = stmtId; + builder.Stmt = new Prepare.Types.OneOfMessage(); + switch (type) + { + case PreparedStatementType.Find: + builder.Stmt.Type = Prepare.Types.OneOfMessage.Types.Type.Find; + var message = CreateFindMessage(schema, collection, isRelational, filter, findParams); + message.Args.Clear(); + if (filter.HasLimit) + { + uint positionFind = (uint)filter.Parameters.Count; + message.Limit = null; + message.LimitExpr = new LimitExpr + { + RowCount = new Expr + { + Type = Expr.Types.Type.Placeholder, + Position = positionFind++ + }, + Offset = new Expr + { + Type = Expr.Types.Type.Placeholder, + Position = positionFind++ + } + }; + } + builder.Stmt.Find = message; + break; + + case PreparedStatementType.Update: + builder.Stmt.Type = Prepare.Types.OneOfMessage.Types.Type.Update; + var updateMessage = CreateUpdateMessage(schema, collection, isRelational, filter, updateSpecs); + updateMessage.Args.Clear(); + if (filter.HasLimit) + { + uint positionUpdate = (uint)filter.Parameters.Count; + updateMessage.Limit = null; + updateMessage.LimitExpr = new LimitExpr + { + RowCount = new Expr + { + Type = Expr.Types.Type.Placeholder, + Position = positionUpdate++ + } + }; + } + builder.Stmt.Update = updateMessage; + break; + + case PreparedStatementType.Delete: + builder.Stmt.Type = Prepare.Types.OneOfMessage.Types.Type.Delete; + var deleteMessage = CreateDeleteMessage(schema, collection, isRelational, filter); + deleteMessage.Args.Clear(); + if (filter.HasLimit) + { + uint positionDelete = (uint)filter.Parameters.Count; + deleteMessage.Limit = null; + deleteMessage.LimitExpr = new LimitExpr + { + RowCount = new Expr + { + Type = Expr.Types.Type.Placeholder, + Position = positionDelete++ + } + }; + } + builder.Stmt.Delete = deleteMessage; + break; + + case PreparedStatementType.Insert: + builder.Stmt.Type = Prepare.Types.OneOfMessage.Types.Type.Insert; + var insertMessage = CreateInsertMessage(schema, isRelational, collection, rows, columns, upsert); + insertMessage.Args.Clear(); + uint position = 0; + foreach (var row in insertMessage.Row) + { + foreach (var field in row.Field) + { + if (field.Type == Expr.Types.Type.Literal) + { + field.Type = Expr.Types.Type.Placeholder; + field.Literal = null; + field.Position = position++; + } + } + } + builder.Stmt.Insert = insertMessage; + break; + + case PreparedStatementType.SqlStatement: + builder.Stmt.Type = Prepare.Types.OneOfMessage.Types.Type.Stmt; + var sqlMessage = CreateExecuteSQLStatement(sql, rows); + sqlMessage.Args.Clear(); + builder.Stmt.StmtExecute = sqlMessage; + break; + } + + _packetReaderWriter.Write((int)ClientMessages.Types.Type.PreparePrepare, builder); + ReadOk(); + } + + public void SendExecutePreparedStatement(uint stmtId, IEnumerable args) + { + var builder = new Execute(); + builder.StmtId = stmtId; + AddArgs(builder.Args.Add, args); + + _packetReaderWriter.Write((int)ClientMessages.Types.Type.PrepareExecute, builder); + } + + public void AddArgs(Action addFunction, IEnumerable args) + { + foreach (var arg in args) + { + if (arg.GetType().IsArray) + AddArgs(addFunction, (System.Array)arg); + else + addFunction(ExprUtil.BuildAny(arg)); + } + } + + public void SendDeallocatePreparedStatement(uint stmtId) + { + var builder = new Deallocate(); + builder.StmtId = stmtId; + _packetReaderWriter.Write((int)ClientMessages.Types.Type.PrepareDeallocate, builder); + ReadOk(); + } + } +} diff --git a/MySQL.Data/src/X/Protocol/X/XTimeDecoder.cs b/MySQL.Data/src/X/Protocol/X/XTimeDecoder.cs index 70164289e..0addea64b 100644 --- a/MySQL.Data/src/X/Protocol/X/XTimeDecoder.cs +++ b/MySQL.Data/src/X/Protocol/X/XTimeDecoder.cs @@ -1,66 +1,66 @@ -// Copyright © 2015, 2016, Oracle and/or its affiliates. All rights reserved. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - - -using Google.Protobuf; -using MySql.Data.MySqlClient; -using MySql.Data.MySqlClient.X.XDevAPI.Common; -using MySqlX.Data; -using MySqlX.XDevAPI; -using System; - -namespace MySqlX.Protocol.X -{ - internal class XTimeDecoder : ValueDecoder - { - public override void SetMetadata() - { - Column.Type = ColumnType.Time; - Column.ClrType = typeof(TimeSpan); - ClrValueDecoder = ValueDecoder; - } - - public object ValueDecoder(byte[] bytes) - { - CodedInputStream input = new CodedInputStream(bytes); - Int64 hour = 0, min = 0, sec = 0, usec = 0; - - bool negative = input.ReadInt32() > 0; - if (!input.IsAtEnd) - hour = input.ReadInt64(); - if (!input.IsAtEnd) - min = input.ReadInt64(); - if (!input.IsAtEnd) - sec = input.ReadInt64(); - if (!input.IsAtEnd) - usec = input.ReadInt64(); - if (negative) hour *= -1; - return new TimeSpan(0, (int)hour, (int)min, (int)sec, (int)usec * 1000); - } - } -} +// Copyright © 2015, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + +using Google.Protobuf; +using MySql.Data.MySqlClient; +using MySql.Data.MySqlClient.X.XDevAPI.Common; +using MySqlX.Data; +using MySqlX.XDevAPI; +using System; + +namespace MySqlX.Protocol.X +{ + internal class XTimeDecoder : ValueDecoder + { + public override void SetMetadata() + { + Column.Type = ColumnType.Time; + Column.ClrType = typeof(TimeSpan); + ClrValueDecoder = ValueDecoder; + } + + public object ValueDecoder(byte[] bytes) + { + CodedInputStream input = new CodedInputStream(bytes); + Int64 hour = 0, min = 0, sec = 0, usec = 0; + + bool negative = input.ReadInt32() > 0; + if (!input.IsAtEnd) + hour = input.ReadInt64(); + if (!input.IsAtEnd) + min = input.ReadInt64(); + if (!input.IsAtEnd) + sec = input.ReadInt64(); + if (!input.IsAtEnd) + usec = input.ReadInt64(); + if (negative) hour *= -1; + return new TimeSpan(0, (int)hour, (int)min, (int)sec, (int)usec * 1000); + } + } +} diff --git a/MySQL.Data/src/X/Protocol/X/XValueDecoderFactory.cs b/MySQL.Data/src/X/Protocol/X/XValueDecoderFactory.cs index 047547527..c96fc1776 100644 --- a/MySQL.Data/src/X/Protocol/X/XValueDecoderFactory.cs +++ b/MySQL.Data/src/X/Protocol/X/XValueDecoderFactory.cs @@ -1,56 +1,56 @@ -// Copyright © 2015, 2016, Oracle and/or its affiliates. All rights reserved. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - - -using MySql.Data.MySqlClient; -using MySqlX.XDevAPI.Relational; - -namespace MySqlX.Protocol.X -{ - internal class XValueDecoderFactory - { - public static ValueDecoder GetValueDecoder(Column c, Mysqlx.Resultset.ColumnMetaData.Types.FieldType type) - { - switch (type) - { - case Mysqlx.Resultset.ColumnMetaData.Types.FieldType.Bit: return new BitDecoder(); - case Mysqlx.Resultset.ColumnMetaData.Types.FieldType.Bytes: return new ByteDecoder(false); - case Mysqlx.Resultset.ColumnMetaData.Types.FieldType.Enum: return new ByteDecoder(true); - case Mysqlx.Resultset.ColumnMetaData.Types.FieldType.Set: return new SetDecoder(); - case Mysqlx.Resultset.ColumnMetaData.Types.FieldType.Time: return new XTimeDecoder(); - case Mysqlx.Resultset.ColumnMetaData.Types.FieldType.Datetime: return new XDateTimeDecoder(); - case Mysqlx.Resultset.ColumnMetaData.Types.FieldType.Sint: return new IntegerDecoder(true); - case Mysqlx.Resultset.ColumnMetaData.Types.FieldType.Uint: return new IntegerDecoder(false); - case Mysqlx.Resultset.ColumnMetaData.Types.FieldType.Float: return new FloatDecoder(true); - case Mysqlx.Resultset.ColumnMetaData.Types.FieldType.Double: return new FloatDecoder(false); - case Mysqlx.Resultset.ColumnMetaData.Types.FieldType.Decimal: return new DecimalDecoder(); - } - throw new MySqlException("Unknown field type " + type.ToString()); - } - } -} +// Copyright © 2015, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + +using MySql.Data.MySqlClient; +using MySqlX.XDevAPI.Relational; + +namespace MySqlX.Protocol.X +{ + internal class XValueDecoderFactory + { + public static ValueDecoder GetValueDecoder(Column c, Mysqlx.Resultset.ColumnMetaData.Types.FieldType type) + { + switch (type) + { + case Mysqlx.Resultset.ColumnMetaData.Types.FieldType.Bit: return new BitDecoder(); + case Mysqlx.Resultset.ColumnMetaData.Types.FieldType.Bytes: return new ByteDecoder(false); + case Mysqlx.Resultset.ColumnMetaData.Types.FieldType.Enum: return new ByteDecoder(true); + case Mysqlx.Resultset.ColumnMetaData.Types.FieldType.Set: return new SetDecoder(); + case Mysqlx.Resultset.ColumnMetaData.Types.FieldType.Time: return new XTimeDecoder(); + case Mysqlx.Resultset.ColumnMetaData.Types.FieldType.Datetime: return new XDateTimeDecoder(); + case Mysqlx.Resultset.ColumnMetaData.Types.FieldType.Sint: return new IntegerDecoder(true); + case Mysqlx.Resultset.ColumnMetaData.Types.FieldType.Uint: return new IntegerDecoder(false); + case Mysqlx.Resultset.ColumnMetaData.Types.FieldType.Float: return new FloatDecoder(true); + case Mysqlx.Resultset.ColumnMetaData.Types.FieldType.Double: return new FloatDecoder(false); + case Mysqlx.Resultset.ColumnMetaData.Types.FieldType.Decimal: return new DecimalDecoder(); + } + throw new MySqlException("Unknown field type " + type.ToString()); + } + } +} diff --git a/MySQL.Data/src/X/RoutingServices/DefaultRoutingService.cs b/MySQL.Data/src/X/RoutingServices/DefaultRoutingService.cs index ea44cbd6d..c4f36483c 100644 --- a/MySQL.Data/src/X/RoutingServices/DefaultRoutingService.cs +++ b/MySQL.Data/src/X/RoutingServices/DefaultRoutingService.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2015, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/X/RoutingServices/RoutingServiceBase.cs b/MySQL.Data/src/X/RoutingServices/RoutingServiceBase.cs index 37fbf555b..026d8b17f 100644 --- a/MySQL.Data/src/X/RoutingServices/RoutingServiceBase.cs +++ b/MySQL.Data/src/X/RoutingServices/RoutingServiceBase.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2015, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/X/Serialization/JsonParser.cs b/MySQL.Data/src/X/Serialization/JsonParser.cs index e92792c57..cba5307de 100644 --- a/MySQL.Data/src/X/Serialization/JsonParser.cs +++ b/MySQL.Data/src/X/Serialization/JsonParser.cs @@ -1,213 +1,213 @@ -// Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySqlX.XDevAPI; -using System; -using System.Collections.Generic; - -namespace MySqlX.Serialization -{ - /// - /// Main class for parsing json strings. - /// - public class JsonParser - { - private int _pos = 0; - private String _input; - - /// - /// Initializes a new instance of the JsonParser class. - /// - public JsonParser() - {} - - /// - /// Parses the received string into a dictionary. - /// - /// The string to parse. - /// A object that represents the parsed string. - public static Dictionary Parse(string s) - { - JsonParser p = new JsonParser(); - return p.ParseInternal(s); - } - - private Dictionary ParseInternal(string s) - { - _input = s; - Dictionary dic = ReadGroup(); - if (_pos != _input.Length) - throw new IndexOutOfRangeException("It's not the end of stream."); - return dic; - } - - private Dictionary ReadGroup() - { - Dictionary values = new Dictionary(); - - RequireToken('{'); - if (PeekToken() != '}') - while (true) - { - string key = ReadQuotedToken(); - if (key == null) break; - RequireToken(':'); - var obj = ReadValue(); - values[key] = obj; - if (PeekToken() == '}') break; - RequireToken(','); - } - RequireToken('}'); - return values; - } - - private object ReadValue() - { - char t = PeekToken(); - if (t == '"') return ReadQuotedToken(); - if (t == '{') return ReadGroup(); - if (t == '[') return ReadArray(); - string stringValue = ReadUntilToken(',', '}', ']'); - bool flag; - if (bool.TryParse(stringValue, out flag)) return flag; - if (stringValue.Trim() == "null") return null; - int intValue; - long longValue; - double doubleValue; - if (int.TryParse(stringValue, out intValue)) return intValue; - if (long.TryParse(stringValue, out longValue)) return longValue; - if (double.TryParse( - stringValue, - System.Globalization.NumberStyles.Any, - System.Globalization.CultureInfo.InvariantCulture, - out doubleValue)) - return doubleValue; - - // May be a function. - int openingParen = 0; - for (int i=0; i0) - { - stringValue += ReadUntilToken(')') + ")"; - RequireToken(')'); - openingParen--; - } - - return new MySqlExpression(stringValue); - } - - private object[] ReadArray() - { - List values = new List(); - - RequireToken('['); - while (true) - { - values.Add(ReadValue()); - if (PeekToken() == ']') break; - RequireToken(','); - } - RequireToken(']'); - return values.ToArray(); - } - - private char PeekToken() - { - SkipWhite(); - if (_pos == _input.Length) - throw new Exception("Unexpected end of stream found."); - return _input[_pos]; - } - - private string ReadQuotedToken() - { - RequireToken('"'); - string val = ReadUntilToken('"'); - RequireToken('"'); - return val; - } - - private bool TokenInGroup(char[] tokens, char c) - { - foreach (char token in tokens) - if (token == c) return true; - return false; - } - - private string ReadUntilToken(params char[] end) - { - string val = ""; - bool escapedQuoteExpected = false; - while (_pos < _input.Length) - { - char c = _input[_pos++]; - - if (!escapedQuoteExpected) - { - if (c == 92) - escapedQuoteExpected = true; - else if (TokenInGroup(end, c)) - { - _pos--; - return val; - } - } - else if (c == 34) - escapedQuoteExpected = false; - - val += c; - } - throw new Exception("Failed to find ending '\"' while reading stream."); - } - - private void RequireToken(char token) - { - if (!ReadToken(token)) - throw new Exception("Expected token '" + token + "'"); - } - - private bool ReadToken(char token) - { - SkipWhite(); - if (_pos == _input.Length) return false; - char c = _input[_pos++]; - return c == token; - } - - private void SkipWhite() - { - while (Char.IsWhiteSpace(_input[_pos])) - _pos++; - } - } -} +// Copyright © 2015, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySqlX.XDevAPI; +using System; +using System.Collections.Generic; + +namespace MySqlX.Serialization +{ + /// + /// Main class for parsing json strings. + /// + public class JsonParser + { + private int _pos = 0; + private String _input; + + /// + /// Initializes a new instance of the JsonParser class. + /// + public JsonParser() + {} + + /// + /// Parses the received string into a dictionary. + /// + /// The string to parse. + /// A object that represents the parsed string. + public static Dictionary Parse(string s) + { + JsonParser p = new JsonParser(); + return p.ParseInternal(s); + } + + private Dictionary ParseInternal(string s) + { + _input = s; + Dictionary dic = ReadGroup(); + if (_pos != _input.Length) + throw new IndexOutOfRangeException("It's not the end of stream."); + return dic; + } + + private Dictionary ReadGroup() + { + Dictionary values = new Dictionary(); + + RequireToken('{'); + if (PeekToken() != '}') + while (true) + { + string key = ReadQuotedToken(); + if (key == null) break; + RequireToken(':'); + var obj = ReadValue(); + values[key] = obj; + if (PeekToken() == '}') break; + RequireToken(','); + } + RequireToken('}'); + return values; + } + + private object ReadValue() + { + char t = PeekToken(); + if (t == '"') return ReadQuotedToken(); + if (t == '{') return ReadGroup(); + if (t == '[') return ReadArray(); + string stringValue = ReadUntilToken(',', '}', ']'); + bool flag; + if (bool.TryParse(stringValue, out flag)) return flag; + if (stringValue.Trim() == "null") return null; + int intValue; + long longValue; + double doubleValue; + if (int.TryParse(stringValue, out intValue)) return intValue; + if (long.TryParse(stringValue, out longValue)) return longValue; + if (double.TryParse( + stringValue, + System.Globalization.NumberStyles.Any, + System.Globalization.CultureInfo.InvariantCulture, + out doubleValue)) + return doubleValue; + + // May be a function. + int openingParen = 0; + for (int i=0; i0) + { + stringValue += ReadUntilToken(')') + ")"; + RequireToken(')'); + openingParen--; + } + + return new MySqlExpression(stringValue); + } + + private object[] ReadArray() + { + List values = new List(); + + RequireToken('['); + while (true) + { + values.Add(ReadValue()); + if (PeekToken() == ']') break; + RequireToken(','); + } + RequireToken(']'); + return values.ToArray(); + } + + private char PeekToken() + { + SkipWhite(); + if (_pos == _input.Length) + throw new Exception("Unexpected end of stream found."); + return _input[_pos]; + } + + private string ReadQuotedToken() + { + RequireToken('"'); + string val = ReadUntilToken('"'); + RequireToken('"'); + return val; + } + + private bool TokenInGroup(char[] tokens, char c) + { + foreach (char token in tokens) + if (token == c) return true; + return false; + } + + private string ReadUntilToken(params char[] end) + { + string val = ""; + bool escapedQuoteExpected = false; + while (_pos < _input.Length) + { + char c = _input[_pos++]; + + if (!escapedQuoteExpected) + { + if (c == 92) + escapedQuoteExpected = true; + else if (TokenInGroup(end, c)) + { + _pos--; + return val; + } + } + else if (c == 34) + escapedQuoteExpected = false; + + val += c; + } + throw new Exception("Failed to find ending '\"' while reading stream."); + } + + private void RequireToken(char token) + { + if (!ReadToken(token)) + throw new Exception("Expected token '" + token + "'"); + } + + private bool ReadToken(char token) + { + SkipWhite(); + if (_pos == _input.Length) return false; + char c = _input[_pos++]; + return c == token; + } + + private void SkipWhite() + { + while (Char.IsWhiteSpace(_input[_pos])) + _pos++; + } + } +} diff --git a/MySQL.Data/src/X/Sessions/InternalSession.cs b/MySQL.Data/src/X/Sessions/InternalSession.cs index a8a414c71..f04de1f48 100644 --- a/MySQL.Data/src/X/Sessions/InternalSession.cs +++ b/MySQL.Data/src/X/Sessions/InternalSession.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2015, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/X/Sessions/QueueTaskScheduler.cs b/MySQL.Data/src/X/Sessions/QueueTaskScheduler.cs index 20528191c..10054750b 100644 --- a/MySQL.Data/src/X/Sessions/QueueTaskScheduler.cs +++ b/MySQL.Data/src/X/Sessions/QueueTaskScheduler.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2015, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/X/Sessions/XInternalSession.cs b/MySQL.Data/src/X/Sessions/XInternalSession.cs index c64286b34..9b7322515 100644 --- a/MySQL.Data/src/X/Sessions/XInternalSession.cs +++ b/MySQL.Data/src/X/Sessions/XInternalSession.cs @@ -1,1056 +1,1056 @@ -// Copyright (c) 2015, 2023, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySql.Data; -using MySql.Data.Common; -using MySql.Data.MySqlClient; -using MySql.Data.MySqlClient.Authentication; -using MySqlX.Communication; -using MySqlX.Protocol; -using MySqlX.Protocol.X; -using MySqlX.Security; -using MySqlX.XDevAPI; -using MySqlX.XDevAPI.Common; -using MySqlX.XDevAPI.CRUD; -using MySqlX.XDevAPI.Relational; -using System; -using System.Collections; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using System.Reflection; -using System.Text; -using System.Threading; - -namespace MySqlX.Sessions -{ - /// - /// Implementation class of InternalSession to manage connections using the Xprotocol type object. - /// - internal class XInternalSession : InternalSession - { - /// - /// Defines the compression controller that will be passed on the instance when - /// compression is enabled. - /// - private XCompressionController _readerCompressionController; - - /// - /// Defines the compression controller that will be passed on the instance when - /// compression is enabled. - /// - private XCompressionController _writerCompressionController; - - private XProtocol _protocol; - private XPacketReaderWriter _packetReaderWriter; - private bool _serverSupportsTls = false; - private const string mysqlxNamespace = "mysqlx"; - internal bool _supportsPreparedStatements = true; - private int _stmtId = 0; - private List _preparedStatements = new List(); - internal bool? _sessionResetNoReauthentication = null; - internal MyNetworkStream _myNetworkStream; - - public XInternalSession(MySqlXConnectionStringBuilder settings) : base(settings) - { - } - - protected override void Open() - { - bool isUnix = Settings.ConnectionProtocol == MySqlConnectionProtocol.Unix || - Settings.ConnectionProtocol == MySqlConnectionProtocol.UnixSocket; - - _stream = MyNetworkStream.CreateStreamAsync( - Settings.Server == "127.0.0.1" || Settings.Server == "::1" - ? "localhost" - : Settings.Server, - Settings.ConnectTimeout, - Settings.Keepalive, - Settings.Port, - isUnix, false).GetAwaiter().GetResult(); - _myNetworkStream = (MyNetworkStream)_stream; - if (_stream == null) - throw new MySqlException(ResourcesX.UnableToConnect); - - _packetReaderWriter = new XPacketReaderWriter(_stream, _myNetworkStream.Socket); - _protocol = new XProtocol(_packetReaderWriter); - - Settings.CharacterSet = string.IsNullOrWhiteSpace(Settings.CharacterSet) ? "utf8mb4" : Settings.CharacterSet; - var encoding = CharSetMap.GetEncoding(Settings.CharacterSet); - - SetState(SessionState.Connecting, false); - - try - { - GetAndSetCapabilities(); - } - catch (Exception) - { - throw; - } - - // Validates use of TLS. - if (Settings.SslMode != MySqlSslMode.Disabled) - { - if (_serverSupportsTls) - { - var result = new Ssl( - Settings.Server, - Settings.SslMode, - Settings.CertificateFile, - Settings.CertificateStoreLocation, - Settings.CertificatePassword, - Settings.CertificateThumbprint, - Settings.SslCa, - Settings.SslCert, - Settings.SslKey, - Settings.TlsVersion, - Settings.ConnectTimeout) - .StartSSLAsync(_stream, encoding, Settings.ToString(), CancellationToken.None, false).GetAwaiter().GetResult(); - - _stream = result.Item2; - - if (_readerCompressionController != null && _readerCompressionController.IsCompressionEnabled) - { - _packetReaderWriter = new XPacketReaderWriter(_stream, _readerCompressionController, _writerCompressionController, _myNetworkStream.Socket); - } - else - { - _packetReaderWriter = new XPacketReaderWriter(_stream, _myNetworkStream.Socket); - } - - _protocol.SetXPackets(_packetReaderWriter); - } - else - { - // Client requires SSL connections. - string message = String.Format(Resources.NoServerSSLSupport, - Settings.Server); - throw new MySqlException(message); - } - } - else if (_readerCompressionController != null && _readerCompressionController.IsCompressionEnabled) - { - _packetReaderWriter = new XPacketReaderWriter(_stream, _readerCompressionController, _writerCompressionController, _myNetworkStream.Socket); - _protocol.SetXPackets(_packetReaderWriter); - } - - Authenticate(); - - SetState(SessionState.Open, false); - } - - internal void Authenticate() - { - // Default authentication - if (Settings.Auth == MySqlAuthenticationMode.Default) - { - if ((Settings.SslMode != MySqlSslMode.Disabled && _serverSupportsTls) || Settings.ConnectionProtocol == MySqlConnectionProtocol.Unix) - { - Settings.Auth = MySqlAuthenticationMode.PLAIN; - AuthenticatePlain(); - } - else - { - bool authenticated = false; - // first try using MYSQL41 - Settings.Auth = MySqlAuthenticationMode.MYSQL41; - try - { - AuthenticateMySQL41(); - authenticated = true; - } - catch (MySqlException ex) - { - // code 1045 Invalid user or password - if (ex.Code != 1045) - throw; - } - - // second try using SHA256_MEMORY - if (!authenticated) - { - try - { - Settings.Auth = MySqlAuthenticationMode.SHA256_MEMORY; - AuthenticateSha256Memory(); - authenticated = true; - } - catch (MySqlException ex) - { - // code 1045 Invalid user or password - if (ex.Code == 1045) - throw new MySqlException(1045, "HY000", ResourcesX.AuthenticationFailed); - else - throw; - } - } - } - } - // User defined authentication - else - { - switch (Settings.Auth) - { - case MySqlAuthenticationMode.PLAIN: - AuthenticatePlain(); - break; - case MySqlAuthenticationMode.MYSQL41: - AuthenticateMySQL41(); - break; - case MySqlAuthenticationMode.EXTERNAL: - AuthenticateExternal(); - break; - case MySqlAuthenticationMode.SHA256_MEMORY: - AuthenticateSha256Memory(); - break; - default: - throw new NotImplementedException(Settings.Auth.ToString()); - } - } - } - - private void GetAndSetCapabilities() - { - _protocol.GetServerCapabilities(); - var clientCapabilities = new Dictionary(); - Mysqlx.Connection.Capability capability = null; - - // Validates TLS use. - if (Settings.SslMode != MySqlSslMode.Disabled) - { - capability = _protocol.Capabilities.Capabilities_.FirstOrDefault(i => i.Name.ToLowerInvariant() == "tls"); - if (capability != null) - { - _serverSupportsTls = true; - clientCapabilities.Add("tls", "1"); - } - } - - // Set connection-attributes. - if (Settings.ConnectionAttributes.ToLower() != "false") - clientCapabilities.Add("session_connect_attrs", GetConnectionAttributes(Settings.ConnectionAttributes)); - - // Set compression algorithm. - if (Settings.Compression != CompressionType.Disabled) - { - capability = _protocol.Capabilities.Capabilities_.FirstOrDefault(i => i.Name.ToLowerInvariant() == XCompressionController.COMPRESSION_KEY); - - // Raise error if client expects compression but server doesn't support it. - if (Settings.Compression == CompressionType.Required && capability == null) - { - throw new NotSupportedException(ResourcesX.CompressionNotSupportedByServer); - } - - // Update capabilities with the compression algorithm negotiation if server supports compression. - if (capability != null) - { - var algorithmsDictionary = capability.Value.Obj.Fld.ToDictionary( - field => field.Key, - field => field.Value.Array.Value.ToDictionary(value => value.Scalar.VString.Value.ToStringUtf8().ToLowerInvariant()).Keys.ToList()); - - if (algorithmsDictionary.ContainsKey(XCompressionController.ALGORITHMS_SUBKEY)) - { - var supportedCompressionAlgorithms = algorithmsDictionary[XCompressionController.ALGORITHMS_SUBKEY].ToList().ToArray(); - VerifyDefaultOrder(ref supportedCompressionAlgorithms); - var userCompressionAlgorithms = NegotiateUserAgainstClientAlgorithms(Settings.CompressionAlgorithm); - var compressionCapabilities = NegotiateCompression(supportedCompressionAlgorithms, userCompressionAlgorithms); - if (compressionCapabilities != null) - { - clientCapabilities.Add(XCompressionController.COMPRESSION_KEY, compressionCapabilities); - var compressionAlgorithm = compressionCapabilities.First().Value.ToString(); - _readerCompressionController = new XCompressionController((CompressionAlgorithms)Enum.Parse(typeof(CompressionAlgorithms), compressionAlgorithm), false); - _writerCompressionController = new XCompressionController((CompressionAlgorithms)Enum.Parse(typeof(CompressionAlgorithms), compressionAlgorithm), true); - _packetReaderWriter = new XPacketReaderWriter(_stream, _readerCompressionController, _writerCompressionController, _myNetworkStream.Socket); - - } - } - } - } - - try - { - _protocol.SetCapabilities(clientCapabilities); - } - catch (MySqlException ex) - { - if (ex.Message == "Capability 'session_connect_attrs' doesn't exist") - clientCapabilities.Remove("session_connect_attrs"); - _protocol.SetCapabilities(clientCapabilities); - } - } - - /// - /// Reorder the list of algorithms retrieved from server to the preferred order - /// - private void VerifyDefaultOrder(ref string[] algorithms) - { - var clientSupportedAlgorithms = Enum.GetNames(typeof(CompressionAlgorithms)); - List output = new List(); - foreach (var item in clientSupportedAlgorithms) - { - if (algorithms.Contains(item)) - { - output.Add(item); - } - } - algorithms = output.ToArray(); - } - - /// - /// Validate the algorithms given in the connection string are valid compared with enum CompressionAlgorithms - /// - public List NegotiateUserAgainstClientAlgorithms(string inputString) - { - inputString = inputString.Contains("[") ? inputString.Replace("[", string.Empty) : inputString; - inputString = inputString.Contains("]") ? inputString.Replace("]", string.Empty) : inputString; - inputString.Trim(); - if (string.IsNullOrEmpty(inputString)) - { - return Enum.GetNames(typeof(CompressionAlgorithms)).ToList(); - } - var elements = inputString.ToLowerInvariant().Split(','); - List ret = new List(); - for (var i = 0; i < elements.Length; i++) - { - switch (elements[i].ToLowerInvariant()) - { - case "lz4": - case "lz4_message": - elements[i] = CompressionAlgorithms.lz4_message.ToString(); - break; - case "zstd": - case "zstd_stream": - elements[i] = CompressionAlgorithms.zstd_stream.ToString(); - break; - - case "deflate": - case "deflate_stream": -#if NETFRAMEWORK - if (elements.Length == 1 && Settings.Compression == CompressionType.Required) - { - throw new NotSupportedException(string.Format(ResourcesX.CompressionForSpecificAlgorithmNotSupportedInNetFramework, elements[i])); - } -#else - elements[i] = CompressionAlgorithms.deflate_stream.ToString(); -#endif - break; - - } - if (Enum.IsDefined(typeof(CompressionAlgorithms), elements[i])) - { - ret.Add(elements[i]); - } - } - return ret; - } - - /// - /// Negotiates compression capabilities with the server. - /// - /// An array containing the compression algorithms supported by the server. - /// An array containing the compression algorithms given by user/client. - private Dictionary NegotiateCompression(string[] serverSupportedAlgorithms, List clientAgainstUserAlgorithms) - { - if (serverSupportedAlgorithms == null || serverSupportedAlgorithms.Length == 0) - { - if (Settings.Compression == CompressionType.Required && clientAgainstUserAlgorithms.Count > 0) - { - throw new NotSupportedException(ResourcesX.CompressionAlgorithmNegotiationFailed); - } - return null; - } - - // If server and client don't have matching compression algorithms either log a warning message - // or raise an exception based on the selected compression type. - if (!clientAgainstUserAlgorithms.Any(element => serverSupportedAlgorithms.Contains(element))) - { - if (Settings.Compression == CompressionType.Preferred) - { - MySqlTrace.LogWarning(-1, ResourcesX.CompressionAlgorithmNegotiationFailed); - return null; - } - else if (Settings.Compression == CompressionType.Required) - { - throw new NotSupportedException(ResourcesX.CompressionAlgorithmNegotiationFailed); - } - } - - string negotiatedAlgorithm = null; - for (int index = 0; index < clientAgainstUserAlgorithms.Count; index++) - { - if (!serverSupportedAlgorithms.Contains(clientAgainstUserAlgorithms[index])) - { - continue; - } - - negotiatedAlgorithm = clientAgainstUserAlgorithms[index]; - break; - } - - if (negotiatedAlgorithm == null) - { - return null; - } - - // Create the compression capability object. - var compressionCapabilities = new Dictionary(); - compressionCapabilities.Add(XCompressionController.ALGORITHMS_SUBKEY, negotiatedAlgorithm); - compressionCapabilities.Add(XCompressionController.SERVER_COMBINE_MIXED_MESSAGES_SUBKEY, XCompressionController.DEFAULT_SERVER_COMBINE_MIXED_MESSAGES_VALUE); - - // TODO: For future use. - //compressionCapabilities.Add(XCompressionController.SERVER_MAX_COMBINE_MESSAGES_SUBKEY, XCompressionController.DEFAULT_SERVER_MAX_COMBINE_MESSAGES_VALUE); - - return compressionCapabilities; - } - - private Dictionary GetConnectionAttributes(string connectionAttrs) - { - Dictionary attrs = new Dictionary(); - - if (connectionAttrs.StartsWith("[") && connectionAttrs.EndsWith("]")) - { - connectionAttrs = connectionAttrs.Substring(1, connectionAttrs.Length - 2); - - if (!string.IsNullOrWhiteSpace(connectionAttrs)) - { - foreach (var pair in connectionAttrs.Split(',')) - { - string[] keyValue = pair.Split('='); - string key = keyValue[0].Trim(); - string value = keyValue.Length > 1 ? keyValue[1].Trim() : string.Empty; - - if (key == string.Empty) - throw new MySqlException(ResourcesX.EmptyKeyConnectionAttribute); - - if (key.StartsWith("_")) - throw new MySqlException(ResourcesX.InvalidUserDefinedAttribute); - - try { attrs.Add(key, value); } - catch (ArgumentException) { throw new MySqlException(string.Format(ResourcesX.DuplicateUserDefinedAttribute, key)); } - } - } - } - else if (connectionAttrs != "true") - throw new MySqlException(ResourcesX.InvalidConnectionAttributes); - - MySqlConnectAttrs clientAttrs = new MySqlConnectAttrs(); - attrs.Add("_pid", clientAttrs.PID); - attrs.Add("_platform", clientAttrs.Platform); - attrs.Add("_os", clientAttrs.OSName); - attrs.Add("_source_host", Settings.Server); - attrs.Add("_client_name", clientAttrs.ClientName); - attrs.Add("_client_version", clientAttrs.ClientVersion); - attrs.Add("_client_license", clientAttrs.ClientLicence); - attrs.Add("_framework", clientAttrs.Framework); - - return attrs; - } - - private void AuthenticateMySQL41() - { - MySQL41AuthenticationPlugin plugin = new MySQL41AuthenticationPlugin(Settings); - _protocol.SendAuthStart(plugin.AuthName, null, null); - byte[] extraData = _protocol.ReadAuthContinue(); - _protocol.SendAuthContinue(plugin.Continue(extraData)); - _protocol.ReadAuthOk(); - } - - private void AuthenticatePlain() - { - PlainAuthenticationPlugin plugin = new PlainAuthenticationPlugin(Settings); - _protocol.SendAuthStart(plugin.AuthName, plugin.GetAuthData(), null); - _protocol.ReadAuthOk(); - } - - private void AuthenticateExternal() - { - ExternalAuthenticationPlugin plugin = new ExternalAuthenticationPlugin(Settings); - _protocol.SendAuthStart(plugin.AuthName, Encoding.UTF8.GetBytes(""), null); - _protocol.ReadAuthOk(); - } - - private void AuthenticateSha256Memory() - { - Sha256MemoryAuthenticationPlugin plugin = new Sha256MemoryAuthenticationPlugin(); - _protocol.SendAuthStart(plugin.PluginName, null, null); - byte[] nonce = _protocol.ReadAuthContinue(); - - string data = $"{Settings.Database}\0{Settings.UserID}\0"; - byte[] byteData = Encoding.UTF8.GetBytes(data); - byte[] clientHash = plugin.GetClientHash(Settings.Password, nonce); - byte[] authData = new byte[byteData.Length + clientHash.Length]; - byteData.CopyTo(authData, 0); - clientHash.CopyTo(authData, byteData.Length); - - _protocol.SendAuthContinue(authData); - _protocol.ReadAuthOk(); - } - - protected internal void SetState(SessionState newState, bool broadcast) - { - if (newState == SessionState && !broadcast) - return; - SessionState oldSessionState = SessionState; - SessionState = newState; - - //TODO check if we need to send this event - //if (broadcast) - //OnStateChange(new StateChangeEventArgs(oldConnectionState, connectionState)); - } - - internal override ProtocolBase GetProtocol() - { - return _protocol; - } - - public override void Close() - { - try - { - try - { - // Deallocate compression objects. - _readerCompressionController?.Close(); - _writerCompressionController?.Close(); - - // Deallocate all the remaining prepared statements for current session. - foreach (int stmtId in _preparedStatements) - { - if (!_myNetworkStream.IsSocketClosed) - { - DeallocatePreparedStatement(stmtId); - } - _preparedStatements.Remove(stmtId); - } - } - catch (Exception) - { - //TODO log exception - } - - if (!_myNetworkStream.IsSocketClosed) - { - _protocol.SendSessionClose(); - } - } - finally - { - SessionState = SessionState.Closed; - _stream.Dispose(); - } - } - - public void CreateCollection(string schemaName, string collectionName) - { - ExecuteCmdNonQuery(XpluginStatementCommand.XPLUGIN_STMT_CREATE_COLLECTION, - true, - new KeyValuePair("schema", schemaName), - new KeyValuePair("name", collectionName)); - } - - /// - /// Prepare the dictionary of arguments required to create a MySQL message. - /// - /// The name of the MySQL schema. - /// The name of the collection. - /// This object hold the parameters required to create the collection. - /// - /// Collection referente. - public void CreateCollection(string schemaName, string collectionName, CreateCollectionOptions options) - { - var dictionary = new Dictionary(); - if (!options.Equals(null)) - { - if (!string.IsNullOrEmpty(options.Validation.Level.ToString())) - { - dictionary.Add("level", (string)options.Validation.Level.ToString().ToLowerInvariant()); - } - - if (!string.IsNullOrEmpty(options.Validation.Schema)) - { - dictionary.Add("schema", new DbDoc(options.Validation.Schema)); - } - } - - ExecuteCmdNonQueryOptions(XpluginStatementCommand.XPLUGIN_STMT_CREATE_COLLECTION, - true, - new KeyValuePair("schema", schemaName), - new KeyValuePair("name", collectionName), - new KeyValuePair("reuse_existing", options.ReuseExisting), - new KeyValuePair("options", dictionary) - ); - } - - /// - /// Prepare the dictionary of arguments required to Modify a MySQL message. - /// - /// The name of the MySQL schema. - /// The name of the collection. - /// This object hold the parameters required to Modify the collection. - /// - public void ModifyCollection(string schemaName, string collectionName, ModifyCollectionOptions? options) - { - var dictionary = new Dictionary(); - if (!options.Equals(null)) - { - if (options.Value.Validation.Level != null) - { - dictionary.Add("level", options.Value.Validation.Level.ToString().ToLowerInvariant()); - } - if (options.Value.Validation.Schema != null) - { - dictionary.Add("schema", new DbDoc(options.Value.Validation.Schema)); - } - } - ExecuteCmdNonQueryOptions(XpluginStatementCommand.XPLUGIN_STMT_MODIFY_COLLECTION, - true, - new KeyValuePair("schema", schemaName), - new KeyValuePair("name", collectionName), - new KeyValuePair("options", dictionary)); - } - - public void DropCollection(string schemaName, string collectionName) - { - ExecuteCmdNonQuery(XpluginStatementCommand.XPLUGIN_STMT_DROP_COLLECTION, - true, - new KeyValuePair("schema", schemaName), - new KeyValuePair("name", collectionName)); - } - - public Result CreateCollectionIndex(CreateCollectionIndexStatement statement) - { - List> args = new List>(); - args.Add(new KeyValuePair("name", statement.createIndexParams.IndexName)); - args.Add(new KeyValuePair("collection", statement.Target.Name)); - args.Add(new KeyValuePair("schema", statement.Target.Schema.Name)); - args.Add(new KeyValuePair("unique", false)); - - if (statement.createIndexParams.Type != null) - args.Add(new KeyValuePair("type", statement.createIndexParams.Type)); - - for (int i = 0; i < statement.createIndexParams.Fields.Count; i++) - { - var field = statement.createIndexParams.Fields[i]; - var dictionary = new Dictionary(); - dictionary.Add("member", field.Field); - if (field.Type != null) - dictionary.Add("type", field.Type); - - if (field.Required == null) - dictionary.Add("required", false); - else - dictionary.Add("required", (bool)field.Required); - - if (field.Options != null) - dictionary.Add("options", (ulong)field.Options); - - if (field.Srid != null) - dictionary.Add("srid", (ulong)field.Srid); - - if (field.Array != null) - dictionary.Add("array", (bool)field.Array); - - args.Add(new KeyValuePair("constraint", dictionary)); - } - - return ExecuteCreateCollectionIndex(XpluginStatementCommand.XPLUGIN_STMT_CREATE_COLLECTION_INDEX, false, args.ToArray()); - } - - public void DropCollectionIndex(string schemaName, string collectionName, string indexName) - { - List> args = new List>(); - args.Add(new KeyValuePair("schema", schemaName)); - args.Add(new KeyValuePair("collection", collectionName)); - args.Add(new KeyValuePair("name", indexName)); - ExecuteCmdNonQuery(XpluginStatementCommand.XPLUGIN_STMT_DROP_COLLECTION_INDEX, false, args.ToArray()); - } - - public long TableCount(Schema schema, string name, string type) - { - try - { - string sql = String.Format("SELECT COUNT(*) FROM {0}.{1}", - ExprUnparser.QuoteIdentifier(schema.Name), ExprUnparser.QuoteIdentifier(name)); - return (long)ExecuteQueryAsScalar(sql); - } - catch (MySqlException ex) when (ex.Code == 1146) - { - throw new MySqlException(string.Format(ResourcesX.CollectionTableDoesNotExist, type.ToString(), name, schema.Name), (int)ex.Code); - } - } - - public bool TableExists(Schema schema, string name) - { - string sql = String.Format("SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = '{0}' AND table_name = '{1}'", - schema.Name, name); - long count = (long)ExecuteQueryAsScalar(sql); - return count != 0; - } - - private Result ExecuteCmdNonQuery(string cmd, bool throwOnFail, params KeyValuePair[] args) - { - _protocol.SendExecuteStatement(mysqlxNamespace, cmd, args); - return new Result(this); - } - - private Result ExecuteCmdNonQueryOptions(string cmd, bool throwOnFail, params KeyValuePair[] args) - { - _protocol.SendExecuteStatementOptions(mysqlxNamespace, cmd, args); - return new Result(this); - } - - private Result ExecuteCreateCollectionIndex(string cmd, bool throwOnFail, params KeyValuePair[] args) - { - _protocol.SendCreateCollectionIndexStatement(mysqlxNamespace, cmd, args); - return new Result(this); - } - - public List GetObjectList(Schema s, params string[] types) where T : DatabaseObject - { - for (int i = 0; i < types.Length; i++) - types[i] = types[i].ToUpperInvariant(); - RowResult result = GetRowResult("list_objects", new KeyValuePair("schema", s.Name)); - var rows = result.FetchAll(); - - List docs = new List(); - foreach (var row in rows) - { - if (!types.Contains(row.GetString("type").ToUpperInvariant())) continue; - - List parameters = new List(new object[] { s, row.GetString("name") }); - if (row["name"] is Byte[]) - { - Byte[] byteArray = row["name"] as Byte[]; - parameters[1] = Encoding.UTF8.GetString(byteArray, 0, byteArray.Length); - } - - switch (row.GetString("type").ToUpperInvariant()) - { - case "TABLE": - parameters.Add(false); - break; - case "VIEW": - parameters.Add(true); - break; - } - T t = (T)Activator.CreateInstance(typeof(T), - BindingFlags.NonPublic | BindingFlags.Instance, - null, parameters.ToArray(), null); - docs.Add(t); - } - return docs; - } - - public string GetObjectType(Schema s, string name) - { - RowResult result = GetRowResult("list_objects", - new KeyValuePair("schema", s.Name), - new KeyValuePair("pattern", name)); - var row = result.FetchOne(); - if (row == null) - throw new MySqlException(string.Format(ResourcesX.NoObjectFound, name)); - System.Diagnostics.Debug.Assert(result.FetchOne() == null); - return row.GetString("type"); - } - - public RowResult GetRowResult(string cmd, params KeyValuePair[] args) - { - _protocol.SendExecuteStatement(mysqlxNamespace, cmd, args); - return new RowResult(this); - } - - public Result Insert(Collection collection, object[] json, List newIds, bool upsert) - { - _protocol.SendInsert(collection.Schema.Name, false, collection.Name, json, null, upsert); - return new Result(this); - } - - public Result DeleteDocs(RemoveStatement rs) - { - _protocol.SendDelete(rs.Target.Schema.Name, rs.Target.Name, false, rs.FilterData); - return new Result(this); - } - - public Result DeleteRows(TableDeleteStatement statement) - { - _protocol.SendDelete(statement.Target.Schema.Name, - statement.Target.Name, true, - statement.FilterData); - return new Result(this); - } - - public Result ModifyDocs(ModifyStatement ms) - { - _protocol.SendUpdate(ms.Target.Schema.Name, ms.Target.Name, false, ms.FilterData, ms.Updates); - return new Result(this); - } - - public Result UpdateRows(TableUpdateStatement statement) - { - _protocol.SendUpdate(statement.Target.Schema.Name, - statement.Target.Name, true, - statement.FilterData, - statement.updates); - return new Result(this); - } - - public DocResult FindDocs(FindStatement fs) - { - _protocol.SendFind(fs.Target.Schema.Name, fs.Target.Name, false, fs.FilterData, fs.findParams); - DocResult result = new DocResult(this); - return result; - } - - public RowResult FindRows(TableSelectStatement ss) - { - _protocol.SendFind(ss.Target.Schema.Name, ss.Target.Name, true, ss.FilterData, ss.findParams); - return new RowResult(this); - } - - public Result InsertRows(TableInsertStatement statement) - { - _protocol.SendInsert(statement.Target.Schema.Name, true, statement.Target.Name, statement.values.ToArray(), statement.fields, false); - return new Result(this); - } - - protected Result ExpectOpen(Mysqlx.Expect.Open.Types.Condition.Types.Key condition, object value = null) - { - _protocol.SendExpectOpen(condition, value); - return new Result(this); - } - - public Result ExpectDocidGenerated() - { - return ExpectOpen(Mysqlx.Expect.Open.Types.Condition.Types.Key.ExpectDocidGenerated); - } - - public void ResetSession() - { - if (_sessionResetNoReauthentication == null) - { - try - { - if (!_myNetworkStream.IsSocketClosed) - { - ExpectOpen(Mysqlx.Expect.Open.Types.Condition.Types.Key.ExpectFieldExist, "6.1"); - } - _sessionResetNoReauthentication = true; - } - catch - { - _sessionResetNoReauthentication = false; - } - } - - if (!_myNetworkStream.IsSocketClosed) - { - _protocol.SendResetSession((bool)_sessionResetNoReauthentication); - _protocol.ReadOk(); - } - } - - public int PrepareStatement(BaseStatement statement) - where TResult : BaseResult - { - int stmtId = Interlocked.Increment(ref _stmtId); - string stmtType = statement.GetType().Name; - - if (stmtType == typeof(FindStatement<>).Name) - { - FindStatement fs = statement as FindStatement; - string s = typeof(TDoc).Name; - Debug.Assert(fs != null); - _protocol.SendPrepareStatement( - (uint)stmtId, - DataAccess.PreparedStatementType.Find, - fs.Target.Schema.Name, - fs.Target.Name, - false, - fs.FilterData, - fs.findParams); - } - else if (stmtType == typeof(TableSelectStatement).Name) - { - TableSelectStatement ss = statement as TableSelectStatement; - Debug.Assert(ss != null); - _protocol.SendPrepareStatement( - (uint)stmtId, - DataAccess.PreparedStatementType.Find, - ss.Target.Schema.Name, - ss.Target.Name, - true, - ss.FilterData, - ss.findParams); - } - else if (stmtType == typeof(ModifyStatement<>).Name) - { - ModifyStatement ms = statement as ModifyStatement; - Debug.Assert(ms != null); - _protocol.SendPrepareStatement( - (uint)stmtId, - DataAccess.PreparedStatementType.Update, - ms.Target.Schema.Name, - ms.Target.Name, - false, - ms.FilterData, - null, - ms.Updates); - } - else if (stmtType == typeof(TableUpdateStatement).Name) - { - TableUpdateStatement us = statement as TableUpdateStatement; - Debug.Assert(us != null); - _protocol.SendPrepareStatement( - (uint)stmtId, - DataAccess.PreparedStatementType.Update, - us.Target.Schema.Name, - us.Target.Name, - true, - us.FilterData, - null, - us.updates); - } - else if (stmtType == typeof(RemoveStatement<>).Name) - { - string s = typeof(TDoc).Name; - RemoveStatement rs = statement as RemoveStatement; - Debug.Assert(rs != null); - _protocol.SendPrepareStatement( - (uint)stmtId, - DataAccess.PreparedStatementType.Delete, - rs.Target.Schema.Name, - rs.Target.Name, - false, - rs.FilterData, - null); - } - else if (stmtType == typeof(TableDeleteStatement).Name) - { - TableDeleteStatement ds = statement as TableDeleteStatement; - Debug.Assert(ds != null); - _protocol.SendPrepareStatement( - (uint)stmtId, - DataAccess.PreparedStatementType.Delete, - ds.Target.Schema.Name, - ds.Target.Name, - true, - ds.FilterData, - null); - } - else if (stmtType == typeof(TableInsertStatement).Name) - { - TableInsertStatement insert = statement as TableInsertStatement; - Debug.Assert(insert != null); - _protocol.SendPrepareStatement( - (uint)stmtId, - DataAccess.PreparedStatementType.Insert, - insert.Target.Schema.Name, - insert.Target.Name, - true, - null, - null, - null, - insert.values.ToArray(), - insert.fields, - false); - } - else if (stmtType == typeof(SqlStatement).Name) - { - SqlStatement sqlStatement = statement as SqlStatement; - Debug.Assert(sqlStatement != null); - _protocol.SendPrepareStatement( - (uint)stmtId, - DataAccess.PreparedStatementType.SqlStatement, - null, - null, - true, - null, - null, - null, - sqlStatement.parameters.ToArray(), - null, - false, - sqlStatement.SQL); - } - else - { - throw new NotSupportedException(statement.GetType().Name); - } - - _preparedStatements.Add(stmtId); - return stmtId; - } - - public TResult ExecutePreparedStatement(int stmtId, IEnumerable args) - where TResult : BaseResult - { - _protocol.SendExecutePreparedStatement((uint)stmtId, args); - BaseResult result = null; - if (typeof(TResult) == typeof(DocResult)) - result = new DocResult(this); - else if (typeof(TResult) == typeof(RowResult)) - result = new RowResult(this); - else if (typeof(TResult) == typeof(SqlResult)) - result = new SqlResult(this); - else if (typeof(TResult) == typeof(Result)) - result = new Result(this); - else - throw new ArgumentNullException(typeof(TResult).Name); - - return (TResult)result; - } - - public void DeallocatePreparedStatement(int stmtId) - { - _protocol.SendDeallocatePreparedStatement((uint)stmtId); - _preparedStatements.Remove(stmtId); - } - - /// - /// Gets the compression algorithm being used to compress or decompress data. - /// - /// Flag to indicate if the compression algorithm should be - /// retrieved from the reader or writer controller. - /// The name of the compression algorithm being used if any. - /// null if no compression algorithm is being used. - public string GetCompressionAlgorithm(bool fromReaderController) - { - if (fromReaderController && _readerCompressionController != null) - { - return _readerCompressionController.CompressionAlgorithm.ToString(); - } - else if (!fromReaderController && _writerCompressionController != null) - { - return _writerCompressionController.CompressionAlgorithm.ToString(); - } - - return null; - } - } -} +// Copyright © 2015, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySql.Data; +using MySql.Data.Common; +using MySql.Data.MySqlClient; +using MySql.Data.MySqlClient.Authentication; +using MySqlX.Communication; +using MySqlX.Protocol; +using MySqlX.Protocol.X; +using MySqlX.Security; +using MySqlX.XDevAPI; +using MySqlX.XDevAPI.Common; +using MySqlX.XDevAPI.CRUD; +using MySqlX.XDevAPI.Relational; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading; + +namespace MySqlX.Sessions +{ + /// + /// Implementation class of InternalSession to manage connections using the Xprotocol type object. + /// + internal class XInternalSession : InternalSession + { + /// + /// Defines the compression controller that will be passed on the instance when + /// compression is enabled. + /// + private XCompressionController _readerCompressionController; + + /// + /// Defines the compression controller that will be passed on the instance when + /// compression is enabled. + /// + private XCompressionController _writerCompressionController; + + private XProtocol _protocol; + private XPacketReaderWriter _packetReaderWriter; + private bool _serverSupportsTls = false; + private const string mysqlxNamespace = "mysqlx"; + internal bool _supportsPreparedStatements = true; + private int _stmtId = 0; + private List _preparedStatements = new List(); + internal bool? _sessionResetNoReauthentication = null; + internal MyNetworkStream _myNetworkStream; + + public XInternalSession(MySqlXConnectionStringBuilder settings) : base(settings) + { + } + + protected override void Open() + { + bool isUnix = Settings.ConnectionProtocol == MySqlConnectionProtocol.Unix || + Settings.ConnectionProtocol == MySqlConnectionProtocol.UnixSocket; + + _stream = MyNetworkStream.CreateStreamAsync( + Settings.Server == "127.0.0.1" || Settings.Server == "::1" + ? "localhost" + : Settings.Server, + Settings.ConnectTimeout, + Settings.Keepalive, + Settings.Port, + isUnix, false).GetAwaiter().GetResult(); + _myNetworkStream = (MyNetworkStream)_stream; + if (_stream == null) + throw new MySqlException(ResourcesX.UnableToConnect); + + _packetReaderWriter = new XPacketReaderWriter(_stream, _myNetworkStream.Socket); + _protocol = new XProtocol(_packetReaderWriter); + + Settings.CharacterSet = string.IsNullOrWhiteSpace(Settings.CharacterSet) ? "utf8mb4" : Settings.CharacterSet; + var encoding = CharSetMap.GetEncoding(Settings.CharacterSet); + + SetState(SessionState.Connecting, false); + + try + { + GetAndSetCapabilities(); + } + catch (Exception) + { + throw; + } + + // Validates use of TLS. + if (Settings.SslMode != MySqlSslMode.Disabled) + { + if (_serverSupportsTls) + { + var result = new Ssl( + Settings.Server, + Settings.SslMode, + Settings.CertificateFile, + Settings.CertificateStoreLocation, + Settings.CertificatePassword, + Settings.CertificateThumbprint, + Settings.SslCa, + Settings.SslCert, + Settings.SslKey, + Settings.TlsVersion, + Settings.ConnectTimeout) + .StartSSLAsync(_stream, encoding, Settings.ToString(), CancellationToken.None, false).GetAwaiter().GetResult(); + + _stream = result.Item2; + + if (_readerCompressionController != null && _readerCompressionController.IsCompressionEnabled) + { + _packetReaderWriter = new XPacketReaderWriter(_stream, _readerCompressionController, _writerCompressionController, _myNetworkStream.Socket); + } + else + { + _packetReaderWriter = new XPacketReaderWriter(_stream, _myNetworkStream.Socket); + } + + _protocol.SetXPackets(_packetReaderWriter); + } + else + { + // Client requires SSL connections. + string message = String.Format(Resources.NoServerSSLSupport, + Settings.Server); + throw new MySqlException(message); + } + } + else if (_readerCompressionController != null && _readerCompressionController.IsCompressionEnabled) + { + _packetReaderWriter = new XPacketReaderWriter(_stream, _readerCompressionController, _writerCompressionController, _myNetworkStream.Socket); + _protocol.SetXPackets(_packetReaderWriter); + } + + Authenticate(); + + SetState(SessionState.Open, false); + } + + internal void Authenticate() + { + // Default authentication + if (Settings.Auth == MySqlAuthenticationMode.Default) + { + if ((Settings.SslMode != MySqlSslMode.Disabled && _serverSupportsTls) || Settings.ConnectionProtocol == MySqlConnectionProtocol.Unix) + { + Settings.Auth = MySqlAuthenticationMode.PLAIN; + AuthenticatePlain(); + } + else + { + bool authenticated = false; + // first try using MYSQL41 + Settings.Auth = MySqlAuthenticationMode.MYSQL41; + try + { + AuthenticateMySQL41(); + authenticated = true; + } + catch (MySqlException ex) + { + // code 1045 Invalid user or password + if (ex.Code != 1045) + throw; + } + + // second try using SHA256_MEMORY + if (!authenticated) + { + try + { + Settings.Auth = MySqlAuthenticationMode.SHA256_MEMORY; + AuthenticateSha256Memory(); + authenticated = true; + } + catch (MySqlException ex) + { + // code 1045 Invalid user or password + if (ex.Code == 1045) + throw new MySqlException(1045, "HY000", ResourcesX.AuthenticationFailed); + else + throw; + } + } + } + } + // User defined authentication + else + { + switch (Settings.Auth) + { + case MySqlAuthenticationMode.PLAIN: + AuthenticatePlain(); + break; + case MySqlAuthenticationMode.MYSQL41: + AuthenticateMySQL41(); + break; + case MySqlAuthenticationMode.EXTERNAL: + AuthenticateExternal(); + break; + case MySqlAuthenticationMode.SHA256_MEMORY: + AuthenticateSha256Memory(); + break; + default: + throw new NotImplementedException(Settings.Auth.ToString()); + } + } + } + + private void GetAndSetCapabilities() + { + _protocol.GetServerCapabilities(); + var clientCapabilities = new Dictionary(); + Mysqlx.Connection.Capability capability = null; + + // Validates TLS use. + if (Settings.SslMode != MySqlSslMode.Disabled) + { + capability = _protocol.Capabilities.Capabilities_.FirstOrDefault(i => i.Name.ToLowerInvariant() == "tls"); + if (capability != null) + { + _serverSupportsTls = true; + clientCapabilities.Add("tls", "1"); + } + } + + // Set connection-attributes. + if (Settings.ConnectionAttributes.ToLower() != "false") + clientCapabilities.Add("session_connect_attrs", GetConnectionAttributes(Settings.ConnectionAttributes)); + + // Set compression algorithm. + if (Settings.Compression != CompressionType.Disabled) + { + capability = _protocol.Capabilities.Capabilities_.FirstOrDefault(i => i.Name.ToLowerInvariant() == XCompressionController.COMPRESSION_KEY); + + // Raise error if client expects compression but server doesn't support it. + if (Settings.Compression == CompressionType.Required && capability == null) + { + throw new NotSupportedException(ResourcesX.CompressionNotSupportedByServer); + } + + // Update capabilities with the compression algorithm negotiation if server supports compression. + if (capability != null) + { + var algorithmsDictionary = capability.Value.Obj.Fld.ToDictionary( + field => field.Key, + field => field.Value.Array.Value.ToDictionary(value => value.Scalar.VString.Value.ToStringUtf8().ToLowerInvariant()).Keys.ToList()); + + if (algorithmsDictionary.ContainsKey(XCompressionController.ALGORITHMS_SUBKEY)) + { + var supportedCompressionAlgorithms = algorithmsDictionary[XCompressionController.ALGORITHMS_SUBKEY].ToList().ToArray(); + VerifyDefaultOrder(ref supportedCompressionAlgorithms); + var userCompressionAlgorithms = NegotiateUserAgainstClientAlgorithms(Settings.CompressionAlgorithm); + var compressionCapabilities = NegotiateCompression(supportedCompressionAlgorithms, userCompressionAlgorithms); + if (compressionCapabilities != null) + { + clientCapabilities.Add(XCompressionController.COMPRESSION_KEY, compressionCapabilities); + var compressionAlgorithm = compressionCapabilities.First().Value.ToString(); + _readerCompressionController = new XCompressionController((CompressionAlgorithms)Enum.Parse(typeof(CompressionAlgorithms), compressionAlgorithm), false); + _writerCompressionController = new XCompressionController((CompressionAlgorithms)Enum.Parse(typeof(CompressionAlgorithms), compressionAlgorithm), true); + _packetReaderWriter = new XPacketReaderWriter(_stream, _readerCompressionController, _writerCompressionController, _myNetworkStream.Socket); + + } + } + } + } + + try + { + _protocol.SetCapabilities(clientCapabilities); + } + catch (MySqlException ex) + { + if (ex.Message == "Capability 'session_connect_attrs' doesn't exist") + clientCapabilities.Remove("session_connect_attrs"); + _protocol.SetCapabilities(clientCapabilities); + } + } + + /// + /// Reorder the list of algorithms retrieved from server to the preferred order + /// + private void VerifyDefaultOrder(ref string[] algorithms) + { + var clientSupportedAlgorithms = Enum.GetNames(typeof(CompressionAlgorithms)); + List output = new List(); + foreach (var item in clientSupportedAlgorithms) + { + if (algorithms.Contains(item)) + { + output.Add(item); + } + } + algorithms = output.ToArray(); + } + + /// + /// Validate the algorithms given in the connection string are valid compared with enum CompressionAlgorithms + /// + public List NegotiateUserAgainstClientAlgorithms(string inputString) + { + inputString = inputString.Contains("[") ? inputString.Replace("[", string.Empty) : inputString; + inputString = inputString.Contains("]") ? inputString.Replace("]", string.Empty) : inputString; + inputString.Trim(); + if (string.IsNullOrEmpty(inputString)) + { + return Enum.GetNames(typeof(CompressionAlgorithms)).ToList(); + } + var elements = inputString.ToLowerInvariant().Split(','); + List ret = new List(); + for (var i = 0; i < elements.Length; i++) + { + switch (elements[i].ToLowerInvariant()) + { + case "lz4": + case "lz4_message": + elements[i] = CompressionAlgorithms.lz4_message.ToString(); + break; + case "zstd": + case "zstd_stream": + elements[i] = CompressionAlgorithms.zstd_stream.ToString(); + break; + + case "deflate": + case "deflate_stream": +#if NETFRAMEWORK + if (elements.Length == 1 && Settings.Compression == CompressionType.Required) + { + throw new NotSupportedException(string.Format(ResourcesX.CompressionForSpecificAlgorithmNotSupportedInNetFramework, elements[i])); + } +#else + elements[i] = CompressionAlgorithms.deflate_stream.ToString(); +#endif + break; + + } + if (Enum.IsDefined(typeof(CompressionAlgorithms), elements[i])) + { + ret.Add(elements[i]); + } + } + return ret; + } + + /// + /// Negotiates compression capabilities with the server. + /// + /// An array containing the compression algorithms supported by the server. + /// An array containing the compression algorithms given by user/client. + private Dictionary NegotiateCompression(string[] serverSupportedAlgorithms, List clientAgainstUserAlgorithms) + { + if (serverSupportedAlgorithms == null || serverSupportedAlgorithms.Length == 0) + { + if (Settings.Compression == CompressionType.Required && clientAgainstUserAlgorithms.Count > 0) + { + throw new NotSupportedException(ResourcesX.CompressionAlgorithmNegotiationFailed); + } + return null; + } + + // If server and client don't have matching compression algorithms either log a warning message + // or raise an exception based on the selected compression type. + if (!clientAgainstUserAlgorithms.Any(element => serverSupportedAlgorithms.Contains(element))) + { + if (Settings.Compression == CompressionType.Preferred) + { + MySqlTrace.LogWarning(-1, ResourcesX.CompressionAlgorithmNegotiationFailed); + return null; + } + else if (Settings.Compression == CompressionType.Required) + { + throw new NotSupportedException(ResourcesX.CompressionAlgorithmNegotiationFailed); + } + } + + string negotiatedAlgorithm = null; + for (int index = 0; index < clientAgainstUserAlgorithms.Count; index++) + { + if (!serverSupportedAlgorithms.Contains(clientAgainstUserAlgorithms[index])) + { + continue; + } + + negotiatedAlgorithm = clientAgainstUserAlgorithms[index]; + break; + } + + if (negotiatedAlgorithm == null) + { + return null; + } + + // Create the compression capability object. + var compressionCapabilities = new Dictionary(); + compressionCapabilities.Add(XCompressionController.ALGORITHMS_SUBKEY, negotiatedAlgorithm); + compressionCapabilities.Add(XCompressionController.SERVER_COMBINE_MIXED_MESSAGES_SUBKEY, XCompressionController.DEFAULT_SERVER_COMBINE_MIXED_MESSAGES_VALUE); + + // TODO: For future use. + //compressionCapabilities.Add(XCompressionController.SERVER_MAX_COMBINE_MESSAGES_SUBKEY, XCompressionController.DEFAULT_SERVER_MAX_COMBINE_MESSAGES_VALUE); + + return compressionCapabilities; + } + + private Dictionary GetConnectionAttributes(string connectionAttrs) + { + Dictionary attrs = new Dictionary(); + + if (connectionAttrs.StartsWith("[") && connectionAttrs.EndsWith("]")) + { + connectionAttrs = connectionAttrs.Substring(1, connectionAttrs.Length - 2); + + if (!string.IsNullOrWhiteSpace(connectionAttrs)) + { + foreach (var pair in connectionAttrs.Split(',')) + { + string[] keyValue = pair.Split('='); + string key = keyValue[0].Trim(); + string value = keyValue.Length > 1 ? keyValue[1].Trim() : string.Empty; + + if (key == string.Empty) + throw new MySqlException(ResourcesX.EmptyKeyConnectionAttribute); + + if (key.StartsWith("_")) + throw new MySqlException(ResourcesX.InvalidUserDefinedAttribute); + + try { attrs.Add(key, value); } + catch (ArgumentException) { throw new MySqlException(string.Format(ResourcesX.DuplicateUserDefinedAttribute, key)); } + } + } + } + else if (connectionAttrs != "true") + throw new MySqlException(ResourcesX.InvalidConnectionAttributes); + + MySqlConnectAttrs clientAttrs = new MySqlConnectAttrs(); + attrs.Add("_pid", clientAttrs.PID); + attrs.Add("_platform", clientAttrs.Platform); + attrs.Add("_os", clientAttrs.OSName); + attrs.Add("_source_host", Settings.Server); + attrs.Add("_client_name", clientAttrs.ClientName); + attrs.Add("_client_version", clientAttrs.ClientVersion); + attrs.Add("_client_license", clientAttrs.ClientLicence); + attrs.Add("_framework", clientAttrs.Framework); + + return attrs; + } + + private void AuthenticateMySQL41() + { + MySQL41AuthenticationPlugin plugin = new MySQL41AuthenticationPlugin(Settings); + _protocol.SendAuthStart(plugin.AuthName, null, null); + byte[] extraData = _protocol.ReadAuthContinue(); + _protocol.SendAuthContinue(plugin.Continue(extraData)); + _protocol.ReadAuthOk(); + } + + private void AuthenticatePlain() + { + PlainAuthenticationPlugin plugin = new PlainAuthenticationPlugin(Settings); + _protocol.SendAuthStart(plugin.AuthName, plugin.GetAuthData(), null); + _protocol.ReadAuthOk(); + } + + private void AuthenticateExternal() + { + ExternalAuthenticationPlugin plugin = new ExternalAuthenticationPlugin(Settings); + _protocol.SendAuthStart(plugin.AuthName, Encoding.UTF8.GetBytes(""), null); + _protocol.ReadAuthOk(); + } + + private void AuthenticateSha256Memory() + { + Sha256MemoryAuthenticationPlugin plugin = new Sha256MemoryAuthenticationPlugin(); + _protocol.SendAuthStart(plugin.PluginName, null, null); + byte[] nonce = _protocol.ReadAuthContinue(); + + string data = $"{Settings.Database}\0{Settings.UserID}\0"; + byte[] byteData = Encoding.UTF8.GetBytes(data); + byte[] clientHash = plugin.GetClientHash(Settings.Password, nonce); + byte[] authData = new byte[byteData.Length + clientHash.Length]; + byteData.CopyTo(authData, 0); + clientHash.CopyTo(authData, byteData.Length); + + _protocol.SendAuthContinue(authData); + _protocol.ReadAuthOk(); + } + + protected internal void SetState(SessionState newState, bool broadcast) + { + if (newState == SessionState && !broadcast) + return; + SessionState oldSessionState = SessionState; + SessionState = newState; + + //TODO check if we need to send this event + //if (broadcast) + //OnStateChange(new StateChangeEventArgs(oldConnectionState, connectionState)); + } + + internal override ProtocolBase GetProtocol() + { + return _protocol; + } + + public override void Close() + { + try + { + try + { + // Deallocate compression objects. + _readerCompressionController?.Close(); + _writerCompressionController?.Close(); + + // Deallocate all the remaining prepared statements for current session. + foreach (int stmtId in _preparedStatements) + { + if (!_myNetworkStream.IsSocketClosed) + { + DeallocatePreparedStatement(stmtId); + } + _preparedStatements.Remove(stmtId); + } + } + catch (Exception) + { + //TODO log exception + } + + if (!_myNetworkStream.IsSocketClosed) + { + _protocol.SendSessionClose(); + } + } + finally + { + SessionState = SessionState.Closed; + _stream.Dispose(); + } + } + + public void CreateCollection(string schemaName, string collectionName) + { + ExecuteCmdNonQuery(XpluginStatementCommand.XPLUGIN_STMT_CREATE_COLLECTION, + true, + new KeyValuePair("schema", schemaName), + new KeyValuePair("name", collectionName)); + } + + /// + /// Prepare the dictionary of arguments required to create a MySQL message. + /// + /// The name of the MySQL schema. + /// The name of the collection. + /// This object hold the parameters required to create the collection. + /// + /// Collection referente. + public void CreateCollection(string schemaName, string collectionName, CreateCollectionOptions options) + { + var dictionary = new Dictionary(); + if (!options.Equals(null)) + { + if (!string.IsNullOrEmpty(options.Validation.Level.ToString())) + { + dictionary.Add("level", (string)options.Validation.Level.ToString().ToLowerInvariant()); + } + + if (!string.IsNullOrEmpty(options.Validation.Schema)) + { + dictionary.Add("schema", new DbDoc(options.Validation.Schema)); + } + } + + ExecuteCmdNonQueryOptions(XpluginStatementCommand.XPLUGIN_STMT_CREATE_COLLECTION, + true, + new KeyValuePair("schema", schemaName), + new KeyValuePair("name", collectionName), + new KeyValuePair("reuse_existing", options.ReuseExisting), + new KeyValuePair("options", dictionary) + ); + } + + /// + /// Prepare the dictionary of arguments required to Modify a MySQL message. + /// + /// The name of the MySQL schema. + /// The name of the collection. + /// This object hold the parameters required to Modify the collection. + /// + public void ModifyCollection(string schemaName, string collectionName, ModifyCollectionOptions? options) + { + var dictionary = new Dictionary(); + if (!options.Equals(null)) + { + if (options.Value.Validation.Level != null) + { + dictionary.Add("level", options.Value.Validation.Level.ToString().ToLowerInvariant()); + } + if (options.Value.Validation.Schema != null) + { + dictionary.Add("schema", new DbDoc(options.Value.Validation.Schema)); + } + } + ExecuteCmdNonQueryOptions(XpluginStatementCommand.XPLUGIN_STMT_MODIFY_COLLECTION, + true, + new KeyValuePair("schema", schemaName), + new KeyValuePair("name", collectionName), + new KeyValuePair("options", dictionary)); + } + + public void DropCollection(string schemaName, string collectionName) + { + ExecuteCmdNonQuery(XpluginStatementCommand.XPLUGIN_STMT_DROP_COLLECTION, + true, + new KeyValuePair("schema", schemaName), + new KeyValuePair("name", collectionName)); + } + + public Result CreateCollectionIndex(CreateCollectionIndexStatement statement) + { + List> args = new List>(); + args.Add(new KeyValuePair("name", statement.createIndexParams.IndexName)); + args.Add(new KeyValuePair("collection", statement.Target.Name)); + args.Add(new KeyValuePair("schema", statement.Target.Schema.Name)); + args.Add(new KeyValuePair("unique", false)); + + if (statement.createIndexParams.Type != null) + args.Add(new KeyValuePair("type", statement.createIndexParams.Type)); + + for (int i = 0; i < statement.createIndexParams.Fields.Count; i++) + { + var field = statement.createIndexParams.Fields[i]; + var dictionary = new Dictionary(); + dictionary.Add("member", field.Field); + if (field.Type != null) + dictionary.Add("type", field.Type); + + if (field.Required == null) + dictionary.Add("required", false); + else + dictionary.Add("required", (bool)field.Required); + + if (field.Options != null) + dictionary.Add("options", (ulong)field.Options); + + if (field.Srid != null) + dictionary.Add("srid", (ulong)field.Srid); + + if (field.Array != null) + dictionary.Add("array", (bool)field.Array); + + args.Add(new KeyValuePair("constraint", dictionary)); + } + + return ExecuteCreateCollectionIndex(XpluginStatementCommand.XPLUGIN_STMT_CREATE_COLLECTION_INDEX, false, args.ToArray()); + } + + public void DropCollectionIndex(string schemaName, string collectionName, string indexName) + { + List> args = new List>(); + args.Add(new KeyValuePair("schema", schemaName)); + args.Add(new KeyValuePair("collection", collectionName)); + args.Add(new KeyValuePair("name", indexName)); + ExecuteCmdNonQuery(XpluginStatementCommand.XPLUGIN_STMT_DROP_COLLECTION_INDEX, false, args.ToArray()); + } + + public long TableCount(Schema schema, string name, string type) + { + try + { + string sql = String.Format("SELECT COUNT(*) FROM {0}.{1}", + ExprUnparser.QuoteIdentifier(schema.Name), ExprUnparser.QuoteIdentifier(name)); + return (long)ExecuteQueryAsScalar(sql); + } + catch (MySqlException ex) when (ex.Code == 1146) + { + throw new MySqlException(string.Format(ResourcesX.CollectionTableDoesNotExist, type.ToString(), name, schema.Name), (int)ex.Code); + } + } + + public bool TableExists(Schema schema, string name) + { + string sql = String.Format("SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = '{0}' AND table_name = '{1}'", + schema.Name, name); + long count = (long)ExecuteQueryAsScalar(sql); + return count != 0; + } + + private Result ExecuteCmdNonQuery(string cmd, bool throwOnFail, params KeyValuePair[] args) + { + _protocol.SendExecuteStatement(mysqlxNamespace, cmd, args); + return new Result(this); + } + + private Result ExecuteCmdNonQueryOptions(string cmd, bool throwOnFail, params KeyValuePair[] args) + { + _protocol.SendExecuteStatementOptions(mysqlxNamespace, cmd, args); + return new Result(this); + } + + private Result ExecuteCreateCollectionIndex(string cmd, bool throwOnFail, params KeyValuePair[] args) + { + _protocol.SendCreateCollectionIndexStatement(mysqlxNamespace, cmd, args); + return new Result(this); + } + + public List GetObjectList(Schema s, params string[] types) where T : DatabaseObject + { + for (int i = 0; i < types.Length; i++) + types[i] = types[i].ToUpperInvariant(); + RowResult result = GetRowResult("list_objects", new KeyValuePair("schema", s.Name)); + var rows = result.FetchAll(); + + List docs = new List(); + foreach (var row in rows) + { + if (!types.Contains(row.GetString("type").ToUpperInvariant())) continue; + + List parameters = new List(new object[] { s, row.GetString("name") }); + if (row["name"] is Byte[]) + { + Byte[] byteArray = row["name"] as Byte[]; + parameters[1] = Encoding.UTF8.GetString(byteArray, 0, byteArray.Length); + } + + switch (row.GetString("type").ToUpperInvariant()) + { + case "TABLE": + parameters.Add(false); + break; + case "VIEW": + parameters.Add(true); + break; + } + T t = (T)Activator.CreateInstance(typeof(T), + BindingFlags.NonPublic | BindingFlags.Instance, + null, parameters.ToArray(), null); + docs.Add(t); + } + return docs; + } + + public string GetObjectType(Schema s, string name) + { + RowResult result = GetRowResult("list_objects", + new KeyValuePair("schema", s.Name), + new KeyValuePair("pattern", name)); + var row = result.FetchOne(); + if (row == null) + throw new MySqlException(string.Format(ResourcesX.NoObjectFound, name)); + System.Diagnostics.Debug.Assert(result.FetchOne() == null); + return row.GetString("type"); + } + + public RowResult GetRowResult(string cmd, params KeyValuePair[] args) + { + _protocol.SendExecuteStatement(mysqlxNamespace, cmd, args); + return new RowResult(this); + } + + public Result Insert(Collection collection, object[] json, List newIds, bool upsert) + { + _protocol.SendInsert(collection.Schema.Name, false, collection.Name, json, null, upsert); + return new Result(this); + } + + public Result DeleteDocs(RemoveStatement rs) + { + _protocol.SendDelete(rs.Target.Schema.Name, rs.Target.Name, false, rs.FilterData); + return new Result(this); + } + + public Result DeleteRows(TableDeleteStatement statement) + { + _protocol.SendDelete(statement.Target.Schema.Name, + statement.Target.Name, true, + statement.FilterData); + return new Result(this); + } + + public Result ModifyDocs(ModifyStatement ms) + { + _protocol.SendUpdate(ms.Target.Schema.Name, ms.Target.Name, false, ms.FilterData, ms.Updates); + return new Result(this); + } + + public Result UpdateRows(TableUpdateStatement statement) + { + _protocol.SendUpdate(statement.Target.Schema.Name, + statement.Target.Name, true, + statement.FilterData, + statement.updates); + return new Result(this); + } + + public DocResult FindDocs(FindStatement fs) + { + _protocol.SendFind(fs.Target.Schema.Name, fs.Target.Name, false, fs.FilterData, fs.findParams); + DocResult result = new DocResult(this); + return result; + } + + public RowResult FindRows(TableSelectStatement ss) + { + _protocol.SendFind(ss.Target.Schema.Name, ss.Target.Name, true, ss.FilterData, ss.findParams); + return new RowResult(this); + } + + public Result InsertRows(TableInsertStatement statement) + { + _protocol.SendInsert(statement.Target.Schema.Name, true, statement.Target.Name, statement.values.ToArray(), statement.fields, false); + return new Result(this); + } + + protected Result ExpectOpen(Mysqlx.Expect.Open.Types.Condition.Types.Key condition, object value = null) + { + _protocol.SendExpectOpen(condition, value); + return new Result(this); + } + + public Result ExpectDocidGenerated() + { + return ExpectOpen(Mysqlx.Expect.Open.Types.Condition.Types.Key.ExpectDocidGenerated); + } + + public void ResetSession() + { + if (_sessionResetNoReauthentication == null) + { + try + { + if (!_myNetworkStream.IsSocketClosed) + { + ExpectOpen(Mysqlx.Expect.Open.Types.Condition.Types.Key.ExpectFieldExist, "6.1"); + } + _sessionResetNoReauthentication = true; + } + catch + { + _sessionResetNoReauthentication = false; + } + } + + if (!_myNetworkStream.IsSocketClosed) + { + _protocol.SendResetSession((bool)_sessionResetNoReauthentication); + _protocol.ReadOk(); + } + } + + public int PrepareStatement(BaseStatement statement) + where TResult : BaseResult + { + int stmtId = Interlocked.Increment(ref _stmtId); + string stmtType = statement.GetType().Name; + + if (stmtType == typeof(FindStatement<>).Name) + { + FindStatement fs = statement as FindStatement; + string s = typeof(TDoc).Name; + Debug.Assert(fs != null); + _protocol.SendPrepareStatement( + (uint)stmtId, + DataAccess.PreparedStatementType.Find, + fs.Target.Schema.Name, + fs.Target.Name, + false, + fs.FilterData, + fs.findParams); + } + else if (stmtType == typeof(TableSelectStatement).Name) + { + TableSelectStatement ss = statement as TableSelectStatement; + Debug.Assert(ss != null); + _protocol.SendPrepareStatement( + (uint)stmtId, + DataAccess.PreparedStatementType.Find, + ss.Target.Schema.Name, + ss.Target.Name, + true, + ss.FilterData, + ss.findParams); + } + else if (stmtType == typeof(ModifyStatement<>).Name) + { + ModifyStatement ms = statement as ModifyStatement; + Debug.Assert(ms != null); + _protocol.SendPrepareStatement( + (uint)stmtId, + DataAccess.PreparedStatementType.Update, + ms.Target.Schema.Name, + ms.Target.Name, + false, + ms.FilterData, + null, + ms.Updates); + } + else if (stmtType == typeof(TableUpdateStatement).Name) + { + TableUpdateStatement us = statement as TableUpdateStatement; + Debug.Assert(us != null); + _protocol.SendPrepareStatement( + (uint)stmtId, + DataAccess.PreparedStatementType.Update, + us.Target.Schema.Name, + us.Target.Name, + true, + us.FilterData, + null, + us.updates); + } + else if (stmtType == typeof(RemoveStatement<>).Name) + { + string s = typeof(TDoc).Name; + RemoveStatement rs = statement as RemoveStatement; + Debug.Assert(rs != null); + _protocol.SendPrepareStatement( + (uint)stmtId, + DataAccess.PreparedStatementType.Delete, + rs.Target.Schema.Name, + rs.Target.Name, + false, + rs.FilterData, + null); + } + else if (stmtType == typeof(TableDeleteStatement).Name) + { + TableDeleteStatement ds = statement as TableDeleteStatement; + Debug.Assert(ds != null); + _protocol.SendPrepareStatement( + (uint)stmtId, + DataAccess.PreparedStatementType.Delete, + ds.Target.Schema.Name, + ds.Target.Name, + true, + ds.FilterData, + null); + } + else if (stmtType == typeof(TableInsertStatement).Name) + { + TableInsertStatement insert = statement as TableInsertStatement; + Debug.Assert(insert != null); + _protocol.SendPrepareStatement( + (uint)stmtId, + DataAccess.PreparedStatementType.Insert, + insert.Target.Schema.Name, + insert.Target.Name, + true, + null, + null, + null, + insert.values.ToArray(), + insert.fields, + false); + } + else if (stmtType == typeof(SqlStatement).Name) + { + SqlStatement sqlStatement = statement as SqlStatement; + Debug.Assert(sqlStatement != null); + _protocol.SendPrepareStatement( + (uint)stmtId, + DataAccess.PreparedStatementType.SqlStatement, + null, + null, + true, + null, + null, + null, + sqlStatement.parameters.ToArray(), + null, + false, + sqlStatement.SQL); + } + else + { + throw new NotSupportedException(statement.GetType().Name); + } + + _preparedStatements.Add(stmtId); + return stmtId; + } + + public TResult ExecutePreparedStatement(int stmtId, IEnumerable args) + where TResult : BaseResult + { + _protocol.SendExecutePreparedStatement((uint)stmtId, args); + BaseResult result = null; + if (typeof(TResult) == typeof(DocResult)) + result = new DocResult(this); + else if (typeof(TResult) == typeof(RowResult)) + result = new RowResult(this); + else if (typeof(TResult) == typeof(SqlResult)) + result = new SqlResult(this); + else if (typeof(TResult) == typeof(Result)) + result = new Result(this); + else + throw new ArgumentNullException(typeof(TResult).Name); + + return (TResult)result; + } + + public void DeallocatePreparedStatement(int stmtId) + { + _protocol.SendDeallocatePreparedStatement((uint)stmtId); + _preparedStatements.Remove(stmtId); + } + + /// + /// Gets the compression algorithm being used to compress or decompress data. + /// + /// Flag to indicate if the compression algorithm should be + /// retrieved from the reader or writer controller. + /// The name of the compression algorithm being used if any. + /// null if no compression algorithm is being used. + public string GetCompressionAlgorithm(bool fromReaderController) + { + if (fromReaderController && _readerCompressionController != null) + { + return _readerCompressionController.CompressionAlgorithm.ToString(); + } + else if (!fromReaderController && _writerCompressionController != null) + { + return _writerCompressionController.CompressionAlgorithm.ToString(); + } + + return null; + } + } +} diff --git a/MySQL.Data/src/X/XDevAPI/BaseSession.cs b/MySQL.Data/src/X/XDevAPI/BaseSession.cs index 4fdc98720..e7804c907 100644 --- a/MySQL.Data/src/X/XDevAPI/BaseSession.cs +++ b/MySQL.Data/src/X/XDevAPI/BaseSession.cs @@ -1,834 +1,834 @@ -// Copyright (c) 2015, 2022, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySql.Data; -using MySql.Data.Common; -using MySql.Data.Failover; -using MySql.Data.MySqlClient; -using MySqlX.Common; -using MySqlX.Sessions; -using MySqlX.XDevAPI.Relational; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Text.RegularExpressions; - -namespace MySqlX.XDevAPI -{ - /// - /// Represents a base class for a Session. - /// - public abstract class BaseSession : IDisposable - { - private InternalSession _internalSession; - private string _connectionString; - private bool _isDefaultPort = true; - private const uint X_PROTOCOL_DEFAULT_PORT = 33060; - private const char CONNECTION_DATA_KEY_SEPARATOR = ';'; - private const char CONNECTION_DATA_VALUE_SEPARATOR = '='; - private const string PORT_CONNECTION_OPTION_KEYWORD = "port"; - private const string SERVER_CONNECTION_OPTION_KEYWORD = "server"; - private const string CONNECT_TIMEOUT_CONNECTION_OPTION_KEYWORD = "connect-timeout"; - private const string CONNECTION_ATTRIBUTES_CONNECTION_OPTION_KEYWORD = "connection-attributes"; - private const string DNS_SRV_CONNECTION_OPTION_KEYWORD = "dns-srv"; - private const string DNS_SRV_URI_SCHEME = "mysqlx+srv"; - private const string MYSQLX_URI_SCHEME = "mysqlx"; - internal QueueTaskScheduler _scheduler = new QueueTaskScheduler(); - protected readonly Client _client; - - internal InternalSession InternalSession - { - get - { - if (_internalSession == null) - throw new MySqlException(ResourcesX.InvalidSession); - return _internalSession; - } - } - - internal XInternalSession XSession - { - get { return InternalSession as XInternalSession; } - } - - internal DateTime IdleSince { get; set; } - - #region Session status properties - - private DBVersion? _version = null; - - internal DBVersion Version => _version ?? (_version = XSession.GetServerVersion()).Value; - - private int? _threadId = null; - internal int ThreadId => _threadId ?? (_threadId = XSession.GetThreadId()).Value; - - /// - /// Flag to set if prepared statements are supported. - /// - internal bool SupportsPreparedStatements { get; set; } = true; - - #endregion - - /// - /// Gets the connection settings for this session. - /// - public MySqlXConnectionStringBuilder Settings { get; private set; } - - /// - /// Gets the currently active schema. - /// - public Schema Schema { get; protected set; } - - /// - /// Gets the default schema provided when creating the session. - /// - public Schema DefaultSchema { get; private set; } - - /// - /// Gets the connection uri representation of the connection options provided during the creation of the session. - /// - public String Uri - { - get - { - var builder = new StringBuilder(string.Format("mysqlx://{0}:{1}{2}?", - Settings.Server, - Settings.Port, - string.IsNullOrEmpty(Settings.Database) ? - string.Empty : - "/" + Settings.Database)); - var firstItemAdded = false; - var certificateFileAdded = false; - foreach (var item in Settings.values) - { - // Skip connection options already included in the connection URI. - if (item.Key == "server" || item.Key == "database" || item.Key == "port") - continue; - - // Skip CertificateFile if it has already been included. - if ((item.Key == "certificatefile" || item.Key == "sslca") && certificateFileAdded) - continue; - - try - { - var value = Settings[item.Key]; - // Get the default value of the connection option. - var option = MySqlXConnectionStringBuilder.Options.Values.First( - o => o.Keyword == item.Key || - (o.Synonyms != null && o.Synonyms.Contains(item.Key))); - var defaultValue = option.DefaultValue; - // If the default value has been changed then include it in the connection URI. - if (value != null && (defaultValue == null || (value.ToString() != defaultValue.ToString()))) - { - if (!firstItemAdded) - firstItemAdded = true; - else - builder.Append("&"); - - if (item.Key == "certificatefile" || item.Key == "sslca") - { - certificateFileAdded = true; - builder.Append("sslca"); - } - else - builder.Append(item.Key); - builder.Append("="); - builder.Append(value is bool ? value.ToString().ToLower() : value.ToString()); - } - } - // Dismiss any not supported exceptions since they are expected. - catch (NotSupportedException) { } - catch (ArgumentException) { } - } - - return builder.ToString(); - } - } - - /// - /// Initializes a new instance of the BaseSession class based on the specified connection string. - /// - /// The connection used to create the session. - /// A object. - /// is null. - /// Unable to parse the when - /// in URI format. - /// - /// When using Unix sockets the protocol=unix or protocol=unixsocket connection option is required. - /// This will enable elements passed in the server connection option to be treated as Unix sockets. The user is also required - /// to explicitly set sslmode to none since X Plugin does not support SSL when using Unix sockets. Note that - /// protocol=unix and protocol=unixsocket are synonyms. - ///   - /// Multiple hosts can be specified as part of the , - /// which enables client-side failover when trying to establish a connection. - ///   - /// Connection URI examples: - /// - mysqlx://test:test@[192.1.10.10,localhost] - /// - mysqlx://test:test@[192.1.10.10,127.0.0.1] - /// - mysqlx://root:@[../tmp/mysqlx.sock,/tmp/mysqld.sock]?protocol=unix&sslmode=none - /// - mysqlx://test:test@[192.1.10.10:33060,127.0.0.1:33060] - /// - mysqlx://test:test@[192.1.10.10,120.0.0.2:22000,[::1]:33060]/test?connectiontimeout=10 - /// - mysqlx://test:test@[(address=server.example,priority=20),(address=127.0.0.1,priority=100)] - /// - mysqlx://test:test@[(address=server.example,priority=100),(address=127.0.0.1,priority=75),(address=192.0.10.56,priority=25)] - /// - ///   - /// Connection string examples: - /// - server=10.10.10.10,localhost;port=33060;uid=test;password=test; - /// - host=10.10.10.10,192.101.10.2,localhost;port=5202;uid=test;password=test; - /// - host=./tmp/mysqld.sock,/var/run/mysqldx.sock;port=5202;uid=root;protocol=unix;sslmode=none; - /// - server=(address=server.example,priority=20),(address=127.0.0.1,priority=100);port=33060;uid=test;password=test; - /// - server=(address=server.example,priority=100),(address=127.0.0.1,priority=75),(address=192.0.10.56,priority=25);port=33060;uid=test;password=test; - /// - ///   - /// Failover methods - /// - Sequential: Connection attempts will be performed in a sequential order, that is, one after another until - /// a connection is successful or all the elements from the list have been tried. - /// - /// - Priority based: If a priority is provided, the connection attemps will be performed in descending order, starting - /// with the host with the highest priority. Priority must be a value between 0 and 100. Additionally, it is required to either - /// give a priority for every host or no priority to any host. - /// - /// - internal BaseSession(string connectionString, Client client = null) : this() - { - if (string.IsNullOrWhiteSpace(connectionString)) - throw new ArgumentNullException("connectionString"); - - _client = client; - this._connectionString = ParseConnectionData(connectionString, client); - - // Multiple hosts were specified. - if (FailoverManager.FailoverGroup != null && FailoverManager.FailoverGroup.Hosts?.Count > 1) - { - _internalSession = FailoverManager.AttemptConnectionXProtocol(this._connectionString, out this._connectionString, _isDefaultPort, client); - Settings.ConnectionString = this._connectionString; - Settings.AnalyzeConnectionString(this._connectionString, true, _isDefaultPort); - } - // A single host was specified. - else - { - Settings.ConnectionString = _connectionString; - if (!(_connectionString.Contains("sslmode") || _connectionString.Contains("ssl mode") || _connectionString.Contains("ssl-mode"))) - Settings.SslMode = MySqlSslMode.Required; - Settings.AnalyzeConnectionString(this._connectionString, true, _isDefaultPort); - - if (Settings.DnsSrv) - { - var dnsSrvRecords = DnsSrv.GetDnsSrvRecords(Settings.Server); - FailoverManager.SetHostList(dnsSrvRecords.ConvertAll(r => new FailoverServer(r.Target, r.Port, r.Priority)), - FailoverMethod.Sequential); - _internalSession = FailoverManager.AttemptConnectionXProtocol(this._connectionString, out this._connectionString, _isDefaultPort, client); - Settings.ConnectionString = this._connectionString; - } - else - _internalSession = InternalSession.GetSession(Settings); - } - - // Set the default schema if provided by the user. - if (!string.IsNullOrWhiteSpace(Settings.Database)) - DefaultSchema = GetSchema(Settings.Database); - } - - /// - /// Initializes a new instance of the BaseSession class based on the specified anonymous type object. - /// - /// The connection data as an anonymous type used to create the session. - /// A object. - /// is null. - /// - /// Multiple hosts can be specified as part of the , which enables client-side failover when trying to - /// establish a connection. - ///   - /// To assign multiple hosts, create a property similar to the connection string examples shown in - /// . Note that the value of the property must be a string. - /// - /// - internal BaseSession(object connectionData, Client client = null) : this() - { - if (connectionData == null) - throw new ArgumentNullException("connectionData"); - - _client = client; - if (client == null) - FailoverManager.Reset(); - - var values = Tools.GetDictionaryFromAnonymous(connectionData); - if (!values.Keys.Any(s => s.ToLowerInvariant() == PORT_CONNECTION_OPTION_KEYWORD)) - values.Add(PORT_CONNECTION_OPTION_KEYWORD, X_PROTOCOL_DEFAULT_PORT); - - bool hostsParsed = false; - foreach (var value in values) - { - if (!Settings.ContainsKey(value.Key)) - throw new KeyNotFoundException(string.Format(ResourcesX.InvalidConnectionStringAttribute, value.Key)); - - Settings.SetValue(value.Key, value.Value); - if (!hostsParsed && !string.IsNullOrEmpty(Settings[SERVER_CONNECTION_OPTION_KEYWORD].ToString())) - { - var server = value.Value.ToString(); - if (IsUnixSocket(server)) - Settings.SetValue(value.Key, server = NormalizeUnixSocket(server)); - - FailoverManager.ParseHostList(server, true, false); - if (FailoverManager.FailoverGroup != null && FailoverManager.FailoverGroup.Hosts?.Count > 1) - Settings[SERVER_CONNECTION_OPTION_KEYWORD] = null; - else if (FailoverManager.FailoverGroup != null) - Settings[SERVER_CONNECTION_OPTION_KEYWORD] = FailoverManager.FailoverGroup.Hosts[0].Host; - - hostsParsed = true; - } - } - this._connectionString = Settings.ToString(); - - Settings.AnalyzeConnectionString(this._connectionString, true, _isDefaultPort); - if (FailoverManager.FailoverGroup != null && FailoverManager.FailoverGroup.Hosts?.Count > 1) - { - // Multiple hosts were specified. - _internalSession = FailoverManager.AttemptConnectionXProtocol(this._connectionString, out this._connectionString, _isDefaultPort, client); - Settings.ConnectionString = _connectionString; - } - else - { - if (Settings.DnsSrv) - { - var dnsSrvRecords = DnsSrv.GetDnsSrvRecords(Settings.Server); - FailoverManager.SetHostList(dnsSrvRecords.ConvertAll(r => new FailoverServer(r.Target, r.Port, null)), - FailoverMethod.Sequential); - _internalSession = FailoverManager.AttemptConnectionXProtocol(this._connectionString, out this._connectionString, _isDefaultPort, client); - Settings.ConnectionString = this._connectionString; - } - else - _internalSession = InternalSession.GetSession(Settings); - } - - if (!string.IsNullOrWhiteSpace(Settings.Database)) - DefaultSchema = GetSchema(Settings.Database); - } - - internal BaseSession(InternalSession internalSession, Client client) - { - _internalSession = internalSession; - Settings = internalSession.Settings; - _client = client; - } - - // Constructor used exclusively to parse connection string or connection data - internal BaseSession() - { - Settings = new MySqlXConnectionStringBuilder(); - } - - /// - /// Drops the database/schema with the given name. - /// - /// The name of the schema. - /// is null. - public void DropSchema(string schema) - { - if (string.IsNullOrWhiteSpace(schema)) throw new ArgumentNullException(nameof(schema)); - Schema s = this.GetSchema(schema); - if (!s.ExistsInDatabase()) return; - InternalSession.ExecuteSqlNonQuery("DROP DATABASE `" + schema + "`"); - } - - /// - /// Creates a schema/database with the given name. - /// - /// The name of the schema/database. - /// A object that matches the recently created schema/database. - public Schema CreateSchema(string schema) - { - InternalSession.ExecuteSqlNonQuery("CREATE DATABASE `" + schema + "`"); - return new Schema(this, schema); - } - - /// - /// Gets the schema with the given name. - /// - /// The name of the schema. - /// A object set with the provided schema name. - public Schema GetSchema(string schema) - { - this.Schema = new Schema(this, schema); - return this.Schema; - } - - /// - /// Gets a list of schemas (or databases) in this session. - /// - /// A list containing all existing schemas (or databases). - public List GetSchemas() - { - RowResult result = XSession.GetSqlRowResult("select * from information_schema.schemata"); - result.FetchAll(); - var query = from row in result.Rows - select new Schema(this, row.GetString("schema_name")); - return query.ToList(); - } - - /// - /// Starts a new transaction. - /// - public void StartTransaction() - { - InternalSession.ExecuteSqlNonQuery("START TRANSACTION"); - } - - /// - /// Commits the current transaction. - /// - /// A object containing the results of the commit operation. - public void Commit() - { - InternalSession.ExecuteSqlNonQuery("COMMIT"); - } - - /// - /// Rolls back the current transaction. - /// - public void Rollback() - { - InternalSession.ExecuteSqlNonQuery("ROLLBACK"); - } - - /// - /// Closes this session or releases it to the pool. - /// - public void Close() - { - if (XSession.SessionState != SessionState.Closed) - { - if (_client == null) - CloseFully(); - else - { - _client.ReleaseSession(this); - XSession.SetState(SessionState.Closed, false); - _internalSession = null; - } - } - } - - /// - /// Closes this session - /// - internal void CloseFully() - { - XSession.Close(); - } - - internal void Reset() - { - XSession.ResetSession(); - } - - #region Savepoints - - /// - /// Sets a transaction savepoint with an autogenerated name. - /// - /// The autogenerated name of the transaction savepoint. - public string SetSavepoint() - { - // Autogenerate the name of the savepoint. - return SetSavepoint($"savepoint_{Guid.NewGuid().ToString().Replace("-", "_")}"); - } - - /// - /// Sets a named transaction savepoint. - /// - /// The name of the transaction savepoint. - /// The name of the transaction savepoint. - public string SetSavepoint(string name) - { - InternalSession.ExecuteSqlNonQuery($"SAVEPOINT {name}"); - return name; - } - - /// - /// Removes the named savepoint from the set of savepoints within the current transaction. - /// - /// The name of the transaction savepoint. - public void ReleaseSavepoint(string name) - { - InternalSession.ExecuteSqlNonQuery($"RELEASE SAVEPOINT {name}"); - } - - /// - /// Rolls back a transaction to the named savepoint without terminating the transaction. - /// - /// The name of the transaction savepoint. - public void RollbackTo(string name) - { - InternalSession.ExecuteSqlNonQuery($"ROLLBACK TO {name}"); - } - - #endregion - - /// - /// Parses the connection data. - /// - /// The connection string or connection URI. - /// A object. - /// An updated connection string representation of the provided connection string or connection URI. - protected internal string ParseConnectionData(string connectionData, Client client = null) - { - if (client == null) - FailoverManager.Reset(); - - if (Regex.IsMatch(connectionData, @"^mysqlx(\+\w+)?://.*", RegexOptions.IgnoreCase)) - { - return ParseConnectionUri(connectionData); - } - else - return ParseConnectionString(connectionData); - } - - /// - /// Parses a connection URI. - /// - /// The connection URI to parse. - /// The connection string representation of the provided . - private string ParseConnectionUri(string connectionUri) - { - Uri uri = null; - string updatedUri = null; - bool parseServerAsUnixSocket = false; - string hierPart = null; - try - { - uri = new Uri(connectionUri); - } - catch (UriFormatException ex) - { - if (ex.Message != "Invalid URI: The hostname could not be parsed.") - throw; - - // Identify if multiple hosts were specified. - string[] splitUri = connectionUri.Split('@', '?'); - if (splitUri.Length == 1) throw; - - hierPart = splitUri[1]; - var schema = string.Empty; - parseServerAsUnixSocket = IsUnixSocket(hierPart); - bool isArray = hierPart.StartsWith("[") && hierPart.Contains("]"); - - // Remove schema. - if ((!parseServerAsUnixSocket && hierPart.Contains("/")) && !isArray || - (parseServerAsUnixSocket && hierPart.Contains(")/")) || - (hierPart.StartsWith("[") && hierPart.Contains("]/") && isArray)) - { - schema = hierPart.Substring(hierPart.LastIndexOf('/') + 1); - hierPart = hierPart.Substring(0, hierPart.Length - schema.Length - 1); - } - - if (parseServerAsUnixSocket) - { - updatedUri = splitUri[0] + "@localhost" + - (schema != string.Empty ? "/" + schema : string.Empty) + - (splitUri.Length > 2 ? "?" + splitUri[2] : string.Empty); - } - else if (isArray) - { - hierPart = hierPart.Substring(1, hierPart.Length - 2); - int hostCount = FailoverManager.ParseHostList(hierPart, true, true); - if (FailoverManager.FailoverGroup != null) - { - hierPart = FailoverManager.FailoverGroup.ActiveHost.Host; - parseServerAsUnixSocket = IsUnixSocket(FailoverManager.FailoverGroup.ActiveHost.Host); - updatedUri = splitUri[0] + "@" + - (parseServerAsUnixSocket ? "localhost" : hierPart) + - (FailoverManager.FailoverGroup.ActiveHost.Port != -1 ? ":" + FailoverManager.FailoverGroup.ActiveHost.Port : string.Empty) + - (schema != string.Empty ? "/" + schema : string.Empty) + - (splitUri.Length == 3 ? "?" + splitUri[2] : string.Empty); - } - else if (hostCount == 1) - updatedUri = splitUri[0] + "@" + hierPart + - (schema != string.Empty ? "/" + schema : string.Empty) + - (splitUri.Length == 3 ? "?" + splitUri[2] : string.Empty); - else - throw; - } - } - - if (uri == null) - uri = updatedUri == null ? new Uri(connectionUri) : new Uri(updatedUri); - - if (uri.Scheme == DNS_SRV_URI_SCHEME) - { - if (FailoverManager.FailoverGroup != null && FailoverManager.FailoverGroup.Hosts?.Count > 1) - throw new ArgumentException(Resources.DnsSrvInvalidConnOptionMultihost); - if (!uri.IsDefaultPort) - throw new ArgumentException(Resources.DnsSrvInvalidConnOptionPort); - if (parseServerAsUnixSocket) - throw new ArgumentException(Resources.DnsSrvInvalidConnOptionUnixSocket); - } - else if (uri.Scheme != MYSQLX_URI_SCHEME) - throw new ArgumentException(string.Format(ResourcesX.DnsSrvInvalidScheme, uri.Scheme)); - - return ConvertToConnectionString(uri, hierPart, parseServerAsUnixSocket, uri.Scheme == DNS_SRV_URI_SCHEME); - } - - /// - /// Validates if the string provided is a Unix socket file. - /// - /// The Unix socket to evaluate. - /// true if is a valid Unix socket; otherwise, false. - internal static bool IsUnixSocket(string unixSocket) - { - if (unixSocket.StartsWith(".") || - unixSocket.StartsWith("/") || - unixSocket.StartsWith("(.") || - unixSocket.StartsWith("(/") || - unixSocket.StartsWith("%2") || - unixSocket.StartsWith("(%2")) - return true; - - return false; - } - - /// - /// Converts the URI object into a connection string. - /// - /// An instance with the values for the provided connection options. - /// The path of the Unix socket file. - /// If true the replaces the value for the server connection option; otherwise, false - /// Flag indicating if this is a connection using DNS SRV. - /// A connection string. - private string ConvertToConnectionString(Uri uri, string unixSocketPath, bool parseServerAsUnixSocket, bool isDnsSrvScheme) - { - List connectionParts = new List(); - - if (string.IsNullOrWhiteSpace(uri.Host)) - throw new UriFormatException(ResourcesX.InvalidUriData + "host"); - connectionParts.Add("server=" + (parseServerAsUnixSocket ? - NormalizeUnixSocket(unixSocketPath) : - uri.Host)); - connectionParts.Add("port=" + (uri.Port == -1 ? 33060 : uri.Port)); - _isDefaultPort = uri.IsDefaultPort; - if (uri.Scheme == DNS_SRV_URI_SCHEME) - connectionParts.Add("dns-srv=true"); - - if (!string.IsNullOrWhiteSpace(uri.UserInfo)) - { - string[] userData = uri.UserInfo.Split(':'); - if (userData.Length > 2) - throw new UriFormatException(ResourcesX.InvalidUriData + "user info"); - connectionParts.Add("uid=" + System.Uri.UnescapeDataString(userData[0])); - if (userData.Length > 1) - connectionParts.Add("password=" + System.Uri.UnescapeDataString(userData[1])); - } - if (uri.Segments.Length > 2) - throw new UriFormatException(ResourcesX.InvalidUriData + "segments"); - if (uri.Segments.Length > 1) - { - connectionParts.Add("database=" + System.Uri.UnescapeDataString(uri.Segments[1])); - } - if (!string.IsNullOrWhiteSpace(uri.Query)) - { - string[] queries = System.Uri.UnescapeDataString(uri.Query).Substring(1).Split(new char[] { '&' }, StringSplitOptions.RemoveEmptyEntries); - foreach (string query in queries) - { - string[] keyValue = query.Replace(";", string.Empty).Split('='); - string part; - var connectionAttributesOption = MySqlXConnectionStringBuilder.Options.Options.First(item => item.Keyword == CONNECTION_ATTRIBUTES_CONNECTION_OPTION_KEYWORD); - var dnsSrvOption = MySqlXConnectionStringBuilder.Options.Options.First(item => item.Keyword == DNS_SRV_CONNECTION_OPTION_KEYWORD); - - if (!((connectionAttributesOption.Keyword == keyValue[0]) || connectionAttributesOption.Synonyms.Contains(keyValue[0]) && keyValue.Count() > 2)) - { - if (keyValue.Length > 2) - throw new ArgumentException(ResourcesX.InvalidUriQuery + ":" + keyValue[0]); - var connecttimeoutOption = MySqlXConnectionStringBuilder.Options.Options.First(item => item.Keyword == CONNECT_TIMEOUT_CONNECTION_OPTION_KEYWORD); - if ((connecttimeoutOption.Keyword == keyValue[0] || connecttimeoutOption.Synonyms.Contains(keyValue[0])) && - String.IsNullOrWhiteSpace(keyValue[1])) - throw new FormatException(ResourcesX.InvalidConnectionTimeoutValue); - part = keyValue[0] + "=" + (keyValue.Length == 2 ? keyValue[1] : "true").Replace("(", string.Empty).Replace(")", string.Empty); - } - else if (keyValue[1] == string.Empty) - throw new MySqlException(ResourcesX.InvalidUriQuery + ": " + keyValue[0]); - else - part = keyValue[0] + "=" + query.Replace(keyValue[0] + "=", string.Empty); - - if (isDnsSrvScheme && (dnsSrvOption.Keyword == keyValue[0] || dnsSrvOption.Synonyms.Contains(keyValue[0])) && !Convert.ToBoolean(keyValue[1])) - throw new ArgumentException(string.Format(ResourcesX.DnsSrvConflictingOptions, dnsSrvOption.Keyword)); - else if (isDnsSrvScheme && (dnsSrvOption.Keyword == keyValue[0] || dnsSrvOption.Synonyms.Contains(keyValue[0]))) - continue; - - connectionParts.Add(part); - } - } - - return string.Join("; ", connectionParts); - } - - /// - /// Parses a connection string. - /// - /// The connection string to parse. - /// The parsed connection string. - private string ParseConnectionString(string connectionString) - { - var updatedConnectionString = string.Empty; - bool portProvided = false; - bool isDnsSrv = false; - var connectionOptionsDictionary = connectionString.Split(CONNECTION_DATA_KEY_SEPARATOR) - .Select(item => item.Split(new char[] { CONNECTION_DATA_VALUE_SEPARATOR }, 2)) - .Where(item => item.Length == 2) - .ToDictionary(item => item[0], item => item[1]); - var serverOption = MySqlXConnectionStringBuilder.Options.Options.First(item => item.Keyword == SERVER_CONNECTION_OPTION_KEYWORD); - var connecttimeoutOption = MySqlXConnectionStringBuilder.Options.Options.First(item => item.Keyword == CONNECT_TIMEOUT_CONNECTION_OPTION_KEYWORD); - foreach (KeyValuePair keyValuePair in connectionOptionsDictionary) - { - // Value is an equal or a semicolon - if (keyValuePair.Value == "=" || keyValuePair.Value == "\"") - throw new MySqlException(string.Format(Resources.InvalidConnectionStringValue, (keyValuePair.Value == "\"" ? ";" : "="), keyValuePair.Key)); - - // Key is not server or any of its synonyms. - if (keyValuePair.Key != serverOption.Keyword && !serverOption.Synonyms.Contains(keyValuePair.Key)) - { - if ((connecttimeoutOption.Keyword == keyValuePair.Key || connecttimeoutOption.Synonyms.Contains(keyValuePair.Key)) && - String.IsNullOrWhiteSpace(keyValuePair.Value)) - throw new FormatException(ResourcesX.InvalidConnectionTimeoutValue); - if (keyValuePair.Key == PORT_CONNECTION_OPTION_KEYWORD) - portProvided = true; - if (keyValuePair.Key == DNS_SRV_CONNECTION_OPTION_KEYWORD) - isDnsSrv = Convert.ToBoolean(keyValuePair.Value); - - updatedConnectionString += $"{keyValuePair.Key}{CONNECTION_DATA_VALUE_SEPARATOR}{keyValuePair.Value}{CONNECTION_DATA_KEY_SEPARATOR}"; - continue; - } - - // Key is server or one of its synonyms. - var updatedValue = keyValuePair.Value; - if (IsUnixSocket(keyValuePair.Value)) - updatedValue = NormalizeUnixSocket(keyValuePair.Value); - - // The value for the server connection option doesn't have a server list format. - if (FailoverManager.ParseHostList(updatedValue, true, false) == 1 && FailoverManager.FailoverGroup == null) - updatedConnectionString = $"{SERVER_CONNECTION_OPTION_KEYWORD}{CONNECTION_DATA_VALUE_SEPARATOR}{updatedValue}{CONNECTION_DATA_KEY_SEPARATOR}{updatedConnectionString}"; - } - - // DNS SRV Validation - Port cannot be provided by the user and multihost is not allowed if dns-srv is true - if (isDnsSrv) - { - if (portProvided) - throw new ArgumentException(Resources.DnsSrvInvalidConnOptionPort); - if (FailoverManager.FailoverGroup != null) - throw new ArgumentException(Resources.DnsSrvInvalidConnOptionMultihost); - } - - // Default port must be added if not provided by the user. - if (FailoverManager.FailoverGroup == null) - return portProvided ? updatedConnectionString : $"{updatedConnectionString}{CONNECTION_DATA_KEY_SEPARATOR}{PORT_CONNECTION_OPTION_KEYWORD}{CONNECTION_DATA_VALUE_SEPARATOR}{X_PROTOCOL_DEFAULT_PORT}"; - - return $"{SERVER_CONNECTION_OPTION_KEYWORD}{CONNECTION_DATA_VALUE_SEPARATOR}{FailoverManager.FailoverGroup.ActiveHost.Host}{CONNECTION_DATA_KEY_SEPARATOR}" + - (!portProvided ? $"{PORT_CONNECTION_OPTION_KEYWORD}{CONNECTION_DATA_VALUE_SEPARATOR}{X_PROTOCOL_DEFAULT_PORT}{CONNECTION_DATA_KEY_SEPARATOR}" : string.Empty) + - updatedConnectionString; - } - - /// - /// Normalizes the Unix socket by removing leading and ending parenthesis as well as removing special characters. - /// - /// The Unix socket to normalize. - /// A normalized Unix socket. - internal static string NormalizeUnixSocket(string unixSocket) - { - unixSocket = unixSocket.Replace("%2F", "/"); - if (unixSocket.StartsWith("(") && unixSocket.EndsWith(")")) - unixSocket = unixSocket.Substring(1, unixSocket.Length - 2); - - return unixSocket; - } - - #region IDisposable Support - private bool disposedValue = false; // To detect redundant calls - - /// - /// Disposes the current object. Disposes of the managed state if the flag is set to true. - /// - /// Flag to indicate if the managed state is to be disposed. - protected virtual void Dispose(bool disposing) - { - if (!disposedValue) - { - if (disposing) - { - // dispose managed state (managed objects). - Close(); - } - - // free unmanaged resources (unmanaged objects) and override a finalizer below. - // set large fields to null. - - disposedValue = true; - } - } - - // override a finalizer only if Dispose(bool disposing) above has code to free unmanaged resources. - // ~BaseSession() { - // // Do not change this code. Put cleanup code in Dispose(bool disposing) above. - // Dispose(false); - // } - - /// - /// Disposes the current object. Code added to correctly implement the disposable pattern. - /// - public void Dispose() - { - // Do not change this code. Put cleanup code in Dispose(bool disposing) above. - Dispose(true); - // uncomment the following line if the finalizer is overridden above. - // GC.SuppressFinalize(this); - } - #endregion - } - - /// - /// Describes the state of the session. - /// - public enum SessionState - { - /// - /// The session is closed. - /// - Closed = 0, - /// - /// The session is open. - /// - Open = 1, - /// - /// The session object is connecting to the data source. - /// - Connecting = 2, - /// - /// The session object is executing a command. - /// - Executing = 4, - } -} +// Copyright © 2015, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySql.Data; +using MySql.Data.Common; +using MySql.Data.Failover; +using MySql.Data.MySqlClient; +using MySqlX.Common; +using MySqlX.Sessions; +using MySqlX.XDevAPI.Relational; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; + +namespace MySqlX.XDevAPI +{ + /// + /// Represents a base class for a Session. + /// + public abstract class BaseSession : IDisposable + { + private InternalSession _internalSession; + private string _connectionString; + private bool _isDefaultPort = true; + private const uint X_PROTOCOL_DEFAULT_PORT = 33060; + private const char CONNECTION_DATA_KEY_SEPARATOR = ';'; + private const char CONNECTION_DATA_VALUE_SEPARATOR = '='; + private const string PORT_CONNECTION_OPTION_KEYWORD = "port"; + private const string SERVER_CONNECTION_OPTION_KEYWORD = "server"; + private const string CONNECT_TIMEOUT_CONNECTION_OPTION_KEYWORD = "connect-timeout"; + private const string CONNECTION_ATTRIBUTES_CONNECTION_OPTION_KEYWORD = "connection-attributes"; + private const string DNS_SRV_CONNECTION_OPTION_KEYWORD = "dns-srv"; + private const string DNS_SRV_URI_SCHEME = "mysqlx+srv"; + private const string MYSQLX_URI_SCHEME = "mysqlx"; + internal QueueTaskScheduler _scheduler = new QueueTaskScheduler(); + protected readonly Client _client; + + internal InternalSession InternalSession + { + get + { + if (_internalSession == null) + throw new MySqlException(ResourcesX.InvalidSession); + return _internalSession; + } + } + + internal XInternalSession XSession + { + get { return InternalSession as XInternalSession; } + } + + internal DateTime IdleSince { get; set; } + + #region Session status properties + + private DBVersion? _version = null; + + internal DBVersion Version => _version ?? (_version = XSession.GetServerVersion()).Value; + + private int? _threadId = null; + internal int ThreadId => _threadId ?? (_threadId = XSession.GetThreadId()).Value; + + /// + /// Flag to set if prepared statements are supported. + /// + internal bool SupportsPreparedStatements { get; set; } = true; + + #endregion + + /// + /// Gets the connection settings for this session. + /// + public MySqlXConnectionStringBuilder Settings { get; private set; } + + /// + /// Gets the currently active schema. + /// + public Schema Schema { get; protected set; } + + /// + /// Gets the default schema provided when creating the session. + /// + public Schema DefaultSchema { get; private set; } + + /// + /// Gets the connection uri representation of the connection options provided during the creation of the session. + /// + public String Uri + { + get + { + var builder = new StringBuilder(string.Format("mysqlx://{0}:{1}{2}?", + Settings.Server, + Settings.Port, + string.IsNullOrEmpty(Settings.Database) ? + string.Empty : + "/" + Settings.Database)); + var firstItemAdded = false; + var certificateFileAdded = false; + foreach (var item in Settings.values) + { + // Skip connection options already included in the connection URI. + if (item.Key == "server" || item.Key == "database" || item.Key == "port") + continue; + + // Skip CertificateFile if it has already been included. + if ((item.Key == "certificatefile" || item.Key == "sslca") && certificateFileAdded) + continue; + + try + { + var value = Settings[item.Key]; + // Get the default value of the connection option. + var option = MySqlXConnectionStringBuilder.Options.Values.First( + o => o.Keyword == item.Key || + (o.Synonyms != null && o.Synonyms.Contains(item.Key))); + var defaultValue = option.DefaultValue; + // If the default value has been changed then include it in the connection URI. + if (value != null && (defaultValue == null || (value.ToString() != defaultValue.ToString()))) + { + if (!firstItemAdded) + firstItemAdded = true; + else + builder.Append("&"); + + if (item.Key == "certificatefile" || item.Key == "sslca") + { + certificateFileAdded = true; + builder.Append("sslca"); + } + else + builder.Append(item.Key); + builder.Append("="); + builder.Append(value is bool ? value.ToString().ToLower() : value.ToString()); + } + } + // Dismiss any not supported exceptions since they are expected. + catch (NotSupportedException) { } + catch (ArgumentException) { } + } + + return builder.ToString(); + } + } + + /// + /// Initializes a new instance of the BaseSession class based on the specified connection string. + /// + /// The connection used to create the session. + /// A object. + /// is null. + /// Unable to parse the when + /// in URI format. + /// + /// When using Unix sockets the protocol=unix or protocol=unixsocket connection option is required. + /// This will enable elements passed in the server connection option to be treated as Unix sockets. The user is also required + /// to explicitly set sslmode to none since X Plugin does not support SSL when using Unix sockets. Note that + /// protocol=unix and protocol=unixsocket are synonyms. + ///   + /// Multiple hosts can be specified as part of the , + /// which enables client-side failover when trying to establish a connection. + ///   + /// Connection URI examples: + /// - mysqlx://test:test@[192.1.10.10,localhost] + /// - mysqlx://test:test@[192.1.10.10,127.0.0.1] + /// - mysqlx://root:@[../tmp/mysqlx.sock,/tmp/mysqld.sock]?protocol=unix&sslmode=none + /// - mysqlx://test:test@[192.1.10.10:33060,127.0.0.1:33060] + /// - mysqlx://test:test@[192.1.10.10,120.0.0.2:22000,[::1]:33060]/test?connectiontimeout=10 + /// - mysqlx://test:test@[(address=server.example,priority=20),(address=127.0.0.1,priority=100)] + /// - mysqlx://test:test@[(address=server.example,priority=100),(address=127.0.0.1,priority=75),(address=192.0.10.56,priority=25)] + /// + ///   + /// Connection string examples: + /// - server=10.10.10.10,localhost;port=33060;uid=test;password=test; + /// - host=10.10.10.10,192.101.10.2,localhost;port=5202;uid=test;password=test; + /// - host=./tmp/mysqld.sock,/var/run/mysqldx.sock;port=5202;uid=root;protocol=unix;sslmode=none; + /// - server=(address=server.example,priority=20),(address=127.0.0.1,priority=100);port=33060;uid=test;password=test; + /// - server=(address=server.example,priority=100),(address=127.0.0.1,priority=75),(address=192.0.10.56,priority=25);port=33060;uid=test;password=test; + /// + ///   + /// Failover methods + /// - Sequential: Connection attempts will be performed in a sequential order, that is, one after another until + /// a connection is successful or all the elements from the list have been tried. + /// + /// - Priority based: If a priority is provided, the connection attemps will be performed in descending order, starting + /// with the host with the highest priority. Priority must be a value between 0 and 100. Additionally, it is required to either + /// give a priority for every host or no priority to any host. + /// + /// + internal BaseSession(string connectionString, Client client = null) : this() + { + if (string.IsNullOrWhiteSpace(connectionString)) + throw new ArgumentNullException("connectionString"); + + _client = client; + this._connectionString = ParseConnectionData(connectionString, client); + + // Multiple hosts were specified. + if (FailoverManager.FailoverGroup != null && FailoverManager.FailoverGroup.Hosts?.Count > 1) + { + _internalSession = FailoverManager.AttemptConnectionXProtocol(this._connectionString, out this._connectionString, _isDefaultPort, client); + Settings.ConnectionString = this._connectionString; + Settings.AnalyzeConnectionString(this._connectionString, true, _isDefaultPort); + } + // A single host was specified. + else + { + Settings.ConnectionString = _connectionString; + if (!(_connectionString.Contains("sslmode") || _connectionString.Contains("ssl mode") || _connectionString.Contains("ssl-mode"))) + Settings.SslMode = MySqlSslMode.Required; + Settings.AnalyzeConnectionString(this._connectionString, true, _isDefaultPort); + + if (Settings.DnsSrv) + { + var dnsSrvRecords = DnsSrv.GetDnsSrvRecords(Settings.Server); + FailoverManager.SetHostList(dnsSrvRecords.ConvertAll(r => new FailoverServer(r.Target, r.Port, r.Priority)), + FailoverMethod.Sequential); + _internalSession = FailoverManager.AttemptConnectionXProtocol(this._connectionString, out this._connectionString, _isDefaultPort, client); + Settings.ConnectionString = this._connectionString; + } + else + _internalSession = InternalSession.GetSession(Settings); + } + + // Set the default schema if provided by the user. + if (!string.IsNullOrWhiteSpace(Settings.Database)) + DefaultSchema = GetSchema(Settings.Database); + } + + /// + /// Initializes a new instance of the BaseSession class based on the specified anonymous type object. + /// + /// The connection data as an anonymous type used to create the session. + /// A object. + /// is null. + /// + /// Multiple hosts can be specified as part of the , which enables client-side failover when trying to + /// establish a connection. + ///   + /// To assign multiple hosts, create a property similar to the connection string examples shown in + /// . Note that the value of the property must be a string. + /// + /// + internal BaseSession(object connectionData, Client client = null) : this() + { + if (connectionData == null) + throw new ArgumentNullException("connectionData"); + + _client = client; + if (client == null) + FailoverManager.Reset(); + + var values = Tools.GetDictionaryFromAnonymous(connectionData); + if (!values.Keys.Any(s => s.ToLowerInvariant() == PORT_CONNECTION_OPTION_KEYWORD)) + values.Add(PORT_CONNECTION_OPTION_KEYWORD, X_PROTOCOL_DEFAULT_PORT); + + bool hostsParsed = false; + foreach (var value in values) + { + if (!Settings.ContainsKey(value.Key)) + throw new KeyNotFoundException(string.Format(ResourcesX.InvalidConnectionStringAttribute, value.Key)); + + Settings.SetValue(value.Key, value.Value); + if (!hostsParsed && !string.IsNullOrEmpty(Settings[SERVER_CONNECTION_OPTION_KEYWORD].ToString())) + { + var server = value.Value.ToString(); + if (IsUnixSocket(server)) + Settings.SetValue(value.Key, server = NormalizeUnixSocket(server)); + + FailoverManager.ParseHostList(server, true, false); + if (FailoverManager.FailoverGroup != null && FailoverManager.FailoverGroup.Hosts?.Count > 1) + Settings[SERVER_CONNECTION_OPTION_KEYWORD] = null; + else if (FailoverManager.FailoverGroup != null) + Settings[SERVER_CONNECTION_OPTION_KEYWORD] = FailoverManager.FailoverGroup.Hosts[0].Host; + + hostsParsed = true; + } + } + this._connectionString = Settings.ToString(); + + Settings.AnalyzeConnectionString(this._connectionString, true, _isDefaultPort); + if (FailoverManager.FailoverGroup != null && FailoverManager.FailoverGroup.Hosts?.Count > 1) + { + // Multiple hosts were specified. + _internalSession = FailoverManager.AttemptConnectionXProtocol(this._connectionString, out this._connectionString, _isDefaultPort, client); + Settings.ConnectionString = _connectionString; + } + else + { + if (Settings.DnsSrv) + { + var dnsSrvRecords = DnsSrv.GetDnsSrvRecords(Settings.Server); + FailoverManager.SetHostList(dnsSrvRecords.ConvertAll(r => new FailoverServer(r.Target, r.Port, null)), + FailoverMethod.Sequential); + _internalSession = FailoverManager.AttemptConnectionXProtocol(this._connectionString, out this._connectionString, _isDefaultPort, client); + Settings.ConnectionString = this._connectionString; + } + else + _internalSession = InternalSession.GetSession(Settings); + } + + if (!string.IsNullOrWhiteSpace(Settings.Database)) + DefaultSchema = GetSchema(Settings.Database); + } + + internal BaseSession(InternalSession internalSession, Client client) + { + _internalSession = internalSession; + Settings = internalSession.Settings; + _client = client; + } + + // Constructor used exclusively to parse connection string or connection data + internal BaseSession() + { + Settings = new MySqlXConnectionStringBuilder(); + } + + /// + /// Drops the database/schema with the given name. + /// + /// The name of the schema. + /// is null. + public void DropSchema(string schema) + { + if (string.IsNullOrWhiteSpace(schema)) throw new ArgumentNullException(nameof(schema)); + Schema s = this.GetSchema(schema); + if (!s.ExistsInDatabase()) return; + InternalSession.ExecuteSqlNonQuery("DROP DATABASE `" + schema + "`"); + } + + /// + /// Creates a schema/database with the given name. + /// + /// The name of the schema/database. + /// A object that matches the recently created schema/database. + public Schema CreateSchema(string schema) + { + InternalSession.ExecuteSqlNonQuery("CREATE DATABASE `" + schema + "`"); + return new Schema(this, schema); + } + + /// + /// Gets the schema with the given name. + /// + /// The name of the schema. + /// A object set with the provided schema name. + public Schema GetSchema(string schema) + { + this.Schema = new Schema(this, schema); + return this.Schema; + } + + /// + /// Gets a list of schemas (or databases) in this session. + /// + /// A list containing all existing schemas (or databases). + public List GetSchemas() + { + RowResult result = XSession.GetSqlRowResult("select * from information_schema.schemata"); + result.FetchAll(); + var query = from row in result.Rows + select new Schema(this, row.GetString("schema_name")); + return query.ToList(); + } + + /// + /// Starts a new transaction. + /// + public void StartTransaction() + { + InternalSession.ExecuteSqlNonQuery("START TRANSACTION"); + } + + /// + /// Commits the current transaction. + /// + /// A object containing the results of the commit operation. + public void Commit() + { + InternalSession.ExecuteSqlNonQuery("COMMIT"); + } + + /// + /// Rolls back the current transaction. + /// + public void Rollback() + { + InternalSession.ExecuteSqlNonQuery("ROLLBACK"); + } + + /// + /// Closes this session or releases it to the pool. + /// + public void Close() + { + if (XSession.SessionState != SessionState.Closed) + { + if (_client == null) + CloseFully(); + else + { + _client.ReleaseSession(this); + XSession.SetState(SessionState.Closed, false); + _internalSession = null; + } + } + } + + /// + /// Closes this session + /// + internal void CloseFully() + { + XSession.Close(); + } + + internal void Reset() + { + XSession.ResetSession(); + } + + #region Savepoints + + /// + /// Sets a transaction savepoint with an autogenerated name. + /// + /// The autogenerated name of the transaction savepoint. + public string SetSavepoint() + { + // Autogenerate the name of the savepoint. + return SetSavepoint($"savepoint_{Guid.NewGuid().ToString().Replace("-", "_")}"); + } + + /// + /// Sets a named transaction savepoint. + /// + /// The name of the transaction savepoint. + /// The name of the transaction savepoint. + public string SetSavepoint(string name) + { + InternalSession.ExecuteSqlNonQuery($"SAVEPOINT {name}"); + return name; + } + + /// + /// Removes the named savepoint from the set of savepoints within the current transaction. + /// + /// The name of the transaction savepoint. + public void ReleaseSavepoint(string name) + { + InternalSession.ExecuteSqlNonQuery($"RELEASE SAVEPOINT {name}"); + } + + /// + /// Rolls back a transaction to the named savepoint without terminating the transaction. + /// + /// The name of the transaction savepoint. + public void RollbackTo(string name) + { + InternalSession.ExecuteSqlNonQuery($"ROLLBACK TO {name}"); + } + + #endregion + + /// + /// Parses the connection data. + /// + /// The connection string or connection URI. + /// A object. + /// An updated connection string representation of the provided connection string or connection URI. + protected internal string ParseConnectionData(string connectionData, Client client = null) + { + if (client == null) + FailoverManager.Reset(); + + if (Regex.IsMatch(connectionData, @"^mysqlx(\+\w+)?://.*", RegexOptions.IgnoreCase)) + { + return ParseConnectionUri(connectionData); + } + else + return ParseConnectionString(connectionData); + } + + /// + /// Parses a connection URI. + /// + /// The connection URI to parse. + /// The connection string representation of the provided . + private string ParseConnectionUri(string connectionUri) + { + Uri uri = null; + string updatedUri = null; + bool parseServerAsUnixSocket = false; + string hierPart = null; + try + { + uri = new Uri(connectionUri); + } + catch (UriFormatException ex) + { + if (ex.Message != "Invalid URI: The hostname could not be parsed.") + throw; + + // Identify if multiple hosts were specified. + string[] splitUri = connectionUri.Split('@', '?'); + if (splitUri.Length == 1) throw; + + hierPart = splitUri[1]; + var schema = string.Empty; + parseServerAsUnixSocket = IsUnixSocket(hierPart); + bool isArray = hierPart.StartsWith("[") && hierPart.Contains("]"); + + // Remove schema. + if ((!parseServerAsUnixSocket && hierPart.Contains("/")) && !isArray || + (parseServerAsUnixSocket && hierPart.Contains(")/")) || + (hierPart.StartsWith("[") && hierPart.Contains("]/") && isArray)) + { + schema = hierPart.Substring(hierPart.LastIndexOf('/') + 1); + hierPart = hierPart.Substring(0, hierPart.Length - schema.Length - 1); + } + + if (parseServerAsUnixSocket) + { + updatedUri = splitUri[0] + "@localhost" + + (schema != string.Empty ? "/" + schema : string.Empty) + + (splitUri.Length > 2 ? "?" + splitUri[2] : string.Empty); + } + else if (isArray) + { + hierPart = hierPart.Substring(1, hierPart.Length - 2); + int hostCount = FailoverManager.ParseHostList(hierPart, true, true); + if (FailoverManager.FailoverGroup != null) + { + hierPart = FailoverManager.FailoverGroup.ActiveHost.Host; + parseServerAsUnixSocket = IsUnixSocket(FailoverManager.FailoverGroup.ActiveHost.Host); + updatedUri = splitUri[0] + "@" + + (parseServerAsUnixSocket ? "localhost" : hierPart) + + (FailoverManager.FailoverGroup.ActiveHost.Port != -1 ? ":" + FailoverManager.FailoverGroup.ActiveHost.Port : string.Empty) + + (schema != string.Empty ? "/" + schema : string.Empty) + + (splitUri.Length == 3 ? "?" + splitUri[2] : string.Empty); + } + else if (hostCount == 1) + updatedUri = splitUri[0] + "@" + hierPart + + (schema != string.Empty ? "/" + schema : string.Empty) + + (splitUri.Length == 3 ? "?" + splitUri[2] : string.Empty); + else + throw; + } + } + + if (uri == null) + uri = updatedUri == null ? new Uri(connectionUri) : new Uri(updatedUri); + + if (uri.Scheme == DNS_SRV_URI_SCHEME) + { + if (FailoverManager.FailoverGroup != null && FailoverManager.FailoverGroup.Hosts?.Count > 1) + throw new ArgumentException(Resources.DnsSrvInvalidConnOptionMultihost); + if (!uri.IsDefaultPort) + throw new ArgumentException(Resources.DnsSrvInvalidConnOptionPort); + if (parseServerAsUnixSocket) + throw new ArgumentException(Resources.DnsSrvInvalidConnOptionUnixSocket); + } + else if (uri.Scheme != MYSQLX_URI_SCHEME) + throw new ArgumentException(string.Format(ResourcesX.DnsSrvInvalidScheme, uri.Scheme)); + + return ConvertToConnectionString(uri, hierPart, parseServerAsUnixSocket, uri.Scheme == DNS_SRV_URI_SCHEME); + } + + /// + /// Validates if the string provided is a Unix socket file. + /// + /// The Unix socket to evaluate. + /// true if is a valid Unix socket; otherwise, false. + internal static bool IsUnixSocket(string unixSocket) + { + if (unixSocket.StartsWith(".") || + unixSocket.StartsWith("/") || + unixSocket.StartsWith("(.") || + unixSocket.StartsWith("(/") || + unixSocket.StartsWith("%2") || + unixSocket.StartsWith("(%2")) + return true; + + return false; + } + + /// + /// Converts the URI object into a connection string. + /// + /// An instance with the values for the provided connection options. + /// The path of the Unix socket file. + /// If true the replaces the value for the server connection option; otherwise, false + /// Flag indicating if this is a connection using DNS SRV. + /// A connection string. + private string ConvertToConnectionString(Uri uri, string unixSocketPath, bool parseServerAsUnixSocket, bool isDnsSrvScheme) + { + List connectionParts = new List(); + + if (string.IsNullOrWhiteSpace(uri.Host)) + throw new UriFormatException(ResourcesX.InvalidUriData + "host"); + connectionParts.Add("server=" + (parseServerAsUnixSocket ? + NormalizeUnixSocket(unixSocketPath) : + uri.Host)); + connectionParts.Add("port=" + (uri.Port == -1 ? 33060 : uri.Port)); + _isDefaultPort = uri.IsDefaultPort; + if (uri.Scheme == DNS_SRV_URI_SCHEME) + connectionParts.Add("dns-srv=true"); + + if (!string.IsNullOrWhiteSpace(uri.UserInfo)) + { + string[] userData = uri.UserInfo.Split(':'); + if (userData.Length > 2) + throw new UriFormatException(ResourcesX.InvalidUriData + "user info"); + connectionParts.Add("uid=" + System.Uri.UnescapeDataString(userData[0])); + if (userData.Length > 1) + connectionParts.Add("password=" + System.Uri.UnescapeDataString(userData[1])); + } + if (uri.Segments.Length > 2) + throw new UriFormatException(ResourcesX.InvalidUriData + "segments"); + if (uri.Segments.Length > 1) + { + connectionParts.Add("database=" + System.Uri.UnescapeDataString(uri.Segments[1])); + } + if (!string.IsNullOrWhiteSpace(uri.Query)) + { + string[] queries = System.Uri.UnescapeDataString(uri.Query).Substring(1).Split(new char[] { '&' }, StringSplitOptions.RemoveEmptyEntries); + foreach (string query in queries) + { + string[] keyValue = query.Replace(";", string.Empty).Split('='); + string part; + var connectionAttributesOption = MySqlXConnectionStringBuilder.Options.Options.First(item => item.Keyword == CONNECTION_ATTRIBUTES_CONNECTION_OPTION_KEYWORD); + var dnsSrvOption = MySqlXConnectionStringBuilder.Options.Options.First(item => item.Keyword == DNS_SRV_CONNECTION_OPTION_KEYWORD); + + if (!((connectionAttributesOption.Keyword == keyValue[0]) || connectionAttributesOption.Synonyms.Contains(keyValue[0]) && keyValue.Count() > 2)) + { + if (keyValue.Length > 2) + throw new ArgumentException(ResourcesX.InvalidUriQuery + ":" + keyValue[0]); + var connecttimeoutOption = MySqlXConnectionStringBuilder.Options.Options.First(item => item.Keyword == CONNECT_TIMEOUT_CONNECTION_OPTION_KEYWORD); + if ((connecttimeoutOption.Keyword == keyValue[0] || connecttimeoutOption.Synonyms.Contains(keyValue[0])) && + String.IsNullOrWhiteSpace(keyValue[1])) + throw new FormatException(ResourcesX.InvalidConnectionTimeoutValue); + part = keyValue[0] + "=" + (keyValue.Length == 2 ? keyValue[1] : "true").Replace("(", string.Empty).Replace(")", string.Empty); + } + else if (keyValue[1] == string.Empty) + throw new MySqlException(ResourcesX.InvalidUriQuery + ": " + keyValue[0]); + else + part = keyValue[0] + "=" + query.Replace(keyValue[0] + "=", string.Empty); + + if (isDnsSrvScheme && (dnsSrvOption.Keyword == keyValue[0] || dnsSrvOption.Synonyms.Contains(keyValue[0])) && !Convert.ToBoolean(keyValue[1])) + throw new ArgumentException(string.Format(ResourcesX.DnsSrvConflictingOptions, dnsSrvOption.Keyword)); + else if (isDnsSrvScheme && (dnsSrvOption.Keyword == keyValue[0] || dnsSrvOption.Synonyms.Contains(keyValue[0]))) + continue; + + connectionParts.Add(part); + } + } + + return string.Join("; ", connectionParts); + } + + /// + /// Parses a connection string. + /// + /// The connection string to parse. + /// The parsed connection string. + private string ParseConnectionString(string connectionString) + { + var updatedConnectionString = string.Empty; + bool portProvided = false; + bool isDnsSrv = false; + var connectionOptionsDictionary = connectionString.Split(CONNECTION_DATA_KEY_SEPARATOR) + .Select(item => item.Split(new char[] { CONNECTION_DATA_VALUE_SEPARATOR }, 2)) + .Where(item => item.Length == 2) + .ToDictionary(item => item[0], item => item[1]); + var serverOption = MySqlXConnectionStringBuilder.Options.Options.First(item => item.Keyword == SERVER_CONNECTION_OPTION_KEYWORD); + var connecttimeoutOption = MySqlXConnectionStringBuilder.Options.Options.First(item => item.Keyword == CONNECT_TIMEOUT_CONNECTION_OPTION_KEYWORD); + foreach (KeyValuePair keyValuePair in connectionOptionsDictionary) + { + // Value is an equal or a semicolon + if (keyValuePair.Value == "=" || keyValuePair.Value == "\"") + throw new MySqlException(string.Format(Resources.InvalidConnectionStringValue, (keyValuePair.Value == "\"" ? ";" : "="), keyValuePair.Key)); + + // Key is not server or any of its synonyms. + if (keyValuePair.Key != serverOption.Keyword && !serverOption.Synonyms.Contains(keyValuePair.Key)) + { + if ((connecttimeoutOption.Keyword == keyValuePair.Key || connecttimeoutOption.Synonyms.Contains(keyValuePair.Key)) && + String.IsNullOrWhiteSpace(keyValuePair.Value)) + throw new FormatException(ResourcesX.InvalidConnectionTimeoutValue); + if (keyValuePair.Key == PORT_CONNECTION_OPTION_KEYWORD) + portProvided = true; + if (keyValuePair.Key == DNS_SRV_CONNECTION_OPTION_KEYWORD) + isDnsSrv = Convert.ToBoolean(keyValuePair.Value); + + updatedConnectionString += $"{keyValuePair.Key}{CONNECTION_DATA_VALUE_SEPARATOR}{keyValuePair.Value}{CONNECTION_DATA_KEY_SEPARATOR}"; + continue; + } + + // Key is server or one of its synonyms. + var updatedValue = keyValuePair.Value; + if (IsUnixSocket(keyValuePair.Value)) + updatedValue = NormalizeUnixSocket(keyValuePair.Value); + + // The value for the server connection option doesn't have a server list format. + if (FailoverManager.ParseHostList(updatedValue, true, false) == 1 && FailoverManager.FailoverGroup == null) + updatedConnectionString = $"{SERVER_CONNECTION_OPTION_KEYWORD}{CONNECTION_DATA_VALUE_SEPARATOR}{updatedValue}{CONNECTION_DATA_KEY_SEPARATOR}{updatedConnectionString}"; + } + + // DNS SRV Validation - Port cannot be provided by the user and multihost is not allowed if dns-srv is true + if (isDnsSrv) + { + if (portProvided) + throw new ArgumentException(Resources.DnsSrvInvalidConnOptionPort); + if (FailoverManager.FailoverGroup != null) + throw new ArgumentException(Resources.DnsSrvInvalidConnOptionMultihost); + } + + // Default port must be added if not provided by the user. + if (FailoverManager.FailoverGroup == null) + return portProvided ? updatedConnectionString : $"{updatedConnectionString}{CONNECTION_DATA_KEY_SEPARATOR}{PORT_CONNECTION_OPTION_KEYWORD}{CONNECTION_DATA_VALUE_SEPARATOR}{X_PROTOCOL_DEFAULT_PORT}"; + + return $"{SERVER_CONNECTION_OPTION_KEYWORD}{CONNECTION_DATA_VALUE_SEPARATOR}{FailoverManager.FailoverGroup.ActiveHost.Host}{CONNECTION_DATA_KEY_SEPARATOR}" + + (!portProvided ? $"{PORT_CONNECTION_OPTION_KEYWORD}{CONNECTION_DATA_VALUE_SEPARATOR}{X_PROTOCOL_DEFAULT_PORT}{CONNECTION_DATA_KEY_SEPARATOR}" : string.Empty) + + updatedConnectionString; + } + + /// + /// Normalizes the Unix socket by removing leading and ending parenthesis as well as removing special characters. + /// + /// The Unix socket to normalize. + /// A normalized Unix socket. + internal static string NormalizeUnixSocket(string unixSocket) + { + unixSocket = unixSocket.Replace("%2F", "/"); + if (unixSocket.StartsWith("(") && unixSocket.EndsWith(")")) + unixSocket = unixSocket.Substring(1, unixSocket.Length - 2); + + return unixSocket; + } + + #region IDisposable Support + private bool disposedValue = false; // To detect redundant calls + + /// + /// Disposes the current object. Disposes of the managed state if the flag is set to true. + /// + /// Flag to indicate if the managed state is to be disposed. + protected virtual void Dispose(bool disposing) + { + if (!disposedValue) + { + if (disposing) + { + // dispose managed state (managed objects). + Close(); + } + + // free unmanaged resources (unmanaged objects) and override a finalizer below. + // set large fields to null. + + disposedValue = true; + } + } + + // override a finalizer only if Dispose(bool disposing) above has code to free unmanaged resources. + // ~BaseSession() { + // // Do not change this code. Put cleanup code in Dispose(bool disposing) above. + // Dispose(false); + // } + + /// + /// Disposes the current object. Code added to correctly implement the disposable pattern. + /// + public void Dispose() + { + // Do not change this code. Put cleanup code in Dispose(bool disposing) above. + Dispose(true); + // uncomment the following line if the finalizer is overridden above. + // GC.SuppressFinalize(this); + } + #endregion + } + + /// + /// Describes the state of the session. + /// + public enum SessionState + { + /// + /// The session is closed. + /// + Closed = 0, + /// + /// The session is open. + /// + Open = 1, + /// + /// The session object is connecting to the data source. + /// + Connecting = 2, + /// + /// The session object is executing a command. + /// + Executing = 4, + } +} diff --git a/MySQL.Data/src/X/XDevAPI/CRUD/AddStatement.cs b/MySQL.Data/src/X/XDevAPI/CRUD/AddStatement.cs index 01111c516..f200f0556 100644 --- a/MySQL.Data/src/X/XDevAPI/CRUD/AddStatement.cs +++ b/MySQL.Data/src/X/XDevAPI/CRUD/AddStatement.cs @@ -1,76 +1,76 @@ -// Copyright (c) 2015, 2023, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySqlX.XDevAPI.Common; -using System; -using System.Collections.Generic; -using System.Linq; - -namespace MySqlX.XDevAPI.CRUD -{ - /// - /// Represents a chaining collection insert statement. - /// - /// - public class AddStatement : CrudStatement - { - private List _Docs = new List(); - internal bool upsert; - - internal AddStatement(Collection collection) : base(collection) { } - - /// - /// Adds documents to the collection. - /// - /// The documents to add. - /// This object. - /// The array is null. - public AddStatement Add(params object[] items) - { - if (items == null) - throw new ArgumentNullException(); - - _Docs.AddRange(GetDocs(items)); - return this; - } - - /// - /// Executes the Add statement. - /// - /// A object containing the results of the execution. - public override Result Execute() - { - ValidateOpenSession(); - if (_Docs.Count == 0) - return new Result(null); - - //List newIds = AssignIds(); - return Target.Session.XSession.Insert(Target, _Docs.Cast().ToArray(), null, upsert); - } - } -} +// Copyright © 2015, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySqlX.XDevAPI.Common; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace MySqlX.XDevAPI.CRUD +{ + /// + /// Represents a chaining collection insert statement. + /// + /// + public class AddStatement : CrudStatement + { + private List _Docs = new List(); + internal bool upsert; + + internal AddStatement(Collection collection) : base(collection) { } + + /// + /// Adds documents to the collection. + /// + /// The documents to add. + /// This object. + /// The array is null. + public AddStatement Add(params object[] items) + { + if (items == null) + throw new ArgumentNullException(); + + _Docs.AddRange(GetDocs(items)); + return this; + } + + /// + /// Executes the Add statement. + /// + /// A object containing the results of the execution. + public override Result Execute() + { + ValidateOpenSession(); + if (_Docs.Count == 0) + return new Result(null); + + //List newIds = AssignIds(); + return Target.Session.XSession.Insert(Target, _Docs.Cast().ToArray(), null, upsert); + } + } +} diff --git a/MySQL.Data/src/X/XDevAPI/CRUD/CreateCollectionIndexStatement.cs b/MySQL.Data/src/X/XDevAPI/CRUD/CreateCollectionIndexStatement.cs index c96b3b445..40bd6ab9f 100644 --- a/MySQL.Data/src/X/XDevAPI/CRUD/CreateCollectionIndexStatement.cs +++ b/MySQL.Data/src/X/XDevAPI/CRUD/CreateCollectionIndexStatement.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2015, 2023, Oracle and/or its affiliates. +// Copyright © 2015, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/X/XDevAPI/CRUD/CreateIndexParams.cs b/MySQL.Data/src/X/XDevAPI/CRUD/CreateIndexParams.cs index 75a467837..7039bcd67 100644 --- a/MySQL.Data/src/X/XDevAPI/CRUD/CreateIndexParams.cs +++ b/MySQL.Data/src/X/XDevAPI/CRUD/CreateIndexParams.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2015, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/X/XDevAPI/CRUD/CrudStatement.cs b/MySQL.Data/src/X/XDevAPI/CRUD/CrudStatement.cs index 71f24b5af..f27d75b37 100644 --- a/MySQL.Data/src/X/XDevAPI/CRUD/CrudStatement.cs +++ b/MySQL.Data/src/X/XDevAPI/CRUD/CrudStatement.cs @@ -1,69 +1,69 @@ -// Copyright (c) 2015, 2023, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using System; -using System.Collections.Generic; -#if !NETFRAMEWORK -using System.Text.Json; -#endif -using MySqlX.XDevAPI.Common; - -namespace MySqlX.XDevAPI.CRUD -{ - /// - /// Represents a collection statement. - /// - /// Type of - /// Type of object - public abstract class CrudStatement : TargetedBaseStatement, TResult, T> - where TResult : Result - { - internal CrudStatement(Collection collection) : base(collection) - { - } - - /// - /// Converts base s into objects. - /// - /// Array of objects to be converted to objects. - /// An enumerable collection of objects. - protected IEnumerable GetDocs(object[] items) - { - foreach (object item in items) - { - if (typeof(T).Name == "DbDoc") - { - DbDoc d = item is DbDoc ? item as DbDoc : new DbDoc(item); - yield return (T)Convert.ChangeType(d, typeof(T)); - } - else - yield return (T)item; - } - } - } -} +// Copyright © 2015, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using System; +using System.Collections.Generic; +#if !NETFRAMEWORK +using System.Text.Json; +#endif +using MySqlX.XDevAPI.Common; + +namespace MySqlX.XDevAPI.CRUD +{ + /// + /// Represents a collection statement. + /// + /// Type of + /// Type of object + public abstract class CrudStatement : TargetedBaseStatement, TResult, T> + where TResult : Result + { + internal CrudStatement(Collection collection) : base(collection) + { + } + + /// + /// Converts base s into objects. + /// + /// Array of objects to be converted to objects. + /// An enumerable collection of objects. + protected IEnumerable GetDocs(object[] items) + { + foreach (object item in items) + { + if (typeof(T).Name == "DbDoc") + { + DbDoc d = item is DbDoc ? item as DbDoc : new DbDoc(item); + yield return (T)Convert.ChangeType(d, typeof(T)); + } + else + yield return (T)item; + } + } + } +} diff --git a/MySQL.Data/src/X/XDevAPI/CRUD/DocResult.cs b/MySQL.Data/src/X/XDevAPI/CRUD/DocResult.cs index cb6b0c068..5ee41f76c 100644 --- a/MySQL.Data/src/X/XDevAPI/CRUD/DocResult.cs +++ b/MySQL.Data/src/X/XDevAPI/CRUD/DocResult.cs @@ -1,74 +1,74 @@ -// Copyright (c) 2015, 2023, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using System.Collections.Generic; -using System.Diagnostics; -using MySqlX.XDevAPI.Common; -using MySqlX.Sessions; -using System; -using MySql.Data.MySqlClient; -#if !NETFRAMEWORK -using System.Text.Json; -#endif - -namespace MySqlX.XDevAPI.CRUD -{ - /// - /// Represents the result of an operation that includes a collection of documents. - /// - /// - public class DocResult : BufferingResult - { - System.Text.Encoding _encoding = System.Text.Encoding.UTF8; - - internal DocResult(InternalSession session) : base(session) - { - // this is just a single column "doc" - Debug.Assert(_columns.Count == 1); - } - - protected override T ReadItem(bool dumping) - { - List values = Protocol.ReadRow(this); - if (values == null) return default; - - Debug.Assert(values.Count == 1); - - if (typeof(T).Name == "DbDoc") - return (T)Convert.ChangeType(new DbDoc(_encoding.GetString(values[0]).TrimEnd('\0')), typeof(T)); - else - { -#if !NETFRAMEWORK - return JsonSerializer.Deserialize(_encoding.GetString(values[0]).TrimEnd('\0')); -#else - throw new MySqlException("Custom type mapping is only supported from .NET Core 3.1."); -#endif - } - } - } -} +// Copyright © 2015, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using System.Collections.Generic; +using System.Diagnostics; +using MySqlX.XDevAPI.Common; +using MySqlX.Sessions; +using System; +using MySql.Data.MySqlClient; +#if !NETFRAMEWORK +using System.Text.Json; +#endif + +namespace MySqlX.XDevAPI.CRUD +{ + /// + /// Represents the result of an operation that includes a collection of documents. + /// + /// + public class DocResult : BufferingResult + { + System.Text.Encoding _encoding = System.Text.Encoding.UTF8; + + internal DocResult(InternalSession session) : base(session) + { + // this is just a single column "doc" + Debug.Assert(_columns.Count == 1); + } + + protected override T ReadItem(bool dumping) + { + List values = Protocol.ReadRow(this); + if (values == null) return default; + + Debug.Assert(values.Count == 1); + + if (typeof(T).Name == "DbDoc") + return (T)Convert.ChangeType(new DbDoc(_encoding.GetString(values[0]).TrimEnd('\0')), typeof(T)); + else + { +#if !NETFRAMEWORK + return JsonSerializer.Deserialize(_encoding.GetString(values[0]).TrimEnd('\0')); +#else + throw new MySqlException("Custom type mapping is only supported from .NET Core 3.1."); +#endif + } + } + } +} diff --git a/MySQL.Data/src/X/XDevAPI/CRUD/FindParams.cs b/MySQL.Data/src/X/XDevAPI/CRUD/FindParams.cs index 7617f17db..b658b1380 100644 --- a/MySQL.Data/src/X/XDevAPI/CRUD/FindParams.cs +++ b/MySQL.Data/src/X/XDevAPI/CRUD/FindParams.cs @@ -1,43 +1,43 @@ -// Copyright © 2015, 2018, Oracle and/or its affiliates. All rights reserved. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySql.Data.MySqlClient; -using MySqlX.Protocol.X; -using MySqlX.XDevAPI.Common; - -namespace MySqlX.XDevAPI.CRUD -{ - internal class FindParams : FilterParams - { - public string[] GroupBy; - public string GroupByCritieria; - public string[] Projection; - public RowLock Locking; - public LockContention LockingOption; - } -} +// Copyright © 2015, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySql.Data.MySqlClient; +using MySqlX.Protocol.X; +using MySqlX.XDevAPI.Common; + +namespace MySqlX.XDevAPI.CRUD +{ + internal class FindParams : FilterParams + { + public string[] GroupBy; + public string GroupByCritieria; + public string[] Projection; + public RowLock Locking; + public LockContention LockingOption; + } +} diff --git a/MySQL.Data/src/X/XDevAPI/CRUD/FindStatement.cs b/MySQL.Data/src/X/XDevAPI/CRUD/FindStatement.cs index fb92bcbb5..813edad1f 100644 --- a/MySQL.Data/src/X/XDevAPI/CRUD/FindStatement.cs +++ b/MySQL.Data/src/X/XDevAPI/CRUD/FindStatement.cs @@ -1,172 +1,172 @@ -// Copyright (c) 2015, 2023, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySql.Data; -using MySql.Data.MySqlClient; -using MySqlX.XDevAPI.Common; -using System; -using System.Collections.Generic; - -namespace MySqlX.XDevAPI.CRUD -{ - /// - /// Represents a chaining collection find statement. - /// - /// - public class FindStatement : FilterableStatement, Collection, DocResult, T> - { - internal FindParams findParams = new FindParams(); - - internal FindStatement(Collection c, string condition) : base(c, condition) - { - } - - /// - /// List of column projections that shall be returned. - /// - /// List of columns. - /// This object set with the specified columns or fields. - public FindStatement Fields(params string[] columns) - { - if (columns == null) - return this; - - var projectionList = new List(); - foreach (var item in columns) - { - if (item != null) - projectionList.Add(item); - } - - findParams.Projection = projectionList.Count > 0 ? projectionList.ToArray() : null; - SetChanged(); - return this; - } - - /// - /// Executes the Find statement. - /// - /// A object containing the results of execution and data. - public override DocResult Execute() - { - return Execute(Target.Session.XSession.FindDocs, this); - } - - /// - /// Locks matching rows against updates. - /// - /// Optional row lock option to use. - /// This same object set with the lock shared option. - /// The server version is lower than 8.0.3. - public FindStatement LockShared(LockContention lockOption = LockContention.Default) - { - if (!this.Session.InternalSession.GetServerVersion().isAtLeast(8, 0, 3)) - throw new MySqlException(string.Format(ResourcesX.FunctionalityNotSupported, "8.0.3")); - - findParams.Locking = Protocol.X.RowLock.SharedLock; - findParams.LockingOption = lockOption; - SetChanged(); - return this; - } - - /// - /// Locks matching rows so no other transaction can read or write to it. - /// - /// Optional row lock option to use. - /// This same object set with the lock exclusive option. - /// The server version is lower than 8.0.3. - public FindStatement LockExclusive(LockContention lockOption = LockContention.Default) - { - if (!this.Session.InternalSession.GetServerVersion().isAtLeast(8, 0, 3)) - throw new MySqlException(string.Format(ResourcesX.FunctionalityNotSupported, "8.0.3")); - - findParams.Locking = Protocol.X.RowLock.ExclusiveLock; - findParams.LockingOption = lockOption; - SetChanged(); - return this; - } - - /// - /// Sets the collection aggregation. - /// - /// The field list for aggregation. - /// This same object set with the specified group-by criteria. - public FindStatement GroupBy(params string[] groupBy) - { - if (groupBy == null) - return this; - - var groupByList = new List(); - foreach (var item in groupBy) - { - if (item != null) - groupByList.Add(item); - } - - findParams.GroupBy = groupByList.Count > 0 ? groupByList.ToArray() : null; - SetChanged(); - return this; - } - - /// - /// Filters criteria for aggregated groups. - /// - /// The filter criteria for aggregated groups. - /// This same object set with the specified filter criteria. - public FindStatement Having(string having) - { - findParams.GroupByCritieria = having; - SetChanged(); - return this; - } - - /// - /// Sets user-defined sorting criteria for the operation. The strings use normal SQL syntax like - /// "order ASC" or "pages DESC, age ASC". - /// - /// The order criteria. - /// This same object set with the specified order criteria. - public FindStatement Sort(params string[] order) - { - FilterData.OrderBy = order; - SetChanged(); - return this; - } - - /// - /// Enables the setting of Where condition for this operation. - /// - /// The Where condition. - /// This same object set with the specified condition criteria. - [Obsolete("Where(string condition) has been deprecated since version 8.0.17.")] - public new FindStatement Where(string condition) - { - return base.Where(condition); - } - } -} +// Copyright © 2015, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySql.Data; +using MySql.Data.MySqlClient; +using MySqlX.XDevAPI.Common; +using System; +using System.Collections.Generic; + +namespace MySqlX.XDevAPI.CRUD +{ + /// + /// Represents a chaining collection find statement. + /// + /// + public class FindStatement : FilterableStatement, Collection, DocResult, T> + { + internal FindParams findParams = new FindParams(); + + internal FindStatement(Collection c, string condition) : base(c, condition) + { + } + + /// + /// List of column projections that shall be returned. + /// + /// List of columns. + /// This object set with the specified columns or fields. + public FindStatement Fields(params string[] columns) + { + if (columns == null) + return this; + + var projectionList = new List(); + foreach (var item in columns) + { + if (item != null) + projectionList.Add(item); + } + + findParams.Projection = projectionList.Count > 0 ? projectionList.ToArray() : null; + SetChanged(); + return this; + } + + /// + /// Executes the Find statement. + /// + /// A object containing the results of execution and data. + public override DocResult Execute() + { + return Execute(Target.Session.XSession.FindDocs, this); + } + + /// + /// Locks matching rows against updates. + /// + /// Optional row lock option to use. + /// This same object set with the lock shared option. + /// The server version is lower than 8.0.3. + public FindStatement LockShared(LockContention lockOption = LockContention.Default) + { + if (!this.Session.InternalSession.GetServerVersion().isAtLeast(8, 0, 3)) + throw new MySqlException(string.Format(ResourcesX.FunctionalityNotSupported, "8.0.3")); + + findParams.Locking = Protocol.X.RowLock.SharedLock; + findParams.LockingOption = lockOption; + SetChanged(); + return this; + } + + /// + /// Locks matching rows so no other transaction can read or write to it. + /// + /// Optional row lock option to use. + /// This same object set with the lock exclusive option. + /// The server version is lower than 8.0.3. + public FindStatement LockExclusive(LockContention lockOption = LockContention.Default) + { + if (!this.Session.InternalSession.GetServerVersion().isAtLeast(8, 0, 3)) + throw new MySqlException(string.Format(ResourcesX.FunctionalityNotSupported, "8.0.3")); + + findParams.Locking = Protocol.X.RowLock.ExclusiveLock; + findParams.LockingOption = lockOption; + SetChanged(); + return this; + } + + /// + /// Sets the collection aggregation. + /// + /// The field list for aggregation. + /// This same object set with the specified group-by criteria. + public FindStatement GroupBy(params string[] groupBy) + { + if (groupBy == null) + return this; + + var groupByList = new List(); + foreach (var item in groupBy) + { + if (item != null) + groupByList.Add(item); + } + + findParams.GroupBy = groupByList.Count > 0 ? groupByList.ToArray() : null; + SetChanged(); + return this; + } + + /// + /// Filters criteria for aggregated groups. + /// + /// The filter criteria for aggregated groups. + /// This same object set with the specified filter criteria. + public FindStatement Having(string having) + { + findParams.GroupByCritieria = having; + SetChanged(); + return this; + } + + /// + /// Sets user-defined sorting criteria for the operation. The strings use normal SQL syntax like + /// "order ASC" or "pages DESC, age ASC". + /// + /// The order criteria. + /// This same object set with the specified order criteria. + public FindStatement Sort(params string[] order) + { + FilterData.OrderBy = order; + SetChanged(); + return this; + } + + /// + /// Enables the setting of Where condition for this operation. + /// + /// The Where condition. + /// This same object set with the specified condition criteria. + [Obsolete("Where(string condition) has been deprecated since version 8.0.17.")] + public new FindStatement Where(string condition) + { + return base.Where(condition); + } + } +} diff --git a/MySQL.Data/src/X/XDevAPI/CRUD/ModifyStatement.cs b/MySQL.Data/src/X/XDevAPI/CRUD/ModifyStatement.cs index 6be178191..dc21975cf 100644 --- a/MySQL.Data/src/X/XDevAPI/CRUD/ModifyStatement.cs +++ b/MySQL.Data/src/X/XDevAPI/CRUD/ModifyStatement.cs @@ -1,199 +1,199 @@ -// Copyright (c) 2015, 2023, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySql.Data; -using MySql.Data.MySqlClient; -using Mysqlx.Crud; -using MySqlX.XDevAPI.Common; -using System; -using System.Collections.Generic; -#if !NETFRAMEWORK -using System.Text.Json; -#endif - -namespace MySqlX.XDevAPI.CRUD -{ - /// - /// Represents a chaining collection modify statement. - /// - /// - public class ModifyStatement : FilterableStatement, Collection, Result, T> - { - internal ModifyStatement(Collection collection, string condition) : base(collection, condition) - { - Updates = new List(); - } - - internal List Updates; - - /// - /// Sets key and value. - /// - /// The document path key. - /// The new value. - /// This object. - public ModifyStatement Set(string docPath, object value) - { - Updates.Add(new UpdateSpec(UpdateOperation.Types.UpdateType.ItemSet, docPath).SetValue(value)); - SetChanged(); - return this; - } - - /// - /// Changes value for a key. - /// - /// The document path key. - /// The new value. - /// This object. - public ModifyStatement Change(string docPath, object value) - { - Updates.Add(new UpdateSpec(UpdateOperation.Types.UpdateType.ItemReplace, docPath).SetValue(value)); - SetChanged(); - return this; - } - - /// - /// Removes keys or values from a document. - /// - /// An array of document paths representing the keys to be removed. - /// This object. - public ModifyStatement Unset(params string[] docPath) - { - if (docPath == null) - return this; - - foreach (var item in docPath) - { - if (item != null) - Updates.Add(new UpdateSpec(UpdateOperation.Types.UpdateType.ItemRemove, item)); - } - - SetChanged(); - return this; - } - - /// - /// Creates a object set with the changes to be applied to all matching documents. - /// - /// The JSON-formatted object describing the set of changes. - /// A object set with the changes described in . - /// can be a object, an anonymous object, a JSON string or a custom type object. - /// is null. - /// is null or white space. - public ModifyStatement Patch(object document) - { - if (document == null) - throw new ArgumentNullException(nameof(document)); - - if (document is string && string.IsNullOrWhiteSpace((string)document)) - throw new ArgumentNullException(nameof(document), Resources.ParameterNullOrEmpty); - - DbDoc dbDocument = document is DbDoc ? document as DbDoc : new DbDoc(document); - - if (dbDocument.values.Count == 0) - { -#if !NETFRAMEWORK - var customObject = JsonSerializer.Serialize(document); - Updates.Add(new UpdateSpec(UpdateOperation.Types.UpdateType.MergePatch, string.Empty).SetValue(customObject)); -#else - throw new MySqlException(ResourcesX.CustomTypeNotSupported); -#endif - } - else - Updates.Add(new UpdateSpec(UpdateOperation.Types.UpdateType.MergePatch, string.Empty).SetValue(dbDocument.values)); - - SetChanged(); - return this; - } - - /// - /// Inserts an item into the specified array. - /// - /// The document path key including the index on which the item will be inserted. - /// The value to insert into the array. - /// A object containing the updated array. - public ModifyStatement ArrayInsert(string field, object value) - { - if (value is string && value.ToString() == string.Empty) - throw new ArgumentException(nameof(value), Resources.StringEmpty); - - Updates.Add(new UpdateSpec(UpdateOperation.Types.UpdateType.ArrayInsert, field).SetValue(value)); - SetChanged(); - return this; - } - - /// - /// Appends an item to the specified array. - /// - /// The document path key. - /// The value to append to the array. - /// A object containing the updated array. - public ModifyStatement ArrayAppend(string docPath, object value) - { - if (value is string && value.ToString() == string.Empty) - throw new ArgumentException(nameof(value), Resources.StringEmpty); - - Updates.Add(new UpdateSpec(UpdateOperation.Types.UpdateType.ArrayAppend, docPath).SetValue(value)); - SetChanged(); - return this; - } - - /// - /// Allows the user to set the sorting criteria for the operation. The strings use normal SQL syntax like - /// "order ASC" or "pages DESC, age ASC". - /// - /// The order criteria. - /// A generic object representing the implementing statement type. - public ModifyStatement Sort(params string[] order) - { - FilterData.OrderBy = order; - SetChanged(); - return this; - } - - /// - /// Enables the setting of Where condition for this operation. - /// - /// The Where condition. - /// The implementing statement type. - [Obsolete("Where(string condition) has been deprecated since version 8.0.17.")] - public new ModifyStatement Where(string condition) - { - return base.Where(condition); - } - - /// - /// Executes the modify statement. - /// - /// A object containing the results of the execution. - public override Result Execute() - { - return Execute(Target.Session.XSession.ModifyDocs, this); - } - } -} +// Copyright © 2015, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySql.Data; +using MySql.Data.MySqlClient; +using Mysqlx.Crud; +using MySqlX.XDevAPI.Common; +using System; +using System.Collections.Generic; +#if !NETFRAMEWORK +using System.Text.Json; +#endif + +namespace MySqlX.XDevAPI.CRUD +{ + /// + /// Represents a chaining collection modify statement. + /// + /// + public class ModifyStatement : FilterableStatement, Collection, Result, T> + { + internal ModifyStatement(Collection collection, string condition) : base(collection, condition) + { + Updates = new List(); + } + + internal List Updates; + + /// + /// Sets key and value. + /// + /// The document path key. + /// The new value. + /// This object. + public ModifyStatement Set(string docPath, object value) + { + Updates.Add(new UpdateSpec(UpdateOperation.Types.UpdateType.ItemSet, docPath).SetValue(value)); + SetChanged(); + return this; + } + + /// + /// Changes value for a key. + /// + /// The document path key. + /// The new value. + /// This object. + public ModifyStatement Change(string docPath, object value) + { + Updates.Add(new UpdateSpec(UpdateOperation.Types.UpdateType.ItemReplace, docPath).SetValue(value)); + SetChanged(); + return this; + } + + /// + /// Removes keys or values from a document. + /// + /// An array of document paths representing the keys to be removed. + /// This object. + public ModifyStatement Unset(params string[] docPath) + { + if (docPath == null) + return this; + + foreach (var item in docPath) + { + if (item != null) + Updates.Add(new UpdateSpec(UpdateOperation.Types.UpdateType.ItemRemove, item)); + } + + SetChanged(); + return this; + } + + /// + /// Creates a object set with the changes to be applied to all matching documents. + /// + /// The JSON-formatted object describing the set of changes. + /// A object set with the changes described in . + /// can be a object, an anonymous object, a JSON string or a custom type object. + /// is null. + /// is null or white space. + public ModifyStatement Patch(object document) + { + if (document == null) + throw new ArgumentNullException(nameof(document)); + + if (document is string && string.IsNullOrWhiteSpace((string)document)) + throw new ArgumentNullException(nameof(document), Resources.ParameterNullOrEmpty); + + DbDoc dbDocument = document is DbDoc ? document as DbDoc : new DbDoc(document); + + if (dbDocument.values.Count == 0) + { +#if !NETFRAMEWORK + var customObject = JsonSerializer.Serialize(document); + Updates.Add(new UpdateSpec(UpdateOperation.Types.UpdateType.MergePatch, string.Empty).SetValue(customObject)); +#else + throw new MySqlException(ResourcesX.CustomTypeNotSupported); +#endif + } + else + Updates.Add(new UpdateSpec(UpdateOperation.Types.UpdateType.MergePatch, string.Empty).SetValue(dbDocument.values)); + + SetChanged(); + return this; + } + + /// + /// Inserts an item into the specified array. + /// + /// The document path key including the index on which the item will be inserted. + /// The value to insert into the array. + /// A object containing the updated array. + public ModifyStatement ArrayInsert(string field, object value) + { + if (value is string && value.ToString() == string.Empty) + throw new ArgumentException(nameof(value), Resources.StringEmpty); + + Updates.Add(new UpdateSpec(UpdateOperation.Types.UpdateType.ArrayInsert, field).SetValue(value)); + SetChanged(); + return this; + } + + /// + /// Appends an item to the specified array. + /// + /// The document path key. + /// The value to append to the array. + /// A object containing the updated array. + public ModifyStatement ArrayAppend(string docPath, object value) + { + if (value is string && value.ToString() == string.Empty) + throw new ArgumentException(nameof(value), Resources.StringEmpty); + + Updates.Add(new UpdateSpec(UpdateOperation.Types.UpdateType.ArrayAppend, docPath).SetValue(value)); + SetChanged(); + return this; + } + + /// + /// Allows the user to set the sorting criteria for the operation. The strings use normal SQL syntax like + /// "order ASC" or "pages DESC, age ASC". + /// + /// The order criteria. + /// A generic object representing the implementing statement type. + public ModifyStatement Sort(params string[] order) + { + FilterData.OrderBy = order; + SetChanged(); + return this; + } + + /// + /// Enables the setting of Where condition for this operation. + /// + /// The Where condition. + /// The implementing statement type. + [Obsolete("Where(string condition) has been deprecated since version 8.0.17.")] + public new ModifyStatement Where(string condition) + { + return base.Where(condition); + } + + /// + /// Executes the modify statement. + /// + /// A object containing the results of the execution. + public override Result Execute() + { + return Execute(Target.Session.XSession.ModifyDocs, this); + } + } +} diff --git a/MySQL.Data/src/X/XDevAPI/CRUD/RemoveStatement.cs b/MySQL.Data/src/X/XDevAPI/CRUD/RemoveStatement.cs index f7d4210a3..de06ca276 100644 --- a/MySQL.Data/src/X/XDevAPI/CRUD/RemoveStatement.cs +++ b/MySQL.Data/src/X/XDevAPI/CRUD/RemoveStatement.cs @@ -1,77 +1,77 @@ -// Copyright (c) 2015, 2023, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySqlX.XDevAPI.Common; -using System; - -namespace MySqlX.XDevAPI.CRUD -{ - /// - /// Represents a chaining collection remove statement. - /// - /// - public class RemoveStatement : FilterableStatement, Collection, Result, T> - { - internal RemoveStatement(Collection collection, string condition) : base(collection, condition) - { - } - - /// - /// Sets user-defined sorting criteria for the operation. The strings use normal SQL syntax like - /// "order ASC" or "pages DESC, age ASC". - /// - /// The order criteria. - /// A generic object representing the implementing statement type. - public RemoveStatement Sort(params string[] order) - { - FilterData.OrderBy = order; - SetChanged(); - return this; - } - - /// - /// Enables the setting of Where condition for this operation. - /// - /// The Where condition. - /// The implementing statement type. - [Obsolete("Where(string condition) has been deprecated since version 8.0.17.")] - public new RemoveStatement Where(string condition) - { - return base.Where(condition); - } - - /// - /// Executes the remove statement. - /// - /// A object containing the results of the execution. - public override Result Execute() - { - return Execute(Target.Session.XSession.DeleteDocs, this); - } - } -} +// Copyright © 2015, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySqlX.XDevAPI.Common; +using System; + +namespace MySqlX.XDevAPI.CRUD +{ + /// + /// Represents a chaining collection remove statement. + /// + /// + public class RemoveStatement : FilterableStatement, Collection, Result, T> + { + internal RemoveStatement(Collection collection, string condition) : base(collection, condition) + { + } + + /// + /// Sets user-defined sorting criteria for the operation. The strings use normal SQL syntax like + /// "order ASC" or "pages DESC, age ASC". + /// + /// The order criteria. + /// A generic object representing the implementing statement type. + public RemoveStatement Sort(params string[] order) + { + FilterData.OrderBy = order; + SetChanged(); + return this; + } + + /// + /// Enables the setting of Where condition for this operation. + /// + /// The Where condition. + /// The implementing statement type. + [Obsolete("Where(string condition) has been deprecated since version 8.0.17.")] + public new RemoveStatement Where(string condition) + { + return base.Where(condition); + } + + /// + /// Executes the remove statement. + /// + /// A object containing the results of the execution. + public override Result Execute() + { + return Execute(Target.Session.XSession.DeleteDocs, this); + } + } +} diff --git a/MySQL.Data/src/X/XDevAPI/CRUD/UpdateSpec.cs b/MySQL.Data/src/X/XDevAPI/CRUD/UpdateSpec.cs index d338cc29d..d6c76c627 100644 --- a/MySQL.Data/src/X/XDevAPI/CRUD/UpdateSpec.cs +++ b/MySQL.Data/src/X/XDevAPI/CRUD/UpdateSpec.cs @@ -1,109 +1,109 @@ -// Copyright (c) 2015, 2022, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySql.Data; -using Mysqlx.Crud; -using Mysqlx.Expr; -using MySqlX.Protocol.X; -using MySqlX.Serialization; -using System; -using static Mysqlx.Crud.UpdateOperation.Types; - -namespace MySqlX.XDevAPI.CRUD -{ - internal class UpdateSpec - { - public UpdateSpec(UpdateOperation.Types.UpdateType updateType, string docPath) - { - if (updateType is not UpdateOperation.Types.UpdateType.MergePatch && string.IsNullOrWhiteSpace(docPath)) - throw new ArgumentException(ResourcesX.DocPathNullOrEmpty); - - Type = updateType; - Path = docPath; - } - - public string Path { get; private set; } - public UpdateOperation.Types.UpdateType Type { get; private set; } - public object Value { get; private set; } - - public bool HasValue - { - get { return Value != null; } - } - - public Expr GetValue(UpdateType operationType) - { - bool evaluateStringExpression = true; - if (operationType == UpdateType.ArrayAppend || operationType == UpdateType.ArrayInsert || operationType == UpdateType.ItemSet) - { - Value = ExprUtil.ParseAnonymousObject(Value) ?? Value; - if (Value is string) - { - try - { - JsonParser.Parse(Value as string); - } - catch (Exception) - { - evaluateStringExpression = false; - } - } - } - - return ExprUtil.ArgObjectToExpr(Value, false, evaluateStringExpression); - } - - public ColumnIdentifier GetSource(bool isRelational) - { - var source = Path; - - // accomodate parser's documentField() handling by removing "@" - if (source.Length > 0 && source[0] == '@') - source = source.Substring(1); - - ExprParser p = new ExprParser(source, false); - ColumnIdentifier identifier; - - if (isRelational) - identifier = p.ParseTableUpdateField(); - else - identifier = p.DocumentField().Identifier; - - if (p.tokenPos < p.tokens.Count) - throw new ArgumentException("Invalid document path."); - - return identifier; - } - - public UpdateSpec SetValue(object o) - { - Value = o; - return this; - } - } -} +// Copyright © 2015, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySql.Data; +using Mysqlx.Crud; +using Mysqlx.Expr; +using MySqlX.Protocol.X; +using MySqlX.Serialization; +using System; +using static Mysqlx.Crud.UpdateOperation.Types; + +namespace MySqlX.XDevAPI.CRUD +{ + internal class UpdateSpec + { + public UpdateSpec(UpdateOperation.Types.UpdateType updateType, string docPath) + { + if (updateType is not UpdateOperation.Types.UpdateType.MergePatch && string.IsNullOrWhiteSpace(docPath)) + throw new ArgumentException(ResourcesX.DocPathNullOrEmpty); + + Type = updateType; + Path = docPath; + } + + public string Path { get; private set; } + public UpdateOperation.Types.UpdateType Type { get; private set; } + public object Value { get; private set; } + + public bool HasValue + { + get { return Value != null; } + } + + public Expr GetValue(UpdateType operationType) + { + bool evaluateStringExpression = true; + if (operationType == UpdateType.ArrayAppend || operationType == UpdateType.ArrayInsert || operationType == UpdateType.ItemSet) + { + Value = ExprUtil.ParseAnonymousObject(Value) ?? Value; + if (Value is string) + { + try + { + JsonParser.Parse(Value as string); + } + catch (Exception) + { + evaluateStringExpression = false; + } + } + } + + return ExprUtil.ArgObjectToExpr(Value, false, evaluateStringExpression); + } + + public ColumnIdentifier GetSource(bool isRelational) + { + var source = Path; + + // accomodate parser's documentField() handling by removing "@" + if (source.Length > 0 && source[0] == '@') + source = source.Substring(1); + + ExprParser p = new ExprParser(source, false); + ColumnIdentifier identifier; + + if (isRelational) + identifier = p.ParseTableUpdateField(); + else + identifier = p.DocumentField().Identifier; + + if (p.tokenPos < p.tokens.Count) + throw new ArgumentException("Invalid document path."); + + return identifier; + } + + public UpdateSpec SetValue(object o) + { + Value = o; + return this; + } + } +} diff --git a/MySQL.Data/src/X/XDevAPI/Client.cs b/MySQL.Data/src/X/XDevAPI/Client.cs index bb69ed047..69d5e2749 100644 --- a/MySQL.Data/src/X/XDevAPI/Client.cs +++ b/MySQL.Data/src/X/XDevAPI/Client.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2018, 2022, Oracle and/or its affiliates. +// Copyright © 2018, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/X/XDevAPI/Collection.cs b/MySQL.Data/src/X/XDevAPI/Collection.cs index 9c612b916..fd9da2702 100644 --- a/MySQL.Data/src/X/XDevAPI/Collection.cs +++ b/MySQL.Data/src/X/XDevAPI/Collection.cs @@ -1,191 +1,191 @@ -// Copyright (c) 2015, 2023, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySql.Data; -using MySql.Data.MySqlClient; -using MySqlX.XDevAPI.Common; -using MySqlX.XDevAPI.CRUD; -using System; - -namespace MySqlX.XDevAPI -{ - /// - /// Represents a collection of documents. - /// - public class Collection : Collection - { - internal Collection(Schema schema, string name) - : base(schema, name) - { - } - - #region Add Operations - - /// - /// Creates an containing the provided objects that can be used to add - /// one or more items to a collection. - /// - /// The objects to add. - /// An object containing the objects to add. - /// is null. - /// This method can take anonymous objects, domain objects, or just plain JSON strings. - /// The statement can be further modified before execution. - public new AddStatement Add(params object[] items) => base.Add(items); - - #endregion - - #region Remove Operations - - /// - /// Creates a with the given condition that can be used to remove - /// one or more documents from a collection.The statement can then be further modified before execution. - /// - /// The condition to match documents. - /// A object set with the given condition. - /// is null or white space. - /// The statement can then be further modified before execution. - public new RemoveStatement Remove(string condition) => base.Remove(condition); - - #endregion - - #region Modify Operations - - /// - /// Creates a with the given condition that can be used to modify one or more - /// documents from a collection. - /// - /// The condition to match documents. - /// A object set with the given condition. - /// is null or white space. - /// The statement can then be further modified before execution. - public new ModifyStatement Modify(string condition) => base.Modify(condition); - - /// - /// Replaces the document matching the given identifier. - /// - /// The unique identifier of the document to replace. - /// The document to replace the matching document. - /// A object containing the results of the execution. - /// is null or whitespace. - /// is null. - /// This is a direct execution method. Operation succeeds even if no matching document was found; - /// in which case, the Result.RecordsAffected property is zero. If the new document contains an identifier, the value - /// is ignored. - public Result ReplaceOne(object id, object doc) - { - if (id == null) - throw new ArgumentNullException(nameof(id)); - string stringId = id.ToString(); - if (string.IsNullOrWhiteSpace(stringId)) - throw new ArgumentNullException(nameof(id), Resources.ParameterNullOrEmpty); - if (doc == null) - throw new ArgumentNullException(nameof(doc)); - - DbDoc currentDocument = GetOne(id); - var modify = Modify("_id = :id").Bind("id", stringId); - DbDoc newDocument = doc is DbDoc ? doc as DbDoc : new DbDoc(doc); - - if (currentDocument != null) - { - // check for not matching id's - if (newDocument.HasId && !newDocument.Id.Equals(currentDocument.Id)) - throw new MySqlException(ResourcesX.ReplaceWithNoMatchingId); - - // Unset all properties - foreach (var dictionary in currentDocument.values) - if (dictionary.Key != "_id") modify.Unset(dictionary.Key); - } - - // Set new properties - foreach (var dictionary in newDocument.values) - if (dictionary.Key != "_id") modify.Set(dictionary.Key, dictionary.Value); - - return modify.Execute(); - } - #endregion - - #region Add-Modify Operations - - /// - /// Adds the given document to the collection unless the identifier or any other field that has a unique index - /// already exists, in which case it will update the matching document. - /// - /// The unique identifier of the document to replace. - /// The document to replace the matching document. - /// A object containing the results of the execution. - /// The server version is lower than 8.0.3. - /// is null or white space. - /// is null. - /// The is different from the one in . - /// This is a direct execution method. - public Result AddOrReplaceOne(object id, object doc) - { - if (!this.Session.InternalSession.GetServerVersion().isAtLeast(8, 0, 3)) - throw new MySqlException(string.Format(ResourcesX.FunctionalityNotSupported, "8.0.3")); - if (id == null) - throw new ArgumentNullException(nameof(id)); - string stringId = id.ToString(); - if (string.IsNullOrWhiteSpace(stringId)) - throw new ArgumentNullException(nameof(id), Resources.ParameterNullOrEmpty); - if (doc == null) - throw new ArgumentNullException(nameof(doc)); - - DbDoc currentDocument = GetOne(id); - DbDoc newDocument = doc is DbDoc ? doc as DbDoc : new DbDoc(doc); - - // check for not matching id's - if (currentDocument != null && newDocument.HasId - && !newDocument.Id.Equals(currentDocument.Id)) - throw new MySqlException(ResourcesX.ReplaceWithNoMatchingId); - - newDocument.Id = id; - AddStatement stmt = Add(newDocument); - stmt.upsert = true; - return stmt.Execute(); - } - #endregion - - /// - /// Creates a with the given condition, which can be used to find documents in a - /// collection. - /// - /// An optional condition to match documents. - /// A object set with the given condition. - /// The statement can then be further modified before execution. - public new FindStatement Find(string condition = null) => base.Find(condition); - - /// - /// Returns the document with the given identifier. - /// - /// The unique identifier of the document to replace. - /// A object if a document matching given identifier exists; otherwise, null. - /// is null or white space. - /// This is a direct execution method. - public new DbDoc GetOne(object id) => base.GetOne(id); - } -} +// Copyright © 2015, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySql.Data; +using MySql.Data.MySqlClient; +using MySqlX.XDevAPI.Common; +using MySqlX.XDevAPI.CRUD; +using System; + +namespace MySqlX.XDevAPI +{ + /// + /// Represents a collection of documents. + /// + public class Collection : Collection + { + internal Collection(Schema schema, string name) + : base(schema, name) + { + } + + #region Add Operations + + /// + /// Creates an containing the provided objects that can be used to add + /// one or more items to a collection. + /// + /// The objects to add. + /// An object containing the objects to add. + /// is null. + /// This method can take anonymous objects, domain objects, or just plain JSON strings. + /// The statement can be further modified before execution. + public new AddStatement Add(params object[] items) => base.Add(items); + + #endregion + + #region Remove Operations + + /// + /// Creates a with the given condition that can be used to remove + /// one or more documents from a collection.The statement can then be further modified before execution. + /// + /// The condition to match documents. + /// A object set with the given condition. + /// is null or white space. + /// The statement can then be further modified before execution. + public new RemoveStatement Remove(string condition) => base.Remove(condition); + + #endregion + + #region Modify Operations + + /// + /// Creates a with the given condition that can be used to modify one or more + /// documents from a collection. + /// + /// The condition to match documents. + /// A object set with the given condition. + /// is null or white space. + /// The statement can then be further modified before execution. + public new ModifyStatement Modify(string condition) => base.Modify(condition); + + /// + /// Replaces the document matching the given identifier. + /// + /// The unique identifier of the document to replace. + /// The document to replace the matching document. + /// A object containing the results of the execution. + /// is null or whitespace. + /// is null. + /// This is a direct execution method. Operation succeeds even if no matching document was found; + /// in which case, the Result.RecordsAffected property is zero. If the new document contains an identifier, the value + /// is ignored. + public Result ReplaceOne(object id, object doc) + { + if (id == null) + throw new ArgumentNullException(nameof(id)); + string stringId = id.ToString(); + if (string.IsNullOrWhiteSpace(stringId)) + throw new ArgumentNullException(nameof(id), Resources.ParameterNullOrEmpty); + if (doc == null) + throw new ArgumentNullException(nameof(doc)); + + DbDoc currentDocument = GetOne(id); + var modify = Modify("_id = :id").Bind("id", stringId); + DbDoc newDocument = doc is DbDoc ? doc as DbDoc : new DbDoc(doc); + + if (currentDocument != null) + { + // check for not matching id's + if (newDocument.HasId && !newDocument.Id.Equals(currentDocument.Id)) + throw new MySqlException(ResourcesX.ReplaceWithNoMatchingId); + + // Unset all properties + foreach (var dictionary in currentDocument.values) + if (dictionary.Key != "_id") modify.Unset(dictionary.Key); + } + + // Set new properties + foreach (var dictionary in newDocument.values) + if (dictionary.Key != "_id") modify.Set(dictionary.Key, dictionary.Value); + + return modify.Execute(); + } + #endregion + + #region Add-Modify Operations + + /// + /// Adds the given document to the collection unless the identifier or any other field that has a unique index + /// already exists, in which case it will update the matching document. + /// + /// The unique identifier of the document to replace. + /// The document to replace the matching document. + /// A object containing the results of the execution. + /// The server version is lower than 8.0.3. + /// is null or white space. + /// is null. + /// The is different from the one in . + /// This is a direct execution method. + public Result AddOrReplaceOne(object id, object doc) + { + if (!this.Session.InternalSession.GetServerVersion().isAtLeast(8, 0, 3)) + throw new MySqlException(string.Format(ResourcesX.FunctionalityNotSupported, "8.0.3")); + if (id == null) + throw new ArgumentNullException(nameof(id)); + string stringId = id.ToString(); + if (string.IsNullOrWhiteSpace(stringId)) + throw new ArgumentNullException(nameof(id), Resources.ParameterNullOrEmpty); + if (doc == null) + throw new ArgumentNullException(nameof(doc)); + + DbDoc currentDocument = GetOne(id); + DbDoc newDocument = doc is DbDoc ? doc as DbDoc : new DbDoc(doc); + + // check for not matching id's + if (currentDocument != null && newDocument.HasId + && !newDocument.Id.Equals(currentDocument.Id)) + throw new MySqlException(ResourcesX.ReplaceWithNoMatchingId); + + newDocument.Id = id; + AddStatement stmt = Add(newDocument); + stmt.upsert = true; + return stmt.Execute(); + } + #endregion + + /// + /// Creates a with the given condition, which can be used to find documents in a + /// collection. + /// + /// An optional condition to match documents. + /// A object set with the given condition. + /// The statement can then be further modified before execution. + public new FindStatement Find(string condition = null) => base.Find(condition); + + /// + /// Returns the document with the given identifier. + /// + /// The unique identifier of the document to replace. + /// A object if a document matching given identifier exists; otherwise, null. + /// is null or white space. + /// This is a direct execution method. + public new DbDoc GetOne(object id) => base.GetOne(id); + } +} diff --git a/MySQL.Data/src/X/XDevAPI/Common/BaseResult.cs b/MySQL.Data/src/X/XDevAPI/Common/BaseResult.cs index e79e2bf4d..af7a8faf3 100644 --- a/MySQL.Data/src/X/XDevAPI/Common/BaseResult.cs +++ b/MySQL.Data/src/X/XDevAPI/Common/BaseResult.cs @@ -1,114 +1,114 @@ -// Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using System.Collections.Generic; -using MySqlX.Protocol; -using MySqlX.Sessions; -using System.Collections.ObjectModel; -using System; - -namespace MySqlX.XDevAPI.Common -{ - /// - /// Base abstract class that defines elements inherited by all result types. - /// - public abstract class BaseResult - { - private List _warnings = new List(); - internal ulong _recordsAffected; - internal ulong _affectedItemsCount; - internal ulong _autoIncrementValue; - internal InternalSession _session; - internal bool _hasData; - internal bool _hasMoreResults = false; - internal List _documentIds = new List(); - - /// - /// Gets the number of records affected by the statement that generated this result. - /// - public UInt64 AffectedItemsCount - { - get { return _affectedItemsCount; } - } - - internal BaseResult(InternalSession session) - { - if (session == null) return; - _session = session; - - // if we have an active resultset then we must buffer it entirely - if (session.ActiveResult != null) - { - session.ActiveResult.Buffer(); - session.ActiveResult = null; - } - - _hasData = Protocol.HasData(this); - if (_hasData) - session.ActiveResult = this; - } - - /// - /// Gets the object of the session. - /// - protected ProtocolBase Protocol - { - get { return _session?.GetProtocol(); } - } - - internal void AddWarning(WarningInfo w) - { - _warnings.Add(w); - } - - /// - /// Gets a read-only collection of objects derived from statement execution. - /// -#if NET_45_OR_GREATER - public IReadOnlyList Warnings -#else - public ReadOnlyCollection Warnings -#endif - { - get { return _warnings.AsReadOnly(); } - } - - /// - /// Gets the number of warnings in the collection derived from statement execution. - /// - public Int32 WarningsCount - { - get { return _warnings.Count; } - } - - /// - /// No action is performed by this method. It is intended to be overriden by child classes if required. - /// - protected virtual void Buffer() { } - } -} +// Copyright © 2015, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using System.Collections.Generic; +using MySqlX.Protocol; +using MySqlX.Sessions; +using System.Collections.ObjectModel; +using System; + +namespace MySqlX.XDevAPI.Common +{ + /// + /// Base abstract class that defines elements inherited by all result types. + /// + public abstract class BaseResult + { + private List _warnings = new List(); + internal ulong _recordsAffected; + internal ulong _affectedItemsCount; + internal ulong _autoIncrementValue; + internal InternalSession _session; + internal bool _hasData; + internal bool _hasMoreResults = false; + internal List _documentIds = new List(); + + /// + /// Gets the number of records affected by the statement that generated this result. + /// + public UInt64 AffectedItemsCount + { + get { return _affectedItemsCount; } + } + + internal BaseResult(InternalSession session) + { + if (session == null) return; + _session = session; + + // if we have an active resultset then we must buffer it entirely + if (session.ActiveResult != null) + { + session.ActiveResult.Buffer(); + session.ActiveResult = null; + } + + _hasData = Protocol.HasData(this); + if (_hasData) + session.ActiveResult = this; + } + + /// + /// Gets the object of the session. + /// + protected ProtocolBase Protocol + { + get { return _session?.GetProtocol(); } + } + + internal void AddWarning(WarningInfo w) + { + _warnings.Add(w); + } + + /// + /// Gets a read-only collection of objects derived from statement execution. + /// +#if NET_45_OR_GREATER + public IReadOnlyList Warnings +#else + public ReadOnlyCollection Warnings +#endif + { + get { return _warnings.AsReadOnly(); } + } + + /// + /// Gets the number of warnings in the collection derived from statement execution. + /// + public Int32 WarningsCount + { + get { return _warnings.Count; } + } + + /// + /// No action is performed by this method. It is intended to be overriden by child classes if required. + /// + protected virtual void Buffer() { } + } +} diff --git a/MySQL.Data/src/X/XDevAPI/Common/BaseStatement.cs b/MySQL.Data/src/X/XDevAPI/Common/BaseStatement.cs index f28f811b9..a335a59fa 100644 --- a/MySQL.Data/src/X/XDevAPI/Common/BaseStatement.cs +++ b/MySQL.Data/src/X/XDevAPI/Common/BaseStatement.cs @@ -1,163 +1,163 @@ -// Copyright (c) 2015, 2023, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySql.Data; -using MySql.Data.MySqlClient; -using MySqlX.XDevAPI.Relational; -using System; -using System.Collections; -using System.Threading; -using System.Threading.Tasks; - -namespace MySqlX.XDevAPI.Common -{ - /// - /// Base abstract class for API statement. - /// - /// - /// - public abstract class BaseStatement where TResult : BaseResult - { - // Prepared statements flags - internal bool _hasChanged, _isPrepared; - protected int _stmtId; - - /// - /// Initializes a new instance of the BaseStatement class based on the specified session. - /// - /// The session where the statement will be executed. - public BaseStatement(BaseSession session) - { - Session = session; - _hasChanged = true; - } - - /// - /// Gets the that owns the statement. - /// - public BaseSession Session { get; private set; } - - /// - /// Executes the base statements. This method is intended to be defined by child classes. - /// - /// A result object containing the details of the execution. - public abstract TResult Execute(); - - /// - /// Executes a statement asynchronously. - /// - /// A result object containing the details of the execution. - public async Task ExecuteAsync() - { - return await Task.Factory.StartNew(() => - { - var result = Execute(); - if (result is BufferingResult) - { - (result as BufferingResult).FetchAll(); - } - else if (result is BufferingResult) - { - (result as BufferingResult).FetchAll(); - } - return result; - }, - CancellationToken.None, - TaskCreationOptions.None, - Session._scheduler); - } - - /// - /// Validates if the session is open and valid. - /// - protected void ValidateOpenSession() - { - if (Session.XSession.SessionState != SessionState.Open) - throw new MySqlException(ResourcesX.InvalidSession); - } - - /// - /// Sets the status as Changed for prepared statement validation. - /// - protected void SetChanged() - { - _hasChanged = true; - } - - /// - /// Converts a statement to prepared statement for a second execution - /// without any change but Bind, Limit, or Offset. - /// - protected virtual TResult ConvertToPreparedStatement(Func executeFunc, T t, IEnumerable args) - //where T : FilterableStatement - { - if (!Session.SupportsPreparedStatements) - { - // Normal execution - return executeFunc(t); - } - - if (_hasChanged) - { - if (_isPrepared) - { - // Deallocate prepared statement - Session.XSession.DeallocatePreparedStatement(_stmtId); - _isPrepared = false; - } - // Normal execution - return executeFunc(t); - } - else - { - if (!_isPrepared) - { - // Create prepared statement - try - { - _stmtId = Session.XSession.PrepareStatement(this); - _isPrepared = true; - } - catch (MySqlException ex) - when (ex.Code == 1461 // Can't create more than max_prepared_stmt_count statements - || ex.Code == 1047) // Unexpected message received - { - // Set prepared statements not supported to avoid trying it - // on following executions. - Session.SupportsPreparedStatements = false; - _isPrepared = false; - // Normal execution - return executeFunc(t); - } - } - // Execute prepared statement - return Session.XSession.ExecutePreparedStatement(_stmtId, args); - } - } - } -} +// Copyright © 2015, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySql.Data; +using MySql.Data.MySqlClient; +using MySqlX.XDevAPI.Relational; +using System; +using System.Collections; +using System.Threading; +using System.Threading.Tasks; + +namespace MySqlX.XDevAPI.Common +{ + /// + /// Base abstract class for API statement. + /// + /// + /// + public abstract class BaseStatement where TResult : BaseResult + { + // Prepared statements flags + internal bool _hasChanged, _isPrepared; + protected int _stmtId; + + /// + /// Initializes a new instance of the BaseStatement class based on the specified session. + /// + /// The session where the statement will be executed. + public BaseStatement(BaseSession session) + { + Session = session; + _hasChanged = true; + } + + /// + /// Gets the that owns the statement. + /// + public BaseSession Session { get; private set; } + + /// + /// Executes the base statements. This method is intended to be defined by child classes. + /// + /// A result object containing the details of the execution. + public abstract TResult Execute(); + + /// + /// Executes a statement asynchronously. + /// + /// A result object containing the details of the execution. + public async Task ExecuteAsync() + { + return await Task.Factory.StartNew(() => + { + var result = Execute(); + if (result is BufferingResult) + { + (result as BufferingResult).FetchAll(); + } + else if (result is BufferingResult) + { + (result as BufferingResult).FetchAll(); + } + return result; + }, + CancellationToken.None, + TaskCreationOptions.None, + Session._scheduler); + } + + /// + /// Validates if the session is open and valid. + /// + protected void ValidateOpenSession() + { + if (Session.XSession.SessionState != SessionState.Open) + throw new MySqlException(ResourcesX.InvalidSession); + } + + /// + /// Sets the status as Changed for prepared statement validation. + /// + protected void SetChanged() + { + _hasChanged = true; + } + + /// + /// Converts a statement to prepared statement for a second execution + /// without any change but Bind, Limit, or Offset. + /// + protected virtual TResult ConvertToPreparedStatement(Func executeFunc, T t, IEnumerable args) + //where T : FilterableStatement + { + if (!Session.SupportsPreparedStatements) + { + // Normal execution + return executeFunc(t); + } + + if (_hasChanged) + { + if (_isPrepared) + { + // Deallocate prepared statement + Session.XSession.DeallocatePreparedStatement(_stmtId); + _isPrepared = false; + } + // Normal execution + return executeFunc(t); + } + else + { + if (!_isPrepared) + { + // Create prepared statement + try + { + _stmtId = Session.XSession.PrepareStatement(this); + _isPrepared = true; + } + catch (MySqlException ex) + when (ex.Code == 1461 // Can't create more than max_prepared_stmt_count statements + || ex.Code == 1047) // Unexpected message received + { + // Set prepared statements not supported to avoid trying it + // on following executions. + Session.SupportsPreparedStatements = false; + _isPrepared = false; + // Normal execution + return executeFunc(t); + } + } + // Execute prepared statement + return Session.XSession.ExecutePreparedStatement(_stmtId, args); + } + } + } +} diff --git a/MySQL.Data/src/X/XDevAPI/Common/BufferingResult.cs b/MySQL.Data/src/X/XDevAPI/Common/BufferingResult.cs index 74637c2b1..ae7c87bca 100644 --- a/MySQL.Data/src/X/XDevAPI/Common/BufferingResult.cs +++ b/MySQL.Data/src/X/XDevAPI/Common/BufferingResult.cs @@ -1,242 +1,242 @@ -// Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using System; -using System.Collections; -using System.Collections.Generic; -using MySqlX.XDevAPI.Relational; -using MySqlX.Sessions; -using System.Collections.ObjectModel; -using MySql.Data; -using MySqlX; -using MySql.Data.MySqlClient; - -namespace MySqlX.XDevAPI.Common -{ - /// - /// Abstract class for buffered results. - /// - /// Generic result type. - public abstract class BufferingResult : BaseResult, IEnumerable, IEnumerator - { - /// - /// Index of the current item. - /// - protected int _position; - /// - /// List of generic items in this buffered result. - /// - protected List _items = new List(); - /// - /// Flag that indicates if all items have been read. - /// - protected bool _isComplete; - Dictionary _nameMap = new Dictionary(StringComparer.OrdinalIgnoreCase); - internal List _columns = null; - - - internal BufferingResult(InternalSession session) : base(session) - { - LoadColumnData(); - PageSize = 20; - _position = -1; - } - - /// - /// Gets a dictionary containing the column names and their index. - /// - protected Dictionary NameMap - { - get { return _nameMap; } - } - - /// - /// Gets the page size set for this buffered result. - /// - public int PageSize { get; private set; } - - /// - /// Loads the column data into the field. - /// - protected void LoadColumnData() - { - _columns = new List(); - if (_hasData) - { - _columns = Protocol.LoadColumnMetadata(); - if (_columns.Count == 0) - _hasData = false; - for (int i = 0; i < _columns.Count; i++) - _nameMap.Add(_columns[i].ColumnLabel ?? _columns[i].ColumnName, i); - } - else - Protocol.CloseResult(this); - } - - /// - /// Retrieves a read-only list of the generic items associated to this buffered result. - /// - /// A generic list representing items in this buffered result. - public ReadOnlyCollection FetchAll() - { - while (PageInItems()) ; - return _items.AsReadOnly(); - } - - internal void Dump() - { - if (_isComplete) return; - while (true) - { - if (ReadItem(true) == null) break; - } - _isComplete = true; - } - - /// - /// Retrieves one element from the generic items associated to this buffered result. - /// - /// A generic object that corresponds to the current or default item. - public T FetchOne() - { - if (!Next()) - return default(T); - return Current; - } - - /// - /// Determines if all items have already been read. - /// - /// True if all items have been retrived, false otherwise. - public bool Next() - { - _position++; - if (_position >= _items.Count) - { - if (_isComplete) return false; - if (!PageInItems()) - { - _isComplete = true; - return false; - } - } - return true; - } - - protected abstract T ReadItem(bool dumping); - - private bool PageInItems() - { - if (_isComplete) return false; - int count = 0; - for (int i = 0; i < PageSize; i++) - { - T item = ReadItem(false); - if (item == null) - { - _isComplete = !_hasData; - _session.ActiveResult = null; - break; - } - _items.Add(item); - count++; - } - return count > 0; - } - - /// - /// Gets the current item. - /// - /// All items have already been read. - public T Current - { - get - { - if (_position == _items.Count) - throw new InvalidOperationException(String.Format(ResourcesX.NoDataAtIndex, _position)); - return _items[_position]; - } - } - - object IEnumerator.Current - { - get { return this.Current; } - } - - /// - /// Determines if all items have already been read. - /// - /// True if all items have been retrived, false otherwise. - public bool MoveNext() - { - return Next(); - } - - /// - /// Resets the value of the field to zero. - /// - public void Reset() - { - _position = 0; - } - - /// - /// Gets an representation of this object. - /// - /// An representation of this object. - public IEnumerator GetEnumerator() - { - return this; - } - - /// - /// Gets an representation of this object. - /// - /// An representation of this object. - IEnumerator IEnumerable.GetEnumerator() - { - return this; - } - - /// - /// Retrieves a read-only list of the generic items associated to this buffered result. - /// - /// A generic list representing items in this buffered result. - protected override void Buffer() - { - FetchAll(); - } - - /// - /// No body has been defined for this method. - /// - public void Dispose() - { - } - } -} +// Copyright © 2015, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using System; +using System.Collections; +using System.Collections.Generic; +using MySqlX.XDevAPI.Relational; +using MySqlX.Sessions; +using System.Collections.ObjectModel; +using MySql.Data; +using MySqlX; +using MySql.Data.MySqlClient; + +namespace MySqlX.XDevAPI.Common +{ + /// + /// Abstract class for buffered results. + /// + /// Generic result type. + public abstract class BufferingResult : BaseResult, IEnumerable, IEnumerator + { + /// + /// Index of the current item. + /// + protected int _position; + /// + /// List of generic items in this buffered result. + /// + protected List _items = new List(); + /// + /// Flag that indicates if all items have been read. + /// + protected bool _isComplete; + Dictionary _nameMap = new Dictionary(StringComparer.OrdinalIgnoreCase); + internal List _columns = null; + + + internal BufferingResult(InternalSession session) : base(session) + { + LoadColumnData(); + PageSize = 20; + _position = -1; + } + + /// + /// Gets a dictionary containing the column names and their index. + /// + protected Dictionary NameMap + { + get { return _nameMap; } + } + + /// + /// Gets the page size set for this buffered result. + /// + public int PageSize { get; private set; } + + /// + /// Loads the column data into the field. + /// + protected void LoadColumnData() + { + _columns = new List(); + if (_hasData) + { + _columns = Protocol.LoadColumnMetadata(); + if (_columns.Count == 0) + _hasData = false; + for (int i = 0; i < _columns.Count; i++) + _nameMap.Add(_columns[i].ColumnLabel ?? _columns[i].ColumnName, i); + } + else + Protocol.CloseResult(this); + } + + /// + /// Retrieves a read-only list of the generic items associated to this buffered result. + /// + /// A generic list representing items in this buffered result. + public ReadOnlyCollection FetchAll() + { + while (PageInItems()) ; + return _items.AsReadOnly(); + } + + internal void Dump() + { + if (_isComplete) return; + while (true) + { + if (ReadItem(true) == null) break; + } + _isComplete = true; + } + + /// + /// Retrieves one element from the generic items associated to this buffered result. + /// + /// A generic object that corresponds to the current or default item. + public T FetchOne() + { + if (!Next()) + return default(T); + return Current; + } + + /// + /// Determines if all items have already been read. + /// + /// True if all items have been retrived, false otherwise. + public bool Next() + { + _position++; + if (_position >= _items.Count) + { + if (_isComplete) return false; + if (!PageInItems()) + { + _isComplete = true; + return false; + } + } + return true; + } + + protected abstract T ReadItem(bool dumping); + + private bool PageInItems() + { + if (_isComplete) return false; + int count = 0; + for (int i = 0; i < PageSize; i++) + { + T item = ReadItem(false); + if (item == null) + { + _isComplete = !_hasData; + _session.ActiveResult = null; + break; + } + _items.Add(item); + count++; + } + return count > 0; + } + + /// + /// Gets the current item. + /// + /// All items have already been read. + public T Current + { + get + { + if (_position == _items.Count) + throw new InvalidOperationException(String.Format(ResourcesX.NoDataAtIndex, _position)); + return _items[_position]; + } + } + + object IEnumerator.Current + { + get { return this.Current; } + } + + /// + /// Determines if all items have already been read. + /// + /// True if all items have been retrived, false otherwise. + public bool MoveNext() + { + return Next(); + } + + /// + /// Resets the value of the field to zero. + /// + public void Reset() + { + _position = 0; + } + + /// + /// Gets an representation of this object. + /// + /// An representation of this object. + public IEnumerator GetEnumerator() + { + return this; + } + + /// + /// Gets an representation of this object. + /// + /// An representation of this object. + IEnumerator IEnumerable.GetEnumerator() + { + return this; + } + + /// + /// Retrieves a read-only list of the generic items associated to this buffered result. + /// + /// A generic list representing items in this buffered result. + protected override void Buffer() + { + FetchAll(); + } + + /// + /// No body has been defined for this method. + /// + public void Dispose() + { + } + } +} diff --git a/MySQL.Data/src/X/XDevAPI/Common/CollectionOptions.cs b/MySQL.Data/src/X/XDevAPI/Common/CollectionOptions.cs index d15fa54e5..a08a391ea 100644 --- a/MySQL.Data/src/X/XDevAPI/Common/CollectionOptions.cs +++ b/MySQL.Data/src/X/XDevAPI/Common/CollectionOptions.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2019, 2020 Oracle and/or its affiliates. +// Copyright © 2019, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -79,4 +79,4 @@ public enum ValidationLevel //Enable schema validation STRICT } -} \ No newline at end of file +} diff --git a/MySQL.Data/src/X/XDevAPI/Common/ColumnType.cs b/MySQL.Data/src/X/XDevAPI/Common/ColumnType.cs index 279c045b2..c850f65d4 100644 --- a/MySQL.Data/src/X/XDevAPI/Common/ColumnType.cs +++ b/MySQL.Data/src/X/XDevAPI/Common/ColumnType.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2016, 2021, Oracle and/or its affiliates. +// Copyright © 2016, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/X/XDevAPI/Common/ErrorInfo.cs b/MySQL.Data/src/X/XDevAPI/Common/ErrorInfo.cs index 834289273..af22db16c 100644 --- a/MySQL.Data/src/X/XDevAPI/Common/ErrorInfo.cs +++ b/MySQL.Data/src/X/XDevAPI/Common/ErrorInfo.cs @@ -1,57 +1,57 @@ -// Copyright © 2015, 2017, Oracle and/or its affiliates. All rights reserved. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using System; - -namespace MySqlX.XDevAPI.Common -{ - /// - /// Class to represent an error in this result. - /// - public class ErrorInfo - { - /// - /// Numeric code. - /// - public UInt32 Code; - /// - /// Return code indicating the outcome of the executed SQL statement. - /// - public string SqlState; - /// - /// Error message. - /// - public string Message; - - /// - /// Initializes a new instance of the ErrorInfo class. - /// - public ErrorInfo() - {} - } -} +// Copyright © 2015, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using System; + +namespace MySqlX.XDevAPI.Common +{ + /// + /// Class to represent an error in this result. + /// + public class ErrorInfo + { + /// + /// Numeric code. + /// + public UInt32 Code; + /// + /// Return code indicating the outcome of the executed SQL statement. + /// + public string SqlState; + /// + /// Error message. + /// + public string Message; + + /// + /// Initializes a new instance of the ErrorInfo class. + /// + public ErrorInfo() + {} + } +} diff --git a/MySQL.Data/src/X/XDevAPI/Common/FilterParams.cs b/MySQL.Data/src/X/XDevAPI/Common/FilterParams.cs index 0d2c30abc..9d5ad512f 100644 --- a/MySQL.Data/src/X/XDevAPI/Common/FilterParams.cs +++ b/MySQL.Data/src/X/XDevAPI/Common/FilterParams.cs @@ -1,94 +1,94 @@ -// Copyright © 2015, 2019, Oracle and/or its affiliates. All rights reserved. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySqlX.Protocol.X; -using Mysqlx.Crud; -using Mysqlx.Expr; -using System.Collections.Generic; -using Mysqlx.Datatypes; -using System; -using MySqlX; -using MySql.Data; - -namespace MySqlX.XDevAPI.Common -{ - internal class FilterParams - { - public long Limit = -1; - public long Offset = -1; - public string Condition; - public Dictionary Parameters = new Dictionary(); - public Dictionary placeholderNameToPosition; - public bool IsRelational; - public string[] OrderBy; - public bool hadLimit = false; - public bool hadOffset = false; - - public bool HasLimit - { - get { return Limit != -1; } - } - - public List GetOrderByExpressions(bool allowRelational) - { - return new ExprParser(ExprUtil.JoinString(OrderBy), allowRelational).ParseOrderSpec(); - } - - public Expr GetConditionExpression(bool allowRelational) - { - ExprParser parser = new ExprParser(Condition, allowRelational); - Expr expr = parser.Parse(); - if (parser.GetPositionalPlaceholderCount() > 0) - { - this.placeholderNameToPosition = parser.GetPlaceholderNameToPositionMap(); - } - return expr; - } - - public IEnumerable GetArgsExpression(Dictionary parameters) - { - if (placeholderNameToPosition == null || placeholderNameToPosition.Count == 0) - throw new ArgumentException(ResourcesX.NoPlaceholders); - - Scalar[] paramsList = new Scalar[placeholderNameToPosition.Count]; - foreach (var param in parameters) - { - if (!placeholderNameToPosition.ContainsKey(param.Key.ToLowerInvariant())) - throw new ArgumentNullException(string.Format(ResourcesX.UnknownPlaceholder, param.Key)); - paramsList[placeholderNameToPosition[param.Key.ToLowerInvariant()]] = ExprUtil.ArgObjectToScalar(param.Value) - ?? throw new ArgumentException(param.Key); - } - return paramsList; - } - - public FilterParams Clone() - { - return (FilterParams)this.MemberwiseClone(); - } - } -} +// Copyright © 2015, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySqlX.Protocol.X; +using Mysqlx.Crud; +using Mysqlx.Expr; +using System.Collections.Generic; +using Mysqlx.Datatypes; +using System; +using MySqlX; +using MySql.Data; + +namespace MySqlX.XDevAPI.Common +{ + internal class FilterParams + { + public long Limit = -1; + public long Offset = -1; + public string Condition; + public Dictionary Parameters = new Dictionary(); + public Dictionary placeholderNameToPosition; + public bool IsRelational; + public string[] OrderBy; + public bool hadLimit = false; + public bool hadOffset = false; + + public bool HasLimit + { + get { return Limit != -1; } + } + + public List GetOrderByExpressions(bool allowRelational) + { + return new ExprParser(ExprUtil.JoinString(OrderBy), allowRelational).ParseOrderSpec(); + } + + public Expr GetConditionExpression(bool allowRelational) + { + ExprParser parser = new ExprParser(Condition, allowRelational); + Expr expr = parser.Parse(); + if (parser.GetPositionalPlaceholderCount() > 0) + { + this.placeholderNameToPosition = parser.GetPlaceholderNameToPositionMap(); + } + return expr; + } + + public IEnumerable GetArgsExpression(Dictionary parameters) + { + if (placeholderNameToPosition == null || placeholderNameToPosition.Count == 0) + throw new ArgumentException(ResourcesX.NoPlaceholders); + + Scalar[] paramsList = new Scalar[placeholderNameToPosition.Count]; + foreach (var param in parameters) + { + if (!placeholderNameToPosition.ContainsKey(param.Key.ToLowerInvariant())) + throw new ArgumentNullException(string.Format(ResourcesX.UnknownPlaceholder, param.Key)); + paramsList[placeholderNameToPosition[param.Key.ToLowerInvariant()]] = ExprUtil.ArgObjectToScalar(param.Value) + ?? throw new ArgumentException(param.Key); + } + return paramsList; + } + + public FilterParams Clone() + { + return (FilterParams)this.MemberwiseClone(); + } + } +} diff --git a/MySQL.Data/src/X/XDevAPI/Common/FilterableStatement.cs b/MySQL.Data/src/X/XDevAPI/Common/FilterableStatement.cs index 88ff3e5bb..e1ab2cfbf 100644 --- a/MySQL.Data/src/X/XDevAPI/Common/FilterableStatement.cs +++ b/MySQL.Data/src/X/XDevAPI/Common/FilterableStatement.cs @@ -1,202 +1,202 @@ -// Copyright (c) 2015, 2023, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySql.Data; -using MySqlX.Serialization; -using System; -using System.Collections.Generic; - -namespace MySqlX.XDevAPI.Common -{ - /// - /// Abstract class for filterable statements. - /// - /// The filterable statement. - /// The database object. - /// The type of result. - /// The type of the implemented object. - public abstract class FilterableStatement : TargetedBaseStatement - where T : FilterableStatement - where TTarget : DatabaseObject - where TResult : BaseResult - { - private FilterParams filter = new FilterParams(); - - /// - /// Initializes a new instance of the FiltarableStatement class based on the target and condition. - /// - /// The database object. - /// The optional filter condition. - public FilterableStatement(TTarget target, string condition = null) : base(target) - { - if (condition != null) - Where(condition); - } - - internal FilterParams FilterData - { - get { return filter; } - } - - /// - /// Enables the setting of Where condition for this operation. - /// - /// The Where condition. - /// The implementing statement type. - public T Where(string condition) - { - filter.Condition = condition; - SetChanged(); - return (T)this; - } - - /// - /// Sets the number of items to be returned by the operation. - /// - /// The number of items to be returned. - /// The implementing statement type. - /// is equal or lower than 0. - public T Limit(long rows) - { - if (rows <= 0) throw new ArgumentOutOfRangeException(nameof(rows), string.Format(ResourcesX.NumberNotGreaterThanZero, nameof(rows))); - filter.Limit = rows; - return (T)this; - } - - /// - /// Sets the number of items to be skipped before including them into the result. - /// - /// The number of items to be skipped. - /// The implementing statement type. - public T Offset(long rows) - { - filter.Offset = rows; - return (T)this; - } - - /// - /// Binds the parameter values in filter expression. - /// - /// The parameter name. - /// The value of the parameter. - /// A generic object representing the implementing statement type. - public T Bind(string parameterName, object value) - { - FilterData.Parameters[parameterName.ToLowerInvariant()] = value is string ? QuoteString((string)value) : value; - return (T)this; - } - - /// - /// Binds the parameter values in filter expression. - /// - /// The parameters as a DbDoc object. - /// A generic object representing the implementing statement type. - public T Bind(DbDoc dbDocParams) - { - return Bind(dbDocParams.ToString()); - } - - /// - /// Binds the parameter values in filter expression. - /// - /// The parameters as a JSON string. - /// The implementing statement type. - public T Bind(string jsonParams) - { - foreach (var item in JsonParser.Parse(jsonParams)) - { - Bind(item.Key, item.Value); - } - return (T)this; - } - - /// - /// Binds the parameter values in filter expression. - /// - /// The parameters as an anonymous object: new { param1 = value1, param2 = value2, ... }. - /// The implementing statement type. - public T Bind(object jsonParams) - { - return Bind(new DbDoc(jsonParams)); - } - - /// - /// Executes the statement. - /// - /// The function to execute. - /// The generic object to use. - /// A generic result object containing the results of the execution. - protected virtual TResult Execute(Func executeFunc, T t) - { - try - { - ValidateOpenSession(); - List parameters = new List(FilterData.Parameters.Values); - if (_isPrepared && FilterData.hadLimit != FilterData.HasLimit) - { - SetChanged(); - } - // Add the prepared statement placeholder values for limit and offset - if (!_hasChanged) - { - // Limit and offset placeholder values - if (FilterData.HasLimit) - { - parameters.Add(FilterData.Limit); - parameters.Add(FilterData.Offset == -1 ? 0 : FilterData.Offset); - } - } - var result = ConvertToPreparedStatement(executeFunc, t, parameters); - _hasChanged = false; - return result; - } - finally - { - FilterData.hadLimit = FilterData.HasLimit; - FilterData.hadOffset = FilterData.Offset != -1; - } - } - - /// - /// Clones the filterable data but Session and Target remain the - /// same. - /// - /// A clone of this filterable statement. - public virtual T Clone() - { - var t = (T)this.MemberwiseClone(); - t.filter = t.FilterData.Clone(); - return t; - } - - private static string QuoteString(string value) - { - return "'" + value.Trim().Replace("'", "\\'") + "'"; - } - } -} +// Copyright © 2015, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySql.Data; +using MySqlX.Serialization; +using System; +using System.Collections.Generic; + +namespace MySqlX.XDevAPI.Common +{ + /// + /// Abstract class for filterable statements. + /// + /// The filterable statement. + /// The database object. + /// The type of result. + /// The type of the implemented object. + public abstract class FilterableStatement : TargetedBaseStatement + where T : FilterableStatement + where TTarget : DatabaseObject + where TResult : BaseResult + { + private FilterParams filter = new FilterParams(); + + /// + /// Initializes a new instance of the FiltarableStatement class based on the target and condition. + /// + /// The database object. + /// The optional filter condition. + public FilterableStatement(TTarget target, string condition = null) : base(target) + { + if (condition != null) + Where(condition); + } + + internal FilterParams FilterData + { + get { return filter; } + } + + /// + /// Enables the setting of Where condition for this operation. + /// + /// The Where condition. + /// The implementing statement type. + public T Where(string condition) + { + filter.Condition = condition; + SetChanged(); + return (T)this; + } + + /// + /// Sets the number of items to be returned by the operation. + /// + /// The number of items to be returned. + /// The implementing statement type. + /// is equal or lower than 0. + public T Limit(long rows) + { + if (rows <= 0) throw new ArgumentOutOfRangeException(nameof(rows), string.Format(ResourcesX.NumberNotGreaterThanZero, nameof(rows))); + filter.Limit = rows; + return (T)this; + } + + /// + /// Sets the number of items to be skipped before including them into the result. + /// + /// The number of items to be skipped. + /// The implementing statement type. + public T Offset(long rows) + { + filter.Offset = rows; + return (T)this; + } + + /// + /// Binds the parameter values in filter expression. + /// + /// The parameter name. + /// The value of the parameter. + /// A generic object representing the implementing statement type. + public T Bind(string parameterName, object value) + { + FilterData.Parameters[parameterName.ToLowerInvariant()] = value is string ? QuoteString((string)value) : value; + return (T)this; + } + + /// + /// Binds the parameter values in filter expression. + /// + /// The parameters as a DbDoc object. + /// A generic object representing the implementing statement type. + public T Bind(DbDoc dbDocParams) + { + return Bind(dbDocParams.ToString()); + } + + /// + /// Binds the parameter values in filter expression. + /// + /// The parameters as a JSON string. + /// The implementing statement type. + public T Bind(string jsonParams) + { + foreach (var item in JsonParser.Parse(jsonParams)) + { + Bind(item.Key, item.Value); + } + return (T)this; + } + + /// + /// Binds the parameter values in filter expression. + /// + /// The parameters as an anonymous object: new { param1 = value1, param2 = value2, ... }. + /// The implementing statement type. + public T Bind(object jsonParams) + { + return Bind(new DbDoc(jsonParams)); + } + + /// + /// Executes the statement. + /// + /// The function to execute. + /// The generic object to use. + /// A generic result object containing the results of the execution. + protected virtual TResult Execute(Func executeFunc, T t) + { + try + { + ValidateOpenSession(); + List parameters = new List(FilterData.Parameters.Values); + if (_isPrepared && FilterData.hadLimit != FilterData.HasLimit) + { + SetChanged(); + } + // Add the prepared statement placeholder values for limit and offset + if (!_hasChanged) + { + // Limit and offset placeholder values + if (FilterData.HasLimit) + { + parameters.Add(FilterData.Limit); + parameters.Add(FilterData.Offset == -1 ? 0 : FilterData.Offset); + } + } + var result = ConvertToPreparedStatement(executeFunc, t, parameters); + _hasChanged = false; + return result; + } + finally + { + FilterData.hadLimit = FilterData.HasLimit; + FilterData.hadOffset = FilterData.Offset != -1; + } + } + + /// + /// Clones the filterable data but Session and Target remain the + /// same. + /// + /// A clone of this filterable statement. + public virtual T Clone() + { + var t = (T)this.MemberwiseClone(); + t.filter = t.FilterData.Clone(); + return t; + } + + private static string QuoteString(string value) + { + return "'" + value.Trim().Replace("'", "\\'") + "'"; + } + } +} diff --git a/MySQL.Data/src/X/XDevAPI/Common/QueryStatement.cs b/MySQL.Data/src/X/XDevAPI/Common/QueryStatement.cs index a8eb00f82..1fb41938e 100644 --- a/MySQL.Data/src/X/XDevAPI/Common/QueryStatement.cs +++ b/MySQL.Data/src/X/XDevAPI/Common/QueryStatement.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2017, 2023, Oracle and/or its affiliates. +// Copyright © 2017, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/X/XDevAPI/Common/Result.cs b/MySQL.Data/src/X/XDevAPI/Common/Result.cs index 44d74f476..7312573b7 100644 --- a/MySQL.Data/src/X/XDevAPI/Common/Result.cs +++ b/MySQL.Data/src/X/XDevAPI/Common/Result.cs @@ -1,60 +1,60 @@ -// Copyright (c) 2015, 2022, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySqlX.Sessions; -using System; -using System.Collections.ObjectModel; - -namespace MySqlX.XDevAPI.Common -{ - /// - /// Represents a general statement result. - /// - public class Result : BaseResult - { - internal Result(InternalSession session) : base(session) - { - if (session == null) return; - GeneratedIds = new ReadOnlyCollection(_documentIds); - session.GetProtocol().CloseResult(this); - } - - /// - /// Gets the last inserted identifier (if there is one) by the statement that generated this result. - /// - public UInt64 AutoIncrementValue - { - get { return _autoIncrementValue; } - } - - /// - /// Gets the list of generated identifiers in the order of the Add() calls. - /// - public ReadOnlyCollection GeneratedIds { get; } - } -} +// Copyright © 2015, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySqlX.Sessions; +using System; +using System.Collections.ObjectModel; + +namespace MySqlX.XDevAPI.Common +{ + /// + /// Represents a general statement result. + /// + public class Result : BaseResult + { + internal Result(InternalSession session) : base(session) + { + if (session == null) return; + GeneratedIds = new ReadOnlyCollection(_documentIds); + session.GetProtocol().CloseResult(this); + } + + /// + /// Gets the last inserted identifier (if there is one) by the statement that generated this result. + /// + public UInt64 AutoIncrementValue + { + get { return _autoIncrementValue; } + } + + /// + /// Gets the list of generated identifiers in the order of the Add() calls. + /// + public ReadOnlyCollection GeneratedIds { get; } + } +} diff --git a/MySQL.Data/src/X/XDevAPI/Common/TargetedBaseStatement.cs b/MySQL.Data/src/X/XDevAPI/Common/TargetedBaseStatement.cs index 27bd6308f..bf9cdac85 100644 --- a/MySQL.Data/src/X/XDevAPI/Common/TargetedBaseStatement.cs +++ b/MySQL.Data/src/X/XDevAPI/Common/TargetedBaseStatement.cs @@ -1,55 +1,55 @@ -// Copyright (c) 2015, 2023, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -namespace MySqlX.XDevAPI.Common -{ - /// - /// Abstract class to select a database object target. - /// - /// The database object. - /// The execution result. - /// The type of the implemented object. - public abstract class TargetedBaseStatement : BaseStatement - where TTarget : DatabaseObject - where TResult : BaseResult - { - /// - /// Initializes a new instance of the TargetedBaseStatement class based on the provided target. - /// - /// The database object. - public TargetedBaseStatement(TTarget target) : base(target.Schema.Session) - { - Target = target; - } - - /// - /// Gets the database target. - /// - public TTarget Target { get; private set; } - } -} +// Copyright © 2015, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +namespace MySqlX.XDevAPI.Common +{ + /// + /// Abstract class to select a database object target. + /// + /// The database object. + /// The execution result. + /// The type of the implemented object. + public abstract class TargetedBaseStatement : BaseStatement + where TTarget : DatabaseObject + where TResult : BaseResult + { + /// + /// Initializes a new instance of the TargetedBaseStatement class based on the provided target. + /// + /// The database object. + public TargetedBaseStatement(TTarget target) : base(target.Schema.Session) + { + Target = target; + } + + /// + /// Gets the database target. + /// + public TTarget Target { get; private set; } + } +} diff --git a/MySQL.Data/src/X/XDevAPI/Common/WarningInfo.cs b/MySQL.Data/src/X/XDevAPI/Common/WarningInfo.cs index 6acbf8aeb..6d2306895 100644 --- a/MySQL.Data/src/X/XDevAPI/Common/WarningInfo.cs +++ b/MySQL.Data/src/X/XDevAPI/Common/WarningInfo.cs @@ -1,62 +1,62 @@ -// Copyright © 2015, 2017, Oracle and/or its affiliates. All rights reserved. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -namespace MySqlX.XDevAPI.Common -{ - /// - /// Represents a warning in this result. - /// - public class WarningInfo - { - /// - /// Numeric value associated to the warning message. - /// - public uint Code; - - /// - /// Error message. - /// - public string Message; - - /// - /// Strict level for the warning. - /// - public uint Level; - - /// - /// Initializes a new instance of the WarningInfo class based on the code and msg. - /// - /// The code for the warning. - /// The error message for the warning. - public WarningInfo(uint code, string msg) - { - Code = code; - Message = msg; - } - } -} +// Copyright © 2015, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +namespace MySqlX.XDevAPI.Common +{ + /// + /// Represents a warning in this result. + /// + public class WarningInfo + { + /// + /// Numeric value associated to the warning message. + /// + public uint Code; + + /// + /// Error message. + /// + public string Message; + + /// + /// Strict level for the warning. + /// + public uint Level; + + /// + /// Initializes a new instance of the WarningInfo class based on the code and msg. + /// + /// The code for the warning. + /// The error message for the warning. + public WarningInfo(uint code, string msg) + { + Code = code; + Message = msg; + } + } +} diff --git a/MySQL.Data/src/X/XDevAPI/DatabaseObject.cs b/MySQL.Data/src/X/XDevAPI/DatabaseObject.cs index 69b59ba70..b2b279f0a 100644 --- a/MySQL.Data/src/X/XDevAPI/DatabaseObject.cs +++ b/MySQL.Data/src/X/XDevAPI/DatabaseObject.cs @@ -1,76 +1,76 @@ -// Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - - -using MySql.Data; -using MySql.Data.MySqlClient; - -namespace MySqlX.XDevAPI -{ - /// - /// Represents a database object. - /// - public abstract class DatabaseObject - { - internal DatabaseObject(Schema schema, string name) - { - Schema = schema; - Name = name; - } - - /// - /// Gets the session that owns the database object. - /// - public BaseSession Session - { - get { return Schema.Session; } - } - - /// - /// Gets the schema that owns the database object. - /// - public Schema Schema { get; internal set; } - - /// - /// Gets the database object name. - /// - public string Name { get; internal set; } - - /// - /// Verifies that the database object exists in the database. - /// - /// True if the object exists in database, false otherwise. - public abstract bool ExistsInDatabase(); - - protected void ValidateOpenSession() - { - if (Session.XSession.SessionState != SessionState.Open) - throw new MySqlException(ResourcesX.InvalidSession); - } - } -} +// Copyright © 2015, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + +using MySql.Data; +using MySql.Data.MySqlClient; + +namespace MySqlX.XDevAPI +{ + /// + /// Represents a database object. + /// + public abstract class DatabaseObject + { + internal DatabaseObject(Schema schema, string name) + { + Schema = schema; + Name = name; + } + + /// + /// Gets the session that owns the database object. + /// + public BaseSession Session + { + get { return Schema.Session; } + } + + /// + /// Gets the schema that owns the database object. + /// + public Schema Schema { get; internal set; } + + /// + /// Gets the database object name. + /// + public string Name { get; internal set; } + + /// + /// Verifies that the database object exists in the database. + /// + /// True if the object exists in database, false otherwise. + public abstract bool ExistsInDatabase(); + + protected void ValidateOpenSession() + { + if (Session.XSession.SessionState != SessionState.Open) + throw new MySqlException(ResourcesX.InvalidSession); + } + } +} diff --git a/MySQL.Data/src/X/XDevAPI/DbDoc.cs b/MySQL.Data/src/X/XDevAPI/DbDoc.cs index aa8be6783..ce84cc844 100644 --- a/MySQL.Data/src/X/XDevAPI/DbDoc.cs +++ b/MySQL.Data/src/X/XDevAPI/DbDoc.cs @@ -1,303 +1,303 @@ -// Copyright (c) 2015, 2023, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySql.Data; -using MySqlX.Serialization; -using System; -using System.Collections; -using System.Collections.Generic; -using System.Reflection; -using System.Text; - -namespace MySqlX.XDevAPI -{ - /// - /// Represents a generic document in JSON format. - /// - public class DbDoc - { - internal Dictionary values = new Dictionary(); - - /// - /// Initializes a new instance of the DbDoc class based on the object provided. The value can be a domain object, anonymous object, or JSON string. - /// - /// The value for this DbDoc. - public DbDoc(object val = null) - { - if (val == null) - { - return; - } - - try - { - if (val is string) - values = JsonParser.Parse(val as string); - else if (val is Dictionary) - values = JsonParser.Parse(DictToString(val as Dictionary, 2)); - else if (val is DbDoc) - values = JsonParser.Parse(DictToString((val as DbDoc).values, 2)); - else - values = ParseObject(val); - } - catch (Exception exception) - { - // Throw message indicating the format of the Json document is invalid and append the message - // returned by the Json parser. - throw (new Exception(string.Format(ResourcesX.InvalidJsonDocument, exception.Message))); - } - } - - /// - /// Gets the value of a document property. - /// - /// The key path for the property. - /// - public object this[string path] - { - get { return GetValue(path); } - } - - /// - /// Gets the identifier of the document. - /// - public object Id - { - get { return values["_id"]; } - internal set { SetValue("_id", value); } - } - - /// - /// Gets a value indicating if this document has an identifier (property named _id with a value). - /// - public bool HasId - { - get { return values.ContainsKey("_id"); } - } - - //internal void EnsureId() - //{ - // if (!HasId) - // { - // char separatorChar = '-'; - // string[] token = Guid.NewGuid().ToString().Split(separatorChar); - // string guid = string.Empty; - // for (int i = token.Length-1; i >= 0; i--) - // { - // guid += token[i]; - // if (i != 0) guid += separatorChar; - // } - - // SetValue("_id", guid.Replace(separatorChar.ToString(), string.Empty)); - // } - //} - - private object GetValue(string path) - { - string[] levels = path.Split('.'); - Dictionary dic = values; - object returnValue = null; - foreach (string level in levels) - { - if (!dic.ContainsKey(level)) - throw new InvalidOperationException( - String.Format(ResourcesX.PathNotFound, path)); - if (dic[level] is Dictionary) - returnValue = dic = dic[level] as Dictionary; - else if (dic[level] == null) return null; - else if (dic[level].GetType().GetTypeInfo().IsGenericType) - returnValue = dic = ParseObject(dic[level]); - else - returnValue = dic[level]; - } - - return returnValue; - } - - /// - /// Sets a property on this document. - /// - /// The key of the property. - /// The new property value. - public void SetValue(string key, object val) - { - IList e = val as IList; - - if (e != null) - values[key] = GetArrayValues(e); - else if (val is DbDoc) - values[key] = (val as DbDoc).values; - else if (val is Dictionary) - values[key] = val; - else if (val != null && val.GetType().Namespace != "System") - values[key] = ParseObject(val); - else - values[key] = val; - } - - private Dictionary[] GetArrayValues(IEnumerable value) - { - List> values = new List>(); - foreach (object o in value) - values.Add(ParseObject(o)); - return values.ToArray(); - } - - /// - /// Returns this document in Json format. - /// - /// A Json formatted string. - public override string ToString() - { - return DictToString(values, 2); - } - - private string DictToString(Dictionary vals, int ident) - { - StringBuilder json = new StringBuilder("{"); - string delimiter = ""; - foreach (string key in vals.Keys) - { - json.Append(delimiter); - json.AppendLine(); - json.Append(' ', ident); - json.AppendFormat("\"{0}\": {1}", key, GetValue(vals[key], ident) ?? "null"); - delimiter = ", "; - } - json.AppendLine(); - json.Append(' ', ident - 2); - json.Append("}"); - return json.ToString(); - } - - private string GetValue(object val, int ident) - { - if (val == null) return null; - - if (val.GetType().IsArray) - { - - StringBuilder values = new StringBuilder("["); - string separator = string.Empty; - foreach (var item in (Array)val) - { - values.Append(separator); - values.AppendLine(); - values.Append(' ', ident + 2); - values.Append(GetValue(item, ident + 2)); - separator = ", "; - } - values.AppendLine(); - values.Append(' ', ident); - values.Append("]"); - return values.ToString(); - } - if (val is Dictionary) - return DictToString(val as Dictionary, ident + 2); - else if (val is MySqlExpression) - { - var expression = (MySqlExpression)val; - return expression.value; - } - - string quoteChar = ""; - if (val is string || val is DateTime) - { - quoteChar = "\""; - } - - return quoteChar + ( - val is bool ? - val.ToString().ToLowerInvariant() : - val is double ? - ((double)val).ToString(System.Globalization.CultureInfo.InvariantCulture) : - val.ToString() - ) + quoteChar; - } - - private bool CompareDictionaries(Dictionary dict1, Dictionary dict2) - { - IEqualityComparer valueComparer = EqualityComparer.Default; - if (dict1.Count != dict2.Count) return false; - foreach (TKey key in dict1.Keys) - { - if (!dict2.ContainsKey(key)) return false; - object val = dict1[key]; - object val2 = dict2[key]; - if (val is Dictionary[] && val2 is Dictionary[]) - { - Dictionary[] valArray1 = (Dictionary[])val; - Dictionary[] valArray2 = (Dictionary[])val2; - if (valArray1.Length != valArray2.Length) return false; - for (int i = 0; i < valArray1.Length; i++) - { - if (!CompareDictionaries(valArray1[i], valArray2[i])) return false; - } - } - else if (val is Dictionary && val2 is Dictionary) - return CompareDictionaries((Dictionary)val, (Dictionary)val2); - else if (!val.Equals(val2)) return false; - } - return true; - } - - /// - /// Compares this DbDoc with another one. - /// - /// The DbDoc to compare to. - /// True if they are equal, false otherwise. - public override bool Equals(object obj) - { - if (!(obj is DbDoc)) - throw new InvalidOperationException("DbDoc can only be compared with another DbDoc"); - DbDoc toCompare = obj as DbDoc; - return CompareDictionaries(values, toCompare.values); - } - - /// - /// Gets a value that serves as a hash function for a particular type. - /// - /// A hash code for the current object. - public override int GetHashCode() - { - return base.GetHashCode(); - } - - private Dictionary ParseObject(object val) - { - Type t = val.GetType(); - bool allProps = t.Name.Contains("Anonymous"); - Dictionary vals = new Dictionary(); - - PropertyInfo[] props = allProps ? t.GetProperties() : t.GetProperties(BindingFlags.Public); - foreach (PropertyInfo prop in props) - vals.Add(prop.Name, prop.GetValue(val, null)); - return vals; - } - } -} +// Copyright © 2015, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySql.Data; +using MySqlX.Serialization; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Reflection; +using System.Text; + +namespace MySqlX.XDevAPI +{ + /// + /// Represents a generic document in JSON format. + /// + public class DbDoc + { + internal Dictionary values = new Dictionary(); + + /// + /// Initializes a new instance of the DbDoc class based on the object provided. The value can be a domain object, anonymous object, or JSON string. + /// + /// The value for this DbDoc. + public DbDoc(object val = null) + { + if (val == null) + { + return; + } + + try + { + if (val is string) + values = JsonParser.Parse(val as string); + else if (val is Dictionary) + values = JsonParser.Parse(DictToString(val as Dictionary, 2)); + else if (val is DbDoc) + values = JsonParser.Parse(DictToString((val as DbDoc).values, 2)); + else + values = ParseObject(val); + } + catch (Exception exception) + { + // Throw message indicating the format of the Json document is invalid and append the message + // returned by the Json parser. + throw (new Exception(string.Format(ResourcesX.InvalidJsonDocument, exception.Message))); + } + } + + /// + /// Gets the value of a document property. + /// + /// The key path for the property. + /// + public object this[string path] + { + get { return GetValue(path); } + } + + /// + /// Gets the identifier of the document. + /// + public object Id + { + get { return values["_id"]; } + internal set { SetValue("_id", value); } + } + + /// + /// Gets a value indicating if this document has an identifier (property named _id with a value). + /// + public bool HasId + { + get { return values.ContainsKey("_id"); } + } + + //internal void EnsureId() + //{ + // if (!HasId) + // { + // char separatorChar = '-'; + // string[] token = Guid.NewGuid().ToString().Split(separatorChar); + // string guid = string.Empty; + // for (int i = token.Length-1; i >= 0; i--) + // { + // guid += token[i]; + // if (i != 0) guid += separatorChar; + // } + + // SetValue("_id", guid.Replace(separatorChar.ToString(), string.Empty)); + // } + //} + + private object GetValue(string path) + { + string[] levels = path.Split('.'); + Dictionary dic = values; + object returnValue = null; + foreach (string level in levels) + { + if (!dic.ContainsKey(level)) + throw new InvalidOperationException( + String.Format(ResourcesX.PathNotFound, path)); + if (dic[level] is Dictionary) + returnValue = dic = dic[level] as Dictionary; + else if (dic[level] == null) return null; + else if (dic[level].GetType().GetTypeInfo().IsGenericType) + returnValue = dic = ParseObject(dic[level]); + else + returnValue = dic[level]; + } + + return returnValue; + } + + /// + /// Sets a property on this document. + /// + /// The key of the property. + /// The new property value. + public void SetValue(string key, object val) + { + IList e = val as IList; + + if (e != null) + values[key] = GetArrayValues(e); + else if (val is DbDoc) + values[key] = (val as DbDoc).values; + else if (val is Dictionary) + values[key] = val; + else if (val != null && val.GetType().Namespace != "System") + values[key] = ParseObject(val); + else + values[key] = val; + } + + private Dictionary[] GetArrayValues(IEnumerable value) + { + List> values = new List>(); + foreach (object o in value) + values.Add(ParseObject(o)); + return values.ToArray(); + } + + /// + /// Returns this document in Json format. + /// + /// A Json formatted string. + public override string ToString() + { + return DictToString(values, 2); + } + + private string DictToString(Dictionary vals, int ident) + { + StringBuilder json = new StringBuilder("{"); + string delimiter = ""; + foreach (string key in vals.Keys) + { + json.Append(delimiter); + json.AppendLine(); + json.Append(' ', ident); + json.AppendFormat("\"{0}\": {1}", key, GetValue(vals[key], ident) ?? "null"); + delimiter = ", "; + } + json.AppendLine(); + json.Append(' ', ident - 2); + json.Append("}"); + return json.ToString(); + } + + private string GetValue(object val, int ident) + { + if (val == null) return null; + + if (val.GetType().IsArray) + { + + StringBuilder values = new StringBuilder("["); + string separator = string.Empty; + foreach (var item in (Array)val) + { + values.Append(separator); + values.AppendLine(); + values.Append(' ', ident + 2); + values.Append(GetValue(item, ident + 2)); + separator = ", "; + } + values.AppendLine(); + values.Append(' ', ident); + values.Append("]"); + return values.ToString(); + } + if (val is Dictionary) + return DictToString(val as Dictionary, ident + 2); + else if (val is MySqlExpression) + { + var expression = (MySqlExpression)val; + return expression.value; + } + + string quoteChar = ""; + if (val is string || val is DateTime) + { + quoteChar = "\""; + } + + return quoteChar + ( + val is bool ? + val.ToString().ToLowerInvariant() : + val is double ? + ((double)val).ToString(System.Globalization.CultureInfo.InvariantCulture) : + val.ToString() + ) + quoteChar; + } + + private bool CompareDictionaries(Dictionary dict1, Dictionary dict2) + { + IEqualityComparer valueComparer = EqualityComparer.Default; + if (dict1.Count != dict2.Count) return false; + foreach (TKey key in dict1.Keys) + { + if (!dict2.ContainsKey(key)) return false; + object val = dict1[key]; + object val2 = dict2[key]; + if (val is Dictionary[] && val2 is Dictionary[]) + { + Dictionary[] valArray1 = (Dictionary[])val; + Dictionary[] valArray2 = (Dictionary[])val2; + if (valArray1.Length != valArray2.Length) return false; + for (int i = 0; i < valArray1.Length; i++) + { + if (!CompareDictionaries(valArray1[i], valArray2[i])) return false; + } + } + else if (val is Dictionary && val2 is Dictionary) + return CompareDictionaries((Dictionary)val, (Dictionary)val2); + else if (!val.Equals(val2)) return false; + } + return true; + } + + /// + /// Compares this DbDoc with another one. + /// + /// The DbDoc to compare to. + /// True if they are equal, false otherwise. + public override bool Equals(object obj) + { + if (!(obj is DbDoc)) + throw new InvalidOperationException("DbDoc can only be compared with another DbDoc"); + DbDoc toCompare = obj as DbDoc; + return CompareDictionaries(values, toCompare.values); + } + + /// + /// Gets a value that serves as a hash function for a particular type. + /// + /// A hash code for the current object. + public override int GetHashCode() + { + return base.GetHashCode(); + } + + private Dictionary ParseObject(object val) + { + Type t = val.GetType(); + bool allProps = t.Name.Contains("Anonymous"); + Dictionary vals = new Dictionary(); + + PropertyInfo[] props = allProps ? t.GetProperties() : t.GetProperties(BindingFlags.Public); + foreach (PropertyInfo prop in props) + vals.Add(prop.Name, prop.GetValue(val, null)); + return vals; + } + } +} diff --git a/MySQL.Data/src/X/XDevAPI/GenericCollection.cs b/MySQL.Data/src/X/XDevAPI/GenericCollection.cs index d4e839c42..e46c5a82f 100644 --- a/MySQL.Data/src/X/XDevAPI/GenericCollection.cs +++ b/MySQL.Data/src/X/XDevAPI/GenericCollection.cs @@ -1,301 +1,301 @@ -// Copyright (c) 2015, 2023, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySql.Data; -using MySql.Data.MySqlClient; -using MySqlX.XDevAPI.Common; -using MySqlX.XDevAPI.CRUD; -using System; - -namespace MySqlX.XDevAPI -{ - /// - /// Represents a collection of documents with a generic type. - /// - /// - public class Collection : DatabaseObject - { - /// - /// Initializes a new instance of the generic Collection class based on the specified schema - /// and name. - /// - /// The object associated to this collection. - /// The name of the collection. - public Collection(Schema s, string name) : base(s, name) { } - - /// - /// Creates an containing the provided generic object. The add - /// statement can be further modified before execution. - /// - /// The generic object to add. - /// An object containing the object to add. - public AddStatement Add(params object[] items) - { - if (items == null) - throw new ArgumentNullException(); - - AddStatement stmt = new AddStatement(this); - stmt.Add(items); - return stmt; - } - - #region Remove Operations - - /// - /// Creates a with the given condition that can be used to remove - /// one or more documents from a collection.The statement can then be further modified before execution. - /// - /// The condition to match documents. - /// A object set with the given condition. - /// is null or white space. - /// The statement can then be further modified before execution. - public RemoveStatement Remove(string condition) - { - if (string.IsNullOrWhiteSpace(condition)) - throw new ArgumentNullException(nameof(condition), Resources.ParameterNullOrEmpty); - - RemoveStatement stmt = new RemoveStatement(this, condition); - return stmt; - } - - /// - /// Removes the document with the given identifier. - /// - /// The unique identifier of the document to replace. - /// A object containing the results of the execution. - /// is null or white space. - /// This is a direct execution method. - public Result RemoveOne(object id) - { - if (id == null) - throw new ArgumentNullException(nameof(id)); - string stringId = id.ToString(); - if (string.IsNullOrWhiteSpace(stringId)) - throw new ArgumentNullException(nameof(id), Resources.ParameterNullOrEmpty); - - return Remove("_id = :id").Bind("id", id).Execute(); - } - - #endregion - - #region Modify Operations - - /// - /// Creates a with the given condition that can be used to modify one or more - /// documents from a collection. - /// - /// The condition to match documents. - /// A object set with the given condition. - /// is null or white space. - /// The statement can then be further modified before execution. - public ModifyStatement Modify(string condition) - { - if (string.IsNullOrWhiteSpace(condition)) - throw new ArgumentNullException(nameof(condition), Resources.ParameterNullOrEmpty); - - ModifyStatement stmt = new ModifyStatement(this, condition); - return stmt; - } - #endregion - - /// - /// Returns the number of documents in this collection on the server. - /// - /// The number of documents found. - public long Count() - { - long result = 0; - try - { - ValidateOpenSession(); - result = Session.XSession.TableCount(Schema, Name, "Collection"); - } - catch (MySqlException ex) - { - switch (ex.Number) - { - case (int)CloseNotification.IDLE: - case (int)CloseNotification.KILLED: - case (int)CloseNotification.SHUTDOWN: - XDevAPI.Session.ThrowSessionClosedByServerException(ex, Session); - break; - default: - throw; - } - } - return result; - } - - /// - /// Creates a with the given condition which can be used to find documents in a - /// collection. - /// - /// An optional condition to match documents. - /// A object set with the given condition. - /// The statement can then be further modified before execution. - public FindStatement Find(string condition = null) - { - FindStatement stmt = new FindStatement(this, condition); - return stmt; - } - - /// - /// Creates an index based on the properties provided in the JSON document. - /// - /// The index name. - /// JSON document describing the index to be created. - /// - /// is a JSON document with the following fields: - /// - /// - fields: array of IndexField objects, each describing a single document member to be - /// included in the index (see below). - /// - type: string, (optional) the type of index. One of INDEX or SPATIAL. Default is INDEX and may - /// be omitted. - /// - ///   - /// A single IndexField description consists of the following fields: - /// - /// - field: string, the full document path to the document member or field to be indexed. - /// - type: string, one of the supported SQL column types to map the field into (see the following list). - /// For numeric types, the optional UNSIGNED keyword may follow. For the TEXT type, the length to consider for - /// indexing may be added. - /// - required: bool, (optional) true if the field is required to exist in the document. defaults to - /// false, except for GEOJSON where it defaults to true. - /// - options: int, (optional) special option flags for use when decoding GEOJSON data. - /// - srid: int, (optional) srid value for use when decoding GEOJSON data. - /// - ///   - /// Supported SQL column types: - /// - /// - INT [UNSIGNED] - /// - TINYINT [UNSIGNED] - /// - SMALLINT[UNSIGNED] - /// - MEDIUMINT [UNSIGNED] - /// - INTEGER [UNSIGNED] - /// - BIGINT [UNSIGNED] - /// - REAL [UNSIGNED] - /// - FLOAT [UNSIGNED] - /// - DOUBLE [UNSIGNED] - /// - DECIMAL [UNSIGNED] - /// - NUMERIC [UNSIGNED] - /// - DATE - /// - TIME - /// - TIMESTAMP - /// - DATETIME - /// - TEXT[(length)] - /// - CHAR[(lenght)] - /// - GEOJSON (extra options: options, srid) - /// - /// - public void CreateIndex(string indexName, object indexDefinition) - { - new CreateCollectionIndexStatement(this, indexName, new DbDoc(indexDefinition)).Execute(); - } - - /// - /// Drops a collection index. - /// - /// The index name. - /// is null or white space. - public void DropIndex(string indexName) - { - if (string.IsNullOrWhiteSpace(indexName)) throw new ArgumentNullException(nameof(indexName)); - - ValidateOpenSession(); - - try - { - bool indexExists = Convert.ToInt32(Session.XSession.ExecuteQueryAsScalar( - string.Format("SELECT COUNT(*)>0 FROM information_schema.statistics WHERE table_schema = '{0}' AND table_name = '{1}' AND index_name = '{2}'", - this.Schema.Name, this.Name, indexName))) == 1; - if (!indexExists) return; - - Session.XSession.DropCollectionIndex(this.Schema.Name, this.Name, indexName); - } - catch (MySqlException ex) - { - switch (ex.Number) - { - case (int)CloseNotification.IDLE: - case (int)CloseNotification.KILLED: - case (int)CloseNotification.SHUTDOWN: - XDevAPI.Session.ThrowSessionClosedByServerException(ex, Session); - break; - default: - throw; - } - } - } - - /// - /// Verifies if the current collection exists in the server schema. - /// - /// true if the collection exists; otherwise, false. - public override bool ExistsInDatabase() - { - bool result = false; - try - { - ValidateOpenSession(); - result = Session.XSession.TableExists(Schema, Name); - } - catch (MySqlException ex) - { - switch (ex.Number) - { - case (int)CloseNotification.IDLE: - case (int)CloseNotification.KILLED: - case (int)CloseNotification.SHUTDOWN: - XDevAPI.Session.ThrowSessionClosedByServerException(ex, Session); - break; - default: - throw; - } - } - return result; - } - - /// - /// Returns the document with the given identifier. - /// - /// The unique identifier of the document to replace. - /// A object if a document matching given identifier exists; otherwise, null. - /// is null or white space. - /// This is a direct execution method. - public T GetOne(object id) - { - if (id == null) - throw new ArgumentNullException(nameof(id)); - string stringId = id.ToString(); - if (string.IsNullOrWhiteSpace(stringId)) - throw new ArgumentNullException(nameof(id), Resources.ParameterNullOrEmpty); - - return Find("_id = :id").Bind("id", id).Execute().FetchOne(); - } - } -} +// Copyright © 2015, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySql.Data; +using MySql.Data.MySqlClient; +using MySqlX.XDevAPI.Common; +using MySqlX.XDevAPI.CRUD; +using System; + +namespace MySqlX.XDevAPI +{ + /// + /// Represents a collection of documents with a generic type. + /// + /// + public class Collection : DatabaseObject + { + /// + /// Initializes a new instance of the generic Collection class based on the specified schema + /// and name. + /// + /// The object associated to this collection. + /// The name of the collection. + public Collection(Schema s, string name) : base(s, name) { } + + /// + /// Creates an containing the provided generic object. The add + /// statement can be further modified before execution. + /// + /// The generic object to add. + /// An object containing the object to add. + public AddStatement Add(params object[] items) + { + if (items == null) + throw new ArgumentNullException(); + + AddStatement stmt = new AddStatement(this); + stmt.Add(items); + return stmt; + } + + #region Remove Operations + + /// + /// Creates a with the given condition that can be used to remove + /// one or more documents from a collection.The statement can then be further modified before execution. + /// + /// The condition to match documents. + /// A object set with the given condition. + /// is null or white space. + /// The statement can then be further modified before execution. + public RemoveStatement Remove(string condition) + { + if (string.IsNullOrWhiteSpace(condition)) + throw new ArgumentNullException(nameof(condition), Resources.ParameterNullOrEmpty); + + RemoveStatement stmt = new RemoveStatement(this, condition); + return stmt; + } + + /// + /// Removes the document with the given identifier. + /// + /// The unique identifier of the document to replace. + /// A object containing the results of the execution. + /// is null or white space. + /// This is a direct execution method. + public Result RemoveOne(object id) + { + if (id == null) + throw new ArgumentNullException(nameof(id)); + string stringId = id.ToString(); + if (string.IsNullOrWhiteSpace(stringId)) + throw new ArgumentNullException(nameof(id), Resources.ParameterNullOrEmpty); + + return Remove("_id = :id").Bind("id", id).Execute(); + } + + #endregion + + #region Modify Operations + + /// + /// Creates a with the given condition that can be used to modify one or more + /// documents from a collection. + /// + /// The condition to match documents. + /// A object set with the given condition. + /// is null or white space. + /// The statement can then be further modified before execution. + public ModifyStatement Modify(string condition) + { + if (string.IsNullOrWhiteSpace(condition)) + throw new ArgumentNullException(nameof(condition), Resources.ParameterNullOrEmpty); + + ModifyStatement stmt = new ModifyStatement(this, condition); + return stmt; + } + #endregion + + /// + /// Returns the number of documents in this collection on the server. + /// + /// The number of documents found. + public long Count() + { + long result = 0; + try + { + ValidateOpenSession(); + result = Session.XSession.TableCount(Schema, Name, "Collection"); + } + catch (MySqlException ex) + { + switch (ex.Number) + { + case (int)CloseNotification.IDLE: + case (int)CloseNotification.KILLED: + case (int)CloseNotification.SHUTDOWN: + XDevAPI.Session.ThrowSessionClosedByServerException(ex, Session); + break; + default: + throw; + } + } + return result; + } + + /// + /// Creates a with the given condition which can be used to find documents in a + /// collection. + /// + /// An optional condition to match documents. + /// A object set with the given condition. + /// The statement can then be further modified before execution. + public FindStatement Find(string condition = null) + { + FindStatement stmt = new FindStatement(this, condition); + return stmt; + } + + /// + /// Creates an index based on the properties provided in the JSON document. + /// + /// The index name. + /// JSON document describing the index to be created. + /// + /// is a JSON document with the following fields: + /// + /// - fields: array of IndexField objects, each describing a single document member to be + /// included in the index (see below). + /// - type: string, (optional) the type of index. One of INDEX or SPATIAL. Default is INDEX and may + /// be omitted. + /// + ///   + /// A single IndexField description consists of the following fields: + /// + /// - field: string, the full document path to the document member or field to be indexed. + /// - type: string, one of the supported SQL column types to map the field into (see the following list). + /// For numeric types, the optional UNSIGNED keyword may follow. For the TEXT type, the length to consider for + /// indexing may be added. + /// - required: bool, (optional) true if the field is required to exist in the document. defaults to + /// false, except for GEOJSON where it defaults to true. + /// - options: int, (optional) special option flags for use when decoding GEOJSON data. + /// - srid: int, (optional) srid value for use when decoding GEOJSON data. + /// + ///   + /// Supported SQL column types: + /// + /// - INT [UNSIGNED] + /// - TINYINT [UNSIGNED] + /// - SMALLINT[UNSIGNED] + /// - MEDIUMINT [UNSIGNED] + /// - INTEGER [UNSIGNED] + /// - BIGINT [UNSIGNED] + /// - REAL [UNSIGNED] + /// - FLOAT [UNSIGNED] + /// - DOUBLE [UNSIGNED] + /// - DECIMAL [UNSIGNED] + /// - NUMERIC [UNSIGNED] + /// - DATE + /// - TIME + /// - TIMESTAMP + /// - DATETIME + /// - TEXT[(length)] + /// - CHAR[(lenght)] + /// - GEOJSON (extra options: options, srid) + /// + /// + public void CreateIndex(string indexName, object indexDefinition) + { + new CreateCollectionIndexStatement(this, indexName, new DbDoc(indexDefinition)).Execute(); + } + + /// + /// Drops a collection index. + /// + /// The index name. + /// is null or white space. + public void DropIndex(string indexName) + { + if (string.IsNullOrWhiteSpace(indexName)) throw new ArgumentNullException(nameof(indexName)); + + ValidateOpenSession(); + + try + { + bool indexExists = Convert.ToInt32(Session.XSession.ExecuteQueryAsScalar( + string.Format("SELECT COUNT(*)>0 FROM information_schema.statistics WHERE table_schema = '{0}' AND table_name = '{1}' AND index_name = '{2}'", + this.Schema.Name, this.Name, indexName))) == 1; + if (!indexExists) return; + + Session.XSession.DropCollectionIndex(this.Schema.Name, this.Name, indexName); + } + catch (MySqlException ex) + { + switch (ex.Number) + { + case (int)CloseNotification.IDLE: + case (int)CloseNotification.KILLED: + case (int)CloseNotification.SHUTDOWN: + XDevAPI.Session.ThrowSessionClosedByServerException(ex, Session); + break; + default: + throw; + } + } + } + + /// + /// Verifies if the current collection exists in the server schema. + /// + /// true if the collection exists; otherwise, false. + public override bool ExistsInDatabase() + { + bool result = false; + try + { + ValidateOpenSession(); + result = Session.XSession.TableExists(Schema, Name); + } + catch (MySqlException ex) + { + switch (ex.Number) + { + case (int)CloseNotification.IDLE: + case (int)CloseNotification.KILLED: + case (int)CloseNotification.SHUTDOWN: + XDevAPI.Session.ThrowSessionClosedByServerException(ex, Session); + break; + default: + throw; + } + } + return result; + } + + /// + /// Returns the document with the given identifier. + /// + /// The unique identifier of the document to replace. + /// A object if a document matching given identifier exists; otherwise, null. + /// is null or white space. + /// This is a direct execution method. + public T GetOne(object id) + { + if (id == null) + throw new ArgumentNullException(nameof(id)); + string stringId = id.ToString(); + if (string.IsNullOrWhiteSpace(stringId)) + throw new ArgumentNullException(nameof(id), Resources.ParameterNullOrEmpty); + + return Find("_id = :id").Bind("id", id).Execute().FetchOne(); + } + } +} diff --git a/MySQL.Data/src/X/XDevAPI/Iterator.cs b/MySQL.Data/src/X/XDevAPI/Iterator.cs index 81a6c1443..208425359 100644 --- a/MySQL.Data/src/X/XDevAPI/Iterator.cs +++ b/MySQL.Data/src/X/XDevAPI/Iterator.cs @@ -1,16 +1,16 @@ -// Copyright © 2015, 2017, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2015, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/X/XDevAPI/MySqlExpression.cs b/MySQL.Data/src/X/XDevAPI/MySqlExpression.cs index dc740c116..e3f433348 100644 --- a/MySQL.Data/src/X/XDevAPI/MySqlExpression.cs +++ b/MySQL.Data/src/X/XDevAPI/MySqlExpression.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2017, 2021, Oracle and/or its affiliates. +// Copyright © 2017, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/X/XDevAPI/MySqlX.cs b/MySQL.Data/src/X/XDevAPI/MySqlX.cs index aab91be04..9dc53bc73 100644 --- a/MySQL.Data/src/X/XDevAPI/MySqlX.cs +++ b/MySQL.Data/src/X/XDevAPI/MySqlX.cs @@ -1,147 +1,147 @@ -// Copyright (c) 2015, 2022, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -namespace MySqlX.XDevAPI -{ - - /// - /// Main class for session operations related to Connector/NET implementation of the X DevAPI. - /// - - public class MySQLX - { - /// - /// Opens a session to the server given or to the first available server if multiple servers were specified. - /// - /// The connection string or URI string format. - /// - /// A object representing the established session. - /// Multiple hosts can be specified as part of the which - /// will enable client side failover when trying to establish a connection. For additional details and syntax - /// examples refer to the remarks section. - public static Session GetSession(string connectionString) - { - return new Session(connectionString); - } - - /// - /// Opens a session to the server given. - /// - /// The connection data for the server. - /// - /// A object representing the established session. - public static Session GetSession(object connectionData) - { - return new Session(connectionData); - } - - /// - /// Creates a new instance. - /// - /// The connection string or URI string format. - /// - /// The connection options in JSON string format. - /// A object representing a session pool. - public static Client GetClient(string connectionString, string connectionOptions) - { - return new Client(connectionString, connectionOptions); - } - - /// - /// Creates a new instance. - /// - /// The connection string or URI string format. - /// - /// The connection options in object format. - /// - /// - /// new { pooling = new - /// { - /// enabled = true, - /// maxSize = 15, - /// maxIdleTime = 60000, - /// queueTimeout = 60000 - /// } - /// } - /// - /// - /// - /// A object representing a session pool. - public static Client GetClient(string connectionString, object connectionOptions) - { - return new Client(connectionString, connectionOptions); - } - - /// - /// Creates a new instance. - /// - /// The connection data. - /// - /// The connection options in JSON string format. - /// A object representing a session pool. - public static Client GetClient(object connectionData, string connectionOptions) - { - return new Client(connectionData, connectionOptions); - } - - /// - /// Creates a new instance. - /// - /// The connection data. - /// - /// The connection options in object format. - /// - /// - /// new { pooling = new - /// { - /// enabled = true, - /// maxSize = 15, - /// maxIdleTime = 60000, - /// queueTimeout = 60000 - /// } - /// } - /// - /// - /// - /// A object representing a session pool. - public static Client GetClient(object connectionData, object connectionOptions) - { - return new Client(connectionData, connectionOptions); - } - - //public static Iterator CsvFileRowIterator() - //{ - // throw new NotImplementedException(); - //} - - //public static Iterator JsonFileDocIterator() - //{ - // throw new NotImplementedException(); - //} - } -} +// Copyright © 2015, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +namespace MySqlX.XDevAPI +{ + + /// + /// Main class for session operations related to Connector/NET implementation of the X DevAPI. + /// + + public class MySQLX + { + /// + /// Opens a session to the server given or to the first available server if multiple servers were specified. + /// + /// The connection string or URI string format. + /// + /// A object representing the established session. + /// Multiple hosts can be specified as part of the which + /// will enable client side failover when trying to establish a connection. For additional details and syntax + /// examples refer to the remarks section. + public static Session GetSession(string connectionString) + { + return new Session(connectionString); + } + + /// + /// Opens a session to the server given. + /// + /// The connection data for the server. + /// + /// A object representing the established session. + public static Session GetSession(object connectionData) + { + return new Session(connectionData); + } + + /// + /// Creates a new instance. + /// + /// The connection string or URI string format. + /// + /// The connection options in JSON string format. + /// A object representing a session pool. + public static Client GetClient(string connectionString, string connectionOptions) + { + return new Client(connectionString, connectionOptions); + } + + /// + /// Creates a new instance. + /// + /// The connection string or URI string format. + /// + /// The connection options in object format. + /// + /// + /// new { pooling = new + /// { + /// enabled = true, + /// maxSize = 15, + /// maxIdleTime = 60000, + /// queueTimeout = 60000 + /// } + /// } + /// + /// + /// + /// A object representing a session pool. + public static Client GetClient(string connectionString, object connectionOptions) + { + return new Client(connectionString, connectionOptions); + } + + /// + /// Creates a new instance. + /// + /// The connection data. + /// + /// The connection options in JSON string format. + /// A object representing a session pool. + public static Client GetClient(object connectionData, string connectionOptions) + { + return new Client(connectionData, connectionOptions); + } + + /// + /// Creates a new instance. + /// + /// The connection data. + /// + /// The connection options in object format. + /// + /// + /// new { pooling = new + /// { + /// enabled = true, + /// maxSize = 15, + /// maxIdleTime = 60000, + /// queueTimeout = 60000 + /// } + /// } + /// + /// + /// + /// A object representing a session pool. + public static Client GetClient(object connectionData, object connectionOptions) + { + return new Client(connectionData, connectionOptions); + } + + //public static Iterator CsvFileRowIterator() + //{ + // throw new NotImplementedException(); + //} + + //public static Iterator JsonFileDocIterator() + //{ + // throw new NotImplementedException(); + //} + } +} diff --git a/MySQL.Data/src/X/XDevAPI/MySqlXConnectionStringBuilder.cs b/MySQL.Data/src/X/XDevAPI/MySqlXConnectionStringBuilder.cs index 9ceeff51a..edd0959b3 100644 --- a/MySQL.Data/src/X/XDevAPI/MySqlXConnectionStringBuilder.cs +++ b/MySQL.Data/src/X/XDevAPI/MySqlXConnectionStringBuilder.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2019, 2022, Oracle and/or its affiliates. +// Copyright © 2019, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/X/XDevAPI/Relational/Column.cs b/MySQL.Data/src/X/XDevAPI/Relational/Column.cs index 2aabe71cf..08ac7a2d6 100644 --- a/MySQL.Data/src/X/XDevAPI/Relational/Column.cs +++ b/MySQL.Data/src/X/XDevAPI/Relational/Column.cs @@ -1,109 +1,109 @@ -// Copyright © 2015, 2017, Oracle and/or its affiliates. All rights reserved. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using System; -using MySqlX.Protocol; -using MySqlX.Data; -using MySql.Data.MySqlClient; -using MySql.Data.MySqlClient.X.XDevAPI.Common; - -namespace MySqlX.XDevAPI.Relational -{ - /// - /// Represents a table column. - /// - public class Column - { - internal ValueDecoder _decoder; - internal UInt64 _collationNumber; - - /// - /// Gets the original column name. - /// - public string ColumnName { get; internal set; } - /// - /// Gets the alias of the column name. - /// - public string ColumnLabel { get; internal set; } - /// - /// Gets the table name the column orginates from. - /// - public string TableName { get; internal set; } - /// - /// Gets the alias of the table name . - /// - public string TableLabel { get; internal set; } - /// - /// Gets the schema name the column originates from. - /// - public string SchemaName { get; internal set; } - /// - /// Gets the catalog the schema originates from. - /// In MySQL protocol this is `def` by default. - /// - public string DatabaseName { get; internal set; } - /// - /// Gets the collation used for this column. - /// - public string CollationName { get; internal set; } - /// - /// Gets the character set used for this column. - /// - public string CharacterSetName { get; internal set; } - /// - /// Gets the column length. - /// - public UInt32 Length { get; internal set; } - /// - /// Gets the fractional decimal digits for floating point and fixed point numbers. - /// - public UInt32 FractionalDigits { get; internal set; } - /// - /// Gets the Mysql data type. - /// - public ColumnType Type { get; internal set; } - /// - /// Gets the .NET Clr data type. - /// - public Type ClrType { get; internal set; } - /// - /// True if it's a signed number. - /// - public bool IsNumberSigned { get; internal set; } - /// - /// True if column is UINT zerofill or BYTES rightpad. - /// - public bool IsPadded { get; internal set; } - - /// - /// Initializes a new instance of the Column class. - /// - public Column() - {} - } -} +// Copyright © 2015, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using System; +using MySqlX.Protocol; +using MySqlX.Data; +using MySql.Data.MySqlClient; +using MySql.Data.MySqlClient.X.XDevAPI.Common; + +namespace MySqlX.XDevAPI.Relational +{ + /// + /// Represents a table column. + /// + public class Column + { + internal ValueDecoder _decoder; + internal UInt64 _collationNumber; + + /// + /// Gets the original column name. + /// + public string ColumnName { get; internal set; } + /// + /// Gets the alias of the column name. + /// + public string ColumnLabel { get; internal set; } + /// + /// Gets the table name the column orginates from. + /// + public string TableName { get; internal set; } + /// + /// Gets the alias of the table name . + /// + public string TableLabel { get; internal set; } + /// + /// Gets the schema name the column originates from. + /// + public string SchemaName { get; internal set; } + /// + /// Gets the catalog the schema originates from. + /// In MySQL protocol this is `def` by default. + /// + public string DatabaseName { get; internal set; } + /// + /// Gets the collation used for this column. + /// + public string CollationName { get; internal set; } + /// + /// Gets the character set used for this column. + /// + public string CharacterSetName { get; internal set; } + /// + /// Gets the column length. + /// + public UInt32 Length { get; internal set; } + /// + /// Gets the fractional decimal digits for floating point and fixed point numbers. + /// + public UInt32 FractionalDigits { get; internal set; } + /// + /// Gets the Mysql data type. + /// + public ColumnType Type { get; internal set; } + /// + /// Gets the .NET Clr data type. + /// + public Type ClrType { get; internal set; } + /// + /// True if it's a signed number. + /// + public bool IsNumberSigned { get; internal set; } + /// + /// True if column is UINT zerofill or BYTES rightpad. + /// + public bool IsPadded { get; internal set; } + + /// + /// Initializes a new instance of the Column class. + /// + public Column() + {} + } +} diff --git a/MySQL.Data/src/X/XDevAPI/Relational/InternalRowResult.cs b/MySQL.Data/src/X/XDevAPI/Relational/InternalRowResult.cs index b689dff59..ae6c99928 100644 --- a/MySQL.Data/src/X/XDevAPI/Relational/InternalRowResult.cs +++ b/MySQL.Data/src/X/XDevAPI/Relational/InternalRowResult.cs @@ -1,140 +1,140 @@ -// Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using MySqlX.XDevAPI.Common; -using MySqlX.Sessions; -using MySql.Data.MySqlClient; -using System.Collections.ObjectModel; -using System.Linq; - -namespace MySqlX.XDevAPI.Relational -{ - /// - /// Represents a resultset that contains rows of data. - /// - public class InternalRowResult : BufferingResult - { - internal InternalRowResult(InternalSession session) : base(session) - { - } - - /// - /// Gets the columns in this resultset. - /// -#if NET_45_OR_GREATER - public IReadOnlyList Columns -#else - public ReadOnlyCollection Columns -#endif - { - get { return _columns.AsReadOnly(); } - } - - /// - /// Gets the number of columns in this resultset. - /// - public Int32 ColumnCount - { - get { return _columns.Count; } - } - - /// - /// Gets a list containing the column names in this resultset. - /// - public List ColumnNames - { - get { return _columns.Select(o => o.ColumnLabel).ToList(); } - } - - /// - /// Gets the rows of this resultset. This collection will be incomplete unless all the rows have been read - /// either by using the Next method or the Buffer method. - /// -#if NET_45_OR_GREATER - public IReadOnlyList Rows -#else - public ReadOnlyCollection Rows -#endif - { - get { return _items.AsReadOnly(); } - } - - /// - /// Gets the value of the column value at the current index. - /// - /// The column index. - /// The CLR value at the column index. - public object this[int index] - { - get { return GetValue(index); } - } - - /// - /// Allows getting the value of the column value at the current index. - /// - /// The column index. - /// The CLR value at the column index. - private object GetValue(int index) - { - if (_position == _items.Count) - throw new InvalidOperationException("No data at position"); - return _items[_position][index]; - } - - /// - /// Returns the index of the given column name. - /// - /// The name of the column to find. - /// The numeric index of column. - public int IndexOf(string name) - { - if (!NameMap.ContainsKey(name)) - throw new MySqlException("Column not found '" + name + "'"); - return NameMap[name]; - } - - protected override Row ReadItem(bool dumping) - { - ///TODO: fix this - List values = Protocol.ReadRow(this); - if (values == null) return null; - if (dumping) return new Row(NameMap, null); - - Debug.Assert(values.Count == _columns.Count, "Value count does not equal column count"); - object[] clrValues = new object[values.Count]; - for (int i = 0; i < values.Count; i++) - clrValues[i] = Columns[i]._decoder.ClrValueDecoder(values[i]); - - Row row = new Row(NameMap, clrValues); - return row; - } - } -} +// Copyright © 2015, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using MySqlX.XDevAPI.Common; +using MySqlX.Sessions; +using MySql.Data.MySqlClient; +using System.Collections.ObjectModel; +using System.Linq; + +namespace MySqlX.XDevAPI.Relational +{ + /// + /// Represents a resultset that contains rows of data. + /// + public class InternalRowResult : BufferingResult + { + internal InternalRowResult(InternalSession session) : base(session) + { + } + + /// + /// Gets the columns in this resultset. + /// +#if NET_45_OR_GREATER + public IReadOnlyList Columns +#else + public ReadOnlyCollection Columns +#endif + { + get { return _columns.AsReadOnly(); } + } + + /// + /// Gets the number of columns in this resultset. + /// + public Int32 ColumnCount + { + get { return _columns.Count; } + } + + /// + /// Gets a list containing the column names in this resultset. + /// + public List ColumnNames + { + get { return _columns.Select(o => o.ColumnLabel).ToList(); } + } + + /// + /// Gets the rows of this resultset. This collection will be incomplete unless all the rows have been read + /// either by using the Next method or the Buffer method. + /// +#if NET_45_OR_GREATER + public IReadOnlyList Rows +#else + public ReadOnlyCollection Rows +#endif + { + get { return _items.AsReadOnly(); } + } + + /// + /// Gets the value of the column value at the current index. + /// + /// The column index. + /// The CLR value at the column index. + public object this[int index] + { + get { return GetValue(index); } + } + + /// + /// Allows getting the value of the column value at the current index. + /// + /// The column index. + /// The CLR value at the column index. + private object GetValue(int index) + { + if (_position == _items.Count) + throw new InvalidOperationException("No data at position"); + return _items[_position][index]; + } + + /// + /// Returns the index of the given column name. + /// + /// The name of the column to find. + /// The numeric index of column. + public int IndexOf(string name) + { + if (!NameMap.ContainsKey(name)) + throw new MySqlException("Column not found '" + name + "'"); + return NameMap[name]; + } + + protected override Row ReadItem(bool dumping) + { + ///TODO: fix this + List values = Protocol.ReadRow(this); + if (values == null) return null; + if (dumping) return new Row(NameMap, null); + + Debug.Assert(values.Count == _columns.Count, "Value count does not equal column count"); + object[] clrValues = new object[values.Count]; + for (int i = 0; i < values.Count; i++) + clrValues[i] = Columns[i]._decoder.ClrValueDecoder(values[i]); + + Row row = new Row(NameMap, clrValues); + return row; + } + } +} diff --git a/MySQL.Data/src/X/XDevAPI/Relational/Row.cs b/MySQL.Data/src/X/XDevAPI/Relational/Row.cs index 25c22d17a..719303b1f 100644 --- a/MySQL.Data/src/X/XDevAPI/Relational/Row.cs +++ b/MySQL.Data/src/X/XDevAPI/Relational/Row.cs @@ -1,97 +1,97 @@ -// Copyright © 2015, 2017, Oracle and/or its affiliates. All rights reserved. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySql.Data; -using MySqlX; -using System; -using System.Collections.Generic; - -namespace MySqlX.XDevAPI.Relational -{ - /// - /// Represents a single row of data in a table. - /// - public class Row - { - private object[] _values; - private Dictionary _nameMap; - - internal Row(Dictionary nameMap, object[] values) - { - _values = values; - _nameMap = nameMap; - } - - /// - /// Gets the value of the row at the given index. - /// - /// The column index to retrieve the value. - /// The value at the index. - public object this[int index] - { - get { return GetValue(index); } - } - - /// - /// Gets the value of the column as a string. - /// - /// The name of the column. - /// The value of the column as a string. - public string GetString(string name) - { - return GetValue(name).ToString(); - } - - /// - /// Gets a string based indexer into the row. Returns the value as a CLR type. - /// - /// The column index to get. - /// The CLR value for the column. - public object this[string name] - { - get - { - return GetValue(name); - } - } - - private object GetValue(int index) - { - if (index < 0 || index >= _values.Length) - throw new IndexOutOfRangeException(String.Format(ResourcesX.InvalidRowIndex, index)); - return _values[index]; - } - - private object GetValue(string name) - { - if (!_nameMap.ContainsKey(name)) - throw new InvalidOperationException(String.Format(ResourcesX.InvalidNameIndex, name)); - return GetValue(_nameMap[name]); - } - } -} +// Copyright © 2015, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySql.Data; +using MySqlX; +using System; +using System.Collections.Generic; + +namespace MySqlX.XDevAPI.Relational +{ + /// + /// Represents a single row of data in a table. + /// + public class Row + { + private object[] _values; + private Dictionary _nameMap; + + internal Row(Dictionary nameMap, object[] values) + { + _values = values; + _nameMap = nameMap; + } + + /// + /// Gets the value of the row at the given index. + /// + /// The column index to retrieve the value. + /// The value at the index. + public object this[int index] + { + get { return GetValue(index); } + } + + /// + /// Gets the value of the column as a string. + /// + /// The name of the column. + /// The value of the column as a string. + public string GetString(string name) + { + return GetValue(name).ToString(); + } + + /// + /// Gets a string based indexer into the row. Returns the value as a CLR type. + /// + /// The column index to get. + /// The CLR value for the column. + public object this[string name] + { + get + { + return GetValue(name); + } + } + + private object GetValue(int index) + { + if (index < 0 || index >= _values.Length) + throw new IndexOutOfRangeException(String.Format(ResourcesX.InvalidRowIndex, index)); + return _values[index]; + } + + private object GetValue(string name) + { + if (!_nameMap.ContainsKey(name)) + throw new InvalidOperationException(String.Format(ResourcesX.InvalidNameIndex, name)); + return GetValue(_nameMap[name]); + } + } +} diff --git a/MySQL.Data/src/X/XDevAPI/Relational/RowResult.cs b/MySQL.Data/src/X/XDevAPI/Relational/RowResult.cs index a59af481d..d8e7cede2 100644 --- a/MySQL.Data/src/X/XDevAPI/Relational/RowResult.cs +++ b/MySQL.Data/src/X/XDevAPI/Relational/RowResult.cs @@ -1,43 +1,43 @@ -// Copyright © 2015, 2017, Oracle and/or its affiliates. All rights reserved. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySqlX.Sessions; - -namespace MySqlX.XDevAPI.Relational -{ - - /// - /// Inherits from . Creates a resultset that contains rows of data. - /// - public sealed class RowResult : InternalRowResult - { - internal RowResult(InternalSession session) : base(session) - { - } - } -} +// Copyright © 2015, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySqlX.Sessions; + +namespace MySqlX.XDevAPI.Relational +{ + + /// + /// Inherits from . Creates a resultset that contains rows of data. + /// + public sealed class RowResult : InternalRowResult + { + internal RowResult(InternalSession session) : base(session) + { + } + } +} diff --git a/MySQL.Data/src/X/XDevAPI/Relational/SqlResult.cs b/MySQL.Data/src/X/XDevAPI/Relational/SqlResult.cs index d4ca4f291..c02d7ca6d 100644 --- a/MySQL.Data/src/X/XDevAPI/Relational/SqlResult.cs +++ b/MySQL.Data/src/X/XDevAPI/Relational/SqlResult.cs @@ -1,68 +1,68 @@ -// Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using System; -using MySqlX.Sessions; - -namespace MySqlX.XDevAPI.Relational -{ - /// - /// Represents a resultset that contains rows of data for relational operations. - /// - public class SqlResult : InternalRowResult - { - internal SqlResult(InternalSession session) : base(session) - { - - } - - /// - /// Gets a boolean value indicating if this result has data. - /// - public bool HasData - { - get { return _hasData; } - } - - /// - /// Moves to next resultset. - /// - /// True if there is a new resultset, false otherwise. - public bool NextResult() - { - if (!_hasMoreResults) - return false; - _hasData = Protocol.HasData(this); - LoadColumnData(); - _isComplete = !_hasData; - _position = -1; - _items.Clear(); - return _hasData; - } - } -} +// Copyright © 2015, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using System; +using MySqlX.Sessions; + +namespace MySqlX.XDevAPI.Relational +{ + /// + /// Represents a resultset that contains rows of data for relational operations. + /// + public class SqlResult : InternalRowResult + { + internal SqlResult(InternalSession session) : base(session) + { + + } + + /// + /// Gets a boolean value indicating if this result has data. + /// + public bool HasData + { + get { return _hasData; } + } + + /// + /// Moves to next resultset. + /// + /// True if there is a new resultset, false otherwise. + public bool NextResult() + { + if (!_hasMoreResults) + return false; + _hasData = Protocol.HasData(this); + LoadColumnData(); + _isComplete = !_hasData; + _position = -1; + _items.Clear(); + return _hasData; + } + } +} diff --git a/MySQL.Data/src/X/XDevAPI/Relational/SqlStatement.cs b/MySQL.Data/src/X/XDevAPI/Relational/SqlStatement.cs index 8ce94b656..18b83c872 100644 --- a/MySQL.Data/src/X/XDevAPI/Relational/SqlStatement.cs +++ b/MySQL.Data/src/X/XDevAPI/Relational/SqlStatement.cs @@ -1,108 +1,108 @@ -// Copyright (c) 2015, 2023, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySql.Data.MySqlClient; -using MySqlX.XDevAPI.Common; -using System; -using System.Collections.Generic; - -namespace MySqlX.XDevAPI.Relational -{ - /// - /// Represents a sql statement. - /// - public class SqlStatement : BaseStatement - { - /// - /// Initializes a new instance of the SqlStament class bassed on the session and sql statement. - /// - /// The session the Sql statement belongs to. - /// The Sql statement. - public SqlStatement(Session session, string sql) : base(session) - { - SQL = sql; - } - - /// - /// Gets the current Sql statement. - /// - public string SQL { get; private set; } - /// - /// Gets the list of parameters associated to this Sql statement. - /// - protected internal List parameters = new List(); - - /// - /// Executes the current Sql statement. - /// - /// A object with the resultset and execution status. - public override SqlResult Execute() - { - SqlResult result = null; - try - { - ValidateOpenSession(); - result = GetSQLResult(this); - } - catch (MySqlException ex) - { - switch (ex.Number) - { - case (int)CloseNotification.IDLE: - case (int)CloseNotification.KILLED: - case (int)CloseNotification.SHUTDOWN: - XDevAPI.Session.ThrowSessionClosedByServerException(ex, Session); - break; - default: - throw; - } - } - - return result; - } - - private SqlResult GetSQLResult(SqlStatement statement) - { - return Session.XSession.GetSQLResult(statement.SQL, parameters.ToArray()); - } - - /// - /// Binds the parameters values by position. - /// - /// The parameter values. - /// This set with the binded parameters. - public SqlStatement Bind(params object[] values) - { - if (values == null) - parameters.Add(null); - else - parameters.AddRange(values); - return this; - } - } -} +// Copyright © 2015, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySql.Data.MySqlClient; +using MySqlX.XDevAPI.Common; +using System; +using System.Collections.Generic; + +namespace MySqlX.XDevAPI.Relational +{ + /// + /// Represents a sql statement. + /// + public class SqlStatement : BaseStatement + { + /// + /// Initializes a new instance of the SqlStament class bassed on the session and sql statement. + /// + /// The session the Sql statement belongs to. + /// The Sql statement. + public SqlStatement(Session session, string sql) : base(session) + { + SQL = sql; + } + + /// + /// Gets the current Sql statement. + /// + public string SQL { get; private set; } + /// + /// Gets the list of parameters associated to this Sql statement. + /// + protected internal List parameters = new List(); + + /// + /// Executes the current Sql statement. + /// + /// A object with the resultset and execution status. + public override SqlResult Execute() + { + SqlResult result = null; + try + { + ValidateOpenSession(); + result = GetSQLResult(this); + } + catch (MySqlException ex) + { + switch (ex.Number) + { + case (int)CloseNotification.IDLE: + case (int)CloseNotification.KILLED: + case (int)CloseNotification.SHUTDOWN: + XDevAPI.Session.ThrowSessionClosedByServerException(ex, Session); + break; + default: + throw; + } + } + + return result; + } + + private SqlResult GetSQLResult(SqlStatement statement) + { + return Session.XSession.GetSQLResult(statement.SQL, parameters.ToArray()); + } + + /// + /// Binds the parameters values by position. + /// + /// The parameter values. + /// This set with the binded parameters. + public SqlStatement Bind(params object[] values) + { + if (values == null) + parameters.Add(null); + else + parameters.AddRange(values); + return this; + } + } +} diff --git a/MySQL.Data/src/X/XDevAPI/Relational/Table.cs b/MySQL.Data/src/X/XDevAPI/Relational/Table.cs index d9ff1be07..48f22d541 100644 --- a/MySQL.Data/src/X/XDevAPI/Relational/Table.cs +++ b/MySQL.Data/src/X/XDevAPI/Relational/Table.cs @@ -1,172 +1,172 @@ -// Copyright (c) 2015, 2020, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using System; -using MySql.Data.MySqlClient; -using MySqlX.XDevAPI.Relational; - -namespace MySqlX.XDevAPI.Relational -{ - /// - /// Represents a server Table or View. - /// - public class Table : DatabaseObject - { - private bool? isView; - - /// - /// Gets a value indicating whether the object is - /// a View (True) or a Table (False). - /// - public bool IsView { - get - { - return CheckIsView(); - } - internal set - { - isView = value; - } - } - - private bool CheckIsView() - { - if (!isView.HasValue) - { - ValidateOpenSession(); - string type = Session.XSession.GetObjectType(Schema, Name).ToUpperInvariant(); - isView = (type == "VIEW"); - } - return isView.Value; - } - - internal Table(Schema schema, string name, bool isView) - : base(schema, name) - { - this.isView = isView; - } - - internal Table(Schema schema, string name) - : base(schema, name) - { - } - - internal Table() : base(null, null) { } - - /// - /// Creates a set with the columns to select. The table select - /// statement can be further modified before execution. This method is intended to select a set - /// of table rows. - /// - /// The optional column names to select. - /// A object for select chain operations. - public TableSelectStatement Select(params string[] columns) - { - return new TableSelectStatement(this, columns); - } - - /// - /// Creates a set with the fileds to insert to. The table - /// insert statement can be further modified before exeuction. This method is intended to - /// insert one or multiple rows into a table. - /// - /// The list of fields to insert. - /// A object for insert chain operations. - public TableInsertStatement Insert(params string[] fields) - { - return new TableInsertStatement(this, fields); - } - - /// - /// Creates a . This method is intended to update table rows - /// values. - /// - /// A object for update chain operations. - public TableUpdateStatement Update() - { - return new TableUpdateStatement(this); - } - - /// - /// Creates a . This method is intended to delete rows from a - /// table. - /// - /// A object for delete chain operations. - public TableDeleteStatement Delete() - { - return new TableDeleteStatement(this, null); - } - - /// - /// Returns the number of rows in the table on the server. - /// - /// The number of rows. - public long Count() - { - long result=0; - try - { - ValidateOpenSession(); - result = Session.XSession.TableCount(Schema, Name, "Table"); - } - catch (MySqlException ex) - { - switch (ex.Number) - { - case (int)CloseNotification.IDLE: - case (int)CloseNotification.KILLED: - case (int)CloseNotification.SHUTDOWN: - XDevAPI.Session.ThrowSessionClosedByServerException(ex, Session); - break; - default: - throw; - } - } - return result; - } - - /// - /// Verifies if the table exists in the database. - /// - /// true if the table exists; otherwise, false. - public override bool ExistsInDatabase() - { - bool result = false; - try - { - ValidateOpenSession(); - return Session.XSession.TableExists(Schema, Name); - } - catch (MySqlException e) - { - XDevAPI.Session.ThrowSessionClosedByServerException(e, Session); - } - return result; - } - } -} +// Copyright © 2015, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using System; +using MySql.Data.MySqlClient; +using MySqlX.XDevAPI.Relational; + +namespace MySqlX.XDevAPI.Relational +{ + /// + /// Represents a server Table or View. + /// + public class Table : DatabaseObject + { + private bool? isView; + + /// + /// Gets a value indicating whether the object is + /// a View (True) or a Table (False). + /// + public bool IsView { + get + { + return CheckIsView(); + } + internal set + { + isView = value; + } + } + + private bool CheckIsView() + { + if (!isView.HasValue) + { + ValidateOpenSession(); + string type = Session.XSession.GetObjectType(Schema, Name).ToUpperInvariant(); + isView = (type == "VIEW"); + } + return isView.Value; + } + + internal Table(Schema schema, string name, bool isView) + : base(schema, name) + { + this.isView = isView; + } + + internal Table(Schema schema, string name) + : base(schema, name) + { + } + + internal Table() : base(null, null) { } + + /// + /// Creates a set with the columns to select. The table select + /// statement can be further modified before execution. This method is intended to select a set + /// of table rows. + /// + /// The optional column names to select. + /// A object for select chain operations. + public TableSelectStatement Select(params string[] columns) + { + return new TableSelectStatement(this, columns); + } + + /// + /// Creates a set with the fileds to insert to. The table + /// insert statement can be further modified before exeuction. This method is intended to + /// insert one or multiple rows into a table. + /// + /// The list of fields to insert. + /// A object for insert chain operations. + public TableInsertStatement Insert(params string[] fields) + { + return new TableInsertStatement(this, fields); + } + + /// + /// Creates a . This method is intended to update table rows + /// values. + /// + /// A object for update chain operations. + public TableUpdateStatement Update() + { + return new TableUpdateStatement(this); + } + + /// + /// Creates a . This method is intended to delete rows from a + /// table. + /// + /// A object for delete chain operations. + public TableDeleteStatement Delete() + { + return new TableDeleteStatement(this, null); + } + + /// + /// Returns the number of rows in the table on the server. + /// + /// The number of rows. + public long Count() + { + long result=0; + try + { + ValidateOpenSession(); + result = Session.XSession.TableCount(Schema, Name, "Table"); + } + catch (MySqlException ex) + { + switch (ex.Number) + { + case (int)CloseNotification.IDLE: + case (int)CloseNotification.KILLED: + case (int)CloseNotification.SHUTDOWN: + XDevAPI.Session.ThrowSessionClosedByServerException(ex, Session); + break; + default: + throw; + } + } + return result; + } + + /// + /// Verifies if the table exists in the database. + /// + /// true if the table exists; otherwise, false. + public override bool ExistsInDatabase() + { + bool result = false; + try + { + ValidateOpenSession(); + return Session.XSession.TableExists(Schema, Name); + } + catch (MySqlException e) + { + XDevAPI.Session.ThrowSessionClosedByServerException(e, Session); + } + return result; + } + } +} diff --git a/MySQL.Data/src/X/XDevAPI/Relational/TableDeleteStatement.cs b/MySQL.Data/src/X/XDevAPI/Relational/TableDeleteStatement.cs index 2d3b5a9d3..74dbbcb96 100644 --- a/MySQL.Data/src/X/XDevAPI/Relational/TableDeleteStatement.cs +++ b/MySQL.Data/src/X/XDevAPI/Relational/TableDeleteStatement.cs @@ -1,66 +1,66 @@ -// Copyright (c) 2015, 2023, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySqlX.XDevAPI.Common; -using System; - -namespace MySqlX.XDevAPI.Relational -{ - /// - /// Represents a chaining table delete statement. - /// - public class TableDeleteStatement : FilterableStatement - { - internal TableDeleteStatement(Table table, string condition) : base(table, condition) - { - FilterData.IsRelational = true; - } - - /// - /// Sets user-defined sorting criteria for the operation. The strings use normal SQL syntax like - /// "order ASC" or "pages DESC, age ASC". - /// - /// The order criteria. - /// A generic object representing the implementing statement type. - public TableDeleteStatement OrderBy(params string[] order) - { - FilterData.OrderBy = order; - SetChanged(); - return this; - } - - /// - /// Executes the delete statement. - /// - /// A object containing the results of the delete execution. - public override Result Execute() - { - return Execute(Target.Session.XSession.DeleteRows, this); - } - } -} +// Copyright © 2015, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySqlX.XDevAPI.Common; +using System; + +namespace MySqlX.XDevAPI.Relational +{ + /// + /// Represents a chaining table delete statement. + /// + public class TableDeleteStatement : FilterableStatement + { + internal TableDeleteStatement(Table table, string condition) : base(table, condition) + { + FilterData.IsRelational = true; + } + + /// + /// Sets user-defined sorting criteria for the operation. The strings use normal SQL syntax like + /// "order ASC" or "pages DESC, age ASC". + /// + /// The order criteria. + /// A generic object representing the implementing statement type. + public TableDeleteStatement OrderBy(params string[] order) + { + FilterData.OrderBy = order; + SetChanged(); + return this; + } + + /// + /// Executes the delete statement. + /// + /// A object containing the results of the delete execution. + public override Result Execute() + { + return Execute(Target.Session.XSession.DeleteRows, this); + } + } +} diff --git a/MySQL.Data/src/X/XDevAPI/Relational/TableInsertStatement.cs b/MySQL.Data/src/X/XDevAPI/Relational/TableInsertStatement.cs index 77eb84080..fcd5706c3 100644 --- a/MySQL.Data/src/X/XDevAPI/Relational/TableInsertStatement.cs +++ b/MySQL.Data/src/X/XDevAPI/Relational/TableInsertStatement.cs @@ -1,71 +1,71 @@ -// Copyright (c) 2015, 2023, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySqlX.XDevAPI.Common; -using System; -using System.Collections.Generic; - -namespace MySqlX.XDevAPI.Relational -{ - /// - /// Represents a chaining table insert statement. - /// - public class TableInsertStatement : TargetedBaseStatement - { - internal string[] fields; - internal List values = new List(); - internal object[] parameters; - - internal TableInsertStatement(Table table, string[] fields) : base(table) - { - this.fields = fields; - } - - /// - /// Executes the insert statement. - /// - /// A object containing the results of the insert statement. - public override Result Execute() - { - ValidateOpenSession(); - return Target.Session.XSession.InsertRows(this); - } - - /// - /// Values to be inserted. - /// Multiple rows supported. - /// - /// The values to be inserted. - /// This same object. - public TableInsertStatement Values(params object[] values) - { - this.values.Add(values); - return this; - } - } -} +// Copyright © 2015, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySqlX.XDevAPI.Common; +using System; +using System.Collections.Generic; + +namespace MySqlX.XDevAPI.Relational +{ + /// + /// Represents a chaining table insert statement. + /// + public class TableInsertStatement : TargetedBaseStatement + { + internal string[] fields; + internal List values = new List(); + internal object[] parameters; + + internal TableInsertStatement(Table table, string[] fields) : base(table) + { + this.fields = fields; + } + + /// + /// Executes the insert statement. + /// + /// A object containing the results of the insert statement. + public override Result Execute() + { + ValidateOpenSession(); + return Target.Session.XSession.InsertRows(this); + } + + /// + /// Values to be inserted. + /// Multiple rows supported. + /// + /// The values to be inserted. + /// This same object. + public TableInsertStatement Values(params object[] values) + { + this.values.Add(values); + return this; + } + } +} diff --git a/MySQL.Data/src/X/XDevAPI/Relational/TableSelectStatement.cs b/MySQL.Data/src/X/XDevAPI/Relational/TableSelectStatement.cs index 41df41dfb..b32f39fb1 100644 --- a/MySQL.Data/src/X/XDevAPI/Relational/TableSelectStatement.cs +++ b/MySQL.Data/src/X/XDevAPI/Relational/TableSelectStatement.cs @@ -1,141 +1,141 @@ -// Copyright (c) 2015, 2023, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySql.Data; -using MySql.Data.MySqlClient; -using MySqlX.XDevAPI.Common; -using MySqlX.XDevAPI.CRUD; -using System; -using System.Collections.Generic; - -namespace MySqlX.XDevAPI.Relational -{ - /// - /// Represents a chaining table select statement. - /// - public class TableSelectStatement : FilterableStatement - { - internal FindParams findParams = new FindParams(); - - internal TableSelectStatement(Table t, params string[] projection) : base(t) - { - findParams.Projection = projection; - FilterData.IsRelational = true; - } - - /// - /// Executes the select statement. - /// - /// A object containing the results of the execution and data. - public override RowResult Execute() - { - return Execute(Target.Session.XSession.FindRows, this); - } - - /// - /// Locks matching rows against updates. - /// - /// Optional row lock option to use. - /// This same object set with lock shared option. - /// The server version is lower than 8.0.3. - public TableSelectStatement LockShared(LockContention lockOption = LockContention.Default) - { - if (!this.Session.InternalSession.GetServerVersion().isAtLeast(8, 0, 3)) - throw new MySqlException(string.Format(ResourcesX.FunctionalityNotSupported, "8.0.3")); - - findParams.Locking = Protocol.X.RowLock.SharedLock; - findParams.LockingOption = lockOption; - SetChanged(); - return this; - } - - /// - /// Locks matching rows so no other transaction can read or write to it. - /// - /// Optional row lock option to use. - /// This same object set with the lock exclusive option. - /// The server version is lower than 8.0.3. - public TableSelectStatement LockExclusive(LockContention lockOption = LockContention.Default) - { - if (!this.Session.InternalSession.GetServerVersion().isAtLeast(8, 0, 3)) - throw new MySqlException(string.Format(ResourcesX.FunctionalityNotSupported, "8.0.3")); - - findParams.Locking = Protocol.X.RowLock.ExclusiveLock; - findParams.LockingOption = lockOption; - SetChanged(); - return this; - } - - /// - /// Sets the table aggregation. - /// - /// The column list for aggregation. - /// This same object set with the specified group-by criteria. - public TableSelectStatement GroupBy(params string[] groupBy) - { - if (groupBy == null) - return this; - - var groupByList = new List(); - foreach (var item in groupBy) - { - if (item != null) - groupByList.Add(item); - } - - findParams.GroupBy = groupByList.Count > 0 ? groupByList.ToArray() : null; - SetChanged(); - return this; - } - - /// - /// Filters criteria for aggregated groups. - /// - /// The filter criteria for aggregated groups. - /// This same object set with the specified filter criteria. - public TableSelectStatement Having(string having) - { - findParams.GroupByCritieria = having; - SetChanged(); - return this; - } - - /// - /// Sets user-defined sorting criteria for the operation. The strings use normal SQL syntax like - /// "order ASC" or "pages DESC, age ASC". - /// - /// The order criteria. - /// A generic object that represents the implementing statement type. - public TableSelectStatement OrderBy(params string[] order) - { - FilterData.OrderBy = order; - SetChanged(); - return this; - } - } -} +// Copyright © 2015, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySql.Data; +using MySql.Data.MySqlClient; +using MySqlX.XDevAPI.Common; +using MySqlX.XDevAPI.CRUD; +using System; +using System.Collections.Generic; + +namespace MySqlX.XDevAPI.Relational +{ + /// + /// Represents a chaining table select statement. + /// + public class TableSelectStatement : FilterableStatement + { + internal FindParams findParams = new FindParams(); + + internal TableSelectStatement(Table t, params string[] projection) : base(t) + { + findParams.Projection = projection; + FilterData.IsRelational = true; + } + + /// + /// Executes the select statement. + /// + /// A object containing the results of the execution and data. + public override RowResult Execute() + { + return Execute(Target.Session.XSession.FindRows, this); + } + + /// + /// Locks matching rows against updates. + /// + /// Optional row lock option to use. + /// This same object set with lock shared option. + /// The server version is lower than 8.0.3. + public TableSelectStatement LockShared(LockContention lockOption = LockContention.Default) + { + if (!this.Session.InternalSession.GetServerVersion().isAtLeast(8, 0, 3)) + throw new MySqlException(string.Format(ResourcesX.FunctionalityNotSupported, "8.0.3")); + + findParams.Locking = Protocol.X.RowLock.SharedLock; + findParams.LockingOption = lockOption; + SetChanged(); + return this; + } + + /// + /// Locks matching rows so no other transaction can read or write to it. + /// + /// Optional row lock option to use. + /// This same object set with the lock exclusive option. + /// The server version is lower than 8.0.3. + public TableSelectStatement LockExclusive(LockContention lockOption = LockContention.Default) + { + if (!this.Session.InternalSession.GetServerVersion().isAtLeast(8, 0, 3)) + throw new MySqlException(string.Format(ResourcesX.FunctionalityNotSupported, "8.0.3")); + + findParams.Locking = Protocol.X.RowLock.ExclusiveLock; + findParams.LockingOption = lockOption; + SetChanged(); + return this; + } + + /// + /// Sets the table aggregation. + /// + /// The column list for aggregation. + /// This same object set with the specified group-by criteria. + public TableSelectStatement GroupBy(params string[] groupBy) + { + if (groupBy == null) + return this; + + var groupByList = new List(); + foreach (var item in groupBy) + { + if (item != null) + groupByList.Add(item); + } + + findParams.GroupBy = groupByList.Count > 0 ? groupByList.ToArray() : null; + SetChanged(); + return this; + } + + /// + /// Filters criteria for aggregated groups. + /// + /// The filter criteria for aggregated groups. + /// This same object set with the specified filter criteria. + public TableSelectStatement Having(string having) + { + findParams.GroupByCritieria = having; + SetChanged(); + return this; + } + + /// + /// Sets user-defined sorting criteria for the operation. The strings use normal SQL syntax like + /// "order ASC" or "pages DESC, age ASC". + /// + /// The order criteria. + /// A generic object that represents the implementing statement type. + public TableSelectStatement OrderBy(params string[] order) + { + FilterData.OrderBy = order; + SetChanged(); + return this; + } + } +} diff --git a/MySQL.Data/src/X/XDevAPI/Relational/TableUpdateStatement.cs b/MySQL.Data/src/X/XDevAPI/Relational/TableUpdateStatement.cs index 643652b3a..f87e94347 100644 --- a/MySQL.Data/src/X/XDevAPI/Relational/TableUpdateStatement.cs +++ b/MySQL.Data/src/X/XDevAPI/Relational/TableUpdateStatement.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2015, 2023, Oracle and/or its affiliates. +// Copyright © 2015, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/X/XDevAPI/Schema.cs b/MySQL.Data/src/X/XDevAPI/Schema.cs index 4bec5525e..f333ce894 100644 --- a/MySQL.Data/src/X/XDevAPI/Schema.cs +++ b/MySQL.Data/src/X/XDevAPI/Schema.cs @@ -1,349 +1,349 @@ -// Copyright (c) 2015, 2023, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySql.Data; -using MySql.Data.MySqlClient; -using MySqlX.XDevAPI.Common; -using MySqlX.XDevAPI.Relational; -using System; -using System.Collections.Generic; - -namespace MySqlX.XDevAPI -{ - /// - /// Represents a schema or database. - /// - public class Schema : DatabaseObject - { - internal Schema(BaseSession session, string name) : base(null, name) - { - Schema = this; - Session = session; - } - - /// - /// Session related to current schema. - /// - public new BaseSession Session { get; private set; } - - - #region Browse Functions - - /// - /// Returns a list of all collections in this schema. - /// - /// A list representing all found collections. - public List GetCollections() - { - List result = null; - try - { - ValidateOpenSession(); - result = Session.XSession.GetObjectList(this, "COLLECTION"); - } - catch (MySqlException ex) - { - switch (ex.Number) - { - case (int)CloseNotification.IDLE: - case (int)CloseNotification.KILLED: - case (int)CloseNotification.SHUTDOWN: - XDevAPI.Session.ThrowSessionClosedByServerException(ex, Session); - break; - default: - throw; - } - } - return result; - } - - /// - /// Returns a list of all tables in this schema. - /// - /// A list representing all found tables. - public List GetTables() - { - List
result = null; - try - { - ValidateOpenSession(); - result = Session.XSession.GetObjectList
(this, "TABLE", "VIEW"); - } - catch (MySqlException ex) - { - switch (ex.Number) - { - case (int)CloseNotification.IDLE: - case (int)CloseNotification.KILLED: - case (int)CloseNotification.SHUTDOWN: - XDevAPI.Session.ThrowSessionClosedByServerException(ex, Session); - break; - default: - throw; - } - } - return result; - } - - #endregion - - #region Instance Functions - - /// - /// Gets a collection by name. - /// - /// The name of the collection to get. - /// Ensures the collection exists in the schema. - /// A object matching the given name. - public Collection GetCollection(string name, bool ValidateExistence = false) - { - Collection c = new Collection(this, name); - if (ValidateExistence) - { - ValidateOpenSession(); - if (!c.ExistsInDatabase()) - throw new MySqlException(String.Format("Collection '{0}' does not exist.", name)); - } - return c; - } - - /// - /// Gets a typed collection object. This is useful for using domain objects. - /// - /// The name of collection to get. - /// Ensures the collection exists in the schema. - /// A generic object set with the given name. - public Collection GetCollection(string name, bool ValidateExistence = false) - { - Collection c = new Collection(this, name); - - if (ValidateExistence) - { - ValidateOpenSession(); - if (!c.ExistsInDatabase()) - throw new MySqlException(String.Format("Collection '{0}' does not exist.", name)); - } - return c; - } - - /// - /// Gets the given collection as a table. - /// - /// The name of the collection. - /// A object set with the given name. - public Table GetCollectionAsTable(string name) - { - return GetTable(name); - } - - /// - /// Gets a table object. Upon return the object may or may not be valid. - /// - /// The name of the table object. - /// A object set with the given name. - public Table GetTable(string name) - { - return new Table(this, name); - } - - #endregion - - #region Create Functions - - /// - /// Creates a . - /// - /// The name of the collection to create. - /// If false, throws an exception if the collection exists. - /// Collection referente. - public Collection CreateCollection(string collectionName, bool ReuseExisting = false) - { - ValidateOpenSession(); - Collection coll = new Collection(this, collectionName); - try - { - if (Session.Version.isAtLeast(8, 0, 19)) - { - CreateCollectionOptions options = new CreateCollectionOptions() { ReuseExisting = ReuseExisting }; - Session.XSession.CreateCollection(Name, collectionName, options); - } - else - { - Session.XSession.CreateCollection(Name, collectionName); - } - } - catch (MySqlException ex) when (ex.Number == (int)CloseNotification.IDLE || ex.Number == (int)CloseNotification.KILLED || ex.Number == (int)CloseNotification.SHUTDOWN) - { - XDevAPI.Session.ThrowSessionClosedByServerException(ex, Session); - } - catch (MySqlException ex) when (ex.Code == 1050) - { - if (ReuseExisting) - return coll; - throw; - } - return new Collection(this, collectionName); - } - - /// - /// Creates a including a schema validation. - /// - /// The name of the collection to create. - /// This object hold the parameters required to create the collection. - /// - /// Collection referente. - public Collection CreateCollection(string collectionName, CreateCollectionOptions options) - { - ValidateOpenSession(); - Collection coll = null; - - try - { - coll = new Collection(this, collectionName); - Session.XSession.CreateCollection(Name, collectionName, options); - } - catch (MySqlException ex) when (ex.Number == (int)CloseNotification.IDLE || ex.Number == (int)CloseNotification.KILLED || ex.Number == (int)CloseNotification.SHUTDOWN) - { - XDevAPI.Session.ThrowSessionClosedByServerException(ex, Session); - } - catch (MySqlException ex_1) when (ex_1.Code == 5015) - { - var msg = string.Format("{0}{1}{2}", ex_1.Message, ", ", ResourcesX.SchemaCreateCollectionMsg); - throw new MySqlException(msg); - } - catch (MySqlException ex) when (ex.Code == 1050) - { - if (options.ReuseExisting) - return coll; - throw; - } - catch (MySqlException) - { - throw; - } - return coll; - } - - /// - /// Modify a collection adding or removing schema validation parameters. - /// - /// The name of the collection to create. - /// This object encapsulate the Validation parameters level and schema. - /// Collection referente. - public Collection ModifyCollection(string collectionName, ModifyCollectionOptions? options) - { - ValidateOpenSession(); - Collection result = null; - try - { - Session.XSession.ModifyCollection(Name, collectionName, options); - result = new Collection(this, collectionName); - } - catch (MySqlException ex) when (ex.Number == (int)CloseNotification.IDLE || ex.Number == (int)CloseNotification.KILLED || ex.Number == (int)CloseNotification.SHUTDOWN) - { - XDevAPI.Session.ThrowSessionClosedByServerException(ex, Session); - } - catch (MySqlException ex_1) when (ex_1.Code == 5157) - { - var msg = string.Format("{0}{1}{2}", ex_1.Message, ", ", ResourcesX.SchemaCreateCollectionMsg); - throw new MySqlException(msg); - } - catch (MySqlException) - { - throw; - } - return result; - } - - #endregion - - /// - /// Drops the given collection. - /// - /// The name of the collection to drop. - /// is null. - public void DropCollection(string name) - { - if (string.IsNullOrWhiteSpace(name)) throw new ArgumentNullException(nameof(name)); - try - { - ValidateOpenSession(); - Collection c = GetCollection(name); - if (!c.ExistsInDatabase()) return; - Session.XSession.DropCollection(Name, name); - } - catch (MySqlException ex) - { - switch (ex.Number) - { - case (int)CloseNotification.IDLE: - case (int)CloseNotification.KILLED: - case (int)CloseNotification.SHUTDOWN: - XDevAPI.Session.ThrowSessionClosedByServerException(ex, Session); - break; - default: - throw; - } - } - } - - #region Base Class - - /// - /// Determines if this schema actually exists. - /// - /// True if exists, false otherwise. - public override bool ExistsInDatabase() - { - bool result = false; - try - { - ValidateOpenSession(); - string sql = String.Format("SELECT COUNT(*) FROM information_schema.schemata WHERE schema_name like '{0}'", Name); - long count = (long)Session.InternalSession.ExecuteQueryAsScalar(sql); - result = count > 0; - } - catch (MySqlException ex) - { - switch (ex.Number) - { - case (int)CloseNotification.IDLE: - case (int)CloseNotification.KILLED: - case (int)CloseNotification.SHUTDOWN: - XDevAPI.Session.ThrowSessionClosedByServerException(ex, Session); - break; - default: - throw; - } - } - return result; - } - - #endregion - } -} +// Copyright © 2015, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySql.Data; +using MySql.Data.MySqlClient; +using MySqlX.XDevAPI.Common; +using MySqlX.XDevAPI.Relational; +using System; +using System.Collections.Generic; + +namespace MySqlX.XDevAPI +{ + /// + /// Represents a schema or database. + /// + public class Schema : DatabaseObject + { + internal Schema(BaseSession session, string name) : base(null, name) + { + Schema = this; + Session = session; + } + + /// + /// Session related to current schema. + /// + public new BaseSession Session { get; private set; } + + + #region Browse Functions + + /// + /// Returns a list of all collections in this schema. + /// + /// A list representing all found collections. + public List GetCollections() + { + List result = null; + try + { + ValidateOpenSession(); + result = Session.XSession.GetObjectList(this, "COLLECTION"); + } + catch (MySqlException ex) + { + switch (ex.Number) + { + case (int)CloseNotification.IDLE: + case (int)CloseNotification.KILLED: + case (int)CloseNotification.SHUTDOWN: + XDevAPI.Session.ThrowSessionClosedByServerException(ex, Session); + break; + default: + throw; + } + } + return result; + } + + /// + /// Returns a list of all tables in this schema. + /// + /// A list representing all found tables. + public List
GetTables() + { + List
result = null; + try + { + ValidateOpenSession(); + result = Session.XSession.GetObjectList
(this, "TABLE", "VIEW"); + } + catch (MySqlException ex) + { + switch (ex.Number) + { + case (int)CloseNotification.IDLE: + case (int)CloseNotification.KILLED: + case (int)CloseNotification.SHUTDOWN: + XDevAPI.Session.ThrowSessionClosedByServerException(ex, Session); + break; + default: + throw; + } + } + return result; + } + + #endregion + + #region Instance Functions + + /// + /// Gets a collection by name. + /// + /// The name of the collection to get. + /// Ensures the collection exists in the schema. + /// A object matching the given name. + public Collection GetCollection(string name, bool ValidateExistence = false) + { + Collection c = new Collection(this, name); + if (ValidateExistence) + { + ValidateOpenSession(); + if (!c.ExistsInDatabase()) + throw new MySqlException(String.Format("Collection '{0}' does not exist.", name)); + } + return c; + } + + /// + /// Gets a typed collection object. This is useful for using domain objects. + /// + /// The name of collection to get. + /// Ensures the collection exists in the schema. + /// A generic object set with the given name. + public Collection GetCollection(string name, bool ValidateExistence = false) + { + Collection c = new Collection(this, name); + + if (ValidateExistence) + { + ValidateOpenSession(); + if (!c.ExistsInDatabase()) + throw new MySqlException(String.Format("Collection '{0}' does not exist.", name)); + } + return c; + } + + /// + /// Gets the given collection as a table. + /// + /// The name of the collection. + /// A object set with the given name. + public Table GetCollectionAsTable(string name) + { + return GetTable(name); + } + + /// + /// Gets a table object. Upon return the object may or may not be valid. + /// + /// The name of the table object. + /// A object set with the given name. + public Table GetTable(string name) + { + return new Table(this, name); + } + + #endregion + + #region Create Functions + + /// + /// Creates a . + /// + /// The name of the collection to create. + /// If false, throws an exception if the collection exists. + /// Collection referente. + public Collection CreateCollection(string collectionName, bool ReuseExisting = false) + { + ValidateOpenSession(); + Collection coll = new Collection(this, collectionName); + try + { + if (Session.Version.isAtLeast(8, 0, 19)) + { + CreateCollectionOptions options = new CreateCollectionOptions() { ReuseExisting = ReuseExisting }; + Session.XSession.CreateCollection(Name, collectionName, options); + } + else + { + Session.XSession.CreateCollection(Name, collectionName); + } + } + catch (MySqlException ex) when (ex.Number == (int)CloseNotification.IDLE || ex.Number == (int)CloseNotification.KILLED || ex.Number == (int)CloseNotification.SHUTDOWN) + { + XDevAPI.Session.ThrowSessionClosedByServerException(ex, Session); + } + catch (MySqlException ex) when (ex.Code == 1050) + { + if (ReuseExisting) + return coll; + throw; + } + return new Collection(this, collectionName); + } + + /// + /// Creates a including a schema validation. + /// + /// The name of the collection to create. + /// This object hold the parameters required to create the collection. + /// + /// Collection referente. + public Collection CreateCollection(string collectionName, CreateCollectionOptions options) + { + ValidateOpenSession(); + Collection coll = null; + + try + { + coll = new Collection(this, collectionName); + Session.XSession.CreateCollection(Name, collectionName, options); + } + catch (MySqlException ex) when (ex.Number == (int)CloseNotification.IDLE || ex.Number == (int)CloseNotification.KILLED || ex.Number == (int)CloseNotification.SHUTDOWN) + { + XDevAPI.Session.ThrowSessionClosedByServerException(ex, Session); + } + catch (MySqlException ex_1) when (ex_1.Code == 5015) + { + var msg = string.Format("{0}{1}{2}", ex_1.Message, ", ", ResourcesX.SchemaCreateCollectionMsg); + throw new MySqlException(msg); + } + catch (MySqlException ex) when (ex.Code == 1050) + { + if (options.ReuseExisting) + return coll; + throw; + } + catch (MySqlException) + { + throw; + } + return coll; + } + + /// + /// Modify a collection adding or removing schema validation parameters. + /// + /// The name of the collection to create. + /// This object encapsulate the Validation parameters level and schema. + /// Collection referente. + public Collection ModifyCollection(string collectionName, ModifyCollectionOptions? options) + { + ValidateOpenSession(); + Collection result = null; + try + { + Session.XSession.ModifyCollection(Name, collectionName, options); + result = new Collection(this, collectionName); + } + catch (MySqlException ex) when (ex.Number == (int)CloseNotification.IDLE || ex.Number == (int)CloseNotification.KILLED || ex.Number == (int)CloseNotification.SHUTDOWN) + { + XDevAPI.Session.ThrowSessionClosedByServerException(ex, Session); + } + catch (MySqlException ex_1) when (ex_1.Code == 5157) + { + var msg = string.Format("{0}{1}{2}", ex_1.Message, ", ", ResourcesX.SchemaCreateCollectionMsg); + throw new MySqlException(msg); + } + catch (MySqlException) + { + throw; + } + return result; + } + + #endregion + + /// + /// Drops the given collection. + /// + /// The name of the collection to drop. + /// is null. + public void DropCollection(string name) + { + if (string.IsNullOrWhiteSpace(name)) throw new ArgumentNullException(nameof(name)); + try + { + ValidateOpenSession(); + Collection c = GetCollection(name); + if (!c.ExistsInDatabase()) return; + Session.XSession.DropCollection(Name, name); + } + catch (MySqlException ex) + { + switch (ex.Number) + { + case (int)CloseNotification.IDLE: + case (int)CloseNotification.KILLED: + case (int)CloseNotification.SHUTDOWN: + XDevAPI.Session.ThrowSessionClosedByServerException(ex, Session); + break; + default: + throw; + } + } + } + + #region Base Class + + /// + /// Determines if this schema actually exists. + /// + /// True if exists, false otherwise. + public override bool ExistsInDatabase() + { + bool result = false; + try + { + ValidateOpenSession(); + string sql = String.Format("SELECT COUNT(*) FROM information_schema.schemata WHERE schema_name like '{0}'", Name); + long count = (long)Session.InternalSession.ExecuteQueryAsScalar(sql); + result = count > 0; + } + catch (MySqlException ex) + { + switch (ex.Number) + { + case (int)CloseNotification.IDLE: + case (int)CloseNotification.KILLED: + case (int)CloseNotification.SHUTDOWN: + XDevAPI.Session.ThrowSessionClosedByServerException(ex, Session); + break; + default: + throw; + } + } + return result; + } + + #endregion + } +} diff --git a/MySQL.Data/src/X/XDevAPI/Session.cs b/MySQL.Data/src/X/XDevAPI/Session.cs index 978e7de8a..8a78297d3 100644 --- a/MySQL.Data/src/X/XDevAPI/Session.cs +++ b/MySQL.Data/src/X/XDevAPI/Session.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2015, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/common/Cache.cs b/MySQL.Data/src/common/Cache.cs index bd1494f8d..ae74c0771 100644 --- a/MySQL.Data/src/common/Cache.cs +++ b/MySQL.Data/src/common/Cache.cs @@ -1,83 +1,83 @@ -// Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using System.Collections.Generic; - -namespace MySql.Data.Common -{ - internal class Cache - { - private readonly int _capacity; - private readonly Queue _keyQ; - private readonly Dictionary _contents; - - public Cache(int initialCapacity, int capacity) - { - _capacity = capacity; - _contents = new Dictionary(initialCapacity); - - if (capacity > 0) - _keyQ = new Queue(initialCapacity); - } - - public TValueType this[TKeyType key] - { - get - { - TValueType val; - if (_contents.TryGetValue(key, out val)) - return val; - else - return default(TValueType); - } - set { InternalAdd(key, value); } - } - - public void Add(TKeyType key, TValueType value) - { - InternalAdd(key, value); - } - - private void InternalAdd(TKeyType key, TValueType value) - { - if (!_contents.ContainsKey(key)) - { - - if (_capacity > 0) - { - _keyQ.Enqueue(key); - - if (_keyQ.Count > _capacity) - _contents.Remove(_keyQ.Dequeue()); - } - } - - _contents[key] = value; - } - } -} +// Copyright © 2004, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using System.Collections.Generic; + +namespace MySql.Data.Common +{ + internal class Cache + { + private readonly int _capacity; + private readonly Queue _keyQ; + private readonly Dictionary _contents; + + public Cache(int initialCapacity, int capacity) + { + _capacity = capacity; + _contents = new Dictionary(initialCapacity); + + if (capacity > 0) + _keyQ = new Queue(initialCapacity); + } + + public TValueType this[TKeyType key] + { + get + { + TValueType val; + if (_contents.TryGetValue(key, out val)) + return val; + else + return default(TValueType); + } + set { InternalAdd(key, value); } + } + + public void Add(TKeyType key, TValueType value) + { + InternalAdd(key, value); + } + + private void InternalAdd(TKeyType key, TValueType value) + { + if (!_contents.ContainsKey(key)) + { + + if (_capacity > 0) + { + _keyQ.Enqueue(key); + + if (_keyQ.Count > _capacity) + _contents.Remove(_keyQ.Dequeue()); + } + } + + _contents[key] = value; + } + } +} diff --git a/MySQL.Data/src/common/ContextString.cs b/MySQL.Data/src/common/ContextString.cs index cf57f4ca6..e91d49a6a 100644 --- a/MySQL.Data/src/common/ContextString.cs +++ b/MySQL.Data/src/common/ContextString.cs @@ -1,171 +1,171 @@ -// Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using System; -using System.Collections; -using System.Text; - -namespace MySql.Data.Common -{ - internal class ContextString - { - readonly bool _escapeBackslash; - - // Create a private ctor so the compiler doesn't give us a default one - public ContextString(string contextMarkers, bool escapeBackslash) - { - ContextMarkers = contextMarkers; - _escapeBackslash = escapeBackslash; - } - - public string ContextMarkers { get; set; } - - public int IndexOf(string src, string target) - { - return IndexOf(src, target, 0); - } - - public int IndexOf(string src, string target, int startIndex) - { - int index = src.IndexOf(target, startIndex); - while (index != -1) - { - if (!IndexInQuotes(src, index, startIndex)) break; - index = src.IndexOf(target, index + 1); - } - return index; - } - - private bool IndexInQuotes(string src, int index, int startIndex) - { - char contextMarker = Char.MinValue; - bool escaped = false; - - for (int i = startIndex; i < index; i++) - { - char c = src[i]; - - int contextIndex = ContextMarkers.IndexOf(c); - - // if we have found the closing marker for our open marker, then close the context - if (contextIndex > -1 && contextMarker == ContextMarkers[contextIndex] && !escaped) - contextMarker = Char.MinValue; - - // if we have found a context marker and we are not in a context yet, then start one - else if (contextMarker == Char.MinValue && contextIndex > -1 && !escaped) - contextMarker = c; - - else if (c == '\\' && _escapeBackslash) - escaped = !escaped; - } - return contextMarker != Char.MinValue || escaped; - } - - public int IndexOf(string src, char target) - { - char contextMarker = Char.MinValue; - bool escaped = false; - int pos = 0; - - foreach (char c in src) - { - int contextIndex = ContextMarkers.IndexOf(c); - - // if we have found the closing marker for our open marker, then close the context - if (contextIndex > -1 && contextMarker == ContextMarkers[contextIndex] && !escaped) - contextMarker = Char.MinValue; - - // if we have found a context marker and we are not in a context yet, then start one - else if (contextMarker == Char.MinValue && contextIndex > -1 && !escaped) - contextMarker = c; - - else if (contextMarker == Char.MinValue && c == target) - return pos; - else if (c == '\\' && _escapeBackslash) - escaped = !escaped; - pos++; - } - return -1; - } - - public string[] Split(string src, string delimiters) - { - ArrayList parts = new ArrayList(); - StringBuilder sb = new StringBuilder(); - bool escaped = false; - - char contextMarker = Char.MinValue; - - foreach (char c in src) - { - if (delimiters.IndexOf(c) != -1 && !escaped) - { - if (contextMarker != Char.MinValue) - sb.Append(c); - else - { - if (sb.Length <= 0) continue; - parts.Add(sb.ToString()); - sb.Remove(0, sb.Length); - } - } - else if (c == '\\' && _escapeBackslash) - escaped = !escaped; - else - { - int contextIndex = ContextMarkers.IndexOf(c); - if (!escaped && contextIndex != -1) - { - // if we have found the closing marker for our open - // marker, then close the context - if ((contextIndex % 2) == 1) - { - if (contextMarker == ContextMarkers[contextIndex - 1]) - contextMarker = Char.MinValue; - } - else - { - // if the opening and closing context markers are - // the same then we will always find the opening - // marker. - if (contextMarker == ContextMarkers[contextIndex + 1]) - contextMarker = Char.MinValue; - else if (contextMarker == Char.MinValue) - contextMarker = c; - } - } - - sb.Append(c); - } - } - if (sb.Length > 0) - parts.Add(sb.ToString()); - return (string[])parts.ToArray(typeof(string)); - } - } -} +// Copyright © 2004, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using System; +using System.Collections; +using System.Text; + +namespace MySql.Data.Common +{ + internal class ContextString + { + readonly bool _escapeBackslash; + + // Create a private ctor so the compiler doesn't give us a default one + public ContextString(string contextMarkers, bool escapeBackslash) + { + ContextMarkers = contextMarkers; + _escapeBackslash = escapeBackslash; + } + + public string ContextMarkers { get; set; } + + public int IndexOf(string src, string target) + { + return IndexOf(src, target, 0); + } + + public int IndexOf(string src, string target, int startIndex) + { + int index = src.IndexOf(target, startIndex); + while (index != -1) + { + if (!IndexInQuotes(src, index, startIndex)) break; + index = src.IndexOf(target, index + 1); + } + return index; + } + + private bool IndexInQuotes(string src, int index, int startIndex) + { + char contextMarker = Char.MinValue; + bool escaped = false; + + for (int i = startIndex; i < index; i++) + { + char c = src[i]; + + int contextIndex = ContextMarkers.IndexOf(c); + + // if we have found the closing marker for our open marker, then close the context + if (contextIndex > -1 && contextMarker == ContextMarkers[contextIndex] && !escaped) + contextMarker = Char.MinValue; + + // if we have found a context marker and we are not in a context yet, then start one + else if (contextMarker == Char.MinValue && contextIndex > -1 && !escaped) + contextMarker = c; + + else if (c == '\\' && _escapeBackslash) + escaped = !escaped; + } + return contextMarker != Char.MinValue || escaped; + } + + public int IndexOf(string src, char target) + { + char contextMarker = Char.MinValue; + bool escaped = false; + int pos = 0; + + foreach (char c in src) + { + int contextIndex = ContextMarkers.IndexOf(c); + + // if we have found the closing marker for our open marker, then close the context + if (contextIndex > -1 && contextMarker == ContextMarkers[contextIndex] && !escaped) + contextMarker = Char.MinValue; + + // if we have found a context marker and we are not in a context yet, then start one + else if (contextMarker == Char.MinValue && contextIndex > -1 && !escaped) + contextMarker = c; + + else if (contextMarker == Char.MinValue && c == target) + return pos; + else if (c == '\\' && _escapeBackslash) + escaped = !escaped; + pos++; + } + return -1; + } + + public string[] Split(string src, string delimiters) + { + ArrayList parts = new ArrayList(); + StringBuilder sb = new StringBuilder(); + bool escaped = false; + + char contextMarker = Char.MinValue; + + foreach (char c in src) + { + if (delimiters.IndexOf(c) != -1 && !escaped) + { + if (contextMarker != Char.MinValue) + sb.Append(c); + else + { + if (sb.Length <= 0) continue; + parts.Add(sb.ToString()); + sb.Remove(0, sb.Length); + } + } + else if (c == '\\' && _escapeBackslash) + escaped = !escaped; + else + { + int contextIndex = ContextMarkers.IndexOf(c); + if (!escaped && contextIndex != -1) + { + // if we have found the closing marker for our open + // marker, then close the context + if ((contextIndex % 2) == 1) + { + if (contextMarker == ContextMarkers[contextIndex - 1]) + contextMarker = Char.MinValue; + } + else + { + // if the opening and closing context markers are + // the same then we will always find the opening + // marker. + if (contextMarker == ContextMarkers[contextIndex + 1]) + contextMarker = Char.MinValue; + else if (contextMarker == Char.MinValue) + contextMarker = c; + } + } + + sb.Append(c); + } + } + if (sb.Length > 0) + parts.Add(sb.ToString()); + return (string[])parts.ToArray(typeof(string)); + } + } +} diff --git a/MySQL.Data/src/common/Dns/DnsEnums.cs b/MySQL.Data/src/common/Dns/DnsEnums.cs index 97a718c29..733c7d574 100644 --- a/MySQL.Data/src/common/Dns/DnsEnums.cs +++ b/MySQL.Data/src/common/Dns/DnsEnums.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2022, Oracle and/or its affiliates. +// Copyright © 2022, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/common/Dns/DnsQuestion.cs b/MySQL.Data/src/common/Dns/DnsQuestion.cs index d8f35d548..bde33a80d 100644 --- a/MySQL.Data/src/common/Dns/DnsQuestion.cs +++ b/MySQL.Data/src/common/Dns/DnsQuestion.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2022, Oracle and/or its affiliates. +// Copyright © 2022, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/common/Dns/DnsRecordHeader.cs b/MySQL.Data/src/common/Dns/DnsRecordHeader.cs index 198e23d61..424d665d6 100644 --- a/MySQL.Data/src/common/Dns/DnsRecordHeader.cs +++ b/MySQL.Data/src/common/Dns/DnsRecordHeader.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2022, Oracle and/or its affiliates. +// Copyright © 2022, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/common/Dns/DnsRecordReader.cs b/MySQL.Data/src/common/Dns/DnsRecordReader.cs index 060ce10dc..430b06427 100644 --- a/MySQL.Data/src/common/Dns/DnsRecordReader.cs +++ b/MySQL.Data/src/common/Dns/DnsRecordReader.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2022, Oracle and/or its affiliates. +// Copyright © 2022, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/common/Dns/DnsRecordUnknown.cs b/MySQL.Data/src/common/Dns/DnsRecordUnknown.cs index 6cff373c3..fc29994a0 100644 --- a/MySQL.Data/src/common/Dns/DnsRecordUnknown.cs +++ b/MySQL.Data/src/common/Dns/DnsRecordUnknown.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2022, Oracle and/or its affiliates. +// Copyright © 2022, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/common/Dns/DnsRequest.cs b/MySQL.Data/src/common/Dns/DnsRequest.cs index fa1c685a8..5b201b89d 100644 --- a/MySQL.Data/src/common/Dns/DnsRequest.cs +++ b/MySQL.Data/src/common/Dns/DnsRequest.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2022, Oracle and/or its affiliates. +// Copyright © 2022, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/common/Dns/DnsResolver.cs b/MySQL.Data/src/common/Dns/DnsResolver.cs index ab5063a74..7f0cfee23 100644 --- a/MySQL.Data/src/common/Dns/DnsResolver.cs +++ b/MySQL.Data/src/common/Dns/DnsResolver.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2022, Oracle and/or its affiliates. +// Copyright © 2022, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/common/Dns/DnsResourceRecord.cs b/MySQL.Data/src/common/Dns/DnsResourceRecord.cs index 32754b722..4b78af5a3 100644 --- a/MySQL.Data/src/common/Dns/DnsResourceRecord.cs +++ b/MySQL.Data/src/common/Dns/DnsResourceRecord.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2022, Oracle and/or its affiliates. +// Copyright © 2022, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/common/Dns/DnsResponse.cs b/MySQL.Data/src/common/Dns/DnsResponse.cs index ababab2d7..d1b9e0433 100644 --- a/MySQL.Data/src/common/Dns/DnsResponse.cs +++ b/MySQL.Data/src/common/Dns/DnsResponse.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2022, Oracle and/or its affiliates. +// Copyright © 2022, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/common/Dns/DnsSrvRecord.cs b/MySQL.Data/src/common/Dns/DnsSrvRecord.cs index 6c3fd39cf..c153b4b16 100644 --- a/MySQL.Data/src/common/Dns/DnsSrvRecord.cs +++ b/MySQL.Data/src/common/Dns/DnsSrvRecord.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2019, 2022, Oracle and/or its affiliates. +// Copyright © 2019, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -98,4 +98,4 @@ public int Compare(DnsSrvRecord x, DnsSrvRecord y) return priorityDiff == 0 ? y.Weight.CompareTo(x.Weight) : priorityDiff; } } -} \ No newline at end of file +} diff --git a/MySQL.Data/src/common/DnsSrv.cs b/MySQL.Data/src/common/DnsSrv.cs index 7d96dc7bf..b0539894b 100644 --- a/MySQL.Data/src/common/DnsSrv.cs +++ b/MySQL.Data/src/common/DnsSrv.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2019, 2022, Oracle and/or its affiliates. +// Copyright © 2019, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -119,4 +119,4 @@ internal static List SortSrvRecords(List srvRecords) /// private static void Reset() => _resolver = null; } -} \ No newline at end of file +} diff --git a/MySQL.Data/src/common/LowResolutionStopwatch.cs b/MySQL.Data/src/common/LowResolutionStopwatch.cs index 801adc1fa..208ee4669 100644 --- a/MySQL.Data/src/common/LowResolutionStopwatch.cs +++ b/MySQL.Data/src/common/LowResolutionStopwatch.cs @@ -1,101 +1,101 @@ -// Copyright (c) 2009, 2019, Oracle and/or its affiliates. All rights reserved. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using System; - -namespace MySql.Data.Common -{ - /// - /// This class is modeled after .NET Stopwatch. It provides better - /// performance (no system calls).It is however less precise than - /// .NET Stopwatch, measuring in milliseconds. It is adequate to use - /// when high-precision is not required (e.g for measuring IO timeouts), - /// but not for other tasks. - /// - internal class LowResolutionStopwatch - { - long _startTime; - public static readonly long Frequency = 1000; // measure in milliseconds - public static readonly bool IsHighResolution = false; - - public LowResolutionStopwatch() - { - ElapsedMilliseconds = 0; - } - public long ElapsedMilliseconds { get; private set; } - - public void Start() - { - _startTime = Environment.TickCount; - } - - public void Stop() - { - long now = Environment.TickCount; - long elapsed; - - // Calculate time different, handle possible overflow - if (now < _startTime) - { - if (now < 0) - elapsed = 1 + ((long)Int32.MaxValue - _startTime) + (now - (long)Int32.MinValue); - else - elapsed = Int32.MaxValue - _startTime + now; - } - else - elapsed = now - _startTime; - - ElapsedMilliseconds += elapsed; - } - - public void Reset() - { - ElapsedMilliseconds = 0; - _startTime = 0; - } - - public TimeSpan Elapsed => new TimeSpan(0, 0, 0, 0, (int)ElapsedMilliseconds); - - public static LowResolutionStopwatch StartNew() - { - LowResolutionStopwatch sw = new LowResolutionStopwatch(); - sw.Start(); - return sw; - } - - public static long GetTimestamp() - { - return Environment.TickCount; - } - - bool IsRunning() - { - return (_startTime != 0); - } - } -} +// Copyright © 2009, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using System; + +namespace MySql.Data.Common +{ + /// + /// This class is modeled after .NET Stopwatch. It provides better + /// performance (no system calls).It is however less precise than + /// .NET Stopwatch, measuring in milliseconds. It is adequate to use + /// when high-precision is not required (e.g for measuring IO timeouts), + /// but not for other tasks. + /// + internal class LowResolutionStopwatch + { + long _startTime; + public static readonly long Frequency = 1000; // measure in milliseconds + public static readonly bool IsHighResolution = false; + + public LowResolutionStopwatch() + { + ElapsedMilliseconds = 0; + } + public long ElapsedMilliseconds { get; private set; } + + public void Start() + { + _startTime = Environment.TickCount; + } + + public void Stop() + { + long now = Environment.TickCount; + long elapsed; + + // Calculate time different, handle possible overflow + if (now < _startTime) + { + if (now < 0) + elapsed = 1 + ((long)Int32.MaxValue - _startTime) + (now - (long)Int32.MinValue); + else + elapsed = Int32.MaxValue - _startTime + now; + } + else + elapsed = now - _startTime; + + ElapsedMilliseconds += elapsed; + } + + public void Reset() + { + ElapsedMilliseconds = 0; + _startTime = 0; + } + + public TimeSpan Elapsed => new TimeSpan(0, 0, 0, 0, (int)ElapsedMilliseconds); + + public static LowResolutionStopwatch StartNew() + { + LowResolutionStopwatch sw = new LowResolutionStopwatch(); + sw.Start(); + return sw; + } + + public static long GetTimestamp() + { + return Environment.TickCount; + } + + bool IsRunning() + { + return (_startTime != 0); + } + } +} diff --git a/MySQL.Data/src/common/MyNetworkStream.cs b/MySQL.Data/src/common/MyNetworkStream.cs index 7b69d4107..6223a5d11 100644 --- a/MySQL.Data/src/common/MyNetworkStream.cs +++ b/MySQL.Data/src/common/MyNetworkStream.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2009, 2023, Oracle and/or its affiliates. +// Copyright © 2009, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -385,4 +385,4 @@ private static void SetKeepAlive(Socket s, uint time) #endregion } -} \ No newline at end of file +} diff --git a/MySQL.Data/src/common/MySqlConnectionStringOption.cs b/MySQL.Data/src/common/MySqlConnectionStringOption.cs index 1fc3a7209..b05ea84fc 100644 --- a/MySQL.Data/src/common/MySqlConnectionStringOption.cs +++ b/MySQL.Data/src/common/MySqlConnectionStringOption.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2019, 2021, Oracle and/or its affiliates. +// Copyright © 2019, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/common/MySqlConnectionStringOptionCollection.cs b/MySQL.Data/src/common/MySqlConnectionStringOptionCollection.cs index 3455a11f2..81ba80bf3 100644 --- a/MySQL.Data/src/common/MySqlConnectionStringOptionCollection.cs +++ b/MySQL.Data/src/common/MySqlConnectionStringOptionCollection.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2019, 2021, Oracle and/or its affiliates. +// Copyright © 2019, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/common/MySqlTokenizer.cs b/MySQL.Data/src/common/MySqlTokenizer.cs index 10ef3d74d..5191d54b9 100644 --- a/MySQL.Data/src/common/MySqlTokenizer.cs +++ b/MySQL.Data/src/common/MySqlTokenizer.cs @@ -1,288 +1,288 @@ -// Copyright (c) 2004, 2021, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Text; - -namespace MySql.Data.Common -{ - internal class MySqlTokenizer - { - private string _sql; - - public MySqlTokenizer() - { - BackslashEscapes = true; - MultiLine = true; - Position = 0; - } - - public MySqlTokenizer(string input) - : this() - { - _sql = input; - } - - #region Properties - - public string Text - { - get { return _sql; } - set { _sql = value; Position = 0; } - } - - public bool AnsiQuotes { get; set; } - - public bool BackslashEscapes { get; set; } - - public bool MultiLine { get; set; } - - public bool SqlServerMode { get; set; } - - public bool Quoted { get; private set; } - - public bool IsComment { get; private set; } - - public int StartIndex { get; set; } - - public int StopIndex { get; set; } - - public int Position { get; set; } - - public bool ReturnComments { get; set; } - - #endregion - - public List GetAllTokens() - { - List tokens = new List(); - string token = NextToken(); - while (token != null) - { - tokens.Add(token); - token = NextToken(); - } - return tokens; - } - - public string NextToken() - { - while (FindToken()) - { - string token = _sql.Substring(StartIndex, StopIndex - StartIndex); - return token; - } - return null; - } - - public static bool IsParameter(string s) - { - if (String.IsNullOrEmpty(s)) return false; - if (s[0] == '?') return true; - return s.Length > 1 && s[0] == '@' && s[1] != '@'; - } - - public string NextParameter() - { - while (FindToken()) - { - if ((StopIndex - StartIndex) < 2) - { - if (IsParameter(_sql.Substring(StartIndex, 1))) return "?"; - else continue; - } - char c1 = _sql[StartIndex]; - char c2 = _sql[StartIndex + 1]; - if (c1 == '?' || - (c1 == '@' && c2 != '@')) - return _sql.Substring(StartIndex, StopIndex - StartIndex); - } - return null; - } - - public bool FindToken() - { - IsComment = Quoted = false; // reset our flags - StartIndex = StopIndex = -1; - - while (Position < _sql.Length) - { - char c = _sql[Position++]; - if (Char.IsWhiteSpace(c)) continue; - - if (c == '`' || c == '\'' || c == '"' || (c == '[' && SqlServerMode)) - ReadQuotedToken(c); - else if (c == '#' || c == '-' || c == '/') - { - if (!ReadComment(c)) - ReadSpecialToken(); - } - else - ReadUnquotedToken(); - if (StartIndex != -1) return true; - } - return false; - } - - public string ReadParenthesis() - { - StringBuilder sb = new StringBuilder("("); - int start = StartIndex; - string token = NextToken(); - while (true) - { - if (token == null) - throw new InvalidOperationException("Unable to parse SQL"); - sb.Append(token); - if (token == ")" && !Quoted) break; - token = NextToken(); - } - return sb.ToString(); - } - - private bool ReadComment(char c) - { - // make sure the comment starts correctly - if (c == '/' && (Position >= _sql.Length || _sql[Position] != '*')) return false; - if (c == '-' && ((Position + 1) >= _sql.Length || _sql[Position] != '-' || _sql[Position + 1] != ' ')) return false; - - string endingPattern = "\n"; - if (_sql[Position] == '*') - endingPattern = "*/"; - - int startingIndex = Position - 1; - - int index = _sql.IndexOf(endingPattern, Position); - if (endingPattern == "\n") - index = _sql.IndexOf('\n', Position); - if (index == -1) - index = _sql.Length - 1; - else - index += endingPattern.Length; - - Position = index; - if (ReturnComments) - { - StartIndex = startingIndex; - StopIndex = index; - IsComment = true; - } - return true; - } - - private void CalculatePosition(int start, int stop) - { - StartIndex = start; - StopIndex = stop; - if (!MultiLine) return; - } - - private void ReadUnquotedToken() - { - StartIndex = Position - 1; - - if (!IsSpecialCharacter(_sql[StartIndex])) - { - while (Position < _sql.Length) - { - char c = _sql[Position]; - if (Char.IsWhiteSpace(c)) break; - if (IsSpecialCharacter(c)) break; - Position++; - } - } - - Quoted = false; - StopIndex = Position; - } - - private void ReadSpecialToken() - { - StartIndex = Position - 1; - - Debug.Assert(IsSpecialCharacter(_sql[StartIndex])); - - StopIndex = Position; - Quoted = false; - } - - /// - /// Read a single quoted identifier from the stream - /// - /// - /// - private void ReadQuotedToken(char quoteChar) - { - if (quoteChar == '[') - quoteChar = ']'; - StartIndex = Position - 1; - bool escaped = false; - - bool found = false; - while (Position < _sql.Length) - { - char c = _sql[Position]; - - if (c == quoteChar && !escaped) - { - found = true; - break; - } - - if (escaped) - escaped = false; - else if (c == '\\' && BackslashEscapes) - escaped = true; - Position++; - } - if (found) Position++; - Quoted = found; - StopIndex = Position; - } - - private bool IsQuoteChar(char c) - { - return c == '`' || c == '\'' || c == '\"'; - } - - internal bool IsParameterMarker(char c) - { - return c == '@' || c == '?'; - } - - private bool IsSpecialCharacter(char c) - { - if (Char.IsLetterOrDigit(c) || - c == '$' || c == '_' || c == '.') return false; - if (IsParameterMarker(c)) return false; - return true; - } - } -} +// Copyright © 2004, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Text; + +namespace MySql.Data.Common +{ + internal class MySqlTokenizer + { + private string _sql; + + public MySqlTokenizer() + { + BackslashEscapes = true; + MultiLine = true; + Position = 0; + } + + public MySqlTokenizer(string input) + : this() + { + _sql = input; + } + + #region Properties + + public string Text + { + get { return _sql; } + set { _sql = value; Position = 0; } + } + + public bool AnsiQuotes { get; set; } + + public bool BackslashEscapes { get; set; } + + public bool MultiLine { get; set; } + + public bool SqlServerMode { get; set; } + + public bool Quoted { get; private set; } + + public bool IsComment { get; private set; } + + public int StartIndex { get; set; } + + public int StopIndex { get; set; } + + public int Position { get; set; } + + public bool ReturnComments { get; set; } + + #endregion + + public List GetAllTokens() + { + List tokens = new List(); + string token = NextToken(); + while (token != null) + { + tokens.Add(token); + token = NextToken(); + } + return tokens; + } + + public string NextToken() + { + while (FindToken()) + { + string token = _sql.Substring(StartIndex, StopIndex - StartIndex); + return token; + } + return null; + } + + public static bool IsParameter(string s) + { + if (String.IsNullOrEmpty(s)) return false; + if (s[0] == '?') return true; + return s.Length > 1 && s[0] == '@' && s[1] != '@'; + } + + public string NextParameter() + { + while (FindToken()) + { + if ((StopIndex - StartIndex) < 2) + { + if (IsParameter(_sql.Substring(StartIndex, 1))) return "?"; + else continue; + } + char c1 = _sql[StartIndex]; + char c2 = _sql[StartIndex + 1]; + if (c1 == '?' || + (c1 == '@' && c2 != '@')) + return _sql.Substring(StartIndex, StopIndex - StartIndex); + } + return null; + } + + public bool FindToken() + { + IsComment = Quoted = false; // reset our flags + StartIndex = StopIndex = -1; + + while (Position < _sql.Length) + { + char c = _sql[Position++]; + if (Char.IsWhiteSpace(c)) continue; + + if (c == '`' || c == '\'' || c == '"' || (c == '[' && SqlServerMode)) + ReadQuotedToken(c); + else if (c == '#' || c == '-' || c == '/') + { + if (!ReadComment(c)) + ReadSpecialToken(); + } + else + ReadUnquotedToken(); + if (StartIndex != -1) return true; + } + return false; + } + + public string ReadParenthesis() + { + StringBuilder sb = new StringBuilder("("); + int start = StartIndex; + string token = NextToken(); + while (true) + { + if (token == null) + throw new InvalidOperationException("Unable to parse SQL"); + sb.Append(token); + if (token == ")" && !Quoted) break; + token = NextToken(); + } + return sb.ToString(); + } + + private bool ReadComment(char c) + { + // make sure the comment starts correctly + if (c == '/' && (Position >= _sql.Length || _sql[Position] != '*')) return false; + if (c == '-' && ((Position + 1) >= _sql.Length || _sql[Position] != '-' || _sql[Position + 1] != ' ')) return false; + + string endingPattern = "\n"; + if (_sql[Position] == '*') + endingPattern = "*/"; + + int startingIndex = Position - 1; + + int index = _sql.IndexOf(endingPattern, Position); + if (endingPattern == "\n") + index = _sql.IndexOf('\n', Position); + if (index == -1) + index = _sql.Length - 1; + else + index += endingPattern.Length; + + Position = index; + if (ReturnComments) + { + StartIndex = startingIndex; + StopIndex = index; + IsComment = true; + } + return true; + } + + private void CalculatePosition(int start, int stop) + { + StartIndex = start; + StopIndex = stop; + if (!MultiLine) return; + } + + private void ReadUnquotedToken() + { + StartIndex = Position - 1; + + if (!IsSpecialCharacter(_sql[StartIndex])) + { + while (Position < _sql.Length) + { + char c = _sql[Position]; + if (Char.IsWhiteSpace(c)) break; + if (IsSpecialCharacter(c)) break; + Position++; + } + } + + Quoted = false; + StopIndex = Position; + } + + private void ReadSpecialToken() + { + StartIndex = Position - 1; + + Debug.Assert(IsSpecialCharacter(_sql[StartIndex])); + + StopIndex = Position; + Quoted = false; + } + + /// + /// Read a single quoted identifier from the stream + /// + /// + /// + private void ReadQuotedToken(char quoteChar) + { + if (quoteChar == '[') + quoteChar = ']'; + StartIndex = Position - 1; + bool escaped = false; + + bool found = false; + while (Position < _sql.Length) + { + char c = _sql[Position]; + + if (c == quoteChar && !escaped) + { + found = true; + break; + } + + if (escaped) + escaped = false; + else if (c == '\\' && BackslashEscapes) + escaped = true; + Position++; + } + if (found) Position++; + Quoted = found; + StopIndex = Position; + } + + private bool IsQuoteChar(char c) + { + return c == '`' || c == '\'' || c == '\"'; + } + + internal bool IsParameterMarker(char c) + { + return c == '@' || c == '?'; + } + + private bool IsSpecialCharacter(char c) + { + if (Char.IsLetterOrDigit(c) || + c == '$' || c == '_' || c == '.') return false; + if (IsParameterMarker(c)) return false; + return true; + } + } +} diff --git a/MySQL.Data/src/common/NativeMethods.cs b/MySQL.Data/src/common/NativeMethods.cs index dd008747a..79a601a65 100644 --- a/MySQL.Data/src/common/NativeMethods.cs +++ b/MySQL.Data/src/common/NativeMethods.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2009, 2022, Oracle and/or its affiliates. +// Copyright © 2009, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/common/Platform.cs b/MySQL.Data/src/common/Platform.cs index 4c0ec59ce..49203adbb 100644 --- a/MySQL.Data/src/common/Platform.cs +++ b/MySQL.Data/src/common/Platform.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2004, 2023, Oracle and/or its affiliates. +// Copyright © 2004, 2024, Oracle and/or its affiliates. // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/common/QueryNormalizer.cs b/MySQL.Data/src/common/QueryNormalizer.cs index f92d4d6ae..881a14874 100644 --- a/MySQL.Data/src/common/QueryNormalizer.cs +++ b/MySQL.Data/src/common/QueryNormalizer.cs @@ -1,380 +1,380 @@ -// Copyright (c) 2009, 2020 Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySql.Data.MySqlClient; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace MySql.Data.Common -{ - internal class QueryNormalizer - { - private static readonly List Keywords = new List(); - private readonly List _tokens = new List(); - private int _pos; - private string _fullSql; - private string _queryType; - - static QueryNormalizer() - { - Keywords = SchemaProvider.GetReservedWords().AsDataTable(). - Select(). - Select(x => x[0].ToString()).ToList(); - } - - public string QueryType => _queryType; - - public string Normalize(string sql) - { - _tokens.Clear(); - StringBuilder newSql = new StringBuilder(); - _fullSql = sql; - - TokenizeSql(sql); - DetermineStatementType(_tokens); - ProcessMathSymbols(_tokens); - CollapseValueLists(_tokens); - CollapseInLists(_tokens); - CollapseWhitespace(_tokens); - - foreach (Token t in _tokens.Where(t => t.Output)) - newSql.Append(t.Text); - - return newSql.ToString(); - } - - private void DetermineStatementType(List tok) - { - foreach (Token t in tok.Where(t => t.Type == TokenType.Keyword)) - { - _queryType = t.Text.ToUpperInvariant(); - break; - } - } - - /// - /// Mark - or + signs that are unary ops as no output - /// - /// - private static void ProcessMathSymbols(List tok) - { - Token lastToken = null; - - foreach (Token t in tok) - { - if (t.Type == TokenType.Symbol && - (t.Text == "-" || t.Text == "+")) - { - if (lastToken != null && - lastToken.Type != TokenType.Number && - lastToken.Type != TokenType.Identifier && - (lastToken.Type != TokenType.Symbol || lastToken.Text != ")")) - t.Output = false; - } - if (t.IsRealToken) - lastToken = t; - } - } - - private static void CollapseWhitespace(List tok) - { - Token lastToken = null; - - foreach (Token t in tok) - { - if (t.Output && - t.Type == TokenType.Whitespace && - lastToken != null && - lastToken.Type == TokenType.Whitespace) - { - t.Output = false; - } - if (t.Output) - lastToken = t; - } - } - - private void CollapseValueLists(List tok) - { - int pos = -1; - while (++pos < tok.Count) - { - Token t = tok[pos]; - if (t.Type != TokenType.Keyword) continue; - if (!t.Text.StartsWith("VALUE", StringComparison.OrdinalIgnoreCase)) continue; - CollapseValueList(tok, ref pos); - } - } - - private void CollapseValueList(List tok, ref int pos) - { - List parenIndices = new List(); - - // this while loop will find all closing parens in this value list - while (true) - { - // find the close ')' - while (++pos < tok.Count) - { - if (tok[pos].Type == TokenType.Symbol && tok[pos].Text == ")") - break; - if (pos == tok.Count - 1) - break; - } - parenIndices.Add(pos); - - // now find the next "real" token - while (++pos < tok.Count) - if (tok[pos].IsRealToken) break; - if (pos == tok.Count) break; - - if (tok[pos].Text == ",") continue; - pos--; - break; - } - - // if we only have 1 value then we don't collapse - if (parenIndices.Count < 2) return; - int index = parenIndices[0]; - tok[++index] = new Token(TokenType.Whitespace, " "); - tok[++index] = new Token(TokenType.Comment, "/* , ... */"); - index++; - - // now mark all the other tokens as no output - while (index <= parenIndices[parenIndices.Count - 1]) - tok[index++].Output = false; - } - - private void CollapseInLists(List tok) - { - int pos = -1; - while (++pos < tok.Count) - { - Token t = tok[pos]; - if (t.Type != TokenType.Keyword) continue; - if (t.Text != "IN") continue; - CollapseInList(tok, ref pos); - } - } - - private static Token GetNextRealToken(List tok, ref int pos) - { - while (++pos < tok.Count) - { - if (tok[pos].IsRealToken) return tok[pos]; - } - return null; - } - - private static void CollapseInList(List tok, ref int pos) - { - Token t = GetNextRealToken(tok, ref pos); - // Debug.Assert(t.Text == "("); - if (t == null) - return; - - // if the first token is a keyword then we likely have a - // SELECT .. IN (SELECT ...) - t = GetNextRealToken(tok, ref pos); - if (t == null || t.Type == TokenType.Keyword) return; - - int start = pos; - // first find all the tokens that make up the in list - while (++pos < tok.Count) - { - t = tok[pos]; - if (t.Type == TokenType.CommandComment) return; - if (!t.IsRealToken) continue; - if (t.Text == "(") return; - if (t.Text == ")") break; - } - int stop = pos; - - for (int i = stop; i > start; i--) - tok.RemoveAt(i); - tok.Insert(++start, new Token(TokenType.Whitespace, " ")); - tok.Insert(++start, new Token(TokenType.Comment, "/* , ... */")); - tok.Insert(++start, new Token(TokenType.Whitespace, " ")); - tok.Insert(++start, new Token(TokenType.Symbol, ")")); - } - - private void TokenizeSql(string sql) - { - _pos = 0; - - while (_pos < sql.Length) - { - char c = sql[_pos]; - if (LetterStartsComment(c) && ConsumeComment()) - continue; - if (Char.IsWhiteSpace(c)) - ConsumeWhitespace(); - else if (c == '\'' || c == '\"' || c == '`') - ConsumeQuotedToken(c); - else if (!IsSpecialCharacter(c)) - ConsumeUnquotedToken(); - else - ConsumeSymbol(); - } - } - - private bool LetterStartsComment(char c) - { - return c == '#' || c == '/' || c == '-'; - } - - private bool IsSpecialCharacter(char c) - { - return !Char.IsLetterOrDigit(c) && c != '$' && c != '_' && c != '.'; - } - - private bool ConsumeComment() - { - char c = _fullSql[_pos]; - // make sure the comment starts correctly - if (c == '/' && ((_pos + 1) >= _fullSql.Length || _fullSql[_pos + 1] != '*')) return false; - if (c == '-' && ((_pos + 2) >= _fullSql.Length || _fullSql[_pos + 1] != '-' || _fullSql[_pos + 2] != ' ')) return false; - - string endingPattern = "\n"; - if (c == '/') - endingPattern = "*/"; - - int startingIndex = _pos; - - int index = _fullSql.IndexOf(endingPattern, _pos); - if (index == -1) - index = _fullSql.Length - 1; - else - index += endingPattern.Length; - string comment = _fullSql.Substring(_pos, index - _pos); - if (comment.StartsWith("/*!", StringComparison.Ordinal)) - _tokens.Add(new Token(TokenType.CommandComment, comment)); - _pos = index; - return true; - } - - private void ConsumeSymbol() - { - char c = _fullSql[_pos++]; - _tokens.Add(new Token(TokenType.Symbol, c.ToString())); - } - - private void ConsumeQuotedToken(char c) - { - bool escaped = false; - int start = _pos; - _pos++; - while (_pos < _fullSql.Length) - { - char x = _fullSql[_pos]; - - if (x == c && !escaped) break; - - if (escaped) - escaped = false; - else if (x == '\\') - escaped = true; - _pos++; - } - _pos++; - _tokens.Add(c == '\'' - ? new Token(TokenType.String, "?") - : new Token(TokenType.Identifier, _fullSql.Substring(start, _pos - start))); - } - - private void ConsumeUnquotedToken() - { - int startPos = _pos; - while (_pos < _fullSql.Length && !IsSpecialCharacter(_fullSql[_pos])) - _pos++; - string word = _fullSql.Substring(startPos, _pos - startPos); - double v; - if (double.TryParse( - word, - System.Globalization.NumberStyles.Any, - System.Globalization.CultureInfo.InvariantCulture, - out v)) - _tokens.Add(new Token(TokenType.Number, "?")); - else - { - Token t = new Token(TokenType.Identifier, word); - if (IsKeyword(word)) - { - t.Type = TokenType.Keyword; - t.Text = t.Text.ToUpperInvariant(); - } - _tokens.Add(t); - } - } - - private void ConsumeWhitespace() - { - _tokens.Add(new Token(TokenType.Whitespace, " ")); - while (_pos < _fullSql.Length && Char.IsWhiteSpace(_fullSql[_pos])) - _pos++; - } - - private static bool IsKeyword(string word) - { - return Keywords.Contains(word.ToUpperInvariant()); - } - } - - internal class Token - { - public TokenType Type; - public string Text; - public bool Output; - - public Token(TokenType type, string text) - { - Type = type; - Text = text; - Output = true; - } - - public bool IsRealToken => Type != TokenType.Comment && - Type != TokenType.CommandComment && - Type != TokenType.Whitespace && - Output; - } - - internal enum TokenType - { - Keyword, - String, - Number, - Symbol, - Identifier, - Comment, - CommandComment, - Whitespace - } -} \ No newline at end of file +// Copyright © 2009, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySql.Data.MySqlClient; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace MySql.Data.Common +{ + internal class QueryNormalizer + { + private static readonly List Keywords = new List(); + private readonly List _tokens = new List(); + private int _pos; + private string _fullSql; + private string _queryType; + + static QueryNormalizer() + { + Keywords = SchemaProvider.GetReservedWords().AsDataTable(). + Select(). + Select(x => x[0].ToString()).ToList(); + } + + public string QueryType => _queryType; + + public string Normalize(string sql) + { + _tokens.Clear(); + StringBuilder newSql = new StringBuilder(); + _fullSql = sql; + + TokenizeSql(sql); + DetermineStatementType(_tokens); + ProcessMathSymbols(_tokens); + CollapseValueLists(_tokens); + CollapseInLists(_tokens); + CollapseWhitespace(_tokens); + + foreach (Token t in _tokens.Where(t => t.Output)) + newSql.Append(t.Text); + + return newSql.ToString(); + } + + private void DetermineStatementType(List tok) + { + foreach (Token t in tok.Where(t => t.Type == TokenType.Keyword)) + { + _queryType = t.Text.ToUpperInvariant(); + break; + } + } + + /// + /// Mark - or + signs that are unary ops as no output + /// + /// + private static void ProcessMathSymbols(List tok) + { + Token lastToken = null; + + foreach (Token t in tok) + { + if (t.Type == TokenType.Symbol && + (t.Text == "-" || t.Text == "+")) + { + if (lastToken != null && + lastToken.Type != TokenType.Number && + lastToken.Type != TokenType.Identifier && + (lastToken.Type != TokenType.Symbol || lastToken.Text != ")")) + t.Output = false; + } + if (t.IsRealToken) + lastToken = t; + } + } + + private static void CollapseWhitespace(List tok) + { + Token lastToken = null; + + foreach (Token t in tok) + { + if (t.Output && + t.Type == TokenType.Whitespace && + lastToken != null && + lastToken.Type == TokenType.Whitespace) + { + t.Output = false; + } + if (t.Output) + lastToken = t; + } + } + + private void CollapseValueLists(List tok) + { + int pos = -1; + while (++pos < tok.Count) + { + Token t = tok[pos]; + if (t.Type != TokenType.Keyword) continue; + if (!t.Text.StartsWith("VALUE", StringComparison.OrdinalIgnoreCase)) continue; + CollapseValueList(tok, ref pos); + } + } + + private void CollapseValueList(List tok, ref int pos) + { + List parenIndices = new List(); + + // this while loop will find all closing parens in this value list + while (true) + { + // find the close ')' + while (++pos < tok.Count) + { + if (tok[pos].Type == TokenType.Symbol && tok[pos].Text == ")") + break; + if (pos == tok.Count - 1) + break; + } + parenIndices.Add(pos); + + // now find the next "real" token + while (++pos < tok.Count) + if (tok[pos].IsRealToken) break; + if (pos == tok.Count) break; + + if (tok[pos].Text == ",") continue; + pos--; + break; + } + + // if we only have 1 value then we don't collapse + if (parenIndices.Count < 2) return; + int index = parenIndices[0]; + tok[++index] = new Token(TokenType.Whitespace, " "); + tok[++index] = new Token(TokenType.Comment, "/* , ... */"); + index++; + + // now mark all the other tokens as no output + while (index <= parenIndices[parenIndices.Count - 1]) + tok[index++].Output = false; + } + + private void CollapseInLists(List tok) + { + int pos = -1; + while (++pos < tok.Count) + { + Token t = tok[pos]; + if (t.Type != TokenType.Keyword) continue; + if (t.Text != "IN") continue; + CollapseInList(tok, ref pos); + } + } + + private static Token GetNextRealToken(List tok, ref int pos) + { + while (++pos < tok.Count) + { + if (tok[pos].IsRealToken) return tok[pos]; + } + return null; + } + + private static void CollapseInList(List tok, ref int pos) + { + Token t = GetNextRealToken(tok, ref pos); + // Debug.Assert(t.Text == "("); + if (t == null) + return; + + // if the first token is a keyword then we likely have a + // SELECT .. IN (SELECT ...) + t = GetNextRealToken(tok, ref pos); + if (t == null || t.Type == TokenType.Keyword) return; + + int start = pos; + // first find all the tokens that make up the in list + while (++pos < tok.Count) + { + t = tok[pos]; + if (t.Type == TokenType.CommandComment) return; + if (!t.IsRealToken) continue; + if (t.Text == "(") return; + if (t.Text == ")") break; + } + int stop = pos; + + for (int i = stop; i > start; i--) + tok.RemoveAt(i); + tok.Insert(++start, new Token(TokenType.Whitespace, " ")); + tok.Insert(++start, new Token(TokenType.Comment, "/* , ... */")); + tok.Insert(++start, new Token(TokenType.Whitespace, " ")); + tok.Insert(++start, new Token(TokenType.Symbol, ")")); + } + + private void TokenizeSql(string sql) + { + _pos = 0; + + while (_pos < sql.Length) + { + char c = sql[_pos]; + if (LetterStartsComment(c) && ConsumeComment()) + continue; + if (Char.IsWhiteSpace(c)) + ConsumeWhitespace(); + else if (c == '\'' || c == '\"' || c == '`') + ConsumeQuotedToken(c); + else if (!IsSpecialCharacter(c)) + ConsumeUnquotedToken(); + else + ConsumeSymbol(); + } + } + + private bool LetterStartsComment(char c) + { + return c == '#' || c == '/' || c == '-'; + } + + private bool IsSpecialCharacter(char c) + { + return !Char.IsLetterOrDigit(c) && c != '$' && c != '_' && c != '.'; + } + + private bool ConsumeComment() + { + char c = _fullSql[_pos]; + // make sure the comment starts correctly + if (c == '/' && ((_pos + 1) >= _fullSql.Length || _fullSql[_pos + 1] != '*')) return false; + if (c == '-' && ((_pos + 2) >= _fullSql.Length || _fullSql[_pos + 1] != '-' || _fullSql[_pos + 2] != ' ')) return false; + + string endingPattern = "\n"; + if (c == '/') + endingPattern = "*/"; + + int startingIndex = _pos; + + int index = _fullSql.IndexOf(endingPattern, _pos); + if (index == -1) + index = _fullSql.Length - 1; + else + index += endingPattern.Length; + string comment = _fullSql.Substring(_pos, index - _pos); + if (comment.StartsWith("/*!", StringComparison.Ordinal)) + _tokens.Add(new Token(TokenType.CommandComment, comment)); + _pos = index; + return true; + } + + private void ConsumeSymbol() + { + char c = _fullSql[_pos++]; + _tokens.Add(new Token(TokenType.Symbol, c.ToString())); + } + + private void ConsumeQuotedToken(char c) + { + bool escaped = false; + int start = _pos; + _pos++; + while (_pos < _fullSql.Length) + { + char x = _fullSql[_pos]; + + if (x == c && !escaped) break; + + if (escaped) + escaped = false; + else if (x == '\\') + escaped = true; + _pos++; + } + _pos++; + _tokens.Add(c == '\'' + ? new Token(TokenType.String, "?") + : new Token(TokenType.Identifier, _fullSql.Substring(start, _pos - start))); + } + + private void ConsumeUnquotedToken() + { + int startPos = _pos; + while (_pos < _fullSql.Length && !IsSpecialCharacter(_fullSql[_pos])) + _pos++; + string word = _fullSql.Substring(startPos, _pos - startPos); + double v; + if (double.TryParse( + word, + System.Globalization.NumberStyles.Any, + System.Globalization.CultureInfo.InvariantCulture, + out v)) + _tokens.Add(new Token(TokenType.Number, "?")); + else + { + Token t = new Token(TokenType.Identifier, word); + if (IsKeyword(word)) + { + t.Type = TokenType.Keyword; + t.Text = t.Text.ToUpperInvariant(); + } + _tokens.Add(t); + } + } + + private void ConsumeWhitespace() + { + _tokens.Add(new Token(TokenType.Whitespace, " ")); + while (_pos < _fullSql.Length && Char.IsWhiteSpace(_fullSql[_pos])) + _pos++; + } + + private static bool IsKeyword(string word) + { + return Keywords.Contains(word.ToUpperInvariant()); + } + } + + internal class Token + { + public TokenType Type; + public string Text; + public bool Output; + + public Token(TokenType type, string text) + { + Type = type; + Text = text; + Output = true; + } + + public bool IsRealToken => Type != TokenType.Comment && + Type != TokenType.CommandComment && + Type != TokenType.Whitespace && + Output; + } + + internal enum TokenType + { + Keyword, + String, + Number, + Symbol, + Identifier, + Comment, + CommandComment, + Whitespace + } +} diff --git a/MySQL.Data/src/common/Ssl.cs b/MySQL.Data/src/common/Ssl.cs index 6db9f033a..f201878d9 100644 --- a/MySQL.Data/src/common/Ssl.cs +++ b/MySQL.Data/src/common/Ssl.cs @@ -1,356 +1,356 @@ -// Copyright (c) 2004, 2023, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySql.Data.common; -using MySql.Data.MySqlClient; -using Org.BouncyCastle.Crypto.Parameters; -using Org.BouncyCastle.Crypto; -using Org.BouncyCastle.Pkcs; -using System; -using System.Collections.Generic; -using System.IO; -using System.Net.Security; -using System.Security.Authentication; -using System.Security.Cryptography; -using System.Security.Cryptography.X509Certificates; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using Org.BouncyCastle.OpenSsl; -using Org.BouncyCastle.Utilities.IO.Pem; - -namespace MySql.Data.Common -{ - /// - /// Handles SSL connections for the Classic and X protocols. - /// - internal class Ssl - { - #region Fields - - /// - /// Contains the connection options provided by the user. - /// - private MySqlConnectionStringBuilder _settings; - - /// - /// A flag to establish how certificates are to be treated and validated. - /// - private bool _treatCertificatesAsPemFormat; - - /// - /// Defines the supported TLS protocols. - /// - private static SslProtocols[] tlsProtocols = new SslProtocols[] { SslProtocols.Tls12 }; - private static Dictionary tlsConnectionRef = new Dictionary(); - private static Dictionary tlsRetry = new Dictionary(); - private static Object thisLock = new Object(); - - #endregion - - public Ssl(MySqlConnectionStringBuilder settings) - { - this._settings = settings; - // Set default value to true since PEM files is the standard for MySQL SSL certificates. - _treatCertificatesAsPemFormat = true; - } - - public Ssl(string server, MySqlSslMode sslMode, string certificateFile, MySqlCertificateStoreLocation certificateStoreLocation, - string certificatePassword, string certificateThumbprint, string sslCa, string sslCert, string sslKey, string tlsVersion, uint connectionTimeout) - { - this._settings = new MySqlConnectionStringBuilder() - { - Server = server, - SslMode = sslMode, - CertificateFile = certificateFile, - CertificateStoreLocation = certificateStoreLocation, - CertificatePassword = certificatePassword, - CertificateThumbprint = certificateThumbprint, - SslCa = sslCa, - SslCert = sslCert, - SslKey = sslKey, - TlsVersion = tlsVersion, - ConnectionTimeout = connectionTimeout - }; - // Set default value to true since PEM files is the standard for MySQL SSL certificates. - _treatCertificatesAsPemFormat = true; - } - - /// - /// Retrieves a certificate from PEM file. - /// - private X509Certificate2 GetCertificateFromPEM(string certificatePath, string certificatePassword) - { - var certParser = new Org.BouncyCastle.X509.X509CertificateParser(); - var cert = certParser.ReadCertificate(File.ReadAllBytes(certificatePath)); - return new X509Certificate2(cert.GetEncoded(),certificatePassword); - } - - - /// - /// Retrieves a collection containing the client SSL PFX certificates. - /// - /// Dependent on connection string settings. - /// Either file or store based certificates are used. - private X509CertificateCollection GetPFXClientCertificates() - { - X509CertificateCollection certs = new X509CertificateCollection(); - - // Check for file-based certificate - if (_settings.CertificateFile != null) - { - if (_treatCertificatesAsPemFormat) - { - certs.Add(GetCertificateFromPEM(_settings.CertificateFile, _settings.CertificatePassword)); - return certs; - } - else - { - X509Certificate2 clientCert = new X509Certificate2(_settings.CertificateFile, - _settings.CertificatePassword); - certs.Add(clientCert); - return certs; - } - } - - if (_settings.CertificateStoreLocation == MySqlCertificateStoreLocation.None) - return certs; - - StoreLocation location = - (_settings.CertificateStoreLocation == MySqlCertificateStoreLocation.CurrentUser) ? - StoreLocation.CurrentUser : StoreLocation.LocalMachine; - - try - { - // Check for store-based certificate - X509Store store = new X509Store(StoreName.My, location); - store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly); - - - if (_settings.CertificateThumbprint == null) - { - // Return all certificates from the store. - certs.AddRange(store.Certificates); - - if (certs.Count == 0) - throw new MySqlException("No certificates were found in the certificate store"); - - return certs; - } - else - { - bool validateCert = _settings.SslMode == MySqlSslMode.VerifyCA || _settings.SslMode == MySqlSslMode.VerifyFull; - - // Find certificate with given thumbprint - certs.AddRange(store.Certificates.Find(X509FindType.FindByThumbprint, - _settings.CertificateThumbprint, validateCert)); - - if (certs.Count == 0) - throw new MySqlException(String.Format(Resources.InvalidCertificateThumbprint, _settings.CertificateThumbprint)); - - return certs; - } - } - catch (CryptographicException ex) - { - throw new MySqlException("Certificate couldn't be loaded from the CertificateStoreLocation", ex); - } - } - - /// - /// Initiates the SSL connection. - /// - /// The base stream. - /// The encoding used in the SSL connection. - /// The connection string used to establish the connection. - /// Boolean that indicates if the function will be executed asynchronously. - /// The cancellation token. - /// A instance ready to initiate an SSL connection. - public async Task> StartSSLAsync(Stream baseStream, Encoding encoding, string connectionString, CancellationToken cancellationToken, bool execAsync) - { - // If SslCa connection option was provided, check for the file extension as it can also be set as a PFX file. - if (_settings.SslCa != null) - { - var fileExtension = GetCertificateFileExtension(_settings.SslCa, true); - - if (fileExtension != null) - _treatCertificatesAsPemFormat = fileExtension != "pfx"; - } - - RemoteCertificateValidationCallback sslValidateCallback = new RemoteCertificateValidationCallback(ServerCheckValidation); - SslStream sslStream = new SslStream(baseStream, false, sslValidateCallback, null); - X509CertificateCollection certs = (_treatCertificatesAsPemFormat && - _settings.CertificateStoreLocation == MySqlCertificateStoreLocation.None) - ? new X509CertificateCollection() - : GetPFXClientCertificates(); - - string connectionId = connectionString.GetHashCode().ToString(); - SslProtocols tlsProtocol = SslProtocols.None; - - if (_settings.TlsVersion != null) - { -#if NET452 || NETSTANDARD2_0 - if (_settings.TlsVersion.Equals("Tls13", StringComparison.OrdinalIgnoreCase)) - throw new NotSupportedException(Resources.Tlsv13NotSupported); -#endif - - SslProtocols sslProtocolsToUse = (SslProtocols)Enum.Parse(typeof(SslProtocols), _settings.TlsVersion); - List listProtocols = new List(); - -#if NET48 || NETSTANDARD2_1 || NET5_0_OR_GREATER - if (sslProtocolsToUse.HasFlag((SslProtocols)12288)) - listProtocols.Add((SslProtocols)12288); -#endif - - if (sslProtocolsToUse.HasFlag(SslProtocols.Tls12)) - listProtocols.Add(SslProtocols.Tls12); - - tlsProtocols = listProtocols.ToArray(); - } - - if (tlsConnectionRef.ContainsKey(connectionId)) - { - tlsProtocol = tlsConnectionRef[connectionId]; - } - else - { - if (!tlsRetry.ContainsKey(connectionId)) - { - lock (tlsRetry) - { - tlsRetry[connectionId] = 0; - } - } - for (int i = tlsRetry[connectionId]; i < tlsProtocols.Length; i++) - { - tlsProtocol |= tlsProtocols[i]; - } - } - try - { - tlsProtocol = (tlsProtocol == SslProtocols.None) ? SslProtocols.Tls12 : tlsProtocol; - - if (execAsync) - { - using (cancellationToken.Register(() => throw new AggregateException($"Authentication to host '{_settings.Server}' failed.", new IOException()))) - await sslStream.AuthenticateAsClientAsync(_settings.Server, certs, tlsProtocol, false).ConfigureAwait(false); - } - else - { - using (cancellationToken.Register(() => throw new AggregateException($"Authentication to host '{_settings.Server}' failed.", new IOException()))) - sslStream.AuthenticateAsClientAsync(_settings.Server, certs, tlsProtocol, false).GetAwaiter().GetResult(); - } - - lock (tlsConnectionRef) - { - tlsConnectionRef[connectionId] = tlsProtocol; - } - tlsRetry.Remove(connectionId); - } - catch (AggregateException ex) - { - if (ex.GetBaseException() is IOException) - { - tlsConnectionRef.Remove(connectionId); - if (tlsRetry.ContainsKey(connectionId)) - { - if (tlsRetry[connectionId] > tlsProtocols.Length) - throw new MySqlException(Resources.SslConnectionError, ex); - tlsRetry[connectionId] += 1; - } - } - throw ex.GetBaseException(); - } - - baseStream = sslStream; - MySqlStream stream = new MySqlStream(sslStream, encoding, false); - stream.SequenceByte = 2; - - return new Tuple(stream, baseStream); - } - - /// - /// Verifies the SSL certificates used for authentication. - /// - /// An object that contains state information for this validation. - /// The MySQL server certificate used to authenticate the remote party. - /// The chain of certificate authorities associated with the remote certificate. - /// One or more errors associated with the remote certificate. - /// true if no errors were found based on the selected SSL mode; false, otherwise. - private bool ServerCheckValidation(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) - { - if (sslPolicyErrors == SslPolicyErrors.None) - return true; - - if (_settings.SslMode == MySqlSslMode.Required || - _settings.SslMode == MySqlSslMode.Preferred) - { - // Tolerate all certificate errors. - return true; - } - - // Validate PEM certificates using Bouncy Castle. - if (_treatCertificatesAsPemFormat) - { - SslPemCertificateValidator.ValidateCertificate(chain, _settings); - return true; - } - // Validate PFX certificate errors. - else if (_settings.SslMode == MySqlSslMode.VerifyCA && - sslPolicyErrors == SslPolicyErrors.RemoteCertificateNameMismatch) - { - // Tolerate name mismatch in certificate, if full validation is not requested. - return true; - } - - return false; - } - - /// - /// Gets the extension of the specified file. - /// - /// The path of the file. - /// Flag to indicate if the result should be converted to lower case. - /// The . character is ommited from the result. - /// - private string GetCertificateFileExtension(string filePath, bool toLowerCase) - { - if (filePath == null || !File.Exists(filePath)) - return null; - - var extension = Path.GetExtension(filePath); - extension = string.IsNullOrEmpty(extension) - ? null - : extension.Substring(extension.IndexOf(".") + 1); - - return toLowerCase - ? extension.ToLowerInvariant() - : extension; - } - } -} +// Copyright © 2004, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySql.Data.common; +using MySql.Data.MySqlClient; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Pkcs; +using System; +using System.Collections.Generic; +using System.IO; +using System.Net.Security; +using System.Security.Authentication; +using System.Security.Cryptography; +using System.Security.Cryptography.X509Certificates; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Org.BouncyCastle.OpenSsl; +using Org.BouncyCastle.Utilities.IO.Pem; + +namespace MySql.Data.Common +{ + /// + /// Handles SSL connections for the Classic and X protocols. + /// + internal class Ssl + { + #region Fields + + /// + /// Contains the connection options provided by the user. + /// + private MySqlConnectionStringBuilder _settings; + + /// + /// A flag to establish how certificates are to be treated and validated. + /// + private bool _treatCertificatesAsPemFormat; + + /// + /// Defines the supported TLS protocols. + /// + private static SslProtocols[] tlsProtocols = new SslProtocols[] { SslProtocols.Tls12 }; + private static Dictionary tlsConnectionRef = new Dictionary(); + private static Dictionary tlsRetry = new Dictionary(); + private static Object thisLock = new Object(); + + #endregion + + public Ssl(MySqlConnectionStringBuilder settings) + { + this._settings = settings; + // Set default value to true since PEM files is the standard for MySQL SSL certificates. + _treatCertificatesAsPemFormat = true; + } + + public Ssl(string server, MySqlSslMode sslMode, string certificateFile, MySqlCertificateStoreLocation certificateStoreLocation, + string certificatePassword, string certificateThumbprint, string sslCa, string sslCert, string sslKey, string tlsVersion, uint connectionTimeout) + { + this._settings = new MySqlConnectionStringBuilder() + { + Server = server, + SslMode = sslMode, + CertificateFile = certificateFile, + CertificateStoreLocation = certificateStoreLocation, + CertificatePassword = certificatePassword, + CertificateThumbprint = certificateThumbprint, + SslCa = sslCa, + SslCert = sslCert, + SslKey = sslKey, + TlsVersion = tlsVersion, + ConnectionTimeout = connectionTimeout + }; + // Set default value to true since PEM files is the standard for MySQL SSL certificates. + _treatCertificatesAsPemFormat = true; + } + + /// + /// Retrieves a certificate from PEM file. + /// + private X509Certificate2 GetCertificateFromPEM(string certificatePath, string certificatePassword) + { + var certParser = new Org.BouncyCastle.X509.X509CertificateParser(); + var cert = certParser.ReadCertificate(File.ReadAllBytes(certificatePath)); + return new X509Certificate2(cert.GetEncoded(),certificatePassword); + } + + + /// + /// Retrieves a collection containing the client SSL PFX certificates. + /// + /// Dependent on connection string settings. + /// Either file or store based certificates are used. + private X509CertificateCollection GetPFXClientCertificates() + { + X509CertificateCollection certs = new X509CertificateCollection(); + + // Check for file-based certificate + if (_settings.CertificateFile != null) + { + if (_treatCertificatesAsPemFormat) + { + certs.Add(GetCertificateFromPEM(_settings.CertificateFile, _settings.CertificatePassword)); + return certs; + } + else + { + X509Certificate2 clientCert = new X509Certificate2(_settings.CertificateFile, + _settings.CertificatePassword); + certs.Add(clientCert); + return certs; + } + } + + if (_settings.CertificateStoreLocation == MySqlCertificateStoreLocation.None) + return certs; + + StoreLocation location = + (_settings.CertificateStoreLocation == MySqlCertificateStoreLocation.CurrentUser) ? + StoreLocation.CurrentUser : StoreLocation.LocalMachine; + + try + { + // Check for store-based certificate + X509Store store = new X509Store(StoreName.My, location); + store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly); + + + if (_settings.CertificateThumbprint == null) + { + // Return all certificates from the store. + certs.AddRange(store.Certificates); + + if (certs.Count == 0) + throw new MySqlException("No certificates were found in the certificate store"); + + return certs; + } + else + { + bool validateCert = _settings.SslMode == MySqlSslMode.VerifyCA || _settings.SslMode == MySqlSslMode.VerifyFull; + + // Find certificate with given thumbprint + certs.AddRange(store.Certificates.Find(X509FindType.FindByThumbprint, + _settings.CertificateThumbprint, validateCert)); + + if (certs.Count == 0) + throw new MySqlException(String.Format(Resources.InvalidCertificateThumbprint, _settings.CertificateThumbprint)); + + return certs; + } + } + catch (CryptographicException ex) + { + throw new MySqlException("Certificate couldn't be loaded from the CertificateStoreLocation", ex); + } + } + + /// + /// Initiates the SSL connection. + /// + /// The base stream. + /// The encoding used in the SSL connection. + /// The connection string used to establish the connection. + /// Boolean that indicates if the function will be executed asynchronously. + /// The cancellation token. + /// A instance ready to initiate an SSL connection. + public async Task> StartSSLAsync(Stream baseStream, Encoding encoding, string connectionString, CancellationToken cancellationToken, bool execAsync) + { + // If SslCa connection option was provided, check for the file extension as it can also be set as a PFX file. + if (_settings.SslCa != null) + { + var fileExtension = GetCertificateFileExtension(_settings.SslCa, true); + + if (fileExtension != null) + _treatCertificatesAsPemFormat = fileExtension != "pfx"; + } + + RemoteCertificateValidationCallback sslValidateCallback = new RemoteCertificateValidationCallback(ServerCheckValidation); + SslStream sslStream = new SslStream(baseStream, false, sslValidateCallback, null); + X509CertificateCollection certs = (_treatCertificatesAsPemFormat && + _settings.CertificateStoreLocation == MySqlCertificateStoreLocation.None) + ? new X509CertificateCollection() + : GetPFXClientCertificates(); + + string connectionId = connectionString.GetHashCode().ToString(); + SslProtocols tlsProtocol = SslProtocols.None; + + if (_settings.TlsVersion != null) + { +#if NET452 || NETSTANDARD2_0 + if (_settings.TlsVersion.Equals("Tls13", StringComparison.OrdinalIgnoreCase)) + throw new NotSupportedException(Resources.Tlsv13NotSupported); +#endif + + SslProtocols sslProtocolsToUse = (SslProtocols)Enum.Parse(typeof(SslProtocols), _settings.TlsVersion); + List listProtocols = new List(); + +#if NET48 || NETSTANDARD2_1 || NET5_0_OR_GREATER + if (sslProtocolsToUse.HasFlag((SslProtocols)12288)) + listProtocols.Add((SslProtocols)12288); +#endif + + if (sslProtocolsToUse.HasFlag(SslProtocols.Tls12)) + listProtocols.Add(SslProtocols.Tls12); + + tlsProtocols = listProtocols.ToArray(); + } + + if (tlsConnectionRef.ContainsKey(connectionId)) + { + tlsProtocol = tlsConnectionRef[connectionId]; + } + else + { + if (!tlsRetry.ContainsKey(connectionId)) + { + lock (tlsRetry) + { + tlsRetry[connectionId] = 0; + } + } + for (int i = tlsRetry[connectionId]; i < tlsProtocols.Length; i++) + { + tlsProtocol |= tlsProtocols[i]; + } + } + try + { + tlsProtocol = (tlsProtocol == SslProtocols.None) ? SslProtocols.Tls12 : tlsProtocol; + + if (execAsync) + { + using (cancellationToken.Register(() => throw new AggregateException($"Authentication to host '{_settings.Server}' failed.", new IOException()))) + await sslStream.AuthenticateAsClientAsync(_settings.Server, certs, tlsProtocol, false).ConfigureAwait(false); + } + else + { + using (cancellationToken.Register(() => throw new AggregateException($"Authentication to host '{_settings.Server}' failed.", new IOException()))) + sslStream.AuthenticateAsClientAsync(_settings.Server, certs, tlsProtocol, false).GetAwaiter().GetResult(); + } + + lock (tlsConnectionRef) + { + tlsConnectionRef[connectionId] = tlsProtocol; + } + tlsRetry.Remove(connectionId); + } + catch (AggregateException ex) + { + if (ex.GetBaseException() is IOException) + { + tlsConnectionRef.Remove(connectionId); + if (tlsRetry.ContainsKey(connectionId)) + { + if (tlsRetry[connectionId] > tlsProtocols.Length) + throw new MySqlException(Resources.SslConnectionError, ex); + tlsRetry[connectionId] += 1; + } + } + throw ex.GetBaseException(); + } + + baseStream = sslStream; + MySqlStream stream = new MySqlStream(sslStream, encoding, false); + stream.SequenceByte = 2; + + return new Tuple(stream, baseStream); + } + + /// + /// Verifies the SSL certificates used for authentication. + /// + /// An object that contains state information for this validation. + /// The MySQL server certificate used to authenticate the remote party. + /// The chain of certificate authorities associated with the remote certificate. + /// One or more errors associated with the remote certificate. + /// true if no errors were found based on the selected SSL mode; false, otherwise. + private bool ServerCheckValidation(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) + { + if (sslPolicyErrors == SslPolicyErrors.None) + return true; + + if (_settings.SslMode == MySqlSslMode.Required || + _settings.SslMode == MySqlSslMode.Preferred) + { + // Tolerate all certificate errors. + return true; + } + + // Validate PEM certificates using Bouncy Castle. + if (_treatCertificatesAsPemFormat) + { + SslPemCertificateValidator.ValidateCertificate(chain, _settings); + return true; + } + // Validate PFX certificate errors. + else if (_settings.SslMode == MySqlSslMode.VerifyCA && + sslPolicyErrors == SslPolicyErrors.RemoteCertificateNameMismatch) + { + // Tolerate name mismatch in certificate, if full validation is not requested. + return true; + } + + return false; + } + + /// + /// Gets the extension of the specified file. + /// + /// The path of the file. + /// Flag to indicate if the result should be converted to lower case. + /// The . character is ommited from the result. + /// + private string GetCertificateFileExtension(string filePath, bool toLowerCase) + { + if (filePath == null || !File.Exists(filePath)) + return null; + + var extension = Path.GetExtension(filePath); + extension = string.IsNullOrEmpty(extension) + ? null + : extension.Substring(extension.IndexOf(".") + 1); + + return toLowerCase + ? extension.ToLowerInvariant() + : extension; + } + } +} diff --git a/MySQL.Data/src/common/SslPemCertificateValidator.cs b/MySQL.Data/src/common/SslPemCertificateValidator.cs index c92005be8..d29b26689 100644 --- a/MySQL.Data/src/common/SslPemCertificateValidator.cs +++ b/MySQL.Data/src/common/SslPemCertificateValidator.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2019, 2022, Oracle and/or its affiliates. +// Copyright © 2019, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/common/StreamCreator.cs b/MySQL.Data/src/common/StreamCreator.cs index f1d9496cf..1305ec867 100644 --- a/MySQL.Data/src/common/StreamCreator.cs +++ b/MySQL.Data/src/common/StreamCreator.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2004, 2022, Oracle and/or its affiliates. +// Copyright © 2004, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/common/StringUtility.cs b/MySQL.Data/src/common/StringUtility.cs index f8b8ad350..8e1359378 100644 --- a/MySQL.Data/src/common/StringUtility.cs +++ b/MySQL.Data/src/common/StringUtility.cs @@ -1,45 +1,45 @@ -// Copyright (c) 2014, 2021, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - - -namespace MySql.Data.Common -{ - internal class StringUtility - { - public static string ToUpperInvariant(string s) - { - return s.ToUpperInvariant(); - } - - public static string ToLowerInvariant(string s) - { - return s.ToLowerInvariant(); - } - - } -} +// Copyright © 2014, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + +namespace MySql.Data.Common +{ + internal class StringUtility + { + public static string ToUpperInvariant(string s) + { + return s.ToUpperInvariant(); + } + + public static string ToLowerInvariant(string s) + { + return s.ToLowerInvariant(); + } + + } +} diff --git a/MySQL.Data/src/common/UnixEndPoint.cs b/MySQL.Data/src/common/UnixEndPoint.cs index 178986ad8..b05c2baa8 100644 --- a/MySQL.Data/src/common/UnixEndPoint.cs +++ b/MySQL.Data/src/common/UnixEndPoint.cs @@ -1,16 +1,16 @@ -// Copyright © 2017, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2017, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/common/Version.cs b/MySQL.Data/src/common/Version.cs index 1386be26c..b524e5d2a 100644 --- a/MySQL.Data/src/common/Version.cs +++ b/MySQL.Data/src/common/Version.cs @@ -1,101 +1,101 @@ -// Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using System; -using MySql.Data.MySqlClient; - -namespace MySql.Data.Common -{ - /// - /// Summary description for Version. - /// - internal struct DBVersion - { - private readonly string _srcString; - - public DBVersion(string s, int major, int minor, int build) - { - Major = major; - Minor = minor; - Build = build; - _srcString = s; - IsEnterprise = s.ToLowerInvariant().Contains("-enterprise-"); - } - - public int Major { get; } - - public int Minor { get; } - - public int Build { get; } - - public bool IsEnterprise - { - get; private set; - } - - public static DBVersion Parse(string versionString) - { - int start = 0; - int index = versionString.IndexOf('.', start); - if (index == -1) - throw new MySqlException(Resources.BadVersionFormat); - string val = versionString.Substring(start, index - start).Trim(); - int major = Convert.ToInt32(val, System.Globalization.NumberFormatInfo.InvariantInfo); - - start = index + 1; - index = versionString.IndexOf('.', start); - if (index == -1) - throw new MySqlException(Resources.BadVersionFormat); - val = versionString.Substring(start, index - start).Trim(); - int minor = Convert.ToInt32(val, System.Globalization.NumberFormatInfo.InvariantInfo); - - start = index + 1; - int i = start; - while (i < versionString.Length && Char.IsDigit(versionString, i)) - i++; - val = versionString.Substring(start, i - start).Trim(); - int build = Convert.ToInt32(val, System.Globalization.NumberFormatInfo.InvariantInfo); - - return new DBVersion(versionString, major, minor, build); - } - - public bool isAtLeast(int majorNum, int minorNum, int buildNum) - { - if (Major > majorNum) return true; - if (Major == majorNum && Minor > minorNum) return true; - if (Major == majorNum && Minor == minorNum && Build >= buildNum) return true; - return false; - } - - public override string ToString() - { - return _srcString; - } - - } -} +// Copyright © 2004, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using System; +using MySql.Data.MySqlClient; + +namespace MySql.Data.Common +{ + /// + /// Summary description for Version. + /// + internal struct DBVersion + { + private readonly string _srcString; + + public DBVersion(string s, int major, int minor, int build) + { + Major = major; + Minor = minor; + Build = build; + _srcString = s; + IsEnterprise = s.ToLowerInvariant().Contains("-enterprise-"); + } + + public int Major { get; } + + public int Minor { get; } + + public int Build { get; } + + public bool IsEnterprise + { + get; private set; + } + + public static DBVersion Parse(string versionString) + { + int start = 0; + int index = versionString.IndexOf('.', start); + if (index == -1) + throw new MySqlException(Resources.BadVersionFormat); + string val = versionString.Substring(start, index - start).Trim(); + int major = Convert.ToInt32(val, System.Globalization.NumberFormatInfo.InvariantInfo); + + start = index + 1; + index = versionString.IndexOf('.', start); + if (index == -1) + throw new MySqlException(Resources.BadVersionFormat); + val = versionString.Substring(start, index - start).Trim(); + int minor = Convert.ToInt32(val, System.Globalization.NumberFormatInfo.InvariantInfo); + + start = index + 1; + int i = start; + while (i < versionString.Length && Char.IsDigit(versionString, i)) + i++; + val = versionString.Substring(start, i - start).Trim(); + int build = Convert.ToInt32(val, System.Globalization.NumberFormatInfo.InvariantInfo); + + return new DBVersion(versionString, major, minor, build); + } + + public bool isAtLeast(int majorNum, int minorNum, int buildNum) + { + if (Major > majorNum) return true; + if (Major == majorNum && Minor > minorNum) return true; + if (Major == majorNum && Minor == minorNum && Build >= buildNum) return true; + return false; + } + + public override string ToString() + { + return _srcString; + } + + } +} diff --git a/MySQL.Data/src/common/netstandard2_0/NamedPipeStream.cs b/MySQL.Data/src/common/netstandard2_0/NamedPipeStream.cs index 46b3507c7..47cf4d06c 100644 --- a/MySQL.Data/src/common/netstandard2_0/NamedPipeStream.cs +++ b/MySQL.Data/src/common/netstandard2_0/NamedPipeStream.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2009, 2022, Oracle and/or its affiliates. +// Copyright © 2009, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/src/common/netstandard2_0/SharedMemoryStream.cs b/MySQL.Data/src/common/netstandard2_0/SharedMemoryStream.cs index 6cf1f5430..f9b092d53 100644 --- a/MySQL.Data/src/common/netstandard2_0/SharedMemoryStream.cs +++ b/MySQL.Data/src/common/netstandard2_0/SharedMemoryStream.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2014, 2021, Oracle and/or its affiliates. +// Copyright © 2014, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/tests/MySql.Data.Tests/AttributeTests.cs b/MySQL.Data/tests/MySql.Data.Tests/AttributeTests.cs index 4ca6a3cc7..269a21b5f 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/AttributeTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/AttributeTests.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2022, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/tests/MySql.Data.Tests/AuthTests.cs b/MySQL.Data/tests/MySql.Data.Tests/AuthTests.cs index 82bff80be..8be4eeca9 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/AuthTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/AuthTests.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2016, 2023, Oracle and/or its affiliates. +// Copyright © 2016, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -2241,4 +2241,4 @@ public void Sha256AndNativeWithCertificates() } } } -} \ No newline at end of file +} diff --git a/MySQL.Data/tests/MySql.Data.Tests/BlobTests.cs b/MySQL.Data/tests/MySql.Data.Tests/BlobTests.cs index edc0f4cd0..a49c7bb41 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/BlobTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/BlobTests.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2013, 2020 Oracle and/or its affiliates. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/tests/MySql.Data.Tests/BlobTestsCompressed.cs b/MySQL.Data/tests/MySql.Data.Tests/BlobTestsCompressed.cs index 4e9a8e7d5..2dc442e06 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/BlobTestsCompressed.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/BlobTestsCompressed.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -38,4 +38,4 @@ internal override void AdjustConnectionSettings(MySqlConnectionStringBuilder set settings.UseCompression = true; } } -} \ No newline at end of file +} diff --git a/MySQL.Data/tests/MySql.Data.Tests/CharSetTests.cs b/MySQL.Data/tests/MySql.Data.Tests/CharSetTests.cs index ecf9715e9..2e461ab60 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/CharSetTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/CharSetTests.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2013, 2022, Oracle and/or its affiliates. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -628,4 +628,4 @@ public void CharacterVariablesByAssignedServerDefault() #endregion WL14389 } -} \ No newline at end of file +} diff --git a/MySQL.Data/tests/MySql.Data.Tests/CharSetUTF8Tests.cs b/MySQL.Data/tests/MySql.Data.Tests/CharSetUTF8Tests.cs index 695a469b6..53878b95c 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/CharSetUTF8Tests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/CharSetUTF8Tests.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2013, 2022, Oracle and/or its affiliates. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/tests/MySql.Data.Tests/ClientSideFailoverTests.cs b/MySQL.Data/tests/MySql.Data.Tests/ClientSideFailoverTests.cs index b4b251fd5..ca9ec8aad 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/ClientSideFailoverTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/ClientSideFailoverTests.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2019, 2022, Oracle and/or its affiliates. +// Copyright © 2019, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -197,4 +197,4 @@ public void FailWhenMySqlExceptionRaised() Assert.Throws(() => conn.Open()); } } -} \ No newline at end of file +} diff --git a/MySQL.Data/tests/MySql.Data.Tests/CmdTests.cs b/MySQL.Data/tests/MySql.Data.Tests/CmdTests.cs index 3522add9d..8cc409197 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/CmdTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/CmdTests.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2013, 2023, Oracle and/or its affiliates. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -978,4 +978,4 @@ public void LastInserteIdRedux() } } -} \ No newline at end of file +} diff --git a/MySQL.Data/tests/MySql.Data.Tests/CmdTestsCompressed.cs b/MySQL.Data/tests/MySql.Data.Tests/CmdTestsCompressed.cs index 148e3db6f..e259383f9 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/CmdTestsCompressed.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/CmdTestsCompressed.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -43,4 +43,4 @@ public override void InsertingPreparedNulls() base.InsertingPreparedNulls(); } } -} \ No newline at end of file +} diff --git a/MySQL.Data/tests/MySql.Data.Tests/ConnectionStringBuilderTests.cs b/MySQL.Data/tests/MySql.Data.Tests/ConnectionStringBuilderTests.cs index baee233cd..e6e01b814 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/ConnectionStringBuilderTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/ConnectionStringBuilderTests.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2013, 2022, Oracle and/or its affiliates. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -464,4 +464,4 @@ public void KerberosAuthModeTest() Assert.Throws(() => conn = new MySqlConnection(connString)); } } -} \ No newline at end of file +} diff --git a/MySQL.Data/tests/MySql.Data.Tests/ConnectionTests.cs b/MySQL.Data/tests/MySql.Data.Tests/ConnectionTests.cs index 5ceaede9d..f4a4fdf8c 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/ConnectionTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/ConnectionTests.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2013, 2023, Oracle and/or its affiliates. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/tests/MySql.Data.Tests/DataTypeTests.cs b/MySQL.Data/tests/MySql.Data.Tests/DataTypeTests.cs index b5f2f8b76..428716362 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/DataTypeTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/DataTypeTests.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2013, 2022, Oracle and/or its affiliates. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -1693,4 +1693,4 @@ public void OldGetStringBehaviorOn() } } -} \ No newline at end of file +} diff --git a/MySQL.Data/tests/MySql.Data.Tests/DateTimeTests.cs b/MySQL.Data/tests/MySql.Data.Tests/DateTimeTests.cs index 97bb7dffb..398f4c58a 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/DateTimeTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/DateTimeTests.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2013, 2022, Oracle and/or its affiliates. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/tests/MySql.Data.Tests/DnsSrvTests.cs b/MySQL.Data/tests/MySql.Data.Tests/DnsSrvTests.cs index 9f2ebfbc9..b51b16dd9 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/DnsSrvTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/DnsSrvTests.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2019, 2022, Oracle and/or its affiliates. +// Copyright © 2019, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -128,4 +128,4 @@ public void DnsSrvRecordsTest() Assert.True(sortedRecords.Select(r => r.Target).SequenceEqual(expectedOrder.Select(r => r.Target))); } } -} \ No newline at end of file +} diff --git a/MySQL.Data/tests/MySql.Data.Tests/EventTests.cs b/MySQL.Data/tests/MySql.Data.Tests/EventTests.cs index 9d31609f6..836c62f65 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/EventTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/EventTests.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -73,4 +73,4 @@ private void StateChangeHandler(object sender, StateChangeEventArgs e) { } } -} \ No newline at end of file +} diff --git a/MySQL.Data/tests/MySql.Data.Tests/ExceptionTests.cs b/MySQL.Data/tests/MySql.Data.Tests/ExceptionTests.cs index c138474f8..f5d43f9da 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/ExceptionTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/ExceptionTests.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2013, 2022, Oracle and/or its affiliates. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/BlobTestsPipe.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/BlobTestsPipe.cs index 4b406bdd7..645764316 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/BlobTestsPipe.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/BlobTestsPipe.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/BlobTestsPipeCompressed.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/BlobTestsPipeCompressed.cs index 557f72f4c..880541c8f 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/BlobTestsPipeCompressed.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/BlobTestsPipeCompressed.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -46,4 +46,4 @@ internal override void AdjustConnectionSettings(MySqlConnectionStringBuilder set settings.SslMode = MySqlSslMode.None; } } -} \ No newline at end of file +} diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/BlobTestsSharedMem.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/BlobTestsSharedMem.cs index 5da5fb5af..163a24b5b 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/BlobTestsSharedMem.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/BlobTestsSharedMem.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -42,4 +42,4 @@ internal override void AdjustConnectionSettings(MySqlConnectionStringBuilder set settings.SslMode = MySqlSslMode.None; } } -} \ No newline at end of file +} diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/BlobTestsSharedMemCompressed.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/BlobTestsSharedMemCompressed.cs index 19f1eccc6..36c8932ad 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/BlobTestsSharedMemCompressed.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/BlobTestsSharedMemCompressed.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -47,4 +47,4 @@ internal override void AdjustConnectionSettings(MySqlConnectionStringBuilder set } } -} \ No newline at end of file +} diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/CmdTestsPipe.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/CmdTestsPipe.cs index 298499417..8a98b187b 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/CmdTestsPipe.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/CmdTestsPipe.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -42,4 +42,4 @@ internal override void AdjustConnectionSettings(MySqlConnectionStringBuilder set settings.SslMode = MySqlSslMode.None; } } -} \ No newline at end of file +} diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/CmdTestsPipeCompressed.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/CmdTestsPipeCompressed.cs index ca170eec2..68ec9c1b1 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/CmdTestsPipeCompressed.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/CmdTestsPipeCompressed.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -43,4 +43,4 @@ internal override void AdjustConnectionSettings(MySqlConnectionStringBuilder set settings.UseCompression = true; } } -} \ No newline at end of file +} diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/CmdTestsSharedMem.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/CmdTestsSharedMem.cs index a7a28c3c6..75533132f 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/CmdTestsSharedMem.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/CmdTestsSharedMem.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -40,4 +40,4 @@ internal override void AdjustConnectionSettings(MySqlConnectionStringBuilder set settings.SslMode = MySqlSslMode.None; } } -} \ No newline at end of file +} diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/CmdTestsSharedmemCompressed.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/CmdTestsSharedmemCompressed.cs index 55d721794..a5a61238e 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/CmdTestsSharedmemCompressed.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/CmdTestsSharedmemCompressed.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -43,4 +43,4 @@ internal override void AdjustConnectionSettings(MySqlConnectionStringBuilder set settings.UseCompression = true; } } -} \ No newline at end of file +} diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/CultureTests.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/CultureTests.cs index ccd55ae5b..ccb2a1f4b 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/CultureTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/CultureTests.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/DataTypeTests.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/DataTypeTests.cs index ef4c8a20a..4ae5238ef 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/DataTypeTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/DataTypeTests.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/DateTimeTests.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/DateTimeTests.cs index 20b8fc326..ba43bb143 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/DateTimeTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/DateTimeTests.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -196,4 +196,4 @@ public void DateTimeInDataTable() } } } -} \ No newline at end of file +} diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/GetSchemaTests.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/GetSchemaTests.cs index 1f77a4d05..f0abd1339 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/GetSchemaTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/GetSchemaTests.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2013, 2022, Oracle and/or its affiliates. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -800,4 +800,4 @@ public void GetIndexColumnsWithFullTextIndex() StringAssert.AreEqualIgnoringCase(indexName, row[0]["INDEX_NAME"].ToString()); } } -} \ No newline at end of file +} diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/InstallerTests.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/InstallerTests.cs index 6bd16bd4f..d028719b0 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/InstallerTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/InstallerTests.cs @@ -1,16 +1,16 @@ -// Copyright © 2013, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MediumTrust/MediumTrustDomain.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MediumTrust/MediumTrustDomain.cs index 2ad5addf6..614b000b0 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MediumTrust/MediumTrustDomain.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MediumTrust/MediumTrustDomain.cs @@ -1,16 +1,16 @@ -// Copyright © 2013, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MediumTrust/MediumTrustFixtureAttribute.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MediumTrust/MediumTrustFixtureAttribute.cs index c68e25c60..8a320dba1 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MediumTrust/MediumTrustFixtureAttribute.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MediumTrust/MediumTrustFixtureAttribute.cs @@ -1,16 +1,16 @@ -// Copyright © 2013, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MediumTrust/MediumTrustTestClassCommand.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MediumTrust/MediumTrustTestClassCommand.cs index 949e95475..3275ea3b1 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MediumTrust/MediumTrustTestClassCommand.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MediumTrust/MediumTrustTestClassCommand.cs @@ -1,16 +1,16 @@ -// Copyright © 2013, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MediumTrust/MediumTrustTestCommand.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MediumTrust/MediumTrustTestCommand.cs index 708ae40c2..2d8064ae1 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MediumTrust/MediumTrustTestCommand.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MediumTrust/MediumTrustTestCommand.cs @@ -1,16 +1,16 @@ -// Copyright © 2013, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MediumTrust/MySql.MediumTrustsTests.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MediumTrust/MySql.MediumTrustsTests.cs index 235f4eb09..7c40953bb 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MediumTrust/MySql.MediumTrustsTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MediumTrust/MySql.MediumTrustsTests.cs @@ -1,16 +1,16 @@ -// Copyright © 2013, 2014, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MediumTrust/MySqlClientPermissionTests.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MediumTrust/MySqlClientPermissionTests.cs index 954e3e6ca..6fed750b1 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MediumTrust/MySqlClientPermissionTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MediumTrust/MySqlClientPermissionTests.cs @@ -1,16 +1,16 @@ -// Copyright © 2004, 2011, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2004, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MySQLHelperTests.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MySQLHelperTests.cs index f75706edd..a2bdd79c3 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MySQLHelperTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MySQLHelperTests.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MySqlCommandBuilderTests.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MySqlCommandBuilderTests.cs index c4d9127f1..309184a2e 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MySqlCommandBuilderTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MySqlCommandBuilderTests.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2013, 2022, Oracle and/or its affiliates. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MySqlDataAdapterTests.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MySqlDataAdapterTests.cs index d683e71de..2c8651fd9 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MySqlDataAdapterTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MySqlDataAdapterTests.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2013, 2022, Oracle and/or its affiliates. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MySqlDataReaderTests.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MySqlDataReaderTests.cs index da290e298..12e0315d1 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MySqlDataReaderTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MySqlDataReaderTests.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/NETCore20Tests.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/NETCore20Tests.cs index de0ab53d1..86aced015 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/NETCore20Tests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/NETCore20Tests.cs @@ -1,23 +1,29 @@ -// Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. +// Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved. // -// MySQL Connector/NET is licensed under the terms of the GPLv2 -// , like most -// MySQL Connectors. There are special exceptions to the terms and -// conditions of the GPLv2 as it is applied to this software, see the -// FLOSS License Exception -// . +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. // -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published -// by the Free Software Foundation; version 2 of the License. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -// for more details. +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. // -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA using System; diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/OutputParametersBatchPrepared.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/OutputParametersBatchPrepared.cs index e0d9b5fa4..4e2a243c6 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/OutputParametersBatchPrepared.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/OutputParametersBatchPrepared.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/OutputParametersNoBatch.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/OutputParametersNoBatch.cs index eaa605bd2..16733d657 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/OutputParametersNoBatch.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/OutputParametersNoBatch.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -35,4 +35,4 @@ internal override void AdjustConnectionSettings(MySqlConnectionStringBuilder set settings.AllowBatch = false; } } -} \ No newline at end of file +} diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/OutputParametersNoBatchPrepared.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/OutputParametersNoBatchPrepared.cs index a8dd1bbcd..c32f42b8f 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/OutputParametersNoBatchPrepared.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/OutputParametersNoBatchPrepared.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -41,4 +41,4 @@ internal override void AdjustConnectionSettings(MySqlConnectionStringBuilder set settings.AllowBatch = false; } } -} \ No newline at end of file +} diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/PSPipe.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/PSPipe.cs index 113e51b6c..556ed12d6 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/PSPipe.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/PSPipe.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/PSPipeCompressed.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/PSPipeCompressed.cs index 12b17730b..8554aa4da 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/PSPipeCompressed.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/PSPipeCompressed.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/PSSharedMemory.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/PSSharedMemory.cs index 17b93e689..93c1b3ee5 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/PSSharedMemory.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/PSSharedMemory.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/PSSharedMemoryCompressed.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/PSSharedMemoryCompressed.cs index e93683ccc..ea2b05efb 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/PSSharedMemoryCompressed.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/PSSharedMemoryCompressed.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/PartialTrustSandbox.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/PartialTrustSandbox.cs index e1e6b4e83..c590ff8cf 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/PartialTrustSandbox.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/PartialTrustSandbox.cs @@ -1,16 +1,16 @@ -// Copyright © 2013, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/PerfMonTests.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/PerfMonTests.cs index 14c8f6869..0e69f2da6 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/PerfMonTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/PerfMonTests.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/ProcedureParameterTests.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/ProcedureParameterTests.cs index 62d90c882..0b4894594 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/ProcedureParameterTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/ProcedureParameterTests.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2013, 2022, Oracle and/or its affiliates. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/ReplicationTests.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/ReplicationTests.cs index 37445ed5c..c25ee2aca 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/ReplicationTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/ReplicationTests.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/StressTestsPipe.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/StressTestsPipe.cs index f5874e185..ce7589b61 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/StressTestsPipe.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/StressTestsPipe.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/StressTestsPipeCompressed.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/StressTestsPipeCompressed.cs index dd0d9a548..0fcbf6fab 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/StressTestsPipeCompressed.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/StressTestsPipeCompressed.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/StressTestsSharedMemory.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/StressTestsSharedMemory.cs index 7dcb6e9a4..794e92c25 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/StressTestsSharedMemory.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/StressTestsSharedMemory.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/StressTestsSharedMemoryCompressed.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/StressTestsSharedMemoryCompressed.cs index 15379a454..8872d295d 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/StressTestsSharedMemoryCompressed.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/StressTestsSharedMemoryCompressed.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/ThreadingTests.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/ThreadingTests.cs index b3c80ad4c..2c297992b 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/ThreadingTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/ThreadingTests.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/TimeoutAndCancel.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/TimeoutAndCancel.cs index b4fbe2462..48a894fc5 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/TimeoutAndCancel.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/TimeoutAndCancel.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2013, 2022, Oracle and/or its affiliates. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/TimeoutAndCancelCompressed.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/TimeoutAndCancelCompressed.cs index d4a54048c..621effb45 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/TimeoutAndCancelCompressed.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/TimeoutAndCancelCompressed.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/TimeoutAndCancelPipe.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/TimeoutAndCancelPipe.cs index 79c4200c4..db56d7dd4 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/TimeoutAndCancelPipe.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/TimeoutAndCancelPipe.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/TimeoutAndCancelSharedMemory.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/TimeoutAndCancelSharedMemory.cs index 21821e844..811c4d7a2 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/TimeoutAndCancelSharedMemory.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/TimeoutAndCancelSharedMemory.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/TypeTests.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/TypeTests.cs index 00a2ded7f..b2271bed1 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/TypeTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/TypeTests.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2013, 2022, Oracle and/or its affiliates. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -65,4 +65,4 @@ public void TestSerializationMySqlDataTime() } #endif } -} \ No newline at end of file +} diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/UsageAdvisorTests.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/UsageAdvisorTests.cs index c4146d171..06cf54f96 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/UsageAdvisorTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/UsageAdvisorTests.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -211,4 +211,4 @@ public void BadIndexUsed() StringAssert.Contains("Query Closed", listener.Strings[5]); } } -} \ No newline at end of file +} diff --git a/MySQL.Data/tests/MySql.Data.Tests/GenericListener.cs b/MySQL.Data/tests/MySql.Data.Tests/GenericListener.cs index 52ac0bbbd..ff2f5c444 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/GenericListener.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/GenericListener.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/tests/MySql.Data.Tests/LoggingTests.cs b/MySQL.Data/tests/MySql.Data.Tests/LoggingTests.cs index 47c826a02..7fe068944 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/LoggingTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/LoggingTests.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -151,4 +151,4 @@ public void QuotedTokenAt300() } } } -} \ No newline at end of file +} diff --git a/MySQL.Data/tests/MySql.Data.Tests/MySqlBulkLoaderTests.cs b/MySQL.Data/tests/MySql.Data.Tests/MySqlBulkLoaderTests.cs index db2a09040..5e0c8bb56 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/MySqlBulkLoaderTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/MySqlBulkLoaderTests.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2013, 2022, Oracle and/or its affiliates. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -855,4 +855,4 @@ public void BulkLoadStreamColumnOrder() Assert.AreEqual("col3", dt.Rows[0][3].ToString().Trim()); } } -} \ No newline at end of file +} diff --git a/MySQL.Data/tests/MySql.Data.Tests/MySqlDataReaderTests.cs b/MySQL.Data/tests/MySql.Data.Tests/MySqlDataReaderTests.cs index 96a7fb9df..530c91c6e 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/MySqlDataReaderTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/MySqlDataReaderTests.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2013, 2022, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/tests/MySql.Data.Tests/OutputParametersBatch.cs b/MySQL.Data/tests/MySql.Data.Tests/OutputParametersBatch.cs index 49cc00a37..82a1997b9 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/OutputParametersBatch.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/OutputParametersBatch.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2013, 2022, Oracle and/or its affiliates. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/tests/MySql.Data.Tests/ParameterTests.cs b/MySQL.Data/tests/MySql.Data.Tests/ParameterTests.cs index b3badb9b2..75229f3fc 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/ParameterTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/ParameterTests.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2013, 2022, Oracle and/or its affiliates. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -991,4 +991,4 @@ public void AddObjectPerformance() Assert.True(sw2.Elapsed.TotalSeconds < 1); } } -} \ No newline at end of file +} diff --git a/MySQL.Data/tests/MySql.Data.Tests/PoolingTests.cs b/MySQL.Data/tests/MySql.Data.Tests/PoolingTests.cs index 7a6f01a75..910f73016 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/PoolingTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/PoolingTests.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2013, 2022, Oracle and/or its affiliates. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/tests/MySql.Data.Tests/PreparedStatementCompressed.cs b/MySQL.Data/tests/MySql.Data.Tests/PreparedStatementCompressed.cs index aa3b18569..76a937054 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/PreparedStatementCompressed.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/PreparedStatementCompressed.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/tests/MySql.Data.Tests/PreparedStatements.cs b/MySQL.Data/tests/MySql.Data.Tests/PreparedStatements.cs index 42985fe16..c7370fbad 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/PreparedStatements.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/PreparedStatements.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2013, 2022, Oracle and/or its affiliates. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/tests/MySql.Data.Tests/Properties/AssemblyInfo.cs b/MySQL.Data/tests/MySql.Data.Tests/Properties/AssemblyInfo.cs index 42b344ad7..311cedc69 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Properties/AssemblyInfo.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Properties/AssemblyInfo.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2004, 2019, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2004, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/tests/MySql.Data.Tests/ScriptExecution.cs b/MySQL.Data/tests/MySql.Data.Tests/ScriptExecution.cs index 531ea1d48..585edd440 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/ScriptExecution.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/ScriptExecution.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2013, 2021, Oracle and/or its affiliates. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/tests/MySql.Data.Tests/SimpleTransactions.cs b/MySQL.Data/tests/MySql.Data.Tests/SimpleTransactions.cs index d3a209a02..01254868e 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/SimpleTransactions.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/SimpleTransactions.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2013, 2021, Oracle and/or its affiliates. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/tests/MySql.Data.Tests/SqlServerMode.cs b/MySQL.Data/tests/MySql.Data.Tests/SqlServerMode.cs index 3e031740d..e81985b5d 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/SqlServerMode.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/SqlServerMode.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -52,4 +52,4 @@ public void Simple() } } } -} \ No newline at end of file +} diff --git a/MySQL.Data/tests/MySql.Data.Tests/SqlTokenizer.cs b/MySQL.Data/tests/MySql.Data.Tests/SqlTokenizer.cs index 32e4eb244..9e0a3e9a8 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/SqlTokenizer.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/SqlTokenizer.cs @@ -1,16 +1,16 @@ -// Copyright © 2013, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/tests/MySql.Data.Tests/SslTests.cs b/MySQL.Data/tests/MySql.Data.Tests/SslTests.cs index b0c0987c6..1e4037cbb 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/SslTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/SslTests.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2018, 2022, Oracle and/or its affiliates. +// Copyright © 2018, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/tests/MySql.Data.Tests/StoredProcedure.cs b/MySQL.Data/tests/MySql.Data.Tests/StoredProcedure.cs index 4fff00534..ab47cc78b 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/StoredProcedure.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/StoredProcedure.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2013, 2022, Oracle and/or its affiliates. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -1222,4 +1222,4 @@ public void IsSyntacticallyCorrect(string spName, bool isIt) Assert.IsTrue(MySqlClient.StoredProcedure.IsSyntacticallyCorrect(spName) == isIt); } } -} \ No newline at end of file +} diff --git a/MySQL.Data/tests/MySql.Data.Tests/StoredProcedureWithAccess.cs b/MySQL.Data/tests/MySql.Data.Tests/StoredProcedureWithAccess.cs index 2dca28635..ba50c3390 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/StoredProcedureWithAccess.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/StoredProcedureWithAccess.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/tests/MySql.Data.Tests/StressTests.cs b/MySQL.Data/tests/MySql.Data.Tests/StressTests.cs index fa02eae96..6e65b4852 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/StressTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/StressTests.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2013, 2021, Oracle and/or its affiliates. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/tests/MySql.Data.Tests/StressTestsCompressed.cs b/MySQL.Data/tests/MySql.Data.Tests/StressTestsCompressed.cs index 9df210478..6bd2d7fcc 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/StressTestsCompressed.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/StressTestsCompressed.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -37,4 +37,4 @@ internal override void AdjustConnectionSettings(MySqlConnectionStringBuilder set settings.UseCompression = true; } } -} \ No newline at end of file +} diff --git a/MySQL.Data/tests/MySql.Data.Tests/Syntax.cs b/MySQL.Data/tests/MySql.Data.Tests/Syntax.cs index 4b26e969e..5a59e9bba 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Syntax.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Syntax.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2013, 2022, Oracle and/or its affiliates. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/tests/MySql.Data.Tests/Syntax2.cs b/MySQL.Data/tests/MySql.Data.Tests/Syntax2.cs index b3896ece4..253a68a9a 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Syntax2.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Syntax2.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2013, 2021, Oracle and/or its affiliates. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/tests/MySql.Data.Tests/TableCaching.cs b/MySQL.Data/tests/MySql.Data.Tests/TableCaching.cs index 960c9e581..32bebd7b8 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/TableCaching.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/TableCaching.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/tests/MySql.Data.Tests/TestBase.cs b/MySQL.Data/tests/MySql.Data.Tests/TestBase.cs index 0dcf501fd..35e44a965 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/TestBase.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/TestBase.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2016, 2022, Oracle and/or its affiliates. +// Copyright © 2016, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/tests/MySql.Data.Tests/Tokenizer.cs b/MySQL.Data/tests/MySql.Data.Tests/Tokenizer.cs index f7e89b8dc..54cf1dc71 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Tokenizer.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Tokenizer.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/tests/MySql.Data.Tests/Transactions.cs b/MySQL.Data/tests/MySql.Data.Tests/Transactions.cs index 639b2a038..7f79e875a 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Transactions.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Transactions.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2013, 2022, Oracle and/or its affiliates. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -874,4 +874,4 @@ private static async Task SelectStarLimit1(string connectionString, string table } } } -} \ No newline at end of file +} diff --git a/MySQL.Data/tests/MySql.Data.Tests/UnixSockets.cs b/MySQL.Data/tests/MySql.Data.Tests/UnixSockets.cs index 2c2dae067..ce5b4ff3d 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/UnixSockets.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/UnixSockets.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2017, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -54,4 +54,4 @@ public void ConnectionTest() } } } -} \ No newline at end of file +} diff --git a/MySQL.Data/tests/MySql.Data.Tests/Utils.cs b/MySQL.Data/tests/MySql.Data.Tests/Utils.cs index 7c3637646..fedcd785b 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Utils.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Utils.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2013, 2021, Oracle and/or its affiliates. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -70,4 +70,4 @@ public static bool TableExists(string tableName, MySqlConnection conn) } } } -} \ No newline at end of file +} diff --git a/MySQL.Data/tests/MySqlX.Data.Performance.Console.Tests/Program.cs b/MySQL.Data/tests/MySqlX.Data.Performance.Console.Tests/Program.cs index 9311b64ef..74052df56 100644 --- a/MySQL.Data/tests/MySqlX.Data.Performance.Console.Tests/Program.cs +++ b/MySQL.Data/tests/MySqlX.Data.Performance.Console.Tests/Program.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2018, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -162,4 +162,4 @@ static void ExecuteAllClassTests(string className, string nameSpace, int executi } } } -} \ No newline at end of file +} diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/BaseTest.cs b/MySQL.Data/tests/MySqlX.Data.Tests/BaseTest.cs index 1c8ab9e5e..ac30710f4 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/BaseTest.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/BaseTest.cs @@ -1,282 +1,282 @@ -// Copyright (c) 2015, 2023, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySql.Data.MySqlClient; -using MySqlX.XDevAPI; -using MySqlX.XDevAPI.Common; -using MySqlX.XDevAPI.CRUD; -using MySqlX.XDevAPI.Relational; -using NUnit.Framework; -using System; -using System.Data; -using System.IO; -using System.Net; -using System.Net.Sockets; -using System.Reflection; - -namespace MySqlX.Data.Tests -{ - public class BaseTest - { - protected Session session; - protected Schema testSchema; - protected static readonly string schemaName = "test"; - public static readonly string sslCa = "ca.pem"; - public static readonly string sslCert = "client-cert.pem"; - public static readonly string sslKey = "client-key.pem"; - public static readonly string clientPfxIncorrect = "client-incorrect.pfx"; - public static readonly string clientPfx = "client.pfx"; - public static readonly string sslCertificatePassword = "pass"; - - #region Properties - internal static string Port { get; private set; } = Environment.GetEnvironmentVariable("MYSQL_PORT") ?? "3306"; - internal static string XPort { get; private set; } = Environment.GetEnvironmentVariable("MYSQLX_PORT") ?? "33060"; - internal static string Host { get; private set; } = Environment.GetEnvironmentVariable("MYSQL_HOST") ?? "localhost"; - internal static string RootUser { get; private set; } = Environment.GetEnvironmentVariable("MYSQL_ROOT_USER") ?? "root"; - internal static string RootPassword { get; private set; } = Environment.GetEnvironmentVariable("MYSQL_ROOT_PASSWORD") ?? string.Empty; - public static string ConnectionString { get; private set; } - public static string ConnectionStringUri { get; private set; } - public static string ConnectionStringNoPassword { get; private set; } - public static string ConnectionStringRoot { get; private set; } - public static string ConnectionStringUriNative { get; private set; } - public static string ConnectionStringUserWithSSLPEM { get; private set; } - public static string connSSLURI { get; private set; } - public static bool ServerIsDown { get; set; } - #endregion - - #region Ctor - static BaseTest() - { - ConnectionStringRoot = $"server={Host};port={Port};uid={RootUser};password={RootPassword}"; - ConnectionString = $"server={Host};port={XPort};uid=test;password=test"; - ConnectionStringNoPassword = $"server={Host};port={XPort};uid=testNoPass;"; - ConnectionStringUri = $"mysqlx://test:test@{Host}:{XPort}"; - ConnectionStringUriNative = $"mysqlx://testNative:test@{Host}:{XPort}"; - ConnectionStringUserWithSSLPEM = $"server={Host};user=test;port={XPort};password=test;SslCa={sslCa};SslCert={sslCert};SslKey={sslKey}"; - connSSLURI = ConnectionStringUri + $"?Ssl-ca={sslCa}&SslCert={sslCert}&SslKey={sslKey}&Auth=AUTO"; - } - #endregion - - #region SetUp - [OneTimeSetUp] - public virtual void BaseSetUp() - { - Assembly executingAssembly = typeof(BaseTest).GetTypeInfo().Assembly; - Stream stream = executingAssembly.GetManifestResourceStream("MySqlX.Data.Tests.Properties.CreateUsers.sql"); - StreamReader sr = new StreamReader(stream); - string sql = sr.ReadToEnd(); - sr.Dispose(); - ExecuteSqlAsRoot(sql); - session = GetSession(); - testSchema = session.GetSchema(schemaName); - if (SchemaExistsInDatabase(testSchema)) - session.DropSchema(schemaName); - session.CreateSchema(schemaName); - } - #endregion - - #region TearDown - [OneTimeTearDown] - public virtual void BaseTearDown() - { - using (Session s = GetSession()) - { - Schema schema = s.GetSchema(schemaName); - if (SchemaExistsInDatabase(schema)) - s.DropSchema(schemaName); - schema.Session.DropSchema(schemaName); - Assert.False(SchemaExistsInDatabase(schema)); - } - - DropUsers(); - } - #endregion - - #region Methods - private void DropUsers() - { - var users = FillTable("SELECT user, host FROM mysql.user WHERE user NOT LIKE 'mysql%' AND user NOT LIKE 'root'"); - foreach (DataRow row in users.Rows) - ExecuteSqlAsRoot(string.Format("DROP USER '{0}'@'{1}'", row[0].ToString(), row[1].ToString())); - ExecuteSqlAsRoot("FLUSH PRIVILEGES"); - } - - public DataTable FillTable(string sql) - { - DataTable dt = new DataTable(); - using (var conn = new MySqlConnection(ConnectionStringRoot)) - { - conn.Open(); - MySqlDataAdapter da = new MySqlDataAdapter(sql, conn); - da.Fill(dt); - } - return dt; - } - - protected Table GetTable(string schema, string table) - { - return GetSession().GetSchema(schema).GetTable(table); - } - - protected SqlResult ExecuteSQL(string sql) - { - Session session = GetSession(); - session.SetCurrentSchema(schemaName); - SqlResult r = ExecuteSQLStatement(session.SQL(sql)); - var rows = r.HasData ? r.FetchAll() : null; - return r; - } - - protected Collection CreateCollection(string name, string schema = null) - { - if (schema == null) - schema = schemaName; - Schema test = session.GetSchema(schema); - test.DropCollection(name); - return test.CreateCollection(name); - } - - public Session GetSession(bool setCurrentSchema = false) - { - if (session == null) - { - session = MySQLX.GetSession(ConnectionString); - if (setCurrentSchema) - session.SetCurrentSchema(schemaName); - } - return session; - } - - protected void ExecuteSqlAsRoot(string sql) - { - using (var conn = new MySqlConnection(ConnectionStringRoot + ";ssl mode=none")) - { - conn.Open(); - MySqlScript s = new(conn, sql); - s.Execute(); - } - } - - protected Result ExecuteAddStatement(AddStatement stmt) - { - return stmt.Execute(); - } - - protected Result ExecuteModifyStatement(ModifyStatement stmt) - { - return stmt.Execute(); - } - - protected DocResult ExecuteFindStatement(FindStatement stmt) - { - return stmt.Execute(); - } - - protected SqlResult ExecuteSQLStatement(SqlStatement stmt) - { - return stmt.Execute(); - } - - protected Result ExecuteRemoveStatement(RemoveStatement stmt) - { - return stmt.Execute(); - } - - protected RowResult ExecuteSelectStatement(TableSelectStatement stmt) - { - return stmt.Execute(); - } - - protected Result ExecuteInsertStatement(TableInsertStatement stmt) - { - return stmt.Execute(); - } - - protected Result ExecuteUpdateStatement(TableUpdateStatement stmt) - { - return stmt.Execute(); - } - - protected Result ExecuteDeleteStatement(TableDeleteStatement stmt) - { - return stmt.Execute(); - } - - protected bool SchemaExistsInDatabase(Schema schema) - { - return schema.ExistsInDatabase(); - } - - protected bool CollectionExistsInDatabase(Collection collection) - { - return collection.ExistsInDatabase(); - } - - protected bool TableExistsInDatabase(Table table) - { - return table.ExistsInDatabase(); - } - - public string GetIPV6Address() - { - string strHostName = System.Net.Dns.GetHostName(); - IPHostEntry ipEntry = System.Net.Dns.GetHostEntry(strHostName); - IPAddress[] addr = ipEntry.AddressList; - return addr[0].ToString(); - } - - /// - /// Method to get the local ip address of the active MySql Server - /// - /// when is true return IPv6(::1), otherwise return IPv4(127.0.0.1) which is the default - /// Return the ip address as string - public string GetMySqlServerIp(bool isIpV6 = false) - { - var hostname = session.SQL("Select SUBSTRING_INDEX(host, ':', 1) as 'ip' From information_schema.processlist WHERE ID = connection_id()").Execute().FetchOne()[0].ToString(); - string ipv4 = string.Empty; - string ipv6 = string.Empty; - - foreach (var item in Dns.GetHostEntry(hostname).AddressList) - { - switch (item.AddressFamily) - { - case AddressFamily.InterNetwork: - ipv4 = item.ToString(); - break; - case AddressFamily.InterNetworkV6: - ipv6 = item.ToString(); - break; - } - } - - return isIpV6 ? ipv6 : ipv4; - } - - #endregion - } -} +// Copyright © 2015, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySql.Data.MySqlClient; +using MySqlX.XDevAPI; +using MySqlX.XDevAPI.Common; +using MySqlX.XDevAPI.CRUD; +using MySqlX.XDevAPI.Relational; +using NUnit.Framework; +using System; +using System.Data; +using System.IO; +using System.Net; +using System.Net.Sockets; +using System.Reflection; + +namespace MySqlX.Data.Tests +{ + public class BaseTest + { + protected Session session; + protected Schema testSchema; + protected static readonly string schemaName = "test"; + public static readonly string sslCa = "ca.pem"; + public static readonly string sslCert = "client-cert.pem"; + public static readonly string sslKey = "client-key.pem"; + public static readonly string clientPfxIncorrect = "client-incorrect.pfx"; + public static readonly string clientPfx = "client.pfx"; + public static readonly string sslCertificatePassword = "pass"; + + #region Properties + internal static string Port { get; private set; } = Environment.GetEnvironmentVariable("MYSQL_PORT") ?? "3306"; + internal static string XPort { get; private set; } = Environment.GetEnvironmentVariable("MYSQLX_PORT") ?? "33060"; + internal static string Host { get; private set; } = Environment.GetEnvironmentVariable("MYSQL_HOST") ?? "localhost"; + internal static string RootUser { get; private set; } = Environment.GetEnvironmentVariable("MYSQL_ROOT_USER") ?? "root"; + internal static string RootPassword { get; private set; } = Environment.GetEnvironmentVariable("MYSQL_ROOT_PASSWORD") ?? string.Empty; + public static string ConnectionString { get; private set; } + public static string ConnectionStringUri { get; private set; } + public static string ConnectionStringNoPassword { get; private set; } + public static string ConnectionStringRoot { get; private set; } + public static string ConnectionStringUriNative { get; private set; } + public static string ConnectionStringUserWithSSLPEM { get; private set; } + public static string connSSLURI { get; private set; } + public static bool ServerIsDown { get; set; } + #endregion + + #region Ctor + static BaseTest() + { + ConnectionStringRoot = $"server={Host};port={Port};uid={RootUser};password={RootPassword}"; + ConnectionString = $"server={Host};port={XPort};uid=test;password=test"; + ConnectionStringNoPassword = $"server={Host};port={XPort};uid=testNoPass;"; + ConnectionStringUri = $"mysqlx://test:test@{Host}:{XPort}"; + ConnectionStringUriNative = $"mysqlx://testNative:test@{Host}:{XPort}"; + ConnectionStringUserWithSSLPEM = $"server={Host};user=test;port={XPort};password=test;SslCa={sslCa};SslCert={sslCert};SslKey={sslKey}"; + connSSLURI = ConnectionStringUri + $"?Ssl-ca={sslCa}&SslCert={sslCert}&SslKey={sslKey}&Auth=AUTO"; + } + #endregion + + #region SetUp + [OneTimeSetUp] + public virtual void BaseSetUp() + { + Assembly executingAssembly = typeof(BaseTest).GetTypeInfo().Assembly; + Stream stream = executingAssembly.GetManifestResourceStream("MySqlX.Data.Tests.Properties.CreateUsers.sql"); + StreamReader sr = new StreamReader(stream); + string sql = sr.ReadToEnd(); + sr.Dispose(); + ExecuteSqlAsRoot(sql); + session = GetSession(); + testSchema = session.GetSchema(schemaName); + if (SchemaExistsInDatabase(testSchema)) + session.DropSchema(schemaName); + session.CreateSchema(schemaName); + } + #endregion + + #region TearDown + [OneTimeTearDown] + public virtual void BaseTearDown() + { + using (Session s = GetSession()) + { + Schema schema = s.GetSchema(schemaName); + if (SchemaExistsInDatabase(schema)) + s.DropSchema(schemaName); + schema.Session.DropSchema(schemaName); + Assert.False(SchemaExistsInDatabase(schema)); + } + + DropUsers(); + } + #endregion + + #region Methods + private void DropUsers() + { + var users = FillTable("SELECT user, host FROM mysql.user WHERE user NOT LIKE 'mysql%' AND user NOT LIKE 'root'"); + foreach (DataRow row in users.Rows) + ExecuteSqlAsRoot(string.Format("DROP USER '{0}'@'{1}'", row[0].ToString(), row[1].ToString())); + ExecuteSqlAsRoot("FLUSH PRIVILEGES"); + } + + public DataTable FillTable(string sql) + { + DataTable dt = new DataTable(); + using (var conn = new MySqlConnection(ConnectionStringRoot)) + { + conn.Open(); + MySqlDataAdapter da = new MySqlDataAdapter(sql, conn); + da.Fill(dt); + } + return dt; + } + + protected Table GetTable(string schema, string table) + { + return GetSession().GetSchema(schema).GetTable(table); + } + + protected SqlResult ExecuteSQL(string sql) + { + Session session = GetSession(); + session.SetCurrentSchema(schemaName); + SqlResult r = ExecuteSQLStatement(session.SQL(sql)); + var rows = r.HasData ? r.FetchAll() : null; + return r; + } + + protected Collection CreateCollection(string name, string schema = null) + { + if (schema == null) + schema = schemaName; + Schema test = session.GetSchema(schema); + test.DropCollection(name); + return test.CreateCollection(name); + } + + public Session GetSession(bool setCurrentSchema = false) + { + if (session == null) + { + session = MySQLX.GetSession(ConnectionString); + if (setCurrentSchema) + session.SetCurrentSchema(schemaName); + } + return session; + } + + protected void ExecuteSqlAsRoot(string sql) + { + using (var conn = new MySqlConnection(ConnectionStringRoot + ";ssl mode=none")) + { + conn.Open(); + MySqlScript s = new(conn, sql); + s.Execute(); + } + } + + protected Result ExecuteAddStatement(AddStatement stmt) + { + return stmt.Execute(); + } + + protected Result ExecuteModifyStatement(ModifyStatement stmt) + { + return stmt.Execute(); + } + + protected DocResult ExecuteFindStatement(FindStatement stmt) + { + return stmt.Execute(); + } + + protected SqlResult ExecuteSQLStatement(SqlStatement stmt) + { + return stmt.Execute(); + } + + protected Result ExecuteRemoveStatement(RemoveStatement stmt) + { + return stmt.Execute(); + } + + protected RowResult ExecuteSelectStatement(TableSelectStatement stmt) + { + return stmt.Execute(); + } + + protected Result ExecuteInsertStatement(TableInsertStatement stmt) + { + return stmt.Execute(); + } + + protected Result ExecuteUpdateStatement(TableUpdateStatement stmt) + { + return stmt.Execute(); + } + + protected Result ExecuteDeleteStatement(TableDeleteStatement stmt) + { + return stmt.Execute(); + } + + protected bool SchemaExistsInDatabase(Schema schema) + { + return schema.ExistsInDatabase(); + } + + protected bool CollectionExistsInDatabase(Collection collection) + { + return collection.ExistsInDatabase(); + } + + protected bool TableExistsInDatabase(Table table) + { + return table.ExistsInDatabase(); + } + + public string GetIPV6Address() + { + string strHostName = System.Net.Dns.GetHostName(); + IPHostEntry ipEntry = System.Net.Dns.GetHostEntry(strHostName); + IPAddress[] addr = ipEntry.AddressList; + return addr[0].ToString(); + } + + /// + /// Method to get the local ip address of the active MySql Server + /// + /// when is true return IPv6(::1), otherwise return IPv4(127.0.0.1) which is the default + /// Return the ip address as string + public string GetMySqlServerIp(bool isIpV6 = false) + { + var hostname = session.SQL("Select SUBSTRING_INDEX(host, ':', 1) as 'ip' From information_schema.processlist WHERE ID = connection_id()").Execute().FetchOne()[0].ToString(); + string ipv4 = string.Empty; + string ipv6 = string.Empty; + + foreach (var item in Dns.GetHostEntry(hostname).AddressList) + { + switch (item.AddressFamily) + { + case AddressFamily.InterNetwork: + ipv4 = item.ToString(); + break; + case AddressFamily.InterNetworkV6: + ipv6 = item.ToString(); + break; + } + } + + return isIpV6 ? ipv6 : ipv4; + } + + #endregion + } +} diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/BasicFindTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/BasicFindTests.cs index 2e20b5fec..6c0f85bb9 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/BasicFindTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/BasicFindTests.cs @@ -1,2284 +1,2284 @@ -// Copyright (c) 2015, 2023, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySql.Data.Common; -using MySql.Data.MySqlClient; -using MySqlX.XDevAPI; -using MySqlX.XDevAPI.Common; -using MySqlX.XDevAPI.CRUD; -using NUnit.Framework; -using System; - -namespace MySqlX.Data.Tests -{ - public class BasicFindTests : BaseTest - { - [Test] - public void SimpleFind() - { - Collection coll = CreateCollection("test"); - var docs = new[] - { - new { _id = 1, title = "Book 1", pages = 20 }, - new { _id = 2, title = "Book 2", pages = 30 }, - new { _id = 3, title = "Book 3", pages = 40 }, - new { _id = 4, title = "Book 4", pages = 50 }, - }; - Result r = ExecuteAddStatement(coll.Add(docs)); - Assert.AreEqual(4, r.AffectedItemsCount); - - var foundDocs = ExecuteFindStatement(coll.Find("pages > 20")); - Assert.True(foundDocs.Next()); - Assert.True(foundDocs.Current["title"].ToString() == "Book 2"); - Assert.True(foundDocs.Next()); - Assert.True(foundDocs.Current["title"].ToString() == "Book 3"); - Assert.True(foundDocs.Next()); - Assert.True(foundDocs.Current["title"].ToString() == "Book 4"); - Assert.False(foundDocs.Next()); - } - - [Test] - public void SimpleFindWithSort() - { - Collection coll = CreateCollection("test"); - var docs = new[] - { - new { _id = 1, title = "Book 1", pages = 20 }, - new { _id = 2, title = "Book 2", pages = 30 }, - new { _id = 3, title = "Book 3", pages = 40 }, - new { _id = 4, title = "Book 4", pages = 50 }, - }; - Result r = ExecuteAddStatement(coll.Add(docs)); - Assert.AreEqual(4, r.AffectedItemsCount); - - var foundDocs = ExecuteFindStatement(coll.Find("pages > 20").Sort("pages DESC")); - Assert.True(foundDocs.Next()); - Assert.True(foundDocs.Current["title"].ToString() == "Book 4"); - Assert.True(foundDocs.Next()); - Assert.True(foundDocs.Current["title"].ToString() == "Book 3"); - Assert.True(foundDocs.Next()); - Assert.True(foundDocs.Current["title"].ToString() == "Book 2"); - Assert.False(foundDocs.Next()); - } - - [Test] - public void SimpleFindWithLimitAndOffset() - { - Collection coll = CreateCollection("test"); - var docs = new[] - { - new { _id = 1, title = "Book 1", pages = 20 }, - new { _id = 2, title = "Book 2", pages = 30 }, - new { _id = 3, title = "Book 3", pages = 40 }, - new { _id = 4, title = "Book 4", pages = 50 }, - }; - Result r = ExecuteAddStatement(coll.Add(docs)); - Assert.AreEqual(4, r.AffectedItemsCount); - - var foundDocs = ExecuteFindStatement(coll.Find("pages > 20").Limit(1)); - Assert.True(foundDocs.Next()); - Assert.True(foundDocs.Current["title"].ToString() == "Book 2"); - Assert.False(foundDocs.Next()); - - var resultDocs = ExecuteFindStatement(coll.Find("pages > 20").Offset(1).Limit(2)).FetchAll(); - Assert.AreEqual(40, resultDocs[0]["pages"]); - Assert.AreEqual(50, resultDocs[1]["pages"]); - - // Limit out of range. - Assert.Throws(() => ExecuteFindStatement(coll.Find().Limit(0))); - Assert.Throws(() => ExecuteFindStatement(coll.Find().Limit(-1))); - } - - [Test] - public void FindConditional() - { - Collection coll = CreateCollection("test"); - var docs = new[] - { - new { _id = 1, title = "Book 1", pages = 20 }, - new { _id = 2, title = "Book 2", pages = 30 }, - new { _id = 3, title = "Book 3", pages = 40 }, - new { _id = 4, title = "Book 4", pages = 50 }, - }; - Result r = ExecuteAddStatement(coll.Add(docs)); - Assert.AreEqual(4, r.AffectedItemsCount); - - var foundDocs = ExecuteFindStatement(coll.Find("pages = :Pages").Bind("pAges", 40)); - Assert.True(foundDocs.Next()); - Assert.True(foundDocs.Current["title"].ToString() == "Book 3"); - Assert.False(foundDocs.Next()); - } - - [Test] - public void BindDbDoc() - { - Collection coll = CreateCollection("test"); - var docs = new[] - { - new { _id = 1, title = "Book 1", pages = 20 }, - new { _id = 2, title = "Book 2", pages = 30 }, - new { _id = 3, title = "Book 3", pages = 40 }, - new { _id = 4, title = "Book 4", pages = 50 }, - }; - Result r = ExecuteAddStatement(coll.Add(docs)); - Assert.AreEqual(4, r.AffectedItemsCount); - - DbDoc docParams = new DbDoc(new { pages1 = 30, pages2 = 40 }); - var foundDocs = ExecuteFindStatement(coll.Find("pages = :Pages1 || pages = :Pages2").Bind(docParams)); - Assert.True(foundDocs.Next()); - Assert.AreEqual("Book 2", foundDocs.Current["title"]); - Assert.True(foundDocs.Next()); - Assert.AreEqual("Book 3", foundDocs.Current["title"]); - Assert.False(foundDocs.Next()); - } - - [Test] - public void BindJsonAsAnonymous() - { - Collection coll = CreateCollection("test"); - var docs = new[] - { - new { _id = 1, title = "Book 1", pages = 20 }, - new { _id = 2, title = "Book 2", pages = 30 }, - new { _id = 3, title = "Book 3", pages = 40 }, - new { _id = 4, title = "Book 4", pages = 50 }, - }; - Result r = ExecuteAddStatement(coll.Add(docs)); - Assert.AreEqual(4, r.AffectedItemsCount); - - var jsonParams = new { pages1 = 30, pages2 = 40 }; - var foundDocs = ExecuteFindStatement(coll.Find("pages = :Pages1 || pages = :Pages2").Bind(jsonParams)); - Assert.True(foundDocs.Next()); - Assert.AreEqual("Book 2", foundDocs.Current["title"]); - Assert.True(foundDocs.Next()); - Assert.AreEqual("Book 3", foundDocs.Current["title"]); - Assert.False(foundDocs.Next()); - } - - [Test] - public void BindJsonAsString() - { - Collection coll = CreateCollection("test"); - var docs = new[] - { - new { _id = 1, title = "Book 1", pages = 20 }, - new { _id = 2, title = "Book 2", pages = 30 }, - new { _id = 3, title = "Book 3", pages = 40 }, - new { _id = 4, title = "Book 4", pages = 50 }, - }; - Result r = ExecuteAddStatement(coll.Add(docs)); - Assert.AreEqual(4, r.AffectedItemsCount); - - var jsonParams = "{ \"pages1\" : 30, \"pages2\" : 40 }"; - var foundDocs = ExecuteFindStatement(coll.Find("pages = :Pages1 || pages = :Pages2").Bind(jsonParams)); - Assert.True(foundDocs.Next()); - Assert.AreEqual("Book 2", foundDocs.Current["title"]); - Assert.True(foundDocs.Next()); - Assert.AreEqual("Book 3", foundDocs.Current["title"]); - Assert.False(foundDocs.Next()); - } - - [Test] - public void RowLockingNotSupportedInOlderVersions() - { - if (session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql lower than 8.0.3."); - Collection coll = CreateCollection("test"); - - Exception ex = Assert.Throws(() => ExecuteFindStatement(coll.Find().LockShared())); - Assert.AreEqual("This functionality is only supported from server version 8.0.3 onwards.", ex.Message); - - ex = Assert.Throws(() => ExecuteFindStatement(coll.Find().LockExclusive())); - Assert.AreEqual("This functionality is only supported from server version 8.0.3 onwards.", ex.Message); - } - - [Test] - public void SimpleSharedLock() - { - if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); - - ExecuteSQLStatement(session.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); - using (var session2 = MySQLX.GetSession(ConnectionString)) - { - ExecuteSQLStatement(session2.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); - Collection coll = CreateCollection("test"); - var docs = new[] - { - new { _id = 1, a = 1 }, - new { _id = 2, a = 1 }, - new { _id = 3, a = 1 }, - }; - ExecuteAddStatement(coll.Add(docs)); - Collection coll2 = session2.GetSchema("test").GetCollection("test"); - - ExecuteSQLStatement(session.SQL("START TRANSACTION")); - var docResult = ExecuteFindStatement(coll.Find("_id = 1").LockShared()); - Assert.That(docResult.FetchAll(), Has.One.Items); - - ExecuteSQLStatement(session2.SQL("START TRANSACTION")); - // Should return immediately since document isn't locked. - docResult = ExecuteFindStatement(coll2.Find("_id = 2").LockShared()); - Assert.That(docResult.FetchAll(), Has.One.Items); - // Should return immediately due to LockShared() allows reading by other sessions. - docResult = ExecuteFindStatement(coll2.Find("_id = 1").LockShared()); - Assert.That(docResult.FetchAll(), Has.One.Items); - - ExecuteSQLStatement(session.SQL("ROLLBACK")); - ExecuteSQLStatement(session2.SQL("ROLLBACK")); - } - } - - [Test] - public void SharedLockForbidsToModifyDocuments() - { - if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); - - ExecuteSQLStatement(session.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); - using (var session2 = MySQLX.GetSession(ConnectionString)) - { - ExecuteSQLStatement(session2.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); - Collection coll = CreateCollection("test"); - var docs = new[] - { - new { _id = 1, a = 1 }, - new { _id = 2, a = 1 }, - new { _id = 3, a = 1 }, - }; - ExecuteAddStatement(coll.Add(docs)); - Collection coll2 = session2.GetSchema("test").GetCollection("test"); - - ExecuteSQLStatement(session.SQL("START TRANSACTION")); - var docResult = ExecuteFindStatement(coll.Find("_id = 1").LockShared()); - Assert.That(docResult.FetchAll(), Has.One.Items); - - ExecuteSQLStatement(session2.SQL("START TRANSACTION")); - // Reading the same document is allowed with LockShared(). - docResult = ExecuteFindStatement(coll2.Find("_id = 1")); - Assert.That(docResult.FetchAll(), Has.One.Items); - - // Modify() is allowed for non-locked documents. - Result result = ExecuteModifyStatement(coll2.Modify("_id = 2").Set("a", 2)); - Assert.AreEqual(1, result.AffectedItemsCount); - // Session1 blocks, Modify() is not allowed for locked documents. - ExecuteSQLStatement(session2.SQL("SET SESSION innodb_lock_wait_timeout=1")); - Exception ex = Assert.Throws(() => ExecuteModifyStatement(coll2.Modify("_id = 1").Set("a", 2))); - Assert.AreEqual("Lock wait timeout exceeded; try restarting transaction", ex.Message); - - ExecuteSQLStatement(session.SQL("ROLLBACK")); - // Modify() is allowed since document isn't locked anymore. - ExecuteModifyStatement(coll2.Modify("_id = 1").Set("a", 2)); - ExecuteSQLStatement(session2.SQL("COMMIT")); - } - } - - [Test] - public void ExclusiveLockForbidsToModifyDocuments() - { - if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); - - ExecuteSQLStatement(session.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); - using (var session2 = MySQLX.GetSession(ConnectionString)) - { - ExecuteSQLStatement(session2.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); - Collection coll = CreateCollection("test"); - var docs = new[] - { - new { _id = 1, a = 1 }, - new { _id = 2, a = 1 }, - new { _id = 3, a = 1 }, - }; - ExecuteAddStatement(coll.Add(docs)); - Collection coll2 = session2.GetSchema("test").GetCollection("test"); - - ExecuteSQLStatement(session.SQL("START TRANSACTION")); - var docResult = ExecuteFindStatement(coll.Find("_id = 1").LockExclusive()); - Assert.That(docResult.FetchAll(), Has.One.Items); - - ExecuteSQLStatement(session2.SQL("START TRANSACTION")); - - // Modify() is allowed for non-locked documents. - Result result = ExecuteModifyStatement(coll2.Modify("_id = 2").Set("a", 2)); - Assert.AreEqual(1, result.AffectedItemsCount); - // Session2 blocks, Modify() is not allowed for locked documents. - ExecuteSQLStatement(session2.SQL("SET SESSION innodb_lock_wait_timeout=1")); - Exception ex = Assert.Throws(() => ExecuteModifyStatement(coll2.Modify("_id = 1").Set("a", 2))); - Assert.AreEqual("Lock wait timeout exceeded; try restarting transaction", ex.Message); - ex = Assert.Throws(() => ExecuteModifyStatement(coll2.Modify("_id = 1").Change("a", 12))); - Assert.AreEqual("Lock wait timeout exceeded; try restarting transaction", ex.Message); - - ExecuteSQLStatement(session.SQL("ROLLBACK")); - // Modify() is allowed since document isn't locked anymore. - ExecuteModifyStatement(coll2.Modify("_id = 1").Set("a", 2)); - ExecuteSQLStatement(session2.SQL("COMMIT")); - } - } - - [Test] - public void SharedLockAfterExclusiveLock() - { - if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); - - ExecuteSQLStatement(session.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); - using (var session2 = MySQLX.GetSession(ConnectionString)) - { - ExecuteSQLStatement(session2.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); - Collection coll = CreateCollection("test"); - ExecuteSQLStatement(session2.SQL("ALTER TABLE `test`.`test` ADD COLUMN `$ix_i_r_index` INT GENERATED ALWAYS AS (JSON_UNQUOTE(JSON_EXTRACT(doc, '$._id'))) VIRTUAL NOT NULL, ADD UNIQUE INDEX `myIndex`(`$ix_i_r_index`)")); - var docs = new[] - { - new { _id = 1, a = 1 }, - new { _id = 2, a = 1 }, - new { _id = 3, a = 1 }, - }; - ExecuteAddStatement(coll.Add(docs)); - Collection coll2 = session2.GetSchema("test").GetCollection("test"); - - ExecuteSQLStatement(session.SQL("START TRANSACTION")); - var docResult = ExecuteFindStatement(coll.Find("_id = 1").LockExclusive()); - Assert.That(docResult.FetchAll(), Has.One.Items); - - ExecuteSQLStatement(session2.SQL("START TRANSACTION")); - // Should return immediately since document isn't locked. - docResult = ExecuteFindStatement(coll2.Find("_id = 2").LockShared()); - Assert.That(docResult.FetchAll(), Has.One.Items); - // Session2 blocks due to LockExclusive() not allowing to read locked documents. - ExecuteSQLStatement(session2.SQL("SET SESSION innodb_lock_wait_timeout=1")); - Exception ex = Assert.Throws(() => ExecuteFindStatement(coll2.Find("_id = 1").LockShared())); - Assert.AreEqual("Lock wait timeout exceeded; try restarting transaction", ex.Message); - - // Session unlocks documents. - ExecuteSQLStatement(session.SQL("ROLLBACK")); - // Document can now be recovered. - docResult = ExecuteFindStatement(coll2.Find("_id = 1").LockShared()); - Assert.That(docResult.FetchAll(), Has.One.Items); - ExecuteSQLStatement(session2.SQL("ROLLBACK")); - } - } - - [Test] - public void ExclusiveLockAfterSharedLock() - { - if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); - - ExecuteSQLStatement(session.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); - using (var session2 = MySQLX.GetSession(ConnectionString)) - { - ExecuteSQLStatement(session2.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); - Collection coll = CreateCollection("test"); - ExecuteSQLStatement(session2.SQL("ALTER TABLE `test`.`test` ADD COLUMN `$ix_i_r_index` INT GENERATED ALWAYS AS (JSON_UNQUOTE(JSON_EXTRACT(doc, '$._id'))) VIRTUAL NOT NULL, ADD UNIQUE INDEX `myIndex`(`$ix_i_r_index`)")); - var docs = new[] - { - new { _id = 1, a = 1 }, - new { _id = 2, a = 1 }, - new { _id = 3, a = 1 }, - }; - ExecuteAddStatement(coll.Add(docs)); - Collection coll2 = session2.GetSchema("test").GetCollection("test"); - - ExecuteSQLStatement(session.SQL("START TRANSACTION")); - var docResult = ExecuteFindStatement(coll.Find("_id in (1, 3)").LockShared()); - Assert.AreEqual(2, docResult.FetchAll().Count); - - ExecuteSQLStatement(session2.SQL("START TRANSACTION")); - // Should return immediately since document isn't locked. - docResult = ExecuteFindStatement(coll2.Find("_id = 2").LockExclusive()); - // Should return immediately due to LockShared() allows reading by other sessions. - docResult = ExecuteFindStatement(coll2.Find("_id = 2").LockShared()); - Assert.That(docResult.FetchAll(), Has.One.Items); - // Session2 blocks due to to LockExclusive() not allowing to read locked documents. - ExecuteSQLStatement(session2.SQL("SET SESSION innodb_lock_wait_timeout=1")); - Exception ex = Assert.Throws(() => ExecuteFindStatement(coll2.Find("_id = 1").LockExclusive())); - Assert.AreEqual("Lock wait timeout exceeded; try restarting transaction", ex.Message); - - // Session unlocks documents. - ExecuteSQLStatement(session.SQL("ROLLBACK")); - docResult = ExecuteFindStatement(coll2.Find("_id = 1").LockExclusive()); - Assert.That(docResult.FetchAll(), Has.One.Items); - ExecuteSQLStatement(session2.SQL("ROLLBACK")); - } - } - - [Test] - public void ExclusiveLockAfterExclusiveLock() - { - if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); - - ExecuteSQLStatement(session.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); - using (var session2 = MySQLX.GetSession(ConnectionString)) - { - ExecuteSQLStatement(session2.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); - Collection coll = CreateCollection("test"); - ExecuteSQLStatement(session2.SQL("ALTER TABLE `test`.`test` ADD COLUMN `$ix_i_r_index` INT GENERATED ALWAYS AS (JSON_UNQUOTE(JSON_EXTRACT(doc, '$._id'))) VIRTUAL NOT NULL, ADD UNIQUE INDEX `myIndex`(`$ix_i_r_index`)")); - var docs = new[] - { - new { _id = 1, a = 1 }, - new { _id = 2, a = 1 }, - new { _id = 3, a = 1 } - }; - ExecuteAddStatement(coll.Add(docs)); - Collection coll2 = session2.GetSchema("test").GetCollection("test"); - - ExecuteSQLStatement(session.SQL("START TRANSACTION")); - var docResult = ExecuteFindStatement(coll.Find("_id = 1").LockExclusive()); - Assert.That(docResult.FetchAll(), Has.One.Items); - - ExecuteSQLStatement(session2.SQL("START TRANSACTION")); - // Should return immediately since document isn't locked. - docResult = ExecuteFindStatement(coll2.Find("_id = 2").LockExclusive()); - Assert.That(docResult.FetchAll(), Has.One.Items); - // Session2 blocks due to to LockExclusive() not allowing to read locked documents. - ExecuteSQLStatement(session2.SQL("SET SESSION innodb_lock_wait_timeout=1")); - Exception ex = Assert.Throws(() => ExecuteFindStatement(coll2.Find("_id = 1").LockExclusive())); - Assert.AreEqual("Lock wait timeout exceeded; try restarting transaction", ex.Message); - - // Session unlocks documents. - ExecuteSQLStatement(session.SQL("ROLLBACK")); - docResult = ExecuteFindStatement(coll2.Find("_id = 1").LockExclusive()); - Assert.That(docResult.FetchAll(), Has.One.Items); - ExecuteSQLStatement(session2.SQL("ROLLBACK")); - } - } - - [Test] - public void InOperatorWithListOfValues() - { - if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); - - // Validates the IN operator allows expressions of the type - // ( compExpr ["NOT"] "IN" "(" argsList ")" ) | ( compExpr ["NOT"] "IN" "[" argsList "]" ) - Collection coll = CreateCollection("test"); - ExecuteAddStatement(coll.Add(new DbDoc("{ \"a\": 1, \"b\": [ 1, \"value\" ], \"d\":\"\" }"))); - - Assert.That(ExecuteFindStatement(coll.Find("a IN (1,2,3)")).FetchAll(), Has.One.Items); - Assert.That(ExecuteFindStatement(coll.Find("a not in (0,2,3)")).FetchAll(), Has.One.Items); - Assert.That(ExecuteFindStatement(coll.Find("b[0] in (1,2,3)")).FetchAll(), Has.One.Items); - Assert.That(ExecuteFindStatement(coll.Find("b[1] in (\"a\", \"b\", \"value\")")).FetchAll(), Has.One.Items); - Assert.That(ExecuteFindStatement(coll.Find("b[0] NOT IN (0,2,3)")).FetchAll(), Has.One.Items); - Assert.That(ExecuteFindStatement(coll.Find("b[1] not in (\"a\", \"b\", \"c\")")).FetchAll(), Has.One.Items); - Assert.That(ExecuteFindStatement(coll.Find("a in [1,2,3]")).FetchAll(), Has.One.Items); - CollectionAssert.IsEmpty(ExecuteFindStatement(coll.Find("a in [2,3,4]")).FetchAll()); - Assert.That(ExecuteFindStatement(coll.Find("a NOT in [0,2,3]")).FetchAll(), Has.One.Items); - Assert.That(ExecuteFindStatement(coll.Find("b not IN [1,2,3]")).FetchAll(), Has.One.Items); - CollectionAssert.IsEmpty(ExecuteFindStatement(coll.Find("b[0] not IN [1,2,3]")).FetchAll()); - CollectionAssert.IsEmpty(ExecuteFindStatement(coll.Find("c NOT IN [1,2,3]")).FetchAll()); - CollectionAssert.IsEmpty(ExecuteFindStatement(coll.Find("a IN ('', ' ')")).FetchAll()); - CollectionAssert.IsEmpty(ExecuteFindStatement(coll.Find("'' IN (1,2,3)")).FetchAll()); - Assert.That(ExecuteFindStatement(coll.Find("d IN ('')")).FetchAll(), Has.One.Items); - - Collection movies = CreateCollection("movies"); - var docString = "{ \"_id\" : \"a6f4b93e1a264a108393524f29546a8c\", \"title\" : \"AFRICAN EGG\", \"description\" : \"A Fast-Paced Documentary of a Pastry Chef And a Dentist who must Pursue a Forensic Psychologist in The Gulf of Mexico\", \"releaseyear\" : 2006, \"language\" : \"English\", \"duration\" : 130, \"rating\" : \"G\", \"genre\" : \"Science fiction\", \"actors\" : [{ \"name\" : \"MILLA PECK\", \"country\" : \"Mexico\", \"birthdate\": \"12 Jan 1984\"}, { \"name\" : \"VAL BOLGER\", \"country\" : \"Botswana\", \"birthdate\": \"26 Jul 1975\" }, { \"name\" : \"SCARLETT BENING\", \"country\" : \"Syria\", \"birthdate\": \"16 Mar 1978\" }], \"additionalinfo\" : { \"director\" : \"Sharice Legaspi\", \"writers\" : [\"Rusty Couturier\", \"Angelic Orduno\", \"Carin Postell\"], \"productioncompanies\" : [\"Qvodrill\", \"Indigoholdings\"] } }"; - ExecuteAddStatement(movies.Add(new DbDoc(docString))); - - Assert.That(ExecuteFindStatement(movies.Find("(1>5) in (true, false)")).FetchAll(), Has.One.Items); - CollectionAssert.IsEmpty(ExecuteFindStatement(movies.Find("(1+5) in (1, 2, 3, 4, 5)")).FetchAll()); - Assert.That(ExecuteFindStatement(movies.Find("('a'>'b') in (true, false)")).FetchAll(), Has.One.Items); - Assert.Throws(() => ExecuteFindStatement(movies.Find("(1>5) in [true, false]")).FetchAll()); - Assert.Throws(() => ExecuteFindStatement(movies.Find("(1+5) in [1, 2, 3, 4, 5]")).FetchAll()); - Assert.Throws(() => ExecuteFindStatement(movies.Find("('a'>'b') in [true, false]")).FetchAll()); - Assert.That(ExecuteFindStatement(movies.Find("true IN [(1>5), !(false), (true || false), (false && true)]")).FetchAll(), Has.One.Items); - Assert.That(ExecuteFindStatement(movies.Find("true IN ((1>5), !(false), (true || false), (false && true))")).FetchAll(), Has.One.Items); - CollectionAssert.IsEmpty(ExecuteFindStatement(movies.Find("{\"field\":true} IN (\"mystring\", 124, myvar, othervar.jsonobj)")).FetchAll()); - CollectionAssert.IsEmpty(ExecuteFindStatement(movies.Find("actor.name IN ['a name', null, (1<5-4), myvar.jsonobj.name]")).FetchAll()); - Assert.That(ExecuteFindStatement(movies.Find("!false && true IN [true]")).FetchAll(), Has.One.Items); - Assert.Throws(() => ExecuteFindStatement(movies.Find("1-5/2*2 > 3-2/1*2 IN [true, false]")).FetchAll()); - CollectionAssert.IsEmpty(ExecuteFindStatement(movies.Find("true IN [1-5/2*2 > 3-2/1*2]")).FetchAll()); - Assert.That(ExecuteFindStatement(movies.Find(" 'African Egg' IN ('African Egg', 1, true, NULL, [0,1,2], { 'title' : 'Atomic Firefighter' }) ")).FetchAll(), Has.One.Items); - Assert.That(ExecuteFindStatement(movies.Find(" 1 IN ('African Egg', 1, true, NULL, [0,1,2], { 'title' : 'Atomic Firefighter' }) ")).FetchAll(), Has.One.Items); - Assert.That(ExecuteFindStatement(movies.Find(" [0,1,2] IN ('African Egg', 1, true, NULL, [0,1,2], { 'title' : 'Atomic Firefighter' }) ")).FetchAll(), Has.One.Items); - Assert.That(ExecuteFindStatement(movies.Find(" { 'title' : 'Atomic Firefighter' } IN ('African Egg', 1, true, NULL, [0,1,2], { 'title' : 'Atomic Firefighter' }) ")).FetchAll(), Has.One.Items); - CollectionAssert.IsEmpty(ExecuteFindStatement(movies.Find("title IN ('African Egg', 'The Witcher', 'Jurassic Perk')")).FetchAll()); - Assert.That(ExecuteFindStatement(movies.Find("releaseyear IN (2006, 2010, 2017)")).FetchAll(), Has.One.Items); - Assert.That(ExecuteFindStatement(movies.Find("1 IN [1,2,3]")).FetchAll(), Has.One.Items); - CollectionAssert.IsEmpty(ExecuteFindStatement(movies.Find("0 IN [1,2,3]")).FetchAll()); - Assert.That(ExecuteFindStatement(movies.Find("0 NOT IN [1,2,3]")).FetchAll(), Has.One.Items); - CollectionAssert.IsEmpty(ExecuteFindStatement(movies.Find("1 NOT IN [1,2,3]")).FetchAll()); - Assert.That(ExecuteFindStatement(movies.Find("releaseyear IN [2006, 2007, 2008]")).FetchAll(), Has.One.Items); - } - - [Test] - public void InOperatorWithCompExpr() - { - if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); - - // Validates the IN operator allows expressions of the type: compExpr ["NOT"] "IN" compExpr - Collection coll = CreateCollection("test"); - var docString = "{ \"a\": 1, \"b\": \"foo\", \"c\": { \"d\": true, \"e\": [1,2,3] }, \"f\": [ {\"x\":5}, {\"x\":7 } ] }"; - ExecuteAddStatement(coll.Add(new DbDoc(docString))); - - Assert.That(ExecuteFindStatement(coll.Find("a in [1,2,3]")).FetchAll(), Has.One.Items); - Assert.That(ExecuteFindStatement(coll.Find("c.e[0] in [1,2,3]")).FetchAll(), Has.One.Items); - Assert.That(ExecuteFindStatement(coll.Find("5 in f[*].x")).FetchAll(), Has.One.Items); - Assert.That(ExecuteFindStatement(coll.Find("3 in c.e")).FetchAll(), Has.One.Items); - CollectionAssert.IsEmpty(ExecuteFindStatement(coll.Find("5 in c.e")).FetchAll()); - CollectionAssert.IsEmpty(ExecuteFindStatement(coll.Find("\"foo\" in " + docString)).FetchAll()); - CollectionAssert.IsEmpty(ExecuteFindStatement(coll.Find("\"a\" in " + docString)).FetchAll()); - CollectionAssert.IsEmpty(ExecuteFindStatement(coll.Find("a in " + docString)).FetchAll()); - Assert.That(ExecuteFindStatement(coll.Find("{\"a\":1} in " + docString)).FetchAll(), Has.One.Items); - Assert.That(ExecuteFindStatement(coll.Find("\"foo\" in b")).FetchAll(), Has.One.Items); - - Collection movies = CreateCollection("movies"); - docString = "{ \"_id\" : \"a6f4b93e1a264a108393524f29546a8c\", \"title\" : \"AFRICAN EGG\", \"description\" : \"A Fast-Paced Documentary of a Pastry Chef And a Dentist who must Pursue a Forensic Psychologist in The Gulf of Mexico\", \"releaseyear\" : 2006, \"language\" : \"English\", \"duration\" : 130, \"rating\" : \"G\", \"genre\" : \"Science fiction\", \"actors\" : [{ \"name\" : \"MILLA PECK\", \"country\" : \"Mexico\", \"birthdate\": \"12 Jan 1984\"}, { \"name\" : \"VAL BOLGER\", \"country\" : \"Botswana\", \"birthdate\": \"26 Jul 1975\" }, { \"name\" : \"SCARLETT BENING\", \"country\" : \"Syria\", \"birthdate\": \"16 Mar 1978\" }], \"additionalinfo\" : { \"director\" : \"Sharice Legaspi\", \"writers\" : [\"Rusty Couturier\", \"Angelic Orduno\", \"Carin Postell\"], \"productioncompanies\" : [\"Qvodrill\", \"Indigoholdings\"] } }"; - ExecuteAddStatement(movies.Add(new DbDoc(docString))); - - Assert.That(ExecuteFindStatement(movies.Find("{ \"name\" : \"MILLA PECK\" } IN actors")).FetchAll(), Has.One.Items); - CollectionAssert.IsEmpty(ExecuteFindStatement(movies.Find("'African Egg' in movietitle")).FetchAll()); - Assert.Throws(() => ExecuteFindStatement(movies.Find("(1 = NULL) IN title")).FetchAll()); - Assert.Throws(() => ExecuteFindStatement(movies.Find("NOT NULL IN title")).FetchAll()); - Assert.That(ExecuteFindStatement(movies.Find("[\"Rusty Couturier\", \"Angelic Orduno\", \"Carin Postell\"] IN additionalinfo.writers")).FetchAll(), Has.One.Items); - Assert.That(ExecuteFindStatement(movies.Find("{ \"name\" : \"MILLA PECK\", \"country\" : \"Mexico\", \"birthdate\": \"12 Jan 1984\"} IN actors")).FetchAll(), Has.One.Items); - CollectionAssert.IsEmpty(ExecuteFindStatement(movies.Find("true IN title")).FetchAll()); - CollectionAssert.IsEmpty(ExecuteFindStatement(movies.Find("false IN genre")).FetchAll()); - Assert.That(ExecuteFindStatement(movies.Find("'Sharice Legaspi' IN additionalinfo.director")).FetchAll(), Has.One.Items); - Assert.That(ExecuteFindStatement(movies.Find("'Mexico' IN actors[*].country")).FetchAll(), Has.One.Items); - Assert.That(ExecuteFindStatement(movies.Find("'Angelic Orduno' IN additionalinfo.writers")).FetchAll(), Has.One.Items); - } - - [Test] - public void InOperatorWithJsonArrays() - { - if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); - - Collection coll = CreateCollection("test"); - var docString = "{ \"_id\": \"1001\", \"ARR\":[1,2,3], \"ARR1\":[\"name\", \"name2\", \"name3\"]}"; - ExecuteAddStatement(coll.Add(new DbDoc(docString))); - - Assert.That(ExecuteFindStatement(coll.Find("\"1001\" in $._id")).FetchAll(), Has.One.Items); - CollectionAssert.IsEmpty(ExecuteFindStatement(coll.Find("\"1002\" in $._id")).FetchAll()); - Assert.That(ExecuteFindStatement(coll.Find("(1+2) in (1, 2, 3)")).FetchAll(), Has.One.Items); - Assert.Throws(() => ExecuteFindStatement(coll.Find("(1+2) in [1, 2, 3]")).FetchAll()); - Assert.Throws(() => ExecuteFindStatement(coll.Find("(1+2) in $.ARR")).FetchAll()); - } - - [Test] - public void GetOne() - { - Collection coll = CreateCollection("test"); - var docs = new[] - { - new { _id = 1, title = "Book 1", pages = 20 }, - new { _id = 2, title = "Book 2", pages = 30 }, - new { _id = 3, title = "Book 3", pages = 40 }, - new { _id = 4, title = "Book 4", pages = 50 }, - }; - Result r = ExecuteAddStatement(coll.Add(docs)); - Assert.AreEqual(4, r.AffectedItemsCount); - - // Expected exceptions. - Assert.Throws(() => coll.GetOne(null)); - Assert.Throws(() => coll.GetOne("")); - Assert.Throws(() => coll.GetOne(string.Empty)); - - // Get document using numeric parameter. - DbDoc document = coll.GetOne(1); - Assert.AreEqual(1, document.Id); - Assert.AreEqual("Book 1", document["title"]); - Assert.AreEqual(20, Convert.ToInt32(document["pages"])); - - // Get document using string parameter. - document = coll.GetOne("3"); - Assert.AreEqual(3, document.Id); - Assert.AreEqual("Book 3", document["title"]); - Assert.AreEqual(40, Convert.ToInt32(document["pages"])); - - // Get a non-existing document. - document = coll.GetOne(5); - Assert.Null(document); - } - - public enum LockMode { Exclusive, Shared } - - [TestCase(LockContention.Default, LockMode.Exclusive)] - [TestCase(LockContention.NoWait, LockMode.Exclusive)] - [TestCase(LockContention.SkipLocked, LockMode.Exclusive)] - [TestCase(LockContention.Default, LockMode.Shared)] - [TestCase(LockContention.NoWait, LockMode.Shared)] - [TestCase(LockContention.SkipLocked, LockMode.Shared)] - public void LockExclusiveAndSharedWithWaitingOptions(LockContention lockOption, LockMode lockMode) - { - if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher."); - - string collectionName = "test"; - var coll = CreateCollection(collectionName); - ExecuteAddStatement(coll.Add(new { _id = 1, name = "Jonh" })); - - // first session locks the row - using (Session s1 = MySQLX.GetSession(ConnectionString)) - { - var coll1 = s1.GetSchema(schemaName).GetCollection(collectionName); - s1.StartTransaction(); - var r1 = ExecuteFindStatement(coll1.Find("_id = :id").Bind("id", 1).LockExclusive()); - Assert.That(r1.FetchAll(), Has.One.Items); - - // second session tries to read the locked row - using (Session s2 = MySQLX.GetSession(ConnectionString)) - { - var coll2 = s2.GetSchema(schemaName).GetCollection(collectionName); - ExecuteSQLStatement(s2.SQL("SET innodb_lock_wait_timeout = 1")); - s2.StartTransaction(); - var stmt2 = coll2.Find("_id = :id").Bind("id", 1); - if (lockMode == LockMode.Exclusive) - stmt2.LockExclusive(lockOption); - else - stmt2.LockShared(lockOption); - - switch (lockOption) - { - case LockContention.Default: - // error 1205 Lock wait timeout exceeded; try restarting transaction - Assert.AreEqual(1205u, Assert.Throws(() => ExecuteFindStatement(stmt2).FetchAll()).Code); - break; - case LockContention.NoWait: - // error 1205 Lock wait timeout exceeded; try restarting transaction - uint expectedError = 1205; - if (session.XSession.GetServerVersion().isAtLeast(8, 0, 5)) - // error 3572 Statement aborted because lock(s) could not be acquired immediately and NOWAIT is set - expectedError = 3572; - Assert.AreEqual(expectedError, Assert.Throws(() => ExecuteFindStatement(stmt2).FetchAll()).Code); - break; - case LockContention.SkipLocked: - if (!session.XSession.GetServerVersion().isAtLeast(8, 0, 5)) - { - // error 1205 Lock wait timeout exceeded; try restarting transaction - Assert.AreEqual(1205u, Assert.Throws(() => ExecuteFindStatement(stmt2).FetchAll()).Code); - break; - } - CollectionAssert.IsEmpty(ExecuteFindStatement(stmt2).FetchAll()); - break; - default: - throw new NotImplementedException(lockOption.ToString()); - } - } - // first session frees the lock - s1.Commit(); - } - } - - [Test] - public void Grouping() - { - ExecuteSQLStatement(GetSession().SQL("SET GLOBAL sql_mode=(SELECT REPLACE(@@sql_mode, 'ONLY_FULL_GROUP_BY', '')); ")); - Collection collection = CreateCollection("test"); - var docs = new[] - { - new { _id = 1, name = "jonh doe", age = 38 }, - new { _id = 2, name = "milton green", age = 45 }, - new { _id = 3, name = "larry smith", age = 24}, - new { _id = 4, name = "mary weinstein", age = 24 }, - new { _id = 5, name = "jerry pratt", age = 45 }, - new { _id = 6, name = "hugh jackman", age = 20}, - new { _id = 7, name = "elizabeth olsen", age = 31} - }; - Result r = ExecuteAddStatement(collection.Add(docs)); - Assert.AreEqual(7, r.AffectedItemsCount); - - // GroupBy operation. - // GroupBy returns 5 rows since age 45 and 24 is repeated. - var result = ExecuteFindStatement(collection.Find().Fields("_id as ID", "name as Name", "age as Age").GroupBy("age")); - Assert.AreEqual(5, result.FetchAll().Count); - - // GroupBy with null. - result = ExecuteFindStatement(collection.Find().Fields("_id as ID", "name as Name", "age as Age").GroupBy(null)); - Assert.AreEqual(7, result.FetchAll().Count); - result = ExecuteFindStatement(collection.Find().Fields("_id as ID", "name as Name", "age as Age").GroupBy(null, null)); - Assert.AreEqual(7, result.FetchAll().Count); - result = ExecuteFindStatement(collection.Find().Fields("_id as ID", "name as Name", "age as Age").GroupBy(null, "age")); - Assert.AreEqual(5, result.FetchAll().Count); - - // Having operation. - // Having reduces the original 5 rows to 3 since 2 rows have a cnt=2, due to the repeated names. - result = ExecuteFindStatement(collection.Find().Fields("_id as ID", "count(name) as cnt", "age as Age").GroupBy("age").Having("cnt = 1")); - Assert.AreEqual(3, result.FetchAll().Count); - - // Having with null. - result = ExecuteFindStatement(collection.Find().Fields("_id as ID", "count(name) as cnt", "age as Age").GroupBy("age").Having(null)); - Assert.AreEqual(5, result.FetchAll().Count); - - // GroupBy with invalid field name. - var ex = Assert.Throws(() => ExecuteFindStatement(collection.Find().Fields("_id as ID", "name as Name", "age as Age").GroupBy("none"))); - Assert.AreEqual("Unknown column 'none' in 'group statement'", ex.Message); - - // GroupBy with empty strings. - var ex2 = Assert.Throws(() => ExecuteFindStatement(collection.Find().Fields("_id as ID", "name as Name", "age as Age").GroupBy(""))); - Assert.AreEqual("No more tokens when expecting one at token pos 0", ex2.Message); - ex2 = Assert.Throws(() => ExecuteFindStatement(collection.Find().Fields("_id as ID", "name as Name", "age as Age").GroupBy(" "))); - Assert.AreEqual("No more tokens when expecting one at token pos 0", ex2.Message); - ex2 = Assert.Throws(() => ExecuteFindStatement(collection.Find().Fields("_id as ID", "name as Name", "age as Age").GroupBy(string.Empty))); - Assert.AreEqual("No more tokens when expecting one at token pos 0", ex2.Message); - - // Having with invalid field name. - ex = Assert.Throws(() => ExecuteFindStatement(collection.Find().Fields("_id as ID", "count(name) as cnt", "age as Age").GroupBy("age").Having("none = 1"))); - Assert.AreEqual("Invalid expression in grouping criteria", ex.Message); - - // Having with empty strings. - ex2 = Assert.Throws(() => ExecuteFindStatement(collection.Find().Fields("_id as ID", "count(name) as cnt", "age as Age").GroupBy("age").Having(""))); - Assert.AreEqual("Unable to parse query ''", ex2.Message); - Assert.AreEqual("No more tokens when expecting one at token pos 0", ex2.InnerException.Message); - ex2 = Assert.Throws(() => ExecuteFindStatement(collection.Find().Fields("_id as ID", "count(name) as cnt", "age as Age").GroupBy("age").Having(" "))); - Assert.AreEqual("Unable to parse query ' '", ex2.Message); - Assert.AreEqual("No more tokens when expecting one at token pos 0", ex2.InnerException.Message); - ex2 = Assert.Throws(() => ExecuteFindStatement(collection.Find().Fields("_id as ID", "count(name) as cnt", "age as Age").GroupBy("age").Having(string.Empty))); - Assert.AreEqual("Unable to parse query ''", ex2.Message); - Assert.AreEqual("No more tokens when expecting one at token pos 0", ex2.InnerException.Message); - } - - [Test] - public void Fields() - { - Collection coll = CreateCollection("test"); - var docs = new[] - { - new { _id = 1, title = "Book 1", pages = 20 }, - new { _id = 2, title = "Book 2", pages = 30 }, - new { _id = 3, title = "Book 3", pages = 40 }, - new { _id = 4, title = "Book 4", pages = 50 }, - }; - Result r = ExecuteAddStatement(coll.Add(docs)); - Assert.AreEqual(4ul, r.AffectedItemsCount); - - // Single field. - var result = ExecuteFindStatement(coll.Find("pages = :Pages").Bind("pAges", 40).Fields("title")); - var document = result.FetchOne(); - Assert.That(document.values, Has.One.Items); - Assert.AreEqual("Book 3", document["title"]); - - // Null values are ignored. - result = ExecuteFindStatement(coll.Find("pages = :Pages").Bind("pAges", 40).Fields(null)); - document = result.FetchOne(); - Assert.AreEqual(3, document.values.Count); - - // Null values are ignored. - result = ExecuteFindStatement(coll.Find("pages = :Pages").Bind("pAges", 40).Fields("title", null)); - document = result.FetchOne(); - Assert.That(document.values, Has.One.Items); - - // Single field in array. - result = ExecuteFindStatement(coll.Find("pages = :Pages").Bind("pAges", 40).Fields(new string[] { "title" })); - document = result.FetchOne(); - Assert.That(document.values, Has.One.Items); - Assert.AreEqual("Book 3", document["title"]); - - // Single field with alias. - result = ExecuteFindStatement(coll.Find("pages = :Pages").Bind("pages", 20).Fields("title as title2")); - document = result.FetchOne(); - Assert.That(document.values, Has.One.Items); - Assert.AreEqual("Book 1", document["title2"]); - Assert.False(document.values.ContainsKey("title")); - - // Unexistent field returns null. - result = ExecuteFindStatement(coll.Find("pages = :Pages").Bind("pages", 20).Fields("book")); - document = result.FetchOne(); - Assert.That(document.values, Has.One.Items); - Assert.Null(document["book"]); - - // Unexistent field with alias returns null. - result = ExecuteFindStatement(coll.Find("pages = :Pages").Bind("pages", 20).Fields("book as book1")); - document = result.FetchOne(); - Assert.That(document.values, Has.One.Items); - Assert.Null(document["book1"]); - - // Multiple fields. - result = ExecuteFindStatement(coll.Find("pages = :Pages").Bind("pAges", 40).Fields("title", "pages", "other")); - document = result.FetchOne(); - Assert.AreEqual(3, document.values.Count); - Assert.AreEqual("Book 3", document["title"]); - Assert.AreEqual(40, document["pages"]); - Assert.Null(document["other"]); - - // Multiple fields in array. - result = ExecuteFindStatement(coll.Find("pages = :Pages").Bind("pAges", 40).Fields(new string[] { "title", "pages" })); - document = result.FetchOne(); - Assert.AreEqual(2, document.values.Count); - Assert.AreEqual("Book 3", document["title"]); - Assert.AreEqual(40, document["pages"]); - - // Sending a document doesn't generate an error. - result = ExecuteFindStatement(coll.Find("pages = :Pages").Bind("pages", 20).Fields("{\"_id\":\"1004\",\"F1\": 1234 }")); - document = result.FetchOne(); - - // Empty string and white space raises error. - var ex = Assert.Throws(() => ExecuteFindStatement(coll.Find("pages = :Pages").Bind("pAges", 40).Fields(""))); - Assert.AreEqual("No more tokens when expecting one at token pos 0", ex.Message); - ex = Assert.Throws(() => ExecuteFindStatement(coll.Find("pages = :Pages").Bind("pAges", 40).Fields(" "))); - Assert.AreEqual("No more tokens when expecting one at token pos 0", ex.Message); - ex = Assert.Throws(() => ExecuteFindStatement(coll.Find("pages = :Pages").Bind("pAges", 40).Fields(string.Empty))); - Assert.AreEqual("No more tokens when expecting one at token pos 0", ex.Message); - - // Multiple word field name raises error. - ex = Assert.Throws(() => result = ExecuteFindStatement(coll.Find("pages = :Pages").Bind("pAges", 40).Fields("Book 1"))); - Assert.AreEqual("Expression has unexpected token '1' at position 1.", ex.Message); - } - - [TestCase("", "")] - [TestCase("'", "'")] - [TestCase("", "'")] - [TestCase("'", "")] - public void FindIdAsString(string prefix, string suffix) - { - Collection coll = CreateCollection("test"); - Result r = null; - var docs = new[] - { - new { _id = $"{prefix}1{suffix}", title = $"{prefix}Book 1{suffix}", pages = 20 }, - new { _id = $"{prefix}2{suffix}", title = $"{prefix}Book 2{suffix}", pages = 30 }, - new { _id = $"{prefix}3{suffix}", title = $"{prefix}Book 3{suffix}", pages = 40 }, - new { _id = $"{prefix}4{suffix}", title = $"{prefix}Book 4{suffix}", pages = 50 }, - }; - r = coll.Add(docs).Execute(); - Assert.AreEqual(4, r.AffectedItemsCount); - - var findStmt = coll.Find("_id = :id and pages = :pages").Bind("id", $"{prefix}3{suffix}").Bind("pages", 40); - var doc = ExecuteFindStatement(findStmt); - var books = doc.FetchAll(); - Assert.That(books, Has.One.Items); - Assert.AreEqual($"{prefix}3{suffix}", books[0]["_id"]); - - findStmt = coll.Find("_id = :id and pages = :pages").Bind("Id", $"{prefix}2{suffix}").Bind("Pages", 30); - doc = ExecuteFindStatement(findStmt); - books = doc.FetchAll(); - Assert.That(books, Has.One.Items); - Assert.AreEqual($"{prefix}2{suffix}", books[0]["_id"]); - - findStmt = coll.Find("title = :title").Bind("Title", $"{prefix}Book 4{suffix}"); - doc = ExecuteFindStatement(findStmt); - books = doc.FetchAll(); - Assert.That(books, Has.One.Items); - Assert.AreEqual($"{prefix}4{suffix}", books[0]["_id"]); - Assert.AreEqual(50, books[0]["pages"]); - } - - [TestCase(":hobbies IN $.additionalinfo.hobbies", "hobbies", "painting", 4)] - [TestCase(":hobbies IN $.additionalinfo.hobbies", "hobbies", "[\"playing\", \"listening\"]", 0)] - [TestCase("[\"playing\", \"listening\"] IN $.additionalinfo.hobbies", null, null, 3)] - public void InOperatorBindingJson(string condition, string bind, string value, int id) - { - Collection coll = CreateCollection("test"); - Result r = null; - var docs = new[] - { - new { _id = 1, title = $"Book 1", pages = 20, additionalinfo = new DbDoc("{\"company\":\"xyz\",\"vehicle\":\"bike\",\"hobbies\":\"reading\"}") }, - new { _id = 2, title = $"Book 2", pages = 30, additionalinfo = new DbDoc("{\"company\":\"abc\",\"vehicle\":\"car\",\"hobbies\":\"boxing\"}") }, - new { _id = 3, title = $"Book 3", pages = 40, additionalinfo = new DbDoc("{\"company\":\"qwe\",\"vehicle\":\"airplane\",\"hobbies\":[\"playing\", \"listening\"]}") }, - new { _id = 4, title = $"Book 4", pages = 50, additionalinfo = new DbDoc("{\"company\":\"zxc\",\"vehicle\":\"boat\",\"hobbies\":\"painting\"}") }, - }; - r = coll.Add(docs).Execute(); - Assert.AreEqual(4, r.AffectedItemsCount); - - var findStmt = coll.Find(condition); - if (bind != null) findStmt.Bind(bind, value); - var result = findStmt.Execute().FetchAll(); - Assert.AreEqual(id == 0 ? 0 : 1, result.Count); - if (id > 0) - { - Assert.AreEqual(id, result[0]["_id"]); - } - } - - [Test] - public void FindUsingOverlaps() - { - Collection coll = CreateCollection("test"); - - coll.Add("{ \"_id\":1, \"title\": \"Book 1\", \"list\":[1, 4]}").Execute(); - coll.Add("{ \"_id\":2, \"title\": \"Book 2\", \"list\":[5, 7]}").Execute(); - coll.Add("{ \"_id\":3, \"title\": \"Book 3\", \"list\":[4, 9]}").Execute(); - coll.Add("{ \"_id\":4, \"title\": \"Book 4\", \"list\":[2]}").Execute(); - coll.Add("{ \"_id\":5, \"title\": \"Book 5\",\"list\":[\"\"]}").Execute(); - coll.Add("{ \"_id\":6, \"title\": \"Book 6\",\"list\":[\" \"]}").Execute(); - - var result = ExecuteFindStatement(coll.Find("[7] OVERLAPS $.list")).FetchAll(); - Assert.AreEqual("Book 2", result[0]["title"]); - result = ExecuteFindStatement(coll.Find("[8] overlaps $.list")).FetchAll(); - CollectionAssert.IsEmpty(result); - result = ExecuteFindStatement(coll.Find("[1, 4] OVERLAPS $.list")).FetchAll(); - CollectionAssert.IsNotEmpty(result); - Assert.AreEqual("Book 1", result[0]["title"]); - Assert.AreEqual("Book 3", result[1]["title"]); - result = ExecuteFindStatement(coll.Find("$.list OVERLAPS [1, 2]")).FetchAll(); - CollectionAssert.IsNotEmpty(result); - Assert.AreEqual("Book 1", result[0]["title"]); - Assert.AreEqual("Book 4", result[1]["title"]); - result = ExecuteFindStatement(coll.Find("'Book 1' NOT OVERLAPS $.title").Fields("_id")).FetchAll(); - Assert.AreEqual(5, result.Count); - Assert.AreEqual(3, result[1].Id); - result = ExecuteFindStatement(coll.Find(":title NOT OVERLAPS $.title").Bind("title", "Book 1").Fields("_id")).FetchAll(); - Assert.AreEqual(5, result.Count); - Assert.AreEqual(4, result[2].Id); - result = ExecuteFindStatement(coll.Find("$.list OVERLAPS :list").Bind("list", 9)).FetchAll(); - Assert.AreEqual("Book 3", result[0]["title"]); - var jsonParams = new { list = 4 }; - result = ExecuteFindStatement(coll.Find("$.list OVERLAPS :list").Bind(jsonParams).Fields("count(_id) as ID", "title as Title", "list as List"). - GroupBy("title", "list").Having("ID > 0")).FetchAll(); - Assert.AreEqual(2, result.Count); - Assert.AreEqual("Book 1", result[0]["Title"]); - result = ExecuteFindStatement(coll.Find("[''] OVERLAPS $.list")).FetchAll(); - Assert.That(result, Has.One.Items); - Assert.AreEqual(5, result[0].Id); - result = ExecuteFindStatement(coll.Find("[' '] OVERLAPS $.list")).FetchAll(); - Assert.That(result, Has.One.Items); - Assert.AreEqual(6, result[0].Id); - - Assert.Throws(() => ExecuteFindStatement(coll.Find("$.list OVERLAPS -")).FetchAll()); - Assert.Throws(() => ExecuteFindStatement(coll.Find("[2, 9] OVERLAPS")).FetchAll()); - Assert.Throws(() => ExecuteFindStatement(coll.Find("[2, 9] OVERPS $.list")).FetchAll()); - } - - #region WL14389 - - [Test, Description("Collection.Find(condition).GroupBy(SearchExprStr).Having(SearchConditionStr)")] - public void FindGroupByHaving() - { - ExecuteSQLStatement(GetSession().SQL("set sql_mode = 'STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION';")); - - Collection collection = CreateCollection("test"); - var docs1 = new[] - { - new { _id = 1, name = "jonh doe", age = 38,profit = 100,test = 1.92,date="21/11/2011" }, - new { _id = 2, name = "milton green", age = 45,profit = 200,test = 12.08,date="21/11/2012" }, - new { _id = 3, name = "larry smith", age = 24,profit = 300,test = 12.1,date="21/11/2013" }, - new { _id = 4, name = "mary weinstein", age = 24 ,profit = 100,test = 12.0,date="21/11/2014" }, - new { _id = 5, name = "jerry pratt", age = 45 ,profit = 400,test = 20.87,date="21/11/2015" }, - new { _id = 6, name = "hugh jackman", age = 20,profit = 500,test = 20.65,date="21/11/2016"}, - new { _id = 7, name = "elizabeth olsen", age = 31,profit = 300,test = 20.45,date="21/11/2017" }, - new { _id = 8, name = "tommy h", age = 31,profit = 3000,test = 0.0,date="21/11/2018"} - }; - - Result r = collection.Add(docs1).Execute(); - Assert.AreEqual(8, r.AffectedItemsCount); - - // GroupBy operation. - // GroupBy returns 5 rows since age 45 and 24 is repeated. - var result = collection.Find().Fields("_id as ID", "name as Name", "age as Age").GroupBy("age").Execute(); - Assert.AreEqual(5, result.FetchAll().Count); - result = collection.Find().Fields("_id as ID", "name as Name", "profit as Profit", "test as test").GroupBy("test").Having("test=1.92").Execute(); - Assert.AreEqual(1, result.FetchAll().Count); - result = collection.Find().Fields("max($.age) as age", "max($.profit) as Profit", "max($.test) as test").GroupBy("$.test").Having("max($.age)>=31"). - Sort("profit DESC").Execute(); - Assert.AreEqual(result.FetchAll().Count, result.FetchAll().Count); - result = collection.Find().Fields("max($.age) as age", "max($.profit) as Profit", "max($.test) as test").GroupBy("$.test").Having("max($.age)>30 && max($.age)<32") - .Execute(); - Assert.AreEqual(2, result.FetchAll().Count); - result = collection.Find().Fields("max($.age) as age", "max($.profit) as Profit", "max($.test) as test").GroupBy("$.test").Having("max($.age)>300000000") - .Execute(); - Assert.AreEqual(0, result.FetchAll().Count); - - result = collection.Find().Fields("max($.age) as age", "max($.profit) as Profit", "max($.test) as test").GroupBy("$.test").Having("max($.age)>30"). - Having("max($.age)<32") - .Execute(); - Assert.AreEqual(5, result.FetchAll().Count); - - result = collection.Find().Fields("max($.age) as age", "max($.profit) as Profit", "max($.test) as test").GroupBy("$.test").Having("max($.age)>30"). - Having("max($.age)<32").Limit(5) - .Execute(); - Assert.AreEqual(5, result.FetchAll().Count); - - result = collection.Find().Fields("max($.age) as age", "max($.profit) as Profit", "max($.test) as test").GroupBy("$.test").Having("max($.age)>30"). - Having("max($.age)<32").Limit(3) - .Execute(); - Assert.AreEqual(3, result.FetchAll().Count); - - result = collection.Find().Fields("max($.age) as age", "max($.profit) as Profit", "max($.test) as test").GroupBy("$.test").Having("max($.age)>30"). - Having("max($.age)<32").Limit(3).Offset(2) - .Execute(); - Assert.AreEqual(3, result.FetchAll().Count); - - Assert.Throws(() => collection.Find().Fields("max($.age) as age", "max($.profit) as Profit", "max($.test) as test").GroupBy("$.test").Having("date=21/11/2011").Execute()); - } - - [Test, Description("Collection.Find().Limit(x).Offset(y)")] - public void FindLimitOffset() - { - ExecuteSQLStatement(GetSession().SQL("set sql_mode = 'STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION';")); - - Collection collection = CreateCollection("test"); - var docs1 = new[] - { - new { _id = 1, name = "jonh doe", age = 38,profit = 100,test = 1.92,date="21/11/2011" }, - new { _id = 2, name = "milton green", age = 45,profit = 200,test = 12.08,date="21/11/2012" }, - new { _id = 3, name = "larry smith", age = 24,profit = 300,test = 12.1,date="21/11/2013" }, - new { _id = 4, name = "mary weinstein", age = 24 ,profit = 100,test = 12.0,date="21/11/2014" }, - new { _id = 5, name = "jerry pratt", age = 45 ,profit = 400,test = 20.87,date="21/11/2015" }, - new { _id = 6, name = "hugh jackman", age = 20,profit = 500,test = 20.65,date="21/11/2016"}, - new { _id = 7, name = "elizabeth olsen", age = 31,profit = 300,test = 20.45,date="21/11/2017" }, - new { _id = 8, name = "tommy h", age = 31,profit = 3000,test = 0.0,date="21/11/2018"} - }; - - Result r = collection.Add(docs1).Execute(); - Assert.AreEqual(8, r.AffectedItemsCount); - - // GroupBy operation. - // GroupBy returns 5 rows since age 45 and 24 is repeated. - var result1 = collection.Find().Limit(2).Offset(-2378723).Execute(); - int k = result1.FetchAll().Count; - result1 = collection.Find().Limit(2).Offset(-1).Execute(); - k = result1.FetchAll().Count; - result1 = collection.Find().Limit(2).Offset(0).Execute(); - k = result1.FetchAll().Count; - - var result = collection.Find().Fields("_id as ID", "name as Name", "age as Age").GroupBy("age").Execute(); - Assert.AreEqual(5, result.FetchAll().Count); - result = collection.Find().Fields("_id as ID", "name as Name", "profit as Profit", "test as test").GroupBy("test").Having("test=1.92").Execute(); - Assert.AreEqual(1, result.FetchAll().Count); - result = collection.Find().Fields("max($.age) as age", "max($.profit) as Profit", "max($.test) as test").GroupBy("$.test").Having("max($.age)>=31"). - Sort("profit DESC").Execute(); - Assert.AreEqual(result.FetchAll().Count, result.FetchAll().Count); - result = collection.Find().Fields("max($.age) as age", "max($.profit) as Profit", "max($.test) as test").GroupBy("$.test").Having("max($.age)>30 && max($.age)<32") - .Execute(); - Assert.AreEqual(2, result.FetchAll().Count); - result = collection.Find().Fields("max($.age) as age", "max($.profit) as Profit", "max($.test) as test").GroupBy("$.test").Having("max($.age)>300000000") - .Execute(); - Assert.AreEqual(0, result.FetchAll().Count); - - result = collection.Find().Fields("max($.age) as age", "max($.profit) as Profit", "max($.test) as test").GroupBy("$.test").Having("max($.age)>30"). - Having("max($.age)<32") - .Execute(); - Assert.AreEqual(5, result.FetchAll().Count); - - result = collection.Find().Fields("max($.age) as age", "max($.profit) as Profit", "max($.test) as test").GroupBy("$.test").Having("max($.age)>30"). - Having("max($.age)<32").Limit(5) - .Execute(); - Assert.AreEqual(5, result.FetchAll().Count); - - result = collection.Find().Fields("max($.age) as age", "max($.profit) as Profit", "max($.test) as test").GroupBy("$.test").Having("max($.age)>30"). - Having("max($.age)<32").Limit(3) - .Execute(); - Assert.AreEqual(3, result.FetchAll().Count); - - result = collection.Find().Fields("max($.age) as age", "max($.profit) as Profit", "max($.test) as test").GroupBy("$.test").Having("max($.age)>30"). - Having("max($.age)<32").Limit(3).Offset(2) - .Execute(); - Assert.AreEqual(3, result.FetchAll().Count); - - result = collection.Find().Fields("$._id as _id", "$.test as test").GroupBy("$.test").Limit(5).Offset(1).Execute(); - Assert.AreEqual(5, result.FetchAll().Count); - - result = collection.Find().Fields("$._id as _id", "$.test as test").GroupBy("$.test").Limit(5).Offset(-1).Execute(); - Assert.AreEqual(5, result.FetchAll().Count); - - result = collection.Find().Fields("$._id as _id", "$.test as test").GroupBy("$.test").Limit(8).Execute(); - Assert.AreEqual(8, result.FetchAll().Count); - - result = collection.Find().Fields("max($.age) as age", "max($.profit) as Profit", "max($.test) as test").GroupBy("$.test").Having("max($.age)>30"). - Having("max($.age)<32").Limit(3).Offset(-1) - .Execute(); - Assert.AreEqual(3, result.FetchAll().Count); - - Assert.Throws(() => collection.Find().Fields("max($.age) as age", "max($.profit) as Profit", "max($.test) as test").GroupBy("$.test").Having("max($.age)>30"). - Having("max($.age)<32").Limit(-1).Offset(0) - .Execute()); - - DbDoc[] jsonlist = new DbDoc[2000]; - for (int i = 0; i < 2000; i++) - { - DbDoc newDoc2 = new DbDoc(); - newDoc2.SetValue("_id", (i + 1000).ToString()); - newDoc2.SetValue("F1", ("Field-1-Data-" + i)); - newDoc2.SetValue("F2", ("Field-2-Data-" + i)); - newDoc2.SetValue("F3", (300 + i).ToString()); - jsonlist[i] = newDoc2; - newDoc2 = null; - } - var res = collection.Add(jsonlist).Execute(); - - result = collection.Find().Fields("$.F1 as F1", "$.F2 as F2").GroupBy("$.F1").Limit(3).Offset(1).Execute(); - Assert.AreEqual(3, result.FetchAll().Count); - - result = collection.Find().Fields("$.F1 as F1", "$.F2 as F2").GroupBy("$.F1").Limit(3).Offset(1844674407370955161).Execute(); - Assert.AreEqual(0, result.FetchAll().Count); - } - - [Test, Description("Collection.Find().Limit(x,y)")] - public void FindLimitOffsetDeprecated() - { - ExecuteSQLStatement(GetSession().SQL("set sql_mode = 'STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION';")); - Collection collection = CreateCollection("test"); - var docs1 = new[] - { - new { _id = 1, name = "jonh doe", age = 38,profit = 100,test = 1.92,date="21/11/2011" }, - new { _id = 2, name = "milton green", age = 45,profit = 200,test = 12.08,date="21/11/2012" }, - new { _id = 3, name = "larry smith", age = 24,profit = 300,test = 12.1,date="21/11/2013" }, - new { _id = 4, name = "mary weinstein", age = 24 ,profit = 100,test = 12.0,date="21/11/2014" }, - new { _id = 5, name = "jerry pratt", age = 45 ,profit = 400,test = 20.87,date="21/11/2015" }, - new { _id = 6, name = "hugh jackman", age = 20,profit = 500,test = 20.65,date="21/11/2016"}, - new { _id = 7, name = "elizabeth olsen", age = 31,profit = 300,test = 20.45,date="21/11/2017" }, - new { _id = 8, name = "tommy h", age = 31,profit = 3000,test = 0.0,date="21/11/2018"} - }; - - Result r = collection.Add(docs1).Execute(); - Assert.AreEqual(8, r.AffectedItemsCount); - - // GroupBy operation. - var result1 = collection.Find().Limit(2).Offset(-2378723).Execute(); - int k = result1.FetchAll().Count; - result1 = collection.Find().Limit(2).Offset(-1).Execute(); - k = result1.FetchAll().Count; - result1 = collection.Find().Limit(2).Offset(0).Execute(); - k = result1.FetchAll().Count; - result1 = collection.Find().Limit(2).Offset(1000000000).Execute(); - k = result1.FetchAll().Count; - collection.Remove("true").Limit(2).Execute(); - - docs1 = new[] - { - new { _id = 1, name = "jonh doe", age = 38,profit = 100,test = 1.92,date="21/11/2011" }, - new { _id = 2, name = "milton green", age = 45,profit = 200,test = 12.08,date="21/11/2012" }, - }; - - r = collection.Add(docs1).Execute(); - Assert.Throws(() => collection.Remove("true").Limit(2).Offset(1).Execute()); - - collection.Remove("true").Limit(2).Offset(0).Execute(); - docs1 = new[] - { - new { _id = 1, name = "jonh doe", age = 38,profit = 100,test = 1.92,date="21/11/2011" }, - new { _id = 2, name = "milton green", age = 45,profit = 200,test = 12.08,date="21/11/2012" }, - }; - - r = collection.Add(docs1).Execute(); - Assert.Throws(() => collection.Modify("_id = 1 || _id = 2").Set("age", 34).Limit(1).Offset(1).Execute()); - - collection.Modify("_id = 1 || _id = 2").Set("age", 34).Limit(2).Offset(0).Execute(); - collection.Modify("_id = 1").Set("age", 38).Limit(2).Offset(0).Execute(); - collection.Modify("_id = 2").Set("age", 45).Limit(2).Offset(0).Execute(); - - var result = collection.Find().Fields("max($.age) as age", "max($.profit) as Profit", "max($.test) as test").GroupBy("$.test").Having("max($.age)>30"). - Having("max($.age)<32").Limit(3).Offset(2) - .Execute(); - Assert.AreEqual(3, result.FetchAll().Count); - - result = collection.Find().Fields("$._id as _id", "$.test as test").GroupBy("$.test").Limit(5).Offset(1).Execute(); - Assert.AreEqual(5, result.FetchAll().Count); - result = collection.Find().Fields("$._id as _id", "$.test as test").GroupBy("$.test").Limit(5).Offset(-1).Execute(); - Assert.AreEqual(5, result.FetchAll().Count); - - result = collection.Find().Fields("max($.age) as age", "max($.profit) as Profit", "max($.test) as test").GroupBy("$.test").Having("max($.age)>30"). - Having("max($.age)<32").Limit(3).Offset(-1) - .Execute(); - Assert.AreEqual(3, result.FetchAll().Count); - - Assert.Throws(() => collection.Find().Fields("max($.age) as age", "max($.profit) as Profit", "max($.test) as test").GroupBy("$.test").Having("max($.age)>30"). - Having("max($.age)<32").Limit(-1).Offset(0) - .Execute()); - } - - [Test, Description("Test MySQLX plugin Collection Dbdoc Scenarios")] - public void CollectionDbdoc() - { - Collection col = CreateCollection("my_collection_1"); - Collection col1 = CreateCollection("my_collection_2"); - var d1 = new DbDoc(); - d1.SetValue("_id", 1); - var docs1 = new[] - { - new { _id = 1, title = "Book 1" }, - new { _id = 2, title = "Book 2" }, - }; - - d1.SetValue("books", docs1); - d1.SetValue("pages", 20); - - var d2 = new DbDoc(); - d2.SetValue("_id", 2); - var docs2 = new[] - { - new { _id = 1, title = "Book 3" }, - new { _id = 2, title = "Book 4" }, - }; - - d2.SetValue("books", docs2); - d2.SetValue("pages", 30); - - var d3 = new DbDoc(); - d3.SetValue("_id", 3); - var docs3 = new[] - { - new { _id = 1, title = "Book 3" }, - new { _id = 2, title = "Book 4" }, - }; - - d3.SetValue("books", docs3); - d3.SetValue("pages", 40); - col.Add(d1).Add(d2).Add(d3).Execute(); - string[] test1 = new string[] { "_id=1" }; - string[] test2 = new string[] { "_id=2" }; - var res = col.Find("$._id = 1").Execute().FetchAll(); - Assert.AreEqual(1, res.Count, "Matching the find count"); - Assert.AreEqual(d1.ToString(), res[0].ToString(), "Matching the string"); - res = col.Find("$._id = 2").Execute().FetchAll(); - Assert.AreEqual(1, res.Count, "Matching the find count"); - Assert.AreEqual(d2.ToString(), res[0].ToString(), "Matching the string"); - res = col.Find("$._id = 3").Execute().FetchAll(); - Assert.AreEqual(1, res.Count, "Matching the find count"); - Assert.AreEqual(d3.ToString(), res[0].ToString(), "Matching the string"); - - } - - [Test, Description("Test MySQLX plugin Collection Dbdoc Scenarios - ID Present DbDoc Blank")] - public void CollectionIDPresentDbdocBlank() - { - Collection col = CreateCollection("my_collection_1"); - Collection col1 = CreateCollection("my_collection_2"); - var d1 = new DbDoc(); - d1.SetValue("_id", 1); - string[] a = { String.Empty }; - d1.SetValue("books", a); - d1.SetValue("pages", 20); - - var d2 = new DbDoc(); - d2.SetValue("_id", 2); - d2.SetValue("books", a); - d2.SetValue("pages", 30); - - var d3 = new DbDoc(); - d3.SetValue("_id", 3); - d3.SetValue("books", a); - d3.SetValue("pages", 40); - - col.Add(d1).Add(d2).Add(d3).Execute(); - string[] test1 = new string[] { "_id=1" }; - string[] test2 = new string[] { "_id=2" }; - var res = col.Find("$._id = 1").Execute().FetchAll(); - Assert.AreEqual(1, res.Count, "Matching the find count"); - Assert.AreEqual(d1.ToString(), res[0].ToString(), "Matching the string"); - res = col.Find("$._id = 2").Execute().FetchAll(); - Assert.AreEqual(1, res.Count, "Matching the find count"); - Assert.AreEqual(d2.ToString(), res[0].ToString(), "Matching the string"); - res = col.Find("$._id = 3").Execute().FetchAll(); - Assert.AreEqual(1, res.Count, "Matching the find count"); - Assert.AreEqual(d3.ToString(), res[0].ToString(), "Matching the string"); - } - - /// - /// Bug 23542055 - /// - [Test, Description("Test MySQLX plugin Find with Many conditions")] - [Ignore("Uncomment to execute")] - public void FindWithManyConditions() - { - int i = 0; - int Condition = 49; - String query = ""; - var col = CreateCollection("my_collection_1"); - - col.Add("{\"_id\":\"1002\",\"TEST1\":1111}").Execute(); - for (i = 0; i < Condition; i++) - { - if (i > 0) - query = query + " OR "; - query = query + "$.TEST1 > " + i; - } - var docs = col.Find(query).Execute(); - } - - [TestCase(1)] - [TestCase(2)] - [TestCase(3)] - [TestCase(4)] - [Test, Description("Reading exclusively locked anonymous object array using LockShared without waiting option. ")] - public void ExclusiveLocksAndCommit(int scenario) - { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher"); - - ExecuteSQLStatement(session.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); - using (var session2 = MySQLX.GetSession(ConnectionString)) - { - ExecuteSQLStatement(session2.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); - Collection coll = CreateCollection("test"); - ExecuteSQLStatement(session2.SQL("ALTER TABLE `test`.`test` ADD COLUMN `$ix_i_r_index` INT GENERATED ALWAYS AS (JSON_UNQUOTE(JSON_EXTRACT(doc, '$._id'))) VIRTUAL NOT NULL, ADD UNIQUE INDEX `myIndex`(`$ix_i_r_index`)")); - Result result1 = null; - switch (scenario) - { - case 1: // Anonymous Object - var docs = new[] - { - new {_id = 1, a = 1}, - new {_id = 2, a = 2}, - new {_id = 3, a = 3} - }; - coll.Add(docs).Execute(); - break; - case 2: // DbDoc - for (int i = 0; i < 3; i++) - { - DbDoc DbDocs = new DbDoc(); - DbDocs.SetValue("_id", i); - DbDocs.SetValue("a", i); - result1 = coll.Add(DbDocs).Execute(); - } - break; - case 3: // Chained Add - var docs1 = new { _id = 1, title = "Book 1", pages = 20, a = 1 }; - var docs2 = new { _id = 2, title = "Book 1", pages = 20, a = 2 }; - var docs3 = new { _id = 3, title = "Book 1", pages = 20, a = 3 }; - result1 = coll.Add(docs1).Add(docs2).Add(docs3).Execute(); - break; - case 4: //Json string - result1 = coll.Add(@"{ ""_id"": 1,""a"": 1 }", @"{""_id"": 2,""a"": 2 }", @"{""_id"": 3, ""a"": 3 }", @"{ ""_id"": 4,""a"": 4 }").Execute(); - break; - } - - var coll2 = session2.GetSchema("test").GetCollection("test"); - session.SQL("START TRANSACTION").Execute(); - var docResult = coll.Find("_id = 1").LockExclusive().Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); - - session2.SQL("START TRANSACTION").Execute(); - // Should return immediately since document isn't locked. - docResult = coll2.Find("_id = 2").LockExclusive().Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); - - // Session2 blocks due to to LockExclusive() not allowing to read locked documents. - session2.SQL("SET SESSION innodb_lock_wait_timeout=1").Execute(); - Exception ex = Assert.Throws(() => ExecuteFindStatement(coll2.Find("_id = :id").LockExclusive().Bind("id", 1))); - - Assert.Throws(() => ExecuteModifyStatement(coll2.Modify("a = 1").Change("a", 10))); - - session.Commit(); - var result = coll2.Modify("a = 1").Set("a", 12).Execute(); - Assert.AreEqual(1, result.AffectedItemsCount); - session.SQL("ROLLBACK").Execute(); - session2.SQL("ROLLBACK").Execute(); - } - } - - [TestCase(null)] - [TestCase(LockMode.Shared)] - [TestCase(LockMode.Exclusive)] - [Test, Description("Reading a document which was locked using lock_shared without waiting option")] - public void SharedLockAndCommit(LockMode? lockMode) - { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher"); - ExecuteSQLStatement(session.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); - using (var session2 = MySQLX.GetSession(ConnectionString)) - { - ExecuteSQLStatement(session2.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); - Collection coll = CreateCollection("test"); - session2.SQL("ALTER TABLE `test`.`test` ADD COLUMN `$ix_i_r_index` INT GENERATED ALWAYS AS (JSON_UNQUOTE(JSON_EXTRACT(doc, '$._id'))) VIRTUAL NOT NULL, ADD UNIQUE INDEX `myIndex`(`$ix_i_r_index`)").Execute(); - var docs = new[] - { - new {_id = 1, a = 1}, - new {_id = 2, a = 2}, - new {_id = 3, a = 3} - }; - - coll.Add(docs).Execute(); - var coll2 = session2.GetSchema("test").GetCollection("test"); - - session.SQL("START TRANSACTION").Execute(); - var docResult = coll.Find("_id = 1").LockShared().Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); - - session2.SQL("START TRANSACTION").Execute(); - // Should return immediately since document isn't locked. - switch (lockMode) - { - case LockMode.Shared: - docResult = coll2.Find("_id = 2").LockShared().Execute(); - break; - case LockMode.Exclusive: - docResult = coll2.Find("_id = 2").LockExclusive().Execute(); - break; - default: - docResult = coll2.Find("_id = 2").Execute(); - break; - } - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); - - // Session2 returns immediately. - session2.SQL("SET SESSION innodb_lock_wait_timeout=1").Execute(); - docResult = coll2.Find("_id = :id").Bind("id", 1).Execute(); - Assert.That(docResult.FetchAll(), Has.One.Items); - - // Session2 blocks due to to LockShared() not allowing to modify locked documents. - Exception ex = Assert.Throws(() => ExecuteModifyStatement(coll2.Modify("a = 1").Change("a", 10))); - - // Session2 returns immediately as session is committed. - session.Commit(); - var result = coll2.Modify("a = 1").Set("a", 12).Execute(); - Assert.AreEqual(1, result.AffectedItemsCount); - - session.SQL("ROLLBACK").Execute(); - session2.SQL("ROLLBACK").Execute(); - } - } - - [TestCase(LockMode.Shared)] - [TestCase(LockMode.Exclusive)] - [Test, Description("Reading a document using lock_shared using SKIPLOCK and NOWAIT options with CRUD operations happening parallely.")] - public void SharedAndExclusiveLockWithSkipAndNoWait(LockMode lockMode) - { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher"); - ExecuteSQLStatement(session.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); - using (var session2 = MySQLX.GetSession(ConnectionString)) - { - ExecuteSQLStatement(session2.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); - Collection coll = CreateCollection("test"); - session2.SQL("ALTER TABLE `test`.`test` ADD COLUMN `$ix_i_r_index` INT GENERATED ALWAYS AS (JSON_UNQUOTE(JSON_EXTRACT(doc, '$._id'))) VIRTUAL NOT NULL, ADD UNIQUE INDEX `myIndex`(`$ix_i_r_index`)").Execute(); - if (lockMode == LockMode.Shared) - session2.SQL("ALTER TABLE `test`.`test` ADD COLUMN `$ix_i_m_index` INT GENERATED ALWAYS AS (JSON_UNQUOTE(JSON_EXTRACT(doc, '$.a'))) VIRTUAL NOT NULL, ADD UNIQUE INDEX `myIndex1`(`$ix_i_m_index`)").Execute(); - - var docs = new[] - { - new {_id = 1, a = 1}, - new {_id = 2, a = 2}, - new {_id = 3, a = 3} - }; - - coll.Add(docs).Execute(); - var coll2 = session2.GetSchema("test").GetCollection("test"); - - session.SQL("START TRANSACTION").Execute(); - var result1 = coll.Modify("a = 1").Set("a", 10).Execute(); - - session2.SQL("START TRANSACTION").Execute(); - session2.SQL("SET SESSION innodb_lock_wait_timeout=1").Execute(); - DocResult docResult = null; - switch (lockMode) - { - case LockMode.Exclusive: - Assert.Throws(() => ExecuteFindStatement(coll2.Find("_id = :id").LockExclusive(LockContention.NoWait).Bind("id", 1))); - docResult = coll2.Find("_id = :id").LockExclusive(LockContention.SkipLocked).Bind("id", 1).Execute(); - break; - case LockMode.Shared: - Assert.Throws(() => ExecuteFindStatement(coll2.Find("_id = :id").LockShared(LockContention.NoWait).Bind("id", 1))); - docResult = coll2.Find("_id = :id").LockShared(LockContention.SkipLocked).Bind("id", 1).Execute(); - break; - } - Assert.AreEqual(0, docResult.FetchAll().Count, "Matching the document ID"); - - session.SQL("ROLLBACK").Execute(); - session2.SQL("ROLLBACK").Execute(); - } - } - - [Test, Description("Multiple lock calls using NOWAIT and SKIPLOCK waiting option. ")] - public void MultipleLocksWithNowaitAndSkiplock() - { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher"); - ExecuteSQLStatement(session.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); - using (var session2 = MySQLX.GetSession(ConnectionString)) - { - ExecuteSQLStatement(session2.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); - Collection coll = CreateCollection("test"); - session2.SQL("ALTER TABLE `test`.`test` ADD COLUMN `$ix_i_r_index` INT GENERATED ALWAYS AS (JSON_UNQUOTE(JSON_EXTRACT(doc, '$._id'))) VIRTUAL NOT NULL, ADD UNIQUE INDEX `myIndex`(`$ix_i_r_index`)").Execute(); - var docs = new[] - { - new {_id = 1, a = 1}, - new {_id = 2, a = 2}, - new {_id = 3, a = 3} - }; - - coll.Add(docs).Execute(); - var coll2 = session2.GetSchema("test").GetCollection("test"); - - session.SQL("START TRANSACTION").Execute(); - var docResult = coll.Find("_id = 1").LockShared().Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); - - session2.SQL("START TRANSACTION").Execute(); - - session2.SQL("SET SESSION innodb_lock_wait_timeout=1").Execute(); - Assert.Throws(() => ExecuteFindStatement(coll2.Find("_id = :id").LockExclusive(LockContention.SkipLocked).LockExclusive(LockContention.NoWait).Bind("id", 1))); - - docResult = coll2.Find("_id = :id").LockExclusive(LockContention.SkipLocked).LockShared(LockContention.NoWait).Bind("id", 1).Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); - - docResult = coll2.Find("_id = :id").LockExclusive(LockContention.SkipLocked).LockShared(LockContention.SkipLocked).Bind("id", 1).Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); - - docResult = coll2.Find("_id = :id").LockShared(LockContention.SkipLocked).LockExclusive(LockContention.SkipLocked).Bind("id", 1).Execute(); - Assert.AreEqual(0, docResult.FetchAll().Count, "Matching the document ID"); - - session.SQL("ROLLBACK").Execute(); - session2.SQL("ROLLBACK").Execute(); - } - } - - [Test, Description("Reading multiple rows in a locked document(lock_shared) using SKIPLOCK and NOWAIT ")] - public void LockSharedMultipleReads() - { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher"); - ExecuteSQLStatement(session.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); - using (var session2 = MySQLX.GetSession(ConnectionString)) - { - ExecuteSQLStatement(session2.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); - Collection coll = CreateCollection("test"); - session2.SQL("ALTER TABLE `test`.`test` ADD COLUMN `$ix_i_r_index` INT GENERATED ALWAYS AS (JSON_EXTRACT(doc, '$._id')) VIRTUAL NOT NULL, ADD UNIQUE INDEX `myIndex`(`$ix_i_r_index`)").Execute(); - var docs = new[] - { - new {_id = 1, a = 1}, - new {_id = 2, a = 2}, - new {_id = 3, a = 3} - }; - - coll.Add(docs).Execute(); - var coll2 = session2.GetSchema("test").GetCollection("test"); - - session.SQL("START TRANSACTION").Execute(); - var docResult = coll.Find("_id >1").LockShared().Execute(); - Assert.AreEqual(2, docResult.FetchAll().Count, "Matching the document ID"); - - session2.SQL("START TRANSACTION").Execute(); - session2.SQL("SET SESSION innodb_lock_wait_timeout=1").Execute(); - - docResult = coll2.Find("_id < 3").LockShared(LockContention.SkipLocked).Execute(); - Assert.AreEqual(2, docResult.FetchAll().Count, "Matching the document ID"); - - docResult = coll2.Find("_id < 3").LockShared(LockContention.NoWait).Execute(); - Assert.AreEqual(2, docResult.FetchAll().Count, "Matching the document ID"); - - docResult = coll2.Find("_id < 3").LockExclusive(LockContention.SkipLocked).Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); - - session.SQL("ROLLBACK").Execute(); - session2.SQL("ROLLBACK").Execute(); - } - } - - [Test, Description("Reading multiple rows in an exclusively locked document using SKIPLOCK and NOWAIT ")] - public void LockExclusiveMultipleReads() - { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher"); - ExecuteSQLStatement(session.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); - using (var session2 = MySQLX.GetSession(ConnectionString)) - { - ExecuteSQLStatement(session2.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); - Collection coll = CreateCollection("test"); - session2.SQL("ALTER TABLE `test`.`test` ADD COLUMN `$ix_i_r_index` INT GENERATED ALWAYS AS (JSON_EXTRACT(doc, '$._id')) VIRTUAL NOT NULL, ADD UNIQUE INDEX `myIndex`(`$ix_i_r_index`)").Execute(); - var docs = new[] - { - new {_id = 1, a = 1}, - new {_id = 2, a = 2}, - new {_id = 3, a = 3} - }; - - coll.Add(docs).Execute(); - var coll2 = session2.GetSchema("test").GetCollection("test"); - - session.SQL("START TRANSACTION").Execute(); - var docResult = coll.Find("_id >1").LockExclusive().Execute(); - Assert.AreEqual(2, docResult.FetchAll().Count, "Matching the document ID"); - - session2.SQL("START TRANSACTION").Execute(); - session2.SQL("SET SESSION innodb_lock_wait_timeout=1").Execute(); - - docResult = coll2.Find("_id < 3").LockShared(LockContention.SkipLocked).Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); - - docResult = coll2.Find("_id < 3").LockExclusive(LockContention.SkipLocked).Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); - - session.SQL("ROLLBACK").Execute(); - session2.SQL("ROLLBACK").Execute(); - } - } - - [Test, Description("Collection.Find() with shared lock and Collection.Modify() normal from two sessions. ")] - public void LockSharedAndModify() - { - if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); - ExecuteSQLStatement(session.SQL("SET autocommit = 0")); - using (var session2 = MySQLX.GetSession(ConnectionString)) - { - session2.SQL("SET autocommit = 0").Execute(); - Collection coll = CreateCollection("test"); - session2.SQL("ALTER TABLE `test`.`test` ADD COLUMN `$ix_i_r_index` INT GENERATED ALWAYS AS (JSON_UNQUOTE(JSON_EXTRACT(doc, '$._id'))) VIRTUAL NOT NULL, ADD UNIQUE INDEX `myIndex`(`$ix_i_r_index`)").Execute(); - var docs = new[] - { - new {_id = 1, a = 1}, - new {_id = 2, a = 2}, - new {_id = 3, a = 3} - }; - - coll.Add(docs).Execute(); - var coll2 = session2.GetSchema("test").GetCollection("test"); - - session.SQL("START TRANSACTION").Execute(); - var docResult = coll.Find("_id = 1").LockShared().Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); - session2.SQL("START TRANSACTION").Execute(); - // Should return immediately since document isn't locked. - docResult = coll2.Find("_id = 1").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); - session2.SQL("SET SESSION innodb_lock_wait_timeout=1").Execute(); - // Should allow to modify immediately since document isn't locked. - var result = coll2.Modify("_id = 2").Set("a", 10).Execute(); - Assert.AreEqual(1, (int)result.AffectedItemsCount, "Match being done"); - Assert.Throws(() => ExecuteModifyStatement(coll2.Modify("_id = 1").Change("a", 10))); - - session.SQL("ROLLBACK").Execute(); - session2.SQL("ROLLBACK").Execute(); - } - - ExecuteSQLStatement(session.SQL("SET autocommit = 1")); - } - - [Test, Description("Collection.Find() with shared lock from two sessions. ")] - public void LockSharedTwoSessions() - { - if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); - ExecuteSQLStatement(session.SQL("SET autocommit = 0")); - using (var session2 = MySQLX.GetSession(ConnectionString)) - { - session2.SQL("SET autocommit = 0").Execute(); - Collection coll = CreateCollection("test"); - session2.SQL("ALTER TABLE `test`.`test` ADD COLUMN `$ix_i_r_index` INT GENERATED ALWAYS AS (JSON_EXTRACT(doc, '$._id')) VIRTUAL NOT NULL, ADD UNIQUE INDEX `myIndex`(`$ix_i_r_index`)").Execute(); - var docs = new[] - { - new {_id = 1, a = 1}, - new {_id = 2, a = 1}, - new {_id = 3, a = 1} - }; - - coll.Add(docs).Execute(); - var coll2 = session2.GetSchema("test").GetCollection("test"); - - session.SQL("START TRANSACTION").Execute(); - var docResult = coll.Find("_id = 1").LockShared().Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); - session2.SQL("START TRANSACTION").Execute(); - // Should return immediately since document isn't locked. - docResult = coll2.Find("_id = 2").LockShared().Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); - // Should return immediately due to LockShared() allows reading by other sessions. - docResult = coll2.Find("_id = 1").LockShared().Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); - session.SQL("ROLLBACK").Execute(); - session2.SQL("ROLLBACK").Execute(); - } - - ExecuteSQLStatement(session.SQL("SET autocommit = 1")); - } - - [Test, Description("Collection.Find() with exclusive lock and Collection.Find() with shared lock from two sessions. ")] - public void LockExclusiveFindAndLockSharedFind() - { - if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); - ExecuteSQLStatement(session.SQL("SET autocommit = 0")); - using (var session2 = MySQLX.GetSession(ConnectionString)) - { - session2.SQL("SET autocommit = 0").Execute(); - Collection coll = CreateCollection("test"); - session2.SQL("ALTER TABLE `test`.`test` ADD COLUMN `$ix_i_r_index` INT GENERATED ALWAYS AS (JSON_UNQUOTE(JSON_EXTRACT(doc, '$._id'))) VIRTUAL NOT NULL, ADD UNIQUE INDEX `myIndex`(`$ix_i_r_index`)").Execute(); - var docs = new[] - { - new {_id = 1, a = 1}, - new {_id = 2, a = 1}, - new {_id = 3, a = 1} - }; - - coll.Add(docs).Execute(); - var coll2 = session2.GetSchema("test").GetCollection("test"); - - session.SQL("START TRANSACTION").Execute(); - var docResult = coll.Find("_id = 1").LockExclusive().Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); - session2.SQL("START TRANSACTION").Execute(); - // Should return immediately since document isn't locked. - docResult = coll2.Find("_id = 2").LockShared().Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); - session2.SQL("SET SESSION innodb_lock_wait_timeout=1").Execute(); - // Session2 blocks due to LockExclusive() not allowing to read locked documents. - Assert.Throws(() => ExecuteFindStatement(coll2.Find("_id = 1").LockShared())); - // Session unlocks documents. - session.SQL("ROLLBACK").Execute(); - docResult = coll2.Find("_id = 1").LockShared().Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); - docResult = coll.Find("_id = 1").LockShared().Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); - session2.SQL("ROLLBACK").Execute(); - } - - ExecuteSQLStatement(session.SQL("SET autocommit = 1")); - } - - [Test, Description("Collection.Find() with shared lock and Collection.Find() with exclusive lock from two sessions. ")] - public void LockSharedFindAndExclusiveLocks() - { - if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); - ExecuteSQLStatement(session.SQL("SET autocommit = 0")); - using (var session2 = MySQLX.GetSession(ConnectionString)) - { - session2.SQL("SET autocommit = 0").Execute(); - Collection coll = CreateCollection("test"); - session2.SQL("ALTER TABLE `test`.`test` ADD COLUMN `$ix_i_r_index` INT GENERATED ALWAYS AS (JSON_UNQUOTE(JSON_EXTRACT(doc, '$._id'))) VIRTUAL NOT NULL, ADD UNIQUE INDEX `myIndex`(`$ix_i_r_index`)").Execute(); - var docs = new[] - { - new {_id = 1, a = 1}, - new {_id = 2, a = 1}, - new {_id = 3, a = 1} - }; - - coll.Add(docs).Execute(); - var coll2 = session2.GetSchema("test").GetCollection("test"); - - session.SQL("START TRANSACTION").Execute(); - var docResult = coll.Find("_id = 1").LockShared().Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document IDs"); - docResult = coll.Find("_id = 3").LockShared().Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document IDs"); - session2.SQL("START TRANSACTION").Execute(); - - // Should return immediately since document isn't locked. - docResult = coll2.Find("_id = 2").LockExclusive().Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); - // Should return immediately due to LockShared() allows reading by other sessions. - docResult = coll2.Find("_id = 2").LockShared().Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); - session2.SQL("SET SESSION innodb_lock_wait_timeout=1").Execute(); - // Session1 blocks due to LockExclusive() not allowing to read locked documents. - coll2.Find("_id = 2").LockExclusive().Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); - Assert.Throws(() => ExecuteFindStatement(coll2.Find("_id = 1").LockExclusive())); - Assert.Throws(() => ExecuteModifyStatement(coll2.Modify("_id = 1").Set("a", 100))); - // Session unlocks documents. - session2.SQL("ROLLBACK").Execute(); - session.SQL("ROLLBACK").Execute(); - } - - ExecuteSQLStatement(session.SQL("SET autocommit = 1")); - } - - [Test, Description("Collection.Find() with exclusive lock and Collection.Find() with exclusive lock from two sessions. ")] - public void LockExclusiveWithRollback() - { - if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); - ExecuteSQLStatement(session.SQL("SET autocommit = 0")); - using (var session2 = MySQLX.GetSession(ConnectionString)) - { - session2.SQL("SET autocommit = 0").Execute(); - Collection coll = CreateCollection("test"); - session2.SQL("ALTER TABLE `test`.`test` ADD COLUMN `$ix_i_r_index` INT GENERATED ALWAYS AS (JSON_UNQUOTE(JSON_EXTRACT(doc, '$._id'))) VIRTUAL NOT NULL, ADD UNIQUE INDEX `myIndex`(`$ix_i_r_index`)").Execute(); - var docs = new[] - { - new {_id = 1, a = 1}, - new {_id = 2, a = 1}, - new {_id = 3, a = 1} - }; - - coll.Add(docs).Execute(); - var coll2 = session2.GetSchema("test").GetCollection("test"); - - session.SQL("START TRANSACTION").Execute(); - var docResult = coll.Find("_id = 1").LockExclusive().Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document IDs"); - session2.SQL("START TRANSACTION").Execute(); - // Should return immediately due to LockShared() allows reading by other sessions. - docResult = coll2.Find("_id = 2").LockExclusive().Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); - session.SQL("SET SESSION innodb_lock_wait_timeout=1").Execute(); - Assert.Throws(() => ExecuteFindStatement(coll.Find("_id = 2").LockExclusive())); - session2.SQL("SET SESSION innodb_lock_wait_timeout=1").Execute(); - // Session1 blocks due to LockExclusive() not allowing to read locked documents. - Assert.Throws(() => ExecuteFindStatement(coll2.Find("_id = 1").LockExclusive())); - // Session unlocks documents. - session2.SQL("ROLLBACK").Execute(); - docResult = coll.Find("_id = 2").LockExclusive().Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); - session.SQL("ROLLBACK").Execute(); - docResult = coll2.Find("_id = 1").LockExclusive().Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); - } - - ExecuteSQLStatement(session.SQL("SET autocommit = 1")); - } - - [Test, Description("Collection.Find() with exclusive lock and Collection.Find() with exclusive lock from two sessions--Select multiple records ")] - public void LockExclusiveWithINSelection() - { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher"); - ExecuteSQLStatement(session.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); - using (var session2 = MySQLX.GetSession(ConnectionString)) - { - ExecuteSQLStatement(session2.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); - Collection coll = CreateCollection("test"); - var docs = new[] - { - new {_id = 1, a = 1}, - new {_id = 2, a = 1}, - new {_id = 3, a = 1} - }; - - coll.Add(docs).Execute(); - session2.SQL("ALTER TABLE `test`.`test` ADD COLUMN `$ix_i_r_index` INT GENERATED ALWAYS AS (JSON_UNQUOTE(JSON_EXTRACT(doc, '$._id'))) VIRTUAL NOT NULL, ADD UNIQUE INDEX `myIndex`(`$ix_i_r_index`)").Execute(); - var coll2 = session2.GetSchema("test").GetCollection("test"); - session.SQL("START TRANSACTION").Execute(); - var docResult = coll.Find("_id in (1,3)").LockExclusive().Execute(); - Assert.AreEqual(2, docResult.FetchAll().Count, "Matching the document ID"); - session2.SQL("START TRANSACTION").Execute(); - // Should return immediately since document isn't locked. - docResult = coll2.Find("_id = 2").LockExclusive().Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); - // Should return immediately due to LockShared() allows reading by other sessions. - docResult = coll2.Find("_id = 2").LockShared().Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); - session2.SQL("SET SESSION innodb_lock_wait_timeout=1").Execute(); - // Session1 blocks due to LockExclusive() not allowing to read locked documents. - coll2.Find("_id = 2").LockExclusive().Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); - Assert.Throws(() => ExecuteFindStatement(coll2.Find("_id = 1").LockExclusive())); - Assert.Throws(() => ExecuteModifyStatement(coll2.Modify("_id = 1").Set("a", 100))); - // Session unlocks documents. - session2.SQL("ROLLBACK").Execute(); - session.SQL("ROLLBACK").Execute(); - } - - ExecuteSQLStatement(session.SQL("SET autocommit = 1")); - } - - [Test, Description("Collection.Find() with shared lock twice ")] - public void LockSharedReadTwice() - { - if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); - ExecuteSQLStatement(session.SQL("SET autocommit = 0")); - using (var session2 = MySQLX.GetSession(ConnectionString)) - { - session2.SQL("SET autocommit = 0").Execute(); - Collection coll = CreateCollection("test"); - session2.SQL("ALTER TABLE `test`.`test` ADD COLUMN `$ix_i_r_index` INT GENERATED ALWAYS AS (JSON_UNQUOTE(JSON_EXTRACT(doc, '$._id'))) VIRTUAL NOT NULL, ADD UNIQUE INDEX `myIndex`(`$ix_i_r_index`)").Execute(); - var docs = new[] - { - new {_id = 1, a = 1}, - new {_id = 2, a = 1}, - new {_id = 3, a = 1} - }; - coll.Add(docs).Execute(); - var coll2 = session2.GetSchema("test").GetCollection("test"); - - session.SQL("START TRANSACTION").Execute(); - var docResult = coll.Find("_id = 1").LockShared().Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); - session2.SQL("START TRANSACTION").Execute(); - - // Should return immediately since document isn't locked. - docResult = coll2.Find("_id = 2").LockExclusive().Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); - docResult = coll2.Find("_id = 2").LockExclusive().Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); - docResult = coll2.Find("_id = 2").LockShared().Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); - docResult = coll2.Find("_id = 2").LockShared().Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); - // Session unlocks documents. - session2.SQL("ROLLBACK").Execute(); - session.SQL("ROLLBACK").Execute(); - } - ExecuteSQLStatement(session.SQL("SET autocommit = 1")); - } - - [Test, Description("Test MySQLX plugin Collection Array or Object contains operator Scenarios-1")] - public void FindInJsonObjects() - { - if (!Platform.IsWindows()) Assert.Ignore("This test is for Windows OS only"); - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher."); - - var col = CreateCollection("my_collection_1"); - string json = @"{ ""_id"": 0, ""title"": ""Book 0"" ,""pages"": 10,""name"": ""Jeoff Archer""}"; - Result r = col.Add(json).Execute(); - Assert.AreEqual(1, (int)r.AffectedItemsCount, "Matching Affected Records Count"); - var foundDocs = col.Find("1 in (1,2,3,6)").Execute(); - Assert.AreEqual(1, foundDocs.FetchAll().Count, "Matching Count"); - //var result = col.Find("0 in $._id").Fields("$.name as name, $.pages as pages, $.title as title").Execute(); - foundDocs = col.Find("'Book 0' in $.title").Execute(); - Assert.AreEqual(1, foundDocs.FetchAll().Count, "Matching Count"); - foundDocs = col.Find("100 in _id").Execute(); - Assert.AreEqual(0, foundDocs.FetchAll().Count, "Matching Count"); - foundDocs = col.Find("100 not in _id").Execute(); - Assert.AreEqual(1, foundDocs.FetchAll().Count, "Matching Count"); - - json = @"{ ""_id"" : 99950, ""city"" : ""KETCHIKAN"", ""loc"" : ""[ -133.18479, 55.942471 ]"", ""pop"" : 422, ""state"" : ""AK"" }"; - r = col.Add(json).Execute(); - - - var d = new DbDoc(@"{ ""id"": 1, ""pages"": 20, - ""person"": { ""name"": ""Fred"", ""age"": 45 } - }"); - var d2 = new DbDoc(); - d2.SetValue("id", 1); - d2.SetValue("pages", 20); - d2.SetValue("person", new { name = "Fred", age = 45 }); - - Assert.AreEqual(d.Equals(d2), true, "Matching"); - col.Add(d).Execute(); - - - d = new DbDoc(@"{""id"":100,""FirstName"":""xyz"",""lastname"":""pqr"", - ""address"": - {""house"":44,""city"":""Delhi"",""country"":""india""}}"); - col.Add(d).Execute(); - - d = new DbDoc(@"{""customerId"":100,""FirstName"":""xyz"",""lastname"":""pqr"", - ""address"": - {""house"":44,""city"":""Delhi"",""country"":""india""}, - ""employer"": - {""cmpName"":""ABC"",""type"":""IT""}}"); - col.Add(d).Execute(); - - d = new DbDoc(@"{ ""id"": 1, ""pages"": 20, - ""books"": [ - {""_id"" : 1, ""title"" : ""Book 1""}, - { ""_id"" : 2, ""title"" : ""Book 2"" } - ] - }"); - col.Add(d).Execute(); - - var docs = new[] { new { _id = 1, title = "Book 1" }, new { _id = 2, title = "Book 2" } }; - d2 = new DbDoc(); - d2.SetValue("id", 100); - d2.SetValue("pages", 20); - d2.SetValue("books", docs); - col.Add(d2).Execute(); - - var result = col.Find("0 in $._id").Fields("$._id as _id,$.name as name, $.pages as pages, $.title as title").Execute(); - var res1 = result.FetchOne(); - Assert.AreEqual(0, res1["_id"]); - Assert.AreEqual("Jeoff Archer", res1["name"]); - Assert.AreEqual(10, res1["pages"]); - Assert.AreEqual("Book 0", res1["title"]); - - result = col.Find("0 in $._id OR 1 in $._id").Fields("$._id as _id,$.name as name, $.pages as pages, $.title as title").Execute(); - res1 = result.FetchOne(); - Assert.AreEqual(0, res1["_id"]); - Assert.AreEqual("Jeoff Archer", res1["name"]); - Assert.AreEqual(10, res1["pages"]); - Assert.AreEqual("Book 0", res1["title"]); - - result = col.Find("0 not in $._id").Fields("$._id as _id,$.name as name, $.pages as pages, $.title as title").Execute(); - var res2 = result.FetchAll(); - Assert.AreEqual(6, res2.Count, "Matching the find count"); - - result = col.Find("'Jeoff Archer' in $.name").Execute(); - res1 = result.FetchOne(); - Assert.AreEqual(0, res1["_id"]); - Assert.AreEqual("Jeoff Archer", res1["name"]); - Assert.AreEqual(10, res1["pages"]); - Assert.AreEqual("Book 0", res1["title"]); - - result = col.Find("0 not in $._id").Fields().Execute(); - res2 = result.FetchAll(); - Assert.IsNotNull(res2[0]["_id"]); - - var test = new DbDoc(); - test.SetValue("_id", 1); - test.SetValue("age", 3488888888.9); - test.SetValue("name", - "ABBBBBBBBBBBBBBXXXXXXXXXXXXXXXYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYTTTTTTYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYABBBBBBBBBBBBBBXXXXXXXXXXXXXXXYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYTTTTTTYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYABBBBBBBBBBBBBBXXXXXXXXXXXXXXXYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYTTTTTTYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYABBBBBBBBBBBBBBXXXXXXXXXXXXXXXYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYTTTTTTYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYABBBBBBBBBBBBBBXXXXXXXXXXXXXXXYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYTTTTTTYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY"); - - var coll = CreateCollection("my_collection_123456789"); - var res = coll.Add(test).Execute(); - var foundDocs2 = coll - .Find( - "'ABBBBBBBBBBBBBBXXXXXXXXXXXXXXXYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYTTTTTTYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYABBBBBBBBBBBBBBXXXXXXXXXXXXXXXYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYTTTTTTYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYABBBBBBBBBBBBBBXXXXXXXXXXXXXXXYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYTTTTTTYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYABBBBBBBBBBBBBBXXXXXXXXXXXXXXXYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYTTTTTTYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYABBBBBBBBBBBBBBXXXXXXXXXXXXXXXYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYTTTTTTYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY' in $.name") - .Execute(); - var docs1 = foundDocs2.FetchAll(); - Assert.AreEqual(1, docs1.Count); - foundDocs2 = coll.Find("3488888888.9 in $.age").Execute(); - docs1 = foundDocs2.FetchAll(); - Assert.AreEqual(1, docs1.Count); - } - - [Test, Description("Test MySQLX plugin Collection Array or Object contains operator Scenarios-3")] - public void FindAndCountJsonValues() - { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher."); - - var col = CreateCollection("my_collection_1"); - Result add; - add = col.Add("{ \"name\": \"abcdefghijk\", \"age\": 1 , \"misc\": \"10-15-2017\"}") - .Add("{ \"name\": \"xyz\", \"age\": 6 , \"misc\": \"19.5\"}").Execute(); - add = col.Add("{ \"name\": \"qwerty@#$%^&\", \"age\": 4 , \"misc\": \"11.9\"}").Execute(); - add = col.Add("{ \"name\": [\"name1\", \"name2\", \"name3\"], \"age\": 1 , \"misc\": \"1.2\"}").Execute(); - add = col.Add( - "{ \"name\": {\"first\" : \"ABCDEF1\", \"middle\" : \"ABCDEF2\", \"last\" : \"ABCDEF3\"}, " + - "\"age\": 1 , \"misc\": \"1.2\"}") - .Execute(); - add = col.Add( - "{ \"name\": {\"first\" : \"ABCDEF1\", \"middle\" : \"ABCDEF2\", \"last\" : \"ABCDEF3\"}, " + - "\"age\": 2, \"misc\": \"1.2\"}") - .Execute(); - var docs = col.Find().Execute(); - var result1 = col.Find("\"10-15-2017\" in $.misc").Execute().FetchAll().Count; - Assert.AreEqual(1, result1); - result1 = col.Find("\"10-15-2019\" in $.misc").Execute().FetchAll().Count; - Assert.AreEqual(0, result1); - var doc = docs.FetchOne(); - var result = col.Find("1 in $.age").Fields("$.name as name, $.age as age, $.misc as misc").Sort("name DESC").Execute(); - Assert.AreEqual(3, result.FetchAll().Count); - var coll = CreateCollection("test"); - coll.Add(new DbDoc("{ \"a\": 1, \"b\": [ 1, \"value\" ], \"d\":\"\", \"ARR1\":[\"Field-1-Data-0\"] }")).Execute(); - result = coll.Find("JSON_TYPE($.ARR1) = 'ARRAY' AND \"Field-1-Data-0\" in $.ARR1").Execute(); - var count = result.FetchAll().Count; - Assert.AreEqual(1, count); - - } - - [Test, Description("Test MySQLX plugin Collection Array or Object contains operator Scenarios-4")] - public void CheckCountAfterSort() - { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher."); - var coll = CreateCollection("test"); - coll.Add("{ \"name\": \"abcdefghijk\", \"age\": 1 , \"misc\": 1.2}") - .Add("{ \"name\": \"xyz\", \"age\": 6 , \"misc\": 19.59}").Execute(); - coll.Add("{ \"name\": \"qwerty@#$%^&\", \"age\": 4 , \"misc\": 11.9}").Execute(); - coll.Add("{ \"name\": \"name1\", \"age\": 4 , \"misc\": 11.9}").Execute(); - coll.Add("{ \"name\": [\"name1\", \"name2\", \"name3\"], \"age\": 1 , \"misc\": 1.2}").Execute(); - coll.Add("{ \"name\": {\"first\" : \"ABCDEF1\", \"middle\" : \"ABCDEF2\", \"last\" : \"ABCDEF3\"}, \"age\": 1 , \"misc\": 1.2}").Execute(); - var docs = coll.Find("4 in $.age").Execute().FetchAll().Count; - Assert.True(docs > 0); - var res3 = coll.Find("4 in $.age").Sort("name ASC").Execute().FetchAll(); - Assert.AreEqual(docs, res3.Count); - } - - [Test, Description("Test MySQLX plugin Find with overlap Bugs")] - public void FindUsingOverLapsBug() - { - if (!session.Version.isAtLeast(8, 0, 17)) Assert.Ignore("This test is for MySql 8.0.17 or higher."); - String json = ""; - String[] splName = { "+", "*", "/", "a+b", "#1", "%", "&", "@1", "!1", "~", "^", - "(", ")", "{", "}", "[", "]", "|", "JSON", "ADD", "JSON_EXTRACT", "JSON_OBJECT", - "?", "=", "+", ";", ",", ":", "<", ">", "-"}; - Collection coll = CreateCollection("test"); - for (int i = 0; i < splName.Length; i++) - { - coll.Add("{\"" + splName[i] + "\":\"data" + i + "\",\"ID\":" + i + "}").Execute(); - var docs2 = coll.Find("$.ID OVERLAPS " + i).Fields("$.`" + splName[i] + "` as col1,$.ID as Id").Execute(); - var res2 = docs2.FetchOne(); - Assert.AreEqual(i.ToString(), res2["Id"].ToString(), "Matching the ID"); - if (i == 30) - Assert.AreEqual("data" + i, "data30", "Matching the String"); - else - Assert.AreEqual("data" + i, res2["col1"].ToString(), "Matching the String"); - } - - coll = CreateCollection("test"); - json = "{\"_id\":\"1005\",\"F1\": 123,\"F2\":\"ABCD\" }"; - coll.Add(json).Execute(); - json = "{\"_id\":\"1006\",\"F1\": 123,\"F2\":\"1234\" }"; - coll.Add(json).Execute(); - json = "{\"_id\":\"1007\",\"F1\": 123,\"F2\":\"S()R%^\" }"; - coll.Add(json).Execute(); - - var docs1 = coll.Find().Fields("$._id as _id", "1 << 4 as tmp").Execute(); - var res = docs1.FetchAll(); - docs1 = coll.Find().Fields("$._id as _id", "$.F2 ^ 1 as tmp").Execute(); - res = docs1.FetchAll(); - coll.Add("{\"_id\":\"100001\",\"x1\":\"31\", \"x2\":\"13\", \"x3\":\"8\", \"x4\":\"18446744073709551614\"}").Execute(); - - docs1 = coll.Find("CAST($.x1 as SIGNED) | pow(2,$.x1) = $.x1").Fields("$._id as _id, $.x1 as x1, $.x2 as x2, $.x3 as x3 , $.x2 | pow(2,$.x1) as tmp").Execute(); - res = docs1.FetchAll(); - - docs1 = coll.Find("~16 = ~CAST($.F2 as SIGNED)").Fields("$._id as _id,$.F2 as f2, ~1 as tmp").Execute(); - res = docs1.FetchAll(); - int maxrec = 100; - DbDoc newDoc = new DbDoc(); - newDoc.SetValue("_id", maxrec + 1000); - newDoc.SetValue("F1", "Field-1-Data-" + maxrec); - newDoc.SetValue("F2", "Field-2-Data-" + maxrec); - newDoc.SetValue("F3", 300 + maxrec); - coll.Add(newDoc).Execute(); - - json = "{'_id':'" + (maxrec + 1000 + 1) + "','F1':'Field-1-Data-" + (maxrec + 1) + "','F2':'Field-2-Data-" + (maxrec + 1) + "','F3':" + (300 + maxrec + 1) + "}"; - json = json.Replace("'", "\""); - coll.Add(json).Execute(); - json = "{'F1': 'Field-1-Data-9999','F2': 'Field-2-Data-9999','F3': 'Field-3-Data-9999'}".Replace("'", "\""); - coll.Add(json).Add(json.Replace("9", "8")).Execute(); - - var docs = coll.Find("$._id OVERLAPS 1100").Fields("$_id as _id,$.F1 as f1, $.F2 as f2, $.F3 as f3").Execute(); - var res1 = docs.FetchOne(); - Assert.AreEqual("1100", res1["_id"].ToString()); - Assert.AreEqual("Field-1-Data-100", res1["f1"].ToString()); - Assert.AreEqual("Field-2-Data-100", res1["f2"].ToString()); - Assert.AreEqual("400", res1["f3"].ToString()); - Assert.Throws(() => ExecuteFindStatement(coll.Find("$.F2 OVERLAPS #").Fields("$_id as _id,$.F1 as f1, $.F2 as f2, $.F3 as f3"))); - - docs = coll.Find("$.F2 OVERLAPS 'ABCD'").Fields("$_id as _id,$.F1 as f1, $.F2 as f2, $.F3 as f3").Execute(); - res1 = docs.FetchOne(); - Assert.AreEqual("1005", res1["_id"]); - Assert.AreEqual(123, res1["f1"]); - Assert.AreEqual("ABCD", res1["f2"]); - Assert.Throws(() => ExecuteFindStatement(coll.Find("$.F2 OVERLAPS [1234").Fields("$_id as _id,$.F1 as f1, $.F2 as f2, $.F3 as f3"))); - Assert.Throws(() => ExecuteFindStatement(coll.Find("$.F2 OVERLAPS S()R%^").Fields("$_id as _id,$.F1 as f1, $.F2 as f2, $.F3 as f3"))); - - docs = coll.Find("$.F2 OVERLAPS 'S()R%^'").Fields("$_id as _id,$.F1 as f1, $.F2 as f2, $.F3 as f3").Execute(); - res1 = docs.FetchOne(); - Assert.AreEqual("1007", res1["_id"]); - Assert.AreEqual(123, res1["f1"]); - Assert.AreEqual("S()R%^", res1["f2"]); - } - - [Test, Description("Test MySQLX plugin Find with overlap and Many conditions")] - public void FindUsingOverLapsManyConditions() - { - if (!session.Version.isAtLeast(8, 0, 17)) Assert.Ignore("This test is for MySql 8.0.17 or higher."); - int Condition = 45; - int i, j = 0; - String query = ""; - Collection coll = CreateCollection("test"); - for (i = 0; i < 50; i++) - { - coll.Add("{\"_id\":\"" + i + "\",\"TEST1\":" + (1000 + j) + "}").Execute(); - j++; - } - j = 0; - for (i = 0; i < Condition; i++) - { - if (i > 0) - query = query + " OR "; - query = query + "$.TEST1 OVERLAPS " + (1000 + j); - j++; - } - var docs = coll.Find(query).Execute(); - Assert.True(docs.FetchAll().Count > 0); - } - - [Test, Description("Deprecated Find Where")] - public void FindWhere() - { - Collection collection = CreateCollection("test"); - var docs = new[] - { - new { _id = 1, title = "Book 1", pages = 20 }, - new { _id = 2, title = "Book 2", pages = 30 }, - new { _id = 3, title = "Book 3", pages = 40 }, - new { _id = 4, title = "Book 4", pages = 50 }, - }; - var result1 = collection.Add(docs).Execute(); - Assert.AreEqual(4, result1.AffectedItemsCount); - - //Deprecated Find().Where() in 8.0.17 - var result2 = collection.Find("$._id = 1").Where("true").Execute().FetchAll(); - Assert.AreEqual(4, result2.Count); - } - - [Test, Description("Test MySQLX plugin Collection match count")] - public void CollectionFindFieldMatchingCount() - { - Collection col = CreateCollection("my_collection_1"); - Collection col1 = CreateCollection("my_collection_2"); - - var d1 = new DbDoc(); - d1.SetValue("_id", 1); - d1.SetValue("books", "test1"); - d1.SetValue("count", 10); - - var d2 = new DbDoc(); - d2.SetValue("_id", 2); - d2.SetValue("books", "test2"); - d2.SetValue("count", 20); - - var d3 = new DbDoc(); - d3.SetValue("_id", 3); - d3.SetValue("books", "test3"); - d3.SetValue("count", 30); - - var d4 = new DbDoc(); - d4.SetValue("_id", 4); - d4.SetValue("books", "test4"); - d4.SetValue("count", 40); - - var d5 = new DbDoc(); - d5.SetValue("_id", 5); - d5.SetValue("books", "test5"); - d5.SetValue("count", 50); - - var d6 = new DbDoc(); - d6.SetValue("_id", 6); - d6.SetValue("books", "test6"); - d6.SetValue("count", 0); - - var d7 = new DbDoc(); - d7.SetValue("_id", 0); - d7.SetValue("books", "test7"); - d7.SetValue("count", 60); - - var final = col.Add(d1, d2).Add(d3).Execute(); - var res1 = col.Find().Fields("{\"_id\":\"1\",\"books\": \"test1\" }").Fields("{\"_id\":\"2\",\"books\": \"test2\" }").Fields("{\"_id\":\"3\",\"books\": \"test3\" }").Execute().FetchAll(); - res1 = col.Find().Fields(new string[] { "_id", "books", "count" }).Execute().FetchAll(); - Assert.AreEqual(3, res1.Count, "Matching the find count"); - Assert.AreEqual(d1.ToString(), res1[0].ToString(), "Matching the doc string 1"); - Assert.AreEqual(d2.ToString(), res1[1].ToString(), "Matching the doc string 2"); - Assert.AreEqual(d3.ToString(), res1[2].ToString(), "Matching the doc string 3"); - final = col.Add(new DbDoc[] { d4, d5 }).Execute(); - var res2 = col.Find().Fields("$._id as _id,$.books as books, $.count as count").Execute().FetchAll(); - Assert.AreEqual(5, res2.Count, "Matching the find count"); - Assert.AreEqual(d1.ToString(), res2[0].ToString(), "Matching the doc string 1"); - Assert.AreEqual(d2.ToString(), res2[1].ToString(), "Matching the doc string 2"); - Assert.AreEqual(d3.ToString(), res2[2].ToString(), "Matching the doc string 3"); - Assert.AreEqual(d4.ToString(), res2[3].ToString(), "Matching the doc string 4"); - Assert.AreEqual(d5.ToString(), res2[4].ToString(), "Matching the doc string 5"); - final = col.Add(d6, d7).Execute(); - var res3 = col.Find().Sort("count ASC").Execute().FetchAll(); - Assert.AreEqual(d6.ToString(), res3[0].ToString(), "Matching the doc string 7"); - Assert.AreEqual(d1.ToString(), res3[1].ToString(), "Matching the doc string 1"); - Assert.AreEqual(d2.ToString(), res3[2].ToString(), "Matching the doc string 2"); - Assert.AreEqual(d3.ToString(), res3[3].ToString(), "Matching the doc string 3"); - Assert.AreEqual(d4.ToString(), res3[4].ToString(), "Matching the doc string 4"); - Assert.AreEqual(d5.ToString(), res3[5].ToString(), "Matching the doc string 5"); - Assert.AreEqual(d7.ToString(), res3[6].ToString(), "Matching the doc string 6"); - var res4 = col.Find().Sort("count DESC").Execute().FetchAll(); - Assert.AreEqual(d7.ToString(), res4[0].ToString(), "Matching the doc string 6"); - Assert.AreEqual(d5.ToString(), res4[1].ToString(), "Matching the doc string 1"); - Assert.AreEqual(d4.ToString(), res4[2].ToString(), "Matching the doc string 2"); - Assert.AreEqual(d3.ToString(), res4[3].ToString(), "Matching the doc string 3"); - Assert.AreEqual(d2.ToString(), res4[4].ToString(), "Matching the doc string 4"); - Assert.AreEqual(d1.ToString(), res4[5].ToString(), "Matching the doc string 5"); - Assert.AreEqual(d6.ToString(), res4[6].ToString(), "Matching the doc string 7"); - col.Modify("_id = 1").Unset("count").Unset("books").Execute(); - col.Modify("_id = 1").Set("count", 10).Set("books", "test1").Execute(); - - } - - [Test, Description("GetName,Schema and Count")] - public void CollectionGetNameSchemaCount() - { - if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher"); - var col = CreateCollection("my_collection_123456789"); - - Result r = col.Add(@"{ ""_id"": 1, ""foo"": 1 }").Execute(); - long count = col.Count(); - Assert.AreEqual(count, 1, "Matching the Collection Count"); - - var collectionName = col.Name; - Assert.AreEqual(collectionName, "my_collection_123456789", "Matching the collection Name"); - - var schema = col.Schema.Name; - Assert.AreEqual(schema, schemaName, "Matching the Schema Name"); - - r = col.Add(@"{ ""_id"": 2, ""foo"": 2 }").Execute(); - count = col.Count(); - Assert.AreEqual(count, 2, "Matching the Collection Count"); - - r = col.Remove("_id=2").Execute(); - count = col.Count(); - Assert.AreEqual(count, 1, "Matching the Collection Count"); - session.Schema.DropCollection("my_collection_123456789"); - } - - #endregion WL14389 - - } -} - +// Copyright © 2015, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySql.Data.Common; +using MySql.Data.MySqlClient; +using MySqlX.XDevAPI; +using MySqlX.XDevAPI.Common; +using MySqlX.XDevAPI.CRUD; +using NUnit.Framework; +using System; + +namespace MySqlX.Data.Tests +{ + public class BasicFindTests : BaseTest + { + [Test] + public void SimpleFind() + { + Collection coll = CreateCollection("test"); + var docs = new[] + { + new { _id = 1, title = "Book 1", pages = 20 }, + new { _id = 2, title = "Book 2", pages = 30 }, + new { _id = 3, title = "Book 3", pages = 40 }, + new { _id = 4, title = "Book 4", pages = 50 }, + }; + Result r = ExecuteAddStatement(coll.Add(docs)); + Assert.AreEqual(4, r.AffectedItemsCount); + + var foundDocs = ExecuteFindStatement(coll.Find("pages > 20")); + Assert.True(foundDocs.Next()); + Assert.True(foundDocs.Current["title"].ToString() == "Book 2"); + Assert.True(foundDocs.Next()); + Assert.True(foundDocs.Current["title"].ToString() == "Book 3"); + Assert.True(foundDocs.Next()); + Assert.True(foundDocs.Current["title"].ToString() == "Book 4"); + Assert.False(foundDocs.Next()); + } + + [Test] + public void SimpleFindWithSort() + { + Collection coll = CreateCollection("test"); + var docs = new[] + { + new { _id = 1, title = "Book 1", pages = 20 }, + new { _id = 2, title = "Book 2", pages = 30 }, + new { _id = 3, title = "Book 3", pages = 40 }, + new { _id = 4, title = "Book 4", pages = 50 }, + }; + Result r = ExecuteAddStatement(coll.Add(docs)); + Assert.AreEqual(4, r.AffectedItemsCount); + + var foundDocs = ExecuteFindStatement(coll.Find("pages > 20").Sort("pages DESC")); + Assert.True(foundDocs.Next()); + Assert.True(foundDocs.Current["title"].ToString() == "Book 4"); + Assert.True(foundDocs.Next()); + Assert.True(foundDocs.Current["title"].ToString() == "Book 3"); + Assert.True(foundDocs.Next()); + Assert.True(foundDocs.Current["title"].ToString() == "Book 2"); + Assert.False(foundDocs.Next()); + } + + [Test] + public void SimpleFindWithLimitAndOffset() + { + Collection coll = CreateCollection("test"); + var docs = new[] + { + new { _id = 1, title = "Book 1", pages = 20 }, + new { _id = 2, title = "Book 2", pages = 30 }, + new { _id = 3, title = "Book 3", pages = 40 }, + new { _id = 4, title = "Book 4", pages = 50 }, + }; + Result r = ExecuteAddStatement(coll.Add(docs)); + Assert.AreEqual(4, r.AffectedItemsCount); + + var foundDocs = ExecuteFindStatement(coll.Find("pages > 20").Limit(1)); + Assert.True(foundDocs.Next()); + Assert.True(foundDocs.Current["title"].ToString() == "Book 2"); + Assert.False(foundDocs.Next()); + + var resultDocs = ExecuteFindStatement(coll.Find("pages > 20").Offset(1).Limit(2)).FetchAll(); + Assert.AreEqual(40, resultDocs[0]["pages"]); + Assert.AreEqual(50, resultDocs[1]["pages"]); + + // Limit out of range. + Assert.Throws(() => ExecuteFindStatement(coll.Find().Limit(0))); + Assert.Throws(() => ExecuteFindStatement(coll.Find().Limit(-1))); + } + + [Test] + public void FindConditional() + { + Collection coll = CreateCollection("test"); + var docs = new[] + { + new { _id = 1, title = "Book 1", pages = 20 }, + new { _id = 2, title = "Book 2", pages = 30 }, + new { _id = 3, title = "Book 3", pages = 40 }, + new { _id = 4, title = "Book 4", pages = 50 }, + }; + Result r = ExecuteAddStatement(coll.Add(docs)); + Assert.AreEqual(4, r.AffectedItemsCount); + + var foundDocs = ExecuteFindStatement(coll.Find("pages = :Pages").Bind("pAges", 40)); + Assert.True(foundDocs.Next()); + Assert.True(foundDocs.Current["title"].ToString() == "Book 3"); + Assert.False(foundDocs.Next()); + } + + [Test] + public void BindDbDoc() + { + Collection coll = CreateCollection("test"); + var docs = new[] + { + new { _id = 1, title = "Book 1", pages = 20 }, + new { _id = 2, title = "Book 2", pages = 30 }, + new { _id = 3, title = "Book 3", pages = 40 }, + new { _id = 4, title = "Book 4", pages = 50 }, + }; + Result r = ExecuteAddStatement(coll.Add(docs)); + Assert.AreEqual(4, r.AffectedItemsCount); + + DbDoc docParams = new DbDoc(new { pages1 = 30, pages2 = 40 }); + var foundDocs = ExecuteFindStatement(coll.Find("pages = :Pages1 || pages = :Pages2").Bind(docParams)); + Assert.True(foundDocs.Next()); + Assert.AreEqual("Book 2", foundDocs.Current["title"]); + Assert.True(foundDocs.Next()); + Assert.AreEqual("Book 3", foundDocs.Current["title"]); + Assert.False(foundDocs.Next()); + } + + [Test] + public void BindJsonAsAnonymous() + { + Collection coll = CreateCollection("test"); + var docs = new[] + { + new { _id = 1, title = "Book 1", pages = 20 }, + new { _id = 2, title = "Book 2", pages = 30 }, + new { _id = 3, title = "Book 3", pages = 40 }, + new { _id = 4, title = "Book 4", pages = 50 }, + }; + Result r = ExecuteAddStatement(coll.Add(docs)); + Assert.AreEqual(4, r.AffectedItemsCount); + + var jsonParams = new { pages1 = 30, pages2 = 40 }; + var foundDocs = ExecuteFindStatement(coll.Find("pages = :Pages1 || pages = :Pages2").Bind(jsonParams)); + Assert.True(foundDocs.Next()); + Assert.AreEqual("Book 2", foundDocs.Current["title"]); + Assert.True(foundDocs.Next()); + Assert.AreEqual("Book 3", foundDocs.Current["title"]); + Assert.False(foundDocs.Next()); + } + + [Test] + public void BindJsonAsString() + { + Collection coll = CreateCollection("test"); + var docs = new[] + { + new { _id = 1, title = "Book 1", pages = 20 }, + new { _id = 2, title = "Book 2", pages = 30 }, + new { _id = 3, title = "Book 3", pages = 40 }, + new { _id = 4, title = "Book 4", pages = 50 }, + }; + Result r = ExecuteAddStatement(coll.Add(docs)); + Assert.AreEqual(4, r.AffectedItemsCount); + + var jsonParams = "{ \"pages1\" : 30, \"pages2\" : 40 }"; + var foundDocs = ExecuteFindStatement(coll.Find("pages = :Pages1 || pages = :Pages2").Bind(jsonParams)); + Assert.True(foundDocs.Next()); + Assert.AreEqual("Book 2", foundDocs.Current["title"]); + Assert.True(foundDocs.Next()); + Assert.AreEqual("Book 3", foundDocs.Current["title"]); + Assert.False(foundDocs.Next()); + } + + [Test] + public void RowLockingNotSupportedInOlderVersions() + { + if (session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql lower than 8.0.3."); + Collection coll = CreateCollection("test"); + + Exception ex = Assert.Throws(() => ExecuteFindStatement(coll.Find().LockShared())); + Assert.AreEqual("This functionality is only supported from server version 8.0.3 onwards.", ex.Message); + + ex = Assert.Throws(() => ExecuteFindStatement(coll.Find().LockExclusive())); + Assert.AreEqual("This functionality is only supported from server version 8.0.3 onwards.", ex.Message); + } + + [Test] + public void SimpleSharedLock() + { + if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); + + ExecuteSQLStatement(session.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); + using (var session2 = MySQLX.GetSession(ConnectionString)) + { + ExecuteSQLStatement(session2.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); + Collection coll = CreateCollection("test"); + var docs = new[] + { + new { _id = 1, a = 1 }, + new { _id = 2, a = 1 }, + new { _id = 3, a = 1 }, + }; + ExecuteAddStatement(coll.Add(docs)); + Collection coll2 = session2.GetSchema("test").GetCollection("test"); + + ExecuteSQLStatement(session.SQL("START TRANSACTION")); + var docResult = ExecuteFindStatement(coll.Find("_id = 1").LockShared()); + Assert.That(docResult.FetchAll(), Has.One.Items); + + ExecuteSQLStatement(session2.SQL("START TRANSACTION")); + // Should return immediately since document isn't locked. + docResult = ExecuteFindStatement(coll2.Find("_id = 2").LockShared()); + Assert.That(docResult.FetchAll(), Has.One.Items); + // Should return immediately due to LockShared() allows reading by other sessions. + docResult = ExecuteFindStatement(coll2.Find("_id = 1").LockShared()); + Assert.That(docResult.FetchAll(), Has.One.Items); + + ExecuteSQLStatement(session.SQL("ROLLBACK")); + ExecuteSQLStatement(session2.SQL("ROLLBACK")); + } + } + + [Test] + public void SharedLockForbidsToModifyDocuments() + { + if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); + + ExecuteSQLStatement(session.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); + using (var session2 = MySQLX.GetSession(ConnectionString)) + { + ExecuteSQLStatement(session2.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); + Collection coll = CreateCollection("test"); + var docs = new[] + { + new { _id = 1, a = 1 }, + new { _id = 2, a = 1 }, + new { _id = 3, a = 1 }, + }; + ExecuteAddStatement(coll.Add(docs)); + Collection coll2 = session2.GetSchema("test").GetCollection("test"); + + ExecuteSQLStatement(session.SQL("START TRANSACTION")); + var docResult = ExecuteFindStatement(coll.Find("_id = 1").LockShared()); + Assert.That(docResult.FetchAll(), Has.One.Items); + + ExecuteSQLStatement(session2.SQL("START TRANSACTION")); + // Reading the same document is allowed with LockShared(). + docResult = ExecuteFindStatement(coll2.Find("_id = 1")); + Assert.That(docResult.FetchAll(), Has.One.Items); + + // Modify() is allowed for non-locked documents. + Result result = ExecuteModifyStatement(coll2.Modify("_id = 2").Set("a", 2)); + Assert.AreEqual(1, result.AffectedItemsCount); + // Session1 blocks, Modify() is not allowed for locked documents. + ExecuteSQLStatement(session2.SQL("SET SESSION innodb_lock_wait_timeout=1")); + Exception ex = Assert.Throws(() => ExecuteModifyStatement(coll2.Modify("_id = 1").Set("a", 2))); + Assert.AreEqual("Lock wait timeout exceeded; try restarting transaction", ex.Message); + + ExecuteSQLStatement(session.SQL("ROLLBACK")); + // Modify() is allowed since document isn't locked anymore. + ExecuteModifyStatement(coll2.Modify("_id = 1").Set("a", 2)); + ExecuteSQLStatement(session2.SQL("COMMIT")); + } + } + + [Test] + public void ExclusiveLockForbidsToModifyDocuments() + { + if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); + + ExecuteSQLStatement(session.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); + using (var session2 = MySQLX.GetSession(ConnectionString)) + { + ExecuteSQLStatement(session2.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); + Collection coll = CreateCollection("test"); + var docs = new[] + { + new { _id = 1, a = 1 }, + new { _id = 2, a = 1 }, + new { _id = 3, a = 1 }, + }; + ExecuteAddStatement(coll.Add(docs)); + Collection coll2 = session2.GetSchema("test").GetCollection("test"); + + ExecuteSQLStatement(session.SQL("START TRANSACTION")); + var docResult = ExecuteFindStatement(coll.Find("_id = 1").LockExclusive()); + Assert.That(docResult.FetchAll(), Has.One.Items); + + ExecuteSQLStatement(session2.SQL("START TRANSACTION")); + + // Modify() is allowed for non-locked documents. + Result result = ExecuteModifyStatement(coll2.Modify("_id = 2").Set("a", 2)); + Assert.AreEqual(1, result.AffectedItemsCount); + // Session2 blocks, Modify() is not allowed for locked documents. + ExecuteSQLStatement(session2.SQL("SET SESSION innodb_lock_wait_timeout=1")); + Exception ex = Assert.Throws(() => ExecuteModifyStatement(coll2.Modify("_id = 1").Set("a", 2))); + Assert.AreEqual("Lock wait timeout exceeded; try restarting transaction", ex.Message); + ex = Assert.Throws(() => ExecuteModifyStatement(coll2.Modify("_id = 1").Change("a", 12))); + Assert.AreEqual("Lock wait timeout exceeded; try restarting transaction", ex.Message); + + ExecuteSQLStatement(session.SQL("ROLLBACK")); + // Modify() is allowed since document isn't locked anymore. + ExecuteModifyStatement(coll2.Modify("_id = 1").Set("a", 2)); + ExecuteSQLStatement(session2.SQL("COMMIT")); + } + } + + [Test] + public void SharedLockAfterExclusiveLock() + { + if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); + + ExecuteSQLStatement(session.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); + using (var session2 = MySQLX.GetSession(ConnectionString)) + { + ExecuteSQLStatement(session2.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); + Collection coll = CreateCollection("test"); + ExecuteSQLStatement(session2.SQL("ALTER TABLE `test`.`test` ADD COLUMN `$ix_i_r_index` INT GENERATED ALWAYS AS (JSON_UNQUOTE(JSON_EXTRACT(doc, '$._id'))) VIRTUAL NOT NULL, ADD UNIQUE INDEX `myIndex`(`$ix_i_r_index`)")); + var docs = new[] + { + new { _id = 1, a = 1 }, + new { _id = 2, a = 1 }, + new { _id = 3, a = 1 }, + }; + ExecuteAddStatement(coll.Add(docs)); + Collection coll2 = session2.GetSchema("test").GetCollection("test"); + + ExecuteSQLStatement(session.SQL("START TRANSACTION")); + var docResult = ExecuteFindStatement(coll.Find("_id = 1").LockExclusive()); + Assert.That(docResult.FetchAll(), Has.One.Items); + + ExecuteSQLStatement(session2.SQL("START TRANSACTION")); + // Should return immediately since document isn't locked. + docResult = ExecuteFindStatement(coll2.Find("_id = 2").LockShared()); + Assert.That(docResult.FetchAll(), Has.One.Items); + // Session2 blocks due to LockExclusive() not allowing to read locked documents. + ExecuteSQLStatement(session2.SQL("SET SESSION innodb_lock_wait_timeout=1")); + Exception ex = Assert.Throws(() => ExecuteFindStatement(coll2.Find("_id = 1").LockShared())); + Assert.AreEqual("Lock wait timeout exceeded; try restarting transaction", ex.Message); + + // Session unlocks documents. + ExecuteSQLStatement(session.SQL("ROLLBACK")); + // Document can now be recovered. + docResult = ExecuteFindStatement(coll2.Find("_id = 1").LockShared()); + Assert.That(docResult.FetchAll(), Has.One.Items); + ExecuteSQLStatement(session2.SQL("ROLLBACK")); + } + } + + [Test] + public void ExclusiveLockAfterSharedLock() + { + if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); + + ExecuteSQLStatement(session.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); + using (var session2 = MySQLX.GetSession(ConnectionString)) + { + ExecuteSQLStatement(session2.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); + Collection coll = CreateCollection("test"); + ExecuteSQLStatement(session2.SQL("ALTER TABLE `test`.`test` ADD COLUMN `$ix_i_r_index` INT GENERATED ALWAYS AS (JSON_UNQUOTE(JSON_EXTRACT(doc, '$._id'))) VIRTUAL NOT NULL, ADD UNIQUE INDEX `myIndex`(`$ix_i_r_index`)")); + var docs = new[] + { + new { _id = 1, a = 1 }, + new { _id = 2, a = 1 }, + new { _id = 3, a = 1 }, + }; + ExecuteAddStatement(coll.Add(docs)); + Collection coll2 = session2.GetSchema("test").GetCollection("test"); + + ExecuteSQLStatement(session.SQL("START TRANSACTION")); + var docResult = ExecuteFindStatement(coll.Find("_id in (1, 3)").LockShared()); + Assert.AreEqual(2, docResult.FetchAll().Count); + + ExecuteSQLStatement(session2.SQL("START TRANSACTION")); + // Should return immediately since document isn't locked. + docResult = ExecuteFindStatement(coll2.Find("_id = 2").LockExclusive()); + // Should return immediately due to LockShared() allows reading by other sessions. + docResult = ExecuteFindStatement(coll2.Find("_id = 2").LockShared()); + Assert.That(docResult.FetchAll(), Has.One.Items); + // Session2 blocks due to to LockExclusive() not allowing to read locked documents. + ExecuteSQLStatement(session2.SQL("SET SESSION innodb_lock_wait_timeout=1")); + Exception ex = Assert.Throws(() => ExecuteFindStatement(coll2.Find("_id = 1").LockExclusive())); + Assert.AreEqual("Lock wait timeout exceeded; try restarting transaction", ex.Message); + + // Session unlocks documents. + ExecuteSQLStatement(session.SQL("ROLLBACK")); + docResult = ExecuteFindStatement(coll2.Find("_id = 1").LockExclusive()); + Assert.That(docResult.FetchAll(), Has.One.Items); + ExecuteSQLStatement(session2.SQL("ROLLBACK")); + } + } + + [Test] + public void ExclusiveLockAfterExclusiveLock() + { + if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); + + ExecuteSQLStatement(session.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); + using (var session2 = MySQLX.GetSession(ConnectionString)) + { + ExecuteSQLStatement(session2.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); + Collection coll = CreateCollection("test"); + ExecuteSQLStatement(session2.SQL("ALTER TABLE `test`.`test` ADD COLUMN `$ix_i_r_index` INT GENERATED ALWAYS AS (JSON_UNQUOTE(JSON_EXTRACT(doc, '$._id'))) VIRTUAL NOT NULL, ADD UNIQUE INDEX `myIndex`(`$ix_i_r_index`)")); + var docs = new[] + { + new { _id = 1, a = 1 }, + new { _id = 2, a = 1 }, + new { _id = 3, a = 1 } + }; + ExecuteAddStatement(coll.Add(docs)); + Collection coll2 = session2.GetSchema("test").GetCollection("test"); + + ExecuteSQLStatement(session.SQL("START TRANSACTION")); + var docResult = ExecuteFindStatement(coll.Find("_id = 1").LockExclusive()); + Assert.That(docResult.FetchAll(), Has.One.Items); + + ExecuteSQLStatement(session2.SQL("START TRANSACTION")); + // Should return immediately since document isn't locked. + docResult = ExecuteFindStatement(coll2.Find("_id = 2").LockExclusive()); + Assert.That(docResult.FetchAll(), Has.One.Items); + // Session2 blocks due to to LockExclusive() not allowing to read locked documents. + ExecuteSQLStatement(session2.SQL("SET SESSION innodb_lock_wait_timeout=1")); + Exception ex = Assert.Throws(() => ExecuteFindStatement(coll2.Find("_id = 1").LockExclusive())); + Assert.AreEqual("Lock wait timeout exceeded; try restarting transaction", ex.Message); + + // Session unlocks documents. + ExecuteSQLStatement(session.SQL("ROLLBACK")); + docResult = ExecuteFindStatement(coll2.Find("_id = 1").LockExclusive()); + Assert.That(docResult.FetchAll(), Has.One.Items); + ExecuteSQLStatement(session2.SQL("ROLLBACK")); + } + } + + [Test] + public void InOperatorWithListOfValues() + { + if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); + + // Validates the IN operator allows expressions of the type + // ( compExpr ["NOT"] "IN" "(" argsList ")" ) | ( compExpr ["NOT"] "IN" "[" argsList "]" ) + Collection coll = CreateCollection("test"); + ExecuteAddStatement(coll.Add(new DbDoc("{ \"a\": 1, \"b\": [ 1, \"value\" ], \"d\":\"\" }"))); + + Assert.That(ExecuteFindStatement(coll.Find("a IN (1,2,3)")).FetchAll(), Has.One.Items); + Assert.That(ExecuteFindStatement(coll.Find("a not in (0,2,3)")).FetchAll(), Has.One.Items); + Assert.That(ExecuteFindStatement(coll.Find("b[0] in (1,2,3)")).FetchAll(), Has.One.Items); + Assert.That(ExecuteFindStatement(coll.Find("b[1] in (\"a\", \"b\", \"value\")")).FetchAll(), Has.One.Items); + Assert.That(ExecuteFindStatement(coll.Find("b[0] NOT IN (0,2,3)")).FetchAll(), Has.One.Items); + Assert.That(ExecuteFindStatement(coll.Find("b[1] not in (\"a\", \"b\", \"c\")")).FetchAll(), Has.One.Items); + Assert.That(ExecuteFindStatement(coll.Find("a in [1,2,3]")).FetchAll(), Has.One.Items); + CollectionAssert.IsEmpty(ExecuteFindStatement(coll.Find("a in [2,3,4]")).FetchAll()); + Assert.That(ExecuteFindStatement(coll.Find("a NOT in [0,2,3]")).FetchAll(), Has.One.Items); + Assert.That(ExecuteFindStatement(coll.Find("b not IN [1,2,3]")).FetchAll(), Has.One.Items); + CollectionAssert.IsEmpty(ExecuteFindStatement(coll.Find("b[0] not IN [1,2,3]")).FetchAll()); + CollectionAssert.IsEmpty(ExecuteFindStatement(coll.Find("c NOT IN [1,2,3]")).FetchAll()); + CollectionAssert.IsEmpty(ExecuteFindStatement(coll.Find("a IN ('', ' ')")).FetchAll()); + CollectionAssert.IsEmpty(ExecuteFindStatement(coll.Find("'' IN (1,2,3)")).FetchAll()); + Assert.That(ExecuteFindStatement(coll.Find("d IN ('')")).FetchAll(), Has.One.Items); + + Collection movies = CreateCollection("movies"); + var docString = "{ \"_id\" : \"a6f4b93e1a264a108393524f29546a8c\", \"title\" : \"AFRICAN EGG\", \"description\" : \"A Fast-Paced Documentary of a Pastry Chef And a Dentist who must Pursue a Forensic Psychologist in The Gulf of Mexico\", \"releaseyear\" : 2006, \"language\" : \"English\", \"duration\" : 130, \"rating\" : \"G\", \"genre\" : \"Science fiction\", \"actors\" : [{ \"name\" : \"MILLA PECK\", \"country\" : \"Mexico\", \"birthdate\": \"12 Jan 1984\"}, { \"name\" : \"VAL BOLGER\", \"country\" : \"Botswana\", \"birthdate\": \"26 Jul 1975\" }, { \"name\" : \"SCARLETT BENING\", \"country\" : \"Syria\", \"birthdate\": \"16 Mar 1978\" }], \"additionalinfo\" : { \"director\" : \"Sharice Legaspi\", \"writers\" : [\"Rusty Couturier\", \"Angelic Orduno\", \"Carin Postell\"], \"productioncompanies\" : [\"Qvodrill\", \"Indigoholdings\"] } }"; + ExecuteAddStatement(movies.Add(new DbDoc(docString))); + + Assert.That(ExecuteFindStatement(movies.Find("(1>5) in (true, false)")).FetchAll(), Has.One.Items); + CollectionAssert.IsEmpty(ExecuteFindStatement(movies.Find("(1+5) in (1, 2, 3, 4, 5)")).FetchAll()); + Assert.That(ExecuteFindStatement(movies.Find("('a'>'b') in (true, false)")).FetchAll(), Has.One.Items); + Assert.Throws(() => ExecuteFindStatement(movies.Find("(1>5) in [true, false]")).FetchAll()); + Assert.Throws(() => ExecuteFindStatement(movies.Find("(1+5) in [1, 2, 3, 4, 5]")).FetchAll()); + Assert.Throws(() => ExecuteFindStatement(movies.Find("('a'>'b') in [true, false]")).FetchAll()); + Assert.That(ExecuteFindStatement(movies.Find("true IN [(1>5), !(false), (true || false), (false && true)]")).FetchAll(), Has.One.Items); + Assert.That(ExecuteFindStatement(movies.Find("true IN ((1>5), !(false), (true || false), (false && true))")).FetchAll(), Has.One.Items); + CollectionAssert.IsEmpty(ExecuteFindStatement(movies.Find("{\"field\":true} IN (\"mystring\", 124, myvar, othervar.jsonobj)")).FetchAll()); + CollectionAssert.IsEmpty(ExecuteFindStatement(movies.Find("actor.name IN ['a name', null, (1<5-4), myvar.jsonobj.name]")).FetchAll()); + Assert.That(ExecuteFindStatement(movies.Find("!false && true IN [true]")).FetchAll(), Has.One.Items); + Assert.Throws(() => ExecuteFindStatement(movies.Find("1-5/2*2 > 3-2/1*2 IN [true, false]")).FetchAll()); + CollectionAssert.IsEmpty(ExecuteFindStatement(movies.Find("true IN [1-5/2*2 > 3-2/1*2]")).FetchAll()); + Assert.That(ExecuteFindStatement(movies.Find(" 'African Egg' IN ('African Egg', 1, true, NULL, [0,1,2], { 'title' : 'Atomic Firefighter' }) ")).FetchAll(), Has.One.Items); + Assert.That(ExecuteFindStatement(movies.Find(" 1 IN ('African Egg', 1, true, NULL, [0,1,2], { 'title' : 'Atomic Firefighter' }) ")).FetchAll(), Has.One.Items); + Assert.That(ExecuteFindStatement(movies.Find(" [0,1,2] IN ('African Egg', 1, true, NULL, [0,1,2], { 'title' : 'Atomic Firefighter' }) ")).FetchAll(), Has.One.Items); + Assert.That(ExecuteFindStatement(movies.Find(" { 'title' : 'Atomic Firefighter' } IN ('African Egg', 1, true, NULL, [0,1,2], { 'title' : 'Atomic Firefighter' }) ")).FetchAll(), Has.One.Items); + CollectionAssert.IsEmpty(ExecuteFindStatement(movies.Find("title IN ('African Egg', 'The Witcher', 'Jurassic Perk')")).FetchAll()); + Assert.That(ExecuteFindStatement(movies.Find("releaseyear IN (2006, 2010, 2017)")).FetchAll(), Has.One.Items); + Assert.That(ExecuteFindStatement(movies.Find("1 IN [1,2,3]")).FetchAll(), Has.One.Items); + CollectionAssert.IsEmpty(ExecuteFindStatement(movies.Find("0 IN [1,2,3]")).FetchAll()); + Assert.That(ExecuteFindStatement(movies.Find("0 NOT IN [1,2,3]")).FetchAll(), Has.One.Items); + CollectionAssert.IsEmpty(ExecuteFindStatement(movies.Find("1 NOT IN [1,2,3]")).FetchAll()); + Assert.That(ExecuteFindStatement(movies.Find("releaseyear IN [2006, 2007, 2008]")).FetchAll(), Has.One.Items); + } + + [Test] + public void InOperatorWithCompExpr() + { + if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); + + // Validates the IN operator allows expressions of the type: compExpr ["NOT"] "IN" compExpr + Collection coll = CreateCollection("test"); + var docString = "{ \"a\": 1, \"b\": \"foo\", \"c\": { \"d\": true, \"e\": [1,2,3] }, \"f\": [ {\"x\":5}, {\"x\":7 } ] }"; + ExecuteAddStatement(coll.Add(new DbDoc(docString))); + + Assert.That(ExecuteFindStatement(coll.Find("a in [1,2,3]")).FetchAll(), Has.One.Items); + Assert.That(ExecuteFindStatement(coll.Find("c.e[0] in [1,2,3]")).FetchAll(), Has.One.Items); + Assert.That(ExecuteFindStatement(coll.Find("5 in f[*].x")).FetchAll(), Has.One.Items); + Assert.That(ExecuteFindStatement(coll.Find("3 in c.e")).FetchAll(), Has.One.Items); + CollectionAssert.IsEmpty(ExecuteFindStatement(coll.Find("5 in c.e")).FetchAll()); + CollectionAssert.IsEmpty(ExecuteFindStatement(coll.Find("\"foo\" in " + docString)).FetchAll()); + CollectionAssert.IsEmpty(ExecuteFindStatement(coll.Find("\"a\" in " + docString)).FetchAll()); + CollectionAssert.IsEmpty(ExecuteFindStatement(coll.Find("a in " + docString)).FetchAll()); + Assert.That(ExecuteFindStatement(coll.Find("{\"a\":1} in " + docString)).FetchAll(), Has.One.Items); + Assert.That(ExecuteFindStatement(coll.Find("\"foo\" in b")).FetchAll(), Has.One.Items); + + Collection movies = CreateCollection("movies"); + docString = "{ \"_id\" : \"a6f4b93e1a264a108393524f29546a8c\", \"title\" : \"AFRICAN EGG\", \"description\" : \"A Fast-Paced Documentary of a Pastry Chef And a Dentist who must Pursue a Forensic Psychologist in The Gulf of Mexico\", \"releaseyear\" : 2006, \"language\" : \"English\", \"duration\" : 130, \"rating\" : \"G\", \"genre\" : \"Science fiction\", \"actors\" : [{ \"name\" : \"MILLA PECK\", \"country\" : \"Mexico\", \"birthdate\": \"12 Jan 1984\"}, { \"name\" : \"VAL BOLGER\", \"country\" : \"Botswana\", \"birthdate\": \"26 Jul 1975\" }, { \"name\" : \"SCARLETT BENING\", \"country\" : \"Syria\", \"birthdate\": \"16 Mar 1978\" }], \"additionalinfo\" : { \"director\" : \"Sharice Legaspi\", \"writers\" : [\"Rusty Couturier\", \"Angelic Orduno\", \"Carin Postell\"], \"productioncompanies\" : [\"Qvodrill\", \"Indigoholdings\"] } }"; + ExecuteAddStatement(movies.Add(new DbDoc(docString))); + + Assert.That(ExecuteFindStatement(movies.Find("{ \"name\" : \"MILLA PECK\" } IN actors")).FetchAll(), Has.One.Items); + CollectionAssert.IsEmpty(ExecuteFindStatement(movies.Find("'African Egg' in movietitle")).FetchAll()); + Assert.Throws(() => ExecuteFindStatement(movies.Find("(1 = NULL) IN title")).FetchAll()); + Assert.Throws(() => ExecuteFindStatement(movies.Find("NOT NULL IN title")).FetchAll()); + Assert.That(ExecuteFindStatement(movies.Find("[\"Rusty Couturier\", \"Angelic Orduno\", \"Carin Postell\"] IN additionalinfo.writers")).FetchAll(), Has.One.Items); + Assert.That(ExecuteFindStatement(movies.Find("{ \"name\" : \"MILLA PECK\", \"country\" : \"Mexico\", \"birthdate\": \"12 Jan 1984\"} IN actors")).FetchAll(), Has.One.Items); + CollectionAssert.IsEmpty(ExecuteFindStatement(movies.Find("true IN title")).FetchAll()); + CollectionAssert.IsEmpty(ExecuteFindStatement(movies.Find("false IN genre")).FetchAll()); + Assert.That(ExecuteFindStatement(movies.Find("'Sharice Legaspi' IN additionalinfo.director")).FetchAll(), Has.One.Items); + Assert.That(ExecuteFindStatement(movies.Find("'Mexico' IN actors[*].country")).FetchAll(), Has.One.Items); + Assert.That(ExecuteFindStatement(movies.Find("'Angelic Orduno' IN additionalinfo.writers")).FetchAll(), Has.One.Items); + } + + [Test] + public void InOperatorWithJsonArrays() + { + if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); + + Collection coll = CreateCollection("test"); + var docString = "{ \"_id\": \"1001\", \"ARR\":[1,2,3], \"ARR1\":[\"name\", \"name2\", \"name3\"]}"; + ExecuteAddStatement(coll.Add(new DbDoc(docString))); + + Assert.That(ExecuteFindStatement(coll.Find("\"1001\" in $._id")).FetchAll(), Has.One.Items); + CollectionAssert.IsEmpty(ExecuteFindStatement(coll.Find("\"1002\" in $._id")).FetchAll()); + Assert.That(ExecuteFindStatement(coll.Find("(1+2) in (1, 2, 3)")).FetchAll(), Has.One.Items); + Assert.Throws(() => ExecuteFindStatement(coll.Find("(1+2) in [1, 2, 3]")).FetchAll()); + Assert.Throws(() => ExecuteFindStatement(coll.Find("(1+2) in $.ARR")).FetchAll()); + } + + [Test] + public void GetOne() + { + Collection coll = CreateCollection("test"); + var docs = new[] + { + new { _id = 1, title = "Book 1", pages = 20 }, + new { _id = 2, title = "Book 2", pages = 30 }, + new { _id = 3, title = "Book 3", pages = 40 }, + new { _id = 4, title = "Book 4", pages = 50 }, + }; + Result r = ExecuteAddStatement(coll.Add(docs)); + Assert.AreEqual(4, r.AffectedItemsCount); + + // Expected exceptions. + Assert.Throws(() => coll.GetOne(null)); + Assert.Throws(() => coll.GetOne("")); + Assert.Throws(() => coll.GetOne(string.Empty)); + + // Get document using numeric parameter. + DbDoc document = coll.GetOne(1); + Assert.AreEqual(1, document.Id); + Assert.AreEqual("Book 1", document["title"]); + Assert.AreEqual(20, Convert.ToInt32(document["pages"])); + + // Get document using string parameter. + document = coll.GetOne("3"); + Assert.AreEqual(3, document.Id); + Assert.AreEqual("Book 3", document["title"]); + Assert.AreEqual(40, Convert.ToInt32(document["pages"])); + + // Get a non-existing document. + document = coll.GetOne(5); + Assert.Null(document); + } + + public enum LockMode { Exclusive, Shared } + + [TestCase(LockContention.Default, LockMode.Exclusive)] + [TestCase(LockContention.NoWait, LockMode.Exclusive)] + [TestCase(LockContention.SkipLocked, LockMode.Exclusive)] + [TestCase(LockContention.Default, LockMode.Shared)] + [TestCase(LockContention.NoWait, LockMode.Shared)] + [TestCase(LockContention.SkipLocked, LockMode.Shared)] + public void LockExclusiveAndSharedWithWaitingOptions(LockContention lockOption, LockMode lockMode) + { + if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher."); + + string collectionName = "test"; + var coll = CreateCollection(collectionName); + ExecuteAddStatement(coll.Add(new { _id = 1, name = "Jonh" })); + + // first session locks the row + using (Session s1 = MySQLX.GetSession(ConnectionString)) + { + var coll1 = s1.GetSchema(schemaName).GetCollection(collectionName); + s1.StartTransaction(); + var r1 = ExecuteFindStatement(coll1.Find("_id = :id").Bind("id", 1).LockExclusive()); + Assert.That(r1.FetchAll(), Has.One.Items); + + // second session tries to read the locked row + using (Session s2 = MySQLX.GetSession(ConnectionString)) + { + var coll2 = s2.GetSchema(schemaName).GetCollection(collectionName); + ExecuteSQLStatement(s2.SQL("SET innodb_lock_wait_timeout = 1")); + s2.StartTransaction(); + var stmt2 = coll2.Find("_id = :id").Bind("id", 1); + if (lockMode == LockMode.Exclusive) + stmt2.LockExclusive(lockOption); + else + stmt2.LockShared(lockOption); + + switch (lockOption) + { + case LockContention.Default: + // error 1205 Lock wait timeout exceeded; try restarting transaction + Assert.AreEqual(1205u, Assert.Throws(() => ExecuteFindStatement(stmt2).FetchAll()).Code); + break; + case LockContention.NoWait: + // error 1205 Lock wait timeout exceeded; try restarting transaction + uint expectedError = 1205; + if (session.XSession.GetServerVersion().isAtLeast(8, 0, 5)) + // error 3572 Statement aborted because lock(s) could not be acquired immediately and NOWAIT is set + expectedError = 3572; + Assert.AreEqual(expectedError, Assert.Throws(() => ExecuteFindStatement(stmt2).FetchAll()).Code); + break; + case LockContention.SkipLocked: + if (!session.XSession.GetServerVersion().isAtLeast(8, 0, 5)) + { + // error 1205 Lock wait timeout exceeded; try restarting transaction + Assert.AreEqual(1205u, Assert.Throws(() => ExecuteFindStatement(stmt2).FetchAll()).Code); + break; + } + CollectionAssert.IsEmpty(ExecuteFindStatement(stmt2).FetchAll()); + break; + default: + throw new NotImplementedException(lockOption.ToString()); + } + } + // first session frees the lock + s1.Commit(); + } + } + + [Test] + public void Grouping() + { + ExecuteSQLStatement(GetSession().SQL("SET GLOBAL sql_mode=(SELECT REPLACE(@@sql_mode, 'ONLY_FULL_GROUP_BY', '')); ")); + Collection collection = CreateCollection("test"); + var docs = new[] + { + new { _id = 1, name = "jonh doe", age = 38 }, + new { _id = 2, name = "milton green", age = 45 }, + new { _id = 3, name = "larry smith", age = 24}, + new { _id = 4, name = "mary weinstein", age = 24 }, + new { _id = 5, name = "jerry pratt", age = 45 }, + new { _id = 6, name = "hugh jackman", age = 20}, + new { _id = 7, name = "elizabeth olsen", age = 31} + }; + Result r = ExecuteAddStatement(collection.Add(docs)); + Assert.AreEqual(7, r.AffectedItemsCount); + + // GroupBy operation. + // GroupBy returns 5 rows since age 45 and 24 is repeated. + var result = ExecuteFindStatement(collection.Find().Fields("_id as ID", "name as Name", "age as Age").GroupBy("age")); + Assert.AreEqual(5, result.FetchAll().Count); + + // GroupBy with null. + result = ExecuteFindStatement(collection.Find().Fields("_id as ID", "name as Name", "age as Age").GroupBy(null)); + Assert.AreEqual(7, result.FetchAll().Count); + result = ExecuteFindStatement(collection.Find().Fields("_id as ID", "name as Name", "age as Age").GroupBy(null, null)); + Assert.AreEqual(7, result.FetchAll().Count); + result = ExecuteFindStatement(collection.Find().Fields("_id as ID", "name as Name", "age as Age").GroupBy(null, "age")); + Assert.AreEqual(5, result.FetchAll().Count); + + // Having operation. + // Having reduces the original 5 rows to 3 since 2 rows have a cnt=2, due to the repeated names. + result = ExecuteFindStatement(collection.Find().Fields("_id as ID", "count(name) as cnt", "age as Age").GroupBy("age").Having("cnt = 1")); + Assert.AreEqual(3, result.FetchAll().Count); + + // Having with null. + result = ExecuteFindStatement(collection.Find().Fields("_id as ID", "count(name) as cnt", "age as Age").GroupBy("age").Having(null)); + Assert.AreEqual(5, result.FetchAll().Count); + + // GroupBy with invalid field name. + var ex = Assert.Throws(() => ExecuteFindStatement(collection.Find().Fields("_id as ID", "name as Name", "age as Age").GroupBy("none"))); + Assert.AreEqual("Unknown column 'none' in 'group statement'", ex.Message); + + // GroupBy with empty strings. + var ex2 = Assert.Throws(() => ExecuteFindStatement(collection.Find().Fields("_id as ID", "name as Name", "age as Age").GroupBy(""))); + Assert.AreEqual("No more tokens when expecting one at token pos 0", ex2.Message); + ex2 = Assert.Throws(() => ExecuteFindStatement(collection.Find().Fields("_id as ID", "name as Name", "age as Age").GroupBy(" "))); + Assert.AreEqual("No more tokens when expecting one at token pos 0", ex2.Message); + ex2 = Assert.Throws(() => ExecuteFindStatement(collection.Find().Fields("_id as ID", "name as Name", "age as Age").GroupBy(string.Empty))); + Assert.AreEqual("No more tokens when expecting one at token pos 0", ex2.Message); + + // Having with invalid field name. + ex = Assert.Throws(() => ExecuteFindStatement(collection.Find().Fields("_id as ID", "count(name) as cnt", "age as Age").GroupBy("age").Having("none = 1"))); + Assert.AreEqual("Invalid expression in grouping criteria", ex.Message); + + // Having with empty strings. + ex2 = Assert.Throws(() => ExecuteFindStatement(collection.Find().Fields("_id as ID", "count(name) as cnt", "age as Age").GroupBy("age").Having(""))); + Assert.AreEqual("Unable to parse query ''", ex2.Message); + Assert.AreEqual("No more tokens when expecting one at token pos 0", ex2.InnerException.Message); + ex2 = Assert.Throws(() => ExecuteFindStatement(collection.Find().Fields("_id as ID", "count(name) as cnt", "age as Age").GroupBy("age").Having(" "))); + Assert.AreEqual("Unable to parse query ' '", ex2.Message); + Assert.AreEqual("No more tokens when expecting one at token pos 0", ex2.InnerException.Message); + ex2 = Assert.Throws(() => ExecuteFindStatement(collection.Find().Fields("_id as ID", "count(name) as cnt", "age as Age").GroupBy("age").Having(string.Empty))); + Assert.AreEqual("Unable to parse query ''", ex2.Message); + Assert.AreEqual("No more tokens when expecting one at token pos 0", ex2.InnerException.Message); + } + + [Test] + public void Fields() + { + Collection coll = CreateCollection("test"); + var docs = new[] + { + new { _id = 1, title = "Book 1", pages = 20 }, + new { _id = 2, title = "Book 2", pages = 30 }, + new { _id = 3, title = "Book 3", pages = 40 }, + new { _id = 4, title = "Book 4", pages = 50 }, + }; + Result r = ExecuteAddStatement(coll.Add(docs)); + Assert.AreEqual(4ul, r.AffectedItemsCount); + + // Single field. + var result = ExecuteFindStatement(coll.Find("pages = :Pages").Bind("pAges", 40).Fields("title")); + var document = result.FetchOne(); + Assert.That(document.values, Has.One.Items); + Assert.AreEqual("Book 3", document["title"]); + + // Null values are ignored. + result = ExecuteFindStatement(coll.Find("pages = :Pages").Bind("pAges", 40).Fields(null)); + document = result.FetchOne(); + Assert.AreEqual(3, document.values.Count); + + // Null values are ignored. + result = ExecuteFindStatement(coll.Find("pages = :Pages").Bind("pAges", 40).Fields("title", null)); + document = result.FetchOne(); + Assert.That(document.values, Has.One.Items); + + // Single field in array. + result = ExecuteFindStatement(coll.Find("pages = :Pages").Bind("pAges", 40).Fields(new string[] { "title" })); + document = result.FetchOne(); + Assert.That(document.values, Has.One.Items); + Assert.AreEqual("Book 3", document["title"]); + + // Single field with alias. + result = ExecuteFindStatement(coll.Find("pages = :Pages").Bind("pages", 20).Fields("title as title2")); + document = result.FetchOne(); + Assert.That(document.values, Has.One.Items); + Assert.AreEqual("Book 1", document["title2"]); + Assert.False(document.values.ContainsKey("title")); + + // Unexistent field returns null. + result = ExecuteFindStatement(coll.Find("pages = :Pages").Bind("pages", 20).Fields("book")); + document = result.FetchOne(); + Assert.That(document.values, Has.One.Items); + Assert.Null(document["book"]); + + // Unexistent field with alias returns null. + result = ExecuteFindStatement(coll.Find("pages = :Pages").Bind("pages", 20).Fields("book as book1")); + document = result.FetchOne(); + Assert.That(document.values, Has.One.Items); + Assert.Null(document["book1"]); + + // Multiple fields. + result = ExecuteFindStatement(coll.Find("pages = :Pages").Bind("pAges", 40).Fields("title", "pages", "other")); + document = result.FetchOne(); + Assert.AreEqual(3, document.values.Count); + Assert.AreEqual("Book 3", document["title"]); + Assert.AreEqual(40, document["pages"]); + Assert.Null(document["other"]); + + // Multiple fields in array. + result = ExecuteFindStatement(coll.Find("pages = :Pages").Bind("pAges", 40).Fields(new string[] { "title", "pages" })); + document = result.FetchOne(); + Assert.AreEqual(2, document.values.Count); + Assert.AreEqual("Book 3", document["title"]); + Assert.AreEqual(40, document["pages"]); + + // Sending a document doesn't generate an error. + result = ExecuteFindStatement(coll.Find("pages = :Pages").Bind("pages", 20).Fields("{\"_id\":\"1004\",\"F1\": 1234 }")); + document = result.FetchOne(); + + // Empty string and white space raises error. + var ex = Assert.Throws(() => ExecuteFindStatement(coll.Find("pages = :Pages").Bind("pAges", 40).Fields(""))); + Assert.AreEqual("No more tokens when expecting one at token pos 0", ex.Message); + ex = Assert.Throws(() => ExecuteFindStatement(coll.Find("pages = :Pages").Bind("pAges", 40).Fields(" "))); + Assert.AreEqual("No more tokens when expecting one at token pos 0", ex.Message); + ex = Assert.Throws(() => ExecuteFindStatement(coll.Find("pages = :Pages").Bind("pAges", 40).Fields(string.Empty))); + Assert.AreEqual("No more tokens when expecting one at token pos 0", ex.Message); + + // Multiple word field name raises error. + ex = Assert.Throws(() => result = ExecuteFindStatement(coll.Find("pages = :Pages").Bind("pAges", 40).Fields("Book 1"))); + Assert.AreEqual("Expression has unexpected token '1' at position 1.", ex.Message); + } + + [TestCase("", "")] + [TestCase("'", "'")] + [TestCase("", "'")] + [TestCase("'", "")] + public void FindIdAsString(string prefix, string suffix) + { + Collection coll = CreateCollection("test"); + Result r = null; + var docs = new[] + { + new { _id = $"{prefix}1{suffix}", title = $"{prefix}Book 1{suffix}", pages = 20 }, + new { _id = $"{prefix}2{suffix}", title = $"{prefix}Book 2{suffix}", pages = 30 }, + new { _id = $"{prefix}3{suffix}", title = $"{prefix}Book 3{suffix}", pages = 40 }, + new { _id = $"{prefix}4{suffix}", title = $"{prefix}Book 4{suffix}", pages = 50 }, + }; + r = coll.Add(docs).Execute(); + Assert.AreEqual(4, r.AffectedItemsCount); + + var findStmt = coll.Find("_id = :id and pages = :pages").Bind("id", $"{prefix}3{suffix}").Bind("pages", 40); + var doc = ExecuteFindStatement(findStmt); + var books = doc.FetchAll(); + Assert.That(books, Has.One.Items); + Assert.AreEqual($"{prefix}3{suffix}", books[0]["_id"]); + + findStmt = coll.Find("_id = :id and pages = :pages").Bind("Id", $"{prefix}2{suffix}").Bind("Pages", 30); + doc = ExecuteFindStatement(findStmt); + books = doc.FetchAll(); + Assert.That(books, Has.One.Items); + Assert.AreEqual($"{prefix}2{suffix}", books[0]["_id"]); + + findStmt = coll.Find("title = :title").Bind("Title", $"{prefix}Book 4{suffix}"); + doc = ExecuteFindStatement(findStmt); + books = doc.FetchAll(); + Assert.That(books, Has.One.Items); + Assert.AreEqual($"{prefix}4{suffix}", books[0]["_id"]); + Assert.AreEqual(50, books[0]["pages"]); + } + + [TestCase(":hobbies IN $.additionalinfo.hobbies", "hobbies", "painting", 4)] + [TestCase(":hobbies IN $.additionalinfo.hobbies", "hobbies", "[\"playing\", \"listening\"]", 0)] + [TestCase("[\"playing\", \"listening\"] IN $.additionalinfo.hobbies", null, null, 3)] + public void InOperatorBindingJson(string condition, string bind, string value, int id) + { + Collection coll = CreateCollection("test"); + Result r = null; + var docs = new[] + { + new { _id = 1, title = $"Book 1", pages = 20, additionalinfo = new DbDoc("{\"company\":\"xyz\",\"vehicle\":\"bike\",\"hobbies\":\"reading\"}") }, + new { _id = 2, title = $"Book 2", pages = 30, additionalinfo = new DbDoc("{\"company\":\"abc\",\"vehicle\":\"car\",\"hobbies\":\"boxing\"}") }, + new { _id = 3, title = $"Book 3", pages = 40, additionalinfo = new DbDoc("{\"company\":\"qwe\",\"vehicle\":\"airplane\",\"hobbies\":[\"playing\", \"listening\"]}") }, + new { _id = 4, title = $"Book 4", pages = 50, additionalinfo = new DbDoc("{\"company\":\"zxc\",\"vehicle\":\"boat\",\"hobbies\":\"painting\"}") }, + }; + r = coll.Add(docs).Execute(); + Assert.AreEqual(4, r.AffectedItemsCount); + + var findStmt = coll.Find(condition); + if (bind != null) findStmt.Bind(bind, value); + var result = findStmt.Execute().FetchAll(); + Assert.AreEqual(id == 0 ? 0 : 1, result.Count); + if (id > 0) + { + Assert.AreEqual(id, result[0]["_id"]); + } + } + + [Test] + public void FindUsingOverlaps() + { + Collection coll = CreateCollection("test"); + + coll.Add("{ \"_id\":1, \"title\": \"Book 1\", \"list\":[1, 4]}").Execute(); + coll.Add("{ \"_id\":2, \"title\": \"Book 2\", \"list\":[5, 7]}").Execute(); + coll.Add("{ \"_id\":3, \"title\": \"Book 3\", \"list\":[4, 9]}").Execute(); + coll.Add("{ \"_id\":4, \"title\": \"Book 4\", \"list\":[2]}").Execute(); + coll.Add("{ \"_id\":5, \"title\": \"Book 5\",\"list\":[\"\"]}").Execute(); + coll.Add("{ \"_id\":6, \"title\": \"Book 6\",\"list\":[\" \"]}").Execute(); + + var result = ExecuteFindStatement(coll.Find("[7] OVERLAPS $.list")).FetchAll(); + Assert.AreEqual("Book 2", result[0]["title"]); + result = ExecuteFindStatement(coll.Find("[8] overlaps $.list")).FetchAll(); + CollectionAssert.IsEmpty(result); + result = ExecuteFindStatement(coll.Find("[1, 4] OVERLAPS $.list")).FetchAll(); + CollectionAssert.IsNotEmpty(result); + Assert.AreEqual("Book 1", result[0]["title"]); + Assert.AreEqual("Book 3", result[1]["title"]); + result = ExecuteFindStatement(coll.Find("$.list OVERLAPS [1, 2]")).FetchAll(); + CollectionAssert.IsNotEmpty(result); + Assert.AreEqual("Book 1", result[0]["title"]); + Assert.AreEqual("Book 4", result[1]["title"]); + result = ExecuteFindStatement(coll.Find("'Book 1' NOT OVERLAPS $.title").Fields("_id")).FetchAll(); + Assert.AreEqual(5, result.Count); + Assert.AreEqual(3, result[1].Id); + result = ExecuteFindStatement(coll.Find(":title NOT OVERLAPS $.title").Bind("title", "Book 1").Fields("_id")).FetchAll(); + Assert.AreEqual(5, result.Count); + Assert.AreEqual(4, result[2].Id); + result = ExecuteFindStatement(coll.Find("$.list OVERLAPS :list").Bind("list", 9)).FetchAll(); + Assert.AreEqual("Book 3", result[0]["title"]); + var jsonParams = new { list = 4 }; + result = ExecuteFindStatement(coll.Find("$.list OVERLAPS :list").Bind(jsonParams).Fields("count(_id) as ID", "title as Title", "list as List"). + GroupBy("title", "list").Having("ID > 0")).FetchAll(); + Assert.AreEqual(2, result.Count); + Assert.AreEqual("Book 1", result[0]["Title"]); + result = ExecuteFindStatement(coll.Find("[''] OVERLAPS $.list")).FetchAll(); + Assert.That(result, Has.One.Items); + Assert.AreEqual(5, result[0].Id); + result = ExecuteFindStatement(coll.Find("[' '] OVERLAPS $.list")).FetchAll(); + Assert.That(result, Has.One.Items); + Assert.AreEqual(6, result[0].Id); + + Assert.Throws(() => ExecuteFindStatement(coll.Find("$.list OVERLAPS -")).FetchAll()); + Assert.Throws(() => ExecuteFindStatement(coll.Find("[2, 9] OVERLAPS")).FetchAll()); + Assert.Throws(() => ExecuteFindStatement(coll.Find("[2, 9] OVERPS $.list")).FetchAll()); + } + + #region WL14389 + + [Test, Description("Collection.Find(condition).GroupBy(SearchExprStr).Having(SearchConditionStr)")] + public void FindGroupByHaving() + { + ExecuteSQLStatement(GetSession().SQL("set sql_mode = 'STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION';")); + + Collection collection = CreateCollection("test"); + var docs1 = new[] + { + new { _id = 1, name = "jonh doe", age = 38,profit = 100,test = 1.92,date="21/11/2011" }, + new { _id = 2, name = "milton green", age = 45,profit = 200,test = 12.08,date="21/11/2012" }, + new { _id = 3, name = "larry smith", age = 24,profit = 300,test = 12.1,date="21/11/2013" }, + new { _id = 4, name = "mary weinstein", age = 24 ,profit = 100,test = 12.0,date="21/11/2014" }, + new { _id = 5, name = "jerry pratt", age = 45 ,profit = 400,test = 20.87,date="21/11/2015" }, + new { _id = 6, name = "hugh jackman", age = 20,profit = 500,test = 20.65,date="21/11/2016"}, + new { _id = 7, name = "elizabeth olsen", age = 31,profit = 300,test = 20.45,date="21/11/2017" }, + new { _id = 8, name = "tommy h", age = 31,profit = 3000,test = 0.0,date="21/11/2018"} + }; + + Result r = collection.Add(docs1).Execute(); + Assert.AreEqual(8, r.AffectedItemsCount); + + // GroupBy operation. + // GroupBy returns 5 rows since age 45 and 24 is repeated. + var result = collection.Find().Fields("_id as ID", "name as Name", "age as Age").GroupBy("age").Execute(); + Assert.AreEqual(5, result.FetchAll().Count); + result = collection.Find().Fields("_id as ID", "name as Name", "profit as Profit", "test as test").GroupBy("test").Having("test=1.92").Execute(); + Assert.AreEqual(1, result.FetchAll().Count); + result = collection.Find().Fields("max($.age) as age", "max($.profit) as Profit", "max($.test) as test").GroupBy("$.test").Having("max($.age)>=31"). + Sort("profit DESC").Execute(); + Assert.AreEqual(result.FetchAll().Count, result.FetchAll().Count); + result = collection.Find().Fields("max($.age) as age", "max($.profit) as Profit", "max($.test) as test").GroupBy("$.test").Having("max($.age)>30 && max($.age)<32") + .Execute(); + Assert.AreEqual(2, result.FetchAll().Count); + result = collection.Find().Fields("max($.age) as age", "max($.profit) as Profit", "max($.test) as test").GroupBy("$.test").Having("max($.age)>300000000") + .Execute(); + Assert.AreEqual(0, result.FetchAll().Count); + + result = collection.Find().Fields("max($.age) as age", "max($.profit) as Profit", "max($.test) as test").GroupBy("$.test").Having("max($.age)>30"). + Having("max($.age)<32") + .Execute(); + Assert.AreEqual(5, result.FetchAll().Count); + + result = collection.Find().Fields("max($.age) as age", "max($.profit) as Profit", "max($.test) as test").GroupBy("$.test").Having("max($.age)>30"). + Having("max($.age)<32").Limit(5) + .Execute(); + Assert.AreEqual(5, result.FetchAll().Count); + + result = collection.Find().Fields("max($.age) as age", "max($.profit) as Profit", "max($.test) as test").GroupBy("$.test").Having("max($.age)>30"). + Having("max($.age)<32").Limit(3) + .Execute(); + Assert.AreEqual(3, result.FetchAll().Count); + + result = collection.Find().Fields("max($.age) as age", "max($.profit) as Profit", "max($.test) as test").GroupBy("$.test").Having("max($.age)>30"). + Having("max($.age)<32").Limit(3).Offset(2) + .Execute(); + Assert.AreEqual(3, result.FetchAll().Count); + + Assert.Throws(() => collection.Find().Fields("max($.age) as age", "max($.profit) as Profit", "max($.test) as test").GroupBy("$.test").Having("date=21/11/2011").Execute()); + } + + [Test, Description("Collection.Find().Limit(x).Offset(y)")] + public void FindLimitOffset() + { + ExecuteSQLStatement(GetSession().SQL("set sql_mode = 'STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION';")); + + Collection collection = CreateCollection("test"); + var docs1 = new[] + { + new { _id = 1, name = "jonh doe", age = 38,profit = 100,test = 1.92,date="21/11/2011" }, + new { _id = 2, name = "milton green", age = 45,profit = 200,test = 12.08,date="21/11/2012" }, + new { _id = 3, name = "larry smith", age = 24,profit = 300,test = 12.1,date="21/11/2013" }, + new { _id = 4, name = "mary weinstein", age = 24 ,profit = 100,test = 12.0,date="21/11/2014" }, + new { _id = 5, name = "jerry pratt", age = 45 ,profit = 400,test = 20.87,date="21/11/2015" }, + new { _id = 6, name = "hugh jackman", age = 20,profit = 500,test = 20.65,date="21/11/2016"}, + new { _id = 7, name = "elizabeth olsen", age = 31,profit = 300,test = 20.45,date="21/11/2017" }, + new { _id = 8, name = "tommy h", age = 31,profit = 3000,test = 0.0,date="21/11/2018"} + }; + + Result r = collection.Add(docs1).Execute(); + Assert.AreEqual(8, r.AffectedItemsCount); + + // GroupBy operation. + // GroupBy returns 5 rows since age 45 and 24 is repeated. + var result1 = collection.Find().Limit(2).Offset(-2378723).Execute(); + int k = result1.FetchAll().Count; + result1 = collection.Find().Limit(2).Offset(-1).Execute(); + k = result1.FetchAll().Count; + result1 = collection.Find().Limit(2).Offset(0).Execute(); + k = result1.FetchAll().Count; + + var result = collection.Find().Fields("_id as ID", "name as Name", "age as Age").GroupBy("age").Execute(); + Assert.AreEqual(5, result.FetchAll().Count); + result = collection.Find().Fields("_id as ID", "name as Name", "profit as Profit", "test as test").GroupBy("test").Having("test=1.92").Execute(); + Assert.AreEqual(1, result.FetchAll().Count); + result = collection.Find().Fields("max($.age) as age", "max($.profit) as Profit", "max($.test) as test").GroupBy("$.test").Having("max($.age)>=31"). + Sort("profit DESC").Execute(); + Assert.AreEqual(result.FetchAll().Count, result.FetchAll().Count); + result = collection.Find().Fields("max($.age) as age", "max($.profit) as Profit", "max($.test) as test").GroupBy("$.test").Having("max($.age)>30 && max($.age)<32") + .Execute(); + Assert.AreEqual(2, result.FetchAll().Count); + result = collection.Find().Fields("max($.age) as age", "max($.profit) as Profit", "max($.test) as test").GroupBy("$.test").Having("max($.age)>300000000") + .Execute(); + Assert.AreEqual(0, result.FetchAll().Count); + + result = collection.Find().Fields("max($.age) as age", "max($.profit) as Profit", "max($.test) as test").GroupBy("$.test").Having("max($.age)>30"). + Having("max($.age)<32") + .Execute(); + Assert.AreEqual(5, result.FetchAll().Count); + + result = collection.Find().Fields("max($.age) as age", "max($.profit) as Profit", "max($.test) as test").GroupBy("$.test").Having("max($.age)>30"). + Having("max($.age)<32").Limit(5) + .Execute(); + Assert.AreEqual(5, result.FetchAll().Count); + + result = collection.Find().Fields("max($.age) as age", "max($.profit) as Profit", "max($.test) as test").GroupBy("$.test").Having("max($.age)>30"). + Having("max($.age)<32").Limit(3) + .Execute(); + Assert.AreEqual(3, result.FetchAll().Count); + + result = collection.Find().Fields("max($.age) as age", "max($.profit) as Profit", "max($.test) as test").GroupBy("$.test").Having("max($.age)>30"). + Having("max($.age)<32").Limit(3).Offset(2) + .Execute(); + Assert.AreEqual(3, result.FetchAll().Count); + + result = collection.Find().Fields("$._id as _id", "$.test as test").GroupBy("$.test").Limit(5).Offset(1).Execute(); + Assert.AreEqual(5, result.FetchAll().Count); + + result = collection.Find().Fields("$._id as _id", "$.test as test").GroupBy("$.test").Limit(5).Offset(-1).Execute(); + Assert.AreEqual(5, result.FetchAll().Count); + + result = collection.Find().Fields("$._id as _id", "$.test as test").GroupBy("$.test").Limit(8).Execute(); + Assert.AreEqual(8, result.FetchAll().Count); + + result = collection.Find().Fields("max($.age) as age", "max($.profit) as Profit", "max($.test) as test").GroupBy("$.test").Having("max($.age)>30"). + Having("max($.age)<32").Limit(3).Offset(-1) + .Execute(); + Assert.AreEqual(3, result.FetchAll().Count); + + Assert.Throws(() => collection.Find().Fields("max($.age) as age", "max($.profit) as Profit", "max($.test) as test").GroupBy("$.test").Having("max($.age)>30"). + Having("max($.age)<32").Limit(-1).Offset(0) + .Execute()); + + DbDoc[] jsonlist = new DbDoc[2000]; + for (int i = 0; i < 2000; i++) + { + DbDoc newDoc2 = new DbDoc(); + newDoc2.SetValue("_id", (i + 1000).ToString()); + newDoc2.SetValue("F1", ("Field-1-Data-" + i)); + newDoc2.SetValue("F2", ("Field-2-Data-" + i)); + newDoc2.SetValue("F3", (300 + i).ToString()); + jsonlist[i] = newDoc2; + newDoc2 = null; + } + var res = collection.Add(jsonlist).Execute(); + + result = collection.Find().Fields("$.F1 as F1", "$.F2 as F2").GroupBy("$.F1").Limit(3).Offset(1).Execute(); + Assert.AreEqual(3, result.FetchAll().Count); + + result = collection.Find().Fields("$.F1 as F1", "$.F2 as F2").GroupBy("$.F1").Limit(3).Offset(1844674407370955161).Execute(); + Assert.AreEqual(0, result.FetchAll().Count); + } + + [Test, Description("Collection.Find().Limit(x,y)")] + public void FindLimitOffsetDeprecated() + { + ExecuteSQLStatement(GetSession().SQL("set sql_mode = 'STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION';")); + Collection collection = CreateCollection("test"); + var docs1 = new[] + { + new { _id = 1, name = "jonh doe", age = 38,profit = 100,test = 1.92,date="21/11/2011" }, + new { _id = 2, name = "milton green", age = 45,profit = 200,test = 12.08,date="21/11/2012" }, + new { _id = 3, name = "larry smith", age = 24,profit = 300,test = 12.1,date="21/11/2013" }, + new { _id = 4, name = "mary weinstein", age = 24 ,profit = 100,test = 12.0,date="21/11/2014" }, + new { _id = 5, name = "jerry pratt", age = 45 ,profit = 400,test = 20.87,date="21/11/2015" }, + new { _id = 6, name = "hugh jackman", age = 20,profit = 500,test = 20.65,date="21/11/2016"}, + new { _id = 7, name = "elizabeth olsen", age = 31,profit = 300,test = 20.45,date="21/11/2017" }, + new { _id = 8, name = "tommy h", age = 31,profit = 3000,test = 0.0,date="21/11/2018"} + }; + + Result r = collection.Add(docs1).Execute(); + Assert.AreEqual(8, r.AffectedItemsCount); + + // GroupBy operation. + var result1 = collection.Find().Limit(2).Offset(-2378723).Execute(); + int k = result1.FetchAll().Count; + result1 = collection.Find().Limit(2).Offset(-1).Execute(); + k = result1.FetchAll().Count; + result1 = collection.Find().Limit(2).Offset(0).Execute(); + k = result1.FetchAll().Count; + result1 = collection.Find().Limit(2).Offset(1000000000).Execute(); + k = result1.FetchAll().Count; + collection.Remove("true").Limit(2).Execute(); + + docs1 = new[] + { + new { _id = 1, name = "jonh doe", age = 38,profit = 100,test = 1.92,date="21/11/2011" }, + new { _id = 2, name = "milton green", age = 45,profit = 200,test = 12.08,date="21/11/2012" }, + }; + + r = collection.Add(docs1).Execute(); + Assert.Throws(() => collection.Remove("true").Limit(2).Offset(1).Execute()); + + collection.Remove("true").Limit(2).Offset(0).Execute(); + docs1 = new[] + { + new { _id = 1, name = "jonh doe", age = 38,profit = 100,test = 1.92,date="21/11/2011" }, + new { _id = 2, name = "milton green", age = 45,profit = 200,test = 12.08,date="21/11/2012" }, + }; + + r = collection.Add(docs1).Execute(); + Assert.Throws(() => collection.Modify("_id = 1 || _id = 2").Set("age", 34).Limit(1).Offset(1).Execute()); + + collection.Modify("_id = 1 || _id = 2").Set("age", 34).Limit(2).Offset(0).Execute(); + collection.Modify("_id = 1").Set("age", 38).Limit(2).Offset(0).Execute(); + collection.Modify("_id = 2").Set("age", 45).Limit(2).Offset(0).Execute(); + + var result = collection.Find().Fields("max($.age) as age", "max($.profit) as Profit", "max($.test) as test").GroupBy("$.test").Having("max($.age)>30"). + Having("max($.age)<32").Limit(3).Offset(2) + .Execute(); + Assert.AreEqual(3, result.FetchAll().Count); + + result = collection.Find().Fields("$._id as _id", "$.test as test").GroupBy("$.test").Limit(5).Offset(1).Execute(); + Assert.AreEqual(5, result.FetchAll().Count); + result = collection.Find().Fields("$._id as _id", "$.test as test").GroupBy("$.test").Limit(5).Offset(-1).Execute(); + Assert.AreEqual(5, result.FetchAll().Count); + + result = collection.Find().Fields("max($.age) as age", "max($.profit) as Profit", "max($.test) as test").GroupBy("$.test").Having("max($.age)>30"). + Having("max($.age)<32").Limit(3).Offset(-1) + .Execute(); + Assert.AreEqual(3, result.FetchAll().Count); + + Assert.Throws(() => collection.Find().Fields("max($.age) as age", "max($.profit) as Profit", "max($.test) as test").GroupBy("$.test").Having("max($.age)>30"). + Having("max($.age)<32").Limit(-1).Offset(0) + .Execute()); + } + + [Test, Description("Test MySQLX plugin Collection Dbdoc Scenarios")] + public void CollectionDbdoc() + { + Collection col = CreateCollection("my_collection_1"); + Collection col1 = CreateCollection("my_collection_2"); + var d1 = new DbDoc(); + d1.SetValue("_id", 1); + var docs1 = new[] + { + new { _id = 1, title = "Book 1" }, + new { _id = 2, title = "Book 2" }, + }; + + d1.SetValue("books", docs1); + d1.SetValue("pages", 20); + + var d2 = new DbDoc(); + d2.SetValue("_id", 2); + var docs2 = new[] + { + new { _id = 1, title = "Book 3" }, + new { _id = 2, title = "Book 4" }, + }; + + d2.SetValue("books", docs2); + d2.SetValue("pages", 30); + + var d3 = new DbDoc(); + d3.SetValue("_id", 3); + var docs3 = new[] + { + new { _id = 1, title = "Book 3" }, + new { _id = 2, title = "Book 4" }, + }; + + d3.SetValue("books", docs3); + d3.SetValue("pages", 40); + col.Add(d1).Add(d2).Add(d3).Execute(); + string[] test1 = new string[] { "_id=1" }; + string[] test2 = new string[] { "_id=2" }; + var res = col.Find("$._id = 1").Execute().FetchAll(); + Assert.AreEqual(1, res.Count, "Matching the find count"); + Assert.AreEqual(d1.ToString(), res[0].ToString(), "Matching the string"); + res = col.Find("$._id = 2").Execute().FetchAll(); + Assert.AreEqual(1, res.Count, "Matching the find count"); + Assert.AreEqual(d2.ToString(), res[0].ToString(), "Matching the string"); + res = col.Find("$._id = 3").Execute().FetchAll(); + Assert.AreEqual(1, res.Count, "Matching the find count"); + Assert.AreEqual(d3.ToString(), res[0].ToString(), "Matching the string"); + + } + + [Test, Description("Test MySQLX plugin Collection Dbdoc Scenarios - ID Present DbDoc Blank")] + public void CollectionIDPresentDbdocBlank() + { + Collection col = CreateCollection("my_collection_1"); + Collection col1 = CreateCollection("my_collection_2"); + var d1 = new DbDoc(); + d1.SetValue("_id", 1); + string[] a = { String.Empty }; + d1.SetValue("books", a); + d1.SetValue("pages", 20); + + var d2 = new DbDoc(); + d2.SetValue("_id", 2); + d2.SetValue("books", a); + d2.SetValue("pages", 30); + + var d3 = new DbDoc(); + d3.SetValue("_id", 3); + d3.SetValue("books", a); + d3.SetValue("pages", 40); + + col.Add(d1).Add(d2).Add(d3).Execute(); + string[] test1 = new string[] { "_id=1" }; + string[] test2 = new string[] { "_id=2" }; + var res = col.Find("$._id = 1").Execute().FetchAll(); + Assert.AreEqual(1, res.Count, "Matching the find count"); + Assert.AreEqual(d1.ToString(), res[0].ToString(), "Matching the string"); + res = col.Find("$._id = 2").Execute().FetchAll(); + Assert.AreEqual(1, res.Count, "Matching the find count"); + Assert.AreEqual(d2.ToString(), res[0].ToString(), "Matching the string"); + res = col.Find("$._id = 3").Execute().FetchAll(); + Assert.AreEqual(1, res.Count, "Matching the find count"); + Assert.AreEqual(d3.ToString(), res[0].ToString(), "Matching the string"); + } + + /// + /// Bug 23542055 + /// + [Test, Description("Test MySQLX plugin Find with Many conditions")] + [Ignore("Uncomment to execute")] + public void FindWithManyConditions() + { + int i = 0; + int Condition = 49; + String query = ""; + var col = CreateCollection("my_collection_1"); + + col.Add("{\"_id\":\"1002\",\"TEST1\":1111}").Execute(); + for (i = 0; i < Condition; i++) + { + if (i > 0) + query = query + " OR "; + query = query + "$.TEST1 > " + i; + } + var docs = col.Find(query).Execute(); + } + + [TestCase(1)] + [TestCase(2)] + [TestCase(3)] + [TestCase(4)] + [Test, Description("Reading exclusively locked anonymous object array using LockShared without waiting option. ")] + public void ExclusiveLocksAndCommit(int scenario) + { + if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher"); + + ExecuteSQLStatement(session.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); + using (var session2 = MySQLX.GetSession(ConnectionString)) + { + ExecuteSQLStatement(session2.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); + Collection coll = CreateCollection("test"); + ExecuteSQLStatement(session2.SQL("ALTER TABLE `test`.`test` ADD COLUMN `$ix_i_r_index` INT GENERATED ALWAYS AS (JSON_UNQUOTE(JSON_EXTRACT(doc, '$._id'))) VIRTUAL NOT NULL, ADD UNIQUE INDEX `myIndex`(`$ix_i_r_index`)")); + Result result1 = null; + switch (scenario) + { + case 1: // Anonymous Object + var docs = new[] + { + new {_id = 1, a = 1}, + new {_id = 2, a = 2}, + new {_id = 3, a = 3} + }; + coll.Add(docs).Execute(); + break; + case 2: // DbDoc + for (int i = 0; i < 3; i++) + { + DbDoc DbDocs = new DbDoc(); + DbDocs.SetValue("_id", i); + DbDocs.SetValue("a", i); + result1 = coll.Add(DbDocs).Execute(); + } + break; + case 3: // Chained Add + var docs1 = new { _id = 1, title = "Book 1", pages = 20, a = 1 }; + var docs2 = new { _id = 2, title = "Book 1", pages = 20, a = 2 }; + var docs3 = new { _id = 3, title = "Book 1", pages = 20, a = 3 }; + result1 = coll.Add(docs1).Add(docs2).Add(docs3).Execute(); + break; + case 4: //Json string + result1 = coll.Add(@"{ ""_id"": 1,""a"": 1 }", @"{""_id"": 2,""a"": 2 }", @"{""_id"": 3, ""a"": 3 }", @"{ ""_id"": 4,""a"": 4 }").Execute(); + break; + } + + var coll2 = session2.GetSchema("test").GetCollection("test"); + session.SQL("START TRANSACTION").Execute(); + var docResult = coll.Find("_id = 1").LockExclusive().Execute(); + Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); + + session2.SQL("START TRANSACTION").Execute(); + // Should return immediately since document isn't locked. + docResult = coll2.Find("_id = 2").LockExclusive().Execute(); + Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); + + // Session2 blocks due to to LockExclusive() not allowing to read locked documents. + session2.SQL("SET SESSION innodb_lock_wait_timeout=1").Execute(); + Exception ex = Assert.Throws(() => ExecuteFindStatement(coll2.Find("_id = :id").LockExclusive().Bind("id", 1))); + + Assert.Throws(() => ExecuteModifyStatement(coll2.Modify("a = 1").Change("a", 10))); + + session.Commit(); + var result = coll2.Modify("a = 1").Set("a", 12).Execute(); + Assert.AreEqual(1, result.AffectedItemsCount); + session.SQL("ROLLBACK").Execute(); + session2.SQL("ROLLBACK").Execute(); + } + } + + [TestCase(null)] + [TestCase(LockMode.Shared)] + [TestCase(LockMode.Exclusive)] + [Test, Description("Reading a document which was locked using lock_shared without waiting option")] + public void SharedLockAndCommit(LockMode? lockMode) + { + if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher"); + ExecuteSQLStatement(session.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); + using (var session2 = MySQLX.GetSession(ConnectionString)) + { + ExecuteSQLStatement(session2.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); + Collection coll = CreateCollection("test"); + session2.SQL("ALTER TABLE `test`.`test` ADD COLUMN `$ix_i_r_index` INT GENERATED ALWAYS AS (JSON_UNQUOTE(JSON_EXTRACT(doc, '$._id'))) VIRTUAL NOT NULL, ADD UNIQUE INDEX `myIndex`(`$ix_i_r_index`)").Execute(); + var docs = new[] + { + new {_id = 1, a = 1}, + new {_id = 2, a = 2}, + new {_id = 3, a = 3} + }; + + coll.Add(docs).Execute(); + var coll2 = session2.GetSchema("test").GetCollection("test"); + + session.SQL("START TRANSACTION").Execute(); + var docResult = coll.Find("_id = 1").LockShared().Execute(); + Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); + + session2.SQL("START TRANSACTION").Execute(); + // Should return immediately since document isn't locked. + switch (lockMode) + { + case LockMode.Shared: + docResult = coll2.Find("_id = 2").LockShared().Execute(); + break; + case LockMode.Exclusive: + docResult = coll2.Find("_id = 2").LockExclusive().Execute(); + break; + default: + docResult = coll2.Find("_id = 2").Execute(); + break; + } + Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); + + // Session2 returns immediately. + session2.SQL("SET SESSION innodb_lock_wait_timeout=1").Execute(); + docResult = coll2.Find("_id = :id").Bind("id", 1).Execute(); + Assert.That(docResult.FetchAll(), Has.One.Items); + + // Session2 blocks due to to LockShared() not allowing to modify locked documents. + Exception ex = Assert.Throws(() => ExecuteModifyStatement(coll2.Modify("a = 1").Change("a", 10))); + + // Session2 returns immediately as session is committed. + session.Commit(); + var result = coll2.Modify("a = 1").Set("a", 12).Execute(); + Assert.AreEqual(1, result.AffectedItemsCount); + + session.SQL("ROLLBACK").Execute(); + session2.SQL("ROLLBACK").Execute(); + } + } + + [TestCase(LockMode.Shared)] + [TestCase(LockMode.Exclusive)] + [Test, Description("Reading a document using lock_shared using SKIPLOCK and NOWAIT options with CRUD operations happening parallely.")] + public void SharedAndExclusiveLockWithSkipAndNoWait(LockMode lockMode) + { + if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher"); + ExecuteSQLStatement(session.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); + using (var session2 = MySQLX.GetSession(ConnectionString)) + { + ExecuteSQLStatement(session2.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); + Collection coll = CreateCollection("test"); + session2.SQL("ALTER TABLE `test`.`test` ADD COLUMN `$ix_i_r_index` INT GENERATED ALWAYS AS (JSON_UNQUOTE(JSON_EXTRACT(doc, '$._id'))) VIRTUAL NOT NULL, ADD UNIQUE INDEX `myIndex`(`$ix_i_r_index`)").Execute(); + if (lockMode == LockMode.Shared) + session2.SQL("ALTER TABLE `test`.`test` ADD COLUMN `$ix_i_m_index` INT GENERATED ALWAYS AS (JSON_UNQUOTE(JSON_EXTRACT(doc, '$.a'))) VIRTUAL NOT NULL, ADD UNIQUE INDEX `myIndex1`(`$ix_i_m_index`)").Execute(); + + var docs = new[] + { + new {_id = 1, a = 1}, + new {_id = 2, a = 2}, + new {_id = 3, a = 3} + }; + + coll.Add(docs).Execute(); + var coll2 = session2.GetSchema("test").GetCollection("test"); + + session.SQL("START TRANSACTION").Execute(); + var result1 = coll.Modify("a = 1").Set("a", 10).Execute(); + + session2.SQL("START TRANSACTION").Execute(); + session2.SQL("SET SESSION innodb_lock_wait_timeout=1").Execute(); + DocResult docResult = null; + switch (lockMode) + { + case LockMode.Exclusive: + Assert.Throws(() => ExecuteFindStatement(coll2.Find("_id = :id").LockExclusive(LockContention.NoWait).Bind("id", 1))); + docResult = coll2.Find("_id = :id").LockExclusive(LockContention.SkipLocked).Bind("id", 1).Execute(); + break; + case LockMode.Shared: + Assert.Throws(() => ExecuteFindStatement(coll2.Find("_id = :id").LockShared(LockContention.NoWait).Bind("id", 1))); + docResult = coll2.Find("_id = :id").LockShared(LockContention.SkipLocked).Bind("id", 1).Execute(); + break; + } + Assert.AreEqual(0, docResult.FetchAll().Count, "Matching the document ID"); + + session.SQL("ROLLBACK").Execute(); + session2.SQL("ROLLBACK").Execute(); + } + } + + [Test, Description("Multiple lock calls using NOWAIT and SKIPLOCK waiting option. ")] + public void MultipleLocksWithNowaitAndSkiplock() + { + if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher"); + ExecuteSQLStatement(session.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); + using (var session2 = MySQLX.GetSession(ConnectionString)) + { + ExecuteSQLStatement(session2.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); + Collection coll = CreateCollection("test"); + session2.SQL("ALTER TABLE `test`.`test` ADD COLUMN `$ix_i_r_index` INT GENERATED ALWAYS AS (JSON_UNQUOTE(JSON_EXTRACT(doc, '$._id'))) VIRTUAL NOT NULL, ADD UNIQUE INDEX `myIndex`(`$ix_i_r_index`)").Execute(); + var docs = new[] + { + new {_id = 1, a = 1}, + new {_id = 2, a = 2}, + new {_id = 3, a = 3} + }; + + coll.Add(docs).Execute(); + var coll2 = session2.GetSchema("test").GetCollection("test"); + + session.SQL("START TRANSACTION").Execute(); + var docResult = coll.Find("_id = 1").LockShared().Execute(); + Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); + + session2.SQL("START TRANSACTION").Execute(); + + session2.SQL("SET SESSION innodb_lock_wait_timeout=1").Execute(); + Assert.Throws(() => ExecuteFindStatement(coll2.Find("_id = :id").LockExclusive(LockContention.SkipLocked).LockExclusive(LockContention.NoWait).Bind("id", 1))); + + docResult = coll2.Find("_id = :id").LockExclusive(LockContention.SkipLocked).LockShared(LockContention.NoWait).Bind("id", 1).Execute(); + Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); + + docResult = coll2.Find("_id = :id").LockExclusive(LockContention.SkipLocked).LockShared(LockContention.SkipLocked).Bind("id", 1).Execute(); + Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); + + docResult = coll2.Find("_id = :id").LockShared(LockContention.SkipLocked).LockExclusive(LockContention.SkipLocked).Bind("id", 1).Execute(); + Assert.AreEqual(0, docResult.FetchAll().Count, "Matching the document ID"); + + session.SQL("ROLLBACK").Execute(); + session2.SQL("ROLLBACK").Execute(); + } + } + + [Test, Description("Reading multiple rows in a locked document(lock_shared) using SKIPLOCK and NOWAIT ")] + public void LockSharedMultipleReads() + { + if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher"); + ExecuteSQLStatement(session.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); + using (var session2 = MySQLX.GetSession(ConnectionString)) + { + ExecuteSQLStatement(session2.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); + Collection coll = CreateCollection("test"); + session2.SQL("ALTER TABLE `test`.`test` ADD COLUMN `$ix_i_r_index` INT GENERATED ALWAYS AS (JSON_EXTRACT(doc, '$._id')) VIRTUAL NOT NULL, ADD UNIQUE INDEX `myIndex`(`$ix_i_r_index`)").Execute(); + var docs = new[] + { + new {_id = 1, a = 1}, + new {_id = 2, a = 2}, + new {_id = 3, a = 3} + }; + + coll.Add(docs).Execute(); + var coll2 = session2.GetSchema("test").GetCollection("test"); + + session.SQL("START TRANSACTION").Execute(); + var docResult = coll.Find("_id >1").LockShared().Execute(); + Assert.AreEqual(2, docResult.FetchAll().Count, "Matching the document ID"); + + session2.SQL("START TRANSACTION").Execute(); + session2.SQL("SET SESSION innodb_lock_wait_timeout=1").Execute(); + + docResult = coll2.Find("_id < 3").LockShared(LockContention.SkipLocked).Execute(); + Assert.AreEqual(2, docResult.FetchAll().Count, "Matching the document ID"); + + docResult = coll2.Find("_id < 3").LockShared(LockContention.NoWait).Execute(); + Assert.AreEqual(2, docResult.FetchAll().Count, "Matching the document ID"); + + docResult = coll2.Find("_id < 3").LockExclusive(LockContention.SkipLocked).Execute(); + Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); + + session.SQL("ROLLBACK").Execute(); + session2.SQL("ROLLBACK").Execute(); + } + } + + [Test, Description("Reading multiple rows in an exclusively locked document using SKIPLOCK and NOWAIT ")] + public void LockExclusiveMultipleReads() + { + if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher"); + ExecuteSQLStatement(session.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); + using (var session2 = MySQLX.GetSession(ConnectionString)) + { + ExecuteSQLStatement(session2.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); + Collection coll = CreateCollection("test"); + session2.SQL("ALTER TABLE `test`.`test` ADD COLUMN `$ix_i_r_index` INT GENERATED ALWAYS AS (JSON_EXTRACT(doc, '$._id')) VIRTUAL NOT NULL, ADD UNIQUE INDEX `myIndex`(`$ix_i_r_index`)").Execute(); + var docs = new[] + { + new {_id = 1, a = 1}, + new {_id = 2, a = 2}, + new {_id = 3, a = 3} + }; + + coll.Add(docs).Execute(); + var coll2 = session2.GetSchema("test").GetCollection("test"); + + session.SQL("START TRANSACTION").Execute(); + var docResult = coll.Find("_id >1").LockExclusive().Execute(); + Assert.AreEqual(2, docResult.FetchAll().Count, "Matching the document ID"); + + session2.SQL("START TRANSACTION").Execute(); + session2.SQL("SET SESSION innodb_lock_wait_timeout=1").Execute(); + + docResult = coll2.Find("_id < 3").LockShared(LockContention.SkipLocked).Execute(); + Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); + + docResult = coll2.Find("_id < 3").LockExclusive(LockContention.SkipLocked).Execute(); + Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); + + session.SQL("ROLLBACK").Execute(); + session2.SQL("ROLLBACK").Execute(); + } + } + + [Test, Description("Collection.Find() with shared lock and Collection.Modify() normal from two sessions. ")] + public void LockSharedAndModify() + { + if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); + ExecuteSQLStatement(session.SQL("SET autocommit = 0")); + using (var session2 = MySQLX.GetSession(ConnectionString)) + { + session2.SQL("SET autocommit = 0").Execute(); + Collection coll = CreateCollection("test"); + session2.SQL("ALTER TABLE `test`.`test` ADD COLUMN `$ix_i_r_index` INT GENERATED ALWAYS AS (JSON_UNQUOTE(JSON_EXTRACT(doc, '$._id'))) VIRTUAL NOT NULL, ADD UNIQUE INDEX `myIndex`(`$ix_i_r_index`)").Execute(); + var docs = new[] + { + new {_id = 1, a = 1}, + new {_id = 2, a = 2}, + new {_id = 3, a = 3} + }; + + coll.Add(docs).Execute(); + var coll2 = session2.GetSchema("test").GetCollection("test"); + + session.SQL("START TRANSACTION").Execute(); + var docResult = coll.Find("_id = 1").LockShared().Execute(); + Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); + session2.SQL("START TRANSACTION").Execute(); + // Should return immediately since document isn't locked. + docResult = coll2.Find("_id = 1").Execute(); + Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); + session2.SQL("SET SESSION innodb_lock_wait_timeout=1").Execute(); + // Should allow to modify immediately since document isn't locked. + var result = coll2.Modify("_id = 2").Set("a", 10).Execute(); + Assert.AreEqual(1, (int)result.AffectedItemsCount, "Match being done"); + Assert.Throws(() => ExecuteModifyStatement(coll2.Modify("_id = 1").Change("a", 10))); + + session.SQL("ROLLBACK").Execute(); + session2.SQL("ROLLBACK").Execute(); + } + + ExecuteSQLStatement(session.SQL("SET autocommit = 1")); + } + + [Test, Description("Collection.Find() with shared lock from two sessions. ")] + public void LockSharedTwoSessions() + { + if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); + ExecuteSQLStatement(session.SQL("SET autocommit = 0")); + using (var session2 = MySQLX.GetSession(ConnectionString)) + { + session2.SQL("SET autocommit = 0").Execute(); + Collection coll = CreateCollection("test"); + session2.SQL("ALTER TABLE `test`.`test` ADD COLUMN `$ix_i_r_index` INT GENERATED ALWAYS AS (JSON_EXTRACT(doc, '$._id')) VIRTUAL NOT NULL, ADD UNIQUE INDEX `myIndex`(`$ix_i_r_index`)").Execute(); + var docs = new[] + { + new {_id = 1, a = 1}, + new {_id = 2, a = 1}, + new {_id = 3, a = 1} + }; + + coll.Add(docs).Execute(); + var coll2 = session2.GetSchema("test").GetCollection("test"); + + session.SQL("START TRANSACTION").Execute(); + var docResult = coll.Find("_id = 1").LockShared().Execute(); + Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); + session2.SQL("START TRANSACTION").Execute(); + // Should return immediately since document isn't locked. + docResult = coll2.Find("_id = 2").LockShared().Execute(); + Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); + // Should return immediately due to LockShared() allows reading by other sessions. + docResult = coll2.Find("_id = 1").LockShared().Execute(); + Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); + session.SQL("ROLLBACK").Execute(); + session2.SQL("ROLLBACK").Execute(); + } + + ExecuteSQLStatement(session.SQL("SET autocommit = 1")); + } + + [Test, Description("Collection.Find() with exclusive lock and Collection.Find() with shared lock from two sessions. ")] + public void LockExclusiveFindAndLockSharedFind() + { + if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); + ExecuteSQLStatement(session.SQL("SET autocommit = 0")); + using (var session2 = MySQLX.GetSession(ConnectionString)) + { + session2.SQL("SET autocommit = 0").Execute(); + Collection coll = CreateCollection("test"); + session2.SQL("ALTER TABLE `test`.`test` ADD COLUMN `$ix_i_r_index` INT GENERATED ALWAYS AS (JSON_UNQUOTE(JSON_EXTRACT(doc, '$._id'))) VIRTUAL NOT NULL, ADD UNIQUE INDEX `myIndex`(`$ix_i_r_index`)").Execute(); + var docs = new[] + { + new {_id = 1, a = 1}, + new {_id = 2, a = 1}, + new {_id = 3, a = 1} + }; + + coll.Add(docs).Execute(); + var coll2 = session2.GetSchema("test").GetCollection("test"); + + session.SQL("START TRANSACTION").Execute(); + var docResult = coll.Find("_id = 1").LockExclusive().Execute(); + Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); + session2.SQL("START TRANSACTION").Execute(); + // Should return immediately since document isn't locked. + docResult = coll2.Find("_id = 2").LockShared().Execute(); + Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); + session2.SQL("SET SESSION innodb_lock_wait_timeout=1").Execute(); + // Session2 blocks due to LockExclusive() not allowing to read locked documents. + Assert.Throws(() => ExecuteFindStatement(coll2.Find("_id = 1").LockShared())); + // Session unlocks documents. + session.SQL("ROLLBACK").Execute(); + docResult = coll2.Find("_id = 1").LockShared().Execute(); + Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); + docResult = coll.Find("_id = 1").LockShared().Execute(); + Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); + session2.SQL("ROLLBACK").Execute(); + } + + ExecuteSQLStatement(session.SQL("SET autocommit = 1")); + } + + [Test, Description("Collection.Find() with shared lock and Collection.Find() with exclusive lock from two sessions. ")] + public void LockSharedFindAndExclusiveLocks() + { + if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); + ExecuteSQLStatement(session.SQL("SET autocommit = 0")); + using (var session2 = MySQLX.GetSession(ConnectionString)) + { + session2.SQL("SET autocommit = 0").Execute(); + Collection coll = CreateCollection("test"); + session2.SQL("ALTER TABLE `test`.`test` ADD COLUMN `$ix_i_r_index` INT GENERATED ALWAYS AS (JSON_UNQUOTE(JSON_EXTRACT(doc, '$._id'))) VIRTUAL NOT NULL, ADD UNIQUE INDEX `myIndex`(`$ix_i_r_index`)").Execute(); + var docs = new[] + { + new {_id = 1, a = 1}, + new {_id = 2, a = 1}, + new {_id = 3, a = 1} + }; + + coll.Add(docs).Execute(); + var coll2 = session2.GetSchema("test").GetCollection("test"); + + session.SQL("START TRANSACTION").Execute(); + var docResult = coll.Find("_id = 1").LockShared().Execute(); + Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document IDs"); + docResult = coll.Find("_id = 3").LockShared().Execute(); + Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document IDs"); + session2.SQL("START TRANSACTION").Execute(); + + // Should return immediately since document isn't locked. + docResult = coll2.Find("_id = 2").LockExclusive().Execute(); + Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); + // Should return immediately due to LockShared() allows reading by other sessions. + docResult = coll2.Find("_id = 2").LockShared().Execute(); + Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); + session2.SQL("SET SESSION innodb_lock_wait_timeout=1").Execute(); + // Session1 blocks due to LockExclusive() not allowing to read locked documents. + coll2.Find("_id = 2").LockExclusive().Execute(); + Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); + Assert.Throws(() => ExecuteFindStatement(coll2.Find("_id = 1").LockExclusive())); + Assert.Throws(() => ExecuteModifyStatement(coll2.Modify("_id = 1").Set("a", 100))); + // Session unlocks documents. + session2.SQL("ROLLBACK").Execute(); + session.SQL("ROLLBACK").Execute(); + } + + ExecuteSQLStatement(session.SQL("SET autocommit = 1")); + } + + [Test, Description("Collection.Find() with exclusive lock and Collection.Find() with exclusive lock from two sessions. ")] + public void LockExclusiveWithRollback() + { + if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); + ExecuteSQLStatement(session.SQL("SET autocommit = 0")); + using (var session2 = MySQLX.GetSession(ConnectionString)) + { + session2.SQL("SET autocommit = 0").Execute(); + Collection coll = CreateCollection("test"); + session2.SQL("ALTER TABLE `test`.`test` ADD COLUMN `$ix_i_r_index` INT GENERATED ALWAYS AS (JSON_UNQUOTE(JSON_EXTRACT(doc, '$._id'))) VIRTUAL NOT NULL, ADD UNIQUE INDEX `myIndex`(`$ix_i_r_index`)").Execute(); + var docs = new[] + { + new {_id = 1, a = 1}, + new {_id = 2, a = 1}, + new {_id = 3, a = 1} + }; + + coll.Add(docs).Execute(); + var coll2 = session2.GetSchema("test").GetCollection("test"); + + session.SQL("START TRANSACTION").Execute(); + var docResult = coll.Find("_id = 1").LockExclusive().Execute(); + Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document IDs"); + session2.SQL("START TRANSACTION").Execute(); + // Should return immediately due to LockShared() allows reading by other sessions. + docResult = coll2.Find("_id = 2").LockExclusive().Execute(); + Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); + session.SQL("SET SESSION innodb_lock_wait_timeout=1").Execute(); + Assert.Throws(() => ExecuteFindStatement(coll.Find("_id = 2").LockExclusive())); + session2.SQL("SET SESSION innodb_lock_wait_timeout=1").Execute(); + // Session1 blocks due to LockExclusive() not allowing to read locked documents. + Assert.Throws(() => ExecuteFindStatement(coll2.Find("_id = 1").LockExclusive())); + // Session unlocks documents. + session2.SQL("ROLLBACK").Execute(); + docResult = coll.Find("_id = 2").LockExclusive().Execute(); + Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); + session.SQL("ROLLBACK").Execute(); + docResult = coll2.Find("_id = 1").LockExclusive().Execute(); + Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); + } + + ExecuteSQLStatement(session.SQL("SET autocommit = 1")); + } + + [Test, Description("Collection.Find() with exclusive lock and Collection.Find() with exclusive lock from two sessions--Select multiple records ")] + public void LockExclusiveWithINSelection() + { + if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher"); + ExecuteSQLStatement(session.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); + using (var session2 = MySQLX.GetSession(ConnectionString)) + { + ExecuteSQLStatement(session2.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); + Collection coll = CreateCollection("test"); + var docs = new[] + { + new {_id = 1, a = 1}, + new {_id = 2, a = 1}, + new {_id = 3, a = 1} + }; + + coll.Add(docs).Execute(); + session2.SQL("ALTER TABLE `test`.`test` ADD COLUMN `$ix_i_r_index` INT GENERATED ALWAYS AS (JSON_UNQUOTE(JSON_EXTRACT(doc, '$._id'))) VIRTUAL NOT NULL, ADD UNIQUE INDEX `myIndex`(`$ix_i_r_index`)").Execute(); + var coll2 = session2.GetSchema("test").GetCollection("test"); + session.SQL("START TRANSACTION").Execute(); + var docResult = coll.Find("_id in (1,3)").LockExclusive().Execute(); + Assert.AreEqual(2, docResult.FetchAll().Count, "Matching the document ID"); + session2.SQL("START TRANSACTION").Execute(); + // Should return immediately since document isn't locked. + docResult = coll2.Find("_id = 2").LockExclusive().Execute(); + Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); + // Should return immediately due to LockShared() allows reading by other sessions. + docResult = coll2.Find("_id = 2").LockShared().Execute(); + Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); + session2.SQL("SET SESSION innodb_lock_wait_timeout=1").Execute(); + // Session1 blocks due to LockExclusive() not allowing to read locked documents. + coll2.Find("_id = 2").LockExclusive().Execute(); + Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); + Assert.Throws(() => ExecuteFindStatement(coll2.Find("_id = 1").LockExclusive())); + Assert.Throws(() => ExecuteModifyStatement(coll2.Modify("_id = 1").Set("a", 100))); + // Session unlocks documents. + session2.SQL("ROLLBACK").Execute(); + session.SQL("ROLLBACK").Execute(); + } + + ExecuteSQLStatement(session.SQL("SET autocommit = 1")); + } + + [Test, Description("Collection.Find() with shared lock twice ")] + public void LockSharedReadTwice() + { + if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); + ExecuteSQLStatement(session.SQL("SET autocommit = 0")); + using (var session2 = MySQLX.GetSession(ConnectionString)) + { + session2.SQL("SET autocommit = 0").Execute(); + Collection coll = CreateCollection("test"); + session2.SQL("ALTER TABLE `test`.`test` ADD COLUMN `$ix_i_r_index` INT GENERATED ALWAYS AS (JSON_UNQUOTE(JSON_EXTRACT(doc, '$._id'))) VIRTUAL NOT NULL, ADD UNIQUE INDEX `myIndex`(`$ix_i_r_index`)").Execute(); + var docs = new[] + { + new {_id = 1, a = 1}, + new {_id = 2, a = 1}, + new {_id = 3, a = 1} + }; + coll.Add(docs).Execute(); + var coll2 = session2.GetSchema("test").GetCollection("test"); + + session.SQL("START TRANSACTION").Execute(); + var docResult = coll.Find("_id = 1").LockShared().Execute(); + Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); + session2.SQL("START TRANSACTION").Execute(); + + // Should return immediately since document isn't locked. + docResult = coll2.Find("_id = 2").LockExclusive().Execute(); + Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); + docResult = coll2.Find("_id = 2").LockExclusive().Execute(); + Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); + docResult = coll2.Find("_id = 2").LockShared().Execute(); + Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); + docResult = coll2.Find("_id = 2").LockShared().Execute(); + Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); + // Session unlocks documents. + session2.SQL("ROLLBACK").Execute(); + session.SQL("ROLLBACK").Execute(); + } + ExecuteSQLStatement(session.SQL("SET autocommit = 1")); + } + + [Test, Description("Test MySQLX plugin Collection Array or Object contains operator Scenarios-1")] + public void FindInJsonObjects() + { + if (!Platform.IsWindows()) Assert.Ignore("This test is for Windows OS only"); + if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher."); + + var col = CreateCollection("my_collection_1"); + string json = @"{ ""_id"": 0, ""title"": ""Book 0"" ,""pages"": 10,""name"": ""Jeoff Archer""}"; + Result r = col.Add(json).Execute(); + Assert.AreEqual(1, (int)r.AffectedItemsCount, "Matching Affected Records Count"); + var foundDocs = col.Find("1 in (1,2,3,6)").Execute(); + Assert.AreEqual(1, foundDocs.FetchAll().Count, "Matching Count"); + //var result = col.Find("0 in $._id").Fields("$.name as name, $.pages as pages, $.title as title").Execute(); + foundDocs = col.Find("'Book 0' in $.title").Execute(); + Assert.AreEqual(1, foundDocs.FetchAll().Count, "Matching Count"); + foundDocs = col.Find("100 in _id").Execute(); + Assert.AreEqual(0, foundDocs.FetchAll().Count, "Matching Count"); + foundDocs = col.Find("100 not in _id").Execute(); + Assert.AreEqual(1, foundDocs.FetchAll().Count, "Matching Count"); + + json = @"{ ""_id"" : 99950, ""city"" : ""KETCHIKAN"", ""loc"" : ""[ -133.18479, 55.942471 ]"", ""pop"" : 422, ""state"" : ""AK"" }"; + r = col.Add(json).Execute(); + + + var d = new DbDoc(@"{ ""id"": 1, ""pages"": 20, + ""person"": { ""name"": ""Fred"", ""age"": 45 } + }"); + var d2 = new DbDoc(); + d2.SetValue("id", 1); + d2.SetValue("pages", 20); + d2.SetValue("person", new { name = "Fred", age = 45 }); + + Assert.AreEqual(d.Equals(d2), true, "Matching"); + col.Add(d).Execute(); + + + d = new DbDoc(@"{""id"":100,""FirstName"":""xyz"",""lastname"":""pqr"", + ""address"": + {""house"":44,""city"":""Delhi"",""country"":""india""}}"); + col.Add(d).Execute(); + + d = new DbDoc(@"{""customerId"":100,""FirstName"":""xyz"",""lastname"":""pqr"", + ""address"": + {""house"":44,""city"":""Delhi"",""country"":""india""}, + ""employer"": + {""cmpName"":""ABC"",""type"":""IT""}}"); + col.Add(d).Execute(); + + d = new DbDoc(@"{ ""id"": 1, ""pages"": 20, + ""books"": [ + {""_id"" : 1, ""title"" : ""Book 1""}, + { ""_id"" : 2, ""title"" : ""Book 2"" } + ] + }"); + col.Add(d).Execute(); + + var docs = new[] { new { _id = 1, title = "Book 1" }, new { _id = 2, title = "Book 2" } }; + d2 = new DbDoc(); + d2.SetValue("id", 100); + d2.SetValue("pages", 20); + d2.SetValue("books", docs); + col.Add(d2).Execute(); + + var result = col.Find("0 in $._id").Fields("$._id as _id,$.name as name, $.pages as pages, $.title as title").Execute(); + var res1 = result.FetchOne(); + Assert.AreEqual(0, res1["_id"]); + Assert.AreEqual("Jeoff Archer", res1["name"]); + Assert.AreEqual(10, res1["pages"]); + Assert.AreEqual("Book 0", res1["title"]); + + result = col.Find("0 in $._id OR 1 in $._id").Fields("$._id as _id,$.name as name, $.pages as pages, $.title as title").Execute(); + res1 = result.FetchOne(); + Assert.AreEqual(0, res1["_id"]); + Assert.AreEqual("Jeoff Archer", res1["name"]); + Assert.AreEqual(10, res1["pages"]); + Assert.AreEqual("Book 0", res1["title"]); + + result = col.Find("0 not in $._id").Fields("$._id as _id,$.name as name, $.pages as pages, $.title as title").Execute(); + var res2 = result.FetchAll(); + Assert.AreEqual(6, res2.Count, "Matching the find count"); + + result = col.Find("'Jeoff Archer' in $.name").Execute(); + res1 = result.FetchOne(); + Assert.AreEqual(0, res1["_id"]); + Assert.AreEqual("Jeoff Archer", res1["name"]); + Assert.AreEqual(10, res1["pages"]); + Assert.AreEqual("Book 0", res1["title"]); + + result = col.Find("0 not in $._id").Fields().Execute(); + res2 = result.FetchAll(); + Assert.IsNotNull(res2[0]["_id"]); + + var test = new DbDoc(); + test.SetValue("_id", 1); + test.SetValue("age", 3488888888.9); + test.SetValue("name", + "ABBBBBBBBBBBBBBXXXXXXXXXXXXXXXYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYTTTTTTYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYABBBBBBBBBBBBBBXXXXXXXXXXXXXXXYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYTTTTTTYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYABBBBBBBBBBBBBBXXXXXXXXXXXXXXXYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYTTTTTTYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYABBBBBBBBBBBBBBXXXXXXXXXXXXXXXYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYTTTTTTYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYABBBBBBBBBBBBBBXXXXXXXXXXXXXXXYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYTTTTTTYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY"); + + var coll = CreateCollection("my_collection_123456789"); + var res = coll.Add(test).Execute(); + var foundDocs2 = coll + .Find( + "'ABBBBBBBBBBBBBBXXXXXXXXXXXXXXXYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYTTTTTTYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYABBBBBBBBBBBBBBXXXXXXXXXXXXXXXYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYTTTTTTYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYABBBBBBBBBBBBBBXXXXXXXXXXXXXXXYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYTTTTTTYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYABBBBBBBBBBBBBBXXXXXXXXXXXXXXXYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYTTTTTTYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYABBBBBBBBBBBBBBXXXXXXXXXXXXXXXYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYTTTTTTYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY' in $.name") + .Execute(); + var docs1 = foundDocs2.FetchAll(); + Assert.AreEqual(1, docs1.Count); + foundDocs2 = coll.Find("3488888888.9 in $.age").Execute(); + docs1 = foundDocs2.FetchAll(); + Assert.AreEqual(1, docs1.Count); + } + + [Test, Description("Test MySQLX plugin Collection Array or Object contains operator Scenarios-3")] + public void FindAndCountJsonValues() + { + if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher."); + + var col = CreateCollection("my_collection_1"); + Result add; + add = col.Add("{ \"name\": \"abcdefghijk\", \"age\": 1 , \"misc\": \"10-15-2017\"}") + .Add("{ \"name\": \"xyz\", \"age\": 6 , \"misc\": \"19.5\"}").Execute(); + add = col.Add("{ \"name\": \"qwerty@#$%^&\", \"age\": 4 , \"misc\": \"11.9\"}").Execute(); + add = col.Add("{ \"name\": [\"name1\", \"name2\", \"name3\"], \"age\": 1 , \"misc\": \"1.2\"}").Execute(); + add = col.Add( + "{ \"name\": {\"first\" : \"ABCDEF1\", \"middle\" : \"ABCDEF2\", \"last\" : \"ABCDEF3\"}, " + + "\"age\": 1 , \"misc\": \"1.2\"}") + .Execute(); + add = col.Add( + "{ \"name\": {\"first\" : \"ABCDEF1\", \"middle\" : \"ABCDEF2\", \"last\" : \"ABCDEF3\"}, " + + "\"age\": 2, \"misc\": \"1.2\"}") + .Execute(); + var docs = col.Find().Execute(); + var result1 = col.Find("\"10-15-2017\" in $.misc").Execute().FetchAll().Count; + Assert.AreEqual(1, result1); + result1 = col.Find("\"10-15-2019\" in $.misc").Execute().FetchAll().Count; + Assert.AreEqual(0, result1); + var doc = docs.FetchOne(); + var result = col.Find("1 in $.age").Fields("$.name as name, $.age as age, $.misc as misc").Sort("name DESC").Execute(); + Assert.AreEqual(3, result.FetchAll().Count); + var coll = CreateCollection("test"); + coll.Add(new DbDoc("{ \"a\": 1, \"b\": [ 1, \"value\" ], \"d\":\"\", \"ARR1\":[\"Field-1-Data-0\"] }")).Execute(); + result = coll.Find("JSON_TYPE($.ARR1) = 'ARRAY' AND \"Field-1-Data-0\" in $.ARR1").Execute(); + var count = result.FetchAll().Count; + Assert.AreEqual(1, count); + + } + + [Test, Description("Test MySQLX plugin Collection Array or Object contains operator Scenarios-4")] + public void CheckCountAfterSort() + { + if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher."); + var coll = CreateCollection("test"); + coll.Add("{ \"name\": \"abcdefghijk\", \"age\": 1 , \"misc\": 1.2}") + .Add("{ \"name\": \"xyz\", \"age\": 6 , \"misc\": 19.59}").Execute(); + coll.Add("{ \"name\": \"qwerty@#$%^&\", \"age\": 4 , \"misc\": 11.9}").Execute(); + coll.Add("{ \"name\": \"name1\", \"age\": 4 , \"misc\": 11.9}").Execute(); + coll.Add("{ \"name\": [\"name1\", \"name2\", \"name3\"], \"age\": 1 , \"misc\": 1.2}").Execute(); + coll.Add("{ \"name\": {\"first\" : \"ABCDEF1\", \"middle\" : \"ABCDEF2\", \"last\" : \"ABCDEF3\"}, \"age\": 1 , \"misc\": 1.2}").Execute(); + var docs = coll.Find("4 in $.age").Execute().FetchAll().Count; + Assert.True(docs > 0); + var res3 = coll.Find("4 in $.age").Sort("name ASC").Execute().FetchAll(); + Assert.AreEqual(docs, res3.Count); + } + + [Test, Description("Test MySQLX plugin Find with overlap Bugs")] + public void FindUsingOverLapsBug() + { + if (!session.Version.isAtLeast(8, 0, 17)) Assert.Ignore("This test is for MySql 8.0.17 or higher."); + String json = ""; + String[] splName = { "+", "*", "/", "a+b", "#1", "%", "&", "@1", "!1", "~", "^", + "(", ")", "{", "}", "[", "]", "|", "JSON", "ADD", "JSON_EXTRACT", "JSON_OBJECT", + "?", "=", "+", ";", ",", ":", "<", ">", "-"}; + Collection coll = CreateCollection("test"); + for (int i = 0; i < splName.Length; i++) + { + coll.Add("{\"" + splName[i] + "\":\"data" + i + "\",\"ID\":" + i + "}").Execute(); + var docs2 = coll.Find("$.ID OVERLAPS " + i).Fields("$.`" + splName[i] + "` as col1,$.ID as Id").Execute(); + var res2 = docs2.FetchOne(); + Assert.AreEqual(i.ToString(), res2["Id"].ToString(), "Matching the ID"); + if (i == 30) + Assert.AreEqual("data" + i, "data30", "Matching the String"); + else + Assert.AreEqual("data" + i, res2["col1"].ToString(), "Matching the String"); + } + + coll = CreateCollection("test"); + json = "{\"_id\":\"1005\",\"F1\": 123,\"F2\":\"ABCD\" }"; + coll.Add(json).Execute(); + json = "{\"_id\":\"1006\",\"F1\": 123,\"F2\":\"1234\" }"; + coll.Add(json).Execute(); + json = "{\"_id\":\"1007\",\"F1\": 123,\"F2\":\"S()R%^\" }"; + coll.Add(json).Execute(); + + var docs1 = coll.Find().Fields("$._id as _id", "1 << 4 as tmp").Execute(); + var res = docs1.FetchAll(); + docs1 = coll.Find().Fields("$._id as _id", "$.F2 ^ 1 as tmp").Execute(); + res = docs1.FetchAll(); + coll.Add("{\"_id\":\"100001\",\"x1\":\"31\", \"x2\":\"13\", \"x3\":\"8\", \"x4\":\"18446744073709551614\"}").Execute(); + + docs1 = coll.Find("CAST($.x1 as SIGNED) | pow(2,$.x1) = $.x1").Fields("$._id as _id, $.x1 as x1, $.x2 as x2, $.x3 as x3 , $.x2 | pow(2,$.x1) as tmp").Execute(); + res = docs1.FetchAll(); + + docs1 = coll.Find("~16 = ~CAST($.F2 as SIGNED)").Fields("$._id as _id,$.F2 as f2, ~1 as tmp").Execute(); + res = docs1.FetchAll(); + int maxrec = 100; + DbDoc newDoc = new DbDoc(); + newDoc.SetValue("_id", maxrec + 1000); + newDoc.SetValue("F1", "Field-1-Data-" + maxrec); + newDoc.SetValue("F2", "Field-2-Data-" + maxrec); + newDoc.SetValue("F3", 300 + maxrec); + coll.Add(newDoc).Execute(); + + json = "{'_id':'" + (maxrec + 1000 + 1) + "','F1':'Field-1-Data-" + (maxrec + 1) + "','F2':'Field-2-Data-" + (maxrec + 1) + "','F3':" + (300 + maxrec + 1) + "}"; + json = json.Replace("'", "\""); + coll.Add(json).Execute(); + json = "{'F1': 'Field-1-Data-9999','F2': 'Field-2-Data-9999','F3': 'Field-3-Data-9999'}".Replace("'", "\""); + coll.Add(json).Add(json.Replace("9", "8")).Execute(); + + var docs = coll.Find("$._id OVERLAPS 1100").Fields("$_id as _id,$.F1 as f1, $.F2 as f2, $.F3 as f3").Execute(); + var res1 = docs.FetchOne(); + Assert.AreEqual("1100", res1["_id"].ToString()); + Assert.AreEqual("Field-1-Data-100", res1["f1"].ToString()); + Assert.AreEqual("Field-2-Data-100", res1["f2"].ToString()); + Assert.AreEqual("400", res1["f3"].ToString()); + Assert.Throws(() => ExecuteFindStatement(coll.Find("$.F2 OVERLAPS #").Fields("$_id as _id,$.F1 as f1, $.F2 as f2, $.F3 as f3"))); + + docs = coll.Find("$.F2 OVERLAPS 'ABCD'").Fields("$_id as _id,$.F1 as f1, $.F2 as f2, $.F3 as f3").Execute(); + res1 = docs.FetchOne(); + Assert.AreEqual("1005", res1["_id"]); + Assert.AreEqual(123, res1["f1"]); + Assert.AreEqual("ABCD", res1["f2"]); + Assert.Throws(() => ExecuteFindStatement(coll.Find("$.F2 OVERLAPS [1234").Fields("$_id as _id,$.F1 as f1, $.F2 as f2, $.F3 as f3"))); + Assert.Throws(() => ExecuteFindStatement(coll.Find("$.F2 OVERLAPS S()R%^").Fields("$_id as _id,$.F1 as f1, $.F2 as f2, $.F3 as f3"))); + + docs = coll.Find("$.F2 OVERLAPS 'S()R%^'").Fields("$_id as _id,$.F1 as f1, $.F2 as f2, $.F3 as f3").Execute(); + res1 = docs.FetchOne(); + Assert.AreEqual("1007", res1["_id"]); + Assert.AreEqual(123, res1["f1"]); + Assert.AreEqual("S()R%^", res1["f2"]); + } + + [Test, Description("Test MySQLX plugin Find with overlap and Many conditions")] + public void FindUsingOverLapsManyConditions() + { + if (!session.Version.isAtLeast(8, 0, 17)) Assert.Ignore("This test is for MySql 8.0.17 or higher."); + int Condition = 45; + int i, j = 0; + String query = ""; + Collection coll = CreateCollection("test"); + for (i = 0; i < 50; i++) + { + coll.Add("{\"_id\":\"" + i + "\",\"TEST1\":" + (1000 + j) + "}").Execute(); + j++; + } + j = 0; + for (i = 0; i < Condition; i++) + { + if (i > 0) + query = query + " OR "; + query = query + "$.TEST1 OVERLAPS " + (1000 + j); + j++; + } + var docs = coll.Find(query).Execute(); + Assert.True(docs.FetchAll().Count > 0); + } + + [Test, Description("Deprecated Find Where")] + public void FindWhere() + { + Collection collection = CreateCollection("test"); + var docs = new[] + { + new { _id = 1, title = "Book 1", pages = 20 }, + new { _id = 2, title = "Book 2", pages = 30 }, + new { _id = 3, title = "Book 3", pages = 40 }, + new { _id = 4, title = "Book 4", pages = 50 }, + }; + var result1 = collection.Add(docs).Execute(); + Assert.AreEqual(4, result1.AffectedItemsCount); + + //Deprecated Find().Where() in 8.0.17 + var result2 = collection.Find("$._id = 1").Where("true").Execute().FetchAll(); + Assert.AreEqual(4, result2.Count); + } + + [Test, Description("Test MySQLX plugin Collection match count")] + public void CollectionFindFieldMatchingCount() + { + Collection col = CreateCollection("my_collection_1"); + Collection col1 = CreateCollection("my_collection_2"); + + var d1 = new DbDoc(); + d1.SetValue("_id", 1); + d1.SetValue("books", "test1"); + d1.SetValue("count", 10); + + var d2 = new DbDoc(); + d2.SetValue("_id", 2); + d2.SetValue("books", "test2"); + d2.SetValue("count", 20); + + var d3 = new DbDoc(); + d3.SetValue("_id", 3); + d3.SetValue("books", "test3"); + d3.SetValue("count", 30); + + var d4 = new DbDoc(); + d4.SetValue("_id", 4); + d4.SetValue("books", "test4"); + d4.SetValue("count", 40); + + var d5 = new DbDoc(); + d5.SetValue("_id", 5); + d5.SetValue("books", "test5"); + d5.SetValue("count", 50); + + var d6 = new DbDoc(); + d6.SetValue("_id", 6); + d6.SetValue("books", "test6"); + d6.SetValue("count", 0); + + var d7 = new DbDoc(); + d7.SetValue("_id", 0); + d7.SetValue("books", "test7"); + d7.SetValue("count", 60); + + var final = col.Add(d1, d2).Add(d3).Execute(); + var res1 = col.Find().Fields("{\"_id\":\"1\",\"books\": \"test1\" }").Fields("{\"_id\":\"2\",\"books\": \"test2\" }").Fields("{\"_id\":\"3\",\"books\": \"test3\" }").Execute().FetchAll(); + res1 = col.Find().Fields(new string[] { "_id", "books", "count" }).Execute().FetchAll(); + Assert.AreEqual(3, res1.Count, "Matching the find count"); + Assert.AreEqual(d1.ToString(), res1[0].ToString(), "Matching the doc string 1"); + Assert.AreEqual(d2.ToString(), res1[1].ToString(), "Matching the doc string 2"); + Assert.AreEqual(d3.ToString(), res1[2].ToString(), "Matching the doc string 3"); + final = col.Add(new DbDoc[] { d4, d5 }).Execute(); + var res2 = col.Find().Fields("$._id as _id,$.books as books, $.count as count").Execute().FetchAll(); + Assert.AreEqual(5, res2.Count, "Matching the find count"); + Assert.AreEqual(d1.ToString(), res2[0].ToString(), "Matching the doc string 1"); + Assert.AreEqual(d2.ToString(), res2[1].ToString(), "Matching the doc string 2"); + Assert.AreEqual(d3.ToString(), res2[2].ToString(), "Matching the doc string 3"); + Assert.AreEqual(d4.ToString(), res2[3].ToString(), "Matching the doc string 4"); + Assert.AreEqual(d5.ToString(), res2[4].ToString(), "Matching the doc string 5"); + final = col.Add(d6, d7).Execute(); + var res3 = col.Find().Sort("count ASC").Execute().FetchAll(); + Assert.AreEqual(d6.ToString(), res3[0].ToString(), "Matching the doc string 7"); + Assert.AreEqual(d1.ToString(), res3[1].ToString(), "Matching the doc string 1"); + Assert.AreEqual(d2.ToString(), res3[2].ToString(), "Matching the doc string 2"); + Assert.AreEqual(d3.ToString(), res3[3].ToString(), "Matching the doc string 3"); + Assert.AreEqual(d4.ToString(), res3[4].ToString(), "Matching the doc string 4"); + Assert.AreEqual(d5.ToString(), res3[5].ToString(), "Matching the doc string 5"); + Assert.AreEqual(d7.ToString(), res3[6].ToString(), "Matching the doc string 6"); + var res4 = col.Find().Sort("count DESC").Execute().FetchAll(); + Assert.AreEqual(d7.ToString(), res4[0].ToString(), "Matching the doc string 6"); + Assert.AreEqual(d5.ToString(), res4[1].ToString(), "Matching the doc string 1"); + Assert.AreEqual(d4.ToString(), res4[2].ToString(), "Matching the doc string 2"); + Assert.AreEqual(d3.ToString(), res4[3].ToString(), "Matching the doc string 3"); + Assert.AreEqual(d2.ToString(), res4[4].ToString(), "Matching the doc string 4"); + Assert.AreEqual(d1.ToString(), res4[5].ToString(), "Matching the doc string 5"); + Assert.AreEqual(d6.ToString(), res4[6].ToString(), "Matching the doc string 7"); + col.Modify("_id = 1").Unset("count").Unset("books").Execute(); + col.Modify("_id = 1").Set("count", 10).Set("books", "test1").Execute(); + + } + + [Test, Description("GetName,Schema and Count")] + public void CollectionGetNameSchemaCount() + { + if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher"); + var col = CreateCollection("my_collection_123456789"); + + Result r = col.Add(@"{ ""_id"": 1, ""foo"": 1 }").Execute(); + long count = col.Count(); + Assert.AreEqual(count, 1, "Matching the Collection Count"); + + var collectionName = col.Name; + Assert.AreEqual(collectionName, "my_collection_123456789", "Matching the collection Name"); + + var schema = col.Schema.Name; + Assert.AreEqual(schema, schemaName, "Matching the Schema Name"); + + r = col.Add(@"{ ""_id"": 2, ""foo"": 2 }").Execute(); + count = col.Count(); + Assert.AreEqual(count, 2, "Matching the Collection Count"); + + r = col.Remove("_id=2").Execute(); + count = col.Count(); + Assert.AreEqual(count, 1, "Matching the Collection Count"); + session.Schema.DropCollection("my_collection_123456789"); + } + + #endregion WL14389 + + } +} + diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/BasicSelectTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/BasicSelectTests.cs index d0e451116..4f5c64bf3 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/BasicSelectTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/BasicSelectTests.cs @@ -1,147 +1,147 @@ -// Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySql.Data.MySqlClient; -using MySqlX.XDevAPI; -using MySqlX.XDevAPI.Relational; -using System; -using NUnit.Framework; - -namespace MySqlX.Data.Tests -{ - public class BasicSelectTests : BaseTest - { - [Test] - public void SimpleSelect() - { - CreateBooksTable(); - Table books = GetTable("test", "books"); - - RowResult result = ExecuteSelectStatement(books.Select("name", "pages")); - var rows = result.FetchAll(); - Assert.True(result.Columns.Count == 2); - Assert.True(rows.Count == 2); - - var result2 = session.SQL("Select* from test.books").Execute(); - var row2 = result2.FetchOne(); - Assert.True(result2.Columns.Count == 3); - } - - [Test] - public void SimpleSelectWithWhere() - { - CreateBooksTable(); - Table books = GetTable("test", "books"); - - RowResult result = ExecuteSelectStatement(books.Select("name", "pages").Where("pages > 250")); - var rows = result.FetchAll(); - Assert.True(result.Columns.Count == 2); - Assert.That(rows, Has.One.Items); - } - - private void CreateBooksTable() - { - ExecuteSQL("DROP TABLE IF EXISTS test.books"); - ExecuteSQL("CREATE TABLE test.books(id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(100), pages INT)"); - ExecuteSQL("INSERT INTO test.books VALUES (NULL, 'Moby Dick', 500)"); - ExecuteSQL("INSERT INTO test.books VALUES (NULL, 'A Tale of Two Cities', 250)"); - } - - public enum LockMode { Exclusive, Shared } - - [TestCase(LockContention.Default, LockMode.Exclusive)] - [TestCase(LockContention.NoWait, LockMode.Exclusive)] - [TestCase(LockContention.SkipLocked, LockMode.Exclusive)] - [TestCase(LockContention.Default, LockMode.Shared)] - [TestCase(LockContention.NoWait, LockMode.Shared)] - [TestCase(LockContention.SkipLocked, LockMode.Shared)] - public void LockExclusiveAndSharedWithWaitingOptions(LockContention lockOption, LockMode lockMode) - { - if (!session.XSession.GetServerVersion().isAtLeast(8, 0, 3)) return; - - CreateBooksTable(); - string tableName = "books"; - string schemaName = "test"; - - // first session locks the row - using (Session s1 = MySQLX.GetSession(ConnectionString)) - { - var t1 = s1.GetSchema(schemaName).GetTable(tableName); - s1.StartTransaction(); - RowResult r1 = ExecuteSelectStatement(t1.Select().Where("id = :id").Bind("id", 1).LockExclusive()); - var rows1 = r1.FetchAll(); - Assert.That(rows1, Has.One.Items); - Assert.AreEqual(1, rows1[0]["id"]); - - // second session tries to read the locked row - using (Session s2 = MySQLX.GetSession(ConnectionString)) - { - var t2 = s2.GetSchema(schemaName).GetTable(tableName); - ExecuteSQLStatement(s2.SQL("SET innodb_lock_wait_timeout = 1")); - s2.StartTransaction(); - var stmt2 = t2.Select(); - if (lockMode == LockMode.Exclusive) - stmt2.LockExclusive(lockOption); - else - stmt2.LockShared(lockOption); - - switch (lockOption) - { - case LockContention.Default: - // error 1205 Lock wait timeout exceeded; try restarting transaction - Assert.AreEqual(1205u, Assert.Throws(() => ExecuteSelectStatement(stmt2).FetchAll()).Code); - break; - case LockContention.NoWait: - // error 1205 Lock wait timeout exceeded; try restarting transaction - uint expectedError = 1205; - if (session.XSession.GetServerVersion().isAtLeast(8, 0, 5)) - // error 3572 Statement aborted because lock(s) could not be acquired immediately and NOWAIT is set - expectedError = 3572; - Assert.AreEqual(expectedError, Assert.Throws(() => ExecuteSelectStatement(stmt2).FetchAll()).Code); - break; - case LockContention.SkipLocked: - if (!session.XSession.GetServerVersion().isAtLeast(8, 0, 5)) - { - // error 1205 Lock wait timeout exceeded; try restarting transaction - Assert.AreEqual(1205u, Assert.Throws(() => ExecuteSelectStatement(stmt2).FetchAll()).Code); - break; - } - var rows2 = ExecuteSelectStatement(stmt2).FetchAll(); - Assert.That(rows2, Has.One.Items); - Assert.AreEqual(2, rows2[0]["id"]); - break; - default: - throw new NotImplementedException(lockOption.ToString()); - } - } - // first session frees the lock - s1.Commit(); - } - } - } -} +// Copyright © 2015, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySql.Data.MySqlClient; +using MySqlX.XDevAPI; +using MySqlX.XDevAPI.Relational; +using System; +using NUnit.Framework; + +namespace MySqlX.Data.Tests +{ + public class BasicSelectTests : BaseTest + { + [Test] + public void SimpleSelect() + { + CreateBooksTable(); + Table books = GetTable("test", "books"); + + RowResult result = ExecuteSelectStatement(books.Select("name", "pages")); + var rows = result.FetchAll(); + Assert.True(result.Columns.Count == 2); + Assert.True(rows.Count == 2); + + var result2 = session.SQL("Select* from test.books").Execute(); + var row2 = result2.FetchOne(); + Assert.True(result2.Columns.Count == 3); + } + + [Test] + public void SimpleSelectWithWhere() + { + CreateBooksTable(); + Table books = GetTable("test", "books"); + + RowResult result = ExecuteSelectStatement(books.Select("name", "pages").Where("pages > 250")); + var rows = result.FetchAll(); + Assert.True(result.Columns.Count == 2); + Assert.That(rows, Has.One.Items); + } + + private void CreateBooksTable() + { + ExecuteSQL("DROP TABLE IF EXISTS test.books"); + ExecuteSQL("CREATE TABLE test.books(id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(100), pages INT)"); + ExecuteSQL("INSERT INTO test.books VALUES (NULL, 'Moby Dick', 500)"); + ExecuteSQL("INSERT INTO test.books VALUES (NULL, 'A Tale of Two Cities', 250)"); + } + + public enum LockMode { Exclusive, Shared } + + [TestCase(LockContention.Default, LockMode.Exclusive)] + [TestCase(LockContention.NoWait, LockMode.Exclusive)] + [TestCase(LockContention.SkipLocked, LockMode.Exclusive)] + [TestCase(LockContention.Default, LockMode.Shared)] + [TestCase(LockContention.NoWait, LockMode.Shared)] + [TestCase(LockContention.SkipLocked, LockMode.Shared)] + public void LockExclusiveAndSharedWithWaitingOptions(LockContention lockOption, LockMode lockMode) + { + if (!session.XSession.GetServerVersion().isAtLeast(8, 0, 3)) return; + + CreateBooksTable(); + string tableName = "books"; + string schemaName = "test"; + + // first session locks the row + using (Session s1 = MySQLX.GetSession(ConnectionString)) + { + var t1 = s1.GetSchema(schemaName).GetTable(tableName); + s1.StartTransaction(); + RowResult r1 = ExecuteSelectStatement(t1.Select().Where("id = :id").Bind("id", 1).LockExclusive()); + var rows1 = r1.FetchAll(); + Assert.That(rows1, Has.One.Items); + Assert.AreEqual(1, rows1[0]["id"]); + + // second session tries to read the locked row + using (Session s2 = MySQLX.GetSession(ConnectionString)) + { + var t2 = s2.GetSchema(schemaName).GetTable(tableName); + ExecuteSQLStatement(s2.SQL("SET innodb_lock_wait_timeout = 1")); + s2.StartTransaction(); + var stmt2 = t2.Select(); + if (lockMode == LockMode.Exclusive) + stmt2.LockExclusive(lockOption); + else + stmt2.LockShared(lockOption); + + switch (lockOption) + { + case LockContention.Default: + // error 1205 Lock wait timeout exceeded; try restarting transaction + Assert.AreEqual(1205u, Assert.Throws(() => ExecuteSelectStatement(stmt2).FetchAll()).Code); + break; + case LockContention.NoWait: + // error 1205 Lock wait timeout exceeded; try restarting transaction + uint expectedError = 1205; + if (session.XSession.GetServerVersion().isAtLeast(8, 0, 5)) + // error 3572 Statement aborted because lock(s) could not be acquired immediately and NOWAIT is set + expectedError = 3572; + Assert.AreEqual(expectedError, Assert.Throws(() => ExecuteSelectStatement(stmt2).FetchAll()).Code); + break; + case LockContention.SkipLocked: + if (!session.XSession.GetServerVersion().isAtLeast(8, 0, 5)) + { + // error 1205 Lock wait timeout exceeded; try restarting transaction + Assert.AreEqual(1205u, Assert.Throws(() => ExecuteSelectStatement(stmt2).FetchAll()).Code); + break; + } + var rows2 = ExecuteSelectStatement(stmt2).FetchAll(); + Assert.That(rows2, Has.One.Items); + Assert.AreEqual(2, rows2[0]["id"]); + break; + default: + throw new NotImplementedException(lockOption.ToString()); + } + } + // first session frees the lock + s1.Commit(); + } + } + } +} diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/CharsetAndCollationTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/CharsetAndCollationTests.cs index 47571507a..a32cf7065 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/CharsetAndCollationTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/CharsetAndCollationTests.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2017, 2022, Oracle and/or its affiliates. +// Copyright © 2017, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/ClientSideFailoverTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/ClientSideFailoverTests.cs index e36fdcd25..f6f525b95 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/ClientSideFailoverTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/ClientSideFailoverTests.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2017, 2022, Oracle and/or its affiliates. +// Copyright © 2017, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/ClientTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/ClientTests.cs index b1bd83d3b..522035522 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/ClientTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/ClientTests.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2018, 2022, Oracle and/or its affiliates. +// Copyright © 2018, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -2663,4 +2663,4 @@ public async void VerifyClientAsync(Client client1) #endregion Methods } -} \ No newline at end of file +} diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/CloseConnectionTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/CloseConnectionTests.cs index b9c3a51ea..e1ccd486f 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/CloseConnectionTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/CloseConnectionTests.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2020, 2021, Oracle and/or its affiliates. +// Copyright © 2020, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/CollectionAsyncTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/CollectionAsyncTests.cs index a74b331ec..3a9d9f8c0 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/CollectionAsyncTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/CollectionAsyncTests.cs @@ -1,134 +1,134 @@ -// Copyright (c) 2015, 2023, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySqlX.XDevAPI; -using MySqlX.XDevAPI.Common; -using MySqlX.XDevAPI.CRUD; -using NUnit.Framework; -using System; -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; - -namespace MySqlX.Data.Tests -{ - public class CollectionAsyncTests : BaseTest - { - [Test] - public void CollectionInsert() - { - var coll = CreateCollection("test"); - List> tasksList = new List>(); - - for (int i = 1; i <= 200; i++) - { - tasksList.Add(coll.Add(string.Format(@"{{ ""_id"": {0}, ""foo"": {0} }}", i)).ExecuteAsync()); - } - - Task.WaitAll(tasksList.ToArray(), TimeSpan.FromMinutes(1)); - - var count = session.SQL("SELECT COUNT(*) FROM test.test").Execute().FetchOne()[0]; - Assert.AreEqual(count, coll.Count()); - } - - [Test] - public void MultipleFindAsync() - { - var coll = CreateCollection("test"); - int docs = 100; - HashSet validator = new HashSet(); - var addStatement = coll.Add(new { id = 1, age = 1 }); - - for (int i = 2; i <= docs; i++) - { - addStatement.Add(new { id = i, age = i }); - } - var result = ExecuteAddStatement(addStatement); - - List>> tasksList = new List>>(); - - for (int i = 1; i <= docs; i++) - { - tasksList.Add(coll.Find("age = :age").Bind("AgE", i).ExecuteAsync()); - } - - Assert.True(Task.WaitAll(tasksList.ToArray(), TimeSpan.FromMinutes(2)), "WaitAll timeout"); - foreach (Task> task in tasksList) - { - var doc = task.Result.FetchOne(); - string value = task.Result.Current["age"].ToString(); - Assert.False(validator.Contains(value), value + " value exists"); - validator.Add(value); - } - Assert.AreEqual(docs, validator.Count); - } - - [Test, Description("Create valid index using a document field type of array and setting array to true/with single key on all possible datatypes concurrently)")] - public async Task IndexArrayMultiThreading() - { - var coll = CreateCollection("test"); - // For server not supporting array indexes, array option will be ignored and and old-style index will be created. - if (!session.Version.isAtLeast(8, 0, 17)) - { - coll.CreateIndex("myIndex", "{\"fields\": [{\"field\": $.myField, \"type\":\"DATE\", \"array\": true}]}"); - return; - } - int v1 = await IndexArrayMultiThreading_T1(); - int v2 = await IndexArrayMultiThreading_T2(); - - Assert.AreEqual(2, v1 + v2); - } - - private async Task IndexArrayMultiThreading_T1() - { - Schema test = session.GetSchema(schemaName); - var coll = test.GetCollection("test"); - Thread.Sleep(100); - coll.CreateIndex("multiArrayIndex1", "{\"fields\": [{\"field\": \"$.intField\", \"type\": \"INT\", \"array\": false}," + - "{\"field\": \"$.charField\", \"type\": \"CHAR(255)\", \"array\": false}," + - "{\"field\": \"$.decimalField\", \"type\": \"DECIMAL\", \"array\": true}," + - "{\"field\": \"$.dateField\", \"type\": \"DATE\", \"array\": false}," + - "{\"field\": \"$.timeField\", \"type\": \"TIME\", \"array\": false}," + - "{\"field\": \"$.datetimeField\", \"type\": \"DATETIME\", \"array\": false}]}"); - return 1; - } - - private async Task IndexArrayMultiThreading_T2() - { - Schema test = session.GetSchema(schemaName); - var coll = test.GetCollection("test"); - coll.CreateIndex("multiArrayIndex2", "{\"fields\": [{\"field\": \"$.intField\", \"type\": \"INT\", \"array\": false}," + - "{\"field\": \"$.charField\", \"type\": \"CHAR(255)\", \"array\": false}," + - "{\"field\": \"$.decimalField\", \"type\": \"DECIMAL\", \"array\": true}," + - "{\"field\": \"$.dateField\", \"type\": \"DATE\", \"array\": false}," + - "{\"field\": \"$.timeField\", \"type\": \"TIME\", \"array\": false}," + - "{\"field\": \"$.datetimeField\", \"type\": \"DATETIME\", \"array\": false}]}"); - return 1; - } - } -} +// Copyright © 2015, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySqlX.XDevAPI; +using MySqlX.XDevAPI.Common; +using MySqlX.XDevAPI.CRUD; +using NUnit.Framework; +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; + +namespace MySqlX.Data.Tests +{ + public class CollectionAsyncTests : BaseTest + { + [Test] + public void CollectionInsert() + { + var coll = CreateCollection("test"); + List> tasksList = new List>(); + + for (int i = 1; i <= 200; i++) + { + tasksList.Add(coll.Add(string.Format(@"{{ ""_id"": {0}, ""foo"": {0} }}", i)).ExecuteAsync()); + } + + Task.WaitAll(tasksList.ToArray(), TimeSpan.FromMinutes(1)); + + var count = session.SQL("SELECT COUNT(*) FROM test.test").Execute().FetchOne()[0]; + Assert.AreEqual(count, coll.Count()); + } + + [Test] + public void MultipleFindAsync() + { + var coll = CreateCollection("test"); + int docs = 100; + HashSet validator = new HashSet(); + var addStatement = coll.Add(new { id = 1, age = 1 }); + + for (int i = 2; i <= docs; i++) + { + addStatement.Add(new { id = i, age = i }); + } + var result = ExecuteAddStatement(addStatement); + + List>> tasksList = new List>>(); + + for (int i = 1; i <= docs; i++) + { + tasksList.Add(coll.Find("age = :age").Bind("AgE", i).ExecuteAsync()); + } + + Assert.True(Task.WaitAll(tasksList.ToArray(), TimeSpan.FromMinutes(2)), "WaitAll timeout"); + foreach (Task> task in tasksList) + { + var doc = task.Result.FetchOne(); + string value = task.Result.Current["age"].ToString(); + Assert.False(validator.Contains(value), value + " value exists"); + validator.Add(value); + } + Assert.AreEqual(docs, validator.Count); + } + + [Test, Description("Create valid index using a document field type of array and setting array to true/with single key on all possible datatypes concurrently)")] + public async Task IndexArrayMultiThreading() + { + var coll = CreateCollection("test"); + // For server not supporting array indexes, array option will be ignored and and old-style index will be created. + if (!session.Version.isAtLeast(8, 0, 17)) + { + coll.CreateIndex("myIndex", "{\"fields\": [{\"field\": $.myField, \"type\":\"DATE\", \"array\": true}]}"); + return; + } + int v1 = await IndexArrayMultiThreading_T1(); + int v2 = await IndexArrayMultiThreading_T2(); + + Assert.AreEqual(2, v1 + v2); + } + + private async Task IndexArrayMultiThreading_T1() + { + Schema test = session.GetSchema(schemaName); + var coll = test.GetCollection("test"); + Thread.Sleep(100); + coll.CreateIndex("multiArrayIndex1", "{\"fields\": [{\"field\": \"$.intField\", \"type\": \"INT\", \"array\": false}," + + "{\"field\": \"$.charField\", \"type\": \"CHAR(255)\", \"array\": false}," + + "{\"field\": \"$.decimalField\", \"type\": \"DECIMAL\", \"array\": true}," + + "{\"field\": \"$.dateField\", \"type\": \"DATE\", \"array\": false}," + + "{\"field\": \"$.timeField\", \"type\": \"TIME\", \"array\": false}," + + "{\"field\": \"$.datetimeField\", \"type\": \"DATETIME\", \"array\": false}]}"); + return 1; + } + + private async Task IndexArrayMultiThreading_T2() + { + Schema test = session.GetSchema(schemaName); + var coll = test.GetCollection("test"); + coll.CreateIndex("multiArrayIndex2", "{\"fields\": [{\"field\": \"$.intField\", \"type\": \"INT\", \"array\": false}," + + "{\"field\": \"$.charField\", \"type\": \"CHAR(255)\", \"array\": false}," + + "{\"field\": \"$.decimalField\", \"type\": \"DECIMAL\", \"array\": true}," + + "{\"field\": \"$.dateField\", \"type\": \"DATE\", \"array\": false}," + + "{\"field\": \"$.timeField\", \"type\": \"TIME\", \"array\": false}," + + "{\"field\": \"$.datetimeField\", \"type\": \"DATETIME\", \"array\": false}]}"); + return 1; + } + } +} diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/CollectionIndexTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/CollectionIndexTests.cs index 2ba762809..4a2a6f264 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/CollectionIndexTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/CollectionIndexTests.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2017, 2023, Oracle and/or its affiliates. +// Copyright © 2017, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -1853,4 +1853,4 @@ private void ValidateIndex(string fieldName, string collectionName, string dataT #endregion Methods } -} \ No newline at end of file +} diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/CollectionTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/CollectionTests.cs index 52baf0761..80d9f73aa 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/CollectionTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/CollectionTests.cs @@ -1,1739 +1,1739 @@ -// Copyright (c) 2015, 2022, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySql.Data; -using MySql.Data.MySqlClient; -using MySqlX.XDevAPI; -using MySqlX.XDevAPI.Common; -using MySqlX.XDevAPI.Relational; -using NUnit.Framework; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; - -namespace MySqlX.Data.Tests -{ - public class CollectionTests : BaseTest - { - [TearDown] - public void tearDown() - { - session.Schema.DropCollection("test"); - session.Schema.DropCollection("test123"); - session.Schema.DropCollection("testcount"); - session.Schema.DropCollection("coll"); - session.Schema.DropCollection("col20"); - session.Schema.DropCollection("col21"); - session.Schema.DropCollection("col22"); - } - - [Test] - public void GetAllCollections() - { - session.DropSchema("test"); - session.CreateSchema("test"); - Collection book = CreateCollection("book"); - List collections = book.Schema.GetCollections(); - Assert.That(collections, Has.One.Items); - Assert.True(collections[0].Name == "book"); - book.Schema.DropCollection("book"); - } - - [Test] - public void CreateAndDropCollection() - { - Session s = GetSession(); - Schema test = s.GetSchema("test"); - Collection testColl = test.CreateCollection("test"); - Assert.True(CollectionExistsInDatabase(testColl)); - - // Drop existing collection. - test.DropCollection("test"); - Assert.False(CollectionExistsInDatabase(testColl)); - - // Drop non-existing collection. - test.DropCollection("test"); - Assert.False(CollectionExistsInDatabase(testColl)); - - //dropCollection when the object to drop contains invalid characters - test.DropCollection("%^&!@~*(&*(*&:>(() => test.DropCollection(string.Empty)); - Assert.Throws(() => test.DropCollection(" ")); - Assert.Throws(() => test.DropCollection(" ")); - Assert.Throws(() => test.DropCollection(null)); - } - - [Test] - public void CreateCollectionIndex() - { - Session session = GetSession(); - Schema test = session.GetSchema(schemaName); - Collection testColl = test.CreateCollection("test"); - Assert.True(CollectionExistsInDatabase(testColl), "ExistsInDatabase failed"); - testColl.CreateIndex("testIndex", "{ \"fields\": [ { \"field\":$.myId, \"type\":\"INT\", \"required\":true } ] }"); - var result = ExecuteAddStatement(testColl.Add(new { myId = 1 }).Add(new { myId = 2 })); - Assert.AreEqual(result.AffectedItemsCount, 2); - } - - [Test] - public void DropCollectionIndex() - { - Session session = GetSession(); - Schema test = session.GetSchema(schemaName); - Collection testColl = CreateCollection("test"); - testColl.CreateIndex("testIndex", "{ \"fields\": [ { \"field\":$.myId, \"type\":\"INT\", \"required\":true } ] }"); - - // Drop existing index. - testColl.DropIndex("testIndex"); - - // Drop non-existing index. - testColl.DropIndex("testIndex"); - - //dropIndex contains invalid characters - testColl.DropIndex("%^&!@~*(&*(*&:>(() => testColl.DropIndex(string.Empty)); - Assert.Throws(() => testColl.DropIndex(" ")); - Assert.Throws(() => testColl.DropIndex(" ")); - Assert.Throws(() => testColl.DropIndex(null)); - - } - - [Test] - public void DropSchemaTests() - { - session.DropSchema("validSchema"); - session.CreateSchema("validSchema"); - session.DropSchema("validSchema"); - session.DropSchema("%^&!@~*(&*(*&:>(() => session.DropSchema(string.Empty)); - Assert.Throws(() => session.DropSchema(" ")); - Assert.Throws(() => session.DropSchema(" ")); - Assert.Throws(() => session.DropSchema(null)); - } - - - [Test] - public void ValidateExistence() - { - Session session = GetSession(); - Schema schema = session.GetSchema(schemaName); - var ex = Assert.Throws(() => schema.GetCollection("nonExistentCollection", true)); - Assert.AreEqual("Collection 'nonExistentCollection' does not exist.", ex.Message); - } - - [Test] - public void CountCollection() - { - Session session = GetSession(); - Schema schema = session.GetSchema(schemaName); - CreateCollection("testCount"); - var count = session.SQL("SELECT COUNT(*) FROM test.testCount").Execute().FetchOne()[0]; - - // Zero records - var collection = schema.GetCollection("testCount"); - Assert.AreEqual(count, collection.Count()); - var table = schema.GetTable("testCount"); - Assert.AreEqual(count, table.Count()); - - // Insert some records - var stm = collection.Add(@"{ ""_id"": 1, ""foo"": 1 }") - .Add(@"{ ""_id"": 2, ""foo"": 2 }") - .Add(@"{ ""_id"": 3, ""foo"": 3 }"); - stm.Execute(); - count = session.SQL("SELECT COUNT(*) FROM test.testCount").Execute().FetchOne()[0]; - Assert.AreEqual(count, collection.Count()); - - table.Insert("doc").Values(@"{ ""_id"": 4, ""foo"": 4 }").Execute(); - count = session.SQL("SELECT COUNT(*) FROM test.testCount").Execute().FetchOne()[0]; - Assert.AreEqual(count, table.Count()); - - collection.RemoveOne(2); - count = session.SQL("SELECT COUNT(*) FROM test.testCount").Execute().FetchOne()[0]; - Assert.AreEqual(count, collection.Count()); - Assert.AreEqual(count, table.Count()); - - // Collection/Table does not exist - var ex = Assert.Throws(() => schema.GetCollection("testCount_").Count()); - Assert.AreEqual("Collection 'testCount_' does not exist in schema 'test'.", ex.Message); - ex = Assert.Throws(() => schema.GetTable("testCount_").Count()); - Assert.AreEqual("Table 'testCount_' does not exist in schema 'test'.", ex.Message); - } - - [Test] - public void ModifyCollectionNoLevelNorSchema() - { - Session s = GetSession(); - Schema test = s.GetSchema("test"); - - // Modify a Collection without passing schema and Level, (Bug#30660917) - test.CreateCollection("coll"); - ModifyCollectionOptions options1 = new ModifyCollectionOptions(); - options1.Validation = new Validation() { }; - Assert.Throws(() => test.ModifyCollection("coll", options1)); - } - - [Test] - public void CreateCollectionWithOptions() - { - Session s = GetSession(); - Schema test = s.GetSchema("test"); - - // CreateCollection Test Cases - - // Create a Collection passing a valid schema and Level - CreateCollectionOptions options = new CreateCollectionOptions(); - Validation val = new Validation(); - val.Level = ValidationLevel.STRICT; - string str = "{\"id\": \"http://json-schema.org/geo\"," - + "\"$schema\": \"http://json-schema.org/draft-06/schema#\"," - + "\"description\": \"A geographical coordinate\"," - + "\"type\": \"object\"," - + "\"properties\": {" - + "\"latitude\": {" - + "\"type\": \"number\"" - + " }," - + "\"longitude\": {" - + "\"type\": \"number\"" - + "}" - + "}," - + "\"required\": [\"latitude\", \"longitude\"]" - + "}"; - val.Schema = str; - options.ReuseExisting = false; - options.Validation = val; - Collection testColl = test.CreateCollection("testWithSchemaValidation", options); - Assert.True(CollectionExistsInDatabase(testColl)); - - //Bug #30830962 - options = new CreateCollectionOptions(); - val = new Validation() { }; - options.Validation = val; - var testbug1 = test.CreateCollection("bug_0962", options); //create collection with empty options - testbug1.Add(@"{ ""latitude"": 20, ""longitude"": 30 }").Execute(); - testbug1.Add(@"{ ""sexo"": 1, ""edad"": 20 }").Execute(); - int.TryParse(session.SQL("SELECT COUNT(*) FROM test.bug_0962").Execute().FetchOne()[0].ToString(), out int expected_count); - Assert.AreEqual(2, expected_count); //Collection is created as STRICT with empty json schema,both records were inserted - - options = new CreateCollectionOptions(); - val = new Validation() { Schema = str }; - options.Validation = val; - testbug1 = test.CreateCollection("bug_0962b", options);// adding an schema from - testbug1.Add(@"{ ""latitude"": 20, ""longitude"": 30 }").Execute(); - var invalidEx = Assert.Throws(() => testbug1.Add(@"{ ""sexo"": 1, ""edad"": 20 }").Execute()); - StringAssert.Contains("Document is not valid according to the schema assigned to collection", invalidEx.Message); - - // Create a Collection passing a reuse_existing parameter to server - CreateCollectionOptions options_reuse = new CreateCollectionOptions(); - options_reuse.ReuseExisting = false; - options_reuse.Validation = val; - Collection testCol2 = test.CreateCollection("testReuseExisting_1", options_reuse); - Assert.True(CollectionExistsInDatabase(testCol2)); - - //Insert Valid record with Level Strict - var insert_statement = testColl.Add(@"{ ""latitude"": 20, ""longitude"": 30 }"); - insert_statement.Execute(); - var count = session.SQL("SELECT COUNT(*) FROM test.testWithSchemaValidation").Execute().FetchOne()[0]; - Assert.AreEqual(count, testColl.Count()); - - //Insert invalid record with Level Strict - insert_statement = testColl.Add(@"{ ""OtherField"": ""value"", ""Age"": 30 }"); - var invalidInsertEx = Assert.Throws(() => insert_statement.Execute()); - StringAssert.Contains("Document is not valid according to the schema assigned to collection", invalidInsertEx.Message); - - //Test: Old MySQL Server Version exceptions - if (!(session.Version.isAtLeast(8, 0, 19))) - { - //FR6.2 - var ex1 = Assert.Throws(() => test.CreateCollection("testInvalid", options)); - StringAssert.Contains("Invalid number of arguments, expected 2 but got 3, " + - "The server doesn't support the requested operation. Please update the MySQL Server and/or Client library", ex1.Message); - - //FR6.3 - test.CreateCollection("testInvalid"); - ModifyCollectionOptions modifyOptions = new ModifyCollectionOptions(); - modifyOptions.Validation = val; - var ex2 = Assert.Throws(() => test.ModifyCollection("testInvalid", modifyOptions)); - StringAssert.Contains("Invalid mysqlx command modify_collection_options, " + - "The server doesn't support the requested operation. Please update the MySQL Server and/or Client library", ex2.Message); - } - - //Create collection with json schema and level OFF. Try to insert document matches this schema - options = new CreateCollectionOptions(); - options.Validation = new Validation() { Level = ValidationLevel.OFF, Schema = str }; - Collection col_test = test.CreateCollection("Test_2b_1", options); - Assert.True(CollectionExistsInDatabase(col_test)); - insert_statement = col_test.Add(@"{ ""latitude"": 120, ""longitude"": 78 }"); - insert_statement.Execute(); - count = session.SQL("SELECT COUNT(*) FROM test.Test_2b_1").Execute().FetchOne()[0]; - Assert.AreEqual(count, col_test.Count()); - - //Create collection with json schema and level OFF,ReuseExisting set to true, Try to insert - options = new CreateCollectionOptions(); - options.Validation = new Validation() { Level = ValidationLevel.OFF, Schema = str }; - options.ReuseExisting = true; - col_test = test.CreateCollection("Test_2b_2", options); - Assert.True(CollectionExistsInDatabase(col_test)); - insert_statement = col_test.Add(@"{ ""latitude"": 20, ""longitude"": 42 }"); - insert_statement.Execute(); - count = session.SQL("SELECT COUNT(*) FROM test.Test_2b_2").Execute().FetchOne()[0]; - Assert.AreEqual(count, col_test.Count()); - - //Create collection with only schema option, Try to insert - options = new CreateCollectionOptions(); - options.Validation = new Validation() { Schema = str }; - col_test = test.CreateCollection("Test_2b_3", options); - Assert.True(CollectionExistsInDatabase(col_test)); - insert_statement = col_test.Add(@"{ ""latitude"": 5, ""longitude"": 10 }"); - insert_statement.Execute(); - count = session.SQL("SELECT COUNT(*) FROM test.Test_2b_3").Execute().FetchOne()[0]; - Assert.AreEqual(count, col_test.Count()); - - //Create collection with only schema option,ReuseExisting set to true, Try to insert - options = new CreateCollectionOptions(); - options.Validation = new Validation() { Schema = str }; - options.ReuseExisting = true; - col_test = test.CreateCollection("Test_2b_4", options); - Assert.True(CollectionExistsInDatabase(col_test)); - insert_statement = col_test.Add(@"{ ""latitude"": 25, ""longitude"": 52 }"); - insert_statement.Execute(); - count = session.SQL("SELECT COUNT(*) FROM test.Test_2b_4").Execute().FetchOne()[0]; - Assert.AreEqual(count, col_test.Count()); - - //Create collection with only level option - options = new CreateCollectionOptions(); - options.Validation = new Validation() { Level = ValidationLevel.OFF }; - col_test = test.CreateCollection("Test_2b_5", options); - Assert.True(CollectionExistsInDatabase(col_test)); - - //ResuseExisting = false should throw exception for an existing collection - CreateCollectionOptions testReuseOptions = new CreateCollectionOptions(); - testReuseOptions.ReuseExisting = false; - testReuseOptions.Validation = new Validation() { Level = ValidationLevel.OFF }; - test.CreateCollection("testReuse"); - var exreuse = Assert.Throws(() => test.CreateCollection("testReuse", testReuseOptions)); - StringAssert.AreEqualIgnoringCase("Table 'testReuse' already exists", exreuse.Message); - - //Test: Resuse Existing = True should return existing collection - testReuseOptions.ReuseExisting = true; - var existing = test.CreateCollection("testReuse", testReuseOptions); - Assert.True(CollectionExistsInDatabase(existing)); - - //Create collection and prepare test data with json schema and level STRICT - CreateCollectionOptions prepareOptions = new CreateCollectionOptions(); - prepareOptions.Validation = new Validation() { Level = ValidationLevel.STRICT, Schema = str }; - var res_stm = test.CreateCollection("TestCreateInsert", prepareOptions).Add(@"{ ""latitude"": 25, ""longitude"": 52 }"); - res_stm.Execute(); - var num = session.SQL("SELECT COUNT(*) FROM test.TestCreateInsert").Execute().FetchOne()[0]; - var collection_test = test.GetCollection("TestCreateInsert"); - Assert.AreEqual(num, collection_test.Count()); - - //Passing invalid Schema - options = new CreateCollectionOptions(); - options.Validation = new Validation() { Level = ValidationLevel.STRICT, Schema = "Not Valid JSON Schema" }; - Exception ex_schema = Assert.Throws(() => test.CreateCollection("testInvalidSchema", options)); - StringAssert.Contains(@"The value provided is not a valid JSON document.", ex_schema.Message); - - //Testing an schema with different data types - str = "{\"id\": \"http://json-schema.org/geo\"," - + "\"$schema\": \"http://json-schema.org/draft-06/schema#\"," - + "\"description\": \"A Person example\"," - + "\"type\": \"object\"," - + "\"properties\": {" - + "\"name\": {" - + "\"type\": \"string\"" - + " }," - + "\"age\": {" - + "\"type\": \"number\"" - + "}" - + "}," - + "\"required\": [\"name\", \"age\"]" - + "}"; - - options = new CreateCollectionOptions(); - options.Validation = new Validation() { Level = ValidationLevel.STRICT, Schema = str }; - Collection person_col = test.CreateCollection("testWithPersonSchema", options); - Assert.True(CollectionExistsInDatabase(person_col)); - person_col.Add(@"{ ""name"": ""John"", ""age"": 52 }").Execute(); - var rows = session.SQL("SELECT COUNT(*) FROM test.testWithPersonSchema").Execute().FetchOne()[0]; - Assert.AreEqual(rows, person_col.Count()); - - // Create an existing collection with different schema - options = new CreateCollectionOptions(); - options.ReuseExisting = true; - options.Validation = new Validation() { Level = ValidationLevel.STRICT, Schema = str }; - Collection col_schema1 = test.CreateCollection("testSchema1", options); - Assert.True(CollectionExistsInDatabase(col_schema1)); - - col_schema1.Add(@"{ ""name"": ""John"", ""age"": 52 }").Execute(); - Assert.AreEqual(1, col_schema1.Count()); - var sqlDefinition1 = session.SQL("SHOW CREATE TABLE test.testSchema1").Execute().FetchOne()[1]; - - - var schema2 = "{\"id\": \"http://json-schema.org/geo\"," - + "\"$schema\": \"http://json-schema.org/draft-06/schema#\"," - + "\"description\": \"A Movies example\"," - + "\"type\": \"object\"," - + "\"properties\": {" - + "\"title\": {" - + "\"type\": \"string\"" - + " }," - + "\"movie\": {" - + "\"type\": \"string\"" - + "}" - + "}," - + "\"required\": [\"title\", \"movie\"]" - + "}"; - - options.Validation = new Validation() { Level = ValidationLevel.STRICT, Schema = schema2 }; - Collection col_schema2 = test.CreateCollection("testSchema1", options); - var sqlDefinition2 = session.SQL("SHOW CREATE TABLE test.testSchema1").Execute().FetchOne()[1]; - Assert.AreEqual(sqlDefinition1, sqlDefinition2); - - //Create a collection without sending reuseExisting parameter and insert record - Collection original_col1 = test.CreateCollection("testOriginal1"); - Assert.True(CollectionExistsInDatabase(original_col1)); - original_col1.Add(@"{ ""name"": ""John"", ""age"": 52 }").Execute(); - rows = session.SQL("SELECT COUNT(*) FROM test.testOriginal1").Execute().FetchOne()[0]; - Assert.AreEqual(rows, original_col1.Count()); - - //Create a new collection sending reuseExisting as true, insert record - Collection original_col2 = test.CreateCollection("testOriginal2", true); - Assert.True(CollectionExistsInDatabase(original_col2)); - original_col2.Add(@"{ ""name"": ""John"", ""age"": 52 }").Execute(); - rows = session.SQL("SELECT COUNT(*) FROM test.testOriginal2").Execute().FetchOne()[0]; - Assert.AreEqual(rows, original_col2.Count()); - - //Create an existing collection sending reuseExisting as true, insert record - Collection original_col3 = test.CreateCollection("testOriginal2", true); - Assert.True(CollectionExistsInDatabase(original_col3)); - original_col3.Add(@"{ ""name"": ""John2"", ""age"": 12 }").Execute(); - Assert.AreEqual(2, original_col3.Count()); - - //Create an existing collection sending reuseExisting as false,exception expected - var ex_existing = Assert.Throws(() => test.CreateCollection("testOriginal2", false)); - StringAssert.AreEqualIgnoringCase(@"Table 'testOriginal2' already exists", ex_existing.Message); - - //Modify collection with only level option - ModifyCollectionOptions Test_Options = new ModifyCollectionOptions(); - Test_Options.Validation = new Validation() { Level = ValidationLevel.OFF }; - Collection col_Test_2a_1 = test.ModifyCollection("testWithSchemaValidation", Test_Options); - - // Inser valid and invalid records with level set to Off - insert_statement = col_Test_2a_1.Add(@"{ ""latitude"": 20, ""longitude"": 30 }") - .Add(@"{ ""OtherField"": ""value"", ""Age"": 30 }"); - insert_statement.Execute(); - count = session.SQL("SELECT COUNT(*) FROM test.testWithSchemaValidation").Execute().FetchOne()[0]; - Assert.AreEqual(count, col_Test_2a_1.Count()); - - //Modify collection with only schema option - Test_Options.Validation = new Validation() { Schema = "{ }" }; - test.ModifyCollection("testWithSchemaValidation", Test_Options); - var sqlCreate = session.SQL("SHOW CREATE TABLE test.testWithSchemaValidation").Execute().FetchOne()[1]; - Assert.True(sqlCreate.ToString().Contains(@"'{\r\n}'") || sqlCreate.ToString().Contains("{}")); - - //Passing null as parameter to ModifyCollection - var emptyOptions = new ModifyCollectionOptions(); - emptyOptions.Validation = new Validation() { }; - test.CreateCollection("testnull"); - exreuse = Assert.Throws(() => test.ModifyCollection("testnull", null)); - Assert.AreEqual(@"Arguments value used under ""validation"" must be an object with at least one field", exreuse.Message); - - test.DropCollection("testWithSchemaValidation"); - test.DropCollection("bug_0962"); - test.DropCollection("bug_0962b"); - test.DropCollection("testReuseExisting_1"); - test.DropCollection("Test_2b_1"); - test.DropCollection("Test_2b_2"); - test.DropCollection("Test_2b_3"); - test.DropCollection("Test_2b_4"); - test.DropCollection("Test_2b_5"); - test.DropCollection("testReuse"); - test.DropCollection("TestCreateInsert"); - test.DropCollection("testWithPersonSchema"); - test.DropCollection("testSchema1"); - test.DropCollection("testOriginal1"); - test.DropCollection("testOriginal2"); - test.DropCollection("testnull"); - } - - /// - /// Server Bug - /// Bug #31667405 - INCORRECT PREPARED STATEMENT OUTCOME WITH NUMERIC STRINGS IN JSON - /// - [Test] - public void PreparedStatementWithNumericStrings() - { - Collection coll = CreateCollection("test"); - object[] _docs = new[] - { - new { _id = "1", title = "foo" }, - new { _id = "2", title = "bar" } - }; - - ExecuteAddStatement(coll.Add(_docs)); - - var stmt = coll.Find("_id=:v").Bind("v", "1"); - var res = stmt.Execute(); - var values = res.FetchOne(); - Assert.AreEqual(1, Convert.ToInt32(values.values["_id"])); - StringAssert.AreEqualIgnoringCase("foo", values.values["title"].ToString()); - - res = coll.Find("_id=:v").Bind("v", "2").Execute(); - values = res.FetchOne(); - Assert.AreEqual(2, Convert.ToInt32(values.values["_id"])); - StringAssert.AreEqualIgnoringCase("bar", values.values["title"].ToString()); - } - - [Test, Description("Verify Count method for Tables,Collections,Collection As Table,Views with different combinations")] - public void AdditionalCountTests() - { - Session session = GetSession(); - Schema schema = session.GetSchema(schemaName); - CreateCollection("testCount"); - var count = session.SQL("SELECT COUNT(*) FROM test.testCount").Execute().FetchOne()[0]; - var collection = schema.GetCollection("testCount"); - var collectionAsTable = schema.GetCollectionAsTable("testCount"); - Assert.AreEqual(count, collection.Count()); - Assert.AreEqual(count, collectionAsTable.Count()); - - session.SQL($"USE {schemaName}").Execute(); - session.SQL("create table test1(name VARCHAR(40), age INT)").Execute(); - count = session.SQL($"SELECT COUNT(*) FROM {schemaName}.test1").Execute().FetchOne()[0]; - Table table = session.GetSchema(schemaName).GetTable("test1"); - Assert.AreEqual(count, collectionAsTable.Count()); - - var result = table.Insert("name", "age") - .Values("MARK", "34") - .Values("richie", "16") - .Values("TEST", "50") - .Execute(); - - Assert.AreEqual((ulong)3, result.AffectedItemsCount); - var selectResult = table.Select().Execute(); - while (selectResult.Next()) ; - Assert.AreEqual(3, selectResult.Rows.Count); - Assert.AreEqual("MARK", selectResult.Rows.ToArray()[0][0].ToString()); - count = session.SQL($"SELECT COUNT(*) FROM {schemaName}.test1").Execute().FetchOne()[0]; - Assert.AreEqual(count, table.Count()); - - // Insert some records - var stm = collection.Add(@"{ ""_id"": 1, ""foo"": 1 }") - .Add(@"{ ""_id"": 2, ""foo"": 2 }") - .Add(@"{ ""_id"": 3, ""foo"": 3 }"); - stm.Execute(); - count = session.SQL("SELECT COUNT(*) FROM test.testCount").Execute().FetchOne()[0]; - Assert.AreEqual(count, collection.Count()); - collectionAsTable = schema.GetCollectionAsTable("testCount"); - Assert.AreEqual(count, collectionAsTable.Count()); - - table = schema.GetTable("testCount"); - table.Insert("doc").Values(@"{ ""_id"": 4, ""foo"": 4 }").Execute(); - count = session.SQL($"SELECT COUNT(*) FROM {schemaName}.testCount").Execute().FetchOne()[0]; - Assert.AreEqual(count, table.Count()); - - collection.RemoveOne(2); - count = session.SQL($"SELECT COUNT(*) FROM {schemaName}.testCount").Execute().FetchOne()[0]; - Assert.AreEqual(count, collection.Count()); - Assert.AreEqual(count, table.Count()); - - // Collection/Table does not exist - Assert.Throws(() => schema.GetCollection("testCount_").Count()); - Assert.Throws(() => schema.GetTable("testCount_").Count()); - - session.SQL("DROP TABLE IF EXISTS test1").Execute(); - session.SQL("CREATE TABLE test1(id1 int,firstname varchar(20))").Execute(); - session.SQL("INSERT INTO test1 values ('1','Rob')").Execute(); - session.SQL("INSERT INTO test1 values ('2','Steve')").Execute(); - session.SQL("CREATE TABLE test2(id2 int,lastname varchar(20))").Execute(); - session.SQL("INSERT INTO test2 values ('1','Williams')").Execute(); - session.SQL("INSERT INTO test2 values ('2','Waugh')").Execute(); - session.SQL("CREATE VIEW view1 AS select * from test1").Execute(); - session.SQL("SELECT * FROM view1").Execute(); - session.SQL("CREATE VIEW view2 AS select * from test2").Execute(); - session.SQL("SELECT * FROM view2").Execute(); - count = session.SQL("SELECT COUNT(*) FROM view1").Execute().FetchOne()[0]; - Assert.AreEqual(count, schema.GetTable("view1").Count()); - schema.DropCollection("testCount"); - session.SQL("DROP TABLE IF EXISTS test1").Execute(); - session.SQL("DROP TABLE IF EXISTS test2").Execute(); - } - - [Test, Description("Verify Expected exceptions in Count")] - public void ExceptionsInCount() - { - if (!session.Version.isAtLeast(8, 0, 0)) Assert.Ignore("This test is for MySql 8.0 or higher."); - var coll = CreateCollection("testCount"); - var docs = new[] - { - new {_id = 1, title = "Book 1", pages = 20}, - new {_id = 2, title = "Book 2", pages = 30}, - new {_id = 3, title = "Book 3", pages = 40}, - new {_id = 4, title = "Book 4", pages = 50} - }; - var r = coll.Add(docs).Execute(); - var count = session.SQL("SELECT COUNT(*) FROM test.testCount").Execute().FetchOne()[0]; - Schema schema = session.GetSchema(schemaName); - var collection = schema.GetCollection("testCount"); - Assert.AreEqual(4, collection.Count()); - - coll.Add(new { _id = 5, title = "Book 5", pages = 60 }).Execute(); - count = session.SQL("SELECT COUNT(*) FROM test.testCount").Execute().FetchOne()[0]; - schema = session.GetSchema(schemaName); - collection = schema.GetCollection("testCount"); - Assert.AreEqual(5, collection.Count()); - - Table table = session.GetSchema("test").GetTable("testCount"); - Assert.AreEqual(5, table.Count()); - - // Expected exceptions. - Assert.Throws(() => coll.RemoveOne(null)); - Assert.Throws(() => coll.RemoveOne("")); - Assert.Throws(() => coll.RemoveOne(string.Empty)); - Assert.Throws(() => coll.RemoveOne(" ")); - - // Remove sending numeric parameter. - Assert.AreEqual(1, coll.RemoveOne(1).AffectedItemsCount); - Assert.AreEqual(4, collection.Count()); - Assert.AreEqual(4, table.Count()); - - // Remove sending string parameter. - Assert.AreEqual(1, coll.RemoveOne("3").AffectedItemsCount); - Assert.AreEqual(3, collection.Count()); - Assert.AreEqual(3, table.Count()); - - // Remove an auto-generated id. - var document = coll.Find("pages = 60").Execute().FetchOne(); - Assert.AreEqual(1, coll.RemoveOne(document.Id).AffectedItemsCount); - Assert.AreEqual(2, collection.Count()); - Assert.AreEqual(2, table.Count()); - - // Remove a non-existing document. - Assert.AreEqual(0, coll.RemoveOne(5).AffectedItemsCount); - Assert.AreEqual(2, collection.Count()); - Assert.AreEqual(2, table.Count()); - - // Add or ReplaceOne - Assert.AreEqual(1, coll.AddOrReplaceOne(5, new { _id = 5, title = "Book 5", pages = 60 }). - AffectedItemsCount); - Assert.AreEqual(3, collection.Count()); - Assert.AreEqual(3, table.Count()); - - // Add or ReplaceOne - Assert.AreEqual(2, coll.AddOrReplaceOne(2, new { title = "Book 50", pages = 60 }). - AffectedItemsCount); - Assert.AreEqual(3, collection.Count()); - Assert.AreEqual(3, table.Count()); - - // Add or ReplaceOne - Assert.AreEqual(1, coll.AddOrReplaceOne(6, new { _id = 6, title = "Book 6", pages = 70 }). - AffectedItemsCount); - Assert.AreEqual(4, collection.Count()); - Assert.AreEqual(4, table.Count()); - - var result = coll.Modify("_id = 5").Set("title", "Book 5").Execute(); - Assert.AreEqual(4, collection.Count()); - Assert.AreEqual(4, table.Count()); - - coll = CreateCollection("testCount"); - - DbDoc[] jsonlist = new DbDoc[1000]; - DbDoc[] jsonlist1 = new DbDoc[1000]; - for (int i = 0; i < 1000; i++) - { - DbDoc newDoc2 = new DbDoc(); - newDoc2.SetValue("_id", (i + 1000)); - newDoc2.SetValue("F1", ("Field-1-Data-" + i)); - newDoc2.SetValue("F2", ("Field-2-Data-" + i)); - newDoc2.SetValue("F3", (300 + i).ToString()); - jsonlist[i] = newDoc2; - newDoc2 = null; - } - - for (int i = 0; i < 1000; i++) - { - DbDoc newDoc2 = new DbDoc(); - newDoc2.SetValue("_id", (i + 10000)); - newDoc2.SetValue("F1", ("Field-1-Data-" + i)); - newDoc2.SetValue("F2", ("Field-2-Data-" + i)); - newDoc2.SetValue("F3", (300 + i).ToString()); - jsonlist1[i] = newDoc2; - newDoc2 = null; - } - Result res = coll.Add(jsonlist).Add(jsonlist1).Execute(); - count = session.SQL("SELECT COUNT(*) FROM test.testCount").Execute().FetchOne()[0]; - schema = session.GetSchema(schemaName); - collection = schema.GetCollection("testCount"); - Assert.AreEqual(2000, collection.Count()); - - r = coll.Remove("_id = :_id").Bind("_id", 1000).Execute(); - Assert.AreEqual(1999, collection.Count()); - } - - [Test, Description("Verify MultiThreading with count")] - public async Task MultithreadCount() - { - _ = await SubProcessA(); - _ = await SubProcessB(); - } - - private Task SubProcessA() - { - using (var sessionA = MySQLX.GetSession(ConnectionString)) - { - Schema schema = sessionA.GetSchema("test"); - var coll = schema.CreateCollection("testCount"); - DbDoc[] jsonlist = new DbDoc[1000]; - for (int i = 0; i < 1000; i++) - { - DbDoc newDoc2 = new DbDoc(); - newDoc2.SetValue("_id", (i + 1000)); - newDoc2.SetValue("F1", ("Field-1-Data-" + i)); - newDoc2.SetValue("F2", ("Field-2-Data-" + i)); - newDoc2.SetValue("F3", (300 + i).ToString()); - jsonlist[i] = newDoc2; - newDoc2 = null; - } - var res = coll.Add(jsonlist).Execute(); - var count = sessionA.SQL("SELECT COUNT(*) FROM test.testCount").Execute().FetchOne()[0]; - var collection = schema.GetCollection("testCount"); - Assert.AreEqual(1000, collection.Count()); - - var r = coll.Remove("_id = :_id").Bind("_id", 1001).Execute(); - Assert.AreEqual(999, collection.Count()); - } - return Task.FromResult(0); - } - - private Task SubProcessB() - { - Thread.Sleep(8000); - using (var sessionB = MySQLX.GetSession(ConnectionString)) - { - Schema schema = session.GetSchema(schemaName); - var coll = schema.GetCollection("testCount"); - - var count = sessionB.SQL("SELECT COUNT(*) FROM test.testCount").Execute().FetchOne()[0]; - schema = sessionB.GetSchema("test"); - var collection = schema.GetCollection("testCount"); - do - { - if (collection.Count() > 5) - { - Assert.AreEqual(999, collection.Count()); - break; - } - } - while (true); - - var r = coll.Remove("_id = :_id").Bind("_id", 1100).Execute(); - Assert.AreEqual(998, collection.Count()); - } - return Task.FromResult(0); - } - - [Test, Description("Verify the behaviour of the dropX method for dropCollection under stressed conditions")] - public void DropUnderStressedConditions() - { - if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher."); - Schema schema = session.GetSchema(schemaName); - - for (var i = 0; i < 10; i++) - { - schema.CreateCollection("my_collection_123456789"); - schema.DropCollection("my_collection_123456789"); - } - - } - - [Test, Description("Verify that dropX method for dropSchema, dropIndex succeeds in stress conditions")] - public void DropObjectsUnderStress() - { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher."); - var schema = session.GetSchema(schemaName); - var testColl = CreateCollection("test123"); - for (var i = 0; i < 150; i++) - { - testColl.Add(new { myId = 1 }).Execute(); - testColl.DropIndex("testIndex"); - testColl.Add(new { myId = 1 }).Execute(); - testColl.DropIndex("testIndex"); - } - - for (var i = 0; i < 1000; i++) - { - session.CreateSchema("validSchema"); - session.DropSchema("validSchema"); - Assert.False(session.GetSchema("validSchema").ExistsInDatabase()); - } - - } - - [Test, Description("Verify that dropX method for dropIndex succeeds when deleted and created again with various combinations")] - public void DropDocuments() - { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher."); - var schema = session.GetSchema(schemaName); - schema.DropCollection("test123"); - var testColl = schema.CreateCollection("test123"); - - var result = testColl.Add(new { myId = 1 }).Add(new { myId = 2 }).Execute(); - result = testColl.Add(new { myId = 1 }).Execute(); - - testColl.DropIndex("testIndex"); - result = testColl.Add(new { myId = 1 }).Execute(); - - testColl.DropIndex("testIndex"); - - testColl.DropIndex("testIndex"); - testColl.DropIndex("testIndex"); - result = testColl.Remove("myId = :myId").Bind("myId", 1).Execute(); - result = testColl.Add(new { myId = 1 }).Execute(); - result = testColl.Remove("myId = :myId").Bind("myId", 1).Execute(); - - } - - [Test, Description("Verify ModifyCollection with level OFF and JSON schema")] - public void SchemaValidation_S1() - { - if (!session.Version.isAtLeast(8, 0, 19)) Assert.Ignore("This test is for MySql 8.0.19 or higher."); - var schema = session.GetSchema(schemaName); - var options = new CreateCollectionOptions(); - var options1 = new ModifyCollectionOptions(); - var val = new Validation(); - var doc1 = "{\"id\": \"http://json-schema.org/geo\"," - + "\"$schema\": \"http://json-schema.org/draft-06/schema#\"," - + "\"description\": \"A Person example\"," - + "\"type\": \"object\"," - + "\"properties\": {" - + "\"name\": {" - + "\"type\": \"string\"" - + " }," - + "\"age\": {" - + "\"type\": \"number\"" - + "}" - + "}," - + "\"required\": [\"name\", \"age\"]" - + "}"; - - session.SQL($"use {schemaName}").Execute(); - val.Level = ValidationLevel.OFF; - val.Schema = doc1; - options.Validation = val; - options.ReuseExisting = false; - var collection = schema.CreateCollection("coll1", options); - collection.Add(@"{ ""name"": ""John"", ""age"": 52 }").Execute(); - var count = session.SQL("select count(*) from coll1").Execute().FetchOne()[0]; - Assert.AreEqual(count, collection.Count()); - - val.Level = ValidationLevel.OFF; - val.Schema = doc1; - options.Validation = val; - options.ReuseExisting = true; - collection = schema.CreateCollection("coll1", options); - collection.Add(@"{ ""name"": ""John"", ""age"": 52 }").Execute(); - count = session.SQL("select count(*) from coll1").Execute().FetchOne()[0]; - Assert.AreEqual(count, collection.Count()); - - val.Level = ValidationLevel.OFF; - val.Schema = doc1; - options.Validation = val; - options.ReuseExisting = true; - collection = schema.CreateCollection("coll2", options); - collection.Add(@"{ ""name"": ""John"", ""age"": 52 }").Execute(); - count = session.SQL("select count(*) from coll2").Execute().FetchOne()[0]; - Assert.AreEqual(count, collection.Count()); - - options.Validation = new Validation() { Level = ValidationLevel.OFF, Schema = doc1 }; - options.ReuseExisting = false; - collection = schema.CreateCollection("coll3", options); - collection.Add(@"{ ""name"": ""Ram"" , ""age"": 22 }").Execute(); - count = session.SQL("select count(*) from coll3").Execute().FetchOne()[0]; - Assert.AreEqual(count, collection.Count()); - - options.Validation = new Validation() { Level = ValidationLevel.OFF, Schema = doc1 }; - options.ReuseExisting = true; - collection = schema.CreateCollection("coll3", options); - collection.Add(@"{ ""name"": ""John"", ""age"": 52 }").Execute(); - count = session.SQL("select count(*) from coll3").Execute().FetchOne()[0]; - Assert.AreEqual(count, collection.Count()); - - var doc3 = "{\"id\": \"http://json-schema.org/geo\"," - + "\"$schema\": \"http://json-schema.org/draft-06/schema#\"," - + "\"description\": \"A geographical coordinate\"," - + "\"type\": \"object\"," - + "\"properties\": {" - + "\"latitude\": {" - + "\"type\": \"number\"" - + " }," - + "\"longitude\": {" - + "\"type\": \"number\"" - + "}" - + "}," - + "\"required\": [\"latitude\", \"longitude\"]" - + "}"; - - val.Level = ValidationLevel.OFF; - val.Schema = doc3; - options1.Validation = val; - collection = schema.ModifyCollection("coll1", options1); - collection.Add(@"{ ""latitude"": 20, ""longitude"": 30 }"); - count = session.SQL("select count(*) from coll1").Execute().FetchOne()[0]; - Assert.AreEqual(count, collection.Count()); - - var doc4 = "{\"id\": \"http://json-schema.org/geo\"," - + "\"$schema\": \"http://json-schema.org/draft-06/schema#\"," - + "\"description\": \"A Person example\"," - + "\"type\": \"object\"," - + "\"properties\": {" - + "\"name\": {" - + "\"type\": \"string\"" - + " }" - + "}," - + "\"required\": [\"name\"]" - + "}"; - - val.Level = ValidationLevel.STRICT; - val.Schema = doc4; - options1.Validation = val; - collection = schema.ModifyCollection("coll3", options1); - collection.Add(@"{ ""name"": ""Samar"" }"); - count = session.SQL("select count(*) from coll3").Execute().FetchOne()[0]; - Assert.AreEqual(count, collection.Count()); - - options1.Validation = new Validation() { Level = ValidationLevel.OFF, Schema = doc1 }; - collection = schema.ModifyCollection("coll2", options1); - collection.Add(@"{ ""name"": ""Ram"" , ""age"": 22 }").Execute(); - count = session.SQL("select count(*) from coll2").Execute().FetchOne()[0]; - Assert.AreEqual(count, collection.Count()); - - val.Level = ValidationLevel.STRICT; - val.Schema = doc1; - options1.Validation = new Validation() { Level = ValidationLevel.STRICT, Schema = doc1 }; - collection = schema.ModifyCollection("coll2", options1); - collection.Add(@"{ ""name"": ""Ram"" , ""age"": 22 }").Execute(); - count = session.SQL("select count(*) from coll2").Execute().FetchOne()[0]; - Assert.AreEqual(count, collection.Count()); - } - - [Test, Description("Checking the createcollection() and ModifyCollection() with either the level or the schema")] - public void SchemaValidation_S2() - { - if (!session.Version.isAtLeast(8, 0, 19)) Assert.Ignore("This test is for MySql 8.0.19 or higher."); - var schema = session.GetSchema(schemaName); - session.SQL($"use {schemaName}").Execute(); - var options = new CreateCollectionOptions(); - var options1 = new ModifyCollectionOptions(); - var doc1 = "{\"id\": \"http://json-schema.org/geo\"," - + "\"$schema\": \"http://json-schema.org/draft-06/schema#\"," - + "\"description\": \"A Person example\"," - + "\"type\": \"object\"," - + "\"properties\": {" - + "\"name\": {" - + "\"type\": \"string\"" - + " }," - + "\"age\": {" - + "\"type\": \"number\"" - + "}" - + "}," - + "\"required\": [\"name\", \"age\"]" - + "}"; - - options.Validation = new Validation { Schema = doc1 }; - options.ReuseExisting = false; - var collection = schema.CreateCollection("coll4", options); - collection.Add(@"{ ""name"": ""John"", ""age"": 52 }").Execute(); - var result = session.SQL("select * from coll4").Execute().FetchAll(); - foreach (Row res in result) - Assert.IsNotNull(res[0]); - var count = session.SQL("select count(*) from coll4").Execute().FetchOne()[0]; - Assert.AreEqual(count, collection.Count()); - - options.Validation = new Validation { Schema = doc1 }; - options.ReuseExisting = true; - collection = schema.CreateCollection("coll4", options); - collection.Add(@"{ ""name"": ""John"", ""age"": 52 }").Execute(); - result = session.SQL("select * from coll4").Execute().FetchAll(); - foreach (Row res in result) - Assert.IsNotNull(res[0]); - count = session.SQL("select count(*) from coll4").Execute().FetchOne()[0]; - Assert.AreEqual(count, collection.Count()); - - options.Validation = new Validation { Schema = doc1 }; - options.ReuseExisting = true; - collection = schema.CreateCollection("colltesting", options); - Assert.Throws(() => ExecuteAddStatement(collection.Add(@"{ ""name"": ""John"", ""age"": ""52"" }"))); - count = session.SQL("select count(*) from colltesting").Execute().FetchOne()[0]; - Assert.AreEqual(count, collection.Count()); - - var doc2 = "{\"id\":\"http://json-schema.org/geo\"," - + "\"$schema\": \"http://json-schema.org/draft-06/schema#\"," - + "\"description\": \"A Person example\"," - + "\"type\": \"object\"," - + "\"properties\": {" - + "\"name\": {\"type\": \"string\"}," - + "\"number\": {\"type\": \"number\"}," - + "\"street_name\": {\"type\": \"string\"} ," - + "\"street_type\": {\"type\": \"string\"}," - + "\"colors\": " - + "{\"type\": \"array\" ," - + "\"description\": \"different colors\"," - + "\"items\": [" - + "{\"type\": \"string\"," - + "\"enum\": [\"red\", \"amber\", \"green\"]" - + "}," - + "{\"type\": \"number\"}," - + "{\"type\": \"boolean\"}"//," - + "{\"type\": \"null\"}," - + "]" - + "}" - + "}," - + "\"required\": [\"name\", \"number\"]" - + "}"; - - options.Validation = new Validation { Schema = doc2 }; - options.ReuseExisting = true; - Assert.Throws(() => schema.CreateCollection("colltesting2", options)); - - options.Validation = new Validation { Level = ValidationLevel.OFF }; ; - options.ReuseExisting = false; - collection = schema.CreateCollection("coll5", options); - collection.Add(@"{ ""name"": ""John"", ""age"": 52 }").Execute(); - result = session.SQL("select * from coll5").Execute().FetchAll(); - foreach (Row res in result) - Assert.IsNotNull(res[0]); - count = session.SQL("select count(*) from coll5").Execute().FetchOne()[0]; - Assert.AreEqual(count, collection.Count()); - - options.Validation = new Validation { Level = ValidationLevel.STRICT }; - options.ReuseExisting = false; - collection = schema.CreateCollection("coll6", options); - collection.Add(@"{ ""name"": ""John"", ""age"": 52 }").Execute(); - result = session.SQL("select * from coll6").Execute().FetchAll(); - foreach (Row res in result) - Assert.IsNotNull(res[0]); - count = session.SQL("select count(*) from coll6").Execute().FetchOne()[0]; - Assert.AreEqual(count, collection.Count()); - - options1.Validation = new Validation() { Schema = doc1 }; - collection = schema.ModifyCollection("coll6", options1); - collection.Add(@"{ ""name"": ""Ram"" , ""age"": 22 }").Execute(); - result = session.SQL("select * from coll6").Execute().FetchAll(); - foreach (Row res in result) - Assert.IsNotNull(res[0]); - count = session.SQL("select count(*) from coll6").Execute().FetchOne()[0]; - Assert.AreEqual(count, collection.Count()); - - options1.Validation = new Validation() { Schema = doc1 }; - collection = schema.ModifyCollection("colltesting", options1); - Assert.Throws(() => ExecuteAddStatement(collection.Add(@"{ ""name"": ""Ram"" , ""age"": ""22"" }"))); - - options1.Validation = new Validation() { Schema = doc2 }; - Assert.Throws(() => collection = schema.ModifyCollection("colltesting2", options1)); - - options1.Validation = new Validation() { Level = ValidationLevel.OFF }; - collection = schema.ModifyCollection("coll4", options1); - collection.Add(@"{ ""name"": ""Ram"" , ""age"": 22 }").Execute(); - result = session.SQL("select * from coll4").Execute().FetchAll(); - foreach (Row res in result) - Assert.IsNotNull(res[0]); - count = session.SQL("select count(*) from coll4").Execute().FetchOne()[0]; - Assert.AreEqual(count, collection.Count()); - - options1.Validation = new Validation() { Level = ValidationLevel.STRICT }; - collection = schema.ModifyCollection("coll5", options1); - collection.Add(@"{ ""name"": ""Ram"" , ""age"": 22 }").Execute(); - result = session.SQL("select * from coll5").Execute().FetchAll(); - foreach (Row res in result) - Assert.IsNotNull(res[0]); - count = session.SQL("select count(*) from coll5").Execute().FetchOne()[0]; - Assert.AreEqual(count, collection.Count()); - - options1.Validation = new Validation() { }; - Assert.Throws(() => schema.ModifyCollection("coll2", options1)); - - string docEnum = "{\"id\":\"http://json-schema.org/draft-06/schema#\",\"$schema\":\"http://json-schema.org/draft-06/schema#\"," - + "\"description\": \"A Person example\",\"type\":\"object\"," - + "\"properties\":{" - + "\"name\":{" - + "\"type\":\"string\"" - + "}," - + "\"number\":{" - + "\"type\":\"number\"" - + "}," - + "\"street_name\":{" - + "\"type\":\"string\"" - + "}," - + "\"street_type\": {" - + "\"type\": \"string\"" - + "}," - + "\"colors\":{" - + "\"type\": \"array\"," - + "\"items\": {" - + "\"type\":\"string\"" - + "}" - + " }," - + "\"consistent\":{" - + "\"type\": \"boolean\"" - + " }," - + "\"Favourite colors\":{" - + "\"enum\": [" - + "\"red\"," - + "\"amber\"," - + "\"green\"" - + "]" - + "}" - + "}" - + "}"; - - options.Validation = new Validation { Schema = docEnum, Level = ValidationLevel.STRICT }; - options.ReuseExisting = true; - collection = schema.CreateCollection("collEnum", options); - collection.Add(@"{ ""name"": ""John"" }").Execute(); - result = session.SQL("select * from collEnum").Execute().FetchAll(); - foreach (Row res in result) - Console.WriteLine("test with enum: " + res[0]); - count = session.SQL("select count(*) from collEnum").Execute().FetchOne()[0]; - Assert.AreEqual(count, collection.Count()); - } - - [Test, Description("Checking the error messages with different level")] - public void SchemaValidation_S3() - { - if (!session.Version.isAtLeast(8, 0, 19)) Assert.Ignore("This test is for MySql 8.0.19 or higher."); - session.SQL($"use {schemaName}").Execute(); - var options = new CreateCollectionOptions(); - var options1 = new ModifyCollectionOptions(); - var doc1 = "{\"id\": \"http://json-schema.org/geo\"," - + "\"$schema\": \"http://json-schema.org/draft-06/schema#\"," - + "\"description\": \"A Person example\"," - + "\"type\": \"object\"," - + "\"properties\": {" - + "\"name\": {" - + "\"type\": \"string\"" - + " }," - + "\"age\": {" - + "\"type\": \"number\"" - + "}" - + "}," - + "\"required\": [\"name\", \"age\"]" - + "}"; - - var schema = session.GetSchema(schemaName); - options.Validation = new Validation { Schema = doc1, Level = ValidationLevel.STRICT }; - options.ReuseExisting = false; - var collection = schema.CreateCollection("coll7", options); - collection.Add(@"{ ""name"": ""John"", ""age"": 52 }").Execute(); - var result = session.SQL("select * from coll7").Execute().FetchAll(); - foreach (Row res in result) - Assert.IsNotNull(res[0]); - var count = session.SQL("select count(*) from coll7").Execute().FetchOne()[0]; - Assert.AreEqual(count, collection.Count()); - - options.Validation = new Validation { Schema = doc1, Level = ValidationLevel.STRICT }; - options.ReuseExisting = false; - collection = schema.CreateCollection("collext", options); - collection.Add(@"{ ""name"": ""John"", ""age"": 52 }").Execute(); - result = session.SQL("select * from collext").Execute().FetchAll(); - foreach (Row res in result) - Assert.IsNotNull(res[0]); ; - count = session.SQL("select count(*) from collext").Execute().FetchOne()[0]; - Assert.AreEqual(count, collection.Count()); - - var doc2 = "{\"id\":\"http://json-schema.org/geo\"," - + "\"$schema\": \"http://json-schema.org/draft-06/schema#\"," - + "\"description\": \"A Person example\"," - + "\"type\": \"object\"," - + "\"properties\": {" - + "\"name\": {\"type\": \"string\"}," - + "\"number\": {\"type\": \"number\"}," - + "\"street_name\": {\"type\": \"string\"} ," - + "\"street_type\": {\"type\": \"string\"}," - + "\"colors\": " - + "{\"type\": \"array\" ," - + "\"description\": \"different colors\"," - + "\"items\": [" - + "{\"type\": \"string\"," - + "\"enum\": [\"red\", \"amber\", \"green\"]" - + "}," - + "{\"type\": \"number\"}," - + "{\"type\": \"boolean\"}"//," - + "{\"type\": \"null\"}," - + "]" - + "}" - + "}," - + "\"required\": [\"name\", \"number\"]" - + "}"; - - options.Validation = new Validation { Schema = doc2, Level = ValidationLevel.STRICT }; - options.ReuseExisting = false; - Assert.Throws(() => schema.CreateCollection("coll8", options)); - - options.Validation = new Validation { Schema = doc1, Level = ValidationLevel.STRICT }; - options.ReuseExisting = true; - collection = schema.CreateCollection("coll8", options); - collection.Add(@"{ ""name"": ""John"", ""age"": 52 }").Execute(); - result = session.SQL("select * from coll8").Execute().FetchAll(); - foreach (Row res in result) - Assert.IsNotNull(res[0]); ; - count = session.SQL("select count(*) from coll8").Execute().FetchOne()[0]; - Assert.AreEqual(count, collection.Count()); - - options.Validation = new Validation { Schema = doc1, Level = ValidationLevel.STRICT }; - options.ReuseExisting = false; - collection = schema.CreateCollection("coll9", options); - Assert.Throws(() => ExecuteAddStatement(collection.Add(@"{""longitude"":""99""}"))); - - options1.Validation = new Validation { Schema = doc1, Level = ValidationLevel.STRICT }; - collection = schema.ModifyCollection("coll7", options1); - Assert.Throws(() => ExecuteAddStatement(collection.Add(@"{ ""number"": ""56"" }"))); - - options.Validation = new Validation { Schema = doc1, Level = ValidationLevel.OFF }; - options.ReuseExisting = false; - collection = schema.CreateCollection("coll10", options); - collection.Add(@"{""longitude"":""99""}").Execute(); - result = session.SQL("select * from coll10").Execute().FetchAll(); - foreach (Row res in result) - Assert.IsNotNull(res[0]); ; - count = session.SQL("select count(*) from coll10").Execute().FetchOne()[0]; - Assert.AreEqual(count, collection.Count()); - - options1.Validation = new Validation { Schema = doc1, Level = ValidationLevel.OFF }; - collection = schema.ModifyCollection("coll10", options1); - collection.Add(@"{ ""name"": 67 }").Execute(); - result = session.SQL("select * from coll10").Execute().FetchAll(); - foreach (Row res in result) - Assert.IsNotNull(res[0]); ; - count = session.SQL("select count(*) from coll10").Execute().FetchOne()[0]; - Assert.AreEqual(count, collection.Count()); - - options.Validation = new Validation { Schema = doc1, Level = ValidationLevel.STRICT }; - options.ReuseExisting = false; - collection = schema.CreateCollection("coll", options); - collection.Add(@"{""_id"":1,""name"": ""John"", ""age"": 52}").Execute(); - result = session.SQL("select * from coll").Execute().FetchAll(); - foreach (Row res in result) - Assert.IsNotNull(res[0]); ; - count = session.SQL("select count(*) from coll").Execute().FetchOne()[0]; - Assert.AreEqual(count, collection.Count()); - } - - /// - /// Bug 30693969 - /// - [Test, Description("Verify ModifyCollection with level OFF and JSON schema with Json schema")] - public void ModifyCollectionSchemaValidation() - { - if (!session.Version.isAtLeast(8, 0, 19)) Assert.Ignore("This test is for MySql 8.0.19 or higher."); - session.SQL($"use {schemaName}").Execute(); - var schema = session.GetSchema(schemaName); - var options = new CreateCollectionOptions(); - var val = new Validation(); - string doc1 = "{" - + " \"id\":\"https://example.com/arrays.schema.json\"," - + " \"$schema\": \"http://json-schema.org/draft-07/schema#\"," - + " \"description\": \"A representation of a person, company, organization, or place\"," - + " \"type\": \"object\"," - + " \"properties\": {" - + " \"fruits\": {" - + " \"type\": \"array\"," - + " \"items\": {" - + "\"type\": \"string\"" - + " }" - + "}," - + "\"vegetables\": {" - + " \"type\": \"array\"," - + "\"items\": { \"$ref\": \"#/definitions/veggie\" }" - + " }" - + "}," - + "\"definitions\": {" - + " \"veggie\": {" - + " \"type\": \"object\"," - + " \"required\": [ \"veggieName\", \"veggieLike\" ]," - + "\"properties\": {" - + " \"veggieName\": {" - + " \"type\": \"string\"," - + " \"description\": \"The name of the vegetable.\"" - + "}," - + "\"veggieLike\": {" - + "\"type\": \"boolean\"," - + "\"description\": \"Do I like this vegetable?\"" - + "}" - + "}" - + "}" - + "}" - + "}"; - - val.Level = ValidationLevel.STRICT; - val.Schema = doc1; - options.Validation = val; - options.ReuseExisting = false; - var collection = schema.CreateCollection("coll20", options); - collection.Add(@"{""fruits"": [ ""apple"", ""orange"", ""pear"" ],""vegetables"": [{""veggieName"": ""potato"",""veggieLike"": true},{""veggieName"": ""broccoli"",""veggieLike"": false}]}").Execute(); - var result = session.SQL("select * from coll20").Execute().FetchAll(); - foreach (Row res in result) - Assert.IsNotNull(res[0]); - var count = session.SQL("select count(*) from coll20").Execute().FetchOne()[0]; - Assert.AreEqual(count, collection.Count()); - - options.Validation = new Validation { Level = ValidationLevel.STRICT, Schema = doc1 }; - options.ReuseExisting = false; - collection = schema.CreateCollection("coll21", options); - collection.Add(@"{""fruits"": [ ""apple"", ""orange"", ""pear"" ],""vegetables"": [{""veggieName"": ""potato"",""veggieLike"": true},{""veggieName"": ""broccoli"",""veggieLike"": false}]}").Execute(); - result = session.SQL("select * from coll21").Execute().FetchAll(); - foreach (Row res in result) - Assert.IsNotNull(res[0]); - count = session.SQL("select count(*) from coll21").Execute().FetchOne()[0]; - Assert.AreEqual(count, collection.Count()); - - val.Level = ValidationLevel.STRICT; - val.Schema = doc1; - options.Validation = val; - options.ReuseExisting = true; - collection = schema.CreateCollection("coll20", options); - collection.Add(@"{""fruits"": [ ""apple"", ""orange"", ""pear"" ],""vegetables"": [{""veggieName"": ""potato"",""veggieLike"": true},{""veggieName"": ""broccoli"",""veggieLike"": false}]}").Execute(); - result = session.SQL("select * from coll20").Execute().FetchAll(); - foreach (Row res in result) - Assert.IsNotNull(res[0]); - count = session.SQL("select count(*) from coll20").Execute().FetchOne()[0]; - Assert.AreEqual(count, collection.Count()); - - options.Validation = new Validation { Level = ValidationLevel.STRICT, Schema = doc1 }; - options.ReuseExisting = true; - collection = schema.CreateCollection("coll21", options); - collection.Add(@"{""fruits"": [ ""apple"", ""orange"", ""pear"" ],""vegetables"": [{""veggieName"": ""potato"",""veggieLike"": true},{""veggieName"": ""broccoli"",""veggieLike"": false}]}").Execute(); - result = session.SQL("select * from coll21").Execute().FetchAll(); - foreach (Row res in result) - Assert.IsNotNull(res[0]); - count = session.SQL("select count(*) from coll21").Execute().FetchOne()[0]; - Assert.AreEqual(count, collection.Count()); - - val.Level = ValidationLevel.OFF; - val.Schema = doc1; - options.Validation = val; - options.ReuseExisting = true; - collection = schema.CreateCollection("coll22", options); - collection.Add(@"{""fruits"": [ 78, ""orange"", ""pear"" ],""vegetables"": [{""veggieName"": ""potato"",""veggieLike"": true},{""veggieName"": ""broccoli"",""veggieLike"": false}]}").Execute(); - result = session.SQL("select * from coll22").Execute().FetchAll(); - foreach (Row res in result) - Assert.IsNotNull(res[0]); - count = session.SQL("select count(*) from coll22").Execute().FetchOne()[0]; - Assert.AreEqual(count, collection.Count()); - } - - [Test, Description("Verify ModifyCollection with level OFF and JSON schema")] - public void SchemaValidationDeleteRecords() - { - // Bug30748283 - if (!session.Version.isAtLeast(8, 0, 19)) Assert.Ignore("This test is for MySql 8.0.19 or higher."); - string doc5 = "{\"id\": \"http://json-schema.org/geo\"," - + "\"$schema\": \"http://json-schema.org/draft-06/schema#\"," - + "\"description\": \"A Person example\"," - + "\"type\": \"object\"," - + "\"properties\": {" - + "\"name\": {" - + "\"type\": \"number\"" - + " }" - + "}," - + "\"required\": [\"name\"]" - + "}"; - - string doc1 = "{\"id\": \"http://json-schema.org/geo\"," - + "\"$schema\": \"http://json-schema.org/draft-06/schema#\"," - + "\"description\": \"A Person example\"," - + "\"type\": \"object\"," - + "\"properties\": {" - + "\"name\": {" - + "\"type\": \"string\"" - + " }" - + ",\"age\": {" - + "\"type\": \"number\"" - + "}" - + "}," - + "\"required\": [\"name\",\"age\"]" - + "}"; - string doc3 = "{\"id\": \"http://json-schema.org/geo\"," - + "\"$schema\": \"http://json-schema.org/draft-06/schema#\"," - + "\"description\": \"A geographical coordinate\"," - + "\"type\": \"object\"," - + "\"properties\": {" - + "\"latitude\": {" - + "\"type\": \"number\"" - + " }," - + "\"longitude\": {" - + "\"type\": \"number\"" - + "}" - + "}," - + "\"required\": [\"latitude\", \"longitude\"]" - + "}"; - - string doc4 = "{\"id\": \"http://json-schema.org/geo\"," - + "\"$schema\": \"http://json-schema.org/draft-06/schema#\"," - + "\"description\": \"A Person example\"," - + "\"type\": \"object\"," - + "\"properties\": {" - + "\"name\": {" - + "\"type\": \"string\"" - + " }" - + "}," - + "\"required\": [\"name\"]" - + "}"; - - session.SQL($"use {schemaName}").Execute(); - var schema = session.GetSchema(schemaName); - var options = new CreateCollectionOptions(); - var options1 = new ModifyCollectionOptions(); - - options.Validation = new Validation { Level = ValidationLevel.STRICT, Schema = doc5 }; - options.ReuseExisting = true; - var collection = schema.CreateCollection("collectiontest", options); - collection.Add(@"{ ""name"": 52 }").Execute(); - var result = session.SQL("select * from collectiontest").Execute().FetchAll(); - foreach (Row res1 in result) - Assert.IsNotNull(res1[0]); - var count = session.SQL("select count(*) from collectiontest").Execute().FetchOne()[0]; - Assert.AreEqual(count, collection.Count()); - - options1.Validation = new Validation { Level = ValidationLevel.STRICT, Schema = doc1 }; - session.SQL("delete from collectiontest").Execute(); - - collection = schema.ModifyCollection("collectiontest", options1); - collection.Add(@"{ ""name"": ""sammeer"",""age"":8 }").Execute(); - var result2 = session.SQL("select * from collectiontest").Execute().FetchAll(); - foreach (Row res2 in result2) - Console.WriteLine(res2[0]); - count = session.SQL("select count(*) from collectiontest").Execute().FetchOne()[0]; - Assert.AreEqual(count, collection.Count()); - - options1.Validation = new Validation { Level = ValidationLevel.OFF, Schema = doc1 }; - collection = schema.ModifyCollection("collectiontest", options1); - collection.Add(@"{ ""name"": 78 }").Execute(); - result = session.SQL("select * from collectiontest").Execute().FetchAll(); - foreach (Row res2 in result) - Assert.IsNotNull(res2[0]); - count = session.SQL("select count(*) from collectiontest").Execute().FetchOne()[0]; - Assert.AreEqual(count, collection.Count()); - - options1.Validation = new Validation { Level = ValidationLevel.STRICT, Schema = doc3 }; - session.SQL("delete from collectiontest").Execute(); - collection = schema.ModifyCollection("collectiontest", options1); - collection.Add(@"{""latitude"": 253, ""longitude"": 525}").Execute(); - result = session.SQL("select * from collectiontest").Execute().FetchAll(); - foreach (Row res2 in result) - Assert.IsNotNull(res2[0]); - count = session.SQL("select count(*) from collectiontest").Execute().FetchOne()[0]; - Assert.AreEqual(count, collection.Count()); - - options1.Validation = new Validation { Level = ValidationLevel.STRICT, Schema = doc4 }; - session.SQL("delete from collectiontest").Execute(); - result = session.SQL("select * from collectiontest").Execute().FetchAll(); - collection = schema.ModifyCollection("collectiontest", options1); - collection.Add(@"{ ""name"": ""Johnny"" }").Execute(); - result = session.SQL("select * from collectiontest").Execute().FetchAll(); - foreach (Row res2 in result) - Assert.IsNotNull(res2[0]); - count = session.SQL("select count(*) from collectiontest").Execute().FetchOne()[0]; - Assert.AreEqual(count, collection.Count()); - - } - - [Test, Description("Test MySQLX plugin Remove Bind Stress")] - public void RemoveBindStress() - { - if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher."); - Collection coll = CreateCollection("test"); - DbDoc[] jsonlist = new DbDoc[10]; - DbDoc[] jsonlist1 = new DbDoc[10]; - for (int i = 0; i < 10; i++) - { - DbDoc newDoc2 = new DbDoc(); - newDoc2.SetValue("_id", (i + 1000)); - newDoc2.SetValue("F1", ("Field-1-Data-" + i)); - newDoc2.SetValue("F2", ("Field-2-Data-" + i)); - newDoc2.SetValue("F3", (300 + i).ToString()); - jsonlist[i] = newDoc2; - newDoc2 = null; - } - - for (int i = 0; i < 10; i++) - { - DbDoc newDoc2 = new DbDoc(); - newDoc2.SetValue("_id", (i + 10000)); - newDoc2.SetValue("F1", ("Field-1-Data-" + i)); - newDoc2.SetValue("F2", ("Field-2-Data-" + i)); - newDoc2.SetValue("F3", (300 + i).ToString()); - jsonlist1[i] = newDoc2; - newDoc2 = null; - } - Result r = coll.Add(jsonlist).Add(jsonlist1).Execute(); - - Assert.AreEqual(20, r.AffectedItemsCount, "Matching"); - - r = coll.Remove("_id = :_id").Bind("_id", 1000).Execute(); - Assert.AreEqual(1, r.AffectedItemsCount, "Matching"); - } - - [Test, Description("Test MySQLX plugin Get Collection as Table")] - public void GetCollectionAsTableStress() - { - if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher."); - Collection testCollection = CreateCollection("test"); - - DbDoc[] jsonlist = new DbDoc[1000]; - for (int i = 0; i < 1000; i++) - { - DbDoc newDoc2 = new DbDoc(); - newDoc2.SetValue("_id", (i + 1000)); - newDoc2.SetValue("F1", ("Field-1-Data-" + i)); - newDoc2.SetValue("F2", ("Field-2-Data-" + i)); - newDoc2.SetValue("F3", (300 + i).ToString()); - jsonlist[i] = newDoc2; - newDoc2 = null; - } - Result r = testCollection.Add(jsonlist).Execute(); - Assert.AreEqual(1000, r.AffectedItemsCount, "Matching"); - - Table test = testSchema.GetCollectionAsTable("test"); - Assert.IsTrue(test.ExistsInDatabase()); - var rows = test.Select("_id").Execute().FetchAll(); - - for (int j = 0; j < rows.Count; j++) - { - var doc = testCollection.Find("_id like :param").Bind("param", (j + 1000)).Execute(); - var docs = doc.FetchAll().Count(); - Assert.AreEqual(1, docs, "Matches"); - } - } - - [Test, Description("Test MySQLX plugin GetCollection Exception Scenario")] - public void GetCollectionException() - { - if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher."); - using (Session sessionPlain = MySQLX.GetSession(ConnectionString)) - { - Schema db = sessionPlain.GetSchema(schemaName); - Collection col = db.GetCollection("my_collection_123456789"); - if (col.ExistsInDatabase()) - { - db.DropCollection("my_collection_123456789"); - col = db.CreateCollection("my_collection_123456789"); - } - else { col = db.CreateCollection("my_collection_123456789"); } - - Collection col1 = db.GetCollection("my_collection_123456789", true); - if (col.ExistsInDatabase()) - { - db.DropCollection("my_collection_123456789"); - col1 = db.CreateCollection("my_collection_123456789"); - } - else { col1 = db.CreateCollection("my_collection_123456789"); } - - var col2 = db.GetTable("my_collection_1234567891"); - Assert.Throws(() => db.GetCollection("my_collection_test", true)); - db.DropCollection("my_collection_123456789"); - } - } - - [Test, Description("Collection GetDocumentIDS Stress(1000 records)")] - public void GetDocumentIDSStress() - { - Collection coll = CreateCollection("test"); - DbDoc[] jsonlist = new DbDoc[1000]; - for (int i = 0; i < 1000; i++) - { - DbDoc newDoc2 = new DbDoc(); - newDoc2.SetValue("_id", (i)); - newDoc2.SetValue("F1", ("Field-1-Data-" + i)); - newDoc2.SetValue("F2", ("Field-2-Data-" + i)); - newDoc2.SetValue("F3", (3 + i).ToString()); - jsonlist[i] = newDoc2; - newDoc2 = null; - } - Result r = coll.Add(jsonlist).Execute(); - Assert.AreEqual(1000, r.AffectedItemsCount, "Matching"); - var documentIds = r.GeneratedIds; - Assert.False(documentIds != null && documentIds.Count > 0); - } - - [Test, Description("Session Performance Test")] - public void SessionPerformanceTest() - { - string json = ""; - int i = 0, j = 0, maxField = 100; - var collection = CreateCollection("test"); - int maxDepth = 97; - json = "{\"_id\":\"1002\",\"XYZ\":1111"; - for (j = 0; j < maxField; j++) - { - json = json + ",\"ARR" + j + "\":["; - for (i = 0; i < maxDepth; i++) - { - json = json + i + ",["; - } - json = json + i; - for (i = maxDepth - 1; i >= 0; i--) - { - json = json + "]," + i; - } - json = json + "]"; - } - json = json + "}"; - - collection.Add(json).Execute(); - json = "{\"_id\":\"1003\",\"XYZ\":2222"; - for (j = 0; j < maxField; j++) - { - json = json + ",\"DATAX" + j + "\":"; - for (i = 0; i < maxDepth; i++) - { - json = json + "{\"D" + i + "\":"; - } - json = json + maxDepth; - for (i = maxDepth - 1; i >= 0; i--) - { - json = json + "}"; - } - } - json = json + "}"; - - collection.Add(json).Execute(); - json = "{\"_id\":\"1001\",\"XYZ\":3333"; - for (j = 0; j < maxField; j++) - { - json = json + ",\"ARR" + j + "\":["; - for (i = 0; i < maxDepth; i++) - { - json = json + i + ",["; - } - json = json + i; - for (i = maxDepth - 1; i >= 0; i--) - { - json = json + "]," + i; - } - json = json + "]"; - } - - for (j = 0; j < maxField; j++) - { - json = json + ",\"DATAX" + j + "\":"; - for (i = 0; i < maxDepth; i++) - { - json = json + "{\"D" + i + "\":"; - } - json = json + maxDepth; - for (i = maxDepth - 1; i >= 0; i--) - { - json = json + "}"; - } - } - json = json + "}"; - collection.Add(json).Execute(); - - // select - string query = "$.ARR" + (maxField - 1); - for (i = 0; i < maxDepth; i++) - { - query = query + "[1]"; - } - query = query + "[0]"; - json = "CAST(" + query + " as SIGNED)= " + maxDepth; - var docs = collection.Find(json).Fields("$._id as _id," + query + " as Arr").Execute(); - var res = docs.FetchAll(); - Assert.AreEqual("1001", res[0]["_id"].ToString(), "Matching the id"); - Assert.AreEqual("1002", res[1]["_id"].ToString(), "Matching the id"); - - query = "$.DATAX" + (maxField - 1); - for (i = 0; i < maxDepth; i++) - { - query = query + ".D" + i; - } - json = "CAST(" + query + " as SIGNED)"; - docs = collection.Find(json + " =" + maxDepth).Fields("$._id as _id ").Execute(); - res = docs.FetchAll(); - Assert.AreEqual("1001", res[0]["_id"].ToString(), "Matching the id"); - Assert.AreEqual("1003", res[1]["_id"].ToString(), "Matching the id"); - } - - /// - /// Bug #34243143 [Connector/NET allows empty string in Set() method which is chained to Modify()] - /// The fix applied for every method in Modify(). - /// - [Test] - public void EmptyStringInModifyMethods() - { - Collection coll = CreateCollection("test"); - object _doc = new { _id = 1, title = "foo" }; - coll.Add(_doc).Execute(); - var result = coll.Find("_id == 1").Execute().FetchOne(); - - Assert.NotNull(result); - Assert.AreEqual(1, result.Id); - - // empty string - var ex = Assert.Throws(() => coll.Modify("_id == 1").Set("", new { title = "bar" }).Execute()); - StringAssert.AreEqualIgnoringCase(ResourcesX.DocPathNullOrEmpty, ex.Message); - ex = Assert.Throws(() => coll.Modify("_id == 1").Unset("").Execute()); - StringAssert.AreEqualIgnoringCase(ResourcesX.DocPathNullOrEmpty, ex.Message); - ex = Assert.Throws(() => coll.Modify("_id == 1").Change("", new { title = "bar" }).Execute()); - StringAssert.AreEqualIgnoringCase(ResourcesX.DocPathNullOrEmpty, ex.Message); - ex = Assert.Throws(() => coll.Modify("_id == 1").ArrayInsert("", new { title = "bar" }).Execute()); - StringAssert.AreEqualIgnoringCase(ResourcesX.DocPathNullOrEmpty, ex.Message); - ex = Assert.Throws(() => coll.Modify("_id == 1").ArrayAppend("", new { title = "bar" }).Execute()); - StringAssert.AreEqualIgnoringCase(ResourcesX.DocPathNullOrEmpty, ex.Message); - - // white space - ex = Assert.Throws(() => coll.Modify("_id == 1").Set(" ", new { title = "bar" }).Execute()); - StringAssert.AreEqualIgnoringCase(ResourcesX.DocPathNullOrEmpty, ex.Message); - ex = Assert.Throws(() => coll.Modify("_id == 1").Unset(" ").Execute()); - StringAssert.AreEqualIgnoringCase(ResourcesX.DocPathNullOrEmpty, ex.Message); - ex = Assert.Throws(() => coll.Modify("_id == 1").Change(" ", new { title = "bar" }).Execute()); - StringAssert.AreEqualIgnoringCase(ResourcesX.DocPathNullOrEmpty, ex.Message); - ex = Assert.Throws(() => coll.Modify("_id == 1").ArrayInsert(" ", new { title = "bar" }).Execute()); - StringAssert.AreEqualIgnoringCase(ResourcesX.DocPathNullOrEmpty, ex.Message); - ex = Assert.Throws(() => coll.Modify("_id == 1").ArrayAppend(" ", new { title = "bar" }).Execute()); - StringAssert.AreEqualIgnoringCase(ResourcesX.DocPathNullOrEmpty, ex.Message); - - // null - ex = Assert.Throws(() => coll.Modify("_id == 1").Set(null, new { title = "bar" }).Execute()); - StringAssert.AreEqualIgnoringCase(ResourcesX.DocPathNullOrEmpty, ex.Message); - ex = Assert.Throws(() => coll.Modify("_id == 1").Change(null, new { title = "bar" }).Execute()); - StringAssert.AreEqualIgnoringCase(ResourcesX.DocPathNullOrEmpty, ex.Message); - ex = Assert.Throws(() => coll.Modify("_id == 1").ArrayInsert(null, new { title = "bar" }).Execute()); - StringAssert.AreEqualIgnoringCase(ResourcesX.DocPathNullOrEmpty, ex.Message); - ex = Assert.Throws(() => coll.Modify("_id == 1").ArrayAppend(null, new { title = "bar" }).Execute()); - StringAssert.AreEqualIgnoringCase(ResourcesX.DocPathNullOrEmpty, ex.Message); - var ex2 = Assert.Throws(() => coll.Modify("_id == 1").Unset(null).Execute()); - } - } -} \ No newline at end of file +// Copyright © 2015, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySql.Data; +using MySql.Data.MySqlClient; +using MySqlX.XDevAPI; +using MySqlX.XDevAPI.Common; +using MySqlX.XDevAPI.Relational; +using NUnit.Framework; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +namespace MySqlX.Data.Tests +{ + public class CollectionTests : BaseTest + { + [TearDown] + public void tearDown() + { + session.Schema.DropCollection("test"); + session.Schema.DropCollection("test123"); + session.Schema.DropCollection("testcount"); + session.Schema.DropCollection("coll"); + session.Schema.DropCollection("col20"); + session.Schema.DropCollection("col21"); + session.Schema.DropCollection("col22"); + } + + [Test] + public void GetAllCollections() + { + session.DropSchema("test"); + session.CreateSchema("test"); + Collection book = CreateCollection("book"); + List collections = book.Schema.GetCollections(); + Assert.That(collections, Has.One.Items); + Assert.True(collections[0].Name == "book"); + book.Schema.DropCollection("book"); + } + + [Test] + public void CreateAndDropCollection() + { + Session s = GetSession(); + Schema test = s.GetSchema("test"); + Collection testColl = test.CreateCollection("test"); + Assert.True(CollectionExistsInDatabase(testColl)); + + // Drop existing collection. + test.DropCollection("test"); + Assert.False(CollectionExistsInDatabase(testColl)); + + // Drop non-existing collection. + test.DropCollection("test"); + Assert.False(CollectionExistsInDatabase(testColl)); + + //dropCollection when the object to drop contains invalid characters + test.DropCollection("%^&!@~*(&*(*&:>(() => test.DropCollection(string.Empty)); + Assert.Throws(() => test.DropCollection(" ")); + Assert.Throws(() => test.DropCollection(" ")); + Assert.Throws(() => test.DropCollection(null)); + } + + [Test] + public void CreateCollectionIndex() + { + Session session = GetSession(); + Schema test = session.GetSchema(schemaName); + Collection testColl = test.CreateCollection("test"); + Assert.True(CollectionExistsInDatabase(testColl), "ExistsInDatabase failed"); + testColl.CreateIndex("testIndex", "{ \"fields\": [ { \"field\":$.myId, \"type\":\"INT\", \"required\":true } ] }"); + var result = ExecuteAddStatement(testColl.Add(new { myId = 1 }).Add(new { myId = 2 })); + Assert.AreEqual(result.AffectedItemsCount, 2); + } + + [Test] + public void DropCollectionIndex() + { + Session session = GetSession(); + Schema test = session.GetSchema(schemaName); + Collection testColl = CreateCollection("test"); + testColl.CreateIndex("testIndex", "{ \"fields\": [ { \"field\":$.myId, \"type\":\"INT\", \"required\":true } ] }"); + + // Drop existing index. + testColl.DropIndex("testIndex"); + + // Drop non-existing index. + testColl.DropIndex("testIndex"); + + //dropIndex contains invalid characters + testColl.DropIndex("%^&!@~*(&*(*&:>(() => testColl.DropIndex(string.Empty)); + Assert.Throws(() => testColl.DropIndex(" ")); + Assert.Throws(() => testColl.DropIndex(" ")); + Assert.Throws(() => testColl.DropIndex(null)); + + } + + [Test] + public void DropSchemaTests() + { + session.DropSchema("validSchema"); + session.CreateSchema("validSchema"); + session.DropSchema("validSchema"); + session.DropSchema("%^&!@~*(&*(*&:>(() => session.DropSchema(string.Empty)); + Assert.Throws(() => session.DropSchema(" ")); + Assert.Throws(() => session.DropSchema(" ")); + Assert.Throws(() => session.DropSchema(null)); + } + + + [Test] + public void ValidateExistence() + { + Session session = GetSession(); + Schema schema = session.GetSchema(schemaName); + var ex = Assert.Throws(() => schema.GetCollection("nonExistentCollection", true)); + Assert.AreEqual("Collection 'nonExistentCollection' does not exist.", ex.Message); + } + + [Test] + public void CountCollection() + { + Session session = GetSession(); + Schema schema = session.GetSchema(schemaName); + CreateCollection("testCount"); + var count = session.SQL("SELECT COUNT(*) FROM test.testCount").Execute().FetchOne()[0]; + + // Zero records + var collection = schema.GetCollection("testCount"); + Assert.AreEqual(count, collection.Count()); + var table = schema.GetTable("testCount"); + Assert.AreEqual(count, table.Count()); + + // Insert some records + var stm = collection.Add(@"{ ""_id"": 1, ""foo"": 1 }") + .Add(@"{ ""_id"": 2, ""foo"": 2 }") + .Add(@"{ ""_id"": 3, ""foo"": 3 }"); + stm.Execute(); + count = session.SQL("SELECT COUNT(*) FROM test.testCount").Execute().FetchOne()[0]; + Assert.AreEqual(count, collection.Count()); + + table.Insert("doc").Values(@"{ ""_id"": 4, ""foo"": 4 }").Execute(); + count = session.SQL("SELECT COUNT(*) FROM test.testCount").Execute().FetchOne()[0]; + Assert.AreEqual(count, table.Count()); + + collection.RemoveOne(2); + count = session.SQL("SELECT COUNT(*) FROM test.testCount").Execute().FetchOne()[0]; + Assert.AreEqual(count, collection.Count()); + Assert.AreEqual(count, table.Count()); + + // Collection/Table does not exist + var ex = Assert.Throws(() => schema.GetCollection("testCount_").Count()); + Assert.AreEqual("Collection 'testCount_' does not exist in schema 'test'.", ex.Message); + ex = Assert.Throws(() => schema.GetTable("testCount_").Count()); + Assert.AreEqual("Table 'testCount_' does not exist in schema 'test'.", ex.Message); + } + + [Test] + public void ModifyCollectionNoLevelNorSchema() + { + Session s = GetSession(); + Schema test = s.GetSchema("test"); + + // Modify a Collection without passing schema and Level, (Bug#30660917) + test.CreateCollection("coll"); + ModifyCollectionOptions options1 = new ModifyCollectionOptions(); + options1.Validation = new Validation() { }; + Assert.Throws(() => test.ModifyCollection("coll", options1)); + } + + [Test] + public void CreateCollectionWithOptions() + { + Session s = GetSession(); + Schema test = s.GetSchema("test"); + + // CreateCollection Test Cases + + // Create a Collection passing a valid schema and Level + CreateCollectionOptions options = new CreateCollectionOptions(); + Validation val = new Validation(); + val.Level = ValidationLevel.STRICT; + string str = "{\"id\": \"http://json-schema.org/geo\"," + + "\"$schema\": \"http://json-schema.org/draft-06/schema#\"," + + "\"description\": \"A geographical coordinate\"," + + "\"type\": \"object\"," + + "\"properties\": {" + + "\"latitude\": {" + + "\"type\": \"number\"" + + " }," + + "\"longitude\": {" + + "\"type\": \"number\"" + + "}" + + "}," + + "\"required\": [\"latitude\", \"longitude\"]" + + "}"; + val.Schema = str; + options.ReuseExisting = false; + options.Validation = val; + Collection testColl = test.CreateCollection("testWithSchemaValidation", options); + Assert.True(CollectionExistsInDatabase(testColl)); + + //Bug #30830962 + options = new CreateCollectionOptions(); + val = new Validation() { }; + options.Validation = val; + var testbug1 = test.CreateCollection("bug_0962", options); //create collection with empty options + testbug1.Add(@"{ ""latitude"": 20, ""longitude"": 30 }").Execute(); + testbug1.Add(@"{ ""sexo"": 1, ""edad"": 20 }").Execute(); + int.TryParse(session.SQL("SELECT COUNT(*) FROM test.bug_0962").Execute().FetchOne()[0].ToString(), out int expected_count); + Assert.AreEqual(2, expected_count); //Collection is created as STRICT with empty json schema,both records were inserted + + options = new CreateCollectionOptions(); + val = new Validation() { Schema = str }; + options.Validation = val; + testbug1 = test.CreateCollection("bug_0962b", options);// adding an schema from + testbug1.Add(@"{ ""latitude"": 20, ""longitude"": 30 }").Execute(); + var invalidEx = Assert.Throws(() => testbug1.Add(@"{ ""sexo"": 1, ""edad"": 20 }").Execute()); + StringAssert.Contains("Document is not valid according to the schema assigned to collection", invalidEx.Message); + + // Create a Collection passing a reuse_existing parameter to server + CreateCollectionOptions options_reuse = new CreateCollectionOptions(); + options_reuse.ReuseExisting = false; + options_reuse.Validation = val; + Collection testCol2 = test.CreateCollection("testReuseExisting_1", options_reuse); + Assert.True(CollectionExistsInDatabase(testCol2)); + + //Insert Valid record with Level Strict + var insert_statement = testColl.Add(@"{ ""latitude"": 20, ""longitude"": 30 }"); + insert_statement.Execute(); + var count = session.SQL("SELECT COUNT(*) FROM test.testWithSchemaValidation").Execute().FetchOne()[0]; + Assert.AreEqual(count, testColl.Count()); + + //Insert invalid record with Level Strict + insert_statement = testColl.Add(@"{ ""OtherField"": ""value"", ""Age"": 30 }"); + var invalidInsertEx = Assert.Throws(() => insert_statement.Execute()); + StringAssert.Contains("Document is not valid according to the schema assigned to collection", invalidInsertEx.Message); + + //Test: Old MySQL Server Version exceptions + if (!(session.Version.isAtLeast(8, 0, 19))) + { + //FR6.2 + var ex1 = Assert.Throws(() => test.CreateCollection("testInvalid", options)); + StringAssert.Contains("Invalid number of arguments, expected 2 but got 3, " + + "The server doesn't support the requested operation. Please update the MySQL Server and/or Client library", ex1.Message); + + //FR6.3 + test.CreateCollection("testInvalid"); + ModifyCollectionOptions modifyOptions = new ModifyCollectionOptions(); + modifyOptions.Validation = val; + var ex2 = Assert.Throws(() => test.ModifyCollection("testInvalid", modifyOptions)); + StringAssert.Contains("Invalid mysqlx command modify_collection_options, " + + "The server doesn't support the requested operation. Please update the MySQL Server and/or Client library", ex2.Message); + } + + //Create collection with json schema and level OFF. Try to insert document matches this schema + options = new CreateCollectionOptions(); + options.Validation = new Validation() { Level = ValidationLevel.OFF, Schema = str }; + Collection col_test = test.CreateCollection("Test_2b_1", options); + Assert.True(CollectionExistsInDatabase(col_test)); + insert_statement = col_test.Add(@"{ ""latitude"": 120, ""longitude"": 78 }"); + insert_statement.Execute(); + count = session.SQL("SELECT COUNT(*) FROM test.Test_2b_1").Execute().FetchOne()[0]; + Assert.AreEqual(count, col_test.Count()); + + //Create collection with json schema and level OFF,ReuseExisting set to true, Try to insert + options = new CreateCollectionOptions(); + options.Validation = new Validation() { Level = ValidationLevel.OFF, Schema = str }; + options.ReuseExisting = true; + col_test = test.CreateCollection("Test_2b_2", options); + Assert.True(CollectionExistsInDatabase(col_test)); + insert_statement = col_test.Add(@"{ ""latitude"": 20, ""longitude"": 42 }"); + insert_statement.Execute(); + count = session.SQL("SELECT COUNT(*) FROM test.Test_2b_2").Execute().FetchOne()[0]; + Assert.AreEqual(count, col_test.Count()); + + //Create collection with only schema option, Try to insert + options = new CreateCollectionOptions(); + options.Validation = new Validation() { Schema = str }; + col_test = test.CreateCollection("Test_2b_3", options); + Assert.True(CollectionExistsInDatabase(col_test)); + insert_statement = col_test.Add(@"{ ""latitude"": 5, ""longitude"": 10 }"); + insert_statement.Execute(); + count = session.SQL("SELECT COUNT(*) FROM test.Test_2b_3").Execute().FetchOne()[0]; + Assert.AreEqual(count, col_test.Count()); + + //Create collection with only schema option,ReuseExisting set to true, Try to insert + options = new CreateCollectionOptions(); + options.Validation = new Validation() { Schema = str }; + options.ReuseExisting = true; + col_test = test.CreateCollection("Test_2b_4", options); + Assert.True(CollectionExistsInDatabase(col_test)); + insert_statement = col_test.Add(@"{ ""latitude"": 25, ""longitude"": 52 }"); + insert_statement.Execute(); + count = session.SQL("SELECT COUNT(*) FROM test.Test_2b_4").Execute().FetchOne()[0]; + Assert.AreEqual(count, col_test.Count()); + + //Create collection with only level option + options = new CreateCollectionOptions(); + options.Validation = new Validation() { Level = ValidationLevel.OFF }; + col_test = test.CreateCollection("Test_2b_5", options); + Assert.True(CollectionExistsInDatabase(col_test)); + + //ResuseExisting = false should throw exception for an existing collection + CreateCollectionOptions testReuseOptions = new CreateCollectionOptions(); + testReuseOptions.ReuseExisting = false; + testReuseOptions.Validation = new Validation() { Level = ValidationLevel.OFF }; + test.CreateCollection("testReuse"); + var exreuse = Assert.Throws(() => test.CreateCollection("testReuse", testReuseOptions)); + StringAssert.AreEqualIgnoringCase("Table 'testReuse' already exists", exreuse.Message); + + //Test: Resuse Existing = True should return existing collection + testReuseOptions.ReuseExisting = true; + var existing = test.CreateCollection("testReuse", testReuseOptions); + Assert.True(CollectionExistsInDatabase(existing)); + + //Create collection and prepare test data with json schema and level STRICT + CreateCollectionOptions prepareOptions = new CreateCollectionOptions(); + prepareOptions.Validation = new Validation() { Level = ValidationLevel.STRICT, Schema = str }; + var res_stm = test.CreateCollection("TestCreateInsert", prepareOptions).Add(@"{ ""latitude"": 25, ""longitude"": 52 }"); + res_stm.Execute(); + var num = session.SQL("SELECT COUNT(*) FROM test.TestCreateInsert").Execute().FetchOne()[0]; + var collection_test = test.GetCollection("TestCreateInsert"); + Assert.AreEqual(num, collection_test.Count()); + + //Passing invalid Schema + options = new CreateCollectionOptions(); + options.Validation = new Validation() { Level = ValidationLevel.STRICT, Schema = "Not Valid JSON Schema" }; + Exception ex_schema = Assert.Throws(() => test.CreateCollection("testInvalidSchema", options)); + StringAssert.Contains(@"The value provided is not a valid JSON document.", ex_schema.Message); + + //Testing an schema with different data types + str = "{\"id\": \"http://json-schema.org/geo\"," + + "\"$schema\": \"http://json-schema.org/draft-06/schema#\"," + + "\"description\": \"A Person example\"," + + "\"type\": \"object\"," + + "\"properties\": {" + + "\"name\": {" + + "\"type\": \"string\"" + + " }," + + "\"age\": {" + + "\"type\": \"number\"" + + "}" + + "}," + + "\"required\": [\"name\", \"age\"]" + + "}"; + + options = new CreateCollectionOptions(); + options.Validation = new Validation() { Level = ValidationLevel.STRICT, Schema = str }; + Collection person_col = test.CreateCollection("testWithPersonSchema", options); + Assert.True(CollectionExistsInDatabase(person_col)); + person_col.Add(@"{ ""name"": ""John"", ""age"": 52 }").Execute(); + var rows = session.SQL("SELECT COUNT(*) FROM test.testWithPersonSchema").Execute().FetchOne()[0]; + Assert.AreEqual(rows, person_col.Count()); + + // Create an existing collection with different schema + options = new CreateCollectionOptions(); + options.ReuseExisting = true; + options.Validation = new Validation() { Level = ValidationLevel.STRICT, Schema = str }; + Collection col_schema1 = test.CreateCollection("testSchema1", options); + Assert.True(CollectionExistsInDatabase(col_schema1)); + + col_schema1.Add(@"{ ""name"": ""John"", ""age"": 52 }").Execute(); + Assert.AreEqual(1, col_schema1.Count()); + var sqlDefinition1 = session.SQL("SHOW CREATE TABLE test.testSchema1").Execute().FetchOne()[1]; + + + var schema2 = "{\"id\": \"http://json-schema.org/geo\"," + + "\"$schema\": \"http://json-schema.org/draft-06/schema#\"," + + "\"description\": \"A Movies example\"," + + "\"type\": \"object\"," + + "\"properties\": {" + + "\"title\": {" + + "\"type\": \"string\"" + + " }," + + "\"movie\": {" + + "\"type\": \"string\"" + + "}" + + "}," + + "\"required\": [\"title\", \"movie\"]" + + "}"; + + options.Validation = new Validation() { Level = ValidationLevel.STRICT, Schema = schema2 }; + Collection col_schema2 = test.CreateCollection("testSchema1", options); + var sqlDefinition2 = session.SQL("SHOW CREATE TABLE test.testSchema1").Execute().FetchOne()[1]; + Assert.AreEqual(sqlDefinition1, sqlDefinition2); + + //Create a collection without sending reuseExisting parameter and insert record + Collection original_col1 = test.CreateCollection("testOriginal1"); + Assert.True(CollectionExistsInDatabase(original_col1)); + original_col1.Add(@"{ ""name"": ""John"", ""age"": 52 }").Execute(); + rows = session.SQL("SELECT COUNT(*) FROM test.testOriginal1").Execute().FetchOne()[0]; + Assert.AreEqual(rows, original_col1.Count()); + + //Create a new collection sending reuseExisting as true, insert record + Collection original_col2 = test.CreateCollection("testOriginal2", true); + Assert.True(CollectionExistsInDatabase(original_col2)); + original_col2.Add(@"{ ""name"": ""John"", ""age"": 52 }").Execute(); + rows = session.SQL("SELECT COUNT(*) FROM test.testOriginal2").Execute().FetchOne()[0]; + Assert.AreEqual(rows, original_col2.Count()); + + //Create an existing collection sending reuseExisting as true, insert record + Collection original_col3 = test.CreateCollection("testOriginal2", true); + Assert.True(CollectionExistsInDatabase(original_col3)); + original_col3.Add(@"{ ""name"": ""John2"", ""age"": 12 }").Execute(); + Assert.AreEqual(2, original_col3.Count()); + + //Create an existing collection sending reuseExisting as false,exception expected + var ex_existing = Assert.Throws(() => test.CreateCollection("testOriginal2", false)); + StringAssert.AreEqualIgnoringCase(@"Table 'testOriginal2' already exists", ex_existing.Message); + + //Modify collection with only level option + ModifyCollectionOptions Test_Options = new ModifyCollectionOptions(); + Test_Options.Validation = new Validation() { Level = ValidationLevel.OFF }; + Collection col_Test_2a_1 = test.ModifyCollection("testWithSchemaValidation", Test_Options); + + // Inser valid and invalid records with level set to Off + insert_statement = col_Test_2a_1.Add(@"{ ""latitude"": 20, ""longitude"": 30 }") + .Add(@"{ ""OtherField"": ""value"", ""Age"": 30 }"); + insert_statement.Execute(); + count = session.SQL("SELECT COUNT(*) FROM test.testWithSchemaValidation").Execute().FetchOne()[0]; + Assert.AreEqual(count, col_Test_2a_1.Count()); + + //Modify collection with only schema option + Test_Options.Validation = new Validation() { Schema = "{ }" }; + test.ModifyCollection("testWithSchemaValidation", Test_Options); + var sqlCreate = session.SQL("SHOW CREATE TABLE test.testWithSchemaValidation").Execute().FetchOne()[1]; + Assert.True(sqlCreate.ToString().Contains(@"'{\r\n}'") || sqlCreate.ToString().Contains("{}")); + + //Passing null as parameter to ModifyCollection + var emptyOptions = new ModifyCollectionOptions(); + emptyOptions.Validation = new Validation() { }; + test.CreateCollection("testnull"); + exreuse = Assert.Throws(() => test.ModifyCollection("testnull", null)); + Assert.AreEqual(@"Arguments value used under ""validation"" must be an object with at least one field", exreuse.Message); + + test.DropCollection("testWithSchemaValidation"); + test.DropCollection("bug_0962"); + test.DropCollection("bug_0962b"); + test.DropCollection("testReuseExisting_1"); + test.DropCollection("Test_2b_1"); + test.DropCollection("Test_2b_2"); + test.DropCollection("Test_2b_3"); + test.DropCollection("Test_2b_4"); + test.DropCollection("Test_2b_5"); + test.DropCollection("testReuse"); + test.DropCollection("TestCreateInsert"); + test.DropCollection("testWithPersonSchema"); + test.DropCollection("testSchema1"); + test.DropCollection("testOriginal1"); + test.DropCollection("testOriginal2"); + test.DropCollection("testnull"); + } + + /// + /// Server Bug + /// Bug #31667405 - INCORRECT PREPARED STATEMENT OUTCOME WITH NUMERIC STRINGS IN JSON + /// + [Test] + public void PreparedStatementWithNumericStrings() + { + Collection coll = CreateCollection("test"); + object[] _docs = new[] + { + new { _id = "1", title = "foo" }, + new { _id = "2", title = "bar" } + }; + + ExecuteAddStatement(coll.Add(_docs)); + + var stmt = coll.Find("_id=:v").Bind("v", "1"); + var res = stmt.Execute(); + var values = res.FetchOne(); + Assert.AreEqual(1, Convert.ToInt32(values.values["_id"])); + StringAssert.AreEqualIgnoringCase("foo", values.values["title"].ToString()); + + res = coll.Find("_id=:v").Bind("v", "2").Execute(); + values = res.FetchOne(); + Assert.AreEqual(2, Convert.ToInt32(values.values["_id"])); + StringAssert.AreEqualIgnoringCase("bar", values.values["title"].ToString()); + } + + [Test, Description("Verify Count method for Tables,Collections,Collection As Table,Views with different combinations")] + public void AdditionalCountTests() + { + Session session = GetSession(); + Schema schema = session.GetSchema(schemaName); + CreateCollection("testCount"); + var count = session.SQL("SELECT COUNT(*) FROM test.testCount").Execute().FetchOne()[0]; + var collection = schema.GetCollection("testCount"); + var collectionAsTable = schema.GetCollectionAsTable("testCount"); + Assert.AreEqual(count, collection.Count()); + Assert.AreEqual(count, collectionAsTable.Count()); + + session.SQL($"USE {schemaName}").Execute(); + session.SQL("create table test1(name VARCHAR(40), age INT)").Execute(); + count = session.SQL($"SELECT COUNT(*) FROM {schemaName}.test1").Execute().FetchOne()[0]; + Table table = session.GetSchema(schemaName).GetTable("test1"); + Assert.AreEqual(count, collectionAsTable.Count()); + + var result = table.Insert("name", "age") + .Values("MARK", "34") + .Values("richie", "16") + .Values("TEST", "50") + .Execute(); + + Assert.AreEqual((ulong)3, result.AffectedItemsCount); + var selectResult = table.Select().Execute(); + while (selectResult.Next()) ; + Assert.AreEqual(3, selectResult.Rows.Count); + Assert.AreEqual("MARK", selectResult.Rows.ToArray()[0][0].ToString()); + count = session.SQL($"SELECT COUNT(*) FROM {schemaName}.test1").Execute().FetchOne()[0]; + Assert.AreEqual(count, table.Count()); + + // Insert some records + var stm = collection.Add(@"{ ""_id"": 1, ""foo"": 1 }") + .Add(@"{ ""_id"": 2, ""foo"": 2 }") + .Add(@"{ ""_id"": 3, ""foo"": 3 }"); + stm.Execute(); + count = session.SQL("SELECT COUNT(*) FROM test.testCount").Execute().FetchOne()[0]; + Assert.AreEqual(count, collection.Count()); + collectionAsTable = schema.GetCollectionAsTable("testCount"); + Assert.AreEqual(count, collectionAsTable.Count()); + + table = schema.GetTable("testCount"); + table.Insert("doc").Values(@"{ ""_id"": 4, ""foo"": 4 }").Execute(); + count = session.SQL($"SELECT COUNT(*) FROM {schemaName}.testCount").Execute().FetchOne()[0]; + Assert.AreEqual(count, table.Count()); + + collection.RemoveOne(2); + count = session.SQL($"SELECT COUNT(*) FROM {schemaName}.testCount").Execute().FetchOne()[0]; + Assert.AreEqual(count, collection.Count()); + Assert.AreEqual(count, table.Count()); + + // Collection/Table does not exist + Assert.Throws(() => schema.GetCollection("testCount_").Count()); + Assert.Throws(() => schema.GetTable("testCount_").Count()); + + session.SQL("DROP TABLE IF EXISTS test1").Execute(); + session.SQL("CREATE TABLE test1(id1 int,firstname varchar(20))").Execute(); + session.SQL("INSERT INTO test1 values ('1','Rob')").Execute(); + session.SQL("INSERT INTO test1 values ('2','Steve')").Execute(); + session.SQL("CREATE TABLE test2(id2 int,lastname varchar(20))").Execute(); + session.SQL("INSERT INTO test2 values ('1','Williams')").Execute(); + session.SQL("INSERT INTO test2 values ('2','Waugh')").Execute(); + session.SQL("CREATE VIEW view1 AS select * from test1").Execute(); + session.SQL("SELECT * FROM view1").Execute(); + session.SQL("CREATE VIEW view2 AS select * from test2").Execute(); + session.SQL("SELECT * FROM view2").Execute(); + count = session.SQL("SELECT COUNT(*) FROM view1").Execute().FetchOne()[0]; + Assert.AreEqual(count, schema.GetTable("view1").Count()); + schema.DropCollection("testCount"); + session.SQL("DROP TABLE IF EXISTS test1").Execute(); + session.SQL("DROP TABLE IF EXISTS test2").Execute(); + } + + [Test, Description("Verify Expected exceptions in Count")] + public void ExceptionsInCount() + { + if (!session.Version.isAtLeast(8, 0, 0)) Assert.Ignore("This test is for MySql 8.0 or higher."); + var coll = CreateCollection("testCount"); + var docs = new[] + { + new {_id = 1, title = "Book 1", pages = 20}, + new {_id = 2, title = "Book 2", pages = 30}, + new {_id = 3, title = "Book 3", pages = 40}, + new {_id = 4, title = "Book 4", pages = 50} + }; + var r = coll.Add(docs).Execute(); + var count = session.SQL("SELECT COUNT(*) FROM test.testCount").Execute().FetchOne()[0]; + Schema schema = session.GetSchema(schemaName); + var collection = schema.GetCollection("testCount"); + Assert.AreEqual(4, collection.Count()); + + coll.Add(new { _id = 5, title = "Book 5", pages = 60 }).Execute(); + count = session.SQL("SELECT COUNT(*) FROM test.testCount").Execute().FetchOne()[0]; + schema = session.GetSchema(schemaName); + collection = schema.GetCollection("testCount"); + Assert.AreEqual(5, collection.Count()); + + Table table = session.GetSchema("test").GetTable("testCount"); + Assert.AreEqual(5, table.Count()); + + // Expected exceptions. + Assert.Throws(() => coll.RemoveOne(null)); + Assert.Throws(() => coll.RemoveOne("")); + Assert.Throws(() => coll.RemoveOne(string.Empty)); + Assert.Throws(() => coll.RemoveOne(" ")); + + // Remove sending numeric parameter. + Assert.AreEqual(1, coll.RemoveOne(1).AffectedItemsCount); + Assert.AreEqual(4, collection.Count()); + Assert.AreEqual(4, table.Count()); + + // Remove sending string parameter. + Assert.AreEqual(1, coll.RemoveOne("3").AffectedItemsCount); + Assert.AreEqual(3, collection.Count()); + Assert.AreEqual(3, table.Count()); + + // Remove an auto-generated id. + var document = coll.Find("pages = 60").Execute().FetchOne(); + Assert.AreEqual(1, coll.RemoveOne(document.Id).AffectedItemsCount); + Assert.AreEqual(2, collection.Count()); + Assert.AreEqual(2, table.Count()); + + // Remove a non-existing document. + Assert.AreEqual(0, coll.RemoveOne(5).AffectedItemsCount); + Assert.AreEqual(2, collection.Count()); + Assert.AreEqual(2, table.Count()); + + // Add or ReplaceOne + Assert.AreEqual(1, coll.AddOrReplaceOne(5, new { _id = 5, title = "Book 5", pages = 60 }). + AffectedItemsCount); + Assert.AreEqual(3, collection.Count()); + Assert.AreEqual(3, table.Count()); + + // Add or ReplaceOne + Assert.AreEqual(2, coll.AddOrReplaceOne(2, new { title = "Book 50", pages = 60 }). + AffectedItemsCount); + Assert.AreEqual(3, collection.Count()); + Assert.AreEqual(3, table.Count()); + + // Add or ReplaceOne + Assert.AreEqual(1, coll.AddOrReplaceOne(6, new { _id = 6, title = "Book 6", pages = 70 }). + AffectedItemsCount); + Assert.AreEqual(4, collection.Count()); + Assert.AreEqual(4, table.Count()); + + var result = coll.Modify("_id = 5").Set("title", "Book 5").Execute(); + Assert.AreEqual(4, collection.Count()); + Assert.AreEqual(4, table.Count()); + + coll = CreateCollection("testCount"); + + DbDoc[] jsonlist = new DbDoc[1000]; + DbDoc[] jsonlist1 = new DbDoc[1000]; + for (int i = 0; i < 1000; i++) + { + DbDoc newDoc2 = new DbDoc(); + newDoc2.SetValue("_id", (i + 1000)); + newDoc2.SetValue("F1", ("Field-1-Data-" + i)); + newDoc2.SetValue("F2", ("Field-2-Data-" + i)); + newDoc2.SetValue("F3", (300 + i).ToString()); + jsonlist[i] = newDoc2; + newDoc2 = null; + } + + for (int i = 0; i < 1000; i++) + { + DbDoc newDoc2 = new DbDoc(); + newDoc2.SetValue("_id", (i + 10000)); + newDoc2.SetValue("F1", ("Field-1-Data-" + i)); + newDoc2.SetValue("F2", ("Field-2-Data-" + i)); + newDoc2.SetValue("F3", (300 + i).ToString()); + jsonlist1[i] = newDoc2; + newDoc2 = null; + } + Result res = coll.Add(jsonlist).Add(jsonlist1).Execute(); + count = session.SQL("SELECT COUNT(*) FROM test.testCount").Execute().FetchOne()[0]; + schema = session.GetSchema(schemaName); + collection = schema.GetCollection("testCount"); + Assert.AreEqual(2000, collection.Count()); + + r = coll.Remove("_id = :_id").Bind("_id", 1000).Execute(); + Assert.AreEqual(1999, collection.Count()); + } + + [Test, Description("Verify MultiThreading with count")] + public async Task MultithreadCount() + { + _ = await SubProcessA(); + _ = await SubProcessB(); + } + + private Task SubProcessA() + { + using (var sessionA = MySQLX.GetSession(ConnectionString)) + { + Schema schema = sessionA.GetSchema("test"); + var coll = schema.CreateCollection("testCount"); + DbDoc[] jsonlist = new DbDoc[1000]; + for (int i = 0; i < 1000; i++) + { + DbDoc newDoc2 = new DbDoc(); + newDoc2.SetValue("_id", (i + 1000)); + newDoc2.SetValue("F1", ("Field-1-Data-" + i)); + newDoc2.SetValue("F2", ("Field-2-Data-" + i)); + newDoc2.SetValue("F3", (300 + i).ToString()); + jsonlist[i] = newDoc2; + newDoc2 = null; + } + var res = coll.Add(jsonlist).Execute(); + var count = sessionA.SQL("SELECT COUNT(*) FROM test.testCount").Execute().FetchOne()[0]; + var collection = schema.GetCollection("testCount"); + Assert.AreEqual(1000, collection.Count()); + + var r = coll.Remove("_id = :_id").Bind("_id", 1001).Execute(); + Assert.AreEqual(999, collection.Count()); + } + return Task.FromResult(0); + } + + private Task SubProcessB() + { + Thread.Sleep(8000); + using (var sessionB = MySQLX.GetSession(ConnectionString)) + { + Schema schema = session.GetSchema(schemaName); + var coll = schema.GetCollection("testCount"); + + var count = sessionB.SQL("SELECT COUNT(*) FROM test.testCount").Execute().FetchOne()[0]; + schema = sessionB.GetSchema("test"); + var collection = schema.GetCollection("testCount"); + do + { + if (collection.Count() > 5) + { + Assert.AreEqual(999, collection.Count()); + break; + } + } + while (true); + + var r = coll.Remove("_id = :_id").Bind("_id", 1100).Execute(); + Assert.AreEqual(998, collection.Count()); + } + return Task.FromResult(0); + } + + [Test, Description("Verify the behaviour of the dropX method for dropCollection under stressed conditions")] + public void DropUnderStressedConditions() + { + if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher."); + Schema schema = session.GetSchema(schemaName); + + for (var i = 0; i < 10; i++) + { + schema.CreateCollection("my_collection_123456789"); + schema.DropCollection("my_collection_123456789"); + } + + } + + [Test, Description("Verify that dropX method for dropSchema, dropIndex succeeds in stress conditions")] + public void DropObjectsUnderStress() + { + if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher."); + var schema = session.GetSchema(schemaName); + var testColl = CreateCollection("test123"); + for (var i = 0; i < 150; i++) + { + testColl.Add(new { myId = 1 }).Execute(); + testColl.DropIndex("testIndex"); + testColl.Add(new { myId = 1 }).Execute(); + testColl.DropIndex("testIndex"); + } + + for (var i = 0; i < 1000; i++) + { + session.CreateSchema("validSchema"); + session.DropSchema("validSchema"); + Assert.False(session.GetSchema("validSchema").ExistsInDatabase()); + } + + } + + [Test, Description("Verify that dropX method for dropIndex succeeds when deleted and created again with various combinations")] + public void DropDocuments() + { + if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher."); + var schema = session.GetSchema(schemaName); + schema.DropCollection("test123"); + var testColl = schema.CreateCollection("test123"); + + var result = testColl.Add(new { myId = 1 }).Add(new { myId = 2 }).Execute(); + result = testColl.Add(new { myId = 1 }).Execute(); + + testColl.DropIndex("testIndex"); + result = testColl.Add(new { myId = 1 }).Execute(); + + testColl.DropIndex("testIndex"); + + testColl.DropIndex("testIndex"); + testColl.DropIndex("testIndex"); + result = testColl.Remove("myId = :myId").Bind("myId", 1).Execute(); + result = testColl.Add(new { myId = 1 }).Execute(); + result = testColl.Remove("myId = :myId").Bind("myId", 1).Execute(); + + } + + [Test, Description("Verify ModifyCollection with level OFF and JSON schema")] + public void SchemaValidation_S1() + { + if (!session.Version.isAtLeast(8, 0, 19)) Assert.Ignore("This test is for MySql 8.0.19 or higher."); + var schema = session.GetSchema(schemaName); + var options = new CreateCollectionOptions(); + var options1 = new ModifyCollectionOptions(); + var val = new Validation(); + var doc1 = "{\"id\": \"http://json-schema.org/geo\"," + + "\"$schema\": \"http://json-schema.org/draft-06/schema#\"," + + "\"description\": \"A Person example\"," + + "\"type\": \"object\"," + + "\"properties\": {" + + "\"name\": {" + + "\"type\": \"string\"" + + " }," + + "\"age\": {" + + "\"type\": \"number\"" + + "}" + + "}," + + "\"required\": [\"name\", \"age\"]" + + "}"; + + session.SQL($"use {schemaName}").Execute(); + val.Level = ValidationLevel.OFF; + val.Schema = doc1; + options.Validation = val; + options.ReuseExisting = false; + var collection = schema.CreateCollection("coll1", options); + collection.Add(@"{ ""name"": ""John"", ""age"": 52 }").Execute(); + var count = session.SQL("select count(*) from coll1").Execute().FetchOne()[0]; + Assert.AreEqual(count, collection.Count()); + + val.Level = ValidationLevel.OFF; + val.Schema = doc1; + options.Validation = val; + options.ReuseExisting = true; + collection = schema.CreateCollection("coll1", options); + collection.Add(@"{ ""name"": ""John"", ""age"": 52 }").Execute(); + count = session.SQL("select count(*) from coll1").Execute().FetchOne()[0]; + Assert.AreEqual(count, collection.Count()); + + val.Level = ValidationLevel.OFF; + val.Schema = doc1; + options.Validation = val; + options.ReuseExisting = true; + collection = schema.CreateCollection("coll2", options); + collection.Add(@"{ ""name"": ""John"", ""age"": 52 }").Execute(); + count = session.SQL("select count(*) from coll2").Execute().FetchOne()[0]; + Assert.AreEqual(count, collection.Count()); + + options.Validation = new Validation() { Level = ValidationLevel.OFF, Schema = doc1 }; + options.ReuseExisting = false; + collection = schema.CreateCollection("coll3", options); + collection.Add(@"{ ""name"": ""Ram"" , ""age"": 22 }").Execute(); + count = session.SQL("select count(*) from coll3").Execute().FetchOne()[0]; + Assert.AreEqual(count, collection.Count()); + + options.Validation = new Validation() { Level = ValidationLevel.OFF, Schema = doc1 }; + options.ReuseExisting = true; + collection = schema.CreateCollection("coll3", options); + collection.Add(@"{ ""name"": ""John"", ""age"": 52 }").Execute(); + count = session.SQL("select count(*) from coll3").Execute().FetchOne()[0]; + Assert.AreEqual(count, collection.Count()); + + var doc3 = "{\"id\": \"http://json-schema.org/geo\"," + + "\"$schema\": \"http://json-schema.org/draft-06/schema#\"," + + "\"description\": \"A geographical coordinate\"," + + "\"type\": \"object\"," + + "\"properties\": {" + + "\"latitude\": {" + + "\"type\": \"number\"" + + " }," + + "\"longitude\": {" + + "\"type\": \"number\"" + + "}" + + "}," + + "\"required\": [\"latitude\", \"longitude\"]" + + "}"; + + val.Level = ValidationLevel.OFF; + val.Schema = doc3; + options1.Validation = val; + collection = schema.ModifyCollection("coll1", options1); + collection.Add(@"{ ""latitude"": 20, ""longitude"": 30 }"); + count = session.SQL("select count(*) from coll1").Execute().FetchOne()[0]; + Assert.AreEqual(count, collection.Count()); + + var doc4 = "{\"id\": \"http://json-schema.org/geo\"," + + "\"$schema\": \"http://json-schema.org/draft-06/schema#\"," + + "\"description\": \"A Person example\"," + + "\"type\": \"object\"," + + "\"properties\": {" + + "\"name\": {" + + "\"type\": \"string\"" + + " }" + + "}," + + "\"required\": [\"name\"]" + + "}"; + + val.Level = ValidationLevel.STRICT; + val.Schema = doc4; + options1.Validation = val; + collection = schema.ModifyCollection("coll3", options1); + collection.Add(@"{ ""name"": ""Samar"" }"); + count = session.SQL("select count(*) from coll3").Execute().FetchOne()[0]; + Assert.AreEqual(count, collection.Count()); + + options1.Validation = new Validation() { Level = ValidationLevel.OFF, Schema = doc1 }; + collection = schema.ModifyCollection("coll2", options1); + collection.Add(@"{ ""name"": ""Ram"" , ""age"": 22 }").Execute(); + count = session.SQL("select count(*) from coll2").Execute().FetchOne()[0]; + Assert.AreEqual(count, collection.Count()); + + val.Level = ValidationLevel.STRICT; + val.Schema = doc1; + options1.Validation = new Validation() { Level = ValidationLevel.STRICT, Schema = doc1 }; + collection = schema.ModifyCollection("coll2", options1); + collection.Add(@"{ ""name"": ""Ram"" , ""age"": 22 }").Execute(); + count = session.SQL("select count(*) from coll2").Execute().FetchOne()[0]; + Assert.AreEqual(count, collection.Count()); + } + + [Test, Description("Checking the createcollection() and ModifyCollection() with either the level or the schema")] + public void SchemaValidation_S2() + { + if (!session.Version.isAtLeast(8, 0, 19)) Assert.Ignore("This test is for MySql 8.0.19 or higher."); + var schema = session.GetSchema(schemaName); + session.SQL($"use {schemaName}").Execute(); + var options = new CreateCollectionOptions(); + var options1 = new ModifyCollectionOptions(); + var doc1 = "{\"id\": \"http://json-schema.org/geo\"," + + "\"$schema\": \"http://json-schema.org/draft-06/schema#\"," + + "\"description\": \"A Person example\"," + + "\"type\": \"object\"," + + "\"properties\": {" + + "\"name\": {" + + "\"type\": \"string\"" + + " }," + + "\"age\": {" + + "\"type\": \"number\"" + + "}" + + "}," + + "\"required\": [\"name\", \"age\"]" + + "}"; + + options.Validation = new Validation { Schema = doc1 }; + options.ReuseExisting = false; + var collection = schema.CreateCollection("coll4", options); + collection.Add(@"{ ""name"": ""John"", ""age"": 52 }").Execute(); + var result = session.SQL("select * from coll4").Execute().FetchAll(); + foreach (Row res in result) + Assert.IsNotNull(res[0]); + var count = session.SQL("select count(*) from coll4").Execute().FetchOne()[0]; + Assert.AreEqual(count, collection.Count()); + + options.Validation = new Validation { Schema = doc1 }; + options.ReuseExisting = true; + collection = schema.CreateCollection("coll4", options); + collection.Add(@"{ ""name"": ""John"", ""age"": 52 }").Execute(); + result = session.SQL("select * from coll4").Execute().FetchAll(); + foreach (Row res in result) + Assert.IsNotNull(res[0]); + count = session.SQL("select count(*) from coll4").Execute().FetchOne()[0]; + Assert.AreEqual(count, collection.Count()); + + options.Validation = new Validation { Schema = doc1 }; + options.ReuseExisting = true; + collection = schema.CreateCollection("colltesting", options); + Assert.Throws(() => ExecuteAddStatement(collection.Add(@"{ ""name"": ""John"", ""age"": ""52"" }"))); + count = session.SQL("select count(*) from colltesting").Execute().FetchOne()[0]; + Assert.AreEqual(count, collection.Count()); + + var doc2 = "{\"id\":\"http://json-schema.org/geo\"," + + "\"$schema\": \"http://json-schema.org/draft-06/schema#\"," + + "\"description\": \"A Person example\"," + + "\"type\": \"object\"," + + "\"properties\": {" + + "\"name\": {\"type\": \"string\"}," + + "\"number\": {\"type\": \"number\"}," + + "\"street_name\": {\"type\": \"string\"} ," + + "\"street_type\": {\"type\": \"string\"}," + + "\"colors\": " + + "{\"type\": \"array\" ," + + "\"description\": \"different colors\"," + + "\"items\": [" + + "{\"type\": \"string\"," + + "\"enum\": [\"red\", \"amber\", \"green\"]" + + "}," + + "{\"type\": \"number\"}," + + "{\"type\": \"boolean\"}"//," + + "{\"type\": \"null\"}," + + "]" + + "}" + + "}," + + "\"required\": [\"name\", \"number\"]" + + "}"; + + options.Validation = new Validation { Schema = doc2 }; + options.ReuseExisting = true; + Assert.Throws(() => schema.CreateCollection("colltesting2", options)); + + options.Validation = new Validation { Level = ValidationLevel.OFF }; ; + options.ReuseExisting = false; + collection = schema.CreateCollection("coll5", options); + collection.Add(@"{ ""name"": ""John"", ""age"": 52 }").Execute(); + result = session.SQL("select * from coll5").Execute().FetchAll(); + foreach (Row res in result) + Assert.IsNotNull(res[0]); + count = session.SQL("select count(*) from coll5").Execute().FetchOne()[0]; + Assert.AreEqual(count, collection.Count()); + + options.Validation = new Validation { Level = ValidationLevel.STRICT }; + options.ReuseExisting = false; + collection = schema.CreateCollection("coll6", options); + collection.Add(@"{ ""name"": ""John"", ""age"": 52 }").Execute(); + result = session.SQL("select * from coll6").Execute().FetchAll(); + foreach (Row res in result) + Assert.IsNotNull(res[0]); + count = session.SQL("select count(*) from coll6").Execute().FetchOne()[0]; + Assert.AreEqual(count, collection.Count()); + + options1.Validation = new Validation() { Schema = doc1 }; + collection = schema.ModifyCollection("coll6", options1); + collection.Add(@"{ ""name"": ""Ram"" , ""age"": 22 }").Execute(); + result = session.SQL("select * from coll6").Execute().FetchAll(); + foreach (Row res in result) + Assert.IsNotNull(res[0]); + count = session.SQL("select count(*) from coll6").Execute().FetchOne()[0]; + Assert.AreEqual(count, collection.Count()); + + options1.Validation = new Validation() { Schema = doc1 }; + collection = schema.ModifyCollection("colltesting", options1); + Assert.Throws(() => ExecuteAddStatement(collection.Add(@"{ ""name"": ""Ram"" , ""age"": ""22"" }"))); + + options1.Validation = new Validation() { Schema = doc2 }; + Assert.Throws(() => collection = schema.ModifyCollection("colltesting2", options1)); + + options1.Validation = new Validation() { Level = ValidationLevel.OFF }; + collection = schema.ModifyCollection("coll4", options1); + collection.Add(@"{ ""name"": ""Ram"" , ""age"": 22 }").Execute(); + result = session.SQL("select * from coll4").Execute().FetchAll(); + foreach (Row res in result) + Assert.IsNotNull(res[0]); + count = session.SQL("select count(*) from coll4").Execute().FetchOne()[0]; + Assert.AreEqual(count, collection.Count()); + + options1.Validation = new Validation() { Level = ValidationLevel.STRICT }; + collection = schema.ModifyCollection("coll5", options1); + collection.Add(@"{ ""name"": ""Ram"" , ""age"": 22 }").Execute(); + result = session.SQL("select * from coll5").Execute().FetchAll(); + foreach (Row res in result) + Assert.IsNotNull(res[0]); + count = session.SQL("select count(*) from coll5").Execute().FetchOne()[0]; + Assert.AreEqual(count, collection.Count()); + + options1.Validation = new Validation() { }; + Assert.Throws(() => schema.ModifyCollection("coll2", options1)); + + string docEnum = "{\"id\":\"http://json-schema.org/draft-06/schema#\",\"$schema\":\"http://json-schema.org/draft-06/schema#\"," + + "\"description\": \"A Person example\",\"type\":\"object\"," + + "\"properties\":{" + + "\"name\":{" + + "\"type\":\"string\"" + + "}," + + "\"number\":{" + + "\"type\":\"number\"" + + "}," + + "\"street_name\":{" + + "\"type\":\"string\"" + + "}," + + "\"street_type\": {" + + "\"type\": \"string\"" + + "}," + + "\"colors\":{" + + "\"type\": \"array\"," + + "\"items\": {" + + "\"type\":\"string\"" + + "}" + + " }," + + "\"consistent\":{" + + "\"type\": \"boolean\"" + + " }," + + "\"Favourite colors\":{" + + "\"enum\": [" + + "\"red\"," + + "\"amber\"," + + "\"green\"" + + "]" + + "}" + + "}" + + "}"; + + options.Validation = new Validation { Schema = docEnum, Level = ValidationLevel.STRICT }; + options.ReuseExisting = true; + collection = schema.CreateCollection("collEnum", options); + collection.Add(@"{ ""name"": ""John"" }").Execute(); + result = session.SQL("select * from collEnum").Execute().FetchAll(); + foreach (Row res in result) + Console.WriteLine("test with enum: " + res[0]); + count = session.SQL("select count(*) from collEnum").Execute().FetchOne()[0]; + Assert.AreEqual(count, collection.Count()); + } + + [Test, Description("Checking the error messages with different level")] + public void SchemaValidation_S3() + { + if (!session.Version.isAtLeast(8, 0, 19)) Assert.Ignore("This test is for MySql 8.0.19 or higher."); + session.SQL($"use {schemaName}").Execute(); + var options = new CreateCollectionOptions(); + var options1 = new ModifyCollectionOptions(); + var doc1 = "{\"id\": \"http://json-schema.org/geo\"," + + "\"$schema\": \"http://json-schema.org/draft-06/schema#\"," + + "\"description\": \"A Person example\"," + + "\"type\": \"object\"," + + "\"properties\": {" + + "\"name\": {" + + "\"type\": \"string\"" + + " }," + + "\"age\": {" + + "\"type\": \"number\"" + + "}" + + "}," + + "\"required\": [\"name\", \"age\"]" + + "}"; + + var schema = session.GetSchema(schemaName); + options.Validation = new Validation { Schema = doc1, Level = ValidationLevel.STRICT }; + options.ReuseExisting = false; + var collection = schema.CreateCollection("coll7", options); + collection.Add(@"{ ""name"": ""John"", ""age"": 52 }").Execute(); + var result = session.SQL("select * from coll7").Execute().FetchAll(); + foreach (Row res in result) + Assert.IsNotNull(res[0]); + var count = session.SQL("select count(*) from coll7").Execute().FetchOne()[0]; + Assert.AreEqual(count, collection.Count()); + + options.Validation = new Validation { Schema = doc1, Level = ValidationLevel.STRICT }; + options.ReuseExisting = false; + collection = schema.CreateCollection("collext", options); + collection.Add(@"{ ""name"": ""John"", ""age"": 52 }").Execute(); + result = session.SQL("select * from collext").Execute().FetchAll(); + foreach (Row res in result) + Assert.IsNotNull(res[0]); ; + count = session.SQL("select count(*) from collext").Execute().FetchOne()[0]; + Assert.AreEqual(count, collection.Count()); + + var doc2 = "{\"id\":\"http://json-schema.org/geo\"," + + "\"$schema\": \"http://json-schema.org/draft-06/schema#\"," + + "\"description\": \"A Person example\"," + + "\"type\": \"object\"," + + "\"properties\": {" + + "\"name\": {\"type\": \"string\"}," + + "\"number\": {\"type\": \"number\"}," + + "\"street_name\": {\"type\": \"string\"} ," + + "\"street_type\": {\"type\": \"string\"}," + + "\"colors\": " + + "{\"type\": \"array\" ," + + "\"description\": \"different colors\"," + + "\"items\": [" + + "{\"type\": \"string\"," + + "\"enum\": [\"red\", \"amber\", \"green\"]" + + "}," + + "{\"type\": \"number\"}," + + "{\"type\": \"boolean\"}"//," + + "{\"type\": \"null\"}," + + "]" + + "}" + + "}," + + "\"required\": [\"name\", \"number\"]" + + "}"; + + options.Validation = new Validation { Schema = doc2, Level = ValidationLevel.STRICT }; + options.ReuseExisting = false; + Assert.Throws(() => schema.CreateCollection("coll8", options)); + + options.Validation = new Validation { Schema = doc1, Level = ValidationLevel.STRICT }; + options.ReuseExisting = true; + collection = schema.CreateCollection("coll8", options); + collection.Add(@"{ ""name"": ""John"", ""age"": 52 }").Execute(); + result = session.SQL("select * from coll8").Execute().FetchAll(); + foreach (Row res in result) + Assert.IsNotNull(res[0]); ; + count = session.SQL("select count(*) from coll8").Execute().FetchOne()[0]; + Assert.AreEqual(count, collection.Count()); + + options.Validation = new Validation { Schema = doc1, Level = ValidationLevel.STRICT }; + options.ReuseExisting = false; + collection = schema.CreateCollection("coll9", options); + Assert.Throws(() => ExecuteAddStatement(collection.Add(@"{""longitude"":""99""}"))); + + options1.Validation = new Validation { Schema = doc1, Level = ValidationLevel.STRICT }; + collection = schema.ModifyCollection("coll7", options1); + Assert.Throws(() => ExecuteAddStatement(collection.Add(@"{ ""number"": ""56"" }"))); + + options.Validation = new Validation { Schema = doc1, Level = ValidationLevel.OFF }; + options.ReuseExisting = false; + collection = schema.CreateCollection("coll10", options); + collection.Add(@"{""longitude"":""99""}").Execute(); + result = session.SQL("select * from coll10").Execute().FetchAll(); + foreach (Row res in result) + Assert.IsNotNull(res[0]); ; + count = session.SQL("select count(*) from coll10").Execute().FetchOne()[0]; + Assert.AreEqual(count, collection.Count()); + + options1.Validation = new Validation { Schema = doc1, Level = ValidationLevel.OFF }; + collection = schema.ModifyCollection("coll10", options1); + collection.Add(@"{ ""name"": 67 }").Execute(); + result = session.SQL("select * from coll10").Execute().FetchAll(); + foreach (Row res in result) + Assert.IsNotNull(res[0]); ; + count = session.SQL("select count(*) from coll10").Execute().FetchOne()[0]; + Assert.AreEqual(count, collection.Count()); + + options.Validation = new Validation { Schema = doc1, Level = ValidationLevel.STRICT }; + options.ReuseExisting = false; + collection = schema.CreateCollection("coll", options); + collection.Add(@"{""_id"":1,""name"": ""John"", ""age"": 52}").Execute(); + result = session.SQL("select * from coll").Execute().FetchAll(); + foreach (Row res in result) + Assert.IsNotNull(res[0]); ; + count = session.SQL("select count(*) from coll").Execute().FetchOne()[0]; + Assert.AreEqual(count, collection.Count()); + } + + /// + /// Bug 30693969 + /// + [Test, Description("Verify ModifyCollection with level OFF and JSON schema with Json schema")] + public void ModifyCollectionSchemaValidation() + { + if (!session.Version.isAtLeast(8, 0, 19)) Assert.Ignore("This test is for MySql 8.0.19 or higher."); + session.SQL($"use {schemaName}").Execute(); + var schema = session.GetSchema(schemaName); + var options = new CreateCollectionOptions(); + var val = new Validation(); + string doc1 = "{" + + " \"id\":\"https://example.com/arrays.schema.json\"," + + " \"$schema\": \"http://json-schema.org/draft-07/schema#\"," + + " \"description\": \"A representation of a person, company, organization, or place\"," + + " \"type\": \"object\"," + + " \"properties\": {" + + " \"fruits\": {" + + " \"type\": \"array\"," + + " \"items\": {" + + "\"type\": \"string\"" + + " }" + + "}," + + "\"vegetables\": {" + + " \"type\": \"array\"," + + "\"items\": { \"$ref\": \"#/definitions/veggie\" }" + + " }" + + "}," + + "\"definitions\": {" + + " \"veggie\": {" + + " \"type\": \"object\"," + + " \"required\": [ \"veggieName\", \"veggieLike\" ]," + + "\"properties\": {" + + " \"veggieName\": {" + + " \"type\": \"string\"," + + " \"description\": \"The name of the vegetable.\"" + + "}," + + "\"veggieLike\": {" + + "\"type\": \"boolean\"," + + "\"description\": \"Do I like this vegetable?\"" + + "}" + + "}" + + "}" + + "}" + + "}"; + + val.Level = ValidationLevel.STRICT; + val.Schema = doc1; + options.Validation = val; + options.ReuseExisting = false; + var collection = schema.CreateCollection("coll20", options); + collection.Add(@"{""fruits"": [ ""apple"", ""orange"", ""pear"" ],""vegetables"": [{""veggieName"": ""potato"",""veggieLike"": true},{""veggieName"": ""broccoli"",""veggieLike"": false}]}").Execute(); + var result = session.SQL("select * from coll20").Execute().FetchAll(); + foreach (Row res in result) + Assert.IsNotNull(res[0]); + var count = session.SQL("select count(*) from coll20").Execute().FetchOne()[0]; + Assert.AreEqual(count, collection.Count()); + + options.Validation = new Validation { Level = ValidationLevel.STRICT, Schema = doc1 }; + options.ReuseExisting = false; + collection = schema.CreateCollection("coll21", options); + collection.Add(@"{""fruits"": [ ""apple"", ""orange"", ""pear"" ],""vegetables"": [{""veggieName"": ""potato"",""veggieLike"": true},{""veggieName"": ""broccoli"",""veggieLike"": false}]}").Execute(); + result = session.SQL("select * from coll21").Execute().FetchAll(); + foreach (Row res in result) + Assert.IsNotNull(res[0]); + count = session.SQL("select count(*) from coll21").Execute().FetchOne()[0]; + Assert.AreEqual(count, collection.Count()); + + val.Level = ValidationLevel.STRICT; + val.Schema = doc1; + options.Validation = val; + options.ReuseExisting = true; + collection = schema.CreateCollection("coll20", options); + collection.Add(@"{""fruits"": [ ""apple"", ""orange"", ""pear"" ],""vegetables"": [{""veggieName"": ""potato"",""veggieLike"": true},{""veggieName"": ""broccoli"",""veggieLike"": false}]}").Execute(); + result = session.SQL("select * from coll20").Execute().FetchAll(); + foreach (Row res in result) + Assert.IsNotNull(res[0]); + count = session.SQL("select count(*) from coll20").Execute().FetchOne()[0]; + Assert.AreEqual(count, collection.Count()); + + options.Validation = new Validation { Level = ValidationLevel.STRICT, Schema = doc1 }; + options.ReuseExisting = true; + collection = schema.CreateCollection("coll21", options); + collection.Add(@"{""fruits"": [ ""apple"", ""orange"", ""pear"" ],""vegetables"": [{""veggieName"": ""potato"",""veggieLike"": true},{""veggieName"": ""broccoli"",""veggieLike"": false}]}").Execute(); + result = session.SQL("select * from coll21").Execute().FetchAll(); + foreach (Row res in result) + Assert.IsNotNull(res[0]); + count = session.SQL("select count(*) from coll21").Execute().FetchOne()[0]; + Assert.AreEqual(count, collection.Count()); + + val.Level = ValidationLevel.OFF; + val.Schema = doc1; + options.Validation = val; + options.ReuseExisting = true; + collection = schema.CreateCollection("coll22", options); + collection.Add(@"{""fruits"": [ 78, ""orange"", ""pear"" ],""vegetables"": [{""veggieName"": ""potato"",""veggieLike"": true},{""veggieName"": ""broccoli"",""veggieLike"": false}]}").Execute(); + result = session.SQL("select * from coll22").Execute().FetchAll(); + foreach (Row res in result) + Assert.IsNotNull(res[0]); + count = session.SQL("select count(*) from coll22").Execute().FetchOne()[0]; + Assert.AreEqual(count, collection.Count()); + } + + [Test, Description("Verify ModifyCollection with level OFF and JSON schema")] + public void SchemaValidationDeleteRecords() + { + // Bug30748283 + if (!session.Version.isAtLeast(8, 0, 19)) Assert.Ignore("This test is for MySql 8.0.19 or higher."); + string doc5 = "{\"id\": \"http://json-schema.org/geo\"," + + "\"$schema\": \"http://json-schema.org/draft-06/schema#\"," + + "\"description\": \"A Person example\"," + + "\"type\": \"object\"," + + "\"properties\": {" + + "\"name\": {" + + "\"type\": \"number\"" + + " }" + + "}," + + "\"required\": [\"name\"]" + + "}"; + + string doc1 = "{\"id\": \"http://json-schema.org/geo\"," + + "\"$schema\": \"http://json-schema.org/draft-06/schema#\"," + + "\"description\": \"A Person example\"," + + "\"type\": \"object\"," + + "\"properties\": {" + + "\"name\": {" + + "\"type\": \"string\"" + + " }" + + ",\"age\": {" + + "\"type\": \"number\"" + + "}" + + "}," + + "\"required\": [\"name\",\"age\"]" + + "}"; + string doc3 = "{\"id\": \"http://json-schema.org/geo\"," + + "\"$schema\": \"http://json-schema.org/draft-06/schema#\"," + + "\"description\": \"A geographical coordinate\"," + + "\"type\": \"object\"," + + "\"properties\": {" + + "\"latitude\": {" + + "\"type\": \"number\"" + + " }," + + "\"longitude\": {" + + "\"type\": \"number\"" + + "}" + + "}," + + "\"required\": [\"latitude\", \"longitude\"]" + + "}"; + + string doc4 = "{\"id\": \"http://json-schema.org/geo\"," + + "\"$schema\": \"http://json-schema.org/draft-06/schema#\"," + + "\"description\": \"A Person example\"," + + "\"type\": \"object\"," + + "\"properties\": {" + + "\"name\": {" + + "\"type\": \"string\"" + + " }" + + "}," + + "\"required\": [\"name\"]" + + "}"; + + session.SQL($"use {schemaName}").Execute(); + var schema = session.GetSchema(schemaName); + var options = new CreateCollectionOptions(); + var options1 = new ModifyCollectionOptions(); + + options.Validation = new Validation { Level = ValidationLevel.STRICT, Schema = doc5 }; + options.ReuseExisting = true; + var collection = schema.CreateCollection("collectiontest", options); + collection.Add(@"{ ""name"": 52 }").Execute(); + var result = session.SQL("select * from collectiontest").Execute().FetchAll(); + foreach (Row res1 in result) + Assert.IsNotNull(res1[0]); + var count = session.SQL("select count(*) from collectiontest").Execute().FetchOne()[0]; + Assert.AreEqual(count, collection.Count()); + + options1.Validation = new Validation { Level = ValidationLevel.STRICT, Schema = doc1 }; + session.SQL("delete from collectiontest").Execute(); + + collection = schema.ModifyCollection("collectiontest", options1); + collection.Add(@"{ ""name"": ""sammeer"",""age"":8 }").Execute(); + var result2 = session.SQL("select * from collectiontest").Execute().FetchAll(); + foreach (Row res2 in result2) + Console.WriteLine(res2[0]); + count = session.SQL("select count(*) from collectiontest").Execute().FetchOne()[0]; + Assert.AreEqual(count, collection.Count()); + + options1.Validation = new Validation { Level = ValidationLevel.OFF, Schema = doc1 }; + collection = schema.ModifyCollection("collectiontest", options1); + collection.Add(@"{ ""name"": 78 }").Execute(); + result = session.SQL("select * from collectiontest").Execute().FetchAll(); + foreach (Row res2 in result) + Assert.IsNotNull(res2[0]); + count = session.SQL("select count(*) from collectiontest").Execute().FetchOne()[0]; + Assert.AreEqual(count, collection.Count()); + + options1.Validation = new Validation { Level = ValidationLevel.STRICT, Schema = doc3 }; + session.SQL("delete from collectiontest").Execute(); + collection = schema.ModifyCollection("collectiontest", options1); + collection.Add(@"{""latitude"": 253, ""longitude"": 525}").Execute(); + result = session.SQL("select * from collectiontest").Execute().FetchAll(); + foreach (Row res2 in result) + Assert.IsNotNull(res2[0]); + count = session.SQL("select count(*) from collectiontest").Execute().FetchOne()[0]; + Assert.AreEqual(count, collection.Count()); + + options1.Validation = new Validation { Level = ValidationLevel.STRICT, Schema = doc4 }; + session.SQL("delete from collectiontest").Execute(); + result = session.SQL("select * from collectiontest").Execute().FetchAll(); + collection = schema.ModifyCollection("collectiontest", options1); + collection.Add(@"{ ""name"": ""Johnny"" }").Execute(); + result = session.SQL("select * from collectiontest").Execute().FetchAll(); + foreach (Row res2 in result) + Assert.IsNotNull(res2[0]); + count = session.SQL("select count(*) from collectiontest").Execute().FetchOne()[0]; + Assert.AreEqual(count, collection.Count()); + + } + + [Test, Description("Test MySQLX plugin Remove Bind Stress")] + public void RemoveBindStress() + { + if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher."); + Collection coll = CreateCollection("test"); + DbDoc[] jsonlist = new DbDoc[10]; + DbDoc[] jsonlist1 = new DbDoc[10]; + for (int i = 0; i < 10; i++) + { + DbDoc newDoc2 = new DbDoc(); + newDoc2.SetValue("_id", (i + 1000)); + newDoc2.SetValue("F1", ("Field-1-Data-" + i)); + newDoc2.SetValue("F2", ("Field-2-Data-" + i)); + newDoc2.SetValue("F3", (300 + i).ToString()); + jsonlist[i] = newDoc2; + newDoc2 = null; + } + + for (int i = 0; i < 10; i++) + { + DbDoc newDoc2 = new DbDoc(); + newDoc2.SetValue("_id", (i + 10000)); + newDoc2.SetValue("F1", ("Field-1-Data-" + i)); + newDoc2.SetValue("F2", ("Field-2-Data-" + i)); + newDoc2.SetValue("F3", (300 + i).ToString()); + jsonlist1[i] = newDoc2; + newDoc2 = null; + } + Result r = coll.Add(jsonlist).Add(jsonlist1).Execute(); + + Assert.AreEqual(20, r.AffectedItemsCount, "Matching"); + + r = coll.Remove("_id = :_id").Bind("_id", 1000).Execute(); + Assert.AreEqual(1, r.AffectedItemsCount, "Matching"); + } + + [Test, Description("Test MySQLX plugin Get Collection as Table")] + public void GetCollectionAsTableStress() + { + if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher."); + Collection testCollection = CreateCollection("test"); + + DbDoc[] jsonlist = new DbDoc[1000]; + for (int i = 0; i < 1000; i++) + { + DbDoc newDoc2 = new DbDoc(); + newDoc2.SetValue("_id", (i + 1000)); + newDoc2.SetValue("F1", ("Field-1-Data-" + i)); + newDoc2.SetValue("F2", ("Field-2-Data-" + i)); + newDoc2.SetValue("F3", (300 + i).ToString()); + jsonlist[i] = newDoc2; + newDoc2 = null; + } + Result r = testCollection.Add(jsonlist).Execute(); + Assert.AreEqual(1000, r.AffectedItemsCount, "Matching"); + + Table test = testSchema.GetCollectionAsTable("test"); + Assert.IsTrue(test.ExistsInDatabase()); + var rows = test.Select("_id").Execute().FetchAll(); + + for (int j = 0; j < rows.Count; j++) + { + var doc = testCollection.Find("_id like :param").Bind("param", (j + 1000)).Execute(); + var docs = doc.FetchAll().Count(); + Assert.AreEqual(1, docs, "Matches"); + } + } + + [Test, Description("Test MySQLX plugin GetCollection Exception Scenario")] + public void GetCollectionException() + { + if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher."); + using (Session sessionPlain = MySQLX.GetSession(ConnectionString)) + { + Schema db = sessionPlain.GetSchema(schemaName); + Collection col = db.GetCollection("my_collection_123456789"); + if (col.ExistsInDatabase()) + { + db.DropCollection("my_collection_123456789"); + col = db.CreateCollection("my_collection_123456789"); + } + else { col = db.CreateCollection("my_collection_123456789"); } + + Collection col1 = db.GetCollection("my_collection_123456789", true); + if (col.ExistsInDatabase()) + { + db.DropCollection("my_collection_123456789"); + col1 = db.CreateCollection("my_collection_123456789"); + } + else { col1 = db.CreateCollection("my_collection_123456789"); } + + var col2 = db.GetTable("my_collection_1234567891"); + Assert.Throws(() => db.GetCollection("my_collection_test", true)); + db.DropCollection("my_collection_123456789"); + } + } + + [Test, Description("Collection GetDocumentIDS Stress(1000 records)")] + public void GetDocumentIDSStress() + { + Collection coll = CreateCollection("test"); + DbDoc[] jsonlist = new DbDoc[1000]; + for (int i = 0; i < 1000; i++) + { + DbDoc newDoc2 = new DbDoc(); + newDoc2.SetValue("_id", (i)); + newDoc2.SetValue("F1", ("Field-1-Data-" + i)); + newDoc2.SetValue("F2", ("Field-2-Data-" + i)); + newDoc2.SetValue("F3", (3 + i).ToString()); + jsonlist[i] = newDoc2; + newDoc2 = null; + } + Result r = coll.Add(jsonlist).Execute(); + Assert.AreEqual(1000, r.AffectedItemsCount, "Matching"); + var documentIds = r.GeneratedIds; + Assert.False(documentIds != null && documentIds.Count > 0); + } + + [Test, Description("Session Performance Test")] + public void SessionPerformanceTest() + { + string json = ""; + int i = 0, j = 0, maxField = 100; + var collection = CreateCollection("test"); + int maxDepth = 97; + json = "{\"_id\":\"1002\",\"XYZ\":1111"; + for (j = 0; j < maxField; j++) + { + json = json + ",\"ARR" + j + "\":["; + for (i = 0; i < maxDepth; i++) + { + json = json + i + ",["; + } + json = json + i; + for (i = maxDepth - 1; i >= 0; i--) + { + json = json + "]," + i; + } + json = json + "]"; + } + json = json + "}"; + + collection.Add(json).Execute(); + json = "{\"_id\":\"1003\",\"XYZ\":2222"; + for (j = 0; j < maxField; j++) + { + json = json + ",\"DATAX" + j + "\":"; + for (i = 0; i < maxDepth; i++) + { + json = json + "{\"D" + i + "\":"; + } + json = json + maxDepth; + for (i = maxDepth - 1; i >= 0; i--) + { + json = json + "}"; + } + } + json = json + "}"; + + collection.Add(json).Execute(); + json = "{\"_id\":\"1001\",\"XYZ\":3333"; + for (j = 0; j < maxField; j++) + { + json = json + ",\"ARR" + j + "\":["; + for (i = 0; i < maxDepth; i++) + { + json = json + i + ",["; + } + json = json + i; + for (i = maxDepth - 1; i >= 0; i--) + { + json = json + "]," + i; + } + json = json + "]"; + } + + for (j = 0; j < maxField; j++) + { + json = json + ",\"DATAX" + j + "\":"; + for (i = 0; i < maxDepth; i++) + { + json = json + "{\"D" + i + "\":"; + } + json = json + maxDepth; + for (i = maxDepth - 1; i >= 0; i--) + { + json = json + "}"; + } + } + json = json + "}"; + collection.Add(json).Execute(); + + // select + string query = "$.ARR" + (maxField - 1); + for (i = 0; i < maxDepth; i++) + { + query = query + "[1]"; + } + query = query + "[0]"; + json = "CAST(" + query + " as SIGNED)= " + maxDepth; + var docs = collection.Find(json).Fields("$._id as _id," + query + " as Arr").Execute(); + var res = docs.FetchAll(); + Assert.AreEqual("1001", res[0]["_id"].ToString(), "Matching the id"); + Assert.AreEqual("1002", res[1]["_id"].ToString(), "Matching the id"); + + query = "$.DATAX" + (maxField - 1); + for (i = 0; i < maxDepth; i++) + { + query = query + ".D" + i; + } + json = "CAST(" + query + " as SIGNED)"; + docs = collection.Find(json + " =" + maxDepth).Fields("$._id as _id ").Execute(); + res = docs.FetchAll(); + Assert.AreEqual("1001", res[0]["_id"].ToString(), "Matching the id"); + Assert.AreEqual("1003", res[1]["_id"].ToString(), "Matching the id"); + } + + /// + /// Bug #34243143 [Connector/NET allows empty string in Set() method which is chained to Modify()] + /// The fix applied for every method in Modify(). + /// + [Test] + public void EmptyStringInModifyMethods() + { + Collection coll = CreateCollection("test"); + object _doc = new { _id = 1, title = "foo" }; + coll.Add(_doc).Execute(); + var result = coll.Find("_id == 1").Execute().FetchOne(); + + Assert.NotNull(result); + Assert.AreEqual(1, result.Id); + + // empty string + var ex = Assert.Throws(() => coll.Modify("_id == 1").Set("", new { title = "bar" }).Execute()); + StringAssert.AreEqualIgnoringCase(ResourcesX.DocPathNullOrEmpty, ex.Message); + ex = Assert.Throws(() => coll.Modify("_id == 1").Unset("").Execute()); + StringAssert.AreEqualIgnoringCase(ResourcesX.DocPathNullOrEmpty, ex.Message); + ex = Assert.Throws(() => coll.Modify("_id == 1").Change("", new { title = "bar" }).Execute()); + StringAssert.AreEqualIgnoringCase(ResourcesX.DocPathNullOrEmpty, ex.Message); + ex = Assert.Throws(() => coll.Modify("_id == 1").ArrayInsert("", new { title = "bar" }).Execute()); + StringAssert.AreEqualIgnoringCase(ResourcesX.DocPathNullOrEmpty, ex.Message); + ex = Assert.Throws(() => coll.Modify("_id == 1").ArrayAppend("", new { title = "bar" }).Execute()); + StringAssert.AreEqualIgnoringCase(ResourcesX.DocPathNullOrEmpty, ex.Message); + + // white space + ex = Assert.Throws(() => coll.Modify("_id == 1").Set(" ", new { title = "bar" }).Execute()); + StringAssert.AreEqualIgnoringCase(ResourcesX.DocPathNullOrEmpty, ex.Message); + ex = Assert.Throws(() => coll.Modify("_id == 1").Unset(" ").Execute()); + StringAssert.AreEqualIgnoringCase(ResourcesX.DocPathNullOrEmpty, ex.Message); + ex = Assert.Throws(() => coll.Modify("_id == 1").Change(" ", new { title = "bar" }).Execute()); + StringAssert.AreEqualIgnoringCase(ResourcesX.DocPathNullOrEmpty, ex.Message); + ex = Assert.Throws(() => coll.Modify("_id == 1").ArrayInsert(" ", new { title = "bar" }).Execute()); + StringAssert.AreEqualIgnoringCase(ResourcesX.DocPathNullOrEmpty, ex.Message); + ex = Assert.Throws(() => coll.Modify("_id == 1").ArrayAppend(" ", new { title = "bar" }).Execute()); + StringAssert.AreEqualIgnoringCase(ResourcesX.DocPathNullOrEmpty, ex.Message); + + // null + ex = Assert.Throws(() => coll.Modify("_id == 1").Set(null, new { title = "bar" }).Execute()); + StringAssert.AreEqualIgnoringCase(ResourcesX.DocPathNullOrEmpty, ex.Message); + ex = Assert.Throws(() => coll.Modify("_id == 1").Change(null, new { title = "bar" }).Execute()); + StringAssert.AreEqualIgnoringCase(ResourcesX.DocPathNullOrEmpty, ex.Message); + ex = Assert.Throws(() => coll.Modify("_id == 1").ArrayInsert(null, new { title = "bar" }).Execute()); + StringAssert.AreEqualIgnoringCase(ResourcesX.DocPathNullOrEmpty, ex.Message); + ex = Assert.Throws(() => coll.Modify("_id == 1").ArrayAppend(null, new { title = "bar" }).Execute()); + StringAssert.AreEqualIgnoringCase(ResourcesX.DocPathNullOrEmpty, ex.Message); + var ex2 = Assert.Throws(() => coll.Modify("_id == 1").Unset(null).Execute()); + } + } +} diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/CompressionTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/CompressionTests.cs index d350f50bc..edec20eb6 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/CompressionTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/CompressionTests.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2019, 2022, Oracle and/or its affiliates. +// Copyright © 2019, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -932,4 +932,4 @@ protected string GenerateDummyText(string textToRepeat, int timesToRepeat) #endregion Methods } -} \ No newline at end of file +} diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/CrudInsertTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/CrudInsertTests.cs index 69a02b978..7532e8be4 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/CrudInsertTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/CrudInsertTests.cs @@ -1,2506 +1,2506 @@ -// Copyright (c) 2015, 2023, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySql.Data; -using MySql.Data.Common; -using MySql.Data.MySqlClient; -using MySqlX.Common; -using MySqlX.XDevAPI; -using MySqlX.XDevAPI.Common; -using MySqlX.XDevAPI.CRUD; -using MySqlX.XDevAPI.Relational; -using NUnit.Framework; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace MySqlX.Data.Tests -{ - public class CrudInsertTests : BaseTest - { - [Test] - public void InsertSingleDbDocWithId() - { - Collection coll = CreateCollection("test"); - Result r = ExecuteAddStatement(coll.Add(@"{ ""_id"": 1, ""foo"": 1 }")); - Assert.AreEqual(1, r.AffectedItemsCount); - Assert.AreEqual(1, coll.Count()); - } - - [Test] - public void InsertSingleDbDocWithoutId() - { - Collection coll = CreateCollection("test"); - var stmt = coll.Add("{ \"foo\": 1 }"); - if (!session.Version.isAtLeast(8, 0, 5)) - { - // Code 5115 Document is missing a required field - Assert.AreEqual(5115u, Assert.Throws(() => ExecuteAddStatement(stmt)).Code); - return; - } - Result r = ExecuteAddStatement(stmt); - Assert.AreEqual(1, r.AffectedItemsCount); - Assert.AreEqual(1, coll.Count()); - Assert.That(r.GeneratedIds, Has.One.Items); - Assert.False(string.IsNullOrWhiteSpace(r.GeneratedIds[0])); - } - - [Test] - public void InsertMultipleDbDocWithoutId() - { - Collection coll = CreateCollection("test"); - var stmt = coll.Add("{ \"foo\": 1 }") - .Add("{ \"amber\": 2 }") - .Add("{ \"any\": 3 }"); - if (!session.Version.isAtLeast(8, 0, 5)) - { - // Code 5115 Document is missing a required field - Assert.AreEqual(5115u, Assert.Throws(() => ExecuteAddStatement(stmt)).Code); - return; - } - Result r = ExecuteAddStatement(stmt); - Assert.AreEqual(3, r.AffectedItemsCount); - Assert.AreEqual(3, coll.Count()); - Assert.AreEqual(3, r.GeneratedIds.Count); - } - - [Test] - public void InsertAnonymousObjectWithId() - { - var obj = new { _id = "5", name = "Sakila", age = 15 }; - - Collection coll = CreateCollection("test"); - Result r = ExecuteAddStatement(coll.Add(obj)); - Assert.AreEqual(1, r.AffectedItemsCount); - //TODO: pull object and verify data - Assert.AreEqual(1, coll.Count()); - } - - [Test] - public void InsertAnonymousObjectWithNoId() - { - var obj = new { name = "Sakila", age = 15 }; - - Collection coll = CreateCollection("test"); - var stmt = coll.Add(obj); - if (!session.Version.isAtLeast(8, 0, 5)) - { - // Code 5115 Document is missing a required field - Assert.AreEqual(5115u, Assert.Throws(() => ExecuteAddStatement(stmt)).Code); - return; - } - Result r = ExecuteAddStatement(stmt); - Assert.AreEqual(1, r.AffectedItemsCount); - //TODO: pull object and verify data - Assert.AreEqual(1, coll.Count()); - Assert.That(r.GeneratedIds, Has.One.Items); - Assert.False(string.IsNullOrWhiteSpace(r.GeneratedIds[0])); - } - - [Test] - public void InsertMultipleAnonymousObjectsWithId() - { - Collection coll = CreateCollection("test"); - var docs = new[] - { - new { _id = 1, title = "Book 1", pages = 20 }, - new { _id = 2, title = "Book 2", pages = 30 }, - new { _id = 3, title = "Book 3", pages = 40 }, - new { _id = 4, title = "Book 4", pages = 50 }, - }; - Result r = ExecuteAddStatement(coll.Add(docs)); - Assert.AreEqual(4, r.AffectedItemsCount); - Assert.AreEqual(4, coll.Count()); - } - - [Test] - public void ValidatesDocumentIds() - { - Collection coll = CreateCollection("test"); - var stmt = coll.Add(new { name = "Book 1" }); - if (!session.Version.isAtLeast(8, 0, 5)) - { - // Code 5115 Document is missing a required field - Assert.AreEqual(5115u, Assert.Throws(() => ExecuteAddStatement(stmt)).Code); - return; - } - Result result = ExecuteAddStatement(stmt); - Assert.AreEqual(1, result.AffectedItemsCount); - - result = ExecuteModifyStatement(coll.Modify($"_id = '{result.GeneratedIds[0]}'").Set("pages", "20")); - Assert.AreEqual(1, result.AffectedItemsCount); - CollectionAssert.IsEmpty(result.GeneratedIds); - } - - [Test] - public void ReuseStatement() - { - Collection coll = CreateCollection("test"); - var docs = new[] - { - new { _id = 1, title = "Book 1", pages = 20 }, - new { _id = 2, title = "Book 2", pages = 30 }, - new { _id = 3, title = "Book 3", pages = 40 }, - new { _id = 4, title = "Book 4", pages = 50 }, - }; - var stmt = coll.Add(new { _id = 0 }); - foreach (var doc in docs) - { - stmt.Add(doc); - } - Result r = ExecuteAddStatement(stmt); - Assert.AreEqual((ulong)docs.Length + 1, r.AffectedItemsCount); - Assert.AreEqual(5, coll.Count()); - } - - [Test] - public void EmptyDocArray() - { - Collection coll = CreateCollection("test"); - - var insertResult = ExecuteAddStatement(coll.Add(new DbDoc[] { })); - Assert.AreEqual(0ul, insertResult.AffectedItemsCount); - - var result = ExecuteFindStatement(coll.Find()).FetchAll(); - CollectionAssert.IsEmpty(result); - } - - [Test] - public void NullParameter() - { - Collection coll = CreateCollection("test"); - - Assert.Throws(() => ExecuteAddStatement(coll.Add(null))); - } - - [Test] - public void InsertingArray() - { - var docs = new[] - { - new { id = 1, title = "Book 1" }, - new { id = 2, title = "Book 2" }, - }; - DbDoc d2 = new DbDoc(); - d2.SetValue("_id", 1); - d2.SetValue("books", docs); - d2.SetValue("pages", 20); - - Collection coll = CreateCollection("test"); - ExecuteAddStatement(coll.Add(d2)); - var result = ExecuteFindStatement(coll.Find()).FetchAll(); - Assert.That(result, Has.One.Items); - Assert.AreEqual(d2.ToString(), result[0].ToString()); - } - - [Test] - public void CompareGuids() - { - Guid guid1 = new Guid(); - Guid guid2 = new Guid(); - Assert.AreEqual(0, Tools.CompareGuids(guid1, guid2)); - Assert.AreEqual(0, Tools.CompareGuids(guid1.ToString(), guid2.ToString())); - - guid1 = Guid.NewGuid(); - guid2 = Guid.NewGuid(); - Assert.True(Tools.CompareGuids(guid1, guid2) != 0); - Assert.True(Tools.CompareGuids(guid1.ToString(), guid2.ToString()) != 0); - } - - [Test] - public void InsertNullValuesAsDbDoc() - { - Collection collection = CreateCollection("test"); - - var nullValues = new String[] { null, "null", "NULL" }; - var docs = new DbDoc[3]; - for (int i = 0; i < docs.Length; i++) - { - docs[i] = new DbDoc(); - docs[i].SetValue("a", nullValues[i]); - docs[i].SetValue("_id", (i + 1)); - } - - ExecuteAddStatement(collection.Add(docs)); - var result = ExecuteFindStatement(collection.Find()).FetchAll(); - Assert.AreEqual(docs.Length, result.Count); - - for (int i = 0; i < docs.Length; i++) - Assert.AreEqual(docs[i].ToString(), result[i].ToString()); - } - - [Test] - public void InsertNullValuesAsJson() - { - var docs = new[] - { - @"{ ""_id"": 1, ""foo"": null}", - @"{ ""_id"": 2, ""foo"": null }", - @"{ ""_id"": 3, ""foo"": ""null"" }", - @"{ ""_id"": 4, ""foo"": ""NULL"" }", - }; - - Collection collection = CreateCollection("test"); - ExecuteAddStatement(collection.Add(docs)); - var result = ExecuteFindStatement(collection.Find()).FetchAll(); - Assert.AreEqual(docs.Length, result.Count); - for (int i = 0; i < docs.Length; i++) - { - var currentDoc = new DbDoc(docs[i]); - var resultingDoc = new DbDoc(result[i]); - Assert.AreEqual(currentDoc.Id, resultingDoc.Id); - Assert.AreEqual(currentDoc["foo"], resultingDoc["foo"]); - } - } - - [Test] - public void AddOrReplaceOne() - { - if (!session.Version.isAtLeast(8, 0, 3)) return; - - Collection collection = CreateCollection("test"); - var docs = new[] - { - new { _id = 1, title = "Book 1", pages = 20 }, - new { _id = 2, title = "Book 2", pages = 30 }, - new { _id = 3, title = "Book 3", pages = 40 }, - new { _id = 4, title = "Book 4", pages = 50 }, - }; - Result result = ExecuteAddStatement(collection.Add(docs)); - Assert.AreEqual(4, result.AffectedItemsCount); - - // Add a document. - Assert.AreEqual(1, collection.AddOrReplaceOne(5, new { _id = 5, title = "Book 5", pages = 60 }).AffectedItemsCount); - Assert.True(collection.GetOne(5) != null); - - Assert.AreEqual(1, collection.AddOrReplaceOne("6", new { title = "Book 6", pages = 70 }).AffectedItemsCount); - Assert.True(collection.GetOne(6) != null); - Assert.True(collection.GetOne("6") != null); - - // Replace a document. - Assert.AreEqual(2, collection.AddOrReplaceOne(1, new { _id = 1, title = "Book X", pages = 10 }).AffectedItemsCount); - DbDoc document = collection.GetOne(1); - Assert.AreEqual(1, Convert.ToInt32(document.Id)); - Assert.AreEqual("Book X", document["title"]); - Assert.AreEqual(10, Convert.ToInt32(document["pages"])); - - Assert.AreEqual(2, collection.AddOrReplaceOne(1, new { title = "Book Y", pages = 9, other = "value" }).AffectedItemsCount); - document = collection.GetOne(1); - Assert.AreEqual(1, Convert.ToInt32(document.Id)); - Assert.AreEqual("Book Y", document["title"]); - Assert.AreEqual(9, Convert.ToInt32(document["pages"])); - Assert.AreEqual("value", document["other"]); - - // Expected exceptions. - Assert.Throws(() => collection.AddOrReplaceOne(null, docs[1])); - Assert.Throws(() => collection.AddOrReplaceOne("", docs[1])); - Assert.Throws(() => collection.AddOrReplaceOne(" ", docs[1])); - Assert.Throws(() => collection.AddOrReplaceOne(string.Empty, docs[1])); - Assert.Throws(() => collection.AddOrReplaceOne("1", null)); - Assert.Throws(() => collection.AddOrReplaceOne(4, new DbDoc("{ \"_id\": 2, \"title\": \"Book\", \"pages\": 60 }")), - ResourcesX.ReplaceWithNoMatchingId); - } - - #region WL14389 - - [Test, Description("Test MySQLX plugin Collection Scenarios - with Create a valid collection and reuse existing object")] - public void CreateCollectionAndReuseObject() - { - using (Session sessionPlain = MySQLX.GetSession(ConnectionString)) - { - var col = CreateCollection("my_collection_123456789"); - object[] data = new object[] - { - new { _id = 1, title = "Book 1", pages = 20 }, - new { _id = 2, title = "Book 2", pages = 30 }, - new { _id = 3, title = "Book 3", pages = 40 }, - new { _id = 4, title = "Book 4", pages = 50 }, - }; - Result result = col.Add(data).Execute(); - var data1 = col.Remove("_id = 1").Execute(); - Assert.AreEqual(1, (int)data1.AffectedItemsCount, "Matching the deleted record count"); - data1 = col.Remove("_id = 2").Execute(); - Assert.AreEqual(1, (int)data1.AffectedItemsCount, "Matching the deleted record count"); - data1 = col.Remove("_id = 3").Execute(); - Assert.AreEqual(1, (int)data1.AffectedItemsCount, "Matching the deleted record count"); - data1 = col.Remove("_id = 4").Execute(); - Assert.AreEqual(1, (int)data1.AffectedItemsCount, "Matching the deleted record count"); - sessionPlain.Close(); - } - } - - [Test, Description("Collection Scenarios - with Create a collection with emptyname")] - public void CreateCollectionEmptyName() - { - Schema db = session.GetSchema(schemaName); - Assert.Throws(() => db.CreateCollection(null)); - } - - [Test, Description("Test MySQLX plugin Collection Scenarios - with Create a collection which exists without reuse existing object")] - public void CreateCollectionWithoutReuseExistingObject() - { - Schema db = session.GetSchema(schemaName); - var col = CreateCollection("my_collection_123456789"); - col = db.GetCollection("my_collection_123456789", true); - Assert.IsNotNull(col); - Assert.Throws(() => db.CreateCollection("my_collection_123456789", false)); - } - - [Test, Description("Test MySQLX plugin Collection Scenarios - Add Objects,Find with condition")] - public void CollectionAddObjectsFindCondition() - { - Schema db = session.GetSchema(schemaName); - Collection col = CreateCollection("my_collection_1"); - var docs = new[] - { - new { _id = 1, title = "Book 1", pages = 20 }, - new { _id = 2, title = "Book 2", pages = 30 }, - new { _id = 3, title = "Book 3", pages = 40 }, - new { _id = 4, title = "Book 4", pages = 50 }, - }; - Result result = col.Add(docs).Execute(); - - Assert.AreEqual(4, (int)result.AffectedItemsCount, "Matching the updated record count"); - var foundDocs = col.Find("pages > 20").Execute(); - Assert.AreEqual(true, foundDocs.Next(), "Next Node Exist"); - Assert.AreEqual("Book 2", foundDocs.Current["title"], "Matching the Node Value"); - Assert.AreEqual(true, foundDocs.Next(), "Next Node Exist"); - Assert.AreEqual("Book 3", foundDocs.Current["title"], "Matching the Node Value"); - Assert.AreEqual(true, foundDocs.Next(), "Next Node Exist"); - Assert.AreEqual("Book 4", foundDocs.Current["title"], "Matching the Node Value"); - Assert.AreEqual(false, foundDocs.Next(), "Next Node doesnot Exist"); - db.DropCollection("my_collection_1"); - } - - [Test, Description("Test MySQLX plugin Collection Scenarios - Add Objects,Find without parameters")] - public void CollectionAddFindNoParams() - { - if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher."); - Collection col = CreateCollection("my_collection_1"); - var docs = new[] - { - new { _id = 1, title = "Book 1", pages = 20 }, - new { _id = 2, title = "Book 2", pages = 30 }, - new { _id = 3, title = "Book 3", pages = 40 }, - new { _id = 4, title = "Book 4", pages = 50 }, - }; - - var result = col.Add(docs).Execute(); - Assert.AreEqual(4, (int)result.AffectedItemsCount, "Matching the updated record count"); - var foundDocs = col.Find().Execute(); - Assert.AreEqual(true, foundDocs.Next(), "Next Node Exist"); - Assert.AreEqual("Book 1", foundDocs.Current["title"], "Matching the Node Value"); - Assert.AreEqual(true, foundDocs.Next(), "Next Node Exist"); - Assert.AreEqual("Book 2", foundDocs.Current["title"], "Matching the Node Value"); - Assert.AreEqual(true, foundDocs.Next(), "Next Node Exist"); - Assert.AreEqual("Book 3", foundDocs.Current["title"], "Matching the Node Value"); - Assert.AreEqual(true, foundDocs.Next(), "Next Node Exist"); - Assert.AreEqual("Book 4", foundDocs.Current["title"], "Matching the Node Value"); - Assert.AreEqual(false, foundDocs.Next(), "Next Node doesnot Exist"); - } - - [Test, Description("Test MySQLX plugin Collection Scenarios - Add/Remove JSON Object with id")] - public void CollectionAddRemoveJSONObjectID() - { - if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher."); - using (var sessionPlain = MySQLX.GetSession(ConnectionString + ";sslmode=" + MySqlSslMode.Required)) - { - Schema db = sessionPlain.GetSchema(schemaName); - Collection col = CreateCollection("my_collection_1"); - DbDoc DbDocs = new DbDoc(); - DbDocs.SetValue("_id", "0"); - DbDocs.SetValue("title", "Book 0"); - DbDocs.SetValue("pages", "10"); - var result = col.Add(DbDocs).Execute(); - Assert.AreEqual(1, (int)result.AffectedItemsCount, "Matching the updated record count"); - DbDoc jsonremovedoc = new DbDoc(); - jsonremovedoc.SetValue("_id", "0"); - var foundDocs = col.Remove("_id='0'").Execute(); - Assert.AreEqual(1, (int)foundDocs.AffectedItemsCount, "Matching the deleted record count"); - db.DropCollection("my_collection_1"); - sessionPlain.Close(); - } - } - - [Test, Description("Test MySQLX plugin Collection Scenarios - Add/Remove with condition")] - public void CollectionAddRemoveJSONObjectCondition() - { - if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher."); - Schema db = session.GetSchema(schemaName); - Collection col = CreateCollection("my_collection_1"); - DbDoc DbDocs = new DbDoc(); - DbDocs.SetValue("_id", "0"); - DbDocs.SetValue("title", "Book 0"); - DbDocs.SetValue("pages", "10"); - var result = col.Add(DbDocs).Execute(); - Assert.AreEqual(1, (int)result.AffectedItemsCount, "Matching the updated record count"); - var foundDocs = col.Remove("pages > 0").Execute(); - Assert.AreEqual(1, (int)foundDocs.AffectedItemsCount, "Matching the deleted record count"); - db.DropCollection("my_collection_1"); - } - - [Test, Description("Test MySQLX plugin Collection Scenarios - Add,Remove with condition limit")] - public void CollectionAddRemoveObjectConditionLimit() - { - if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher."); - Schema db = session.GetSchema(schemaName); - Collection col = CreateCollection("my_collection_1"); - var docs = new[] - { - new { _id = 0, title = "Book 0", pages = 10 }, - new { _id = 1, title = "Book 1", pages = 20 }, - new { _id = 2, title = "Book 2", pages = 30 }, - new { _id = 3, title = "Book 3", pages = 40 }, - new { _id = 4, title = "Book 4", pages = 50 }, - }; - var result = col.Add(docs).Execute(); - Assert.AreEqual(5, (int)result.AffectedItemsCount, "Matching the updated record count"); - var foundDocs = col.Remove("_id=1").Execute(); - Assert.AreEqual(1, (int)foundDocs.AffectedItemsCount, "Matching the deleted record count"); - docs = new[] - { - new { _id = 1, title = "Book 1", pages = 20 }, - }; - result = col.Add(docs).Execute(); - Assert.AreEqual(1, (int)result.AffectedItemsCount, "Matching the updated record count"); - result = col.Remove("pages > 10").Limit(1).Execute(); - Assert.AreEqual(1, (int)result.AffectedItemsCount, "Matching the updated record count"); - result = col.Remove("pages > 10").Limit(3).Execute(); - Assert.AreEqual(3, (int)result.AffectedItemsCount, "Matching the updated record count"); - Assert.Throws(() => col.Remove("pages > 10").Limit(0).Execute()); - db.DropCollection("my_collection_1"); - } - - [Test, Description("Test MySQLX plugin Collection Scenarios - Add/Remove 200 JSON records ")] - public void CollectionAddRemove200JSONRecords() - { - if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher."); - Collection col = CreateCollection("my_collection_1"); - var numOfRecords = 200; - - DbDoc[] jsonlist = new DbDoc[numOfRecords]; - for (int i = 0; i < numOfRecords; i++) - { - DbDoc newDoc2 = new DbDoc(); - newDoc2.SetValue("_id", (i + 1000).ToString()); - newDoc2.SetValue("F1", ("Field-1-Data-" + i)); - newDoc2.SetValue("F2", ("Field-2-Data-" + i)); - newDoc2.SetValue("F3", (300 + i).ToString()); - jsonlist[i] = newDoc2; - newDoc2 = null; - } - var res = col.Add(jsonlist).Execute(); - - Assert.AreEqual(jsonlist[0].ToString(), jsonlist[0].ToString(), "String Match being done"); - for (int i = 0; i < numOfRecords; i++) - { - var data1 = col.Remove($"_id = '{i + 1000}'").Execute(); - Assert.AreEqual(1, (int)data1.AffectedItemsCount, "Matching the deleted record count"); - } - } - - [Test, Description("Test MySQLX plugin Collection Scenarios - Add/Remove documents with limit and orderby ")] - public void CollectionAddRemoveJSONRecordsLimitOrderBy() - { - if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher."); - Schema db = session.GetSchema(schemaName); - Collection col = CreateCollection("my_collection_1"); - - DbDoc[] jsonlist = new DbDoc[10]; - for (int i = 0; i < 10; i++) - { - DbDoc newDoc2 = new DbDoc(); - newDoc2.SetValue("_id", (i).ToString()); - newDoc2.SetValue("F1", ("Field-1-Data-" + i)); - newDoc2.SetValue("F2", ("Field-2-Data-" + i)); - newDoc2.SetValue("F3", (300 + i)); - jsonlist[i] = newDoc2; - newDoc2 = null; - } - col.Add(jsonlist).Execute(); - Assert.AreEqual(jsonlist[0].ToString(), jsonlist[0].ToString(), "String Match being done"); - - Result result = col.Remove("F3 > 305").Limit(1).Execute(); - Assert.AreEqual(1, (int)result.AffectedItemsCount, "Match being done"); - - result = col.Remove("F3 > 303").Sort("F3 DESC").Execute(); - Assert.AreEqual(5, (int)result.AffectedItemsCount, "Match being done"); - - result = col.Remove("F3 > 303").Sort("F3 DESC").Execute(); - Assert.AreEqual(0, (int)result.AffectedItemsCount, "Match being done"); - - result = col.Remove("F3 = 303").Sort("F2 DESC").Execute(); - Assert.AreEqual(1, (int)result.AffectedItemsCount, "Match being done"); - - result = col.Remove("F3 < 301").Sort("F2 DESC").Execute(); - Assert.AreEqual(1, (int)result.AffectedItemsCount, "Match being done"); - - result = col.Remove("F3 < 301").Sort("F2 DESC").Execute(); - Assert.AreEqual(0, (int)result.AffectedItemsCount, "Match being done"); - - db.DropCollection("my_collection_1"); - - } - - [Test, Description("Test MySQLX plugin Collection Scenarios - Add Single/Multiple Docs - Remove Condition/ID/Condition-Limit/Condition-Limit-OrderBy/Bind")] - public void CollectionAddRemoveDocsLimitOrderByBind() - { - if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher."); - Collection col = CreateCollection("my_collection_1"); - DbDoc DbDocs = new DbDoc(); - DbDocs.SetValue("_id", 100000); - DbDocs.SetValue("title", "Book 0"); - DbDocs.SetValue("pages", 10); - var result = col.Add(DbDocs).Execute(); - Assert.AreEqual(1, (int)result.AffectedItemsCount, "Matching the updated record count"); - var foundDocs = col.Remove("pages > 0").Execute(); - Assert.AreEqual(1, (int)foundDocs.AffectedItemsCount, "Matching the deleted record count"); - - var docs = new { _id = 100001, title = "Book 1", pages = 20 }; - result = col.Add(docs).Execute(); - Assert.AreEqual(1, (int)result.AffectedItemsCount, "Matching the updated record count"); - - foundDocs = col.Remove("pages=20").Execute(); - Assert.AreEqual(1, (int)foundDocs.AffectedItemsCount, "Matching the deleted record count"); - - docs = new { _id = -100001, title = "Book 1", pages = 20 }; - result = col.Add(docs).Execute(); - Assert.AreEqual(1, (int)result.AffectedItemsCount, "Matching the updated record count"); - - foundDocs = col.Remove("pages=20").Execute(); - Assert.AreEqual(1, (int)foundDocs.AffectedItemsCount, "Matching the deleted record count"); - var docs1 = new[] - { - new { _id = -100001, title = "Book 0", pages = 10 }, - new { _id = 0, title = "Book 1", pages = 20 }, - new { _id = 100001, title = "Book 2", pages = 30 }, - new { _id = 10000001, title = "Book 3", pages = 40 } - }; - result = col.Add(docs1).Execute(); - Assert.AreEqual(4, (int)result.AffectedItemsCount, "Matching the updated record count"); - - foundDocs = col.Remove("pages > 10").Execute(); - Assert.AreEqual(3, (int)foundDocs.AffectedItemsCount, "Matching the deleted record count"); - - foundDocs = col.Remove("pages=10").Execute(); - Assert.AreEqual(1, (int)foundDocs.AffectedItemsCount, "Matching the deleted record count"); - docs1 = new[] - { - new { _id = -100001, title = "Book 0", pages = 10 }, - new { _id = 0, title = "Book 1", pages = 20 }, - new { _id = 100001, title = "Book 2", pages = 30 }, - new { _id = 10000001, title = "Book 3", pages = 40 }, - new { _id = 10000009, title = "Book 4", pages = 50 } - }; - result = col.Add(docs1).Execute(); - Assert.AreEqual(5, (int)result.AffectedItemsCount, "Matching the updated record count"); - - foundDocs = col.Remove("pages = 40").Execute(); - Assert.AreEqual(1, (int)foundDocs.AffectedItemsCount, "Matching the deleted record count"); - - foundDocs = col.Remove("pages >= 10").Execute(); - Assert.AreEqual(4, (int)foundDocs.AffectedItemsCount, "Matching the deleted record count"); - - result = col.Add(docs1).Execute(); - Assert.AreEqual(5, (int)result.AffectedItemsCount, "Matching the updated record count"); - foundDocs = col.Remove("pages = 40").Limit(1).Execute(); - Assert.AreEqual(1, (int)foundDocs.AffectedItemsCount, "Matching the deleted record count"); - foundDocs = col.Remove("pages <= 50").Execute(); - Assert.AreEqual(4, (int)foundDocs.AffectedItemsCount, "Matching the deleted record count"); - - result = col.Add(docs1).Execute(); - Assert.AreEqual(5, (int)result.AffectedItemsCount, "Matching the updated record count"); - foundDocs = col.Remove("pages = 40").Limit(1).Sort("title").Execute(); - Assert.AreEqual(1, (int)foundDocs.AffectedItemsCount, "Matching the deleted record count"); - foundDocs = col.Remove("pages <= 50").Execute(); - Assert.AreEqual(4, (int)foundDocs.AffectedItemsCount, "Matching the deleted record count"); - - docs1 = new[] - { - new { _id = 1, title = "Book 1", pages = 20 }, - new { _id = 2, title = "Book 2", pages = 30 }, - new { _id = 3, title = "Book 3", pages = 40 }, - new { _id = 4, title = "Book 4", pages = 50 }, - }; - - result = col.Add(docs1).Execute(); - Assert.AreEqual(4, (int)result.AffectedItemsCount, "Matching the updated record count"); - foundDocs = col.Remove("pages = :Pages").Bind("pAges", 50).Execute(); - Assert.AreEqual(1, (int)foundDocs.AffectedItemsCount, "Matching the deleted record count"); - } - - [Test, Description("Test MySQLX plugin Collection Scenarios - Add Single/Multiple Docs - Remove Condition/ID/Condition-Limit/Condition-Limit-OrderBy/Bind using invalid conditions")] - public void CollectionRemoveDocsLimitOrderByBindNegative() - { - if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher."); - Schema db = session.GetSchema(schemaName); - var col = db.CreateCollection("my_collection_1", true); - - DbDoc DbDocs = new DbDoc(); - DbDocs.SetValue("_id", 100000); - DbDocs.SetValue("title", "Book 0"); - DbDocs.SetValue("pages", 10); - var result = col.Add(DbDocs).Execute(); - - Assert.AreEqual(1, (int)result.AffectedItemsCount, "Matching the updated record count"); - var foundDocs = col.Remove("pages > 10").Execute(); - Assert.AreEqual(0, (int)foundDocs.AffectedItemsCount, "Matching the deleted record count"); - - var docs = new { _id = 100001, title = "Book 1", pages = 20 }; - result = col.Add(docs).Execute(); - Assert.AreEqual(1, (int)result.AffectedItemsCount, "Matching the updated record count"); - - foundDocs = col.Remove("pages >= 10").Execute(); - Assert.AreEqual(2, (int)foundDocs.AffectedItemsCount, "Matching the deleted record count"); - - docs = new { _id = -100001, title = "Book 1", pages = 20 }; - result = col.Add(docs).Execute(); - Assert.AreEqual(1, (int)result.AffectedItemsCount, "Matching the updated record count"); - - foundDocs = col.Remove("pages > 10").Execute(); - Assert.AreEqual(1, (int)foundDocs.AffectedItemsCount, "Matching the deleted record count"); - - - var docs1 = new[] - { - new { _id = -100001, title = "Book 0", pages = 10 }, - new { _id = 0, title = "Book 1", pages = 20 }, - new { _id = 100001, title = "Book 2", pages = 30 }, - new { _id = 10000001, title = "Book 3", pages = 40 } - }; - result = col.Add(docs1).Execute(); - Assert.AreEqual(4, (int)result.AffectedItemsCount, "Matching the updated record count"); - - foundDocs = col.Remove("pages > 50").Execute(); - Assert.AreEqual(0, (int)foundDocs.AffectedItemsCount, "Matching the deleted record count"); - - foundDocs = col.Remove("pages < 50").Execute(); - Assert.AreEqual(4, (int)foundDocs.AffectedItemsCount, "Matching the deleted record count"); - - docs1 = new[] - { - new { _id = -100001, title = "Book 0", pages = 10 }, - new { _id = 0, title = "Book 1", pages = 20 }, - new { _id = 100001, title = "Book 2", pages = 30 }, - new { _id = 10000001, title = "Book 3", pages = 40 }, - new { _id = 10000009, title = "Book 4", pages = 50 } - }; - result = col.Add(docs1).Execute(); - Assert.AreEqual(5, (int)result.AffectedItemsCount, "Matching the updated record count"); - - foundDocs = col.Remove("pages = 0").Execute(); - Assert.AreEqual(0, (int)foundDocs.AffectedItemsCount, "Matching the deleted record count"); - - foundDocs = col.Remove("pages <= 50").Execute(); - Assert.AreEqual(5, (int)foundDocs.AffectedItemsCount, "Matching the deleted record count"); - - result = col.Add(docs1).Execute(); - Assert.AreEqual(5, (int)result.AffectedItemsCount, "Matching the updated record count"); - foundDocs = col.Remove("pages = 60").Limit(1).Execute(); - Assert.AreEqual(0, (int)foundDocs.AffectedItemsCount, "Matching the deleted record count"); - - foundDocs = col.Remove("pages <= 50").Execute(); - Assert.AreEqual(5, (int)foundDocs.AffectedItemsCount, "Matching the deleted record count"); - - result = col.Add(docs1).Execute(); - Assert.AreEqual(5, (int)result.AffectedItemsCount, "Matching the updated record count"); - foundDocs = col.Remove("pages = 04").Limit(1).Sort("title").Execute(); - Assert.AreEqual(0, (int)foundDocs.AffectedItemsCount, "Matching the deleted record count"); - foundDocs = col.Remove("pages <= 50").Execute(); - Assert.AreEqual(5, (int)foundDocs.AffectedItemsCount, "Matching the deleted record count"); - - docs1 = new[] - { - new { _id = 1, title = "Book 1", pages = 20 }, - new { _id = 2, title = "Book 2", pages = 30 }, - new { _id = 3, title = "Book 3", pages = 40 }, - new { _id = 4, title = "Book 4", pages = 50 }, - }; - - result = col.Add(docs1).Execute(); - Assert.AreEqual(4, (int)result.AffectedItemsCount, "Matching the updated record count"); - foundDocs = col.Remove("pages1 = :Pages").Bind("pAges", 50).Execute(); - Assert.AreEqual(0, (int)foundDocs.AffectedItemsCount, "Matching the deleted record count"); - foundDocs = col.Remove("pages = :Pages").Bind("pAges", 51).Execute(); - Assert.AreEqual(0, (int)foundDocs.AffectedItemsCount, "Matching the deleted record count"); - foundDocs = col.Remove("pages = :Pages").Bind("pAges", 50).Execute(); - Assert.AreEqual(1, (int)foundDocs.AffectedItemsCount, "Matching the deleted record count"); - db.DropCollection("my_collection_1"); - - } - - [Test, Description("Test MySQLX plugin - MYSQLCNET_680 Allow Reuse Statement after execute Positive1(after a succesful execute)")] - public void AllowReuseStatementAfterExecutePositive1() - { - if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher."); - Schema db = session.GetSchema(schemaName); - var col = db.CreateCollection("my_collection_123456789"); - object[] data = new object[] - { - new { _id = 1, title = "Book 1", pages = 10 }, - new { _id = 2, title = "Book 2", pages = 20 }, - new { _id = 3, title = "Book 3", pages = 30 }, - new { _id = 4, title = "Book 4", pages = 40 }, - new { _id = 5, title = "Book 5", pages = 50 }, - new { _id = 6, title = "Book 6", pages = 60 }, - new { _id = 7, title = "Book 7", pages = 70 }, - new { _id = 8, title = "Book 8", pages = 80 }, - }; - Result result = col.Add(data).Execute(); - Assert.AreEqual(8, (int)result.AffectedItemsCount, "Matching the added record count"); - var data1 = col.Remove("_id=1").Execute(); - Assert.AreEqual(1, (int)data1.AffectedItemsCount, "Matching the deleted record count"); - data1 = col.Remove("pages = :Pages").Bind("pAges", 80).Execute(); - Assert.AreEqual(1, (int)data1.AffectedItemsCount, "Matching the deleted record count"); - data1 = col.Remove("pages = :Pages").Bind("pAges", 70).Execute(); - Assert.AreEqual(1, (int)data1.AffectedItemsCount, "Matching the deleted record count"); - var remData = col.Remove("_id = :param1 AND title = :param2"); - data1 = remData.Bind("param1", 5).Bind("param2", "Book 5").Execute(); - Assert.AreEqual(1, (int)data1.AffectedItemsCount, "Matching the deleted record count"); - data1 = remData.Bind("param1", 6).Bind("param2", "Book 6").Execute(); - Assert.AreEqual(1, (int)data1.AffectedItemsCount, "Matching the deleted record count"); - db.DropCollection("my_collection_123456789"); - } - - [Test, Description("Test MySQLX plugin - MYSQLCNET_680 Allow Reuse Statement after execute-Positive2(after an unsuccessful execute)")] - public void AllowReuseStatementAfterExecutePositive2() - { - var col = CreateCollection("my_collection_123456789"); - object[] data = new object[] - { - new { _id = 1, title = "Book 1", pages = 10 }, - new { _id = 2, title = "Book 2", pages = 20 }, - new { _id = 3, title = "Book 3", pages = 30 }, - new { _id = 4, title = "Book 4", pages = 40 }, - new { _id = 5, title = "Book 5", pages = 50 }, - new { _id = 6, title = "Book 6", pages = 60 }, - new { _id = 7, title = "Book 7", pages = 70 }, - new { _id = 8, title = "Book 8", pages = 80 }, - }; - Result result = col.Add(data).Execute(); - Assert.AreEqual(8, (int)result.AffectedItemsCount, "Matching the added record count"); - var data1 = col.Remove("_id=1").Execute(); - Assert.AreEqual(1, (int)data1.AffectedItemsCount, "Matching the deleted record count"); - data1 = col.Remove("pages = :Pages").Bind("pAges", 80).Execute(); - Assert.AreEqual(1, (int)data1.AffectedItemsCount, "Matching the deleted record count"); - data1 = col.Remove("pages = :Pages").Bind("pAges", 70).Execute(); - Assert.AreEqual(1, (int)data1.AffectedItemsCount, "Matching the deleted record count"); - var remData = col.Remove("_id = :param1 AND title = :param2"); - - data1 = remData.Bind("param1", 35).Bind("param2", "Book 33").Execute(); - Assert.AreEqual(0, (int)data1.AffectedItemsCount, "Matching the deleted record count"); - - data1 = remData.Bind("param1", 6).Bind("param2", "Book 6").Execute(); - Assert.AreEqual(1, (int)data1.AffectedItemsCount, "Matching the deleted record count"); - testSchema.DropCollection("my_collection_123456789"); - } - - [Test, Description("Test MySQLX plugin - MYSQLCNET 755 Collection GetDocumentID")] - public void CollectionGetDocumentID() - { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher."); - Collection coll = CreateCollection("test"); - var docs = new[] - { - new { _id = 100, title = "Book 100", pages = 1000 }, - }; - Result result = coll.Add(docs).Execute(); - var documentIds = result.GeneratedIds; - Assert.False(documentIds != null && documentIds.Count > 0); - - coll = CreateCollection("test"); - var docs1 = new[] - { - new { title = "Book 1", pages = 100 }, - }; - var r = coll.Add(docs1); - var result1 = r.Execute(); - var documentIds1 = result.GeneratedIds; - HashSet firstset = new HashSet(); - for (int i = 0; i < documentIds.Count; i++) - { - if (documentIds1 != null) - { - Assert.AreEqual(documentIds1[i].ToString(), documentIds1[i].ToString(), "Matching the document ID with unique id"); - } - if (!firstset.Add(documentIds1[i])) - { - break; - } - } - - coll = CreateCollection("test"); - docs = new[] - { - new { _id = 100, title = "Book 100", pages = 1000 }, - new { _id = 200, title = "Book 200", pages = 2000 }, - new { _id = 300, title = "Book 300", pages = 3000 }, - new { _id = 400, title = "Book 400", pages = 4000 }, - }; - - var r1 = coll.Add(docs).Execute(); - documentIds = r1.GeneratedIds; - Assert.False(documentIds != null && documentIds.Count > 0); - - coll = CreateCollection("test"); - docs1 = new[] - { - new { title = "Book 1", pages = 100 }, - new { title = "Book 2", pages = 200 }, - new { title = "Book 3", pages = 300 }, - new { title = "Book 4", pages = 400 }, - }; - - var stmt = coll.Add(docs1); - result1 = stmt.Execute(); - documentIds1 = result1.GeneratedIds; - firstset = new HashSet(); - for (int i = 0; i < documentIds1.Count; i++) - { - if (documentIds != null) - { - Assert.AreEqual(documentIds1[i].ToString(), documentIds1[i].ToString(), "Matching the document ID with unique id"); - } - - if (!firstset.Add(documentIds1[i])) - { - break; - } - } - } - - [Test, Description("Test MySQLX UUID Scenario-1(Check UUID is not generated when JSON doc is added using collection.add() with _id fields)")] - public void CheckDocUUIDScenario1() - { - var col = CreateCollection("my_collection_123456789"); - object[] data = new object[] - { - new { _id = 1, title = "Book 1", pages = 20 }, - new { _id = 2, title = "Book 2", pages = 30 }, - new { _id = 3, title = "Book 3", pages = 40 }, - new { _id = 4, title = "Book 4", pages = 50 }, - }; - Result result = col.Add(data).Execute(); - var documentIds = result.GeneratedIds; - Assert.False(documentIds != null && documentIds.Count > 0); - } - - [Test, Description("Test MySQLX UUID Scenario-2(Check UUID generated when multiple JSON docs are added using collection.add().add()..without _id fields)")] - public void CheckDocUUIDScenario2() - { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher."); - var col = CreateCollection("my_collection_123456789"); - object[] data1 = new object[] - { - new { title ="Book 1", pages = 20 }, - new { title = "Book 2", pages = 30 }, - new { title = "Book 3", pages = 40 }, - new { title = "Book 4", pages = 50 } - }; - - object[] data2 = new object[] - { - new { title = "Book 5", pages = 60 }, - new {title = "Book 6", pages = 70 }, - new { title = "Book 7", pages = 80 }, - new { title = "Book 8", pages = 90 }, - }; - var stmt = col.Add(data1).Add(data2); - var result = stmt.Execute(); - var documentIds = result.GeneratedIds; - HashSet firstset = new HashSet(); - for (int i = 0; i < documentIds.Count; i++) - { - if (documentIds != null) - { - Assert.AreEqual(documentIds[i].ToString(), documentIds[i].ToString(), "Matching the document ID with unique id"); - } - if (!firstset.Add(documentIds[i])) - { - Console.WriteLine("Contains duplicate ID"); - break; - } - } - } - - [Test, Description("Test MySQLX UUID Scenario-2(Check UUID generated when multiple JSON docs are added using collection.add(doc, doc, doc... ) without _id fields)")] - public void CheckDocUUIDScenario3() - { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher."); - var col = CreateCollection("my_collection_123456789"); - var stmt = col.Add(@"{ ""foo"": 1 }", @"{""foo"": 2 }", @"{ ""foo"": 3 }", @"{ ""foo"": 4 }"); - Result r = col.Add(@"{ ""foo"": 1 }", @"{""foo"": 2 }", @"{ ""foo"": 3 }", @"{ ""foo"": 4 }").Execute(); - long count = col.Count(); - Assert.AreEqual(count, 4, "Matching the Collection Count"); - var documentIds = r.GeneratedIds; - if (documentIds != null) - { - Assert.AreEqual(documentIds[0].ToString(), documentIds[0].ToString(), "Matching the document ID without unique id"); - Assert.AreEqual(documentIds[1].ToString(), documentIds[1].ToString(), "Matching the document ID without unique id"); - Assert.AreEqual(documentIds[2].ToString(), documentIds[2].ToString(), "Matching the document ID without unique id"); - Assert.AreEqual(documentIds[3].ToString(), documentIds[3].ToString(), "Matching the document ID without unique id"); - } - - var collectionName = col.Name; - Assert.AreEqual(collectionName, "my_collection_123456789", "Matching the collection Name"); - Assert.AreEqual(schemaName, col.Schema.Name, "Matching the Schema Name"); - } - - [Test, Description("Test MySQLX UUID Scenario-4(Check UUID generated when multiple JSON docs are added using some containing and some not containing _id fields)")] - public void CheckDocUUIDScenario4() - { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher."); - var col = CreateCollection("my_collection_123456789"); - object[] data1 = new object[] - { - new { _id = 1, title = "Book 1", pages = 20 }, - new { _id = 2, title = "Book 2", pages = 30 }, - new { _id = 3, title = "Book 3", pages = 40 }, - new { title = "Book 4", pages = 50 } - }; - - object[] data2 = new object[] - { - new { title = "Book 5", pages = 60 }, - new { _id = 6,title = "Book 6", pages = 70 }, - new { title = "Book 7", pages = 80 }, - new { title = "Book 8", pages = 90 }, - }; - - var stmt = col.Add(data1).Add(data2); - Result result = stmt.Execute(); - var documentIdsCount = result.GeneratedIds.Count; - var documentIds = result.GeneratedIds; - Assert.AreEqual(4, documentIdsCount, "Matching the document ID count"); - if (documentIds != null) - { - Assert.AreEqual(documentIds[0].ToString(), documentIds[0].ToString(), "Matching the document ID with unique id"); - Assert.AreEqual(documentIds[1].ToString(), documentIds[1].ToString(), "Matching the document ID with unique id"); - Assert.AreEqual(documentIds[2].ToString(), documentIds[2].ToString(), "Matching the document ID with unique id"); - Assert.AreEqual(documentIds[3].ToString(), documentIds[3].ToString(), "Matching the document ID without unique id"); - } - } - - [Test, Description("Test MySQLX UUID Scenario-5(Check that UUID is not generated by adding multiple doc from the same collection in a session with _id fields)")] - public void CheckDocUUIDScenario5() - { - Collection testCollection = CreateCollection("test"); - DbDoc[] jsonlist = new DbDoc[1000]; - for (int i = 0; i < 1000; i++) - { - DbDoc newDoc2 = new DbDoc(); - newDoc2.SetValue("_id", (i + 1000)); - newDoc2.SetValue("F1", ("Field-1-Data-" + i)); - newDoc2.SetValue("F2", ("Field-2-Data-" + i)); - newDoc2.SetValue("F3", (300 + i).ToString()); - jsonlist[i] = newDoc2; - newDoc2 = null; - } - Result r = testCollection.Add(jsonlist).Execute(); - Assert.AreEqual(1000, r.AffectedItemsCount, "Matching"); - var documentIds = r.GeneratedIds; - Assert.False(documentIds != null && documentIds.Count > 0); - - Schema testSchema = session.GetSchema(schemaName); - Table test = testSchema.GetCollectionAsTable("test"); - Assert.AreEqual(true, test.ExistsInDatabase(), "Matching"); - } - - [Test, Description("Test MySQLX UUID Scenario-6(Check that no duplicate UUID is generated by adding multiple doc from the same collection in a session when there are no _id fields)")] - public void CheckDocUUIDScenario6() - { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher."); - Collection testCollection = CreateCollection("test"); - DbDoc[] jsonlist = new DbDoc[1000]; - for (int i = 0; i < 1000; i++) - { - DbDoc newDoc2 = new DbDoc(); - newDoc2.SetValue("F1", ("Field-1-Data-" + i)); - newDoc2.SetValue("F2", ("Field-2-Data-" + i)); - newDoc2.SetValue("F3", (300 + i).ToString()); - jsonlist[i] = newDoc2; - newDoc2 = null; - } - - var r = testCollection.Add(jsonlist); - var result = r.Execute(); - var countgenerateIDs = result.GeneratedIds.Count; - Assert.AreEqual(1000, countgenerateIDs, "Count of the ID generated by the server"); - for (int i = 0; i < countgenerateIDs; i++) - { - var generatedIDs1 = result.GeneratedIds[i]; - Assert.AreEqual(generatedIDs1, generatedIDs1, "ID generated by the server"); - } - - Schema testSchema = session.GetSchema(schemaName); - Table test = testSchema.GetCollectionAsTable("test"); - Assert.AreEqual(true, test.ExistsInDatabase(), "Matching"); - } - - [Test, Description("Test MySQLX UUID Scenario-7(Check UUID generated when multiple JSON docs are added using collection.add(doc, doc, doc... ) when docs contains _id fields with negative numbers,big positive numbers)")] - public void CheckDocUUIDScenario7() - { - var col = CreateCollection("my_collection_123456789"); - object[] data1 = new object[] - { - new { _id = -1, title = "Book 1", pages = 20 }, - new { _id = 200000000, title = "Book 2", pages = 30 }, - new { _id = -300000000, title = "Book 3", pages = 40 }, - new { title = "Book 4", pages = 50 } - }; - - object[] data2 = new object[] - { - new { title = "Book 5", pages = 60 }, - new { _id = 60000000000000,title = "Book 6", pages = 70 }, - new { title = "Book 7", pages = 80 }, - new { title = "Book 8", pages = 90 }, - }; - - var r = col.Add(data1).Add(data2); - var result = r.Execute(); - var countgenerateIDs = result.GeneratedIds.Count; - Assert.AreEqual(4, countgenerateIDs, "Count of the ID generated by the server"); - for (int i = 0; i < countgenerateIDs; i++) - { - var generatedIDs1 = result.GeneratedIds[i]; - Assert.AreEqual(generatedIDs1, generatedIDs1, "ID generated by the server"); - } - - } - - [Test, Description("Test MySQLX UUID Scenario-8(Check UUID generated when multiple JSON docs are added using collection.add(doc, doc, doc... ) when docs contains _id fields with zero,strings)")] - public void CheckDocUUIDScenario8() - { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher."); - var col = CreateCollection("my_collection_123456789"); - object[] data1 = new object[] - { - new { _id = 0, title = "Book 1", pages = 20 }, - new { _id = "test1", title = "Book 2", pages = 30 }, - new { _id = "^%$^&&%)(*&", title = "Book 3", pages = 40 }, - new { title = "Book 4", pages = 50 } - }; - - object[] data2 = new object[] - { - new { title = "Book 5", pages = 60 }, - new { _id = 60000000000000,title = "Book 6", pages = 70 }, - new { title = "Book 7", pages = 80 }, - new { title = "Book 8", pages = 90 }, - }; - - var r = col.Add(data1).Add(data2); - var result = r.Execute(); - var countgenerateIDs = result.GeneratedIds.Count; - Assert.AreEqual(4, countgenerateIDs, "Count of the ID generated by the server"); - for (int i = 0; i < countgenerateIDs; i++) - { - var generatedIDs1 = result.GeneratedIds[i]; - Assert.AreEqual(generatedIDs1, generatedIDs1, "ID generated by the server"); - } - - } - - [Test, Description("Test MySQLX UUID Scenario-9(Check the behaviour when JSON docs are added using collection.add(doc) when docs contains _id fields with (blank)")] - public void CheckDocUUIDScenario9() - { - Collection testCollection = CreateCollection("test"); - DbDoc[] jsonlist = new DbDoc[1]; - for (int i = 0; i < 1; i++) - { - DbDoc newDoc2 = new DbDoc(); - newDoc2.SetValue("_id", " "); - newDoc2.SetValue("F1", ("Field-1-Data-" + i)); - newDoc2.SetValue("F2", ("Field-2-Data-" + i)); - newDoc2.SetValue("F3", (300 + i).ToString()); - jsonlist[i] = newDoc2; - } - - Result result = testCollection.Add(jsonlist).Execute(); - //ID with blank could be added as per bug#27627861 as client will not do any validation and server will do" - Assert.IsNotNull(result); - - Schema testSchema = session.GetSchema("test"); - Table test = testSchema.GetCollectionAsTable("test"); - Assert.AreEqual(true, test.ExistsInDatabase(), "Matching"); - } - - [Test, Description("Test MySQLX plugin Collection JSON Depth Scenarios")] - public void CollectionAddJSONDepth() - { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher."); - int i, maxArrayelement = 100; - Collection col = CreateCollection("my_collection_1"); - Collection col1 = CreateCollection("my_collection_2"); - - DbDoc d1 = new DbDoc(); - for (i = 0; i < maxArrayelement; i++) - { - d1.SetValue("_id" + "_" + i.ToString(), 10000); - d1.SetValue("person" + "_" + i.ToString(), "Person" + "_" + i.ToString()); - } - - var result = col1.Add(d1).Execute(); - Assert.Greater(result.AffectedItemsCount, 0); - - var data1 = new DbDoc(@"{ ""_id"": 1, ""pages"": 20, - ""person"": { ""name"": ""Fred"", ""age"": 45 } - }"); - var data2 = new DbDoc(@"{ ""_id"": 1, ""pages"": 20, - ""books"": [ - {""_id"" : 1, ""title"" : ""Book 1""}, - { ""_id"" : 2, ""title"" : ""Book 2"" } - ] - }"); - DbDoc d2 = new DbDoc(); - d2.SetValue("_id", 1); - d2.SetValue("pages", 20); - d2.SetValue("taker1", data1); - d2.SetValue("taker2", data2); - - result = col.Add(d2).Execute(); - Assert.Greater(result.AffectedItemsCount, 0); - - var result1 = col1.Find().Execute().FetchAll(); - Assert.AreEqual(1, result1.Count); - var result2 = col.Find().Execute().FetchAll(); - Assert.AreEqual(1, result2.Count); - } - - [Test, Description("Test MySQLX plugin Collection Add function with null")] - public void CollectionAddNullFind() - { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher."); - int i = 1; - Collection col = CreateCollection("my_collection_1"); - var d1 = new DbDoc(); - d1.SetValue("id" + "_" + i.ToString(), "test"); - Assert.AreEqual(1, col.Add(d1).Execute().AffectedItemsCount); - var result1 = col.Find(null).Execute(); - Assert.AreEqual(0, result1.AffectedItemsCount); - Assert.Throws(() => col.Add(null).Execute()); - var result2 = col.Add().Execute(); - Assert.AreEqual(0, result2.AffectedItemsCount); - } - - [Test, Description("Test MySQLX plugin Invalid JSON String")] - public void InvalidJSONString() - { - Collection col = CreateCollection("my_collection_1"); - String json = ""; - json = "{'_id':'1004','F1': [] }"; - Exception ex = Assert.Throws(() => col.Add(json).Execute()); - StringAssert.Contains("The value provided is not a valid JSON document", ex.Message); - } - - [Test, Description("Test MySQLX plugin JSON String long expression")] - public void JSONStringLongExpression() - { - if (Platform.IsMacOSX()) Assert.Ignore("Check failure on MacOS: stack overflow");// TO DO - - Collection col = CreateCollection("my_collection_1"); - String json = "", - query2 = ""; - json = "{\"_id\":\"1004\",\"F1\": 1234 }"; - col.Add(json).Execute(); - query2 = "-1+"; - for (int i = 0; i < 230; i++) - { - query2 = query2 + "("; - } - - query2 = query2 + "(100+2)"; - for (int i = 230; i > 0; i--) - { - query2 = query2 + ")"; - } - - var docs = col.Find().Fields(("{'X':" + query2 + "}")).Execute(); - var res = col.Modify("$.F1 = 1234").Set("F1", query2).Limit(1).Execute(); - Assert.AreEqual(1, res.AffectedItemsCount); - } - - [Test, Description("Test MySQLX plugin Binary Expression")] - public void BinaryExpression() - { - String json = ""; - Collection col = CreateCollection("my_collection_1"); - Collection col1 = CreateCollection("my_collection_2"); - json = "{\"_id\":\"1004\",\"F1\": 123,\"F2\":\"#\" }"; - col.Add(json).Execute(); - - var docs1 = col.Find().Fields("$._id as _id", "1 << 4 as tmp").Execute(); - var res = docs1.FetchAll(); - StringAssert.AreEqualIgnoringCase("1004", res[0].Id.ToString()); - - docs1 = col.Find().Fields("$._id as _id", "$.F2 ^ 1 as tmp").Execute(); - res = docs1.FetchAll(); - StringAssert.AreEqualIgnoringCase("1004", res[0].Id.ToString()); - col.Add("{\"_id\":\"100001\",\"x1\":\"31\", \"x2\":\"13\", \"x3\":\"8\", \"x4\":\"18446744073709551614\"}").Execute(); - docs1 = col.Find("CAST($.x1 as SIGNED) | pow(2,$.x1) = $.x1").Fields("$._id as _id, $.x1 as x1, $.x2 as x2, $.x3 as x3 , $.x2 | pow(2,$.x1) as tmp").Execute(); - res = docs1.FetchAll(); - Assert.IsNotNull(res); - docs1 = col.Find("~16 = ~CAST($.F2 as SIGNED)").Fields("$._id as _id,$.F2 as f2, ~1 as tmp").Execute(); - res = docs1.FetchAll(); - Assert.IsNotNull(res); - int maxrec = 100; - DbDoc newDoc = new DbDoc(); - newDoc.SetValue("_id", maxrec + 1000); - newDoc.SetValue("F1", "Field-1-Data-" + maxrec); - newDoc.SetValue("F2", "Field-2-Data-" + maxrec); - newDoc.SetValue("F3", 300 + maxrec); - col1.Add(newDoc).Execute(); - - json = "{'_id':'" + (maxrec + 1000 + 1) + "','F1':'Field-1-Data-" + (maxrec + 1) + "','F2':'Field-2-Data-" + (maxrec + 1) + "','F3':" + (300 + maxrec + 1) + "}"; - json = json.Replace("'", "\""); - var res1 = col1.Add(json).Execute(); - Assert.AreEqual(1, res1.AffectedItemsCount); - json = "{'F1': 'Field-1-Data-9999','F2': 'Field-2-Data-9999','F3': 'Field-3-Data-9999'}".Replace("'", "\""); - col1.Add(json).Add(json.Replace("9", "8")).Execute(); - Assert.AreEqual(1, res1.AffectedItemsCount); - - var docs = col1.Find("$._id = 1100").Fields("$_id as _id,$.F1 as f1, $.F2 as f2, $.F3 as f3").Execute(); - var res2 = docs.FetchOne(); - Assert.AreEqual("1100", res2["_id"].ToString()); - Assert.AreEqual("Field-1-Data-100", res2["f1"].ToString()); - Assert.AreEqual("Field-2-Data-100", res2["f2"].ToString()); - Assert.AreEqual("400", res2["f3"].ToString()); - - } - - [Test, Description("Test MySQLX plugin Invalid JSON String long expression")] - public void JSONStringSpecialCharacters() - { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher."); - Collection col = CreateCollection("my_collection_1"); - String[] splName = {"+", "*", "/", "a+b", "#1", "%", "&", "@1", "!1", "~", "^", - "(", ")", "{", "}", "[", "]", "|", "JSON", "ADD", "JSON_EXTRACT", "JSON_OBJECT", - "?", "=", "+", ";", ",", ":", "<", ">", "-"}; - for (int i = 0; i < splName.Length; i++) - { - col.Add("{\"" + splName[i] + "\":\"data" + i + "\",\"ID\":" + i + "}").Execute(); - var docs = col.Find("$.ID = " + i).Fields("$.`" + splName[i] + "` as col1,$.ID as Id").Execute(); - var res = docs.FetchOne(); - Assert.AreEqual(i.ToString(), res["Id"].ToString(), "Matching the ID"); - if (i == 30) - Assert.AreEqual("data" + i, "data30", "Matching the String"); - else - Assert.AreEqual("data" + i, res["col1"].ToString(), "Matching the String"); - } - } - - [Test, Description("Test MySQLX plugin Collections Chained Insert")] - public void CollectionsChainedInsert() - { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher."); - Collection col = CreateCollection("my_collection_1"); - DbDoc newDoc = new DbDoc(); - newDoc.SetValue("F1", 1); - - DbDoc newDoc1 = new DbDoc(); - newDoc1.SetValue("F1", 2); - - DbDoc newDoc2 = new DbDoc(); - newDoc2.SetValue("F1", 3); - - DbDoc[] jsonlist = new DbDoc[5]; - for (int i = 0; i < 5; i++) - { - DbDoc newDoc3 = new DbDoc(); - newDoc3.SetValue("F1", 4 + i); - jsonlist[i] = newDoc3; - newDoc3 = null; - } - - DbDoc[] jsonlist1 = new DbDoc[5]; - for (int i = 0; i < 5; i++) - { - DbDoc newDoc4 = new DbDoc(); - newDoc4.SetValue("F1", 10 + i); - jsonlist1[i] = newDoc4; - newDoc4 = null; - } - - DbDoc[] jsonlist2 = new DbDoc[5]; - for (int i = 0; i < 5; i++) - { - DbDoc newDoc5 = new DbDoc(); - newDoc5.SetValue("F1", 100 + i); - jsonlist2[i] = newDoc5; - newDoc5 = null; - } - - var tabRes = col.Add(newDoc).Add(newDoc1).Execute(); - Assert.AreEqual(2, tabRes.AffectedItemsCount, "Matching the affected records"); - - tabRes = col.Add(jsonlist).Add(newDoc2).Execute(); - Assert.AreEqual(6, tabRes.AffectedItemsCount, "Matching the affected records"); - - tabRes = col.Add(jsonlist1).Add(jsonlist2).Execute(); - Assert.AreEqual(10, tabRes.AffectedItemsCount, "Matching the affected records"); - } - - [Test, Description("Test MySQLX plugin Collection Add Array")] - public void CollectionAddArray() - { - if (!Platform.IsWindows()) Assert.Ignore("This test is for Windows OS only."); - if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5, 7, 0 or higher."); - int maxrec = 5; - var col = CreateCollection("my_collection_1"); - DbDoc[] jsonlist = new DbDoc[maxrec]; - for (int i = 0; i < maxrec; i++) - { - DbDoc newDoc2 = new DbDoc(); - newDoc2.SetValue("_id", i); - newDoc2.SetValue("F1", "Field-1-Data-" + i); - newDoc2.SetValue("ARR_INT", new DbDoc(@"{""values"":[1, 2, 3, 4, 5, 6, 7, 8, 9]}")); - newDoc2.SetValue("ARR_STR", new DbDoc(@"{""values"":""['DATA1', 'DATA2', 'DATA3', 'DATA4', 'DATA5', 'DATA6']""}")); - newDoc2.SetValue("ARR_LIT", new DbDoc(@"{""values"":""[null, true, false, null, true, false, null, true, false]""}")); - newDoc2.SetValue("ARR_ARR", new DbDoc(@"{""values"":[[1, 2, 3, 4, 5], [1, 2, 3, 4, 5], [1, 2, 3, 4, 5]]}")); - - col.Add(newDoc2).Execute(); - jsonlist[i] = newDoc2; - } - - jsonlist = null; - var res = col.Find().Execute().FetchAll(); - Assert.AreEqual(5, res.Count, "Matching the find count"); - } - - [Test, Description("Test MySQLX plugin Collection JSON Scenarios")] - public void CollectionAddJSONDocs() - { - if (!Platform.IsWindows()) Assert.Ignore("This test is for Windows OS only."); - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher."); - - Collection col = CreateCollection("my_collection_1"); - string json = @"{ ""_id"": 0, ""title"": ""Book 0"" ,""pages"": 10,""name"": ""Jeoff Archer""}"; - Result r = col.Add(json).Execute(); - - Assert.AreEqual(1, (int)r.AffectedItemsCount, "Matching Affected Records Count"); - var foundDocs = col.Find("pages > 5").Execute(); - Assert.AreEqual(1, foundDocs.Count(), "Matching Count"); - - json = @"{ ""_id"" : 99950, ""city"" : ""KETCHIKAN"", ""loc"" : ""[ -133.18479, 55.942471 ]"", ""pop"" : 422, ""state"" : ""AK"" }"; - r = col.Add(json).Execute(); - - DbDoc d = new DbDoc(@"{ ""id"": 1, ""pages"": 20, - ""person"": { ""name"": ""Fred"", ""age"": 45 } - }"); - DbDoc d2 = new DbDoc(); - d2.SetValue("id", 1); - d2.SetValue("pages", 20); - d2.SetValue("person", new { name = "Fred", age = 45 }); - - Assert.AreEqual(d.Equals(d2), true, "Matching"); - col.Add(d).Execute(); - - d = new DbDoc(@"{""id"":100,""FirstName"":""xyz"",""lastname"":""pqr"", - ""address"": - {""house"":44,""city"":""Delhi"",""country"":""india""}}"); - col.Add(d).Execute(); - - d = new DbDoc(@"{""customerId"":100,""FirstName"":""xyz"",""lastname"":""pqr"", - ""address"": - {""house"":44,""city"":""Delhi"",""country"":""india""}, - ""employer"": - {""cmpName"":""ABC"",""type"":""IT""}}"); - col.Add(d).Execute(); - - d = new DbDoc(@"{ ""id"": 1, ""pages"": 20, - ""books"": [ - {""_id"" : 1, ""title"" : ""Book 1""}, - { ""_id"" : 2, ""title"" : ""Book 2"" } - ] - }"); - col.Add(d).Execute(); - - var docs = new[] { new { _id = 1, title = "Book 1" }, new { _id = 2, title = "Book 2" } }; - d2 = new DbDoc(); - d2.SetValue("id", 100); - d2.SetValue("pages", 20); - d2.SetValue("books", docs); - col.Add(d2).Execute(); - - var result = col.Find("$._id = 0").Fields("$._id as _id,$.name as name, $.pages as pages, $.title as title").Execute(); - var res1 = result.FetchOne(); - Assert.AreEqual(0, res1["_id"]); - Assert.AreEqual("Jeoff Archer", res1["name"]); - Assert.AreEqual(10, res1["pages"]); - Assert.AreEqual("Book 0", res1["title"]); - - result = col.Find("$._id > 0").Fields().Execute(); - var res2 = result.FetchAll(); - Assert.AreEqual(6, res2.Count()); - - DbDoc test = new DbDoc(); - test.SetValue("_id", 1); - test.SetValue("name", "ABBBBBBBBBBBBBBXXXXXXXXXXXXXXXYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYTTTTTTYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYABBBBBBBBBBBBBBXXXXXXXXXXXXXXXYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYTTTTTTYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYABBBBBBBBBBBBBBXXXXXXXXXXXXXXXYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYTTTTTTYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYABBBBBBBBBBBBBBXXXXXXXXXXXXXXXYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYTTTTTTYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYABBBBBBBBBBBBBBXXXXXXXXXXXXXXXYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYTTTTTTYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY"); - var coll = CreateCollection("my_collection_123456789"); - var res = coll.Add(test).Execute(); - foundDocs = coll.Find().Execute(); - var docs1 = foundDocs.FetchAll(); - Assert.AreEqual(1, docs1.Count); - } - - [Test, Description("Verify that the field and column _id has a value when it's not given to a document-Scenario-1(single document add)")] - public void VerifyIDField() - { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("this test is for MySql 8.0.11 or higher."); - List idStringList = new List(); - var col = CreateCollection("my_collection"); - Result result = null; - string generatedIDs1 = null, generatedIDs2 = null; - int countgenerateIDs = 0; - // Anonymous Object Array - object[] data = new object[] { new { title = "Book 1", pages = 30 } }; - var stmt = col.Add(data); - result = stmt.Execute(); - generatedIDs1 = result.GeneratedIds[0]; - Assert.AreEqual(generatedIDs1, generatedIDs1, "ID generated by the server"); - VerifyGeneratedID(generatedIDs1); - countgenerateIDs = result.GeneratedIds.Count; - Assert.AreEqual(1, countgenerateIDs, "Count of the ID generated by the server"); - for (int i = 0; i < countgenerateIDs; i++) - { - idStringList.Add(result.GeneratedIds[i]); - } - - // DbDoc - DbDoc DbDocs = new DbDoc(); - DbDocs.SetValue("title", "Book 0"); - DbDocs.SetValue("pages", 10); - stmt = col.Add(DbDocs); - result = stmt.Execute(); - generatedIDs2 = result.GeneratedIds[0]; - Assert.AreEqual(generatedIDs2, generatedIDs2, "ID generated by the server"); - VerifyGeneratedID(generatedIDs2); - countgenerateIDs = result.GeneratedIds.Count; - Assert.AreEqual(1, countgenerateIDs, "Count of the ID generated by the server"); - for (int i = 0; i < countgenerateIDs; i++) - { - idStringList.Add(result.GeneratedIds[i]); - } - - // Anonymous Object - var docs = new { title = "Book 1", pages = 20 }; - stmt = col.Add(docs); - result = stmt.Execute(); - generatedIDs1 = result.GeneratedIds[0]; - Assert.AreEqual(generatedIDs1, generatedIDs1, "ID generated by the server"); - VerifyGeneratedID(generatedIDs1); - countgenerateIDs = result.GeneratedIds.Count; - Assert.AreEqual(1, countgenerateIDs, "Count of the ID generated by the server"); - for (int i = 0; i < countgenerateIDs; i++) - { - idStringList.Add(result.GeneratedIds[i]); - } - - // JSON - stmt = col.Add("{ \"foo\": 100 }"); - result = stmt.Execute(); - generatedIDs2 = result.GeneratedIds[0]; - Assert.AreEqual(generatedIDs2, generatedIDs2, "ID generated by the server"); - VerifyGeneratedID(generatedIDs2); - countgenerateIDs = result.GeneratedIds.Count; - Assert.AreEqual(1, countgenerateIDs, "Count of the ID generated by the server"); - for (int i = 0; i < countgenerateIDs; i++) - { - idStringList.Add(result.GeneratedIds[i]); - } - - int j = 1; - for (int i = 0; i < idStringList.Count; i++) - { - if (j == idStringList.Count) - { - break; - } - VerifySequence(idStringList[i], idStringList[j]); - j++; - } - } - - [Test, Description("Unique _ids generated server side for multiple documents, single add and generated ids count should be number of docs added-Scenario3")] - public void VerifyIDFieldScenario3() - { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("this test is for MySql 8.0.11 or higher."); - List idStringList = new List(); - var col = CreateCollection("my_collection"); - Result result = null; - string generatedIDs1 = null; - int countgenerateIDs = 0; - HashSet firstset = new HashSet(); - - object[] data1 = new object[] - { - new { title = "Book 1", pages = 20 }, - new { title = "Book 2", pages = 30 }, - new { title = "Book 3", pages = 40 }, - new { title = "Book 4", pages = 50 } - }; - - var stmt = col.Add(data1); - result = stmt.Execute(); - countgenerateIDs = result.GeneratedIds.Count; - Assert.AreEqual(4, countgenerateIDs, "Count of the ID generated by the server"); - for (int i = 0; i < countgenerateIDs; i++) - { - generatedIDs1 = result.GeneratedIds[i]; - Assert.AreEqual(generatedIDs1, generatedIDs1, "ID generated by the server"); - VerifyGeneratedID(generatedIDs1); - Assert.False(!firstset.Add(generatedIDs1)); - } - - for (int i = 0; i < countgenerateIDs; i++) - { - idStringList.Add(result.GeneratedIds[i]); - } - - stmt = col.Add(@"{ ""foo"": 1 }", @"{""foo"": 2 }", @"{ ""foo"": 3 }", @"{ ""foo"": 4 }"); - result = stmt.Execute(); - countgenerateIDs = result.GeneratedIds.Count; - Assert.AreEqual(4, countgenerateIDs, "Count of the ID generated by the server"); - for (int i = 0; i < countgenerateIDs; i++) - { - generatedIDs1 = result.GeneratedIds[i]; - Assert.AreEqual(generatedIDs1, generatedIDs1, "ID generated by the server"); - VerifyGeneratedID(generatedIDs1); - Assert.False(!firstset.Add(generatedIDs1)); - } - - for (int i = 0; i < countgenerateIDs; i++) - { - idStringList.Add(result.GeneratedIds[i]); - } - - int j = 1; - for (int i = 0; i < idStringList.Count; i++) - { - if (j == idStringList.Count) - { - break; - } - VerifySequence(idStringList[i], idStringList[j]); - j++; - } - } - - [Test, Description("Verify that the field and column _id has a value when it's not given to a document-Scenario-1(single document add)-when doc already exists")] - public void VerifyIDFieldScenario4() - { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("this test is for MySql 8.0.11 or higher."); - List idStringList = new List(); - var col = CreateCollection("my_collection"); - Result result = null; - string generatedIDs1 = null, generatedIDs2 = null; - int countgenerateIDs = 0; - object[] data = null; - data = new object[] - { - new { title ="Book 0", pages = 10 }, - new { title ="Book 5", pages = 60, _id = 6} - }; - result = col.Add(data).Execute(); - countgenerateIDs = result.GeneratedIds.Count; - generatedIDs1 = result.GeneratedIds[0]; - Assert.AreEqual(1, countgenerateIDs, "Count of the ID generated by the server"); - for (int i = 0; i < countgenerateIDs; i++) - { - idStringList.Add(result.GeneratedIds[i]); - } - - // Anonymous Object Array - data = new object[] { new { title = "Book 1", pages = 30 } }; - var stmt = col.Add(data); - result = stmt.Execute(); - generatedIDs1 = result.GeneratedIds[0]; - Assert.AreEqual(generatedIDs1, generatedIDs1, "ID generated by the server"); - VerifyGeneratedID(generatedIDs1); - countgenerateIDs = result.GeneratedIds.Count; - Assert.AreEqual(1, countgenerateIDs, "Count of the ID generated by the server"); - for (int i = 0; i < countgenerateIDs; i++) - { - idStringList.Add(result.GeneratedIds[i]); - } - - col = CreateCollection("my_collection"); - data = null; - data = new object[] - { - new { title ="Book 0", pages = 10 }, - new { title ="Book 5", pages = 60, _id = 6} - }; - result = col.Add(data).Execute(); - countgenerateIDs = result.GeneratedIds.Count; - generatedIDs1 = result.GeneratedIds[0]; - Assert.AreEqual(1, countgenerateIDs, "Count of the ID generated by the server"); - for (int i = 0; i < countgenerateIDs; i++) - { - idStringList.Add(result.GeneratedIds[i]); - } - - // DbDoc - DbDoc DbDocs = new DbDoc(); - DbDocs.SetValue("title", "Book 0"); - DbDocs.SetValue("pages", 10); - stmt = col.Add(DbDocs); - result = stmt.Execute(); - generatedIDs2 = result.GeneratedIds[0]; - Assert.AreEqual(generatedIDs2, generatedIDs2, "ID generated by the server"); - VerifyGeneratedID(generatedIDs2); - countgenerateIDs = result.GeneratedIds.Count; - Assert.AreEqual(1, countgenerateIDs, "Count of the ID generated by the server"); - for (int i = 0; i < countgenerateIDs; i++) - { - idStringList.Add(result.GeneratedIds[i]); - } - - col = CreateCollection("my_collection"); - data = null; - data = new object[] - { - new { title ="Book 0", pages = 10 }, - new { title ="Book 5", pages = 60, _id = 6} - }; - result = col.Add(data).Execute(); - countgenerateIDs = result.GeneratedIds.Count; - generatedIDs1 = result.GeneratedIds[0]; - Assert.AreEqual(1, countgenerateIDs, "Count of the ID generated by the server"); - for (int i = 0; i < countgenerateIDs; i++) - { - idStringList.Add(result.GeneratedIds[i]); - } - - // Anonymous Object - var docs = new { title = "Book 1", pages = 20 }; - stmt = col.Add(docs); - result = stmt.Execute(); - generatedIDs1 = result.GeneratedIds[0]; - Assert.AreEqual(generatedIDs1, generatedIDs1, "ID generated by the server"); - VerifyGeneratedID(generatedIDs1); - countgenerateIDs = result.GeneratedIds.Count; - Assert.AreEqual(1, countgenerateIDs, "Count of the ID generated by the server"); - for (int i = 0; i < countgenerateIDs; i++) - { - idStringList.Add(result.GeneratedIds[i]); - } - - col = CreateCollection("my_collection"); - data = null; - data = new object[] - { - new { title ="Book 0", pages = 10 }, - new { title ="Book 5", pages = 60, _id = 6} - }; - result = col.Add(data).Execute(); - countgenerateIDs = result.GeneratedIds.Count; - generatedIDs1 = result.GeneratedIds[0]; - Assert.AreEqual(1, countgenerateIDs, "Count of the ID generated by the server"); - for (int i = 0; i < countgenerateIDs; i++) - { - idStringList.Add(result.GeneratedIds[i]); - } - - //JSON - stmt = col.Add("{ \"foo\": 100 }"); - result = stmt.Execute(); - generatedIDs2 = result.GeneratedIds[0]; - Assert.AreEqual(generatedIDs2, generatedIDs2, "ID generated by the server"); - VerifyGeneratedID(generatedIDs2); - countgenerateIDs = result.GeneratedIds.Count; - Assert.AreEqual(1, countgenerateIDs, "Count of the ID generated by the server"); - for (int i = 0; i < countgenerateIDs; i++) - { - idStringList.Add(result.GeneratedIds[i]); - } - - int j = 1; - for (int i = 0; i < idStringList.Count; i++) - { - if (j == idStringList.Count) - { - break; - } - VerifySequence(idStringList[i], idStringList[j]); - j++; - } - } - - [Test, Description("Unique _ids generated server side for multiple documents,multiple add and generated ids count should be number of docs added-when doc already exists Scenario2")] - public void VerifyIDFieldScenario5() - { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("this test is for MySql 8.0.11 or higher."); - List idStringList = new List(); - Result result = null; - string generatedIDs1 = null; - int countgenerateIDs = 0; - var col = CreateCollection("my_collection"); - object[] data = null; - - data = new object[] - { - new { title ="Book 0", pages = 10 }, - new { title ="Book 5", pages = 60, _id = 6} - }; - result = col.Add(data).Execute(); - countgenerateIDs = result.GeneratedIds.Count; - generatedIDs1 = result.GeneratedIds[0]; - Assert.AreEqual(1, countgenerateIDs, "Count of the ID generated by the server"); - for (int i = 0; i < countgenerateIDs; i++) - { - idStringList.Add(result.GeneratedIds[i]); - } - - HashSet firstset = new HashSet(); - // Anonymous Object Array - object[] data1 = new object[] { new { title ="Book 1", pages = 20 } - }; - object[] data2 = new object[] { new { title = "Book 5", pages = 60 } }; - - var stmt = col.Add(data1).Add(data2); - result = stmt.Execute(); - countgenerateIDs = result.GeneratedIds.Count; - Assert.AreEqual(2, countgenerateIDs, "Count of the ID generated by the server"); - for (int i = 0; i < countgenerateIDs; i++) - { - generatedIDs1 = result.GeneratedIds[i]; - Assert.AreEqual(generatedIDs1, generatedIDs1, "ID generated by the server"); - VerifyGeneratedID(generatedIDs1); - Assert.False(!firstset.Add(generatedIDs1)); - } - for (int i = 0; i < countgenerateIDs; i++) - { - idStringList.Add(result.GeneratedIds[i]); - } - - col = CreateCollection("my_collection"); - data = new object[] - { - new { title ="Book 0", pages = 10 }, - new { title ="Book 5", pages = 60, _id = 6} - }; - result = col.Add(data).Execute(); - countgenerateIDs = result.GeneratedIds.Count; - generatedIDs1 = result.GeneratedIds[0]; - Assert.AreEqual(1, countgenerateIDs, "Count of the ID generated by the server"); - for (int i = 0; i < countgenerateIDs; i++) - { - idStringList.Add(result.GeneratedIds[i]); - } - - // DbDoc - DbDoc DbDocs1 = new DbDoc(); - DbDocs1.SetValue("title", "Book 0"); - DbDocs1.SetValue("pages", 10); - DbDoc DbDocs2 = new DbDoc(); - DbDocs2.SetValue("title", "Book 1"); - DbDocs2.SetValue("pages", 20); - stmt = col.Add(DbDocs1).Add(DbDocs2); - result = stmt.Execute(); - countgenerateIDs = result.GeneratedIds.Count; - Assert.AreEqual(2, countgenerateIDs, "Count of the ID generated by the server"); - for (int i = 0; i < countgenerateIDs; i++) - { - generatedIDs1 = result.GeneratedIds[i]; - Assert.AreEqual(generatedIDs1, generatedIDs1, "ID generated by the server"); - VerifyGeneratedID(generatedIDs1); - Assert.False(!firstset.Add(generatedIDs1)); - } - for (int i = 0; i < countgenerateIDs; i++) - { - idStringList.Add(result.GeneratedIds[i]); - } - - col = CreateCollection("my_collection"); - - data = new object[] - { - new { title ="Book 0", pages = 10 }, - new { title ="Book 5", pages = 60, _id = 6} - }; - result = col.Add(data).Execute(); - countgenerateIDs = result.GeneratedIds.Count; - generatedIDs1 = result.GeneratedIds[0]; - Assert.AreEqual(1, countgenerateIDs, "Count of the ID generated by the server"); - for (int i = 0; i < countgenerateIDs; i++) - { - idStringList.Add(result.GeneratedIds[i]); - } - - // Anonymous Object - var docs1 = new { title = "Book 1", pages = 20 }; - var docs2 = new { title = "Book 2", pages = 30 }; - stmt = col.Add(docs1).Add(docs2); - - result = stmt.Execute(); - countgenerateIDs = result.GeneratedIds.Count; - Assert.AreEqual(2, countgenerateIDs, "Count of the ID generated by the server"); - for (int i = 0; i < countgenerateIDs; i++) - { - generatedIDs1 = result.GeneratedIds[i]; - Assert.AreEqual(generatedIDs1, generatedIDs1, "ID generated by the server"); - VerifyGeneratedID(generatedIDs1); - Assert.False(!firstset.Add(generatedIDs1)); - } - for (int i = 0; i < countgenerateIDs; i++) - { - idStringList.Add(result.GeneratedIds[i]); - } - - col = CreateCollection("my_collection"); - data = new object[] - { - new { title ="Book 0", pages = 10 }, - new { title ="Book 5", pages = 60, _id = 6} - }; - result = col.Add(data).Execute(); - countgenerateIDs = result.GeneratedIds.Count; - generatedIDs1 = result.GeneratedIds[0]; - Assert.AreEqual(1, countgenerateIDs, "Count of the ID generated by the server"); - for (int i = 0; i < countgenerateIDs; i++) - { - idStringList.Add(result.GeneratedIds[i]); - } - - // JSON - stmt = col.Add("{ \"foo1\": 100 }").Add("{ \"foo2\": 200 }"); - result = stmt.Execute(); - countgenerateIDs = result.GeneratedIds.Count; - Assert.AreEqual(2, countgenerateIDs, "Count of the ID generated by the server"); - for (int i = 0; i < countgenerateIDs; i++) - { - generatedIDs1 = result.GeneratedIds[i]; - Assert.AreEqual(generatedIDs1, generatedIDs1, "ID generated by the server"); - VerifyGeneratedID(generatedIDs1); - if (!firstset.Add(generatedIDs1)) - { - break; - } - } - for (int i = 0; i < countgenerateIDs; i++) - { - idStringList.Add(result.GeneratedIds[i]); - } - - int j = 1; - for (int i = 0; i < idStringList.Count; i++) - { - if (j == idStringList.Count) - { - break; - } - VerifySequence(idStringList[i], idStringList[j]); - j++; - } - } - - [Test, Description("Unique _ids generated server side for multiple documents, single add and generated ids count should be number of docs added-when doc already exists Scenario3")] - public void VerifyIDFieldScenario6() - { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("this test is for MySql 8.0.11 or higher."); - List idStringList = new List(); - var col = CreateCollection("my_collection"); - Result result = null; - string generatedIDs1 = null; - int countgenerateIDs = 0; - object[] data = null; - - data = new object[] - { - new { title ="Book 0", pages = 10 }, - new { title ="Book 5", pages = 60, _id = 6} - }; - result = col.Add(data).Execute(); - countgenerateIDs = result.GeneratedIds.Count; - generatedIDs1 = result.GeneratedIds[0]; - Assert.AreEqual(1, countgenerateIDs, "Count of the ID generated by the server"); - for (int i = 0; i < countgenerateIDs; i++) - { - idStringList.Add(result.GeneratedIds[i]); - } - - HashSet firstset = new HashSet(); - // Anonymous Object Array - object[] data1 = new object[] - { - new { title ="Book 1", pages = 20 }, - new { title = "Book 2", pages = 30 }, - new { title = "Book 3", pages = 40 }, - new { title = "Book 4", pages = 50 } - }; - - var stmt = col.Add(data1); - result = stmt.Execute(); - countgenerateIDs = result.GeneratedIds.Count; - Assert.AreEqual(4, countgenerateIDs, "Count of the ID generated by the server"); - for (int i = 0; i < countgenerateIDs; i++) - { - generatedIDs1 = result.GeneratedIds[i]; - Assert.AreEqual(generatedIDs1, generatedIDs1, "ID generated by the server"); - VerifyGeneratedID(generatedIDs1); - Assert.False(!firstset.Add(generatedIDs1)); - } - for (int i = 0; i < countgenerateIDs; i++) - { - idStringList.Add(result.GeneratedIds[i]); - } - - col = CreateCollection("my_collection"); - result = col.Add(@"{ ""foo"": 0, ""_id"":0 }", @"{""foo"": 5 }").Execute(); - countgenerateIDs = result.GeneratedIds.Count; - generatedIDs1 = result.GeneratedIds[0]; - Assert.AreEqual(1, countgenerateIDs, "Count of the ID generated by the server"); - for (int i = 0; i < countgenerateIDs; i++) - { - idStringList.Add(result.GeneratedIds[i]); - } - - // JSON - stmt = col.Add(@"{ ""foo"": 1 }", @"{""foo"": 2 }", @"{ ""foo"": 3 }", @"{ ""foo"": 4 }"); - result = stmt.Execute(); - countgenerateIDs = result.GeneratedIds.Count; - Assert.AreEqual(4, countgenerateIDs, "Count of the ID generated by the server"); - for (int i = 0; i < countgenerateIDs; i++) - { - generatedIDs1 = result.GeneratedIds[i]; - Assert.AreEqual(generatedIDs1, generatedIDs1, "ID generated by the server"); - VerifyGeneratedID(generatedIDs1); - Assert.False(!firstset.Add(generatedIDs1)); - } - for (int i = 0; i < countgenerateIDs; i++) - { - idStringList.Add(result.GeneratedIds[i]); - } - - int j = 1; - for (int i = 0; i < idStringList.Count; i++) - { - if (j == idStringList.Count) - { - break; - } - VerifySequence(idStringList[i], idStringList[j]); - j++; - } - } - - [Test, Description("Client provided _id shouldnt be discarded and generatedids() should give empty list for anonymous object array -single document add")] - public void VerifyIDFieldScenario7() - { - var col = CreateCollection("my_collection"); - object[] data = new object[] - { - new { _id = "1e9c92fda74ed311944e00059a3c7a00", title = "Book 0", pages = 10 }, - }; - Result result = col.Add(data).Execute(); - var generatedIDs = result.GeneratedIds; - Assert.AreEqual(0, generatedIDs.Count, "Matches"); - var doc = col.Find("_id like :param").Bind("param", "1e9c92fda74ed311944e00059a3c7a00").Execute(); - var docs = doc.FetchAll().Count(); - Assert.AreEqual(1, docs, "Matches"); - - //Anonymous Object - var data1 = new { _id = "1e9c92fda74ed311944e00059a3c7a01", title = "Book 0", pages = 10 }; - result = col.Add(data1).Execute(); - - generatedIDs = result.GeneratedIds; - Assert.AreEqual(0, generatedIDs.Count, "Matches"); - doc = col.Find("_id like :param").Bind("param", "1e9c92fda74ed311944e00059a3c7a01").Execute(); - docs = doc.FetchAll().Count(); - Assert.AreEqual(1, docs, "Matches"); - - // DbDoc - DbDoc DbDocs = new DbDoc(); - DbDocs.SetValue("title", "Book 0"); - DbDocs.SetValue("pages", 10); - DbDocs.SetValue("_id", "1e9c92fda74ed311944e00059a3c7a02"); - result = col.Add(DbDocs).Execute(); - - generatedIDs = result.GeneratedIds; - Assert.AreEqual(0, generatedIDs.Count, "Matches"); - doc = col.Find("_id like :param").Bind("param", "1e9c92fda74ed311944e00059a3c7a02").Execute(); - docs = doc.FetchAll().Count(); - Assert.AreEqual(1, docs, "Matches"); - - //JSON - result = col.Add("{\"_id\":\"1e9c92fda74ed311944e00059a3c7a03\",\"title\": \"Book 0\",\"pages\": 10}").Execute(); - generatedIDs = result.GeneratedIds; - Assert.AreEqual(0, generatedIDs.Count, "Matches"); - doc = col.Find("_id like :param").Bind("param", "1e9c92fda74ed311944e00059a3c7a03").Execute(); - docs = doc.FetchAll().Count(); - Assert.AreEqual(1, docs, "Matches"); - } - - [Test, Description("Client provided _id shouldnt be discarded and generatedids() should give empty list for anonymous object array -multiple documents multiple add with negative number")] - public void VerifyIDFieldScenario8() - { - var col = CreateCollection("my_collection"); - object[] data1 = new object[] - { - new { _id = "1e9c92fda74ed311944e00059a3c7a00", title = "Book 0", pages = 10 } - }; - object[] data2 = new object[] - { - new { _id = -1, title = "Book 0", pages = 10 } - }; - Result result = col.Add(data1).Add(data2).Execute(); - var generatedIDs = result.GeneratedIds; - Assert.AreEqual(0, generatedIDs.Count, "Matches"); - var doc = col.Find("_id like :param").Bind("param", "1e9c92fda74ed311944e00059a3c7a00").Execute(); - var docs = doc.FetchAll().Count(); - Assert.AreEqual(1, docs, "Matches"); - doc = col.Find("_id like :param").Bind("param", -1).Execute(); - docs = doc.FetchAll().Count(); - Assert.AreEqual(1, docs, "Matches"); - - // Anonymous Object - var data3 = new { _id = "1e9c92fda74ed311944e00059a3c7a01", title = "Book 0", pages = 10 }; - var data4 = new { _id = -2, title = "Book 0", pages = 10 }; - result = col.Add(data3).Add(data4).Execute(); - generatedIDs = result.GeneratedIds; - Assert.AreEqual(0, generatedIDs.Count, "Matches"); - doc = col.Find("_id like :param").Bind("param", "1e9c92fda74ed311944e00059a3c7a01").Execute(); - docs = doc.FetchAll().Count(); - Assert.AreEqual(1, docs, "Matches"); - doc = col.Find("_id like :param").Bind("param", -2).Execute(); - docs = doc.FetchAll().Count(); - Assert.AreEqual(1, docs, "Matches"); - - //DbDoc - DbDoc DbDocs1 = new DbDoc(); - DbDocs1.SetValue("title", "Book 0"); - DbDocs1.SetValue("pages", 10); - DbDocs1.SetValue("_id", "1e9c92fda74ed311944e00059a3c7a02"); - DbDoc DbDocs2 = new DbDoc(); - DbDocs2.SetValue("title", "Book 0"); - DbDocs2.SetValue("pages", 10); - DbDocs2.SetValue("_id", -3); - result = col.Add(DbDocs1).Add(DbDocs2).Execute(); - generatedIDs = result.GeneratedIds; - Assert.AreEqual(0, generatedIDs.Count, "Matches"); - doc = col.Find("_id like :param").Bind("param", "1e9c92fda74ed311944e00059a3c7a02").Execute(); - docs = doc.FetchAll().Count(); - Assert.AreEqual(1, docs, "Matches"); - doc = col.Find("_id like :param").Bind("param", -3).Execute(); - docs = doc.FetchAll().Count(); - Assert.AreEqual(1, docs, "Matches"); - - // JSON - result = col.Add("{\"_id\":\"1e9c92fda74ed311944e00059a3c7a03\",\"title\": \"Book 0\",\"pages\": 10}"). - Add("{\"_id\":-4,\"title\": \"Book 0\",\"pages\": 10}"). - Execute(); - generatedIDs = result.GeneratedIds; - Assert.AreEqual(0, generatedIDs.Count, "Matches"); - doc = col.Find("_id like :param").Bind("param", "1e9c92fda74ed311944e00059a3c7a03").Execute(); - docs = doc.FetchAll().Count(); - Assert.AreEqual(1, docs, "Matches"); - doc = col.Find("_id like :param").Bind("param", -4).Execute(); - docs = doc.FetchAll().Count(); - Assert.AreEqual(1, docs, "Matches"); - } - - [Test, Description("Client provided _id shouldnt be discarded and generatedids() should give empty list for anonymous object array -multiple documents single add with negative number,zero and big positive numbers")] - public void VerifyIDFieldScenario9() - { - var col = CreateCollection("my_collection"); - // Anonymous Object Array - object[] idList = new object[] { "1e9c92fda74ed311944e00059a3c7a00", -1, 60000000000000, -3000000000000, 0 }; - object[] data1 = new object[] - { - new { _id = idList[0], title = "Book 0", pages = 10 }, - new { _id = idList[1], title = "Book 0", pages = 10 }, - new { _id = idList[2] , title = "Book 0", pages = 10 }, - new { _id = idList[3], title = "Book 0", pages = 10 }, - new { _id = idList[4], title = "Book 0", pages = 10 } - }; - Result result = col.Add(data1).Execute(); - var generatedIDs = result.GeneratedIds; - Assert.AreEqual(0, generatedIDs.Count, "Matches"); - for (int i = 0; i < idList.Length; i++) - { - var doc = col.Find("_id like :param").Bind("param", idList[i]).Execute(); - var docs = doc.FetchAll().Count(); - Assert.AreEqual(1, docs, "Matches the Document ID"); - } - } - - [Test, Description("documents single add with blank id")] - public void CollectionAddBlankId() - { - var col = CreateCollection("my_collection"); - // Anonymous Object Array - object[] idList = new object[] { "", " " }; - object[] data1 = new object[] - { - new { _id = idList[0], title = "Book 0", pages = 10 } - }; - object[] data2 = new object[] - { - new { _id = idList[1], title = "Book 0", pages = 10 } - }; - Result result1 = col.Add(data1).Execute(); - Assert.AreEqual(1, result1.AffectedItemsCount); - result1 = null; - - col = CreateCollection("my_collection"); - result1 = col.Add(data2).Execute(); - Assert.AreEqual(1, result1.AffectedItemsCount); - result1 = null; - - col = CreateCollection("my_collection"); - // DbDoc - DbDoc DbDocs1 = new DbDoc(); - DbDocs1.SetValue("title", "Book 0"); - DbDocs1.SetValue("pages", 10); - DbDocs1.SetValue("_id", ""); - result1 = col.Add(DbDocs1).Execute(); - Assert.AreEqual(1, result1.AffectedItemsCount); - result1 = null; - - col = CreateCollection("my_collection"); - DbDoc DbDocs2 = new DbDoc(); - DbDocs2.SetValue("title", "Book 1"); - DbDocs2.SetValue("pages", 20); - DbDocs2.SetValue("_id", " "); - result1 = col.Add(DbDocs2).Execute(); - Assert.AreEqual(1, result1.AffectedItemsCount); - result1 = null; - - // JSON - col = CreateCollection("my_collection"); - result1 = col.Add("{\"_id\":\"\",\"title\": \"Book 0\",\"pages\": 10}").Execute(); - Assert.AreEqual(1, result1.AffectedItemsCount); - result1 = null; - - col = CreateCollection("my_collection"); - result1 = col.Add("{\"_id\":\" \",\"title\": \"Book 0\",\"pages\": 10}").Execute(); - Assert.AreEqual(1, result1.AffectedItemsCount); - result1 = null; - - } - - [Test, Description("Multiple documents with same id")] - public void CollectionAddMultipleDocsSameId() - { - var col = CreateCollection("my_collection"); - string exception = "Document contains a field value that is not unique but required to be"; - // DbDoc - DbDoc DbDocs1 = new DbDoc(); - DbDocs1.SetValue("title", "Book 0"); - DbDocs1.SetValue("pages", 10); - DbDocs1.SetValue("_id", 1); - DbDoc DbDocs2 = new DbDoc(); - DbDocs2.SetValue("title", "Book 1"); - DbDocs2.SetValue("pages", 20); - DbDocs2.SetValue("_id", 1); - var ex = Assert.Throws(() => col.Add(DbDocs1).Add(DbDocs2).Execute()); - Assert.AreEqual(exception, ex.Message, "Checking the exception"); - - // JSON - ex = Assert.Throws(() => col.Add("{\"_id\":1,\"title\": \"Book 0\",\"pages\": 10}"). - Add("{\"_id\":1,\"title\": \"Book 1\",\"pages\": 20}").Execute()); - Assert.AreEqual(exception, ex.Message, "Checking the exception"); - - // Anonymous Object Array - object[] data1 = new object[] - { - new { _id = 1, title = "Book 0", pages = 10 } - }; - object[] data2 = new object[] - { - new { _id = 1, title = "Book 1", pages = 20 } - }; - ex = Assert.Throws(() => col.Add(data1).Add(data2).Execute()); - Assert.AreEqual(exception, ex.Message, "Checking the exception"); - } - - [Test, Description("Verify the behaviour if a sequence is incremented by the user and added as _id for the document")] - public void VerifySequenceAndIdAdded() - { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher."); - string incrementedString = null, generatedString = null; - var col = CreateCollection("my_collection"); - Result result = null; - string generatedIDs1 = null; - int countgenerateIDs = 0; - // Anonymous Object Array - object[] data = new object[] { new { title = "Book 1", pages = 30 } }; - var stmt = col.Add(data); - - result = stmt.Execute(); - generatedIDs1 = result.GeneratedIds[0]; - Assert.AreEqual(generatedIDs1, generatedIDs1, "ID generated by the server"); - VerifyGeneratedID(generatedIDs1); - countgenerateIDs = result.GeneratedIds.Count; - Assert.AreEqual(1, countgenerateIDs, "Count of the ID generated by the server"); - generatedString = generatedIDs1; - incrementedString = Increment(generatedIDs1, Mode.AlphaNumeric); - - data = new object[] { new { title = "Book 2", pages = 40, _id = generatedString } }; - stmt = col.Add(data); - string exception = "Document contains a field value that is not unique but required to be"; - Exception ex = Assert.Throws(() => stmt.Execute()); - Assert.AreEqual(exception, ex.Message, "Matching the exception"); - - data = new object[] { new { title = "Book 3", pages = 50, _id = incrementedString } }; - stmt = col.Add(data); - result = stmt.Execute(); - Assert.IsNotNull(result); - - data = new object[] { new { title = "Book 4", pages = 60 } }; - stmt = col.Add(data); - ex = Assert.Throws(() => stmt.Execute()); - Assert.AreEqual(exception, ex.Message, "Matching the exception"); - - } - - [Test, Description("documents inserted concurrently by two threads")] - public async Task CollectionConcurrentAdd() - { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher."); - - CreateCollection("my_collection"); - var r1 = await CollectionAddThread1(); - _ = await CollectionAddThread2(); - Assert.AreEqual(1000, r1); - } - public Task CollectionAddThread1() - { - List idStringList = new List(); - var col = CreateCollection("my_collection"); - DbDoc[] jsonlist = new DbDoc[1000]; - for (int i = 0; i < 1000; i++) - { - DbDoc newDoc2 = new DbDoc(); - newDoc2.SetValue("F1", ("Field-1-Data-" + i)); - newDoc2.SetValue("F2", ("Field-2-Data-" + i)); - newDoc2.SetValue("F3", (3 + i).ToString()); - jsonlist[i] = newDoc2; - newDoc2 = null; - } - Result r = col.Add(jsonlist).Execute(); - Assert.AreEqual(1000, r.AffectedItemsCount, "Matching"); - int countgenerateIDs = r.GeneratedIds.Count; - for (int i = 0; i < countgenerateIDs; i++) - { - idStringList.Add(r.GeneratedIds[i]); - } - - int j = 1; - for (int i = 0; i < idStringList.Count; i++) - { - if (j == idStringList.Count) - { - break; - } - VerifySequence(idStringList[i], idStringList[j]); - j++; - } - return Task.FromResult((int)r.AffectedItemsCount); - } - - public Task CollectionAddThread2() - { - List idStringList = new List(); - var col = CreateCollection("my_collection1"); - DbDoc[] jsonlist = new DbDoc[1000]; - for (int i = 0; i < 1000; i++) - { - DbDoc newDoc2 = new DbDoc(); - newDoc2.SetValue("F4", ("Field-1-Data-" + i)); - newDoc2.SetValue("F5", ("Field-2-Data-" + i)); - newDoc2.SetValue("F6", (3 + i).ToString()); - jsonlist[i] = newDoc2; - newDoc2 = null; - } - Result r = col.Add(jsonlist).Execute(); - Assert.AreEqual(1000, r.AffectedItemsCount, "Matching"); - int countgenerateIDs = r.GeneratedIds.Count; - for (int i = 0; i < countgenerateIDs; i++) - { - idStringList.Add(r.GeneratedIds[i]); - } - - int j = 1; - for (int i = 0; i < idStringList.Count; i++) - { - if (j == idStringList.Count) - { - break; - } - VerifySequence(idStringList[i], idStringList[j]); - j++; - } - return Task.FromResult(0); - } - - ///// - ///// Bug24397888 - ///// - [Test, Description("WHEN A DBDOC IS PASSED AS OBJ TO SETVALUE OF ANOTHER DBDOC IT CONVERTS TO BLANK")] - public void DbDocAsObjectConvertToBlank() - { - string newLine = Platform.IsWindows() ? "\r\n" : "\n"; - - var col = CreateCollection("my_collection"); - var data1 = new DbDoc(@"{ ""id"": 1, ""pages"": 20, - ""person"": { ""name"": ""Fred"", ""age"": 45 } - }"); - DbDoc d2 = new DbDoc(); - d2.SetValue("id", 1); - d2.SetValue("pages", 20); - d2.SetValue("taker1", data1); - string expected = $"{{{newLine} \"id\": 1, {newLine} \"pages\": 20, {newLine} \"taker1\": {{{newLine} \"id\": 1, {newLine} \"pages\": 20, {newLine} \"person\": {{{newLine} \"name\": \"Fred\", {newLine} \"age\": 45{newLine} }}{newLine} }}{newLine}}}"; - Assert.AreEqual(expected, d2.ToString()); - } - - [Test, Description("ADDITION OF OBJ FAILS AFTER CREATE INDEX IN 5.7.12 SERVER(WORKS WITH 5.7.9)")] - public void AdditionOfObject() - { - Collection testColl = CreateCollection("test"); - testColl.CreateIndex("testIndex", "{\"fields\": [ { \"field\":$.myId, \"type\":\"INT\" , \"required\":true} ] }"); - testColl.CreateIndex("testIndex1", "{\"fields\": [ { \"field\":$.myAge, \"type\":\"FLOAT\" , \"required\":true} ] }"); - var result = testColl.Add(new { myId = 1, myAge = 35.1, _id = 1 }).Execute(); - Assert.AreEqual(1, result.AffectedItemsCount); - } - - [Test, Description("Test valid insert at Depth n for multiple arrays))")] - public void InsertAtNDepth() - { - if (!session.Version.isAtLeast(8, 0, 3)) return; - string json = ""; - int i = 0, j = 0, maxField = 100; - var collection = CreateCollection("test"); - int maxDepth = 97; - json = "{\"_id\":\"1002\",\"XYZ\":1111"; - for (j = 0; j < maxField; j++) - { - json = json + ",\"ARR" + j + "\":["; - for (i = 0; i < maxDepth; i++) - { - json = json + i + ",["; - } - json = json + i; - for (i = maxDepth - 1; i >= 0; i--) - { - json = json + "]," + i; - } - json = json + "]"; - } - json = json + "}"; - - var res = collection.Add(json).Execute(); - Assert.AreEqual(1, res.AffectedItemsCount); - } - - #endregion WL14389 - - #region Methods - - public void VerifyGeneratedID(string input) - { - byte[] array = Encoding.ASCII.GetBytes(input); - Assert.False(array.Length < 28); - - byte[] uniquePrefix = new byte[4]; - Array.Copy(array, 0, uniquePrefix, 0, 4); - - Assert.AreEqual(System.Text.Encoding.UTF8.GetString(uniquePrefix), System.Text.Encoding.UTF8.GetString(uniquePrefix), - "Unique Prefix of the Generated ID"); - - byte[] startTimeStamp = new byte[8]; - Array.Copy(array, 4, startTimeStamp, 0, 8); - Assert.AreEqual(System.Text.Encoding.UTF8.GetString(startTimeStamp), System.Text.Encoding.UTF8.GetString(startTimeStamp), - "StartTimeStamp of the Generated ID"); - - byte[] serial = new byte[16]; - Array.Copy(array, 12, serial, 0, 16); - Assert.AreEqual(System.Text.Encoding.UTF8.GetString(serial), System.Text.Encoding.UTF8.GetString(serial), - "Serial Number of the Generated ID"); - } - - public bool VerifySequence(string input1, string input2) - { - byte[] array1 = Encoding.ASCII.GetBytes(input1); - Assert.False(array1.Length < 28); - byte[] array2 = Encoding.ASCII.GetBytes(input2); - Assert.False(array2.Length < 28); - Assert.AreNotEqual(input1, input2); - string incrementedString = Increment(input1, Mode.AlphaNumeric); - if (incrementedString.Equals(input2)) - { - return true; - } - else - { - return false; - } - } - public static string Increment(string text, Mode mode) - { - var textArr = text.ToCharArray(); - var characters = new List(); - - if (mode == Mode.AlphaNumeric || mode == Mode.Numeric) - for (char c = '0'; c <= '9'; c++) - characters.Add(c); - - if (mode == Mode.AlphaNumeric || mode == Mode.Alpha) - for (char c = 'a'; c <= 'f'; c++) - characters.Add(c); - - // Loop from end to beginning - for (int i = textArr.Length - 1; i >= 0; i--) - { - if (textArr[i] == characters.Last()) - { - textArr[i] = characters.First(); - } - else - { - textArr[i] = characters[characters.IndexOf(textArr[i]) + 1]; - break; - } - } - - return new string(textArr); - } - public enum Mode - { - AlphaNumeric = 1, - Alpha = 2, - Numeric = 3 - } - - #endregion Methods - } -} +// Copyright © 2015, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySql.Data; +using MySql.Data.Common; +using MySql.Data.MySqlClient; +using MySqlX.Common; +using MySqlX.XDevAPI; +using MySqlX.XDevAPI.Common; +using MySqlX.XDevAPI.CRUD; +using MySqlX.XDevAPI.Relational; +using NUnit.Framework; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace MySqlX.Data.Tests +{ + public class CrudInsertTests : BaseTest + { + [Test] + public void InsertSingleDbDocWithId() + { + Collection coll = CreateCollection("test"); + Result r = ExecuteAddStatement(coll.Add(@"{ ""_id"": 1, ""foo"": 1 }")); + Assert.AreEqual(1, r.AffectedItemsCount); + Assert.AreEqual(1, coll.Count()); + } + + [Test] + public void InsertSingleDbDocWithoutId() + { + Collection coll = CreateCollection("test"); + var stmt = coll.Add("{ \"foo\": 1 }"); + if (!session.Version.isAtLeast(8, 0, 5)) + { + // Code 5115 Document is missing a required field + Assert.AreEqual(5115u, Assert.Throws(() => ExecuteAddStatement(stmt)).Code); + return; + } + Result r = ExecuteAddStatement(stmt); + Assert.AreEqual(1, r.AffectedItemsCount); + Assert.AreEqual(1, coll.Count()); + Assert.That(r.GeneratedIds, Has.One.Items); + Assert.False(string.IsNullOrWhiteSpace(r.GeneratedIds[0])); + } + + [Test] + public void InsertMultipleDbDocWithoutId() + { + Collection coll = CreateCollection("test"); + var stmt = coll.Add("{ \"foo\": 1 }") + .Add("{ \"amber\": 2 }") + .Add("{ \"any\": 3 }"); + if (!session.Version.isAtLeast(8, 0, 5)) + { + // Code 5115 Document is missing a required field + Assert.AreEqual(5115u, Assert.Throws(() => ExecuteAddStatement(stmt)).Code); + return; + } + Result r = ExecuteAddStatement(stmt); + Assert.AreEqual(3, r.AffectedItemsCount); + Assert.AreEqual(3, coll.Count()); + Assert.AreEqual(3, r.GeneratedIds.Count); + } + + [Test] + public void InsertAnonymousObjectWithId() + { + var obj = new { _id = "5", name = "Sakila", age = 15 }; + + Collection coll = CreateCollection("test"); + Result r = ExecuteAddStatement(coll.Add(obj)); + Assert.AreEqual(1, r.AffectedItemsCount); + //TODO: pull object and verify data + Assert.AreEqual(1, coll.Count()); + } + + [Test] + public void InsertAnonymousObjectWithNoId() + { + var obj = new { name = "Sakila", age = 15 }; + + Collection coll = CreateCollection("test"); + var stmt = coll.Add(obj); + if (!session.Version.isAtLeast(8, 0, 5)) + { + // Code 5115 Document is missing a required field + Assert.AreEqual(5115u, Assert.Throws(() => ExecuteAddStatement(stmt)).Code); + return; + } + Result r = ExecuteAddStatement(stmt); + Assert.AreEqual(1, r.AffectedItemsCount); + //TODO: pull object and verify data + Assert.AreEqual(1, coll.Count()); + Assert.That(r.GeneratedIds, Has.One.Items); + Assert.False(string.IsNullOrWhiteSpace(r.GeneratedIds[0])); + } + + [Test] + public void InsertMultipleAnonymousObjectsWithId() + { + Collection coll = CreateCollection("test"); + var docs = new[] + { + new { _id = 1, title = "Book 1", pages = 20 }, + new { _id = 2, title = "Book 2", pages = 30 }, + new { _id = 3, title = "Book 3", pages = 40 }, + new { _id = 4, title = "Book 4", pages = 50 }, + }; + Result r = ExecuteAddStatement(coll.Add(docs)); + Assert.AreEqual(4, r.AffectedItemsCount); + Assert.AreEqual(4, coll.Count()); + } + + [Test] + public void ValidatesDocumentIds() + { + Collection coll = CreateCollection("test"); + var stmt = coll.Add(new { name = "Book 1" }); + if (!session.Version.isAtLeast(8, 0, 5)) + { + // Code 5115 Document is missing a required field + Assert.AreEqual(5115u, Assert.Throws(() => ExecuteAddStatement(stmt)).Code); + return; + } + Result result = ExecuteAddStatement(stmt); + Assert.AreEqual(1, result.AffectedItemsCount); + + result = ExecuteModifyStatement(coll.Modify($"_id = '{result.GeneratedIds[0]}'").Set("pages", "20")); + Assert.AreEqual(1, result.AffectedItemsCount); + CollectionAssert.IsEmpty(result.GeneratedIds); + } + + [Test] + public void ReuseStatement() + { + Collection coll = CreateCollection("test"); + var docs = new[] + { + new { _id = 1, title = "Book 1", pages = 20 }, + new { _id = 2, title = "Book 2", pages = 30 }, + new { _id = 3, title = "Book 3", pages = 40 }, + new { _id = 4, title = "Book 4", pages = 50 }, + }; + var stmt = coll.Add(new { _id = 0 }); + foreach (var doc in docs) + { + stmt.Add(doc); + } + Result r = ExecuteAddStatement(stmt); + Assert.AreEqual((ulong)docs.Length + 1, r.AffectedItemsCount); + Assert.AreEqual(5, coll.Count()); + } + + [Test] + public void EmptyDocArray() + { + Collection coll = CreateCollection("test"); + + var insertResult = ExecuteAddStatement(coll.Add(new DbDoc[] { })); + Assert.AreEqual(0ul, insertResult.AffectedItemsCount); + + var result = ExecuteFindStatement(coll.Find()).FetchAll(); + CollectionAssert.IsEmpty(result); + } + + [Test] + public void NullParameter() + { + Collection coll = CreateCollection("test"); + + Assert.Throws(() => ExecuteAddStatement(coll.Add(null))); + } + + [Test] + public void InsertingArray() + { + var docs = new[] + { + new { id = 1, title = "Book 1" }, + new { id = 2, title = "Book 2" }, + }; + DbDoc d2 = new DbDoc(); + d2.SetValue("_id", 1); + d2.SetValue("books", docs); + d2.SetValue("pages", 20); + + Collection coll = CreateCollection("test"); + ExecuteAddStatement(coll.Add(d2)); + var result = ExecuteFindStatement(coll.Find()).FetchAll(); + Assert.That(result, Has.One.Items); + Assert.AreEqual(d2.ToString(), result[0].ToString()); + } + + [Test] + public void CompareGuids() + { + Guid guid1 = new Guid(); + Guid guid2 = new Guid(); + Assert.AreEqual(0, Tools.CompareGuids(guid1, guid2)); + Assert.AreEqual(0, Tools.CompareGuids(guid1.ToString(), guid2.ToString())); + + guid1 = Guid.NewGuid(); + guid2 = Guid.NewGuid(); + Assert.True(Tools.CompareGuids(guid1, guid2) != 0); + Assert.True(Tools.CompareGuids(guid1.ToString(), guid2.ToString()) != 0); + } + + [Test] + public void InsertNullValuesAsDbDoc() + { + Collection collection = CreateCollection("test"); + + var nullValues = new String[] { null, "null", "NULL" }; + var docs = new DbDoc[3]; + for (int i = 0; i < docs.Length; i++) + { + docs[i] = new DbDoc(); + docs[i].SetValue("a", nullValues[i]); + docs[i].SetValue("_id", (i + 1)); + } + + ExecuteAddStatement(collection.Add(docs)); + var result = ExecuteFindStatement(collection.Find()).FetchAll(); + Assert.AreEqual(docs.Length, result.Count); + + for (int i = 0; i < docs.Length; i++) + Assert.AreEqual(docs[i].ToString(), result[i].ToString()); + } + + [Test] + public void InsertNullValuesAsJson() + { + var docs = new[] + { + @"{ ""_id"": 1, ""foo"": null}", + @"{ ""_id"": 2, ""foo"": null }", + @"{ ""_id"": 3, ""foo"": ""null"" }", + @"{ ""_id"": 4, ""foo"": ""NULL"" }", + }; + + Collection collection = CreateCollection("test"); + ExecuteAddStatement(collection.Add(docs)); + var result = ExecuteFindStatement(collection.Find()).FetchAll(); + Assert.AreEqual(docs.Length, result.Count); + for (int i = 0; i < docs.Length; i++) + { + var currentDoc = new DbDoc(docs[i]); + var resultingDoc = new DbDoc(result[i]); + Assert.AreEqual(currentDoc.Id, resultingDoc.Id); + Assert.AreEqual(currentDoc["foo"], resultingDoc["foo"]); + } + } + + [Test] + public void AddOrReplaceOne() + { + if (!session.Version.isAtLeast(8, 0, 3)) return; + + Collection collection = CreateCollection("test"); + var docs = new[] + { + new { _id = 1, title = "Book 1", pages = 20 }, + new { _id = 2, title = "Book 2", pages = 30 }, + new { _id = 3, title = "Book 3", pages = 40 }, + new { _id = 4, title = "Book 4", pages = 50 }, + }; + Result result = ExecuteAddStatement(collection.Add(docs)); + Assert.AreEqual(4, result.AffectedItemsCount); + + // Add a document. + Assert.AreEqual(1, collection.AddOrReplaceOne(5, new { _id = 5, title = "Book 5", pages = 60 }).AffectedItemsCount); + Assert.True(collection.GetOne(5) != null); + + Assert.AreEqual(1, collection.AddOrReplaceOne("6", new { title = "Book 6", pages = 70 }).AffectedItemsCount); + Assert.True(collection.GetOne(6) != null); + Assert.True(collection.GetOne("6") != null); + + // Replace a document. + Assert.AreEqual(2, collection.AddOrReplaceOne(1, new { _id = 1, title = "Book X", pages = 10 }).AffectedItemsCount); + DbDoc document = collection.GetOne(1); + Assert.AreEqual(1, Convert.ToInt32(document.Id)); + Assert.AreEqual("Book X", document["title"]); + Assert.AreEqual(10, Convert.ToInt32(document["pages"])); + + Assert.AreEqual(2, collection.AddOrReplaceOne(1, new { title = "Book Y", pages = 9, other = "value" }).AffectedItemsCount); + document = collection.GetOne(1); + Assert.AreEqual(1, Convert.ToInt32(document.Id)); + Assert.AreEqual("Book Y", document["title"]); + Assert.AreEqual(9, Convert.ToInt32(document["pages"])); + Assert.AreEqual("value", document["other"]); + + // Expected exceptions. + Assert.Throws(() => collection.AddOrReplaceOne(null, docs[1])); + Assert.Throws(() => collection.AddOrReplaceOne("", docs[1])); + Assert.Throws(() => collection.AddOrReplaceOne(" ", docs[1])); + Assert.Throws(() => collection.AddOrReplaceOne(string.Empty, docs[1])); + Assert.Throws(() => collection.AddOrReplaceOne("1", null)); + Assert.Throws(() => collection.AddOrReplaceOne(4, new DbDoc("{ \"_id\": 2, \"title\": \"Book\", \"pages\": 60 }")), + ResourcesX.ReplaceWithNoMatchingId); + } + + #region WL14389 + + [Test, Description("Test MySQLX plugin Collection Scenarios - with Create a valid collection and reuse existing object")] + public void CreateCollectionAndReuseObject() + { + using (Session sessionPlain = MySQLX.GetSession(ConnectionString)) + { + var col = CreateCollection("my_collection_123456789"); + object[] data = new object[] + { + new { _id = 1, title = "Book 1", pages = 20 }, + new { _id = 2, title = "Book 2", pages = 30 }, + new { _id = 3, title = "Book 3", pages = 40 }, + new { _id = 4, title = "Book 4", pages = 50 }, + }; + Result result = col.Add(data).Execute(); + var data1 = col.Remove("_id = 1").Execute(); + Assert.AreEqual(1, (int)data1.AffectedItemsCount, "Matching the deleted record count"); + data1 = col.Remove("_id = 2").Execute(); + Assert.AreEqual(1, (int)data1.AffectedItemsCount, "Matching the deleted record count"); + data1 = col.Remove("_id = 3").Execute(); + Assert.AreEqual(1, (int)data1.AffectedItemsCount, "Matching the deleted record count"); + data1 = col.Remove("_id = 4").Execute(); + Assert.AreEqual(1, (int)data1.AffectedItemsCount, "Matching the deleted record count"); + sessionPlain.Close(); + } + } + + [Test, Description("Collection Scenarios - with Create a collection with emptyname")] + public void CreateCollectionEmptyName() + { + Schema db = session.GetSchema(schemaName); + Assert.Throws(() => db.CreateCollection(null)); + } + + [Test, Description("Test MySQLX plugin Collection Scenarios - with Create a collection which exists without reuse existing object")] + public void CreateCollectionWithoutReuseExistingObject() + { + Schema db = session.GetSchema(schemaName); + var col = CreateCollection("my_collection_123456789"); + col = db.GetCollection("my_collection_123456789", true); + Assert.IsNotNull(col); + Assert.Throws(() => db.CreateCollection("my_collection_123456789", false)); + } + + [Test, Description("Test MySQLX plugin Collection Scenarios - Add Objects,Find with condition")] + public void CollectionAddObjectsFindCondition() + { + Schema db = session.GetSchema(schemaName); + Collection col = CreateCollection("my_collection_1"); + var docs = new[] + { + new { _id = 1, title = "Book 1", pages = 20 }, + new { _id = 2, title = "Book 2", pages = 30 }, + new { _id = 3, title = "Book 3", pages = 40 }, + new { _id = 4, title = "Book 4", pages = 50 }, + }; + Result result = col.Add(docs).Execute(); + + Assert.AreEqual(4, (int)result.AffectedItemsCount, "Matching the updated record count"); + var foundDocs = col.Find("pages > 20").Execute(); + Assert.AreEqual(true, foundDocs.Next(), "Next Node Exist"); + Assert.AreEqual("Book 2", foundDocs.Current["title"], "Matching the Node Value"); + Assert.AreEqual(true, foundDocs.Next(), "Next Node Exist"); + Assert.AreEqual("Book 3", foundDocs.Current["title"], "Matching the Node Value"); + Assert.AreEqual(true, foundDocs.Next(), "Next Node Exist"); + Assert.AreEqual("Book 4", foundDocs.Current["title"], "Matching the Node Value"); + Assert.AreEqual(false, foundDocs.Next(), "Next Node doesnot Exist"); + db.DropCollection("my_collection_1"); + } + + [Test, Description("Test MySQLX plugin Collection Scenarios - Add Objects,Find without parameters")] + public void CollectionAddFindNoParams() + { + if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher."); + Collection col = CreateCollection("my_collection_1"); + var docs = new[] + { + new { _id = 1, title = "Book 1", pages = 20 }, + new { _id = 2, title = "Book 2", pages = 30 }, + new { _id = 3, title = "Book 3", pages = 40 }, + new { _id = 4, title = "Book 4", pages = 50 }, + }; + + var result = col.Add(docs).Execute(); + Assert.AreEqual(4, (int)result.AffectedItemsCount, "Matching the updated record count"); + var foundDocs = col.Find().Execute(); + Assert.AreEqual(true, foundDocs.Next(), "Next Node Exist"); + Assert.AreEqual("Book 1", foundDocs.Current["title"], "Matching the Node Value"); + Assert.AreEqual(true, foundDocs.Next(), "Next Node Exist"); + Assert.AreEqual("Book 2", foundDocs.Current["title"], "Matching the Node Value"); + Assert.AreEqual(true, foundDocs.Next(), "Next Node Exist"); + Assert.AreEqual("Book 3", foundDocs.Current["title"], "Matching the Node Value"); + Assert.AreEqual(true, foundDocs.Next(), "Next Node Exist"); + Assert.AreEqual("Book 4", foundDocs.Current["title"], "Matching the Node Value"); + Assert.AreEqual(false, foundDocs.Next(), "Next Node doesnot Exist"); + } + + [Test, Description("Test MySQLX plugin Collection Scenarios - Add/Remove JSON Object with id")] + public void CollectionAddRemoveJSONObjectID() + { + if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher."); + using (var sessionPlain = MySQLX.GetSession(ConnectionString + ";sslmode=" + MySqlSslMode.Required)) + { + Schema db = sessionPlain.GetSchema(schemaName); + Collection col = CreateCollection("my_collection_1"); + DbDoc DbDocs = new DbDoc(); + DbDocs.SetValue("_id", "0"); + DbDocs.SetValue("title", "Book 0"); + DbDocs.SetValue("pages", "10"); + var result = col.Add(DbDocs).Execute(); + Assert.AreEqual(1, (int)result.AffectedItemsCount, "Matching the updated record count"); + DbDoc jsonremovedoc = new DbDoc(); + jsonremovedoc.SetValue("_id", "0"); + var foundDocs = col.Remove("_id='0'").Execute(); + Assert.AreEqual(1, (int)foundDocs.AffectedItemsCount, "Matching the deleted record count"); + db.DropCollection("my_collection_1"); + sessionPlain.Close(); + } + } + + [Test, Description("Test MySQLX plugin Collection Scenarios - Add/Remove with condition")] + public void CollectionAddRemoveJSONObjectCondition() + { + if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher."); + Schema db = session.GetSchema(schemaName); + Collection col = CreateCollection("my_collection_1"); + DbDoc DbDocs = new DbDoc(); + DbDocs.SetValue("_id", "0"); + DbDocs.SetValue("title", "Book 0"); + DbDocs.SetValue("pages", "10"); + var result = col.Add(DbDocs).Execute(); + Assert.AreEqual(1, (int)result.AffectedItemsCount, "Matching the updated record count"); + var foundDocs = col.Remove("pages > 0").Execute(); + Assert.AreEqual(1, (int)foundDocs.AffectedItemsCount, "Matching the deleted record count"); + db.DropCollection("my_collection_1"); + } + + [Test, Description("Test MySQLX plugin Collection Scenarios - Add,Remove with condition limit")] + public void CollectionAddRemoveObjectConditionLimit() + { + if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher."); + Schema db = session.GetSchema(schemaName); + Collection col = CreateCollection("my_collection_1"); + var docs = new[] + { + new { _id = 0, title = "Book 0", pages = 10 }, + new { _id = 1, title = "Book 1", pages = 20 }, + new { _id = 2, title = "Book 2", pages = 30 }, + new { _id = 3, title = "Book 3", pages = 40 }, + new { _id = 4, title = "Book 4", pages = 50 }, + }; + var result = col.Add(docs).Execute(); + Assert.AreEqual(5, (int)result.AffectedItemsCount, "Matching the updated record count"); + var foundDocs = col.Remove("_id=1").Execute(); + Assert.AreEqual(1, (int)foundDocs.AffectedItemsCount, "Matching the deleted record count"); + docs = new[] + { + new { _id = 1, title = "Book 1", pages = 20 }, + }; + result = col.Add(docs).Execute(); + Assert.AreEqual(1, (int)result.AffectedItemsCount, "Matching the updated record count"); + result = col.Remove("pages > 10").Limit(1).Execute(); + Assert.AreEqual(1, (int)result.AffectedItemsCount, "Matching the updated record count"); + result = col.Remove("pages > 10").Limit(3).Execute(); + Assert.AreEqual(3, (int)result.AffectedItemsCount, "Matching the updated record count"); + Assert.Throws(() => col.Remove("pages > 10").Limit(0).Execute()); + db.DropCollection("my_collection_1"); + } + + [Test, Description("Test MySQLX plugin Collection Scenarios - Add/Remove 200 JSON records ")] + public void CollectionAddRemove200JSONRecords() + { + if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher."); + Collection col = CreateCollection("my_collection_1"); + var numOfRecords = 200; + + DbDoc[] jsonlist = new DbDoc[numOfRecords]; + for (int i = 0; i < numOfRecords; i++) + { + DbDoc newDoc2 = new DbDoc(); + newDoc2.SetValue("_id", (i + 1000).ToString()); + newDoc2.SetValue("F1", ("Field-1-Data-" + i)); + newDoc2.SetValue("F2", ("Field-2-Data-" + i)); + newDoc2.SetValue("F3", (300 + i).ToString()); + jsonlist[i] = newDoc2; + newDoc2 = null; + } + var res = col.Add(jsonlist).Execute(); + + Assert.AreEqual(jsonlist[0].ToString(), jsonlist[0].ToString(), "String Match being done"); + for (int i = 0; i < numOfRecords; i++) + { + var data1 = col.Remove($"_id = '{i + 1000}'").Execute(); + Assert.AreEqual(1, (int)data1.AffectedItemsCount, "Matching the deleted record count"); + } + } + + [Test, Description("Test MySQLX plugin Collection Scenarios - Add/Remove documents with limit and orderby ")] + public void CollectionAddRemoveJSONRecordsLimitOrderBy() + { + if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher."); + Schema db = session.GetSchema(schemaName); + Collection col = CreateCollection("my_collection_1"); + + DbDoc[] jsonlist = new DbDoc[10]; + for (int i = 0; i < 10; i++) + { + DbDoc newDoc2 = new DbDoc(); + newDoc2.SetValue("_id", (i).ToString()); + newDoc2.SetValue("F1", ("Field-1-Data-" + i)); + newDoc2.SetValue("F2", ("Field-2-Data-" + i)); + newDoc2.SetValue("F3", (300 + i)); + jsonlist[i] = newDoc2; + newDoc2 = null; + } + col.Add(jsonlist).Execute(); + Assert.AreEqual(jsonlist[0].ToString(), jsonlist[0].ToString(), "String Match being done"); + + Result result = col.Remove("F3 > 305").Limit(1).Execute(); + Assert.AreEqual(1, (int)result.AffectedItemsCount, "Match being done"); + + result = col.Remove("F3 > 303").Sort("F3 DESC").Execute(); + Assert.AreEqual(5, (int)result.AffectedItemsCount, "Match being done"); + + result = col.Remove("F3 > 303").Sort("F3 DESC").Execute(); + Assert.AreEqual(0, (int)result.AffectedItemsCount, "Match being done"); + + result = col.Remove("F3 = 303").Sort("F2 DESC").Execute(); + Assert.AreEqual(1, (int)result.AffectedItemsCount, "Match being done"); + + result = col.Remove("F3 < 301").Sort("F2 DESC").Execute(); + Assert.AreEqual(1, (int)result.AffectedItemsCount, "Match being done"); + + result = col.Remove("F3 < 301").Sort("F2 DESC").Execute(); + Assert.AreEqual(0, (int)result.AffectedItemsCount, "Match being done"); + + db.DropCollection("my_collection_1"); + + } + + [Test, Description("Test MySQLX plugin Collection Scenarios - Add Single/Multiple Docs - Remove Condition/ID/Condition-Limit/Condition-Limit-OrderBy/Bind")] + public void CollectionAddRemoveDocsLimitOrderByBind() + { + if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher."); + Collection col = CreateCollection("my_collection_1"); + DbDoc DbDocs = new DbDoc(); + DbDocs.SetValue("_id", 100000); + DbDocs.SetValue("title", "Book 0"); + DbDocs.SetValue("pages", 10); + var result = col.Add(DbDocs).Execute(); + Assert.AreEqual(1, (int)result.AffectedItemsCount, "Matching the updated record count"); + var foundDocs = col.Remove("pages > 0").Execute(); + Assert.AreEqual(1, (int)foundDocs.AffectedItemsCount, "Matching the deleted record count"); + + var docs = new { _id = 100001, title = "Book 1", pages = 20 }; + result = col.Add(docs).Execute(); + Assert.AreEqual(1, (int)result.AffectedItemsCount, "Matching the updated record count"); + + foundDocs = col.Remove("pages=20").Execute(); + Assert.AreEqual(1, (int)foundDocs.AffectedItemsCount, "Matching the deleted record count"); + + docs = new { _id = -100001, title = "Book 1", pages = 20 }; + result = col.Add(docs).Execute(); + Assert.AreEqual(1, (int)result.AffectedItemsCount, "Matching the updated record count"); + + foundDocs = col.Remove("pages=20").Execute(); + Assert.AreEqual(1, (int)foundDocs.AffectedItemsCount, "Matching the deleted record count"); + var docs1 = new[] + { + new { _id = -100001, title = "Book 0", pages = 10 }, + new { _id = 0, title = "Book 1", pages = 20 }, + new { _id = 100001, title = "Book 2", pages = 30 }, + new { _id = 10000001, title = "Book 3", pages = 40 } + }; + result = col.Add(docs1).Execute(); + Assert.AreEqual(4, (int)result.AffectedItemsCount, "Matching the updated record count"); + + foundDocs = col.Remove("pages > 10").Execute(); + Assert.AreEqual(3, (int)foundDocs.AffectedItemsCount, "Matching the deleted record count"); + + foundDocs = col.Remove("pages=10").Execute(); + Assert.AreEqual(1, (int)foundDocs.AffectedItemsCount, "Matching the deleted record count"); + docs1 = new[] + { + new { _id = -100001, title = "Book 0", pages = 10 }, + new { _id = 0, title = "Book 1", pages = 20 }, + new { _id = 100001, title = "Book 2", pages = 30 }, + new { _id = 10000001, title = "Book 3", pages = 40 }, + new { _id = 10000009, title = "Book 4", pages = 50 } + }; + result = col.Add(docs1).Execute(); + Assert.AreEqual(5, (int)result.AffectedItemsCount, "Matching the updated record count"); + + foundDocs = col.Remove("pages = 40").Execute(); + Assert.AreEqual(1, (int)foundDocs.AffectedItemsCount, "Matching the deleted record count"); + + foundDocs = col.Remove("pages >= 10").Execute(); + Assert.AreEqual(4, (int)foundDocs.AffectedItemsCount, "Matching the deleted record count"); + + result = col.Add(docs1).Execute(); + Assert.AreEqual(5, (int)result.AffectedItemsCount, "Matching the updated record count"); + foundDocs = col.Remove("pages = 40").Limit(1).Execute(); + Assert.AreEqual(1, (int)foundDocs.AffectedItemsCount, "Matching the deleted record count"); + foundDocs = col.Remove("pages <= 50").Execute(); + Assert.AreEqual(4, (int)foundDocs.AffectedItemsCount, "Matching the deleted record count"); + + result = col.Add(docs1).Execute(); + Assert.AreEqual(5, (int)result.AffectedItemsCount, "Matching the updated record count"); + foundDocs = col.Remove("pages = 40").Limit(1).Sort("title").Execute(); + Assert.AreEqual(1, (int)foundDocs.AffectedItemsCount, "Matching the deleted record count"); + foundDocs = col.Remove("pages <= 50").Execute(); + Assert.AreEqual(4, (int)foundDocs.AffectedItemsCount, "Matching the deleted record count"); + + docs1 = new[] + { + new { _id = 1, title = "Book 1", pages = 20 }, + new { _id = 2, title = "Book 2", pages = 30 }, + new { _id = 3, title = "Book 3", pages = 40 }, + new { _id = 4, title = "Book 4", pages = 50 }, + }; + + result = col.Add(docs1).Execute(); + Assert.AreEqual(4, (int)result.AffectedItemsCount, "Matching the updated record count"); + foundDocs = col.Remove("pages = :Pages").Bind("pAges", 50).Execute(); + Assert.AreEqual(1, (int)foundDocs.AffectedItemsCount, "Matching the deleted record count"); + } + + [Test, Description("Test MySQLX plugin Collection Scenarios - Add Single/Multiple Docs - Remove Condition/ID/Condition-Limit/Condition-Limit-OrderBy/Bind using invalid conditions")] + public void CollectionRemoveDocsLimitOrderByBindNegative() + { + if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher."); + Schema db = session.GetSchema(schemaName); + var col = db.CreateCollection("my_collection_1", true); + + DbDoc DbDocs = new DbDoc(); + DbDocs.SetValue("_id", 100000); + DbDocs.SetValue("title", "Book 0"); + DbDocs.SetValue("pages", 10); + var result = col.Add(DbDocs).Execute(); + + Assert.AreEqual(1, (int)result.AffectedItemsCount, "Matching the updated record count"); + var foundDocs = col.Remove("pages > 10").Execute(); + Assert.AreEqual(0, (int)foundDocs.AffectedItemsCount, "Matching the deleted record count"); + + var docs = new { _id = 100001, title = "Book 1", pages = 20 }; + result = col.Add(docs).Execute(); + Assert.AreEqual(1, (int)result.AffectedItemsCount, "Matching the updated record count"); + + foundDocs = col.Remove("pages >= 10").Execute(); + Assert.AreEqual(2, (int)foundDocs.AffectedItemsCount, "Matching the deleted record count"); + + docs = new { _id = -100001, title = "Book 1", pages = 20 }; + result = col.Add(docs).Execute(); + Assert.AreEqual(1, (int)result.AffectedItemsCount, "Matching the updated record count"); + + foundDocs = col.Remove("pages > 10").Execute(); + Assert.AreEqual(1, (int)foundDocs.AffectedItemsCount, "Matching the deleted record count"); + + + var docs1 = new[] + { + new { _id = -100001, title = "Book 0", pages = 10 }, + new { _id = 0, title = "Book 1", pages = 20 }, + new { _id = 100001, title = "Book 2", pages = 30 }, + new { _id = 10000001, title = "Book 3", pages = 40 } + }; + result = col.Add(docs1).Execute(); + Assert.AreEqual(4, (int)result.AffectedItemsCount, "Matching the updated record count"); + + foundDocs = col.Remove("pages > 50").Execute(); + Assert.AreEqual(0, (int)foundDocs.AffectedItemsCount, "Matching the deleted record count"); + + foundDocs = col.Remove("pages < 50").Execute(); + Assert.AreEqual(4, (int)foundDocs.AffectedItemsCount, "Matching the deleted record count"); + + docs1 = new[] + { + new { _id = -100001, title = "Book 0", pages = 10 }, + new { _id = 0, title = "Book 1", pages = 20 }, + new { _id = 100001, title = "Book 2", pages = 30 }, + new { _id = 10000001, title = "Book 3", pages = 40 }, + new { _id = 10000009, title = "Book 4", pages = 50 } + }; + result = col.Add(docs1).Execute(); + Assert.AreEqual(5, (int)result.AffectedItemsCount, "Matching the updated record count"); + + foundDocs = col.Remove("pages = 0").Execute(); + Assert.AreEqual(0, (int)foundDocs.AffectedItemsCount, "Matching the deleted record count"); + + foundDocs = col.Remove("pages <= 50").Execute(); + Assert.AreEqual(5, (int)foundDocs.AffectedItemsCount, "Matching the deleted record count"); + + result = col.Add(docs1).Execute(); + Assert.AreEqual(5, (int)result.AffectedItemsCount, "Matching the updated record count"); + foundDocs = col.Remove("pages = 60").Limit(1).Execute(); + Assert.AreEqual(0, (int)foundDocs.AffectedItemsCount, "Matching the deleted record count"); + + foundDocs = col.Remove("pages <= 50").Execute(); + Assert.AreEqual(5, (int)foundDocs.AffectedItemsCount, "Matching the deleted record count"); + + result = col.Add(docs1).Execute(); + Assert.AreEqual(5, (int)result.AffectedItemsCount, "Matching the updated record count"); + foundDocs = col.Remove("pages = 04").Limit(1).Sort("title").Execute(); + Assert.AreEqual(0, (int)foundDocs.AffectedItemsCount, "Matching the deleted record count"); + foundDocs = col.Remove("pages <= 50").Execute(); + Assert.AreEqual(5, (int)foundDocs.AffectedItemsCount, "Matching the deleted record count"); + + docs1 = new[] + { + new { _id = 1, title = "Book 1", pages = 20 }, + new { _id = 2, title = "Book 2", pages = 30 }, + new { _id = 3, title = "Book 3", pages = 40 }, + new { _id = 4, title = "Book 4", pages = 50 }, + }; + + result = col.Add(docs1).Execute(); + Assert.AreEqual(4, (int)result.AffectedItemsCount, "Matching the updated record count"); + foundDocs = col.Remove("pages1 = :Pages").Bind("pAges", 50).Execute(); + Assert.AreEqual(0, (int)foundDocs.AffectedItemsCount, "Matching the deleted record count"); + foundDocs = col.Remove("pages = :Pages").Bind("pAges", 51).Execute(); + Assert.AreEqual(0, (int)foundDocs.AffectedItemsCount, "Matching the deleted record count"); + foundDocs = col.Remove("pages = :Pages").Bind("pAges", 50).Execute(); + Assert.AreEqual(1, (int)foundDocs.AffectedItemsCount, "Matching the deleted record count"); + db.DropCollection("my_collection_1"); + + } + + [Test, Description("Test MySQLX plugin - MYSQLCNET_680 Allow Reuse Statement after execute Positive1(after a succesful execute)")] + public void AllowReuseStatementAfterExecutePositive1() + { + if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher."); + Schema db = session.GetSchema(schemaName); + var col = db.CreateCollection("my_collection_123456789"); + object[] data = new object[] + { + new { _id = 1, title = "Book 1", pages = 10 }, + new { _id = 2, title = "Book 2", pages = 20 }, + new { _id = 3, title = "Book 3", pages = 30 }, + new { _id = 4, title = "Book 4", pages = 40 }, + new { _id = 5, title = "Book 5", pages = 50 }, + new { _id = 6, title = "Book 6", pages = 60 }, + new { _id = 7, title = "Book 7", pages = 70 }, + new { _id = 8, title = "Book 8", pages = 80 }, + }; + Result result = col.Add(data).Execute(); + Assert.AreEqual(8, (int)result.AffectedItemsCount, "Matching the added record count"); + var data1 = col.Remove("_id=1").Execute(); + Assert.AreEqual(1, (int)data1.AffectedItemsCount, "Matching the deleted record count"); + data1 = col.Remove("pages = :Pages").Bind("pAges", 80).Execute(); + Assert.AreEqual(1, (int)data1.AffectedItemsCount, "Matching the deleted record count"); + data1 = col.Remove("pages = :Pages").Bind("pAges", 70).Execute(); + Assert.AreEqual(1, (int)data1.AffectedItemsCount, "Matching the deleted record count"); + var remData = col.Remove("_id = :param1 AND title = :param2"); + data1 = remData.Bind("param1", 5).Bind("param2", "Book 5").Execute(); + Assert.AreEqual(1, (int)data1.AffectedItemsCount, "Matching the deleted record count"); + data1 = remData.Bind("param1", 6).Bind("param2", "Book 6").Execute(); + Assert.AreEqual(1, (int)data1.AffectedItemsCount, "Matching the deleted record count"); + db.DropCollection("my_collection_123456789"); + } + + [Test, Description("Test MySQLX plugin - MYSQLCNET_680 Allow Reuse Statement after execute-Positive2(after an unsuccessful execute)")] + public void AllowReuseStatementAfterExecutePositive2() + { + var col = CreateCollection("my_collection_123456789"); + object[] data = new object[] + { + new { _id = 1, title = "Book 1", pages = 10 }, + new { _id = 2, title = "Book 2", pages = 20 }, + new { _id = 3, title = "Book 3", pages = 30 }, + new { _id = 4, title = "Book 4", pages = 40 }, + new { _id = 5, title = "Book 5", pages = 50 }, + new { _id = 6, title = "Book 6", pages = 60 }, + new { _id = 7, title = "Book 7", pages = 70 }, + new { _id = 8, title = "Book 8", pages = 80 }, + }; + Result result = col.Add(data).Execute(); + Assert.AreEqual(8, (int)result.AffectedItemsCount, "Matching the added record count"); + var data1 = col.Remove("_id=1").Execute(); + Assert.AreEqual(1, (int)data1.AffectedItemsCount, "Matching the deleted record count"); + data1 = col.Remove("pages = :Pages").Bind("pAges", 80).Execute(); + Assert.AreEqual(1, (int)data1.AffectedItemsCount, "Matching the deleted record count"); + data1 = col.Remove("pages = :Pages").Bind("pAges", 70).Execute(); + Assert.AreEqual(1, (int)data1.AffectedItemsCount, "Matching the deleted record count"); + var remData = col.Remove("_id = :param1 AND title = :param2"); + + data1 = remData.Bind("param1", 35).Bind("param2", "Book 33").Execute(); + Assert.AreEqual(0, (int)data1.AffectedItemsCount, "Matching the deleted record count"); + + data1 = remData.Bind("param1", 6).Bind("param2", "Book 6").Execute(); + Assert.AreEqual(1, (int)data1.AffectedItemsCount, "Matching the deleted record count"); + testSchema.DropCollection("my_collection_123456789"); + } + + [Test, Description("Test MySQLX plugin - MYSQLCNET 755 Collection GetDocumentID")] + public void CollectionGetDocumentID() + { + if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher."); + Collection coll = CreateCollection("test"); + var docs = new[] + { + new { _id = 100, title = "Book 100", pages = 1000 }, + }; + Result result = coll.Add(docs).Execute(); + var documentIds = result.GeneratedIds; + Assert.False(documentIds != null && documentIds.Count > 0); + + coll = CreateCollection("test"); + var docs1 = new[] + { + new { title = "Book 1", pages = 100 }, + }; + var r = coll.Add(docs1); + var result1 = r.Execute(); + var documentIds1 = result.GeneratedIds; + HashSet firstset = new HashSet(); + for (int i = 0; i < documentIds.Count; i++) + { + if (documentIds1 != null) + { + Assert.AreEqual(documentIds1[i].ToString(), documentIds1[i].ToString(), "Matching the document ID with unique id"); + } + if (!firstset.Add(documentIds1[i])) + { + break; + } + } + + coll = CreateCollection("test"); + docs = new[] + { + new { _id = 100, title = "Book 100", pages = 1000 }, + new { _id = 200, title = "Book 200", pages = 2000 }, + new { _id = 300, title = "Book 300", pages = 3000 }, + new { _id = 400, title = "Book 400", pages = 4000 }, + }; + + var r1 = coll.Add(docs).Execute(); + documentIds = r1.GeneratedIds; + Assert.False(documentIds != null && documentIds.Count > 0); + + coll = CreateCollection("test"); + docs1 = new[] + { + new { title = "Book 1", pages = 100 }, + new { title = "Book 2", pages = 200 }, + new { title = "Book 3", pages = 300 }, + new { title = "Book 4", pages = 400 }, + }; + + var stmt = coll.Add(docs1); + result1 = stmt.Execute(); + documentIds1 = result1.GeneratedIds; + firstset = new HashSet(); + for (int i = 0; i < documentIds1.Count; i++) + { + if (documentIds != null) + { + Assert.AreEqual(documentIds1[i].ToString(), documentIds1[i].ToString(), "Matching the document ID with unique id"); + } + + if (!firstset.Add(documentIds1[i])) + { + break; + } + } + } + + [Test, Description("Test MySQLX UUID Scenario-1(Check UUID is not generated when JSON doc is added using collection.add() with _id fields)")] + public void CheckDocUUIDScenario1() + { + var col = CreateCollection("my_collection_123456789"); + object[] data = new object[] + { + new { _id = 1, title = "Book 1", pages = 20 }, + new { _id = 2, title = "Book 2", pages = 30 }, + new { _id = 3, title = "Book 3", pages = 40 }, + new { _id = 4, title = "Book 4", pages = 50 }, + }; + Result result = col.Add(data).Execute(); + var documentIds = result.GeneratedIds; + Assert.False(documentIds != null && documentIds.Count > 0); + } + + [Test, Description("Test MySQLX UUID Scenario-2(Check UUID generated when multiple JSON docs are added using collection.add().add()..without _id fields)")] + public void CheckDocUUIDScenario2() + { + if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher."); + var col = CreateCollection("my_collection_123456789"); + object[] data1 = new object[] + { + new { title ="Book 1", pages = 20 }, + new { title = "Book 2", pages = 30 }, + new { title = "Book 3", pages = 40 }, + new { title = "Book 4", pages = 50 } + }; + + object[] data2 = new object[] + { + new { title = "Book 5", pages = 60 }, + new {title = "Book 6", pages = 70 }, + new { title = "Book 7", pages = 80 }, + new { title = "Book 8", pages = 90 }, + }; + var stmt = col.Add(data1).Add(data2); + var result = stmt.Execute(); + var documentIds = result.GeneratedIds; + HashSet firstset = new HashSet(); + for (int i = 0; i < documentIds.Count; i++) + { + if (documentIds != null) + { + Assert.AreEqual(documentIds[i].ToString(), documentIds[i].ToString(), "Matching the document ID with unique id"); + } + if (!firstset.Add(documentIds[i])) + { + Console.WriteLine("Contains duplicate ID"); + break; + } + } + } + + [Test, Description("Test MySQLX UUID Scenario-2(Check UUID generated when multiple JSON docs are added using collection.add(doc, doc, doc... ) without _id fields)")] + public void CheckDocUUIDScenario3() + { + if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher."); + var col = CreateCollection("my_collection_123456789"); + var stmt = col.Add(@"{ ""foo"": 1 }", @"{""foo"": 2 }", @"{ ""foo"": 3 }", @"{ ""foo"": 4 }"); + Result r = col.Add(@"{ ""foo"": 1 }", @"{""foo"": 2 }", @"{ ""foo"": 3 }", @"{ ""foo"": 4 }").Execute(); + long count = col.Count(); + Assert.AreEqual(count, 4, "Matching the Collection Count"); + var documentIds = r.GeneratedIds; + if (documentIds != null) + { + Assert.AreEqual(documentIds[0].ToString(), documentIds[0].ToString(), "Matching the document ID without unique id"); + Assert.AreEqual(documentIds[1].ToString(), documentIds[1].ToString(), "Matching the document ID without unique id"); + Assert.AreEqual(documentIds[2].ToString(), documentIds[2].ToString(), "Matching the document ID without unique id"); + Assert.AreEqual(documentIds[3].ToString(), documentIds[3].ToString(), "Matching the document ID without unique id"); + } + + var collectionName = col.Name; + Assert.AreEqual(collectionName, "my_collection_123456789", "Matching the collection Name"); + Assert.AreEqual(schemaName, col.Schema.Name, "Matching the Schema Name"); + } + + [Test, Description("Test MySQLX UUID Scenario-4(Check UUID generated when multiple JSON docs are added using some containing and some not containing _id fields)")] + public void CheckDocUUIDScenario4() + { + if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher."); + var col = CreateCollection("my_collection_123456789"); + object[] data1 = new object[] + { + new { _id = 1, title = "Book 1", pages = 20 }, + new { _id = 2, title = "Book 2", pages = 30 }, + new { _id = 3, title = "Book 3", pages = 40 }, + new { title = "Book 4", pages = 50 } + }; + + object[] data2 = new object[] + { + new { title = "Book 5", pages = 60 }, + new { _id = 6,title = "Book 6", pages = 70 }, + new { title = "Book 7", pages = 80 }, + new { title = "Book 8", pages = 90 }, + }; + + var stmt = col.Add(data1).Add(data2); + Result result = stmt.Execute(); + var documentIdsCount = result.GeneratedIds.Count; + var documentIds = result.GeneratedIds; + Assert.AreEqual(4, documentIdsCount, "Matching the document ID count"); + if (documentIds != null) + { + Assert.AreEqual(documentIds[0].ToString(), documentIds[0].ToString(), "Matching the document ID with unique id"); + Assert.AreEqual(documentIds[1].ToString(), documentIds[1].ToString(), "Matching the document ID with unique id"); + Assert.AreEqual(documentIds[2].ToString(), documentIds[2].ToString(), "Matching the document ID with unique id"); + Assert.AreEqual(documentIds[3].ToString(), documentIds[3].ToString(), "Matching the document ID without unique id"); + } + } + + [Test, Description("Test MySQLX UUID Scenario-5(Check that UUID is not generated by adding multiple doc from the same collection in a session with _id fields)")] + public void CheckDocUUIDScenario5() + { + Collection testCollection = CreateCollection("test"); + DbDoc[] jsonlist = new DbDoc[1000]; + for (int i = 0; i < 1000; i++) + { + DbDoc newDoc2 = new DbDoc(); + newDoc2.SetValue("_id", (i + 1000)); + newDoc2.SetValue("F1", ("Field-1-Data-" + i)); + newDoc2.SetValue("F2", ("Field-2-Data-" + i)); + newDoc2.SetValue("F3", (300 + i).ToString()); + jsonlist[i] = newDoc2; + newDoc2 = null; + } + Result r = testCollection.Add(jsonlist).Execute(); + Assert.AreEqual(1000, r.AffectedItemsCount, "Matching"); + var documentIds = r.GeneratedIds; + Assert.False(documentIds != null && documentIds.Count > 0); + + Schema testSchema = session.GetSchema(schemaName); + Table test = testSchema.GetCollectionAsTable("test"); + Assert.AreEqual(true, test.ExistsInDatabase(), "Matching"); + } + + [Test, Description("Test MySQLX UUID Scenario-6(Check that no duplicate UUID is generated by adding multiple doc from the same collection in a session when there are no _id fields)")] + public void CheckDocUUIDScenario6() + { + if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher."); + Collection testCollection = CreateCollection("test"); + DbDoc[] jsonlist = new DbDoc[1000]; + for (int i = 0; i < 1000; i++) + { + DbDoc newDoc2 = new DbDoc(); + newDoc2.SetValue("F1", ("Field-1-Data-" + i)); + newDoc2.SetValue("F2", ("Field-2-Data-" + i)); + newDoc2.SetValue("F3", (300 + i).ToString()); + jsonlist[i] = newDoc2; + newDoc2 = null; + } + + var r = testCollection.Add(jsonlist); + var result = r.Execute(); + var countgenerateIDs = result.GeneratedIds.Count; + Assert.AreEqual(1000, countgenerateIDs, "Count of the ID generated by the server"); + for (int i = 0; i < countgenerateIDs; i++) + { + var generatedIDs1 = result.GeneratedIds[i]; + Assert.AreEqual(generatedIDs1, generatedIDs1, "ID generated by the server"); + } + + Schema testSchema = session.GetSchema(schemaName); + Table test = testSchema.GetCollectionAsTable("test"); + Assert.AreEqual(true, test.ExistsInDatabase(), "Matching"); + } + + [Test, Description("Test MySQLX UUID Scenario-7(Check UUID generated when multiple JSON docs are added using collection.add(doc, doc, doc... ) when docs contains _id fields with negative numbers,big positive numbers)")] + public void CheckDocUUIDScenario7() + { + var col = CreateCollection("my_collection_123456789"); + object[] data1 = new object[] + { + new { _id = -1, title = "Book 1", pages = 20 }, + new { _id = 200000000, title = "Book 2", pages = 30 }, + new { _id = -300000000, title = "Book 3", pages = 40 }, + new { title = "Book 4", pages = 50 } + }; + + object[] data2 = new object[] + { + new { title = "Book 5", pages = 60 }, + new { _id = 60000000000000,title = "Book 6", pages = 70 }, + new { title = "Book 7", pages = 80 }, + new { title = "Book 8", pages = 90 }, + }; + + var r = col.Add(data1).Add(data2); + var result = r.Execute(); + var countgenerateIDs = result.GeneratedIds.Count; + Assert.AreEqual(4, countgenerateIDs, "Count of the ID generated by the server"); + for (int i = 0; i < countgenerateIDs; i++) + { + var generatedIDs1 = result.GeneratedIds[i]; + Assert.AreEqual(generatedIDs1, generatedIDs1, "ID generated by the server"); + } + + } + + [Test, Description("Test MySQLX UUID Scenario-8(Check UUID generated when multiple JSON docs are added using collection.add(doc, doc, doc... ) when docs contains _id fields with zero,strings)")] + public void CheckDocUUIDScenario8() + { + if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher."); + var col = CreateCollection("my_collection_123456789"); + object[] data1 = new object[] + { + new { _id = 0, title = "Book 1", pages = 20 }, + new { _id = "test1", title = "Book 2", pages = 30 }, + new { _id = "^%$^&&%)(*&", title = "Book 3", pages = 40 }, + new { title = "Book 4", pages = 50 } + }; + + object[] data2 = new object[] + { + new { title = "Book 5", pages = 60 }, + new { _id = 60000000000000,title = "Book 6", pages = 70 }, + new { title = "Book 7", pages = 80 }, + new { title = "Book 8", pages = 90 }, + }; + + var r = col.Add(data1).Add(data2); + var result = r.Execute(); + var countgenerateIDs = result.GeneratedIds.Count; + Assert.AreEqual(4, countgenerateIDs, "Count of the ID generated by the server"); + for (int i = 0; i < countgenerateIDs; i++) + { + var generatedIDs1 = result.GeneratedIds[i]; + Assert.AreEqual(generatedIDs1, generatedIDs1, "ID generated by the server"); + } + + } + + [Test, Description("Test MySQLX UUID Scenario-9(Check the behaviour when JSON docs are added using collection.add(doc) when docs contains _id fields with (blank)")] + public void CheckDocUUIDScenario9() + { + Collection testCollection = CreateCollection("test"); + DbDoc[] jsonlist = new DbDoc[1]; + for (int i = 0; i < 1; i++) + { + DbDoc newDoc2 = new DbDoc(); + newDoc2.SetValue("_id", " "); + newDoc2.SetValue("F1", ("Field-1-Data-" + i)); + newDoc2.SetValue("F2", ("Field-2-Data-" + i)); + newDoc2.SetValue("F3", (300 + i).ToString()); + jsonlist[i] = newDoc2; + } + + Result result = testCollection.Add(jsonlist).Execute(); + //ID with blank could be added as per bug#27627861 as client will not do any validation and server will do" + Assert.IsNotNull(result); + + Schema testSchema = session.GetSchema("test"); + Table test = testSchema.GetCollectionAsTable("test"); + Assert.AreEqual(true, test.ExistsInDatabase(), "Matching"); + } + + [Test, Description("Test MySQLX plugin Collection JSON Depth Scenarios")] + public void CollectionAddJSONDepth() + { + if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher."); + int i, maxArrayelement = 100; + Collection col = CreateCollection("my_collection_1"); + Collection col1 = CreateCollection("my_collection_2"); + + DbDoc d1 = new DbDoc(); + for (i = 0; i < maxArrayelement; i++) + { + d1.SetValue("_id" + "_" + i.ToString(), 10000); + d1.SetValue("person" + "_" + i.ToString(), "Person" + "_" + i.ToString()); + } + + var result = col1.Add(d1).Execute(); + Assert.Greater(result.AffectedItemsCount, 0); + + var data1 = new DbDoc(@"{ ""_id"": 1, ""pages"": 20, + ""person"": { ""name"": ""Fred"", ""age"": 45 } + }"); + var data2 = new DbDoc(@"{ ""_id"": 1, ""pages"": 20, + ""books"": [ + {""_id"" : 1, ""title"" : ""Book 1""}, + { ""_id"" : 2, ""title"" : ""Book 2"" } + ] + }"); + DbDoc d2 = new DbDoc(); + d2.SetValue("_id", 1); + d2.SetValue("pages", 20); + d2.SetValue("taker1", data1); + d2.SetValue("taker2", data2); + + result = col.Add(d2).Execute(); + Assert.Greater(result.AffectedItemsCount, 0); + + var result1 = col1.Find().Execute().FetchAll(); + Assert.AreEqual(1, result1.Count); + var result2 = col.Find().Execute().FetchAll(); + Assert.AreEqual(1, result2.Count); + } + + [Test, Description("Test MySQLX plugin Collection Add function with null")] + public void CollectionAddNullFind() + { + if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher."); + int i = 1; + Collection col = CreateCollection("my_collection_1"); + var d1 = new DbDoc(); + d1.SetValue("id" + "_" + i.ToString(), "test"); + Assert.AreEqual(1, col.Add(d1).Execute().AffectedItemsCount); + var result1 = col.Find(null).Execute(); + Assert.AreEqual(0, result1.AffectedItemsCount); + Assert.Throws(() => col.Add(null).Execute()); + var result2 = col.Add().Execute(); + Assert.AreEqual(0, result2.AffectedItemsCount); + } + + [Test, Description("Test MySQLX plugin Invalid JSON String")] + public void InvalidJSONString() + { + Collection col = CreateCollection("my_collection_1"); + String json = ""; + json = "{'_id':'1004','F1': [] }"; + Exception ex = Assert.Throws(() => col.Add(json).Execute()); + StringAssert.Contains("The value provided is not a valid JSON document", ex.Message); + } + + [Test, Description("Test MySQLX plugin JSON String long expression")] + public void JSONStringLongExpression() + { + if (Platform.IsMacOSX()) Assert.Ignore("Check failure on MacOS: stack overflow");// TO DO + + Collection col = CreateCollection("my_collection_1"); + String json = "", + query2 = ""; + json = "{\"_id\":\"1004\",\"F1\": 1234 }"; + col.Add(json).Execute(); + query2 = "-1+"; + for (int i = 0; i < 230; i++) + { + query2 = query2 + "("; + } + + query2 = query2 + "(100+2)"; + for (int i = 230; i > 0; i--) + { + query2 = query2 + ")"; + } + + var docs = col.Find().Fields(("{'X':" + query2 + "}")).Execute(); + var res = col.Modify("$.F1 = 1234").Set("F1", query2).Limit(1).Execute(); + Assert.AreEqual(1, res.AffectedItemsCount); + } + + [Test, Description("Test MySQLX plugin Binary Expression")] + public void BinaryExpression() + { + String json = ""; + Collection col = CreateCollection("my_collection_1"); + Collection col1 = CreateCollection("my_collection_2"); + json = "{\"_id\":\"1004\",\"F1\": 123,\"F2\":\"#\" }"; + col.Add(json).Execute(); + + var docs1 = col.Find().Fields("$._id as _id", "1 << 4 as tmp").Execute(); + var res = docs1.FetchAll(); + StringAssert.AreEqualIgnoringCase("1004", res[0].Id.ToString()); + + docs1 = col.Find().Fields("$._id as _id", "$.F2 ^ 1 as tmp").Execute(); + res = docs1.FetchAll(); + StringAssert.AreEqualIgnoringCase("1004", res[0].Id.ToString()); + col.Add("{\"_id\":\"100001\",\"x1\":\"31\", \"x2\":\"13\", \"x3\":\"8\", \"x4\":\"18446744073709551614\"}").Execute(); + docs1 = col.Find("CAST($.x1 as SIGNED) | pow(2,$.x1) = $.x1").Fields("$._id as _id, $.x1 as x1, $.x2 as x2, $.x3 as x3 , $.x2 | pow(2,$.x1) as tmp").Execute(); + res = docs1.FetchAll(); + Assert.IsNotNull(res); + docs1 = col.Find("~16 = ~CAST($.F2 as SIGNED)").Fields("$._id as _id,$.F2 as f2, ~1 as tmp").Execute(); + res = docs1.FetchAll(); + Assert.IsNotNull(res); + int maxrec = 100; + DbDoc newDoc = new DbDoc(); + newDoc.SetValue("_id", maxrec + 1000); + newDoc.SetValue("F1", "Field-1-Data-" + maxrec); + newDoc.SetValue("F2", "Field-2-Data-" + maxrec); + newDoc.SetValue("F3", 300 + maxrec); + col1.Add(newDoc).Execute(); + + json = "{'_id':'" + (maxrec + 1000 + 1) + "','F1':'Field-1-Data-" + (maxrec + 1) + "','F2':'Field-2-Data-" + (maxrec + 1) + "','F3':" + (300 + maxrec + 1) + "}"; + json = json.Replace("'", "\""); + var res1 = col1.Add(json).Execute(); + Assert.AreEqual(1, res1.AffectedItemsCount); + json = "{'F1': 'Field-1-Data-9999','F2': 'Field-2-Data-9999','F3': 'Field-3-Data-9999'}".Replace("'", "\""); + col1.Add(json).Add(json.Replace("9", "8")).Execute(); + Assert.AreEqual(1, res1.AffectedItemsCount); + + var docs = col1.Find("$._id = 1100").Fields("$_id as _id,$.F1 as f1, $.F2 as f2, $.F3 as f3").Execute(); + var res2 = docs.FetchOne(); + Assert.AreEqual("1100", res2["_id"].ToString()); + Assert.AreEqual("Field-1-Data-100", res2["f1"].ToString()); + Assert.AreEqual("Field-2-Data-100", res2["f2"].ToString()); + Assert.AreEqual("400", res2["f3"].ToString()); + + } + + [Test, Description("Test MySQLX plugin Invalid JSON String long expression")] + public void JSONStringSpecialCharacters() + { + if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher."); + Collection col = CreateCollection("my_collection_1"); + String[] splName = {"+", "*", "/", "a+b", "#1", "%", "&", "@1", "!1", "~", "^", + "(", ")", "{", "}", "[", "]", "|", "JSON", "ADD", "JSON_EXTRACT", "JSON_OBJECT", + "?", "=", "+", ";", ",", ":", "<", ">", "-"}; + for (int i = 0; i < splName.Length; i++) + { + col.Add("{\"" + splName[i] + "\":\"data" + i + "\",\"ID\":" + i + "}").Execute(); + var docs = col.Find("$.ID = " + i).Fields("$.`" + splName[i] + "` as col1,$.ID as Id").Execute(); + var res = docs.FetchOne(); + Assert.AreEqual(i.ToString(), res["Id"].ToString(), "Matching the ID"); + if (i == 30) + Assert.AreEqual("data" + i, "data30", "Matching the String"); + else + Assert.AreEqual("data" + i, res["col1"].ToString(), "Matching the String"); + } + } + + [Test, Description("Test MySQLX plugin Collections Chained Insert")] + public void CollectionsChainedInsert() + { + if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher."); + Collection col = CreateCollection("my_collection_1"); + DbDoc newDoc = new DbDoc(); + newDoc.SetValue("F1", 1); + + DbDoc newDoc1 = new DbDoc(); + newDoc1.SetValue("F1", 2); + + DbDoc newDoc2 = new DbDoc(); + newDoc2.SetValue("F1", 3); + + DbDoc[] jsonlist = new DbDoc[5]; + for (int i = 0; i < 5; i++) + { + DbDoc newDoc3 = new DbDoc(); + newDoc3.SetValue("F1", 4 + i); + jsonlist[i] = newDoc3; + newDoc3 = null; + } + + DbDoc[] jsonlist1 = new DbDoc[5]; + for (int i = 0; i < 5; i++) + { + DbDoc newDoc4 = new DbDoc(); + newDoc4.SetValue("F1", 10 + i); + jsonlist1[i] = newDoc4; + newDoc4 = null; + } + + DbDoc[] jsonlist2 = new DbDoc[5]; + for (int i = 0; i < 5; i++) + { + DbDoc newDoc5 = new DbDoc(); + newDoc5.SetValue("F1", 100 + i); + jsonlist2[i] = newDoc5; + newDoc5 = null; + } + + var tabRes = col.Add(newDoc).Add(newDoc1).Execute(); + Assert.AreEqual(2, tabRes.AffectedItemsCount, "Matching the affected records"); + + tabRes = col.Add(jsonlist).Add(newDoc2).Execute(); + Assert.AreEqual(6, tabRes.AffectedItemsCount, "Matching the affected records"); + + tabRes = col.Add(jsonlist1).Add(jsonlist2).Execute(); + Assert.AreEqual(10, tabRes.AffectedItemsCount, "Matching the affected records"); + } + + [Test, Description("Test MySQLX plugin Collection Add Array")] + public void CollectionAddArray() + { + if (!Platform.IsWindows()) Assert.Ignore("This test is for Windows OS only."); + if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5, 7, 0 or higher."); + int maxrec = 5; + var col = CreateCollection("my_collection_1"); + DbDoc[] jsonlist = new DbDoc[maxrec]; + for (int i = 0; i < maxrec; i++) + { + DbDoc newDoc2 = new DbDoc(); + newDoc2.SetValue("_id", i); + newDoc2.SetValue("F1", "Field-1-Data-" + i); + newDoc2.SetValue("ARR_INT", new DbDoc(@"{""values"":[1, 2, 3, 4, 5, 6, 7, 8, 9]}")); + newDoc2.SetValue("ARR_STR", new DbDoc(@"{""values"":""['DATA1', 'DATA2', 'DATA3', 'DATA4', 'DATA5', 'DATA6']""}")); + newDoc2.SetValue("ARR_LIT", new DbDoc(@"{""values"":""[null, true, false, null, true, false, null, true, false]""}")); + newDoc2.SetValue("ARR_ARR", new DbDoc(@"{""values"":[[1, 2, 3, 4, 5], [1, 2, 3, 4, 5], [1, 2, 3, 4, 5]]}")); + + col.Add(newDoc2).Execute(); + jsonlist[i] = newDoc2; + } + + jsonlist = null; + var res = col.Find().Execute().FetchAll(); + Assert.AreEqual(5, res.Count, "Matching the find count"); + } + + [Test, Description("Test MySQLX plugin Collection JSON Scenarios")] + public void CollectionAddJSONDocs() + { + if (!Platform.IsWindows()) Assert.Ignore("This test is for Windows OS only."); + if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher."); + + Collection col = CreateCollection("my_collection_1"); + string json = @"{ ""_id"": 0, ""title"": ""Book 0"" ,""pages"": 10,""name"": ""Jeoff Archer""}"; + Result r = col.Add(json).Execute(); + + Assert.AreEqual(1, (int)r.AffectedItemsCount, "Matching Affected Records Count"); + var foundDocs = col.Find("pages > 5").Execute(); + Assert.AreEqual(1, foundDocs.Count(), "Matching Count"); + + json = @"{ ""_id"" : 99950, ""city"" : ""KETCHIKAN"", ""loc"" : ""[ -133.18479, 55.942471 ]"", ""pop"" : 422, ""state"" : ""AK"" }"; + r = col.Add(json).Execute(); + + DbDoc d = new DbDoc(@"{ ""id"": 1, ""pages"": 20, + ""person"": { ""name"": ""Fred"", ""age"": 45 } + }"); + DbDoc d2 = new DbDoc(); + d2.SetValue("id", 1); + d2.SetValue("pages", 20); + d2.SetValue("person", new { name = "Fred", age = 45 }); + + Assert.AreEqual(d.Equals(d2), true, "Matching"); + col.Add(d).Execute(); + + d = new DbDoc(@"{""id"":100,""FirstName"":""xyz"",""lastname"":""pqr"", + ""address"": + {""house"":44,""city"":""Delhi"",""country"":""india""}}"); + col.Add(d).Execute(); + + d = new DbDoc(@"{""customerId"":100,""FirstName"":""xyz"",""lastname"":""pqr"", + ""address"": + {""house"":44,""city"":""Delhi"",""country"":""india""}, + ""employer"": + {""cmpName"":""ABC"",""type"":""IT""}}"); + col.Add(d).Execute(); + + d = new DbDoc(@"{ ""id"": 1, ""pages"": 20, + ""books"": [ + {""_id"" : 1, ""title"" : ""Book 1""}, + { ""_id"" : 2, ""title"" : ""Book 2"" } + ] + }"); + col.Add(d).Execute(); + + var docs = new[] { new { _id = 1, title = "Book 1" }, new { _id = 2, title = "Book 2" } }; + d2 = new DbDoc(); + d2.SetValue("id", 100); + d2.SetValue("pages", 20); + d2.SetValue("books", docs); + col.Add(d2).Execute(); + + var result = col.Find("$._id = 0").Fields("$._id as _id,$.name as name, $.pages as pages, $.title as title").Execute(); + var res1 = result.FetchOne(); + Assert.AreEqual(0, res1["_id"]); + Assert.AreEqual("Jeoff Archer", res1["name"]); + Assert.AreEqual(10, res1["pages"]); + Assert.AreEqual("Book 0", res1["title"]); + + result = col.Find("$._id > 0").Fields().Execute(); + var res2 = result.FetchAll(); + Assert.AreEqual(6, res2.Count()); + + DbDoc test = new DbDoc(); + test.SetValue("_id", 1); + test.SetValue("name", "ABBBBBBBBBBBBBBXXXXXXXXXXXXXXXYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYTTTTTTYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYABBBBBBBBBBBBBBXXXXXXXXXXXXXXXYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYTTTTTTYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYABBBBBBBBBBBBBBXXXXXXXXXXXXXXXYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYTTTTTTYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYABBBBBBBBBBBBBBXXXXXXXXXXXXXXXYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYTTTTTTYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYABBBBBBBBBBBBBBXXXXXXXXXXXXXXXYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYTTTTTTYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY"); + var coll = CreateCollection("my_collection_123456789"); + var res = coll.Add(test).Execute(); + foundDocs = coll.Find().Execute(); + var docs1 = foundDocs.FetchAll(); + Assert.AreEqual(1, docs1.Count); + } + + [Test, Description("Verify that the field and column _id has a value when it's not given to a document-Scenario-1(single document add)")] + public void VerifyIDField() + { + if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("this test is for MySql 8.0.11 or higher."); + List idStringList = new List(); + var col = CreateCollection("my_collection"); + Result result = null; + string generatedIDs1 = null, generatedIDs2 = null; + int countgenerateIDs = 0; + // Anonymous Object Array + object[] data = new object[] { new { title = "Book 1", pages = 30 } }; + var stmt = col.Add(data); + result = stmt.Execute(); + generatedIDs1 = result.GeneratedIds[0]; + Assert.AreEqual(generatedIDs1, generatedIDs1, "ID generated by the server"); + VerifyGeneratedID(generatedIDs1); + countgenerateIDs = result.GeneratedIds.Count; + Assert.AreEqual(1, countgenerateIDs, "Count of the ID generated by the server"); + for (int i = 0; i < countgenerateIDs; i++) + { + idStringList.Add(result.GeneratedIds[i]); + } + + // DbDoc + DbDoc DbDocs = new DbDoc(); + DbDocs.SetValue("title", "Book 0"); + DbDocs.SetValue("pages", 10); + stmt = col.Add(DbDocs); + result = stmt.Execute(); + generatedIDs2 = result.GeneratedIds[0]; + Assert.AreEqual(generatedIDs2, generatedIDs2, "ID generated by the server"); + VerifyGeneratedID(generatedIDs2); + countgenerateIDs = result.GeneratedIds.Count; + Assert.AreEqual(1, countgenerateIDs, "Count of the ID generated by the server"); + for (int i = 0; i < countgenerateIDs; i++) + { + idStringList.Add(result.GeneratedIds[i]); + } + + // Anonymous Object + var docs = new { title = "Book 1", pages = 20 }; + stmt = col.Add(docs); + result = stmt.Execute(); + generatedIDs1 = result.GeneratedIds[0]; + Assert.AreEqual(generatedIDs1, generatedIDs1, "ID generated by the server"); + VerifyGeneratedID(generatedIDs1); + countgenerateIDs = result.GeneratedIds.Count; + Assert.AreEqual(1, countgenerateIDs, "Count of the ID generated by the server"); + for (int i = 0; i < countgenerateIDs; i++) + { + idStringList.Add(result.GeneratedIds[i]); + } + + // JSON + stmt = col.Add("{ \"foo\": 100 }"); + result = stmt.Execute(); + generatedIDs2 = result.GeneratedIds[0]; + Assert.AreEqual(generatedIDs2, generatedIDs2, "ID generated by the server"); + VerifyGeneratedID(generatedIDs2); + countgenerateIDs = result.GeneratedIds.Count; + Assert.AreEqual(1, countgenerateIDs, "Count of the ID generated by the server"); + for (int i = 0; i < countgenerateIDs; i++) + { + idStringList.Add(result.GeneratedIds[i]); + } + + int j = 1; + for (int i = 0; i < idStringList.Count; i++) + { + if (j == idStringList.Count) + { + break; + } + VerifySequence(idStringList[i], idStringList[j]); + j++; + } + } + + [Test, Description("Unique _ids generated server side for multiple documents, single add and generated ids count should be number of docs added-Scenario3")] + public void VerifyIDFieldScenario3() + { + if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("this test is for MySql 8.0.11 or higher."); + List idStringList = new List(); + var col = CreateCollection("my_collection"); + Result result = null; + string generatedIDs1 = null; + int countgenerateIDs = 0; + HashSet firstset = new HashSet(); + + object[] data1 = new object[] + { + new { title = "Book 1", pages = 20 }, + new { title = "Book 2", pages = 30 }, + new { title = "Book 3", pages = 40 }, + new { title = "Book 4", pages = 50 } + }; + + var stmt = col.Add(data1); + result = stmt.Execute(); + countgenerateIDs = result.GeneratedIds.Count; + Assert.AreEqual(4, countgenerateIDs, "Count of the ID generated by the server"); + for (int i = 0; i < countgenerateIDs; i++) + { + generatedIDs1 = result.GeneratedIds[i]; + Assert.AreEqual(generatedIDs1, generatedIDs1, "ID generated by the server"); + VerifyGeneratedID(generatedIDs1); + Assert.False(!firstset.Add(generatedIDs1)); + } + + for (int i = 0; i < countgenerateIDs; i++) + { + idStringList.Add(result.GeneratedIds[i]); + } + + stmt = col.Add(@"{ ""foo"": 1 }", @"{""foo"": 2 }", @"{ ""foo"": 3 }", @"{ ""foo"": 4 }"); + result = stmt.Execute(); + countgenerateIDs = result.GeneratedIds.Count; + Assert.AreEqual(4, countgenerateIDs, "Count of the ID generated by the server"); + for (int i = 0; i < countgenerateIDs; i++) + { + generatedIDs1 = result.GeneratedIds[i]; + Assert.AreEqual(generatedIDs1, generatedIDs1, "ID generated by the server"); + VerifyGeneratedID(generatedIDs1); + Assert.False(!firstset.Add(generatedIDs1)); + } + + for (int i = 0; i < countgenerateIDs; i++) + { + idStringList.Add(result.GeneratedIds[i]); + } + + int j = 1; + for (int i = 0; i < idStringList.Count; i++) + { + if (j == idStringList.Count) + { + break; + } + VerifySequence(idStringList[i], idStringList[j]); + j++; + } + } + + [Test, Description("Verify that the field and column _id has a value when it's not given to a document-Scenario-1(single document add)-when doc already exists")] + public void VerifyIDFieldScenario4() + { + if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("this test is for MySql 8.0.11 or higher."); + List idStringList = new List(); + var col = CreateCollection("my_collection"); + Result result = null; + string generatedIDs1 = null, generatedIDs2 = null; + int countgenerateIDs = 0; + object[] data = null; + data = new object[] + { + new { title ="Book 0", pages = 10 }, + new { title ="Book 5", pages = 60, _id = 6} + }; + result = col.Add(data).Execute(); + countgenerateIDs = result.GeneratedIds.Count; + generatedIDs1 = result.GeneratedIds[0]; + Assert.AreEqual(1, countgenerateIDs, "Count of the ID generated by the server"); + for (int i = 0; i < countgenerateIDs; i++) + { + idStringList.Add(result.GeneratedIds[i]); + } + + // Anonymous Object Array + data = new object[] { new { title = "Book 1", pages = 30 } }; + var stmt = col.Add(data); + result = stmt.Execute(); + generatedIDs1 = result.GeneratedIds[0]; + Assert.AreEqual(generatedIDs1, generatedIDs1, "ID generated by the server"); + VerifyGeneratedID(generatedIDs1); + countgenerateIDs = result.GeneratedIds.Count; + Assert.AreEqual(1, countgenerateIDs, "Count of the ID generated by the server"); + for (int i = 0; i < countgenerateIDs; i++) + { + idStringList.Add(result.GeneratedIds[i]); + } + + col = CreateCollection("my_collection"); + data = null; + data = new object[] + { + new { title ="Book 0", pages = 10 }, + new { title ="Book 5", pages = 60, _id = 6} + }; + result = col.Add(data).Execute(); + countgenerateIDs = result.GeneratedIds.Count; + generatedIDs1 = result.GeneratedIds[0]; + Assert.AreEqual(1, countgenerateIDs, "Count of the ID generated by the server"); + for (int i = 0; i < countgenerateIDs; i++) + { + idStringList.Add(result.GeneratedIds[i]); + } + + // DbDoc + DbDoc DbDocs = new DbDoc(); + DbDocs.SetValue("title", "Book 0"); + DbDocs.SetValue("pages", 10); + stmt = col.Add(DbDocs); + result = stmt.Execute(); + generatedIDs2 = result.GeneratedIds[0]; + Assert.AreEqual(generatedIDs2, generatedIDs2, "ID generated by the server"); + VerifyGeneratedID(generatedIDs2); + countgenerateIDs = result.GeneratedIds.Count; + Assert.AreEqual(1, countgenerateIDs, "Count of the ID generated by the server"); + for (int i = 0; i < countgenerateIDs; i++) + { + idStringList.Add(result.GeneratedIds[i]); + } + + col = CreateCollection("my_collection"); + data = null; + data = new object[] + { + new { title ="Book 0", pages = 10 }, + new { title ="Book 5", pages = 60, _id = 6} + }; + result = col.Add(data).Execute(); + countgenerateIDs = result.GeneratedIds.Count; + generatedIDs1 = result.GeneratedIds[0]; + Assert.AreEqual(1, countgenerateIDs, "Count of the ID generated by the server"); + for (int i = 0; i < countgenerateIDs; i++) + { + idStringList.Add(result.GeneratedIds[i]); + } + + // Anonymous Object + var docs = new { title = "Book 1", pages = 20 }; + stmt = col.Add(docs); + result = stmt.Execute(); + generatedIDs1 = result.GeneratedIds[0]; + Assert.AreEqual(generatedIDs1, generatedIDs1, "ID generated by the server"); + VerifyGeneratedID(generatedIDs1); + countgenerateIDs = result.GeneratedIds.Count; + Assert.AreEqual(1, countgenerateIDs, "Count of the ID generated by the server"); + for (int i = 0; i < countgenerateIDs; i++) + { + idStringList.Add(result.GeneratedIds[i]); + } + + col = CreateCollection("my_collection"); + data = null; + data = new object[] + { + new { title ="Book 0", pages = 10 }, + new { title ="Book 5", pages = 60, _id = 6} + }; + result = col.Add(data).Execute(); + countgenerateIDs = result.GeneratedIds.Count; + generatedIDs1 = result.GeneratedIds[0]; + Assert.AreEqual(1, countgenerateIDs, "Count of the ID generated by the server"); + for (int i = 0; i < countgenerateIDs; i++) + { + idStringList.Add(result.GeneratedIds[i]); + } + + //JSON + stmt = col.Add("{ \"foo\": 100 }"); + result = stmt.Execute(); + generatedIDs2 = result.GeneratedIds[0]; + Assert.AreEqual(generatedIDs2, generatedIDs2, "ID generated by the server"); + VerifyGeneratedID(generatedIDs2); + countgenerateIDs = result.GeneratedIds.Count; + Assert.AreEqual(1, countgenerateIDs, "Count of the ID generated by the server"); + for (int i = 0; i < countgenerateIDs; i++) + { + idStringList.Add(result.GeneratedIds[i]); + } + + int j = 1; + for (int i = 0; i < idStringList.Count; i++) + { + if (j == idStringList.Count) + { + break; + } + VerifySequence(idStringList[i], idStringList[j]); + j++; + } + } + + [Test, Description("Unique _ids generated server side for multiple documents,multiple add and generated ids count should be number of docs added-when doc already exists Scenario2")] + public void VerifyIDFieldScenario5() + { + if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("this test is for MySql 8.0.11 or higher."); + List idStringList = new List(); + Result result = null; + string generatedIDs1 = null; + int countgenerateIDs = 0; + var col = CreateCollection("my_collection"); + object[] data = null; + + data = new object[] + { + new { title ="Book 0", pages = 10 }, + new { title ="Book 5", pages = 60, _id = 6} + }; + result = col.Add(data).Execute(); + countgenerateIDs = result.GeneratedIds.Count; + generatedIDs1 = result.GeneratedIds[0]; + Assert.AreEqual(1, countgenerateIDs, "Count of the ID generated by the server"); + for (int i = 0; i < countgenerateIDs; i++) + { + idStringList.Add(result.GeneratedIds[i]); + } + + HashSet firstset = new HashSet(); + // Anonymous Object Array + object[] data1 = new object[] { new { title ="Book 1", pages = 20 } + }; + object[] data2 = new object[] { new { title = "Book 5", pages = 60 } }; + + var stmt = col.Add(data1).Add(data2); + result = stmt.Execute(); + countgenerateIDs = result.GeneratedIds.Count; + Assert.AreEqual(2, countgenerateIDs, "Count of the ID generated by the server"); + for (int i = 0; i < countgenerateIDs; i++) + { + generatedIDs1 = result.GeneratedIds[i]; + Assert.AreEqual(generatedIDs1, generatedIDs1, "ID generated by the server"); + VerifyGeneratedID(generatedIDs1); + Assert.False(!firstset.Add(generatedIDs1)); + } + for (int i = 0; i < countgenerateIDs; i++) + { + idStringList.Add(result.GeneratedIds[i]); + } + + col = CreateCollection("my_collection"); + data = new object[] + { + new { title ="Book 0", pages = 10 }, + new { title ="Book 5", pages = 60, _id = 6} + }; + result = col.Add(data).Execute(); + countgenerateIDs = result.GeneratedIds.Count; + generatedIDs1 = result.GeneratedIds[0]; + Assert.AreEqual(1, countgenerateIDs, "Count of the ID generated by the server"); + for (int i = 0; i < countgenerateIDs; i++) + { + idStringList.Add(result.GeneratedIds[i]); + } + + // DbDoc + DbDoc DbDocs1 = new DbDoc(); + DbDocs1.SetValue("title", "Book 0"); + DbDocs1.SetValue("pages", 10); + DbDoc DbDocs2 = new DbDoc(); + DbDocs2.SetValue("title", "Book 1"); + DbDocs2.SetValue("pages", 20); + stmt = col.Add(DbDocs1).Add(DbDocs2); + result = stmt.Execute(); + countgenerateIDs = result.GeneratedIds.Count; + Assert.AreEqual(2, countgenerateIDs, "Count of the ID generated by the server"); + for (int i = 0; i < countgenerateIDs; i++) + { + generatedIDs1 = result.GeneratedIds[i]; + Assert.AreEqual(generatedIDs1, generatedIDs1, "ID generated by the server"); + VerifyGeneratedID(generatedIDs1); + Assert.False(!firstset.Add(generatedIDs1)); + } + for (int i = 0; i < countgenerateIDs; i++) + { + idStringList.Add(result.GeneratedIds[i]); + } + + col = CreateCollection("my_collection"); + + data = new object[] + { + new { title ="Book 0", pages = 10 }, + new { title ="Book 5", pages = 60, _id = 6} + }; + result = col.Add(data).Execute(); + countgenerateIDs = result.GeneratedIds.Count; + generatedIDs1 = result.GeneratedIds[0]; + Assert.AreEqual(1, countgenerateIDs, "Count of the ID generated by the server"); + for (int i = 0; i < countgenerateIDs; i++) + { + idStringList.Add(result.GeneratedIds[i]); + } + + // Anonymous Object + var docs1 = new { title = "Book 1", pages = 20 }; + var docs2 = new { title = "Book 2", pages = 30 }; + stmt = col.Add(docs1).Add(docs2); + + result = stmt.Execute(); + countgenerateIDs = result.GeneratedIds.Count; + Assert.AreEqual(2, countgenerateIDs, "Count of the ID generated by the server"); + for (int i = 0; i < countgenerateIDs; i++) + { + generatedIDs1 = result.GeneratedIds[i]; + Assert.AreEqual(generatedIDs1, generatedIDs1, "ID generated by the server"); + VerifyGeneratedID(generatedIDs1); + Assert.False(!firstset.Add(generatedIDs1)); + } + for (int i = 0; i < countgenerateIDs; i++) + { + idStringList.Add(result.GeneratedIds[i]); + } + + col = CreateCollection("my_collection"); + data = new object[] + { + new { title ="Book 0", pages = 10 }, + new { title ="Book 5", pages = 60, _id = 6} + }; + result = col.Add(data).Execute(); + countgenerateIDs = result.GeneratedIds.Count; + generatedIDs1 = result.GeneratedIds[0]; + Assert.AreEqual(1, countgenerateIDs, "Count of the ID generated by the server"); + for (int i = 0; i < countgenerateIDs; i++) + { + idStringList.Add(result.GeneratedIds[i]); + } + + // JSON + stmt = col.Add("{ \"foo1\": 100 }").Add("{ \"foo2\": 200 }"); + result = stmt.Execute(); + countgenerateIDs = result.GeneratedIds.Count; + Assert.AreEqual(2, countgenerateIDs, "Count of the ID generated by the server"); + for (int i = 0; i < countgenerateIDs; i++) + { + generatedIDs1 = result.GeneratedIds[i]; + Assert.AreEqual(generatedIDs1, generatedIDs1, "ID generated by the server"); + VerifyGeneratedID(generatedIDs1); + if (!firstset.Add(generatedIDs1)) + { + break; + } + } + for (int i = 0; i < countgenerateIDs; i++) + { + idStringList.Add(result.GeneratedIds[i]); + } + + int j = 1; + for (int i = 0; i < idStringList.Count; i++) + { + if (j == idStringList.Count) + { + break; + } + VerifySequence(idStringList[i], idStringList[j]); + j++; + } + } + + [Test, Description("Unique _ids generated server side for multiple documents, single add and generated ids count should be number of docs added-when doc already exists Scenario3")] + public void VerifyIDFieldScenario6() + { + if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("this test is for MySql 8.0.11 or higher."); + List idStringList = new List(); + var col = CreateCollection("my_collection"); + Result result = null; + string generatedIDs1 = null; + int countgenerateIDs = 0; + object[] data = null; + + data = new object[] + { + new { title ="Book 0", pages = 10 }, + new { title ="Book 5", pages = 60, _id = 6} + }; + result = col.Add(data).Execute(); + countgenerateIDs = result.GeneratedIds.Count; + generatedIDs1 = result.GeneratedIds[0]; + Assert.AreEqual(1, countgenerateIDs, "Count of the ID generated by the server"); + for (int i = 0; i < countgenerateIDs; i++) + { + idStringList.Add(result.GeneratedIds[i]); + } + + HashSet firstset = new HashSet(); + // Anonymous Object Array + object[] data1 = new object[] + { + new { title ="Book 1", pages = 20 }, + new { title = "Book 2", pages = 30 }, + new { title = "Book 3", pages = 40 }, + new { title = "Book 4", pages = 50 } + }; + + var stmt = col.Add(data1); + result = stmt.Execute(); + countgenerateIDs = result.GeneratedIds.Count; + Assert.AreEqual(4, countgenerateIDs, "Count of the ID generated by the server"); + for (int i = 0; i < countgenerateIDs; i++) + { + generatedIDs1 = result.GeneratedIds[i]; + Assert.AreEqual(generatedIDs1, generatedIDs1, "ID generated by the server"); + VerifyGeneratedID(generatedIDs1); + Assert.False(!firstset.Add(generatedIDs1)); + } + for (int i = 0; i < countgenerateIDs; i++) + { + idStringList.Add(result.GeneratedIds[i]); + } + + col = CreateCollection("my_collection"); + result = col.Add(@"{ ""foo"": 0, ""_id"":0 }", @"{""foo"": 5 }").Execute(); + countgenerateIDs = result.GeneratedIds.Count; + generatedIDs1 = result.GeneratedIds[0]; + Assert.AreEqual(1, countgenerateIDs, "Count of the ID generated by the server"); + for (int i = 0; i < countgenerateIDs; i++) + { + idStringList.Add(result.GeneratedIds[i]); + } + + // JSON + stmt = col.Add(@"{ ""foo"": 1 }", @"{""foo"": 2 }", @"{ ""foo"": 3 }", @"{ ""foo"": 4 }"); + result = stmt.Execute(); + countgenerateIDs = result.GeneratedIds.Count; + Assert.AreEqual(4, countgenerateIDs, "Count of the ID generated by the server"); + for (int i = 0; i < countgenerateIDs; i++) + { + generatedIDs1 = result.GeneratedIds[i]; + Assert.AreEqual(generatedIDs1, generatedIDs1, "ID generated by the server"); + VerifyGeneratedID(generatedIDs1); + Assert.False(!firstset.Add(generatedIDs1)); + } + for (int i = 0; i < countgenerateIDs; i++) + { + idStringList.Add(result.GeneratedIds[i]); + } + + int j = 1; + for (int i = 0; i < idStringList.Count; i++) + { + if (j == idStringList.Count) + { + break; + } + VerifySequence(idStringList[i], idStringList[j]); + j++; + } + } + + [Test, Description("Client provided _id shouldnt be discarded and generatedids() should give empty list for anonymous object array -single document add")] + public void VerifyIDFieldScenario7() + { + var col = CreateCollection("my_collection"); + object[] data = new object[] + { + new { _id = "1e9c92fda74ed311944e00059a3c7a00", title = "Book 0", pages = 10 }, + }; + Result result = col.Add(data).Execute(); + var generatedIDs = result.GeneratedIds; + Assert.AreEqual(0, generatedIDs.Count, "Matches"); + var doc = col.Find("_id like :param").Bind("param", "1e9c92fda74ed311944e00059a3c7a00").Execute(); + var docs = doc.FetchAll().Count(); + Assert.AreEqual(1, docs, "Matches"); + + //Anonymous Object + var data1 = new { _id = "1e9c92fda74ed311944e00059a3c7a01", title = "Book 0", pages = 10 }; + result = col.Add(data1).Execute(); + + generatedIDs = result.GeneratedIds; + Assert.AreEqual(0, generatedIDs.Count, "Matches"); + doc = col.Find("_id like :param").Bind("param", "1e9c92fda74ed311944e00059a3c7a01").Execute(); + docs = doc.FetchAll().Count(); + Assert.AreEqual(1, docs, "Matches"); + + // DbDoc + DbDoc DbDocs = new DbDoc(); + DbDocs.SetValue("title", "Book 0"); + DbDocs.SetValue("pages", 10); + DbDocs.SetValue("_id", "1e9c92fda74ed311944e00059a3c7a02"); + result = col.Add(DbDocs).Execute(); + + generatedIDs = result.GeneratedIds; + Assert.AreEqual(0, generatedIDs.Count, "Matches"); + doc = col.Find("_id like :param").Bind("param", "1e9c92fda74ed311944e00059a3c7a02").Execute(); + docs = doc.FetchAll().Count(); + Assert.AreEqual(1, docs, "Matches"); + + //JSON + result = col.Add("{\"_id\":\"1e9c92fda74ed311944e00059a3c7a03\",\"title\": \"Book 0\",\"pages\": 10}").Execute(); + generatedIDs = result.GeneratedIds; + Assert.AreEqual(0, generatedIDs.Count, "Matches"); + doc = col.Find("_id like :param").Bind("param", "1e9c92fda74ed311944e00059a3c7a03").Execute(); + docs = doc.FetchAll().Count(); + Assert.AreEqual(1, docs, "Matches"); + } + + [Test, Description("Client provided _id shouldnt be discarded and generatedids() should give empty list for anonymous object array -multiple documents multiple add with negative number")] + public void VerifyIDFieldScenario8() + { + var col = CreateCollection("my_collection"); + object[] data1 = new object[] + { + new { _id = "1e9c92fda74ed311944e00059a3c7a00", title = "Book 0", pages = 10 } + }; + object[] data2 = new object[] + { + new { _id = -1, title = "Book 0", pages = 10 } + }; + Result result = col.Add(data1).Add(data2).Execute(); + var generatedIDs = result.GeneratedIds; + Assert.AreEqual(0, generatedIDs.Count, "Matches"); + var doc = col.Find("_id like :param").Bind("param", "1e9c92fda74ed311944e00059a3c7a00").Execute(); + var docs = doc.FetchAll().Count(); + Assert.AreEqual(1, docs, "Matches"); + doc = col.Find("_id like :param").Bind("param", -1).Execute(); + docs = doc.FetchAll().Count(); + Assert.AreEqual(1, docs, "Matches"); + + // Anonymous Object + var data3 = new { _id = "1e9c92fda74ed311944e00059a3c7a01", title = "Book 0", pages = 10 }; + var data4 = new { _id = -2, title = "Book 0", pages = 10 }; + result = col.Add(data3).Add(data4).Execute(); + generatedIDs = result.GeneratedIds; + Assert.AreEqual(0, generatedIDs.Count, "Matches"); + doc = col.Find("_id like :param").Bind("param", "1e9c92fda74ed311944e00059a3c7a01").Execute(); + docs = doc.FetchAll().Count(); + Assert.AreEqual(1, docs, "Matches"); + doc = col.Find("_id like :param").Bind("param", -2).Execute(); + docs = doc.FetchAll().Count(); + Assert.AreEqual(1, docs, "Matches"); + + //DbDoc + DbDoc DbDocs1 = new DbDoc(); + DbDocs1.SetValue("title", "Book 0"); + DbDocs1.SetValue("pages", 10); + DbDocs1.SetValue("_id", "1e9c92fda74ed311944e00059a3c7a02"); + DbDoc DbDocs2 = new DbDoc(); + DbDocs2.SetValue("title", "Book 0"); + DbDocs2.SetValue("pages", 10); + DbDocs2.SetValue("_id", -3); + result = col.Add(DbDocs1).Add(DbDocs2).Execute(); + generatedIDs = result.GeneratedIds; + Assert.AreEqual(0, generatedIDs.Count, "Matches"); + doc = col.Find("_id like :param").Bind("param", "1e9c92fda74ed311944e00059a3c7a02").Execute(); + docs = doc.FetchAll().Count(); + Assert.AreEqual(1, docs, "Matches"); + doc = col.Find("_id like :param").Bind("param", -3).Execute(); + docs = doc.FetchAll().Count(); + Assert.AreEqual(1, docs, "Matches"); + + // JSON + result = col.Add("{\"_id\":\"1e9c92fda74ed311944e00059a3c7a03\",\"title\": \"Book 0\",\"pages\": 10}"). + Add("{\"_id\":-4,\"title\": \"Book 0\",\"pages\": 10}"). + Execute(); + generatedIDs = result.GeneratedIds; + Assert.AreEqual(0, generatedIDs.Count, "Matches"); + doc = col.Find("_id like :param").Bind("param", "1e9c92fda74ed311944e00059a3c7a03").Execute(); + docs = doc.FetchAll().Count(); + Assert.AreEqual(1, docs, "Matches"); + doc = col.Find("_id like :param").Bind("param", -4).Execute(); + docs = doc.FetchAll().Count(); + Assert.AreEqual(1, docs, "Matches"); + } + + [Test, Description("Client provided _id shouldnt be discarded and generatedids() should give empty list for anonymous object array -multiple documents single add with negative number,zero and big positive numbers")] + public void VerifyIDFieldScenario9() + { + var col = CreateCollection("my_collection"); + // Anonymous Object Array + object[] idList = new object[] { "1e9c92fda74ed311944e00059a3c7a00", -1, 60000000000000, -3000000000000, 0 }; + object[] data1 = new object[] + { + new { _id = idList[0], title = "Book 0", pages = 10 }, + new { _id = idList[1], title = "Book 0", pages = 10 }, + new { _id = idList[2] , title = "Book 0", pages = 10 }, + new { _id = idList[3], title = "Book 0", pages = 10 }, + new { _id = idList[4], title = "Book 0", pages = 10 } + }; + Result result = col.Add(data1).Execute(); + var generatedIDs = result.GeneratedIds; + Assert.AreEqual(0, generatedIDs.Count, "Matches"); + for (int i = 0; i < idList.Length; i++) + { + var doc = col.Find("_id like :param").Bind("param", idList[i]).Execute(); + var docs = doc.FetchAll().Count(); + Assert.AreEqual(1, docs, "Matches the Document ID"); + } + } + + [Test, Description("documents single add with blank id")] + public void CollectionAddBlankId() + { + var col = CreateCollection("my_collection"); + // Anonymous Object Array + object[] idList = new object[] { "", " " }; + object[] data1 = new object[] + { + new { _id = idList[0], title = "Book 0", pages = 10 } + }; + object[] data2 = new object[] + { + new { _id = idList[1], title = "Book 0", pages = 10 } + }; + Result result1 = col.Add(data1).Execute(); + Assert.AreEqual(1, result1.AffectedItemsCount); + result1 = null; + + col = CreateCollection("my_collection"); + result1 = col.Add(data2).Execute(); + Assert.AreEqual(1, result1.AffectedItemsCount); + result1 = null; + + col = CreateCollection("my_collection"); + // DbDoc + DbDoc DbDocs1 = new DbDoc(); + DbDocs1.SetValue("title", "Book 0"); + DbDocs1.SetValue("pages", 10); + DbDocs1.SetValue("_id", ""); + result1 = col.Add(DbDocs1).Execute(); + Assert.AreEqual(1, result1.AffectedItemsCount); + result1 = null; + + col = CreateCollection("my_collection"); + DbDoc DbDocs2 = new DbDoc(); + DbDocs2.SetValue("title", "Book 1"); + DbDocs2.SetValue("pages", 20); + DbDocs2.SetValue("_id", " "); + result1 = col.Add(DbDocs2).Execute(); + Assert.AreEqual(1, result1.AffectedItemsCount); + result1 = null; + + // JSON + col = CreateCollection("my_collection"); + result1 = col.Add("{\"_id\":\"\",\"title\": \"Book 0\",\"pages\": 10}").Execute(); + Assert.AreEqual(1, result1.AffectedItemsCount); + result1 = null; + + col = CreateCollection("my_collection"); + result1 = col.Add("{\"_id\":\" \",\"title\": \"Book 0\",\"pages\": 10}").Execute(); + Assert.AreEqual(1, result1.AffectedItemsCount); + result1 = null; + + } + + [Test, Description("Multiple documents with same id")] + public void CollectionAddMultipleDocsSameId() + { + var col = CreateCollection("my_collection"); + string exception = "Document contains a field value that is not unique but required to be"; + // DbDoc + DbDoc DbDocs1 = new DbDoc(); + DbDocs1.SetValue("title", "Book 0"); + DbDocs1.SetValue("pages", 10); + DbDocs1.SetValue("_id", 1); + DbDoc DbDocs2 = new DbDoc(); + DbDocs2.SetValue("title", "Book 1"); + DbDocs2.SetValue("pages", 20); + DbDocs2.SetValue("_id", 1); + var ex = Assert.Throws(() => col.Add(DbDocs1).Add(DbDocs2).Execute()); + Assert.AreEqual(exception, ex.Message, "Checking the exception"); + + // JSON + ex = Assert.Throws(() => col.Add("{\"_id\":1,\"title\": \"Book 0\",\"pages\": 10}"). + Add("{\"_id\":1,\"title\": \"Book 1\",\"pages\": 20}").Execute()); + Assert.AreEqual(exception, ex.Message, "Checking the exception"); + + // Anonymous Object Array + object[] data1 = new object[] + { + new { _id = 1, title = "Book 0", pages = 10 } + }; + object[] data2 = new object[] + { + new { _id = 1, title = "Book 1", pages = 20 } + }; + ex = Assert.Throws(() => col.Add(data1).Add(data2).Execute()); + Assert.AreEqual(exception, ex.Message, "Checking the exception"); + } + + [Test, Description("Verify the behaviour if a sequence is incremented by the user and added as _id for the document")] + public void VerifySequenceAndIdAdded() + { + if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher."); + string incrementedString = null, generatedString = null; + var col = CreateCollection("my_collection"); + Result result = null; + string generatedIDs1 = null; + int countgenerateIDs = 0; + // Anonymous Object Array + object[] data = new object[] { new { title = "Book 1", pages = 30 } }; + var stmt = col.Add(data); + + result = stmt.Execute(); + generatedIDs1 = result.GeneratedIds[0]; + Assert.AreEqual(generatedIDs1, generatedIDs1, "ID generated by the server"); + VerifyGeneratedID(generatedIDs1); + countgenerateIDs = result.GeneratedIds.Count; + Assert.AreEqual(1, countgenerateIDs, "Count of the ID generated by the server"); + generatedString = generatedIDs1; + incrementedString = Increment(generatedIDs1, Mode.AlphaNumeric); + + data = new object[] { new { title = "Book 2", pages = 40, _id = generatedString } }; + stmt = col.Add(data); + string exception = "Document contains a field value that is not unique but required to be"; + Exception ex = Assert.Throws(() => stmt.Execute()); + Assert.AreEqual(exception, ex.Message, "Matching the exception"); + + data = new object[] { new { title = "Book 3", pages = 50, _id = incrementedString } }; + stmt = col.Add(data); + result = stmt.Execute(); + Assert.IsNotNull(result); + + data = new object[] { new { title = "Book 4", pages = 60 } }; + stmt = col.Add(data); + ex = Assert.Throws(() => stmt.Execute()); + Assert.AreEqual(exception, ex.Message, "Matching the exception"); + + } + + [Test, Description("documents inserted concurrently by two threads")] + public async Task CollectionConcurrentAdd() + { + if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher."); + + CreateCollection("my_collection"); + var r1 = await CollectionAddThread1(); + _ = await CollectionAddThread2(); + Assert.AreEqual(1000, r1); + } + public Task CollectionAddThread1() + { + List idStringList = new List(); + var col = CreateCollection("my_collection"); + DbDoc[] jsonlist = new DbDoc[1000]; + for (int i = 0; i < 1000; i++) + { + DbDoc newDoc2 = new DbDoc(); + newDoc2.SetValue("F1", ("Field-1-Data-" + i)); + newDoc2.SetValue("F2", ("Field-2-Data-" + i)); + newDoc2.SetValue("F3", (3 + i).ToString()); + jsonlist[i] = newDoc2; + newDoc2 = null; + } + Result r = col.Add(jsonlist).Execute(); + Assert.AreEqual(1000, r.AffectedItemsCount, "Matching"); + int countgenerateIDs = r.GeneratedIds.Count; + for (int i = 0; i < countgenerateIDs; i++) + { + idStringList.Add(r.GeneratedIds[i]); + } + + int j = 1; + for (int i = 0; i < idStringList.Count; i++) + { + if (j == idStringList.Count) + { + break; + } + VerifySequence(idStringList[i], idStringList[j]); + j++; + } + return Task.FromResult((int)r.AffectedItemsCount); + } + + public Task CollectionAddThread2() + { + List idStringList = new List(); + var col = CreateCollection("my_collection1"); + DbDoc[] jsonlist = new DbDoc[1000]; + for (int i = 0; i < 1000; i++) + { + DbDoc newDoc2 = new DbDoc(); + newDoc2.SetValue("F4", ("Field-1-Data-" + i)); + newDoc2.SetValue("F5", ("Field-2-Data-" + i)); + newDoc2.SetValue("F6", (3 + i).ToString()); + jsonlist[i] = newDoc2; + newDoc2 = null; + } + Result r = col.Add(jsonlist).Execute(); + Assert.AreEqual(1000, r.AffectedItemsCount, "Matching"); + int countgenerateIDs = r.GeneratedIds.Count; + for (int i = 0; i < countgenerateIDs; i++) + { + idStringList.Add(r.GeneratedIds[i]); + } + + int j = 1; + for (int i = 0; i < idStringList.Count; i++) + { + if (j == idStringList.Count) + { + break; + } + VerifySequence(idStringList[i], idStringList[j]); + j++; + } + return Task.FromResult(0); + } + + ///// + ///// Bug24397888 + ///// + [Test, Description("WHEN A DBDOC IS PASSED AS OBJ TO SETVALUE OF ANOTHER DBDOC IT CONVERTS TO BLANK")] + public void DbDocAsObjectConvertToBlank() + { + string newLine = Platform.IsWindows() ? "\r\n" : "\n"; + + var col = CreateCollection("my_collection"); + var data1 = new DbDoc(@"{ ""id"": 1, ""pages"": 20, + ""person"": { ""name"": ""Fred"", ""age"": 45 } + }"); + DbDoc d2 = new DbDoc(); + d2.SetValue("id", 1); + d2.SetValue("pages", 20); + d2.SetValue("taker1", data1); + string expected = $"{{{newLine} \"id\": 1, {newLine} \"pages\": 20, {newLine} \"taker1\": {{{newLine} \"id\": 1, {newLine} \"pages\": 20, {newLine} \"person\": {{{newLine} \"name\": \"Fred\", {newLine} \"age\": 45{newLine} }}{newLine} }}{newLine}}}"; + Assert.AreEqual(expected, d2.ToString()); + } + + [Test, Description("ADDITION OF OBJ FAILS AFTER CREATE INDEX IN 5.7.12 SERVER(WORKS WITH 5.7.9)")] + public void AdditionOfObject() + { + Collection testColl = CreateCollection("test"); + testColl.CreateIndex("testIndex", "{\"fields\": [ { \"field\":$.myId, \"type\":\"INT\" , \"required\":true} ] }"); + testColl.CreateIndex("testIndex1", "{\"fields\": [ { \"field\":$.myAge, \"type\":\"FLOAT\" , \"required\":true} ] }"); + var result = testColl.Add(new { myId = 1, myAge = 35.1, _id = 1 }).Execute(); + Assert.AreEqual(1, result.AffectedItemsCount); + } + + [Test, Description("Test valid insert at Depth n for multiple arrays))")] + public void InsertAtNDepth() + { + if (!session.Version.isAtLeast(8, 0, 3)) return; + string json = ""; + int i = 0, j = 0, maxField = 100; + var collection = CreateCollection("test"); + int maxDepth = 97; + json = "{\"_id\":\"1002\",\"XYZ\":1111"; + for (j = 0; j < maxField; j++) + { + json = json + ",\"ARR" + j + "\":["; + for (i = 0; i < maxDepth; i++) + { + json = json + i + ",["; + } + json = json + i; + for (i = maxDepth - 1; i >= 0; i--) + { + json = json + "]," + i; + } + json = json + "]"; + } + json = json + "}"; + + var res = collection.Add(json).Execute(); + Assert.AreEqual(1, res.AffectedItemsCount); + } + + #endregion WL14389 + + #region Methods + + public void VerifyGeneratedID(string input) + { + byte[] array = Encoding.ASCII.GetBytes(input); + Assert.False(array.Length < 28); + + byte[] uniquePrefix = new byte[4]; + Array.Copy(array, 0, uniquePrefix, 0, 4); + + Assert.AreEqual(System.Text.Encoding.UTF8.GetString(uniquePrefix), System.Text.Encoding.UTF8.GetString(uniquePrefix), + "Unique Prefix of the Generated ID"); + + byte[] startTimeStamp = new byte[8]; + Array.Copy(array, 4, startTimeStamp, 0, 8); + Assert.AreEqual(System.Text.Encoding.UTF8.GetString(startTimeStamp), System.Text.Encoding.UTF8.GetString(startTimeStamp), + "StartTimeStamp of the Generated ID"); + + byte[] serial = new byte[16]; + Array.Copy(array, 12, serial, 0, 16); + Assert.AreEqual(System.Text.Encoding.UTF8.GetString(serial), System.Text.Encoding.UTF8.GetString(serial), + "Serial Number of the Generated ID"); + } + + public bool VerifySequence(string input1, string input2) + { + byte[] array1 = Encoding.ASCII.GetBytes(input1); + Assert.False(array1.Length < 28); + byte[] array2 = Encoding.ASCII.GetBytes(input2); + Assert.False(array2.Length < 28); + Assert.AreNotEqual(input1, input2); + string incrementedString = Increment(input1, Mode.AlphaNumeric); + if (incrementedString.Equals(input2)) + { + return true; + } + else + { + return false; + } + } + public static string Increment(string text, Mode mode) + { + var textArr = text.ToCharArray(); + var characters = new List(); + + if (mode == Mode.AlphaNumeric || mode == Mode.Numeric) + for (char c = '0'; c <= '9'; c++) + characters.Add(c); + + if (mode == Mode.AlphaNumeric || mode == Mode.Alpha) + for (char c = 'a'; c <= 'f'; c++) + characters.Add(c); + + // Loop from end to beginning + for (int i = textArr.Length - 1; i >= 0; i--) + { + if (textArr[i] == characters.Last()) + { + textArr[i] = characters.First(); + } + else + { + textArr[i] = characters[characters.IndexOf(textArr[i]) + 1]; + break; + } + } + + return new string(textArr); + } + public enum Mode + { + AlphaNumeric = 1, + Alpha = 2, + Numeric = 3 + } + + #endregion Methods + } +} diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/CrudRemoveTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/CrudRemoveTests.cs index 7d394bf52..b2736ef38 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/CrudRemoveTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/CrudRemoveTests.cs @@ -1,380 +1,380 @@ -// Copyright (c) 2015, 2022, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySqlX.XDevAPI; -using MySqlX.XDevAPI.Common; -using NUnit.Framework; -using System; -using System.Collections.Generic; - -namespace MySqlX.Data.Tests -{ - public class CrudRemoveTests : BaseTest - { - [Test] - public void RemoveSingleDocumentById() - { - Collection coll = CreateCollection("test"); - var docs = new[]{ - new { _id = 12, title = "Book 1", pages = 20 }, - new { _id = 34, title = "Book 2", pages = 30 }, - new { _id = 56, title = "Book 3", pages = 40 }, - }; - Result r = ExecuteAddStatement(coll.Add(docs)); - Assert.AreEqual(3, r.AffectedItemsCount); - - // Remove with condition. - r = ExecuteRemoveStatement(coll.Remove("_id = 12")); - Assert.AreEqual(1, r.AffectedItemsCount); - - // Remove by ID. - r = coll.RemoveOne(34); - Assert.AreEqual(1, r.AffectedItemsCount); - - var ex = Assert.Throws(() => coll.Remove("")); -#if !NETFRAMEWORK - Assert.AreEqual("Parameter can't be null or empty. (Parameter 'condition')", ex.Message); -#else - Assert.AreEqual("Parameter can't be null or empty.\r\nParameter name: condition", ex.Message); -#endif - } - - [Test] - public void RemoveMultipleDocuments() - { - Collection coll = CreateCollection("test"); - var docs = new[] - { - new { _id = 1, title = "Book 1", pages = 20 }, - new { _id = 2, title = "Book 2", pages = 30 }, - new { _id = 3, title = "Book 3", pages = 40 }, - new { _id = 4, title = "Book 4", pages = 50 }, - }; - Result r = ExecuteAddStatement(coll.Add(docs)); - Assert.AreEqual(4, r.AffectedItemsCount); - - r = ExecuteRemoveStatement(coll.Remove("pages > 20")); - Assert.AreEqual(3, r.AffectedItemsCount); - } - - [Test] - public void RemoveMultipleDocumentsWithLimit() - { - Collection coll = CreateCollection("test"); - var docs = new[] - { - new { _id = 1, title = "Book 1", pages = 20 }, - new { _id = 2, title = "Book 2", pages = 30 }, - new { _id = 3, title = "Book 3", pages = 40 }, - new { _id = 4, title = "Book 4", pages = 50 }, - }; - Result r = ExecuteAddStatement(coll.Add(docs)); - Assert.AreEqual(4, r.AffectedItemsCount); - - r = ExecuteRemoveStatement(coll.Remove("pages > 20").Limit(1)); - Assert.AreEqual(1, r.AffectedItemsCount); - - // Limit out of range. - Assert.Throws(() => ExecuteRemoveStatement(coll.Remove("True").Limit(0))); - Assert.Throws(() => ExecuteRemoveStatement(coll.Remove("True").Limit(-2))); - Assert.Throws(() => ExecuteRemoveStatement(coll.Remove("pages > 10").Limit(0))); - Assert.Throws(() => ExecuteRemoveStatement(coll.Remove("pages > 20").Limit(-3))); - } - - [Test] - public void RemoveMultipleDocumentsWithLimitAndOrder() - { - Collection coll = CreateCollection("test"); - var docs = new[] - { - new { _id = 1, title = "Book 1", pages = 20 }, - new { _id = 2, title = "Book 2", pages = 30 }, - new { _id = 3, title = "Book 3", pages = 40 }, - new { _id = 4, title = "Book 4", pages = 50 }, - }; - Result r = ExecuteAddStatement(coll.Add(docs)); - Assert.AreEqual(4, r.AffectedItemsCount); - - r = ExecuteRemoveStatement(coll.Remove("pages > 20").Limit(1)); - Assert.AreEqual(1, r.AffectedItemsCount); - } - - [Test] - public void RemovingDocWithNoIdThrowsException() - { - Collection coll = CreateCollection("test"); - DbDoc doc = new DbDoc(); - Exception ex = Assert.Throws(() => ExecuteRemoveStatement(coll.Remove("_id = :id").Bind("id", doc.Id))); - } - - [Test] - public void RemoveBind() - { - Collection coll = CreateCollection("test"); - var docs = new[] - { - new { _id = 1, title = "Book 1", pages = 20 }, - new { _id = 2, title = "Book 2", pages = 30 }, - new { _id = 3, title = "Book 3", pages = 40 }, - new { _id = 4, title = "Book 4", pages = 50 }, - }; - Result r = ExecuteAddStatement(coll.Add(docs)); - Assert.AreEqual(4, r.AffectedItemsCount); - - r = ExecuteRemoveStatement(coll.Remove("pages = :Pages").Bind("pAges", 50)); - Assert.AreEqual(1, r.AffectedItemsCount); - - var jsonParams = new { pages1 = 30, pages2 = 40 }; - var res = coll.Remove("pages = :Pages1 || pages = :Pages2").Bind(jsonParams).Execute(); - Assert.AreEqual(2, res.AffectedItemsCount); - - DbDoc docParams = new DbDoc(new { pages1 = 10, pages2 = 20 }); - coll.Remove("pages = :Pages1 || pages = :Pages2").Bind(docParams).Execute(); - Assert.True(res.AffectedItemsCount > 0); - } - - [Test] - public void RemoveAll() - { - Collection collection = CreateCollection("test"); - var docs = new[] - { - new { _id = 1, title = "Book 1", pages = 20 }, - new { _id = 2, title = "Book 2", pages = 30 }, - new { _id = 3, title = "Book 3", pages = 40 }, - new { _id = 4, title = "Book 4", pages = 50 }, - }; - Result result = ExecuteAddStatement(collection.Add(docs)); - Assert.AreEqual(4, result.AffectedItemsCount); - - // Condition can't be null or empty. - string errorMessage = string.Empty; -#if !NETFRAMEWORK - errorMessage = "Parameter can't be null or empty. (Parameter 'condition')"; -#else - errorMessage = "Parameter can't be null or empty.\r\nParameter name: condition"; -#endif - Exception ex = Assert.Throws(() => ExecuteRemoveStatement(collection.Remove(string.Empty))); - Assert.AreEqual(errorMessage, ex.Message); - ex = Assert.Throws(() => ExecuteRemoveStatement(collection.Remove(""))); - Assert.AreEqual(errorMessage, ex.Message); - ex = Assert.Throws(() => ExecuteRemoveStatement(collection.Remove(" "))); - Assert.AreEqual(errorMessage, ex.Message); - ex = Assert.Throws(() => ExecuteRemoveStatement(collection.Remove(" "))); - Assert.AreEqual(errorMessage, ex.Message); - - // Sending an expression that evaluates to true applies changes on all documents. - result = ExecuteRemoveStatement(collection.Remove("true")); - Assert.AreEqual(4, result.AffectedItemsCount); - } - - [Test] - public void RemoveWithInOperator() - { - if (!session.InternalSession.GetServerVersion().isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); - - Collection collection = CreateCollection("test"); - var docs = new[] - { - new DbDoc("{ \"a\": 1, \"b\": \"foo\", \"c\": { \"d\": true, \"e\": [1,2,3] }, \"f\": [ {\"x\":5}, {\"x\":7 } ] }"), - new DbDoc("{ \"a\": 2, \"b\": \"foo2\", \"c\": { \"d\": true, \"e\": [4,5,6] }, \"f\": [ {\"x\":5}, {\"x\":8 } ] }"), - new DbDoc("{ \"a\": 1, \"b\": \"foo3\", \"c\": { \"d\": true, \"e\": [1,4,3] }, \"f\": [ {\"x\":6}, {\"x\":9 } ] }"), - }; - Result result = ExecuteAddStatement(collection.Add(docs)); - Assert.AreEqual(3, result.AffectedItemsCount); - - Assert.AreEqual(1, ExecuteRemoveStatement(collection.Remove("a IN (2,3)")).AffectedItemsCount); - Assert.AreEqual(2, ExecuteFindStatement(collection.Find()).FetchAll().Count); - - Assert.AreEqual(0, ExecuteRemoveStatement(collection.Remove("a IN [3]")).AffectedItemsCount); - Assert.AreEqual(2, ExecuteFindStatement(collection.Find()).FetchAll().Count); - - Assert.AreEqual(2, ExecuteRemoveStatement(collection.Remove("1 IN c.e")).AffectedItemsCount); - CollectionAssert.IsEmpty(ExecuteFindStatement(collection.Find()).FetchAll()); - } - - [Test] - public void RemoveOne() - { - Collection collection = CreateCollection("test"); - var docs = new[] - { - new { _id = 1, title = "Book 1", pages = 20 }, - new { _id = 2, title = "Book 2", pages = 30 }, - new { _id = 3, title = "Book 3", pages = 40 }, - new { _id = 4, title = "Book 4", pages = 50 }, - }; - Result result = ExecuteAddStatement(collection.Add(docs)); - Assert.AreEqual(4, result.AffectedItemsCount); - - ExecuteAddStatement(collection.Add(new { _id = 5, title = "Book 5", pages = 60 })); - Assert.AreEqual(5, ExecuteFindStatement(collection.Find()).FetchAll().Count); - - // Remove sending numeric parameter. - Assert.AreEqual(1, collection.RemoveOne(1).AffectedItemsCount); - Assert.AreEqual(4, ExecuteFindStatement(collection.Find()).FetchAll().Count); - - // Remove sending string parameter. - Assert.AreEqual(1, collection.RemoveOne("3").AffectedItemsCount); - Assert.AreEqual(3, ExecuteFindStatement(collection.Find()).FetchAll().Count); - - // Remove an auto-generated id. - DbDoc document = ExecuteFindStatement(collection.Find("pages = 60")).FetchOne(); - Assert.AreEqual(1, collection.RemoveOne(document.Id).AffectedItemsCount); - Assert.AreEqual(2, ExecuteFindStatement(collection.Find()).FetchAll().Count); - - // Remove a non-existing document. - Assert.AreEqual(0, collection.RemoveOne(5).AffectedItemsCount); - Assert.AreEqual(2, ExecuteFindStatement(collection.Find()).FetchAll().Count); - - // Expected exceptions. - Assert.Throws(() => collection.RemoveOne(null)); - Assert.Throws(() => collection.RemoveOne("")); - Assert.Throws(() => collection.RemoveOne(string.Empty)); - } - - #region WL14389 - - [Test, Description("MySQLX CNET Forbid remove() with no condition-Scenario-2")] - public void ForbidRemoveWithNoCondition() - { - Collection collection = CreateCollection("test"); - var docs = new[] - { - new { _id = 1, title = "Book 1", pages = 20 }, - new { _id = 2, title = "Book 2", pages = 30 }, - new { _id = 3, title = "Book 3", pages = 40 }, - new { _id = 4, title = "Book 4", pages = 50 }, - }; - Result result = collection.Add(docs).Execute(); - Assert.AreEqual(4, result.AffectedItemsCount); - - result = collection.Remove("_id = 1").Execute(); - Assert.AreEqual(1, result.AffectedItemsCount); - result = collection.Remove("_id = 10").Execute(); - Assert.AreEqual(0, result.AffectedItemsCount); - result = collection.Remove("_id = 2").Execute(); - Assert.AreEqual(1, result.AffectedItemsCount); - result = collection.Remove("_id = 10").Execute(); - Assert.AreEqual(0, result.AffectedItemsCount); - Assert.Throws(() => collection.Remove("")); - } - - [Test, Description("Test MySQLX plugin MySQL Net 846 - Collection Unset Multiple")] - public void CollectionUnsetMultiple() - { - Collection col = CreateCollection("my_collection_1"); - - var d1 = new DbDoc(); - d1.SetValue("_id", 1); - d1.SetValue("books", "test1"); - d1.SetValue("count", 10); - - var d2 = new DbDoc(); - d2.SetValue("_id", 2); - d2.SetValue("books", "test2"); - d2.SetValue("count", 20); - - var d3 = new DbDoc(); - d3.SetValue("_id", 3); - d3.SetValue("books", "test3"); - d3.SetValue("count", 30); - - var d4 = new DbDoc(); - d4.SetValue("_id", 4); - d4.SetValue("books", "test4"); - d4.SetValue("count", 40); - - var d5 = new DbDoc(); - d5.SetValue("_id", 5); - d5.SetValue("books", "test5"); - d5.SetValue("count", 50); - - var d6 = new DbDoc(); - d6.SetValue("_id", 6); - d6.SetValue("books", "test6"); - d6.SetValue("count", 0); - - var d7 = new DbDoc(); - d7.SetValue("_id", 0); - d7.SetValue("books", "test7"); - d7.SetValue("count", 60); - - var final = col.Add(d1, d2).Add(d3).Execute(); - - var res1 = col.Find().Fields("{\"_id\":\"1\",\"books\": \"test1\" }").Fields("{\"_id\":\"2\",\"books\": \"test2\" }").Fields("{\"_id\":\"3\",\"books\": \"test3\" }").Execute().FetchAll(); - res1 = col.Find().Fields(new string[] { "_id", "books", "count" }).Execute().FetchAll(); - Assert.AreEqual(3, res1.Count, "Matching the find count"); - Assert.AreEqual(d1.ToString(), res1[0].ToString(), "Matching the doc string 1"); - Assert.AreEqual(d2.ToString(), res1[1].ToString(), "Matching the doc string 2"); - Assert.AreEqual(d3.ToString(), res1[2].ToString(), "Matching the doc string 3"); - final = col.Add(new DbDoc[] { d4, d5 }).Execute(); - var res2 = col.Find().Fields("$._id as _id,$.books as books, $.count as count").Execute().FetchAll(); - Assert.AreEqual(5, res2.Count, "Matching the find count"); - Assert.AreEqual(d1.ToString(), res2[0].ToString(), "Matching the doc string 1"); - Assert.AreEqual(d2.ToString(), res2[1].ToString(), "Matching the doc string 2"); - Assert.AreEqual(d3.ToString(), res2[2].ToString(), "Matching the doc string 3"); - Assert.AreEqual(d4.ToString(), res2[3].ToString(), "Matching the doc string 4"); - Assert.AreEqual(d5.ToString(), res2[4].ToString(), "Matching the doc string 5"); - final = col.Add(d6, d7).Execute(); - var res3 = col.Find().Sort("count ASC").Execute().FetchAll(); - Assert.AreEqual(d6.ToString(), res3[0].ToString(), "Matching the doc string 7"); - Assert.AreEqual(d1.ToString(), res3[1].ToString(), "Matching the doc string 1"); - Assert.AreEqual(d2.ToString(), res3[2].ToString(), "Matching the doc string 2"); - Assert.AreEqual(d3.ToString(), res3[3].ToString(), "Matching the doc string 3"); - Assert.AreEqual(d4.ToString(), res3[4].ToString(), "Matching the doc string 4"); - Assert.AreEqual(d5.ToString(), res3[5].ToString(), "Matching the doc string 5"); - Assert.AreEqual(d7.ToString(), res3[6].ToString(), "Matching the doc string 6"); - var res4 = col.Find().Sort("count DESC").Execute().FetchAll(); - Assert.AreEqual(d7.ToString(), res4[0].ToString(), "Matching the doc string 6"); - Assert.AreEqual(d5.ToString(), res4[1].ToString(), "Matching the doc string 1"); - Assert.AreEqual(d4.ToString(), res4[2].ToString(), "Matching the doc string 2"); - Assert.AreEqual(d3.ToString(), res4[3].ToString(), "Matching the doc string 3"); - Assert.AreEqual(d2.ToString(), res4[4].ToString(), "Matching the doc string 4"); - Assert.AreEqual(d1.ToString(), res4[5].ToString(), "Matching the doc string 5"); - Assert.AreEqual(d6.ToString(), res4[6].ToString(), "Matching the doc string 7"); - //Unset with multiple variables not supported - col.Modify("_id = 1").Unset(new string[] { "count", "books" }).Execute(); - col.Modify("_id = 1").Set("count", 10).Set("books", "test1").Execute(); - - } - - [Test, Description("Test MySQLX plugin RemovingItemUsingDbDoc")] - public void RemovingItemUsingDbDoc() - { - Collection coll = CreateCollection("test"); - DbDoc doc = new DbDoc(new { _id = 1, title = "Book 1", pages = 20 }); - Result r = coll.Add(doc).Execute(); - Assert.AreEqual(1, (int)r.AffectedItemsCount, "Match being done"); - r = coll.Remove("_id=1").Execute(); - Assert.AreEqual(1, (int)r.AffectedItemsCount, "Match being done"); - } - - #endregion WL14389 - } -} +// Copyright © 2015, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySqlX.XDevAPI; +using MySqlX.XDevAPI.Common; +using NUnit.Framework; +using System; +using System.Collections.Generic; + +namespace MySqlX.Data.Tests +{ + public class CrudRemoveTests : BaseTest + { + [Test] + public void RemoveSingleDocumentById() + { + Collection coll = CreateCollection("test"); + var docs = new[]{ + new { _id = 12, title = "Book 1", pages = 20 }, + new { _id = 34, title = "Book 2", pages = 30 }, + new { _id = 56, title = "Book 3", pages = 40 }, + }; + Result r = ExecuteAddStatement(coll.Add(docs)); + Assert.AreEqual(3, r.AffectedItemsCount); + + // Remove with condition. + r = ExecuteRemoveStatement(coll.Remove("_id = 12")); + Assert.AreEqual(1, r.AffectedItemsCount); + + // Remove by ID. + r = coll.RemoveOne(34); + Assert.AreEqual(1, r.AffectedItemsCount); + + var ex = Assert.Throws(() => coll.Remove("")); +#if !NETFRAMEWORK + Assert.AreEqual("Parameter can't be null or empty. (Parameter 'condition')", ex.Message); +#else + Assert.AreEqual("Parameter can't be null or empty.\r\nParameter name: condition", ex.Message); +#endif + } + + [Test] + public void RemoveMultipleDocuments() + { + Collection coll = CreateCollection("test"); + var docs = new[] + { + new { _id = 1, title = "Book 1", pages = 20 }, + new { _id = 2, title = "Book 2", pages = 30 }, + new { _id = 3, title = "Book 3", pages = 40 }, + new { _id = 4, title = "Book 4", pages = 50 }, + }; + Result r = ExecuteAddStatement(coll.Add(docs)); + Assert.AreEqual(4, r.AffectedItemsCount); + + r = ExecuteRemoveStatement(coll.Remove("pages > 20")); + Assert.AreEqual(3, r.AffectedItemsCount); + } + + [Test] + public void RemoveMultipleDocumentsWithLimit() + { + Collection coll = CreateCollection("test"); + var docs = new[] + { + new { _id = 1, title = "Book 1", pages = 20 }, + new { _id = 2, title = "Book 2", pages = 30 }, + new { _id = 3, title = "Book 3", pages = 40 }, + new { _id = 4, title = "Book 4", pages = 50 }, + }; + Result r = ExecuteAddStatement(coll.Add(docs)); + Assert.AreEqual(4, r.AffectedItemsCount); + + r = ExecuteRemoveStatement(coll.Remove("pages > 20").Limit(1)); + Assert.AreEqual(1, r.AffectedItemsCount); + + // Limit out of range. + Assert.Throws(() => ExecuteRemoveStatement(coll.Remove("True").Limit(0))); + Assert.Throws(() => ExecuteRemoveStatement(coll.Remove("True").Limit(-2))); + Assert.Throws(() => ExecuteRemoveStatement(coll.Remove("pages > 10").Limit(0))); + Assert.Throws(() => ExecuteRemoveStatement(coll.Remove("pages > 20").Limit(-3))); + } + + [Test] + public void RemoveMultipleDocumentsWithLimitAndOrder() + { + Collection coll = CreateCollection("test"); + var docs = new[] + { + new { _id = 1, title = "Book 1", pages = 20 }, + new { _id = 2, title = "Book 2", pages = 30 }, + new { _id = 3, title = "Book 3", pages = 40 }, + new { _id = 4, title = "Book 4", pages = 50 }, + }; + Result r = ExecuteAddStatement(coll.Add(docs)); + Assert.AreEqual(4, r.AffectedItemsCount); + + r = ExecuteRemoveStatement(coll.Remove("pages > 20").Limit(1)); + Assert.AreEqual(1, r.AffectedItemsCount); + } + + [Test] + public void RemovingDocWithNoIdThrowsException() + { + Collection coll = CreateCollection("test"); + DbDoc doc = new DbDoc(); + Exception ex = Assert.Throws(() => ExecuteRemoveStatement(coll.Remove("_id = :id").Bind("id", doc.Id))); + } + + [Test] + public void RemoveBind() + { + Collection coll = CreateCollection("test"); + var docs = new[] + { + new { _id = 1, title = "Book 1", pages = 20 }, + new { _id = 2, title = "Book 2", pages = 30 }, + new { _id = 3, title = "Book 3", pages = 40 }, + new { _id = 4, title = "Book 4", pages = 50 }, + }; + Result r = ExecuteAddStatement(coll.Add(docs)); + Assert.AreEqual(4, r.AffectedItemsCount); + + r = ExecuteRemoveStatement(coll.Remove("pages = :Pages").Bind("pAges", 50)); + Assert.AreEqual(1, r.AffectedItemsCount); + + var jsonParams = new { pages1 = 30, pages2 = 40 }; + var res = coll.Remove("pages = :Pages1 || pages = :Pages2").Bind(jsonParams).Execute(); + Assert.AreEqual(2, res.AffectedItemsCount); + + DbDoc docParams = new DbDoc(new { pages1 = 10, pages2 = 20 }); + coll.Remove("pages = :Pages1 || pages = :Pages2").Bind(docParams).Execute(); + Assert.True(res.AffectedItemsCount > 0); + } + + [Test] + public void RemoveAll() + { + Collection collection = CreateCollection("test"); + var docs = new[] + { + new { _id = 1, title = "Book 1", pages = 20 }, + new { _id = 2, title = "Book 2", pages = 30 }, + new { _id = 3, title = "Book 3", pages = 40 }, + new { _id = 4, title = "Book 4", pages = 50 }, + }; + Result result = ExecuteAddStatement(collection.Add(docs)); + Assert.AreEqual(4, result.AffectedItemsCount); + + // Condition can't be null or empty. + string errorMessage = string.Empty; +#if !NETFRAMEWORK + errorMessage = "Parameter can't be null or empty. (Parameter 'condition')"; +#else + errorMessage = "Parameter can't be null or empty.\r\nParameter name: condition"; +#endif + Exception ex = Assert.Throws(() => ExecuteRemoveStatement(collection.Remove(string.Empty))); + Assert.AreEqual(errorMessage, ex.Message); + ex = Assert.Throws(() => ExecuteRemoveStatement(collection.Remove(""))); + Assert.AreEqual(errorMessage, ex.Message); + ex = Assert.Throws(() => ExecuteRemoveStatement(collection.Remove(" "))); + Assert.AreEqual(errorMessage, ex.Message); + ex = Assert.Throws(() => ExecuteRemoveStatement(collection.Remove(" "))); + Assert.AreEqual(errorMessage, ex.Message); + + // Sending an expression that evaluates to true applies changes on all documents. + result = ExecuteRemoveStatement(collection.Remove("true")); + Assert.AreEqual(4, result.AffectedItemsCount); + } + + [Test] + public void RemoveWithInOperator() + { + if (!session.InternalSession.GetServerVersion().isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); + + Collection collection = CreateCollection("test"); + var docs = new[] + { + new DbDoc("{ \"a\": 1, \"b\": \"foo\", \"c\": { \"d\": true, \"e\": [1,2,3] }, \"f\": [ {\"x\":5}, {\"x\":7 } ] }"), + new DbDoc("{ \"a\": 2, \"b\": \"foo2\", \"c\": { \"d\": true, \"e\": [4,5,6] }, \"f\": [ {\"x\":5}, {\"x\":8 } ] }"), + new DbDoc("{ \"a\": 1, \"b\": \"foo3\", \"c\": { \"d\": true, \"e\": [1,4,3] }, \"f\": [ {\"x\":6}, {\"x\":9 } ] }"), + }; + Result result = ExecuteAddStatement(collection.Add(docs)); + Assert.AreEqual(3, result.AffectedItemsCount); + + Assert.AreEqual(1, ExecuteRemoveStatement(collection.Remove("a IN (2,3)")).AffectedItemsCount); + Assert.AreEqual(2, ExecuteFindStatement(collection.Find()).FetchAll().Count); + + Assert.AreEqual(0, ExecuteRemoveStatement(collection.Remove("a IN [3]")).AffectedItemsCount); + Assert.AreEqual(2, ExecuteFindStatement(collection.Find()).FetchAll().Count); + + Assert.AreEqual(2, ExecuteRemoveStatement(collection.Remove("1 IN c.e")).AffectedItemsCount); + CollectionAssert.IsEmpty(ExecuteFindStatement(collection.Find()).FetchAll()); + } + + [Test] + public void RemoveOne() + { + Collection collection = CreateCollection("test"); + var docs = new[] + { + new { _id = 1, title = "Book 1", pages = 20 }, + new { _id = 2, title = "Book 2", pages = 30 }, + new { _id = 3, title = "Book 3", pages = 40 }, + new { _id = 4, title = "Book 4", pages = 50 }, + }; + Result result = ExecuteAddStatement(collection.Add(docs)); + Assert.AreEqual(4, result.AffectedItemsCount); + + ExecuteAddStatement(collection.Add(new { _id = 5, title = "Book 5", pages = 60 })); + Assert.AreEqual(5, ExecuteFindStatement(collection.Find()).FetchAll().Count); + + // Remove sending numeric parameter. + Assert.AreEqual(1, collection.RemoveOne(1).AffectedItemsCount); + Assert.AreEqual(4, ExecuteFindStatement(collection.Find()).FetchAll().Count); + + // Remove sending string parameter. + Assert.AreEqual(1, collection.RemoveOne("3").AffectedItemsCount); + Assert.AreEqual(3, ExecuteFindStatement(collection.Find()).FetchAll().Count); + + // Remove an auto-generated id. + DbDoc document = ExecuteFindStatement(collection.Find("pages = 60")).FetchOne(); + Assert.AreEqual(1, collection.RemoveOne(document.Id).AffectedItemsCount); + Assert.AreEqual(2, ExecuteFindStatement(collection.Find()).FetchAll().Count); + + // Remove a non-existing document. + Assert.AreEqual(0, collection.RemoveOne(5).AffectedItemsCount); + Assert.AreEqual(2, ExecuteFindStatement(collection.Find()).FetchAll().Count); + + // Expected exceptions. + Assert.Throws(() => collection.RemoveOne(null)); + Assert.Throws(() => collection.RemoveOne("")); + Assert.Throws(() => collection.RemoveOne(string.Empty)); + } + + #region WL14389 + + [Test, Description("MySQLX CNET Forbid remove() with no condition-Scenario-2")] + public void ForbidRemoveWithNoCondition() + { + Collection collection = CreateCollection("test"); + var docs = new[] + { + new { _id = 1, title = "Book 1", pages = 20 }, + new { _id = 2, title = "Book 2", pages = 30 }, + new { _id = 3, title = "Book 3", pages = 40 }, + new { _id = 4, title = "Book 4", pages = 50 }, + }; + Result result = collection.Add(docs).Execute(); + Assert.AreEqual(4, result.AffectedItemsCount); + + result = collection.Remove("_id = 1").Execute(); + Assert.AreEqual(1, result.AffectedItemsCount); + result = collection.Remove("_id = 10").Execute(); + Assert.AreEqual(0, result.AffectedItemsCount); + result = collection.Remove("_id = 2").Execute(); + Assert.AreEqual(1, result.AffectedItemsCount); + result = collection.Remove("_id = 10").Execute(); + Assert.AreEqual(0, result.AffectedItemsCount); + Assert.Throws(() => collection.Remove("")); + } + + [Test, Description("Test MySQLX plugin MySQL Net 846 - Collection Unset Multiple")] + public void CollectionUnsetMultiple() + { + Collection col = CreateCollection("my_collection_1"); + + var d1 = new DbDoc(); + d1.SetValue("_id", 1); + d1.SetValue("books", "test1"); + d1.SetValue("count", 10); + + var d2 = new DbDoc(); + d2.SetValue("_id", 2); + d2.SetValue("books", "test2"); + d2.SetValue("count", 20); + + var d3 = new DbDoc(); + d3.SetValue("_id", 3); + d3.SetValue("books", "test3"); + d3.SetValue("count", 30); + + var d4 = new DbDoc(); + d4.SetValue("_id", 4); + d4.SetValue("books", "test4"); + d4.SetValue("count", 40); + + var d5 = new DbDoc(); + d5.SetValue("_id", 5); + d5.SetValue("books", "test5"); + d5.SetValue("count", 50); + + var d6 = new DbDoc(); + d6.SetValue("_id", 6); + d6.SetValue("books", "test6"); + d6.SetValue("count", 0); + + var d7 = new DbDoc(); + d7.SetValue("_id", 0); + d7.SetValue("books", "test7"); + d7.SetValue("count", 60); + + var final = col.Add(d1, d2).Add(d3).Execute(); + + var res1 = col.Find().Fields("{\"_id\":\"1\",\"books\": \"test1\" }").Fields("{\"_id\":\"2\",\"books\": \"test2\" }").Fields("{\"_id\":\"3\",\"books\": \"test3\" }").Execute().FetchAll(); + res1 = col.Find().Fields(new string[] { "_id", "books", "count" }).Execute().FetchAll(); + Assert.AreEqual(3, res1.Count, "Matching the find count"); + Assert.AreEqual(d1.ToString(), res1[0].ToString(), "Matching the doc string 1"); + Assert.AreEqual(d2.ToString(), res1[1].ToString(), "Matching the doc string 2"); + Assert.AreEqual(d3.ToString(), res1[2].ToString(), "Matching the doc string 3"); + final = col.Add(new DbDoc[] { d4, d5 }).Execute(); + var res2 = col.Find().Fields("$._id as _id,$.books as books, $.count as count").Execute().FetchAll(); + Assert.AreEqual(5, res2.Count, "Matching the find count"); + Assert.AreEqual(d1.ToString(), res2[0].ToString(), "Matching the doc string 1"); + Assert.AreEqual(d2.ToString(), res2[1].ToString(), "Matching the doc string 2"); + Assert.AreEqual(d3.ToString(), res2[2].ToString(), "Matching the doc string 3"); + Assert.AreEqual(d4.ToString(), res2[3].ToString(), "Matching the doc string 4"); + Assert.AreEqual(d5.ToString(), res2[4].ToString(), "Matching the doc string 5"); + final = col.Add(d6, d7).Execute(); + var res3 = col.Find().Sort("count ASC").Execute().FetchAll(); + Assert.AreEqual(d6.ToString(), res3[0].ToString(), "Matching the doc string 7"); + Assert.AreEqual(d1.ToString(), res3[1].ToString(), "Matching the doc string 1"); + Assert.AreEqual(d2.ToString(), res3[2].ToString(), "Matching the doc string 2"); + Assert.AreEqual(d3.ToString(), res3[3].ToString(), "Matching the doc string 3"); + Assert.AreEqual(d4.ToString(), res3[4].ToString(), "Matching the doc string 4"); + Assert.AreEqual(d5.ToString(), res3[5].ToString(), "Matching the doc string 5"); + Assert.AreEqual(d7.ToString(), res3[6].ToString(), "Matching the doc string 6"); + var res4 = col.Find().Sort("count DESC").Execute().FetchAll(); + Assert.AreEqual(d7.ToString(), res4[0].ToString(), "Matching the doc string 6"); + Assert.AreEqual(d5.ToString(), res4[1].ToString(), "Matching the doc string 1"); + Assert.AreEqual(d4.ToString(), res4[2].ToString(), "Matching the doc string 2"); + Assert.AreEqual(d3.ToString(), res4[3].ToString(), "Matching the doc string 3"); + Assert.AreEqual(d2.ToString(), res4[4].ToString(), "Matching the doc string 4"); + Assert.AreEqual(d1.ToString(), res4[5].ToString(), "Matching the doc string 5"); + Assert.AreEqual(d6.ToString(), res4[6].ToString(), "Matching the doc string 7"); + //Unset with multiple variables not supported + col.Modify("_id = 1").Unset(new string[] { "count", "books" }).Execute(); + col.Modify("_id = 1").Set("count", 10).Set("books", "test1").Execute(); + + } + + [Test, Description("Test MySQLX plugin RemovingItemUsingDbDoc")] + public void RemovingItemUsingDbDoc() + { + Collection coll = CreateCollection("test"); + DbDoc doc = new DbDoc(new { _id = 1, title = "Book 1", pages = 20 }); + Result r = coll.Add(doc).Execute(); + Assert.AreEqual(1, (int)r.AffectedItemsCount, "Match being done"); + r = coll.Remove("_id=1").Execute(); + Assert.AreEqual(1, (int)r.AffectedItemsCount, "Match being done"); + } + + #endregion WL14389 + } +} diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/CrudTests/CrudGCTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/CrudTests/CrudGCTests.cs index 907e31c8b..c44326e07 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/CrudTests/CrudGCTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/CrudTests/CrudGCTests.cs @@ -1,60 +1,60 @@ -// Copyright (c) 2015, 2022, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySqlX.XDevAPI; -using MySqlX.XDevAPI.Common; -using System; -using NUnit.Framework; - -namespace MySqlX.Data.Tests.ResultTests -{ - public class CrudGCTests : BaseTest - { -#if NETFRAMEWORK - [Test] - public void FetchAllNoReference() - { - Collection testColl = CreateCollection("test"); - var stmt = testColl.Add(@"{ ""_id"": 1, ""foo"": 1 }"); - stmt.Add(@"{ ""_id"": 2, ""foo"": 2 }"); - stmt.Add(@"{ ""_id"": 3, ""foo"": 3 }"); - stmt.Add(@"{ ""_id"": 4, ""foo"": 4 }"); - Result result = ExecuteAddStatement(stmt); - Assert.AreEqual(4, (int)result.AffectedItemsCount); - - var docResult = ExecuteFindStatement(testColl.Find()); - var docs = docResult.FetchAll(); - WeakReference wr = new WeakReference(docResult); - docResult = null; - GC.Collect(); - Assert.False(wr.IsAlive); - Assert.AreEqual(4, docs.Count); - } -#endif - } -} \ No newline at end of file +// Copyright © 2015, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySqlX.XDevAPI; +using MySqlX.XDevAPI.Common; +using System; +using NUnit.Framework; + +namespace MySqlX.Data.Tests.ResultTests +{ + public class CrudGCTests : BaseTest + { +#if NETFRAMEWORK + [Test] + public void FetchAllNoReference() + { + Collection testColl = CreateCollection("test"); + var stmt = testColl.Add(@"{ ""_id"": 1, ""foo"": 1 }"); + stmt.Add(@"{ ""_id"": 2, ""foo"": 2 }"); + stmt.Add(@"{ ""_id"": 3, ""foo"": 3 }"); + stmt.Add(@"{ ""_id"": 4, ""foo"": 4 }"); + Result result = ExecuteAddStatement(stmt); + Assert.AreEqual(4, (int)result.AffectedItemsCount); + + var docResult = ExecuteFindStatement(testColl.Find()); + var docs = docResult.FetchAll(); + WeakReference wr = new WeakReference(docResult); + docResult = null; + GC.Collect(); + Assert.False(wr.IsAlive); + Assert.AreEqual(4, docs.Count); + } +#endif + } +} diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/CrudTests/DocBufferingTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/CrudTests/DocBufferingTests.cs index 5da347e2b..43eb2665f 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/CrudTests/DocBufferingTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/CrudTests/DocBufferingTests.cs @@ -1,61 +1,61 @@ -// Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySqlX.XDevAPI; -using MySqlX.XDevAPI.Common; -using NUnit.Framework; - -namespace MySqlX.Data.Tests.CrudTests -{ - public class DocBufferingTests : BaseTest - { - [Test] - public void SmartBuffering() - { - Collection test = CreateCollection("test"); - Collection test2 = CreateCollection("test2"); - - var docs = new[] - { - new { _id = 1, title = "Book 1", pages = 20 }, - new { _id = 2, title = "Book 2", pages = 30 }, - new { _id = 3, title = "Book 3", pages = 40 }, - new { _id = 4, title = "Book 4", pages = 50 }, - }; - Result r = ExecuteAddStatement(test.Add(docs)); - Assert.AreEqual(r.Warnings.Count, r.WarningsCount); - - var docResult = ExecuteFindStatement(test.Find()); - foreach (var doc in docResult) - { - var result = ExecuteAddStatement(test2.Add(doc)); - Assert.AreEqual(1, result.AffectedItemsCount); - } - } - } -} +// Copyright © 2015, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySqlX.XDevAPI; +using MySqlX.XDevAPI.Common; +using NUnit.Framework; + +namespace MySqlX.Data.Tests.CrudTests +{ + public class DocBufferingTests : BaseTest + { + [Test] + public void SmartBuffering() + { + Collection test = CreateCollection("test"); + Collection test2 = CreateCollection("test2"); + + var docs = new[] + { + new { _id = 1, title = "Book 1", pages = 20 }, + new { _id = 2, title = "Book 2", pages = 30 }, + new { _id = 3, title = "Book 3", pages = 40 }, + new { _id = 4, title = "Book 4", pages = 50 }, + }; + Result r = ExecuteAddStatement(test.Add(docs)); + Assert.AreEqual(r.Warnings.Count, r.WarningsCount); + + var docResult = ExecuteFindStatement(test.Find()); + foreach (var doc in docResult) + { + var result = ExecuteAddStatement(test2.Add(doc)); + Assert.AreEqual(1, result.AffectedItemsCount); + } + } + } +} diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/CrudUpdateTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/CrudUpdateTests.cs index 213ab2273..ba5ed2dd5 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/CrudUpdateTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/CrudUpdateTests.cs @@ -1,1282 +1,1282 @@ -// Copyright (c) 2015, 2023, Oracle and/or its affiliates. -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySql.Data; -using MySql.Data.MySqlClient; -using MySqlX.XDevAPI; -using MySqlX.XDevAPI.Common; -using NUnit.Framework; -using System; -using System.Collections.Generic; - -namespace MySqlX.Data.Tests -{ - public class CrudUpdateTests : BaseTest - { - [Test] - public void SetItemInSingleDocument() - { - Collection coll = CreateCollection("test"); - Result result = ExecuteAddStatement(coll.Add(new { _id = 1, name = "Book 1" })); - Assert.AreEqual(1, result.AffectedItemsCount); - - // Set integer value. - result = ExecuteModifyStatement(coll.Modify("_id = 1").Set("pages", "20")); - Assert.AreEqual(1, result.AffectedItemsCount); - Assert.AreEqual("20", coll.GetOne(1)["pages"]); - - // Set null value. - result = ExecuteModifyStatement(coll.Modify("_id = 1").Set("pages", null)); - Assert.AreEqual(1, result.AffectedItemsCount); - Assert.Null(coll.GetOne(1)["pages"]); - - // Set existing field. - result = ExecuteModifyStatement(coll.Modify("_id = 1").Set("name", "Book 2")); - Assert.AreEqual(1, result.AffectedItemsCount); - Assert.AreEqual("Book 2", coll.GetOne(1)["name"]); - - // Set alphanumeric field. - var document = new DbDoc(); - document.SetValue("_id", 2); - document.SetValue("1a", "other"); - result = ExecuteAddStatement(coll.Add(document)); - Assert.AreEqual(1, result.AffectedItemsCount); - var insertedDocument = coll.GetOne(2); - - //result = coll.Modify("_id = 1").Set("1a", "other")); - } - - [Test] - public void ChangeItemInSingleDocument() - { - Collection coll = CreateCollection("test"); - Result result = ExecuteAddStatement(coll.Add(new { _id = 1, name = "Book 1", pages = 20 })); - Assert.AreEqual(1, result.AffectedItemsCount); - - result = ExecuteModifyStatement(coll.Modify("_id = 1").Change("name", "Book 2")); - Assert.AreEqual(1, result.AffectedItemsCount); - } - - [Test] - public void RemoveItemInSingleDocumentUsingUnset() - { - Collection coll = CreateCollection("test"); - Result result = ExecuteAddStatement(coll - .Add(new { _id = 1, name = "Book 1", pages = 20 }) - .Add(new { _id = 2, name = "Book 2", pages = 30 }) - .Add(new { _id = 3, name = "Book 3", pages = 40, author = "John", author2 = "Mary" }) - ); - Assert.AreEqual(3, result.AffectedItemsCount); - - // Unset 1 field. - result = ExecuteModifyStatement(coll.Modify("_id = 1").Unset("pages")); - Assert.AreEqual(1, result.AffectedItemsCount); - var document = ExecuteFindStatement(coll.Find("_id = 1")).FetchOne(); - Assert.AreEqual(2, document.values.Count); - - // Unset multiple fields. - result = ExecuteModifyStatement(coll.Modify("_id = 2").Unset("name", "pages")); - Assert.AreEqual(1, result.AffectedItemsCount); - document = ExecuteFindStatement(coll.Find("_id = 2")).FetchOne(); - Assert.That(document.values, Has.One.Items); - result = ExecuteModifyStatement(coll.Modify("_id = 3").Unset(null, "author", "author2")); - document = ExecuteFindStatement(coll.Find("_id = 3")).FetchOne(); - Assert.AreEqual(3, document.values.Count); - - // Unsetting nonexistent fields doesn't raise an error. - result = ExecuteModifyStatement(coll.Modify("_id = 2").Unset("otherfield")); - Assert.AreEqual(0ul, result.AffectedItemsCount); - - // Unsetting null items combined with valid values are ignored. - result = ExecuteModifyStatement(coll.Modify("_id = 3").Unset(null).Unset("name")); - Assert.AreEqual(1ul, result.AffectedItemsCount); - document = ExecuteFindStatement(coll.Find("_id = 3")).FetchOne(); - Assert.AreEqual(2, document.values.Count); - - // Unsetting single null items raises an error - var ex = Assert.Throws(() => ExecuteModifyStatement(coll.Modify("_id = 3").Unset(null))); - Assert.AreEqual("Invalid update expression list", ex.Message); - - // Unsetting empty strings raises an error. - var ex2 = Assert.Throws(() => ExecuteModifyStatement(coll.Modify("_id = 2").Unset(""))); - Assert.AreEqual(ResourcesX.DocPathNullOrEmpty, ex2.Message); - ex2 = Assert.Throws(() => ExecuteModifyStatement(coll.Modify("_id = 2").Unset(string.Empty))); - Assert.AreEqual(ResourcesX.DocPathNullOrEmpty, ex2.Message); - - // Unset with special chars. - Assert.Throws(() => ExecuteModifyStatement(coll.Modify("_id = 3").Unset(null).Unset("@*%#�"))); - Assert.Throws(() => ExecuteModifyStatement(coll.Modify("_id = 3").Unset(null).Unset("******"))); - } - - [Test] - public void SetItemAndBind() - { - Collection coll = CreateCollection("test"); - Result result = ExecuteAddStatement(coll.Add(new { _id = 1, name = "Book 1" }) - .Add(new { _id = 2, name = "Book 2" })); - Assert.AreEqual(2, result.AffectedItemsCount); - - var stmt = coll.Modify("_id = :ID"); - result = ExecuteModifyStatement(stmt.Bind("Id", 2).Set("pages", "20")); - Assert.AreEqual(1, result.AffectedItemsCount); - result = ExecuteModifyStatement(stmt.Bind("Id", 1).Set("pages", 10)); Assert.AreEqual(1, result.AffectedItemsCount); - - var docs = ExecuteFindStatement(coll.Find()).FetchAll(); - Assert.AreEqual(new DbDoc("{ \"_id\": 1, \"name\": \"Book 1\", \"pages\": 10 }").ToString(), docs[0].ToString()); - Assert.AreEqual(new DbDoc("{ \"_id\": 2, \"name\": \"Book 2\", \"pages\": \"20\" }").ToString(), docs[1].ToString()); - } - - [Test] - public void ModifyAll() - { - Collection collection = CreateCollection("test"); - var docs = new[] - { - new { _id = 1, title = "Book 1", pages = 20 }, - new { _id = 2, title = "Book 2", pages = 30 }, - }; - Result result = ExecuteAddStatement(collection.Add(docs)); - Assert.AreEqual(2, result.AffectedItemsCount); - - // Condition can't be null or empty. - string errorMessage = string.Empty; -#if !NETFRAMEWORK - errorMessage = "Parameter can't be null or empty. (Parameter 'condition')"; -#else - errorMessage = "Parameter can't be null or empty.\r\nParameter name: condition"; -#endif - Exception ex = Assert.Throws(() => ExecuteModifyStatement(collection.Modify(string.Empty))); - Assert.AreEqual(ex.Message, errorMessage); - ex = Assert.Throws(() => ExecuteModifyStatement(collection.Modify(""))); - Assert.AreEqual(ex.Message, errorMessage); - ex = Assert.Throws(() => ExecuteModifyStatement(collection.Modify(" "))); - Assert.AreEqual(ex.Message, errorMessage); - ex = Assert.Throws(() => ExecuteModifyStatement(collection.Modify(" "))); - Assert.AreEqual(ex.Message, errorMessage); - ex = Assert.Throws(() => ExecuteModifyStatement(collection.Modify(null))); - Assert.AreEqual(ex.Message, errorMessage); - - // Sending an expression that evaluates to true applies changes on all documents. - result = ExecuteModifyStatement(collection.Modify("true").Set("pages", "10")); - Assert.AreEqual(2, result.AffectedItemsCount); - } - - [Test] - public void ModifyWithLimit() - { - Collection collection = CreateCollection("test"); - var docs = new[] - { - new { _id = 1, title = "Book 1", pages = 20 }, - new { _id = 2, title = "Book 2", pages = 30 }, - }; - Result result = ExecuteAddStatement(collection.Add(docs)); - Assert.AreEqual(2, result.AffectedItemsCount); - - ExecuteModifyStatement(collection.Modify("true").Set("title", "Book X").Limit(1)); - Assert.That(ExecuteFindStatement(collection.Find("title = \"Book X\"")).FetchAll(), Has.One.Items); - - // Limit out of range. - Assert.Throws(() => ExecuteModifyStatement(collection.Modify("true").Set("pages", 10).Limit(0))); - Assert.Throws(() => ExecuteModifyStatement(collection.Modify("true").Set("pages", 10).Limit(-10))); - } - - [Test] - public void ModifyWithInOperator() - { - if (!session.InternalSession.GetServerVersion().isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); - - Collection collection = CreateCollection("test"); - var docs = new[] - { - new DbDoc("{ \"a\": 1, \"b\": \"foo\", \"c\": { \"d\": true, \"e\": [1,2,3] }, \"f\": [ {\"x\":5}, {\"x\":7 } ] }"), - new DbDoc("{ \"a\": 2, \"b\": \"foo2\", \"c\": { \"d\": true, \"e\": [4,5,6] }, \"f\": [ {\"x\":5}, {\"x\":8 } ] }"), - new DbDoc("{ \"a\": 1, \"b\": \"foo3\", \"c\": { \"d\": true, \"e\": [1,4,3] }, \"f\": [ {\"x\":6}, {\"x\":9 } ] }"), - }; - Result result = ExecuteAddStatement(collection.Add(docs)); - Assert.AreEqual(3, result.AffectedItemsCount); - - Assert.AreEqual(3, ExecuteModifyStatement(collection.Modify("a IN (1,2)").Set("a", 3)).AffectedItemsCount); - Assert.AreEqual(3, ExecuteFindStatement(collection.Find().Where("a = 3")).FetchAll().Count); - - Assert.AreEqual(3, ExecuteModifyStatement(collection.Modify("a IN [3]").Set("a", 1)).AffectedItemsCount); - Assert.AreEqual(3, ExecuteFindStatement(collection.Find().Where("a = 1")).FetchAll().Count); - - Assert.AreEqual(2, ExecuteModifyStatement(collection.Modify("1 IN c.e").Set("c.e", "newValue")).AffectedItemsCount); - Assert.AreEqual(2, ExecuteFindStatement(collection.Find().Where("c.e = \"newValue\"")).FetchAll().Count); - } - - [Test] - public void ReplaceOne() - { - Collection collection = CreateCollection("test"); - var docs = new[] - { - new { _id = 1, title = "Book 1", pages = 20 }, - new { _id = 2, title = "Book 2", pages = 30 }, - new { _id = 3, title = "Book 3", pages = 40 }, - new { _id = 4, title = "Book 4", pages = 50 }, - }; - Result result = ExecuteAddStatement(collection.Add(docs)); - Assert.AreEqual(4, result.AffectedItemsCount); - - // Expected exceptions. - Assert.Throws(() => collection.ReplaceOne(null, docs[1])); - Assert.Throws(() => collection.ReplaceOne("", docs[1])); - Assert.Throws(() => collection.ReplaceOne(string.Empty, docs[1])); - Assert.Throws(() => collection.ReplaceOne("1", null)); - // Replace using no matching id - Assert.Throws(() => collection.ReplaceOne(3, new DbDoc("{ \"_id\": 2, \"name\": \"John\", \"lastName\": \"Smith\" }")), - ResourcesX.ReplaceWithNoMatchingId); - - var newDoc = new { _id = 1, title = "Book 11", pages = 311 }; - - // Replace using a numeric identifier. - Assert.AreEqual(1, collection.ReplaceOne(1, newDoc).AffectedItemsCount); - DbDoc document = collection.GetOne(1); - Assert.AreEqual(1, Convert.ToInt32(document.Id)); - Assert.AreEqual("Book 11", document["title"]); - Assert.AreEqual(311, Convert.ToInt32(document["pages"])); - - // Replace using a string identifier. - Assert.AreEqual(1, collection.ReplaceOne("2", new DbDoc("{ \"name\": \"John\", \"lastName\": \"Smith\" }")).AffectedItemsCount); - document = collection.GetOne(2); - Assert.AreEqual(2, Convert.ToInt32(document.Id)); - Assert.AreEqual("John", document["name"]); - Assert.AreEqual("Smith", document["lastName"]); - - // Replace a non-existing document. - Assert.AreEqual(0, collection.ReplaceOne(5, docs[1]).AffectedItemsCount); - Assert.True(collection.GetOne(5) == null); - } - - [Test] - public void ReplaceNestedDocument() - { - var collection = CreateCollection("test"); - var docs = new DbDoc[] - { - new DbDoc(@"{ ""_id"":1, ""pages"":20, ""title"":""Book 1"", ""person"": { ""name"": ""Fred"", ""age"":45 } }" ), - new DbDoc(@"{ ""_id"": 2, ""pages"": 30,""title"" : ""Book 2"", ""person"": { ""name"": ""Peter"", ""age"": 38 } }"), - new DbDoc(@"{ ""_id"": 3, ""pages"": 40,""title"" : ""Book 3"", ""person"": { ""name"": ""Andy"", ""age"": 25 } }"), - new DbDoc(@"{ ""_id"": 4, ""pages"": 50,""title"" : ""Book 4"", ""person"": { ""name"": ""John"", ""age"": 34 } }") - }; - Assert.AreEqual(4, ExecuteAddStatement(collection.Add(docs)).AffectedItemsCount); - - DbDoc d_new = new DbDoc(@"{ ""_id"": 1, ""pages"": 20,""title"" : ""Book 1"", ""person"": { ""name"": ""Fred"", ""age"": 45 ,""State"" : ""Ohio""} }"); - Assert.AreEqual(1, collection.ReplaceOne(1, d_new).AffectedItemsCount); - DbDoc document = collection.GetOne(1); - Assert.AreEqual("Ohio", (document.values["person"] as Dictionary)["State"]); - - d_new = new DbDoc(@"{ ""_id"": 1, ""pages"": 20,""title"" : ""Book 1"", ""person"": { ""name"": ""Fred"", ""age"": 45 ,""State"" : ""Ohio"", ""newProp"": { ""a"":33 } } }"); - Assert.AreEqual(1, collection.ReplaceOne(1, d_new).AffectedItemsCount); - document = collection.GetOne(1); - Assert.AreEqual(33, ((document.values["person"] as Dictionary)["newProp"] as Dictionary)["a"]); - } - - [Test] - public void ArrayInsert() - { - Collection collection = CreateCollection("test"); - ExecuteAddStatement(collection.Add("{ \"x\":[1,2] }")); - - // x[1]=43, x[2]=2. - ExecuteModifyStatement(collection.Modify("true").ArrayInsert("x[1]", 43)); - // x[3]=44. - ExecuteModifyStatement(collection.Modify("true").ArrayInsert("x[3]", 44)); - // Since array only contains 4 items the value 46 is assigned to x[4]. - ExecuteModifyStatement(collection.Modify("true").ArrayInsert("x[5]", 46)); - // Since array only contains 5 items the value 50 is assigned to x[5]. - ExecuteModifyStatement(collection.Modify("true").ArrayInsert("x[20]", 50)); - // Assign an item from different data type. - ExecuteModifyStatement(collection.Modify("true").ArrayInsert("x[6]", "string")); - // Assign a document. - ExecuteModifyStatement(collection.Modify("true").ArrayInsert("x[7]", "{ \"name\":\"Mike\" }")); - - var result = ExecuteFindStatement(collection.Find()); - var document = result.FetchOne(); - var x = (object[])document.values["x"]; - - Assert.AreEqual(8, x.Length); - Assert.AreEqual(1, (int)x[0]); - Assert.AreEqual(43, (int)x[1]); - Assert.AreEqual(2, (int)x[2]); - Assert.AreEqual(44, (int)x[3]); - Assert.AreEqual(46, (int)x[4]); - Assert.AreEqual(50, (int)x[5]); - Assert.AreEqual("string", x[6]); - Assert.True(new DbDoc(x[7]) is DbDoc); - - // No value is inserted if the array doesn't exist. - ExecuteModifyStatement(collection.Modify("true").ArrayInsert("y[0]", 1)); - - result = ExecuteFindStatement(collection.Find()); - document = result.FetchOne(); - Assert.False(document.values.ContainsKey("y")); - - ExecuteModifyStatement(collection.Modify("true").ArrayInsert("x[0]", null)); - ExecuteModifyStatement(collection.Modify("true").ArrayInsert("x[1]", " ")); - - result = ExecuteFindStatement(collection.Find()); - document = result.FetchOne(); - x = (object[])document.values["x"]; - Assert.Null(x[0]); - Assert.AreEqual(" ", x[1]); - - // Insert an empty string fails. - var ex = Assert.Throws(() => ExecuteModifyStatement(collection.Modify("true").ArrayInsert("x[0]", ""))); - StringAssert.Contains("String can't be empty.", ex.Message); - ex = Assert.Throws(() => ExecuteModifyStatement(collection.Modify("true").ArrayInsert("x[0]", string.Empty))); - StringAssert.Contains("String can't be empty.", ex.Message); - - // Not specifying an index raises an error. - var ex2 = Assert.Throws(() => ExecuteModifyStatement(collection.Modify("true").ArrayInsert("dates", "5/1/2018"))); - Assert.AreEqual("A path expression is not a path to a cell in an array.", ex2.Message); - - var col = CreateCollection("my_collection"); - var t1 = "{\"_id\": \"1001\", \"ARR\":[1,2,3], \"ARR1\":[\"name1\",\"name2\", \"name3\"]}"; - col.Add(t1).Execute(); - col.Modify("true").ArrayInsert("ARR[0]", 4).Execute(); - col.Modify("true").ArrayInsert("ARR1[0]", "name4").Execute(); - col.Modify("true").ArrayInsert("ARR[0]", "name5").Execute(); - col.Modify("true").ArrayInsert("ARR1[0]", 5).Execute(); - col.Modify("true").ArrayInsert("ARR[0]", 6).ArrayInsert("ARR1[0]", "name6").ArrayInsert("ARR[0]", 7).ArrayInsert("ARR[0]", 8).Execute(); - col.Modify("true").ArrayInsert("ARR1[0]", null).Execute(); - col.Modify("true").ArrayInsert("ARR1[0]", " ").Execute(); - col.Modify("true").ArrayInsert("ARR1[0]", "****").Execute(); - result = ExecuteFindStatement(col.Find()); - document = result.FetchOne(); - var x2 = (object[])document.values["ARR"]; - Assert.AreEqual(8, x2.Length); - Assert.AreEqual(8, (int)x2[0]); - x2 = (object[])document.values["ARR1"]; - Assert.AreEqual("****", x2[0]); - Assert.AreEqual("name3", x2[8]); - } - - [Test] - public void ArrayAppendWithMySqlExpression() - { - Collection collection = CreateCollection("test"); - - // String containing an expression is not evaluted. - ExecuteAddStatement(collection.Add("{ \"_id\":\"123\", \"name\":\"alice\", \"email\":[ \"alice@ora.com\" ], \"dates\":\"4/1/2017\" }")); - ExecuteModifyStatement(collection.Modify("true").ArrayAppend("email", "UPPER($.name)")); - var document = collection.GetOne("123"); - Assert.AreEqual("UPPER($.name)", (document["email"] as object[])[1]); - - // Use MySqlExpression. - ExecuteAddStatement(collection.Add("{ \"_id\":\"124\", \"name\":\"alice\", \"value\":[ \"alice@ora.com\" ], \"dates\":\"4/1/2017\" }")); - ExecuteModifyStatement(collection.Modify("_id = \"124\"").ArrayAppend("value", new MySqlExpression("UPPER($.name)"))); - document = collection.GetOne("124"); - Assert.AreEqual("ALICE", (document["value"] as object[])[1]); - - // Use embedded MySqlExpression. - ExecuteAddStatement(collection.Add("{ \"_id\":\"125\", \"name\":\"alice\", \"value\":[ \"alice@ora.com\" ], \"dates\":\"4/1/2017\" }")); - ExecuteModifyStatement(collection.Modify("_id = \"125\"").ArrayAppend("value", new { expression = new MySqlExpression("UPPER($.name)") })); - document = collection.GetOne("125"); - var item = ((document["value"] as object[])[1] as Dictionary); - Assert.AreEqual("ALICE", item["expression"]); - - ExecuteAddStatement(collection.Add("{ \"_id\":\"126\", \"name\":\"alice\", \"value\":[ \"alice@ora.com\" ], \"dates\":\"4/1/2017\" }")); - ExecuteModifyStatement(collection.Modify("_id = \"126\"").ArrayAppend("value", new { expression = new MySqlExpression("UPPER($.name)"), literal = "UPPER($.name)" })); - document = collection.GetOne("126"); - item = ((document["value"] as object[])[1] as Dictionary); - Assert.AreEqual("ALICE", item["expression"]); - Assert.AreEqual("UPPER($.name)", item["literal"]); - } - - [Test] - public void ArrayAppendUsesCorrectDataTypes() - { - Collection collection = CreateCollection("test"); - ExecuteAddStatement(collection.Add("{ \"_id\":\"123\", \"email\":[ \"alice@ora.com\"], \"dates\":\"4/1/2017\" }")); - ExecuteModifyStatement(collection.Modify("true").ArrayAppend("dates", "1")); - ExecuteModifyStatement(collection.Modify("true").ArrayAppend("dates", 1)); - var document = collection.GetOne("123"); - var dates = document["dates"] as object[]; - Assert.True(dates[1] is string); - Assert.True(dates[2] is int); - } - - [Test] - public void ArrayAppend() - { - Collection collection = CreateCollection("test"); - ExecuteAddStatement(collection.Add("{ \"x\":[1,2] }")); - - // Append values of different types, null and spaces. - ExecuteModifyStatement(collection.Modify("true").ArrayAppend("x", 43)); - ExecuteModifyStatement(collection.Modify("true").ArrayAppend("x", "string")); - ExecuteModifyStatement(collection.Modify("true").ArrayAppend("x", true)); - ExecuteModifyStatement(collection.Modify("true").ArrayAppend("x", null)); - ExecuteModifyStatement(collection.Modify("true").ArrayAppend("x", " ")); - var result = ExecuteFindStatement(collection.Find()); - DbDoc document = result.FetchOne(); - var x = (object[])document.values["x"]; - - Assert.AreEqual(7, x.Length); - Assert.AreEqual(1, (int)x[0]); - Assert.AreEqual(2, (int)x[1]); - Assert.AreEqual(43, (int)x[2]); - Assert.AreEqual("string", x[3]); - Assert.AreEqual(true, x[4]); - Assert.Null(x[5]); - Assert.AreEqual(" ", x[6]); - - // No value is appended if the array doesn't exist. - ExecuteModifyStatement(collection.Modify("true").ArrayAppend("y", 45)); - - result = ExecuteFindStatement(collection.Find()); - document = result.FetchOne(); - Assert.False(document.values.ContainsKey("y")); - - var ex = Assert.Throws(() => ExecuteModifyStatement(collection.Modify("true").ArrayAppend("x", ""))); - StringAssert.Contains("String can't be empty.", ex.Message); - ex = Assert.Throws(() => ExecuteModifyStatement(collection.Modify("true").ArrayAppend("x", string.Empty))); - StringAssert.Contains("String can't be empty.", ex.Message); - - var col = CreateCollection("my_collection"); - var t1 = "{\"_id\": \"1001\", \"ARR\":[1,2,3], \"ARR1\":[\"name1\",\"name2\", \"name3\"]}"; - col.Add(t1).Execute(); - col.Modify("true").ArrayAppend("ARR", 4).Execute(); - col.Modify("true").ArrayAppend("ARR1", "name4").Execute(); - col.Modify("true").ArrayAppend("ARR", "name5").Execute(); - col.Modify("true").ArrayAppend("ARR1", 5).Execute(); - col.Modify("true").ArrayAppend("ARR", 6).ArrayAppend("ARR1", "name6").ArrayAppend("ARR", 7).ArrayAppend("ARR", 8).Execute(); - - Assert.Throws(() => ExecuteModifyStatement(col.Modify("true").ArrayAppend("ARR1", ""))); - } - - [Test] - public void ArrayInsertWithMySqlExpression() - { - Collection collection = CreateCollection("test"); - ExecuteAddStatement(collection.Add("{ \"x\":[1,2] }")); - - // String containing an expression is not evaluted. - ExecuteAddStatement(collection.Add("{ \"_id\":\"123\", \"name\":\"alice\", \"email\":[ \"alice@ora.com\" ], \"dates\":\"4/1/2017\" }")); - ExecuteModifyStatement(collection.Modify("true").ArrayInsert("email[0]", "UPPER($.name)")); - var document = collection.GetOne("123"); - Assert.AreEqual("UPPER($.name)", (document["email"] as object[])[0]); - - // Use MySqlExpression. - ExecuteAddStatement(collection.Add("{ \"_id\":\"124\", \"name\":\"alice\", \"email\":[ \"alice@ora.com\" ], \"dates\":\"4/1/2017\" }")); - ExecuteModifyStatement(collection.Modify("_id = \"124\"").ArrayInsert("email[0]", new MySqlExpression("UPPER($.name)"))); - document = collection.GetOne("124"); - Assert.AreEqual("ALICE", (document["email"] as object[])[0]); - - // Use embedded MySqlExpression. - ExecuteAddStatement(collection.Add("{ \"_id\":\"125\", \"name\":\"alice\", \"email\":[ \"alice@ora.com\" ], \"dates\":\"4/1/2017\" }")); - ExecuteModifyStatement(collection.Modify("_id = \"125\"").ArrayInsert("email[0]", new { other = new MySqlExpression("UPPER($.name)") })); - document = collection.GetOne("125"); - var item = ((document["email"] as object[])[0] as Dictionary); - Assert.AreEqual("ALICE", item["other"]); - - ExecuteAddStatement(collection.Add("{ \"_id\":\"126\", \"name\":\"alice\", \"email\":[ \"alice@ora.com\" ], \"dates\":\"4/1/2017\" }")); - ExecuteModifyStatement(collection.Modify("_id = \"126\"").ArrayInsert("email[0]", new { other = new MySqlExpression("UPPER($.name)"), literal = "UPPER($.name)" })); - document = collection.GetOne("126"); - item = ((document["email"] as object[])[0] as Dictionary); - Assert.AreEqual("ALICE", item["other"]); - Assert.AreEqual("UPPER($.name)", item["literal"]); - } - - [Test] - public void ArrayOperationsKeepDateValue() - { - Collection collection = CreateCollection("test"); - Result r = ExecuteAddStatement(collection.Add("{ \"_id\": \"123\", \"email\":[\"alice@ora.com\"], \"dates\": \"5/1/2018\" }")); - Assert.AreEqual(1ul, r.AffectedItemsCount); - - // No items are affected since dates isn't an array. - r = ExecuteModifyStatement(collection.Modify("true").ArrayInsert("dates[0]", "4/1/2018")); - Assert.AreEqual(0ul, r.AffectedItemsCount); - - // Converts a non array to an array by appending a value. - ExecuteModifyStatement(collection.Modify("true").ArrayAppend("dates", "6/1/2018")); - - // Array insert at specified index is now succesful since dates is an array. - ExecuteModifyStatement(collection.Modify("true").ArrayInsert("dates[0]", "4/1/2018")); - - DbDoc document = collection.GetOne("123"); - object[] dates = document["dates"] as object[]; - Assert.AreEqual(3, dates.Length); - Assert.AreEqual("4/1/2018", dates[0]); - Assert.AreEqual("5/1/2018", dates[1]); - Assert.AreEqual("6/1/2018", dates[2]); - } - - [Test] - public void Alphanumeric() - { - Collection collection = CreateCollection("test"); - var document = new DbDoc(); - - for (int i = 0; i < 30; i++) - { - document.SetValue("_id", i); - document.SetValue("books", "test" + i); - document.SetValue("pages", i + 10); - document.SetValue("reviewers", "reviewers" + i); - document.SetValue("person", new - { - name = "Fred" + i, - age = i - }); - document.SetValue("1address", "street" + i); - ExecuteAddStatement(collection.Add(document)); - } - - var crudresult = collection.Find("pages=10").Execute().FetchAll(); - Assert.AreEqual(1, crudresult.Count, "Count should be 1 before Unset of pages for _id=0."); - var result = collection.Modify("_id = 0").Unset("pages").Execute(); - Assert.AreEqual(1, result.AffectedItemsCount, "Affected Items Count when modify unset is used"); - crudresult = collection.Find("pages=10").Execute().FetchAll(); - Assert.AreEqual(0, crudresult.Count, "Count should be 0 after Unset of pages for _id=0"); - crudresult = collection.Find("books='test0'").Execute().FetchAll(); - Assert.AreEqual(1, crudresult.Count, "Count should be 0 after Unset of pages for _id=0"); - - result = collection.Modify("_id = 21").Unset("1address").Execute(); - Assert.AreEqual(1, result.AffectedItemsCount, "Affected Items Count when modify unset(multiple docs) is used"); - } - - [Test] - public void UnsetVariations() - { - Collection collection = CreateCollection("test"); - var document = new DbDoc("{ \"_id\":1, \"pages\":1, \"pages2\":2, \"pages3\":3, \"pages4\":{ \"internalPages\":4 } }"); - ExecuteAddStatement(collection.Add(document)); - - // Whitespace is ignored. - ExecuteModifyStatement(collection.Modify("_id = 1").Unset("pages ")); - Assert.False(collection.GetOne(1).values.ContainsKey("pages")); - ExecuteModifyStatement(collection.Modify("_id = 1").Unset(" pages2 ")); - Assert.False(collection.GetOne(1).values.ContainsKey("pages2")); - ExecuteModifyStatement(collection.Modify("_id = 1").Unset(" pages3")); - Assert.False(collection.GetOne(1).values.ContainsKey("pages3")); - ExecuteModifyStatement(collection.Modify("_id = 1").Unset(" pages4.internalPages ")); - Assert.True(collection.GetOne(1).values.ContainsKey("pages4")); - Assert.False(collection.GetOne(1).values.ContainsKey("pages4.internalPages")); - - // Error is raised with incorrect document path. - var ex = Assert.Throws(() => ExecuteModifyStatement(collection.Modify("_id = 1").Unset("pages*"))); - Assert.AreEqual("Invalid document path.", ex.Message); - ex = Assert.Throws(() => ExecuteModifyStatement(collection.Modify("_id = 1").Unset("pages!"))); - Assert.AreEqual("Invalid document path.", ex.Message); - ex = Assert.Throws(() => ExecuteModifyStatement(collection.Modify("_id = 1").Unset("pages*data"))); - Assert.AreEqual("Invalid document path.", ex.Message); - } - - #region WL14389 - - [Test, Description("Collection.Modify(condition).Unset() to accept a list of elements instead of just one.")] - public void CollectionModifyUnset() - { - List idStringList = new List(); - var col = CreateCollection("my_collection"); - var d1 = new DbDoc(); - for (int i = 0; i < 30; i++) - { - d1.SetValue("_id", i); - d1.SetValue("books", "test" + i); - d1.SetValue("pages", i + 10); - d1.SetValue("reviewers", "reviewers" + i); - d1.SetValue("person", new { name = "Fred" + i, age = i }); - d1.SetValue("1address", "street" + i); - col.Add(d1).Execute(); - } - - var crudresult = col.Find("pages=10").Execute().FetchAll(); - Assert.AreEqual(1, crudresult.Count, "Count should be 1 before Unset of pages for _id=0."); - var result = col.Modify("_id = 0").Unset("pages").Execute(); - Assert.AreEqual(1, result.AffectedItemsCount, "Affected Items Count when modify unset is used"); - crudresult = col.Find("pages=10").Execute().FetchAll(); - Assert.AreEqual(0, crudresult.Count, "Count should be 0 after Unset of pages for _id=0"); - crudresult = col.Find("books='test0'").Execute().FetchAll(); - Assert.AreEqual(1, crudresult.Count, "Count should be 0 after Unset of pages for _id=0"); - - crudresult = col.Find("pages=11").Execute().FetchAll(); - Assert.AreEqual(1, crudresult.Count, "Count of pages=11 should be 1 before Unset of pages for _id=1."); - crudresult = col.Find("reviewers='reviewers1'").Execute().FetchAll(); - Assert.AreEqual(1, crudresult.Count, "Count of reviewers1 should be 1 before Unset of pages for _id=1."); - result = col.Modify("_id = 1").Unset("pages").Unset("reviewers").Execute(); - Assert.AreEqual(1, result.AffectedItemsCount, "Affected Items Count when modify multiple unset is used"); - crudresult = col.Find("pages=11").Execute().FetchAll(); - Assert.AreEqual(0, crudresult.Count, "Count should be 0 after Unset of pages for _id=1"); - crudresult = col.Find("reviewers='reviewers1'").Execute().FetchAll(); - Assert.AreEqual(0, crudresult.Count, "Count should be 0 after Unset of pages for _id=1"); - - crudresult = col.Find("pages=21").Execute().FetchAll(); - Assert.AreEqual(1, crudresult.Count, "Count of pages=21 should be 1 before Unset of pages for _id=11."); - crudresult = col.Find("reviewers='reviewers11'").Execute().FetchAll(); - Assert.AreEqual(1, crudresult.Count, "Count of reviewers11 should be 1 before Unset of pages for _id=11."); - result = col.Modify("_id = 11").Unset(new string[] { "pages", "reviewers" }).Execute(); - Assert.AreEqual(1, result.AffectedItemsCount, "Affected Items Count when modify unset(multiple docs) is used"); - crudresult = col.Find("pages=21").Execute().FetchAll(); - Assert.AreEqual(0, crudresult.Count, "Count should be 0 after Unset of pages for _id=11"); - crudresult = col.Find("reviewers='reviewers11'").Execute().FetchAll(); - Assert.AreEqual(0, crudresult.Count, "Count should be 0 after Unset of pages for _id=11"); - - crudresult = col.Find("pages=31").Execute().FetchAll(); - Assert.AreEqual(1, crudresult.Count, "Count of pages=31 should be 1 before Unset of pages for _id=21."); - crudresult = col.Find("reviewers='reviewers21'").Execute().FetchAll(); - Assert.AreEqual(1, crudresult.Count, "Count of reviewers21 should be 1 before Unset of pages for _id=21."); - - result = col.Modify("_id = 21").Unset(" pages ").Execute(); - Assert.AreEqual(1, result.AffectedItemsCount, "Affected Items Count when modify unset(multiple docs) is used"); - //Should have failed when unset is used for fields with special characters - Assert.Throws(() => ExecuteModifyStatement(col.Modify("_id = 22").Unset("pages*"))); - //Should have failed when unset is used for non-existent fields - Assert.Throws(() => ExecuteModifyStatement(col.Modify("_id = 21").Unset("1"))); - //Should have failed when unset is used for special characters - Assert.Throws(() => ExecuteModifyStatement(col.Modify("_id = 21").Unset("@*%#^)(-+!~<>?/"))); - //Should have failed when unset is used for special characters - Assert.Throws(() => ExecuteModifyStatement(col.Modify("_id = 21").Unset("*******"))); - - crudresult = col.Find("pages=31").Execute().FetchAll(); - Assert.AreEqual(0, crudresult.Count, "Count should be 0 after Unset of pages for _id=21"); - - result = col.Modify("_id = 12").Unset(new string[] { " pages1", "reviewers1" }).Execute(); - Assert.AreEqual(0, result.AffectedItemsCount, "Affected Items Count when modify unset(invalid docs) is used"); - crudresult = col.Find("pages=22").Execute().FetchAll(); - Assert.AreEqual(1, crudresult.Count, "Count should be 1 after Unset with invalid of pages for _id=12"); - crudresult = col.Find("reviewers='reviewers12'").Execute().FetchAll(); - Assert.AreEqual(1, crudresult.Count, "Count should be 1 after Unset with invalid of pages for _id=12"); - //Testcase should have failed when unset is used with null - Assert.Throws(() => ExecuteModifyStatement(col.Modify("_id = 12").Unset(null))); - - crudresult = col.Find("pages=22").Execute().FetchAll(); - Assert.AreEqual(1, crudresult.Count, "Count should be 1 after Unset with null of pages for _id=12"); - crudresult = col.Find("reviewers='reviewers12'").Execute().FetchAll(); - Assert.AreEqual(1, crudresult.Count, "Count should be 1 after Unset with null of pages for _id=12"); - - Assert.Throws(() => ExecuteModifyStatement(col.Modify("_id = 12").Unset(""))); - - crudresult = col.Find("pages=22").Execute().FetchAll(); - Assert.AreEqual(1, crudresult.Count, "Count should be 1 after Unset with blank of pages for _id=12"); - crudresult = col.Find("reviewers='reviewers12'").Execute().FetchAll(); - Assert.AreEqual(1, crudresult.Count, "Count should be 1 after Unset with blank of pages for _id=12"); - - crudresult = col.Find("pages=22").Execute().FetchAll(); - Assert.AreEqual(1, crudresult.Count, "Count should be 1 after Unset with blank with space of pages for _id=12"); - crudresult = col.Find("reviewers='reviewers12'").Execute().FetchAll(); - Assert.AreEqual(1, crudresult.Count, "Count should be 1 after Unset with blank with space of pages for _id=12"); - - //Testcase should have failed when unset is used with blank and space - Assert.Throws(() => ExecuteModifyStatement(col.Modify("_id = 12").Unset(new string[] { "", " ", "pages" }))); - - crudresult = col.Find("pages=22").Execute().FetchAll(); - Assert.AreEqual(1, crudresult.Count); - crudresult = col.Find("reviewers='reviewers12'").Execute().FetchAll(); - Assert.AreEqual(1, crudresult.Count); - } - - [Test, Description("All Bug Fixes")] - public void ValidateValuesAfterAppendAndInserts() - { - DbDoc document = null; - Collection collection = CreateCollection("test"); - Result r = collection.Add("{ \"_id\": \"123\", \"email\": [\"alice@ora.com\"], " + - "\"dates\": \"4/1/2017\" }").Execute(); - Assert.AreEqual(1, r.AffectedItemsCount); - - collection.Modify("true").ArrayAppend("dates", "5/1/2018").Execute(); - document = collection.GetOne("123"); - object[] dates = document["dates"] as object[]; - Assert.AreEqual(2, dates.Length); - Assert.AreEqual("4/1/2017", dates[0], "Existing Date"); - Assert.AreEqual("5/1/2018", dates[1], "Appended Date"); - collection.Modify("true").ArrayInsert("dates[0]", "5/1/2059").Execute(); - document = collection.GetOne("123"); - dates = document["dates"] as object[]; - Assert.AreEqual("5/1/2059", dates[0], "Inserted Date"); - - collection = CreateCollection("test"); - r = collection.Add("{ \"_id\": \"123\", \"email\": [\"alice@ora.com\"], " + - "\"dates\": [\"4/1/2017\"] }").Execute(); - Assert.AreEqual(1, r.AffectedItemsCount); - - collection = CreateCollection("test"); - r = collection.Add("{ \"_id\": \"123\", \"email\": [\"alice@ora.com\"], " + - "\"dates\": \"4/1/2017\" }").Execute(); - Assert.AreEqual(1, r.AffectedItemsCount); - collection.Modify("true").ArrayAppend("dates", "1").Execute(); - collection.Modify("true").ArrayAppend("dates", 1).Execute(); - collection.Modify("true").ArrayAppend("dates", "3.1").Execute(); - collection.Modify("true").ArrayAppend("dates", 3.1).Execute(); - document = collection.GetOne("123"); - dates = document["dates"] as object[]; - Assert.AreEqual(5, dates.Length); - Assert.AreEqual("4/1/2017", dates[0], "Existing Date"); - Assert.AreEqual("1", dates[1], "Appended Date"); - Assert.AreEqual(1, dates[2], "Appended Date"); - Assert.AreEqual("3.1", dates[3], "Appended Date"); - Assert.AreEqual(3.1, dates[4], "Appended Date"); - - collection.Modify("true").ArrayInsert("dates[0]", "10").Execute(); - collection.Modify("true").ArrayInsert("dates[0]", 1000).Execute(); - collection.Modify("true").ArrayInsert("dates[0]", "3.1").Execute(); - collection.Modify("true").ArrayInsert("dates[0]", 22.7).Execute(); - document = collection.GetOne("123"); - dates = document["dates"] as object[]; - Assert.AreEqual("10", dates[3], "Inserted Date"); - Assert.AreEqual(1000, dates[2], "Inserted Date"); - Assert.AreEqual("3.1", dates[1], "Inserted Date"); - Assert.AreEqual(22.7, dates[0], "Inserted Date"); - - var d1 = new DbDoc(); - for (int i = 0; i < 30; i++) - { - d1.SetValue("_id", i); - d1.SetValue("books", "test" + i); - d1.SetValue("pages", i + 10); - d1.SetValue("reviewers", "reviewers" + i); - d1.SetValue("person", new - { - name = "Fred" + i, - age = i - }); - d1.SetValue("1address", "street" + i); - collection.Add(d1).Execute(); - } - Assert.Throws(() => ExecuteModifyStatement(collection.Modify("_id = 21").Unset("pages*"))); - - var docs = new[] - { - new { _id = 100, title = "Book 1", pages = 20 }, - new { _id = 200, title = "Book 2", pages = 30 }, - new { _id = 300, title = "Book 3", pages = 40 }, - new { _id = 400, title = "Book 4", pages = 50 }, - }; - r = collection.Add(docs).Execute(); - Assert.AreEqual(4, r.AffectedItemsCount, "Matching the records affected"); - var test1 = collection.Find("pages = :Pages").Bind("pAges", 90).Fields("{\"_id\":100,\"pages\": 20 }").Execute(); - Assert.IsNotNull(test1); - } - - [Test, Description("Collection.modify(condition).arrayAppend(CollectionField, ExprOrLiteral)")] - public void CollectionModifyArrayAppend() - { - - string currentYear = DateTime.Now.Year.ToString(); - DbDoc document = null; - string t1 = "{\"_id\": \"1\", \"name\": \"Alice\" }"; - var collection = CreateCollection("test"); - Result r = collection.Add(t1).Execute(); - Assert.AreEqual(1, r.AffectedItemsCount); - object[] expressions1 = new object[] { "YEAR('2000-01-01')", "MONTH('2008-02-03')", "WEEK('2008-02-20')", "DAY('2008-02-20')", "HOUR('10:05:03')", - "MINUTE('2008-02-03 10:05:03')","SECOND('10:05:03')","MICROSECOND('12:00:00.123456')","QUARTER('2008-04-01')","TIME('2003-12-31 01:02:03')","DATE('2003-12-31 01:02:03')", - "Year(CURDATE())"}; - - object[] expressions2 = new object[] { "5/1/2018",2012,"2012",-22.7,22.7,"22.7", "'large'", - "'838:59:59'" ,true,-100000000,"-10000000000","6/6/2018","9999-12-31 23:59:59","0000-00-00 00:00:00","[a,b,c]","[]"}; - object[] compare_expressions1 = new object[] { 2000, 2, 7, 20, 10, 5, 3, 123456, 2, "01:02:03.000000", "2003-12-31", currentYear }; - object[] compare_expressions2 = new object[] { "5/1/2018",2012, "2012", -22.7, 22.7, "22.7", - "'large'", "'838:59:59'", true, -100000000, "-10000000000","6/6/2018" ,"9999-12-31 23:59:59","0000-00-00 00:00:00","[a,b,c]","[]"}; - for (int k = 0; k < expressions1.Length; k++) - { - collection.Modify("true").ArrayAppend("name", "{ \"dateAndTimeValue\": " + expressions1[k] + " }").Execute(); - } - for (int k = 0; k < expressions2.Length; k++) - { - collection.Modify("true").ArrayAppend("name", "{ \"dateAndTimeValue\": \"" + expressions2[k] + "\" }").Execute(); - } - object[] actors = null; - object test = null; - Dictionary actor0 = null; - int l = 1; - for (int k = 0; k < compare_expressions1.Length; k++) - { - - document = collection.GetOne("1"); - actors = document["name"] as object[]; - actor0 = actors[l] as Dictionary; - test = actor0["dateAndTimeValue"]; - Assert.AreEqual(compare_expressions1[k].ToString(), test.ToString()); - l++; - } - for (int k = 0; k < compare_expressions2.Length; k++) - { - - document = collection.GetOne("1"); - actors = document["name"] as object[]; - actor0 = actors[l] as Dictionary; - test = actor0["dateAndTimeValue"]; - Assert.AreEqual(compare_expressions2[k].ToString(), test.ToString()); - l++; - } - - collection = CreateCollection("test"); - r = collection.Add("{ \"_id\": \"123\", \"email\": [\"alice@ora.com\"], " + - "\"dates\": [\"4/1/2017\"] }").Execute(); - Assert.AreEqual(1, r.AffectedItemsCount); - var reg_expression = new - { - test1 = new MySqlExpression("UPPER($.email)"), - test2 = new MySqlExpression("LOWER($.email)"), - test3 = new MySqlExpression("CONCAT('No', 'S', 'QL')"), - test4 = new MySqlExpression("CHAR(77, 121, 83, 81, '76')"), - test5 = new MySqlExpression("CONCAT('My', NULL, 'QL')"), - test6 = new MySqlExpression("ELT(4, 'ej', 'Heja', 'hej', 'foo')"), - test7 = new MySqlExpression("REPEAT('MySQL', 3)"), - test8 = new MySqlExpression("REVERSE('abc')"), - test9 = new MySqlExpression("RIGHT('foobarbar', 4)"), - test10 = new MySqlExpression("REPLACE('www.mysql.com', 'w', 'Ww')"), - test11 = new MySqlExpression(" HEX('abc')"), - test12 = new MySqlExpression(" BIN(12)"), - }; - object[] compare_expressions = null; - if (session.Version.isAtLeast(8, 0, 0)) - { - compare_expressions = new object[] { "[\\\"ALICE@ORA.COM\\\"]", "[\\\"alice@ora.com\\\", \\\"[\\\\\\\"alice@ora.com\\\\\\\"]\\\"]", - "NoSQL","base64:type253:TXlTUUw=",null,"foo","MySQLMySQLMySQL","cba","rbar","WwWwWw.mysql.com","616263","1100" }; - } - else - { - compare_expressions = new object[] { "[\\\"ALICE@ORA.COM\\\"]", "[\\\"alice@ora.com\\\", \\\"[\\\\\\\"alice@ora.com\\\\\\\"]\\\"]", - "NoSQL","base64:type15:TXlTUUw=",null,"foo","MySQLMySQLMySQL","cba","rbar","WwWwWw.mysql.com","616263","1100" }; - } - - var items = new List(); - items.Add(reg_expression.test1); - items.Add(reg_expression.test2); - items.Add(reg_expression.test3); - items.Add(reg_expression.test4); - items.Add(reg_expression.test5); - items.Add(reg_expression.test6); - items.Add(reg_expression.test7); - items.Add(reg_expression.test8); - items.Add(reg_expression.test9); - items.Add(reg_expression.test10); - items.Add(reg_expression.test11); - items.Add(reg_expression.test12); - int m = 1, n = 0; - foreach (var obj in items) - { - collection.Modify("true").ArrayAppend("email", obj).Execute(); - document = collection.GetOne("123"); - actors = document["email"] as object[]; - if (n == 3) - { } - else - { - Assert.AreEqual(actors[m], compare_expressions[n]); - } - - m++; n++; - } - - string json = ""; - int i = 0, j = 0, maxField = 40; - collection = CreateCollection("test"); - int maxDepth = 2; - json = "{\"_id\":\"1002\",\"XYZ\":1111"; - for (j = 0; j < maxField; j++) - { - json = json + ",\"ARR" + j + "\":["; - for (i = 0; i < maxDepth; i++) - { - json = json + i + ",["; - } - json = json + i; - for (i = maxDepth - 1; i >= 0; i--) - { - json = json + "]," + i; - } - json = json + "]"; - } - json = json + "}"; - - collection.Add(json).Execute(); - r = collection.Modify("true").ArrayAppend("ARR10", 1).ArrayAppend("ARR20", 2).ArrayAppend("ARR30", 3).Execute(); - Assert.AreEqual(1, r.AffectedItemsCount); - r = collection.Modify("true").ArrayAppend("ARR0", null).Execute(); - Assert.AreEqual(1, r.AffectedItemsCount); - r = collection.Modify("true").ArrayAppend("ARR39", null).Execute(); - Assert.AreEqual(1, r.AffectedItemsCount); - - } - - [Test, Description("MySQLX CNET Forbid modify() with no condition-Scenario-1")] - public void ForbidModifyWithNoCondition_S1() - { - - Collection collection = CreateCollection("test"); - var docs = new[] - { - new { _id = 1, title = "Book 1", pages = 20 }, - new { _id = 2, title = "Book 2", pages = 30 }, - new { _id = 3, title = "Book 3", pages = 40 }, - new { _id = 4, title = "Book 4", pages = 50 }, - }; - Result result = collection.Add(docs).Execute(); - Assert.AreEqual(4, result.AffectedItemsCount); - - // Condition can't be null or empty. - Assert.Throws(() => ExecuteModifyStatement(collection.Modify(string.Empty))); - Assert.Throws(() => ExecuteRemoveStatement(collection.Remove(""))); - Assert.Throws(() => ExecuteModifyStatement(collection.Modify(null))); - - // Sending an expression that evaluates to true applies changes on all documents. - result = collection.Modify("true").Set("pages", "10").Execute(); - Assert.AreEqual(4, result.AffectedItemsCount); - - } - - [Test, Description("MySQLX CNET Forbid modify() with no condition-Scenario-2")] - public void ForbidModifyWithNoCondition_S2() - { - - Collection collection = CreateCollection("test"); - var docs = new[] - { - new { _id = 1, title = "Book 1", pages = 20 }, - new { _id = 2, title = "Book 2", pages = 30 }, - new { _id = 3, title = "Book 3", pages = 40 }, - new { _id = 4, title = "Book 4", pages = 50 }, - }; - Result result = collection.Add(docs).Execute(); - Assert.AreEqual(4, result.AffectedItemsCount); - - // Sending an expression that evaluates to true applies changes on all documents. - //Deprecated Modify().Where() in 8.0.17 - result = collection.Modify("true").Where("false").Set("pages", "10").Execute(); - Assert.AreEqual(0, result.AffectedItemsCount); - - result = collection.Modify("true").Where("true").Set("pages", "10").Execute(); - Assert.AreEqual(4, result.AffectedItemsCount); - result = collection.Modify("false").Where("true").Set("pages", "40").Execute(); - Assert.AreEqual(4, result.AffectedItemsCount); - result = collection.Modify("false").Where("false").Set("pages", "40").Execute(); - Assert.AreEqual(0, result.AffectedItemsCount); - - // Condition can't be null or empty. - Assert.Throws(() => ExecuteModifyStatement(collection.Modify(" "))); - } - - [Test, Description("Test valid modify.patch to change element at Depth n for multiple arrays#Bug))")] - public void ModifyPatchNDepth() - { - if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher."); - string json = ""; - int i = 0, j = 0, maxField = 100; - var collection = CreateCollection("test"); - int maxDepth = 46; - json = "{\"_id\":\"1002\",\"XYZ\":1111"; - for (j = 0; j < maxField; j++) - { - json = json + ",\"ARR" + j + "\":["; - for (i = 0; i < maxDepth; i++) - { - json = json + i + ",["; - } - json = json + i; - for (i = maxDepth - 1; i >= 0; i--) - { - json = json + "]," + i; - } - json = json + "]"; - } - json = json + "}"; - - var r = collection.Modify("age = :age").Patch(json). - Bind("age", "18").Execute(); - Assert.IsNotNull(r); - } - - [Test, Description("Test valid modify.patch with condition/limit/OrderBy")] - public void ModifyPatch() - { - if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher."); - var collection = CreateCollection("test"); - var docs = new[] - { - new {_id = 1, title = "Book 1", pages = 20, age = 12}, - new {_id = 2, title = "Book 2", pages = 30,age = 18}, - new {_id = 3, title = "Book 3", pages = 40,age = 34}, - new {_id = 4, title = "Book 4", pages = 50,age = 15} - }; - var r = collection.Add(docs).Execute(); - Assert.AreEqual(4, (int)r.AffectedItemsCount, "Matching the updated record count"); - - var jsonParams = new { title = "Book 100" }; - var foundDocs = collection.Modify("age==18").Patch(jsonParams).Execute(); - Assert.AreEqual(1, (int)foundDocs.AffectedItemsCount, "Matching the record count"); - - var document = collection.GetOne("2"); - Assert.AreEqual("Book 100", document["title"]); - - jsonParams = new { title = "Book 300" }; - r = collection.Modify("age<18").Patch(jsonParams).Limit(1).Execute(); - Assert.AreEqual(1, (int)r.AffectedItemsCount, "Matching the record count"); - - document = collection.GetOne(1); - Assert.AreEqual("Book 300", document["title"]); - - var jsonParams1 = new { title = "Book 10", pages = 1000 }; - r = collection.Modify("age>30").Patch(jsonParams1).Sort("age ASC").Execute(); - Assert.AreEqual(1, (int)r.AffectedItemsCount, "Matching the record count"); - } - - [Test, Description("Test valid modify.patch with set/unset")] - public void ModifyPatchWithSetUnset() - { - if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher."); - var collection = CreateCollection("test"); - var docs = new[] - { - new {_id = 1, title = "Book 1", pages = 20, age = "12"}, - new {_id = 2, title = "Book 2", pages = 30,age = "18"}, - new {_id = 3, title = "Book 3", pages = 40,age = "34"}, - new {_id = 4, title = "Book 4", pages = 50,age = "12"} - }; - Result r = collection.Add(docs).Execute(); - Assert.AreEqual(4, r.AffectedItemsCount); - - var jsonParams = new { title = "Book 500" }; - r = collection.Modify("age = :age").Patch(jsonParams).Bind("age", "18"). - Set("pages", "5000").Execute(); - Assert.AreEqual(1, r.AffectedItemsCount); - - var document = collection.GetOne("2"); - Assert.AreEqual("5000", document["pages"].ToString()); - Assert.AreEqual("Book 500", document["title"].ToString()); - - var jsonParams1 = new { title = "Book 50000", pages = 5000 }; - r = collection.Modify("age = :age").Patch(jsonParams1).Bind("age", "18"). - Unset("pages").Execute(); - Assert.AreEqual(1, r.AffectedItemsCount, "Match being done"); - document = collection.GetOne("2"); - DbDoc test = null; - Assert.Throws(() => test = (DbDoc)document["pages"]); - Assert.AreEqual("Book 50000", document["title"]); - } - - [Test, Description("Test invalid modify.patch to attempt to change _id using modify.patch")] - public void ModifyPatchChangeId() - { - if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher."); - var collection = CreateCollection("test"); - var docs = new[] - { - new {_id = 1, title = "Book 1", pages = 20, age = 12}, - new {_id = 2, title = "Book 2", pages = 30,age = 18}, - new {_id = 3, title = "Book 3", pages = 40,age = 34}, - new {_id = 4, title = "Book 4", pages = 50,age = 12} - }; - Result r = collection.Add(docs).Execute(); - Assert.AreEqual(4, r.AffectedItemsCount); - var document = collection.GetOne("1"); - var jsonParams = new { _id = 123 }; - - r = collection.Modify("age = :age").Patch(jsonParams). - Bind("age", 18).Execute(); - Assert.AreEqual(0, r.AffectedItemsCount); - - var jsonParams2 = new { _id = 123, title = "Book 4000" }; - - r = collection.Modify("age = :age").Patch(jsonParams2). - Bind("age", 18).Execute(); - Assert.AreEqual(1, r.AffectedItemsCount); - - string jsonParams1 = "{ \"_id\": \"123\"}"; - r = collection.Modify("age = :age").Patch(jsonParams1). - Bind("age", 18).Execute(); - Assert.AreEqual(0, r.AffectedItemsCount); - - jsonParams1 = "{ \"_id\": \"123\",\"title\": \"Book 400\"}"; - r = collection.Modify("age = :age").Patch(jsonParams1). - Bind("age", 18).Execute(); - Assert.AreEqual(1, r.AffectedItemsCount); - } - - [Test, Description("Test modify.patch where the key to be modified has array, dbDoc and normal constant value and condition is matched for all.")] - public void ModifyPatchKeyWithArray() - { - if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher."); - var collection = CreateCollection("test"); - var docs1 = new[] - { - new {_id = 1, title = "Book 1", pages = 20, age = 12,name = "Morgan"}, - }; - var docs2 = - "{\"_id\": \"2\",\"age\": 12,\"name\": \"Alice\", " + - "\"address\": {\"zip\": \"12345\", \"city\": \"Los Angeles\", \"street\": \"32 Main str\"}}"; - - var docs3 = "{\"_id\": \"3\", \"age\": 12,\"name\":[\"Cynthia\"], \"ARR1\":[\"name1\",\"name2\", \"name3\"]}"; - Result r = collection.Add(docs1).Execute(); - Assert.AreEqual(1, r.AffectedItemsCount); - r = collection.Add(docs2).Execute(); - Assert.AreEqual(1, r.AffectedItemsCount); - r = collection.Add(docs3).Execute(); - Assert.AreEqual(1, r.AffectedItemsCount); - var jsonParams = new { name = "Changed" }; - r = collection.Modify("age = :age").Patch(jsonParams).Bind("age", 12).Execute(); - Assert.AreEqual(3, r.AffectedItemsCount); - } - - [Test, Description("Test that documents not matching conditions are not modified.")] - public void ModifyPatchNotMatchingConditions() - { - if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher."); - var collection = CreateCollection("test"); - var docs = new[] - { - new {_id = 1, title = "Book 1", pages = 20, age = 12}, - new {_id = 2, title = "Book 2", pages = 30,age = 18}, - new {_id = 3, title = "Book 3", pages = 40,age = 34}, - new {_id = 4, title = "Book 4", pages = 50,age = 12} - }; - Result r = collection.Add(docs).Execute(); - Assert.AreEqual(4, r.AffectedItemsCount); - var document = collection.GetOne("1"); - var jsonParams = new { title = "Book 100" }; - r = collection.Modify("age = :age").Patch(jsonParams).Bind("age", "19").Execute(); - Assert.AreEqual(0, r.AffectedItemsCount); - string jsonParams1 = "{ \"title\": \"Book 100\"}"; - r = collection.Modify("age = :age").Patch(jsonParams1).Bind("age", "28").Execute(); - Assert.AreEqual(0, r.AffectedItemsCount); - jsonParams1 = "{ \"unknownvalues\": null}"; - r = collection.Modify("age = :age").Patch(jsonParams1).Bind("age", "28").Execute(); - Assert.AreEqual(0, r.AffectedItemsCount); - } - - [Test, Description("Test modify.patch with different types of records(anonymous object,Json String,DbDoc) with same key and try to replace using a patch")] - public void ModifyPatchDifferentTypesSameKey() - { - if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher."); - var collection = CreateCollection("test"); - var docs1 = new[] - { - new {_id = 1, title = "Book 1", pages = 20, age = 12,name = "Morgan"}, - }; - var docs2 = - "{\"_id\": \"2\",\"age\": \"12\",\"name\": \"Alice\", " + - "\"address\": {\"zip\": \"12345\", \"city\": \"Los Angeles\", \"street\": \"32 Main str\"}}"; - - var docs3 = new DbDoc(@"{ ""_id"": 3, ""pages"": 20, ""age"":12,""name"":""Cynthiaa"", - ""books"": [ - {""_id"" : 10, ""title"" : ""Book 10""}, - { ""_id"" : 20, ""title"" : ""Book 20"" } - ] - }"); - Result r = collection.Add(docs1).Execute(); - Assert.AreEqual(1, r.AffectedItemsCount); - r = collection.Add(docs2).Execute(); - Assert.AreEqual(1, r.AffectedItemsCount); - r = collection.Add(docs3).Execute(); - Assert.AreEqual(1, r.AffectedItemsCount); - var jsonParams = new { name = "Changed" }; - r = collection.Modify("age = :age").Patch(jsonParams). - Bind("age", 12).Execute(); - Assert.AreEqual(2, r.AffectedItemsCount);//docs2 age is the string - } - - [Test, Description("GetOne with ExistingID and NewID with doc(Verify the Immutable feature also))")] - public void GetOneAndRemoveOne() - { - if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher."); - var coll = CreateCollection("test"); - var docs = new[] - { - new {_id = 1, title = "Book 1", pages = 20}, - new {_id = 2, title = "Book 2", pages = 30}, - new {_id = 3, title = "Book 3", pages = 40}, - new {_id = 4, title = "Book 4", pages = 50} - }; - var r = coll.Add(docs).Execute(); - Assert.AreEqual(4, r.AffectedItemsCount); - - // Expected exceptions. - Assert.Throws(() => coll.GetOne(null)); - Assert.Throws(() => coll.GetOne("")); - Assert.Throws(() => coll.GetOne(string.Empty)); - Assert.Throws(() => coll.GetOne(" ")); - - // Get document using numeric parameter. - var document = coll.GetOne(1); - Assert.AreEqual(1, document.Id); - Assert.AreEqual("Book 1", document["title"]); - Assert.AreEqual(20, Convert.ToInt32(document["pages"])); - - // Get document using string parameter. - document = coll.GetOne("3"); - Assert.AreEqual(3, document.Id); - Assert.AreEqual("Book 3", document["title"]); - Assert.AreEqual(40, Convert.ToInt32(document["pages"])); - - // Get a non-existing document. - document = coll.GetOne(5); - Assert.AreEqual(null, document); - - coll.Add(new { _id = 5, title = "Book 5", pages = 60 }).Execute(); - Assert.AreEqual(5, coll.Find().Execute().FetchAll().Count); - // Remove sending numeric parameter. - //WL11843-Core API v1 alignment Changes - Assert.AreEqual(1, coll.RemoveOne(1).AffectedItemsCount); - Assert.AreEqual(4, coll.Find().Execute().FetchAll().Count); - - // Remove sending string parameter. - Assert.AreEqual(1, coll.RemoveOne("3").AffectedItemsCount); - Assert.AreEqual(3, coll.Find().Execute().FetchAll().Count); - - // Remove an auto-generated id. - document = coll.Find("pages = 60").Execute().FetchOne(); - Assert.AreEqual(1, coll.RemoveOne(document.Id).AffectedItemsCount); - Assert.AreEqual(2, coll.Find().Execute().FetchAll().Count); - - // Remove a non-existing document. - Assert.AreEqual(0, coll.RemoveOne(5).AffectedItemsCount); - Assert.AreEqual(2, coll.Find().Execute().FetchAll().Count); - - } - - [Test, Description("AddReplaceOne with unique id generated by SQL")] - public void AddReplaceOneUniqueId() - { - if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher."); - var collection = CreateCollection("test"); - var docs = new[] - { - new {_id = 1, name = "foo"}, - new {_id = 2, name = "bar"} - }; - var result = collection.Add(docs).Execute(); - Assert.AreEqual(2, result.AffectedItemsCount); - - // Add unique index. - session.SQL( - "ALTER TABLE test.test ADD COLUMN name VARCHAR(3) GENERATED ALWAYS AS (JSON_UNQUOTE(JSON_EXTRACT(doc, '$.name'))) VIRTUAL UNIQUE KEY NOT NULL") - .Execute(); - Assert.Throws(() => collection.AddOrReplaceOne(1, new { name = "bar" })); - Assert.Throws(() => collection.AddOrReplaceOne(1, new { _id = 3, name = "bar", age = "55" })); - } - - #endregion WL14389 - - } -} +// Copyright © 2015, 2024, Oracle and/or its affiliates. +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySql.Data; +using MySql.Data.MySqlClient; +using MySqlX.XDevAPI; +using MySqlX.XDevAPI.Common; +using NUnit.Framework; +using System; +using System.Collections.Generic; + +namespace MySqlX.Data.Tests +{ + public class CrudUpdateTests : BaseTest + { + [Test] + public void SetItemInSingleDocument() + { + Collection coll = CreateCollection("test"); + Result result = ExecuteAddStatement(coll.Add(new { _id = 1, name = "Book 1" })); + Assert.AreEqual(1, result.AffectedItemsCount); + + // Set integer value. + result = ExecuteModifyStatement(coll.Modify("_id = 1").Set("pages", "20")); + Assert.AreEqual(1, result.AffectedItemsCount); + Assert.AreEqual("20", coll.GetOne(1)["pages"]); + + // Set null value. + result = ExecuteModifyStatement(coll.Modify("_id = 1").Set("pages", null)); + Assert.AreEqual(1, result.AffectedItemsCount); + Assert.Null(coll.GetOne(1)["pages"]); + + // Set existing field. + result = ExecuteModifyStatement(coll.Modify("_id = 1").Set("name", "Book 2")); + Assert.AreEqual(1, result.AffectedItemsCount); + Assert.AreEqual("Book 2", coll.GetOne(1)["name"]); + + // Set alphanumeric field. + var document = new DbDoc(); + document.SetValue("_id", 2); + document.SetValue("1a", "other"); + result = ExecuteAddStatement(coll.Add(document)); + Assert.AreEqual(1, result.AffectedItemsCount); + var insertedDocument = coll.GetOne(2); + + //result = coll.Modify("_id = 1").Set("1a", "other")); + } + + [Test] + public void ChangeItemInSingleDocument() + { + Collection coll = CreateCollection("test"); + Result result = ExecuteAddStatement(coll.Add(new { _id = 1, name = "Book 1", pages = 20 })); + Assert.AreEqual(1, result.AffectedItemsCount); + + result = ExecuteModifyStatement(coll.Modify("_id = 1").Change("name", "Book 2")); + Assert.AreEqual(1, result.AffectedItemsCount); + } + + [Test] + public void RemoveItemInSingleDocumentUsingUnset() + { + Collection coll = CreateCollection("test"); + Result result = ExecuteAddStatement(coll + .Add(new { _id = 1, name = "Book 1", pages = 20 }) + .Add(new { _id = 2, name = "Book 2", pages = 30 }) + .Add(new { _id = 3, name = "Book 3", pages = 40, author = "John", author2 = "Mary" }) + ); + Assert.AreEqual(3, result.AffectedItemsCount); + + // Unset 1 field. + result = ExecuteModifyStatement(coll.Modify("_id = 1").Unset("pages")); + Assert.AreEqual(1, result.AffectedItemsCount); + var document = ExecuteFindStatement(coll.Find("_id = 1")).FetchOne(); + Assert.AreEqual(2, document.values.Count); + + // Unset multiple fields. + result = ExecuteModifyStatement(coll.Modify("_id = 2").Unset("name", "pages")); + Assert.AreEqual(1, result.AffectedItemsCount); + document = ExecuteFindStatement(coll.Find("_id = 2")).FetchOne(); + Assert.That(document.values, Has.One.Items); + result = ExecuteModifyStatement(coll.Modify("_id = 3").Unset(null, "author", "author2")); + document = ExecuteFindStatement(coll.Find("_id = 3")).FetchOne(); + Assert.AreEqual(3, document.values.Count); + + // Unsetting nonexistent fields doesn't raise an error. + result = ExecuteModifyStatement(coll.Modify("_id = 2").Unset("otherfield")); + Assert.AreEqual(0ul, result.AffectedItemsCount); + + // Unsetting null items combined with valid values are ignored. + result = ExecuteModifyStatement(coll.Modify("_id = 3").Unset(null).Unset("name")); + Assert.AreEqual(1ul, result.AffectedItemsCount); + document = ExecuteFindStatement(coll.Find("_id = 3")).FetchOne(); + Assert.AreEqual(2, document.values.Count); + + // Unsetting single null items raises an error + var ex = Assert.Throws(() => ExecuteModifyStatement(coll.Modify("_id = 3").Unset(null))); + Assert.AreEqual("Invalid update expression list", ex.Message); + + // Unsetting empty strings raises an error. + var ex2 = Assert.Throws(() => ExecuteModifyStatement(coll.Modify("_id = 2").Unset(""))); + Assert.AreEqual(ResourcesX.DocPathNullOrEmpty, ex2.Message); + ex2 = Assert.Throws(() => ExecuteModifyStatement(coll.Modify("_id = 2").Unset(string.Empty))); + Assert.AreEqual(ResourcesX.DocPathNullOrEmpty, ex2.Message); + + // Unset with special chars. + Assert.Throws(() => ExecuteModifyStatement(coll.Modify("_id = 3").Unset(null).Unset("@*%#�"))); + Assert.Throws(() => ExecuteModifyStatement(coll.Modify("_id = 3").Unset(null).Unset("******"))); + } + + [Test] + public void SetItemAndBind() + { + Collection coll = CreateCollection("test"); + Result result = ExecuteAddStatement(coll.Add(new { _id = 1, name = "Book 1" }) + .Add(new { _id = 2, name = "Book 2" })); + Assert.AreEqual(2, result.AffectedItemsCount); + + var stmt = coll.Modify("_id = :ID"); + result = ExecuteModifyStatement(stmt.Bind("Id", 2).Set("pages", "20")); + Assert.AreEqual(1, result.AffectedItemsCount); + result = ExecuteModifyStatement(stmt.Bind("Id", 1).Set("pages", 10)); Assert.AreEqual(1, result.AffectedItemsCount); + + var docs = ExecuteFindStatement(coll.Find()).FetchAll(); + Assert.AreEqual(new DbDoc("{ \"_id\": 1, \"name\": \"Book 1\", \"pages\": 10 }").ToString(), docs[0].ToString()); + Assert.AreEqual(new DbDoc("{ \"_id\": 2, \"name\": \"Book 2\", \"pages\": \"20\" }").ToString(), docs[1].ToString()); + } + + [Test] + public void ModifyAll() + { + Collection collection = CreateCollection("test"); + var docs = new[] + { + new { _id = 1, title = "Book 1", pages = 20 }, + new { _id = 2, title = "Book 2", pages = 30 }, + }; + Result result = ExecuteAddStatement(collection.Add(docs)); + Assert.AreEqual(2, result.AffectedItemsCount); + + // Condition can't be null or empty. + string errorMessage = string.Empty; +#if !NETFRAMEWORK + errorMessage = "Parameter can't be null or empty. (Parameter 'condition')"; +#else + errorMessage = "Parameter can't be null or empty.\r\nParameter name: condition"; +#endif + Exception ex = Assert.Throws(() => ExecuteModifyStatement(collection.Modify(string.Empty))); + Assert.AreEqual(ex.Message, errorMessage); + ex = Assert.Throws(() => ExecuteModifyStatement(collection.Modify(""))); + Assert.AreEqual(ex.Message, errorMessage); + ex = Assert.Throws(() => ExecuteModifyStatement(collection.Modify(" "))); + Assert.AreEqual(ex.Message, errorMessage); + ex = Assert.Throws(() => ExecuteModifyStatement(collection.Modify(" "))); + Assert.AreEqual(ex.Message, errorMessage); + ex = Assert.Throws(() => ExecuteModifyStatement(collection.Modify(null))); + Assert.AreEqual(ex.Message, errorMessage); + + // Sending an expression that evaluates to true applies changes on all documents. + result = ExecuteModifyStatement(collection.Modify("true").Set("pages", "10")); + Assert.AreEqual(2, result.AffectedItemsCount); + } + + [Test] + public void ModifyWithLimit() + { + Collection collection = CreateCollection("test"); + var docs = new[] + { + new { _id = 1, title = "Book 1", pages = 20 }, + new { _id = 2, title = "Book 2", pages = 30 }, + }; + Result result = ExecuteAddStatement(collection.Add(docs)); + Assert.AreEqual(2, result.AffectedItemsCount); + + ExecuteModifyStatement(collection.Modify("true").Set("title", "Book X").Limit(1)); + Assert.That(ExecuteFindStatement(collection.Find("title = \"Book X\"")).FetchAll(), Has.One.Items); + + // Limit out of range. + Assert.Throws(() => ExecuteModifyStatement(collection.Modify("true").Set("pages", 10).Limit(0))); + Assert.Throws(() => ExecuteModifyStatement(collection.Modify("true").Set("pages", 10).Limit(-10))); + } + + [Test] + public void ModifyWithInOperator() + { + if (!session.InternalSession.GetServerVersion().isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); + + Collection collection = CreateCollection("test"); + var docs = new[] + { + new DbDoc("{ \"a\": 1, \"b\": \"foo\", \"c\": { \"d\": true, \"e\": [1,2,3] }, \"f\": [ {\"x\":5}, {\"x\":7 } ] }"), + new DbDoc("{ \"a\": 2, \"b\": \"foo2\", \"c\": { \"d\": true, \"e\": [4,5,6] }, \"f\": [ {\"x\":5}, {\"x\":8 } ] }"), + new DbDoc("{ \"a\": 1, \"b\": \"foo3\", \"c\": { \"d\": true, \"e\": [1,4,3] }, \"f\": [ {\"x\":6}, {\"x\":9 } ] }"), + }; + Result result = ExecuteAddStatement(collection.Add(docs)); + Assert.AreEqual(3, result.AffectedItemsCount); + + Assert.AreEqual(3, ExecuteModifyStatement(collection.Modify("a IN (1,2)").Set("a", 3)).AffectedItemsCount); + Assert.AreEqual(3, ExecuteFindStatement(collection.Find().Where("a = 3")).FetchAll().Count); + + Assert.AreEqual(3, ExecuteModifyStatement(collection.Modify("a IN [3]").Set("a", 1)).AffectedItemsCount); + Assert.AreEqual(3, ExecuteFindStatement(collection.Find().Where("a = 1")).FetchAll().Count); + + Assert.AreEqual(2, ExecuteModifyStatement(collection.Modify("1 IN c.e").Set("c.e", "newValue")).AffectedItemsCount); + Assert.AreEqual(2, ExecuteFindStatement(collection.Find().Where("c.e = \"newValue\"")).FetchAll().Count); + } + + [Test] + public void ReplaceOne() + { + Collection collection = CreateCollection("test"); + var docs = new[] + { + new { _id = 1, title = "Book 1", pages = 20 }, + new { _id = 2, title = "Book 2", pages = 30 }, + new { _id = 3, title = "Book 3", pages = 40 }, + new { _id = 4, title = "Book 4", pages = 50 }, + }; + Result result = ExecuteAddStatement(collection.Add(docs)); + Assert.AreEqual(4, result.AffectedItemsCount); + + // Expected exceptions. + Assert.Throws(() => collection.ReplaceOne(null, docs[1])); + Assert.Throws(() => collection.ReplaceOne("", docs[1])); + Assert.Throws(() => collection.ReplaceOne(string.Empty, docs[1])); + Assert.Throws(() => collection.ReplaceOne("1", null)); + // Replace using no matching id + Assert.Throws(() => collection.ReplaceOne(3, new DbDoc("{ \"_id\": 2, \"name\": \"John\", \"lastName\": \"Smith\" }")), + ResourcesX.ReplaceWithNoMatchingId); + + var newDoc = new { _id = 1, title = "Book 11", pages = 311 }; + + // Replace using a numeric identifier. + Assert.AreEqual(1, collection.ReplaceOne(1, newDoc).AffectedItemsCount); + DbDoc document = collection.GetOne(1); + Assert.AreEqual(1, Convert.ToInt32(document.Id)); + Assert.AreEqual("Book 11", document["title"]); + Assert.AreEqual(311, Convert.ToInt32(document["pages"])); + + // Replace using a string identifier. + Assert.AreEqual(1, collection.ReplaceOne("2", new DbDoc("{ \"name\": \"John\", \"lastName\": \"Smith\" }")).AffectedItemsCount); + document = collection.GetOne(2); + Assert.AreEqual(2, Convert.ToInt32(document.Id)); + Assert.AreEqual("John", document["name"]); + Assert.AreEqual("Smith", document["lastName"]); + + // Replace a non-existing document. + Assert.AreEqual(0, collection.ReplaceOne(5, docs[1]).AffectedItemsCount); + Assert.True(collection.GetOne(5) == null); + } + + [Test] + public void ReplaceNestedDocument() + { + var collection = CreateCollection("test"); + var docs = new DbDoc[] + { + new DbDoc(@"{ ""_id"":1, ""pages"":20, ""title"":""Book 1"", ""person"": { ""name"": ""Fred"", ""age"":45 } }" ), + new DbDoc(@"{ ""_id"": 2, ""pages"": 30,""title"" : ""Book 2"", ""person"": { ""name"": ""Peter"", ""age"": 38 } }"), + new DbDoc(@"{ ""_id"": 3, ""pages"": 40,""title"" : ""Book 3"", ""person"": { ""name"": ""Andy"", ""age"": 25 } }"), + new DbDoc(@"{ ""_id"": 4, ""pages"": 50,""title"" : ""Book 4"", ""person"": { ""name"": ""John"", ""age"": 34 } }") + }; + Assert.AreEqual(4, ExecuteAddStatement(collection.Add(docs)).AffectedItemsCount); + + DbDoc d_new = new DbDoc(@"{ ""_id"": 1, ""pages"": 20,""title"" : ""Book 1"", ""person"": { ""name"": ""Fred"", ""age"": 45 ,""State"" : ""Ohio""} }"); + Assert.AreEqual(1, collection.ReplaceOne(1, d_new).AffectedItemsCount); + DbDoc document = collection.GetOne(1); + Assert.AreEqual("Ohio", (document.values["person"] as Dictionary)["State"]); + + d_new = new DbDoc(@"{ ""_id"": 1, ""pages"": 20,""title"" : ""Book 1"", ""person"": { ""name"": ""Fred"", ""age"": 45 ,""State"" : ""Ohio"", ""newProp"": { ""a"":33 } } }"); + Assert.AreEqual(1, collection.ReplaceOne(1, d_new).AffectedItemsCount); + document = collection.GetOne(1); + Assert.AreEqual(33, ((document.values["person"] as Dictionary)["newProp"] as Dictionary)["a"]); + } + + [Test] + public void ArrayInsert() + { + Collection collection = CreateCollection("test"); + ExecuteAddStatement(collection.Add("{ \"x\":[1,2] }")); + + // x[1]=43, x[2]=2. + ExecuteModifyStatement(collection.Modify("true").ArrayInsert("x[1]", 43)); + // x[3]=44. + ExecuteModifyStatement(collection.Modify("true").ArrayInsert("x[3]", 44)); + // Since array only contains 4 items the value 46 is assigned to x[4]. + ExecuteModifyStatement(collection.Modify("true").ArrayInsert("x[5]", 46)); + // Since array only contains 5 items the value 50 is assigned to x[5]. + ExecuteModifyStatement(collection.Modify("true").ArrayInsert("x[20]", 50)); + // Assign an item from different data type. + ExecuteModifyStatement(collection.Modify("true").ArrayInsert("x[6]", "string")); + // Assign a document. + ExecuteModifyStatement(collection.Modify("true").ArrayInsert("x[7]", "{ \"name\":\"Mike\" }")); + + var result = ExecuteFindStatement(collection.Find()); + var document = result.FetchOne(); + var x = (object[])document.values["x"]; + + Assert.AreEqual(8, x.Length); + Assert.AreEqual(1, (int)x[0]); + Assert.AreEqual(43, (int)x[1]); + Assert.AreEqual(2, (int)x[2]); + Assert.AreEqual(44, (int)x[3]); + Assert.AreEqual(46, (int)x[4]); + Assert.AreEqual(50, (int)x[5]); + Assert.AreEqual("string", x[6]); + Assert.True(new DbDoc(x[7]) is DbDoc); + + // No value is inserted if the array doesn't exist. + ExecuteModifyStatement(collection.Modify("true").ArrayInsert("y[0]", 1)); + + result = ExecuteFindStatement(collection.Find()); + document = result.FetchOne(); + Assert.False(document.values.ContainsKey("y")); + + ExecuteModifyStatement(collection.Modify("true").ArrayInsert("x[0]", null)); + ExecuteModifyStatement(collection.Modify("true").ArrayInsert("x[1]", " ")); + + result = ExecuteFindStatement(collection.Find()); + document = result.FetchOne(); + x = (object[])document.values["x"]; + Assert.Null(x[0]); + Assert.AreEqual(" ", x[1]); + + // Insert an empty string fails. + var ex = Assert.Throws(() => ExecuteModifyStatement(collection.Modify("true").ArrayInsert("x[0]", ""))); + StringAssert.Contains("String can't be empty.", ex.Message); + ex = Assert.Throws(() => ExecuteModifyStatement(collection.Modify("true").ArrayInsert("x[0]", string.Empty))); + StringAssert.Contains("String can't be empty.", ex.Message); + + // Not specifying an index raises an error. + var ex2 = Assert.Throws(() => ExecuteModifyStatement(collection.Modify("true").ArrayInsert("dates", "5/1/2018"))); + Assert.AreEqual("A path expression is not a path to a cell in an array.", ex2.Message); + + var col = CreateCollection("my_collection"); + var t1 = "{\"_id\": \"1001\", \"ARR\":[1,2,3], \"ARR1\":[\"name1\",\"name2\", \"name3\"]}"; + col.Add(t1).Execute(); + col.Modify("true").ArrayInsert("ARR[0]", 4).Execute(); + col.Modify("true").ArrayInsert("ARR1[0]", "name4").Execute(); + col.Modify("true").ArrayInsert("ARR[0]", "name5").Execute(); + col.Modify("true").ArrayInsert("ARR1[0]", 5).Execute(); + col.Modify("true").ArrayInsert("ARR[0]", 6).ArrayInsert("ARR1[0]", "name6").ArrayInsert("ARR[0]", 7).ArrayInsert("ARR[0]", 8).Execute(); + col.Modify("true").ArrayInsert("ARR1[0]", null).Execute(); + col.Modify("true").ArrayInsert("ARR1[0]", " ").Execute(); + col.Modify("true").ArrayInsert("ARR1[0]", "****").Execute(); + result = ExecuteFindStatement(col.Find()); + document = result.FetchOne(); + var x2 = (object[])document.values["ARR"]; + Assert.AreEqual(8, x2.Length); + Assert.AreEqual(8, (int)x2[0]); + x2 = (object[])document.values["ARR1"]; + Assert.AreEqual("****", x2[0]); + Assert.AreEqual("name3", x2[8]); + } + + [Test] + public void ArrayAppendWithMySqlExpression() + { + Collection collection = CreateCollection("test"); + + // String containing an expression is not evaluted. + ExecuteAddStatement(collection.Add("{ \"_id\":\"123\", \"name\":\"alice\", \"email\":[ \"alice@ora.com\" ], \"dates\":\"4/1/2017\" }")); + ExecuteModifyStatement(collection.Modify("true").ArrayAppend("email", "UPPER($.name)")); + var document = collection.GetOne("123"); + Assert.AreEqual("UPPER($.name)", (document["email"] as object[])[1]); + + // Use MySqlExpression. + ExecuteAddStatement(collection.Add("{ \"_id\":\"124\", \"name\":\"alice\", \"value\":[ \"alice@ora.com\" ], \"dates\":\"4/1/2017\" }")); + ExecuteModifyStatement(collection.Modify("_id = \"124\"").ArrayAppend("value", new MySqlExpression("UPPER($.name)"))); + document = collection.GetOne("124"); + Assert.AreEqual("ALICE", (document["value"] as object[])[1]); + + // Use embedded MySqlExpression. + ExecuteAddStatement(collection.Add("{ \"_id\":\"125\", \"name\":\"alice\", \"value\":[ \"alice@ora.com\" ], \"dates\":\"4/1/2017\" }")); + ExecuteModifyStatement(collection.Modify("_id = \"125\"").ArrayAppend("value", new { expression = new MySqlExpression("UPPER($.name)") })); + document = collection.GetOne("125"); + var item = ((document["value"] as object[])[1] as Dictionary); + Assert.AreEqual("ALICE", item["expression"]); + + ExecuteAddStatement(collection.Add("{ \"_id\":\"126\", \"name\":\"alice\", \"value\":[ \"alice@ora.com\" ], \"dates\":\"4/1/2017\" }")); + ExecuteModifyStatement(collection.Modify("_id = \"126\"").ArrayAppend("value", new { expression = new MySqlExpression("UPPER($.name)"), literal = "UPPER($.name)" })); + document = collection.GetOne("126"); + item = ((document["value"] as object[])[1] as Dictionary); + Assert.AreEqual("ALICE", item["expression"]); + Assert.AreEqual("UPPER($.name)", item["literal"]); + } + + [Test] + public void ArrayAppendUsesCorrectDataTypes() + { + Collection collection = CreateCollection("test"); + ExecuteAddStatement(collection.Add("{ \"_id\":\"123\", \"email\":[ \"alice@ora.com\"], \"dates\":\"4/1/2017\" }")); + ExecuteModifyStatement(collection.Modify("true").ArrayAppend("dates", "1")); + ExecuteModifyStatement(collection.Modify("true").ArrayAppend("dates", 1)); + var document = collection.GetOne("123"); + var dates = document["dates"] as object[]; + Assert.True(dates[1] is string); + Assert.True(dates[2] is int); + } + + [Test] + public void ArrayAppend() + { + Collection collection = CreateCollection("test"); + ExecuteAddStatement(collection.Add("{ \"x\":[1,2] }")); + + // Append values of different types, null and spaces. + ExecuteModifyStatement(collection.Modify("true").ArrayAppend("x", 43)); + ExecuteModifyStatement(collection.Modify("true").ArrayAppend("x", "string")); + ExecuteModifyStatement(collection.Modify("true").ArrayAppend("x", true)); + ExecuteModifyStatement(collection.Modify("true").ArrayAppend("x", null)); + ExecuteModifyStatement(collection.Modify("true").ArrayAppend("x", " ")); + var result = ExecuteFindStatement(collection.Find()); + DbDoc document = result.FetchOne(); + var x = (object[])document.values["x"]; + + Assert.AreEqual(7, x.Length); + Assert.AreEqual(1, (int)x[0]); + Assert.AreEqual(2, (int)x[1]); + Assert.AreEqual(43, (int)x[2]); + Assert.AreEqual("string", x[3]); + Assert.AreEqual(true, x[4]); + Assert.Null(x[5]); + Assert.AreEqual(" ", x[6]); + + // No value is appended if the array doesn't exist. + ExecuteModifyStatement(collection.Modify("true").ArrayAppend("y", 45)); + + result = ExecuteFindStatement(collection.Find()); + document = result.FetchOne(); + Assert.False(document.values.ContainsKey("y")); + + var ex = Assert.Throws(() => ExecuteModifyStatement(collection.Modify("true").ArrayAppend("x", ""))); + StringAssert.Contains("String can't be empty.", ex.Message); + ex = Assert.Throws(() => ExecuteModifyStatement(collection.Modify("true").ArrayAppend("x", string.Empty))); + StringAssert.Contains("String can't be empty.", ex.Message); + + var col = CreateCollection("my_collection"); + var t1 = "{\"_id\": \"1001\", \"ARR\":[1,2,3], \"ARR1\":[\"name1\",\"name2\", \"name3\"]}"; + col.Add(t1).Execute(); + col.Modify("true").ArrayAppend("ARR", 4).Execute(); + col.Modify("true").ArrayAppend("ARR1", "name4").Execute(); + col.Modify("true").ArrayAppend("ARR", "name5").Execute(); + col.Modify("true").ArrayAppend("ARR1", 5).Execute(); + col.Modify("true").ArrayAppend("ARR", 6).ArrayAppend("ARR1", "name6").ArrayAppend("ARR", 7).ArrayAppend("ARR", 8).Execute(); + + Assert.Throws(() => ExecuteModifyStatement(col.Modify("true").ArrayAppend("ARR1", ""))); + } + + [Test] + public void ArrayInsertWithMySqlExpression() + { + Collection collection = CreateCollection("test"); + ExecuteAddStatement(collection.Add("{ \"x\":[1,2] }")); + + // String containing an expression is not evaluted. + ExecuteAddStatement(collection.Add("{ \"_id\":\"123\", \"name\":\"alice\", \"email\":[ \"alice@ora.com\" ], \"dates\":\"4/1/2017\" }")); + ExecuteModifyStatement(collection.Modify("true").ArrayInsert("email[0]", "UPPER($.name)")); + var document = collection.GetOne("123"); + Assert.AreEqual("UPPER($.name)", (document["email"] as object[])[0]); + + // Use MySqlExpression. + ExecuteAddStatement(collection.Add("{ \"_id\":\"124\", \"name\":\"alice\", \"email\":[ \"alice@ora.com\" ], \"dates\":\"4/1/2017\" }")); + ExecuteModifyStatement(collection.Modify("_id = \"124\"").ArrayInsert("email[0]", new MySqlExpression("UPPER($.name)"))); + document = collection.GetOne("124"); + Assert.AreEqual("ALICE", (document["email"] as object[])[0]); + + // Use embedded MySqlExpression. + ExecuteAddStatement(collection.Add("{ \"_id\":\"125\", \"name\":\"alice\", \"email\":[ \"alice@ora.com\" ], \"dates\":\"4/1/2017\" }")); + ExecuteModifyStatement(collection.Modify("_id = \"125\"").ArrayInsert("email[0]", new { other = new MySqlExpression("UPPER($.name)") })); + document = collection.GetOne("125"); + var item = ((document["email"] as object[])[0] as Dictionary); + Assert.AreEqual("ALICE", item["other"]); + + ExecuteAddStatement(collection.Add("{ \"_id\":\"126\", \"name\":\"alice\", \"email\":[ \"alice@ora.com\" ], \"dates\":\"4/1/2017\" }")); + ExecuteModifyStatement(collection.Modify("_id = \"126\"").ArrayInsert("email[0]", new { other = new MySqlExpression("UPPER($.name)"), literal = "UPPER($.name)" })); + document = collection.GetOne("126"); + item = ((document["email"] as object[])[0] as Dictionary); + Assert.AreEqual("ALICE", item["other"]); + Assert.AreEqual("UPPER($.name)", item["literal"]); + } + + [Test] + public void ArrayOperationsKeepDateValue() + { + Collection collection = CreateCollection("test"); + Result r = ExecuteAddStatement(collection.Add("{ \"_id\": \"123\", \"email\":[\"alice@ora.com\"], \"dates\": \"5/1/2018\" }")); + Assert.AreEqual(1ul, r.AffectedItemsCount); + + // No items are affected since dates isn't an array. + r = ExecuteModifyStatement(collection.Modify("true").ArrayInsert("dates[0]", "4/1/2018")); + Assert.AreEqual(0ul, r.AffectedItemsCount); + + // Converts a non array to an array by appending a value. + ExecuteModifyStatement(collection.Modify("true").ArrayAppend("dates", "6/1/2018")); + + // Array insert at specified index is now succesful since dates is an array. + ExecuteModifyStatement(collection.Modify("true").ArrayInsert("dates[0]", "4/1/2018")); + + DbDoc document = collection.GetOne("123"); + object[] dates = document["dates"] as object[]; + Assert.AreEqual(3, dates.Length); + Assert.AreEqual("4/1/2018", dates[0]); + Assert.AreEqual("5/1/2018", dates[1]); + Assert.AreEqual("6/1/2018", dates[2]); + } + + [Test] + public void Alphanumeric() + { + Collection collection = CreateCollection("test"); + var document = new DbDoc(); + + for (int i = 0; i < 30; i++) + { + document.SetValue("_id", i); + document.SetValue("books", "test" + i); + document.SetValue("pages", i + 10); + document.SetValue("reviewers", "reviewers" + i); + document.SetValue("person", new + { + name = "Fred" + i, + age = i + }); + document.SetValue("1address", "street" + i); + ExecuteAddStatement(collection.Add(document)); + } + + var crudresult = collection.Find("pages=10").Execute().FetchAll(); + Assert.AreEqual(1, crudresult.Count, "Count should be 1 before Unset of pages for _id=0."); + var result = collection.Modify("_id = 0").Unset("pages").Execute(); + Assert.AreEqual(1, result.AffectedItemsCount, "Affected Items Count when modify unset is used"); + crudresult = collection.Find("pages=10").Execute().FetchAll(); + Assert.AreEqual(0, crudresult.Count, "Count should be 0 after Unset of pages for _id=0"); + crudresult = collection.Find("books='test0'").Execute().FetchAll(); + Assert.AreEqual(1, crudresult.Count, "Count should be 0 after Unset of pages for _id=0"); + + result = collection.Modify("_id = 21").Unset("1address").Execute(); + Assert.AreEqual(1, result.AffectedItemsCount, "Affected Items Count when modify unset(multiple docs) is used"); + } + + [Test] + public void UnsetVariations() + { + Collection collection = CreateCollection("test"); + var document = new DbDoc("{ \"_id\":1, \"pages\":1, \"pages2\":2, \"pages3\":3, \"pages4\":{ \"internalPages\":4 } }"); + ExecuteAddStatement(collection.Add(document)); + + // Whitespace is ignored. + ExecuteModifyStatement(collection.Modify("_id = 1").Unset("pages ")); + Assert.False(collection.GetOne(1).values.ContainsKey("pages")); + ExecuteModifyStatement(collection.Modify("_id = 1").Unset(" pages2 ")); + Assert.False(collection.GetOne(1).values.ContainsKey("pages2")); + ExecuteModifyStatement(collection.Modify("_id = 1").Unset(" pages3")); + Assert.False(collection.GetOne(1).values.ContainsKey("pages3")); + ExecuteModifyStatement(collection.Modify("_id = 1").Unset(" pages4.internalPages ")); + Assert.True(collection.GetOne(1).values.ContainsKey("pages4")); + Assert.False(collection.GetOne(1).values.ContainsKey("pages4.internalPages")); + + // Error is raised with incorrect document path. + var ex = Assert.Throws(() => ExecuteModifyStatement(collection.Modify("_id = 1").Unset("pages*"))); + Assert.AreEqual("Invalid document path.", ex.Message); + ex = Assert.Throws(() => ExecuteModifyStatement(collection.Modify("_id = 1").Unset("pages!"))); + Assert.AreEqual("Invalid document path.", ex.Message); + ex = Assert.Throws(() => ExecuteModifyStatement(collection.Modify("_id = 1").Unset("pages*data"))); + Assert.AreEqual("Invalid document path.", ex.Message); + } + + #region WL14389 + + [Test, Description("Collection.Modify(condition).Unset() to accept a list of elements instead of just one.")] + public void CollectionModifyUnset() + { + List idStringList = new List(); + var col = CreateCollection("my_collection"); + var d1 = new DbDoc(); + for (int i = 0; i < 30; i++) + { + d1.SetValue("_id", i); + d1.SetValue("books", "test" + i); + d1.SetValue("pages", i + 10); + d1.SetValue("reviewers", "reviewers" + i); + d1.SetValue("person", new { name = "Fred" + i, age = i }); + d1.SetValue("1address", "street" + i); + col.Add(d1).Execute(); + } + + var crudresult = col.Find("pages=10").Execute().FetchAll(); + Assert.AreEqual(1, crudresult.Count, "Count should be 1 before Unset of pages for _id=0."); + var result = col.Modify("_id = 0").Unset("pages").Execute(); + Assert.AreEqual(1, result.AffectedItemsCount, "Affected Items Count when modify unset is used"); + crudresult = col.Find("pages=10").Execute().FetchAll(); + Assert.AreEqual(0, crudresult.Count, "Count should be 0 after Unset of pages for _id=0"); + crudresult = col.Find("books='test0'").Execute().FetchAll(); + Assert.AreEqual(1, crudresult.Count, "Count should be 0 after Unset of pages for _id=0"); + + crudresult = col.Find("pages=11").Execute().FetchAll(); + Assert.AreEqual(1, crudresult.Count, "Count of pages=11 should be 1 before Unset of pages for _id=1."); + crudresult = col.Find("reviewers='reviewers1'").Execute().FetchAll(); + Assert.AreEqual(1, crudresult.Count, "Count of reviewers1 should be 1 before Unset of pages for _id=1."); + result = col.Modify("_id = 1").Unset("pages").Unset("reviewers").Execute(); + Assert.AreEqual(1, result.AffectedItemsCount, "Affected Items Count when modify multiple unset is used"); + crudresult = col.Find("pages=11").Execute().FetchAll(); + Assert.AreEqual(0, crudresult.Count, "Count should be 0 after Unset of pages for _id=1"); + crudresult = col.Find("reviewers='reviewers1'").Execute().FetchAll(); + Assert.AreEqual(0, crudresult.Count, "Count should be 0 after Unset of pages for _id=1"); + + crudresult = col.Find("pages=21").Execute().FetchAll(); + Assert.AreEqual(1, crudresult.Count, "Count of pages=21 should be 1 before Unset of pages for _id=11."); + crudresult = col.Find("reviewers='reviewers11'").Execute().FetchAll(); + Assert.AreEqual(1, crudresult.Count, "Count of reviewers11 should be 1 before Unset of pages for _id=11."); + result = col.Modify("_id = 11").Unset(new string[] { "pages", "reviewers" }).Execute(); + Assert.AreEqual(1, result.AffectedItemsCount, "Affected Items Count when modify unset(multiple docs) is used"); + crudresult = col.Find("pages=21").Execute().FetchAll(); + Assert.AreEqual(0, crudresult.Count, "Count should be 0 after Unset of pages for _id=11"); + crudresult = col.Find("reviewers='reviewers11'").Execute().FetchAll(); + Assert.AreEqual(0, crudresult.Count, "Count should be 0 after Unset of pages for _id=11"); + + crudresult = col.Find("pages=31").Execute().FetchAll(); + Assert.AreEqual(1, crudresult.Count, "Count of pages=31 should be 1 before Unset of pages for _id=21."); + crudresult = col.Find("reviewers='reviewers21'").Execute().FetchAll(); + Assert.AreEqual(1, crudresult.Count, "Count of reviewers21 should be 1 before Unset of pages for _id=21."); + + result = col.Modify("_id = 21").Unset(" pages ").Execute(); + Assert.AreEqual(1, result.AffectedItemsCount, "Affected Items Count when modify unset(multiple docs) is used"); + //Should have failed when unset is used for fields with special characters + Assert.Throws(() => ExecuteModifyStatement(col.Modify("_id = 22").Unset("pages*"))); + //Should have failed when unset is used for non-existent fields + Assert.Throws(() => ExecuteModifyStatement(col.Modify("_id = 21").Unset("1"))); + //Should have failed when unset is used for special characters + Assert.Throws(() => ExecuteModifyStatement(col.Modify("_id = 21").Unset("@*%#^)(-+!~<>?/"))); + //Should have failed when unset is used for special characters + Assert.Throws(() => ExecuteModifyStatement(col.Modify("_id = 21").Unset("*******"))); + + crudresult = col.Find("pages=31").Execute().FetchAll(); + Assert.AreEqual(0, crudresult.Count, "Count should be 0 after Unset of pages for _id=21"); + + result = col.Modify("_id = 12").Unset(new string[] { " pages1", "reviewers1" }).Execute(); + Assert.AreEqual(0, result.AffectedItemsCount, "Affected Items Count when modify unset(invalid docs) is used"); + crudresult = col.Find("pages=22").Execute().FetchAll(); + Assert.AreEqual(1, crudresult.Count, "Count should be 1 after Unset with invalid of pages for _id=12"); + crudresult = col.Find("reviewers='reviewers12'").Execute().FetchAll(); + Assert.AreEqual(1, crudresult.Count, "Count should be 1 after Unset with invalid of pages for _id=12"); + //Testcase should have failed when unset is used with null + Assert.Throws(() => ExecuteModifyStatement(col.Modify("_id = 12").Unset(null))); + + crudresult = col.Find("pages=22").Execute().FetchAll(); + Assert.AreEqual(1, crudresult.Count, "Count should be 1 after Unset with null of pages for _id=12"); + crudresult = col.Find("reviewers='reviewers12'").Execute().FetchAll(); + Assert.AreEqual(1, crudresult.Count, "Count should be 1 after Unset with null of pages for _id=12"); + + Assert.Throws(() => ExecuteModifyStatement(col.Modify("_id = 12").Unset(""))); + + crudresult = col.Find("pages=22").Execute().FetchAll(); + Assert.AreEqual(1, crudresult.Count, "Count should be 1 after Unset with blank of pages for _id=12"); + crudresult = col.Find("reviewers='reviewers12'").Execute().FetchAll(); + Assert.AreEqual(1, crudresult.Count, "Count should be 1 after Unset with blank of pages for _id=12"); + + crudresult = col.Find("pages=22").Execute().FetchAll(); + Assert.AreEqual(1, crudresult.Count, "Count should be 1 after Unset with blank with space of pages for _id=12"); + crudresult = col.Find("reviewers='reviewers12'").Execute().FetchAll(); + Assert.AreEqual(1, crudresult.Count, "Count should be 1 after Unset with blank with space of pages for _id=12"); + + //Testcase should have failed when unset is used with blank and space + Assert.Throws(() => ExecuteModifyStatement(col.Modify("_id = 12").Unset(new string[] { "", " ", "pages" }))); + + crudresult = col.Find("pages=22").Execute().FetchAll(); + Assert.AreEqual(1, crudresult.Count); + crudresult = col.Find("reviewers='reviewers12'").Execute().FetchAll(); + Assert.AreEqual(1, crudresult.Count); + } + + [Test, Description("All Bug Fixes")] + public void ValidateValuesAfterAppendAndInserts() + { + DbDoc document = null; + Collection collection = CreateCollection("test"); + Result r = collection.Add("{ \"_id\": \"123\", \"email\": [\"alice@ora.com\"], " + + "\"dates\": \"4/1/2017\" }").Execute(); + Assert.AreEqual(1, r.AffectedItemsCount); + + collection.Modify("true").ArrayAppend("dates", "5/1/2018").Execute(); + document = collection.GetOne("123"); + object[] dates = document["dates"] as object[]; + Assert.AreEqual(2, dates.Length); + Assert.AreEqual("4/1/2017", dates[0], "Existing Date"); + Assert.AreEqual("5/1/2018", dates[1], "Appended Date"); + collection.Modify("true").ArrayInsert("dates[0]", "5/1/2059").Execute(); + document = collection.GetOne("123"); + dates = document["dates"] as object[]; + Assert.AreEqual("5/1/2059", dates[0], "Inserted Date"); + + collection = CreateCollection("test"); + r = collection.Add("{ \"_id\": \"123\", \"email\": [\"alice@ora.com\"], " + + "\"dates\": [\"4/1/2017\"] }").Execute(); + Assert.AreEqual(1, r.AffectedItemsCount); + + collection = CreateCollection("test"); + r = collection.Add("{ \"_id\": \"123\", \"email\": [\"alice@ora.com\"], " + + "\"dates\": \"4/1/2017\" }").Execute(); + Assert.AreEqual(1, r.AffectedItemsCount); + collection.Modify("true").ArrayAppend("dates", "1").Execute(); + collection.Modify("true").ArrayAppend("dates", 1).Execute(); + collection.Modify("true").ArrayAppend("dates", "3.1").Execute(); + collection.Modify("true").ArrayAppend("dates", 3.1).Execute(); + document = collection.GetOne("123"); + dates = document["dates"] as object[]; + Assert.AreEqual(5, dates.Length); + Assert.AreEqual("4/1/2017", dates[0], "Existing Date"); + Assert.AreEqual("1", dates[1], "Appended Date"); + Assert.AreEqual(1, dates[2], "Appended Date"); + Assert.AreEqual("3.1", dates[3], "Appended Date"); + Assert.AreEqual(3.1, dates[4], "Appended Date"); + + collection.Modify("true").ArrayInsert("dates[0]", "10").Execute(); + collection.Modify("true").ArrayInsert("dates[0]", 1000).Execute(); + collection.Modify("true").ArrayInsert("dates[0]", "3.1").Execute(); + collection.Modify("true").ArrayInsert("dates[0]", 22.7).Execute(); + document = collection.GetOne("123"); + dates = document["dates"] as object[]; + Assert.AreEqual("10", dates[3], "Inserted Date"); + Assert.AreEqual(1000, dates[2], "Inserted Date"); + Assert.AreEqual("3.1", dates[1], "Inserted Date"); + Assert.AreEqual(22.7, dates[0], "Inserted Date"); + + var d1 = new DbDoc(); + for (int i = 0; i < 30; i++) + { + d1.SetValue("_id", i); + d1.SetValue("books", "test" + i); + d1.SetValue("pages", i + 10); + d1.SetValue("reviewers", "reviewers" + i); + d1.SetValue("person", new + { + name = "Fred" + i, + age = i + }); + d1.SetValue("1address", "street" + i); + collection.Add(d1).Execute(); + } + Assert.Throws(() => ExecuteModifyStatement(collection.Modify("_id = 21").Unset("pages*"))); + + var docs = new[] + { + new { _id = 100, title = "Book 1", pages = 20 }, + new { _id = 200, title = "Book 2", pages = 30 }, + new { _id = 300, title = "Book 3", pages = 40 }, + new { _id = 400, title = "Book 4", pages = 50 }, + }; + r = collection.Add(docs).Execute(); + Assert.AreEqual(4, r.AffectedItemsCount, "Matching the records affected"); + var test1 = collection.Find("pages = :Pages").Bind("pAges", 90).Fields("{\"_id\":100,\"pages\": 20 }").Execute(); + Assert.IsNotNull(test1); + } + + [Test, Description("Collection.modify(condition).arrayAppend(CollectionField, ExprOrLiteral)")] + public void CollectionModifyArrayAppend() + { + + string currentYear = DateTime.Now.Year.ToString(); + DbDoc document = null; + string t1 = "{\"_id\": \"1\", \"name\": \"Alice\" }"; + var collection = CreateCollection("test"); + Result r = collection.Add(t1).Execute(); + Assert.AreEqual(1, r.AffectedItemsCount); + object[] expressions1 = new object[] { "YEAR('2000-01-01')", "MONTH('2008-02-03')", "WEEK('2008-02-20')", "DAY('2008-02-20')", "HOUR('10:05:03')", + "MINUTE('2008-02-03 10:05:03')","SECOND('10:05:03')","MICROSECOND('12:00:00.123456')","QUARTER('2008-04-01')","TIME('2003-12-31 01:02:03')","DATE('2003-12-31 01:02:03')", + "Year(CURDATE())"}; + + object[] expressions2 = new object[] { "5/1/2018",2012,"2012",-22.7,22.7,"22.7", "'large'", + "'838:59:59'" ,true,-100000000,"-10000000000","6/6/2018","9999-12-31 23:59:59","0000-00-00 00:00:00","[a,b,c]","[]"}; + object[] compare_expressions1 = new object[] { 2000, 2, 7, 20, 10, 5, 3, 123456, 2, "01:02:03.000000", "2003-12-31", currentYear }; + object[] compare_expressions2 = new object[] { "5/1/2018",2012, "2012", -22.7, 22.7, "22.7", + "'large'", "'838:59:59'", true, -100000000, "-10000000000","6/6/2018" ,"9999-12-31 23:59:59","0000-00-00 00:00:00","[a,b,c]","[]"}; + for (int k = 0; k < expressions1.Length; k++) + { + collection.Modify("true").ArrayAppend("name", "{ \"dateAndTimeValue\": " + expressions1[k] + " }").Execute(); + } + for (int k = 0; k < expressions2.Length; k++) + { + collection.Modify("true").ArrayAppend("name", "{ \"dateAndTimeValue\": \"" + expressions2[k] + "\" }").Execute(); + } + object[] actors = null; + object test = null; + Dictionary actor0 = null; + int l = 1; + for (int k = 0; k < compare_expressions1.Length; k++) + { + + document = collection.GetOne("1"); + actors = document["name"] as object[]; + actor0 = actors[l] as Dictionary; + test = actor0["dateAndTimeValue"]; + Assert.AreEqual(compare_expressions1[k].ToString(), test.ToString()); + l++; + } + for (int k = 0; k < compare_expressions2.Length; k++) + { + + document = collection.GetOne("1"); + actors = document["name"] as object[]; + actor0 = actors[l] as Dictionary; + test = actor0["dateAndTimeValue"]; + Assert.AreEqual(compare_expressions2[k].ToString(), test.ToString()); + l++; + } + + collection = CreateCollection("test"); + r = collection.Add("{ \"_id\": \"123\", \"email\": [\"alice@ora.com\"], " + + "\"dates\": [\"4/1/2017\"] }").Execute(); + Assert.AreEqual(1, r.AffectedItemsCount); + var reg_expression = new + { + test1 = new MySqlExpression("UPPER($.email)"), + test2 = new MySqlExpression("LOWER($.email)"), + test3 = new MySqlExpression("CONCAT('No', 'S', 'QL')"), + test4 = new MySqlExpression("CHAR(77, 121, 83, 81, '76')"), + test5 = new MySqlExpression("CONCAT('My', NULL, 'QL')"), + test6 = new MySqlExpression("ELT(4, 'ej', 'Heja', 'hej', 'foo')"), + test7 = new MySqlExpression("REPEAT('MySQL', 3)"), + test8 = new MySqlExpression("REVERSE('abc')"), + test9 = new MySqlExpression("RIGHT('foobarbar', 4)"), + test10 = new MySqlExpression("REPLACE('www.mysql.com', 'w', 'Ww')"), + test11 = new MySqlExpression(" HEX('abc')"), + test12 = new MySqlExpression(" BIN(12)"), + }; + object[] compare_expressions = null; + if (session.Version.isAtLeast(8, 0, 0)) + { + compare_expressions = new object[] { "[\\\"ALICE@ORA.COM\\\"]", "[\\\"alice@ora.com\\\", \\\"[\\\\\\\"alice@ora.com\\\\\\\"]\\\"]", + "NoSQL","base64:type253:TXlTUUw=",null,"foo","MySQLMySQLMySQL","cba","rbar","WwWwWw.mysql.com","616263","1100" }; + } + else + { + compare_expressions = new object[] { "[\\\"ALICE@ORA.COM\\\"]", "[\\\"alice@ora.com\\\", \\\"[\\\\\\\"alice@ora.com\\\\\\\"]\\\"]", + "NoSQL","base64:type15:TXlTUUw=",null,"foo","MySQLMySQLMySQL","cba","rbar","WwWwWw.mysql.com","616263","1100" }; + } + + var items = new List(); + items.Add(reg_expression.test1); + items.Add(reg_expression.test2); + items.Add(reg_expression.test3); + items.Add(reg_expression.test4); + items.Add(reg_expression.test5); + items.Add(reg_expression.test6); + items.Add(reg_expression.test7); + items.Add(reg_expression.test8); + items.Add(reg_expression.test9); + items.Add(reg_expression.test10); + items.Add(reg_expression.test11); + items.Add(reg_expression.test12); + int m = 1, n = 0; + foreach (var obj in items) + { + collection.Modify("true").ArrayAppend("email", obj).Execute(); + document = collection.GetOne("123"); + actors = document["email"] as object[]; + if (n == 3) + { } + else + { + Assert.AreEqual(actors[m], compare_expressions[n]); + } + + m++; n++; + } + + string json = ""; + int i = 0, j = 0, maxField = 40; + collection = CreateCollection("test"); + int maxDepth = 2; + json = "{\"_id\":\"1002\",\"XYZ\":1111"; + for (j = 0; j < maxField; j++) + { + json = json + ",\"ARR" + j + "\":["; + for (i = 0; i < maxDepth; i++) + { + json = json + i + ",["; + } + json = json + i; + for (i = maxDepth - 1; i >= 0; i--) + { + json = json + "]," + i; + } + json = json + "]"; + } + json = json + "}"; + + collection.Add(json).Execute(); + r = collection.Modify("true").ArrayAppend("ARR10", 1).ArrayAppend("ARR20", 2).ArrayAppend("ARR30", 3).Execute(); + Assert.AreEqual(1, r.AffectedItemsCount); + r = collection.Modify("true").ArrayAppend("ARR0", null).Execute(); + Assert.AreEqual(1, r.AffectedItemsCount); + r = collection.Modify("true").ArrayAppend("ARR39", null).Execute(); + Assert.AreEqual(1, r.AffectedItemsCount); + + } + + [Test, Description("MySQLX CNET Forbid modify() with no condition-Scenario-1")] + public void ForbidModifyWithNoCondition_S1() + { + + Collection collection = CreateCollection("test"); + var docs = new[] + { + new { _id = 1, title = "Book 1", pages = 20 }, + new { _id = 2, title = "Book 2", pages = 30 }, + new { _id = 3, title = "Book 3", pages = 40 }, + new { _id = 4, title = "Book 4", pages = 50 }, + }; + Result result = collection.Add(docs).Execute(); + Assert.AreEqual(4, result.AffectedItemsCount); + + // Condition can't be null or empty. + Assert.Throws(() => ExecuteModifyStatement(collection.Modify(string.Empty))); + Assert.Throws(() => ExecuteRemoveStatement(collection.Remove(""))); + Assert.Throws(() => ExecuteModifyStatement(collection.Modify(null))); + + // Sending an expression that evaluates to true applies changes on all documents. + result = collection.Modify("true").Set("pages", "10").Execute(); + Assert.AreEqual(4, result.AffectedItemsCount); + + } + + [Test, Description("MySQLX CNET Forbid modify() with no condition-Scenario-2")] + public void ForbidModifyWithNoCondition_S2() + { + + Collection collection = CreateCollection("test"); + var docs = new[] + { + new { _id = 1, title = "Book 1", pages = 20 }, + new { _id = 2, title = "Book 2", pages = 30 }, + new { _id = 3, title = "Book 3", pages = 40 }, + new { _id = 4, title = "Book 4", pages = 50 }, + }; + Result result = collection.Add(docs).Execute(); + Assert.AreEqual(4, result.AffectedItemsCount); + + // Sending an expression that evaluates to true applies changes on all documents. + //Deprecated Modify().Where() in 8.0.17 + result = collection.Modify("true").Where("false").Set("pages", "10").Execute(); + Assert.AreEqual(0, result.AffectedItemsCount); + + result = collection.Modify("true").Where("true").Set("pages", "10").Execute(); + Assert.AreEqual(4, result.AffectedItemsCount); + result = collection.Modify("false").Where("true").Set("pages", "40").Execute(); + Assert.AreEqual(4, result.AffectedItemsCount); + result = collection.Modify("false").Where("false").Set("pages", "40").Execute(); + Assert.AreEqual(0, result.AffectedItemsCount); + + // Condition can't be null or empty. + Assert.Throws(() => ExecuteModifyStatement(collection.Modify(" "))); + } + + [Test, Description("Test valid modify.patch to change element at Depth n for multiple arrays#Bug))")] + public void ModifyPatchNDepth() + { + if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher."); + string json = ""; + int i = 0, j = 0, maxField = 100; + var collection = CreateCollection("test"); + int maxDepth = 46; + json = "{\"_id\":\"1002\",\"XYZ\":1111"; + for (j = 0; j < maxField; j++) + { + json = json + ",\"ARR" + j + "\":["; + for (i = 0; i < maxDepth; i++) + { + json = json + i + ",["; + } + json = json + i; + for (i = maxDepth - 1; i >= 0; i--) + { + json = json + "]," + i; + } + json = json + "]"; + } + json = json + "}"; + + var r = collection.Modify("age = :age").Patch(json). + Bind("age", "18").Execute(); + Assert.IsNotNull(r); + } + + [Test, Description("Test valid modify.patch with condition/limit/OrderBy")] + public void ModifyPatch() + { + if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher."); + var collection = CreateCollection("test"); + var docs = new[] + { + new {_id = 1, title = "Book 1", pages = 20, age = 12}, + new {_id = 2, title = "Book 2", pages = 30,age = 18}, + new {_id = 3, title = "Book 3", pages = 40,age = 34}, + new {_id = 4, title = "Book 4", pages = 50,age = 15} + }; + var r = collection.Add(docs).Execute(); + Assert.AreEqual(4, (int)r.AffectedItemsCount, "Matching the updated record count"); + + var jsonParams = new { title = "Book 100" }; + var foundDocs = collection.Modify("age==18").Patch(jsonParams).Execute(); + Assert.AreEqual(1, (int)foundDocs.AffectedItemsCount, "Matching the record count"); + + var document = collection.GetOne("2"); + Assert.AreEqual("Book 100", document["title"]); + + jsonParams = new { title = "Book 300" }; + r = collection.Modify("age<18").Patch(jsonParams).Limit(1).Execute(); + Assert.AreEqual(1, (int)r.AffectedItemsCount, "Matching the record count"); + + document = collection.GetOne(1); + Assert.AreEqual("Book 300", document["title"]); + + var jsonParams1 = new { title = "Book 10", pages = 1000 }; + r = collection.Modify("age>30").Patch(jsonParams1).Sort("age ASC").Execute(); + Assert.AreEqual(1, (int)r.AffectedItemsCount, "Matching the record count"); + } + + [Test, Description("Test valid modify.patch with set/unset")] + public void ModifyPatchWithSetUnset() + { + if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher."); + var collection = CreateCollection("test"); + var docs = new[] + { + new {_id = 1, title = "Book 1", pages = 20, age = "12"}, + new {_id = 2, title = "Book 2", pages = 30,age = "18"}, + new {_id = 3, title = "Book 3", pages = 40,age = "34"}, + new {_id = 4, title = "Book 4", pages = 50,age = "12"} + }; + Result r = collection.Add(docs).Execute(); + Assert.AreEqual(4, r.AffectedItemsCount); + + var jsonParams = new { title = "Book 500" }; + r = collection.Modify("age = :age").Patch(jsonParams).Bind("age", "18"). + Set("pages", "5000").Execute(); + Assert.AreEqual(1, r.AffectedItemsCount); + + var document = collection.GetOne("2"); + Assert.AreEqual("5000", document["pages"].ToString()); + Assert.AreEqual("Book 500", document["title"].ToString()); + + var jsonParams1 = new { title = "Book 50000", pages = 5000 }; + r = collection.Modify("age = :age").Patch(jsonParams1).Bind("age", "18"). + Unset("pages").Execute(); + Assert.AreEqual(1, r.AffectedItemsCount, "Match being done"); + document = collection.GetOne("2"); + DbDoc test = null; + Assert.Throws(() => test = (DbDoc)document["pages"]); + Assert.AreEqual("Book 50000", document["title"]); + } + + [Test, Description("Test invalid modify.patch to attempt to change _id using modify.patch")] + public void ModifyPatchChangeId() + { + if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher."); + var collection = CreateCollection("test"); + var docs = new[] + { + new {_id = 1, title = "Book 1", pages = 20, age = 12}, + new {_id = 2, title = "Book 2", pages = 30,age = 18}, + new {_id = 3, title = "Book 3", pages = 40,age = 34}, + new {_id = 4, title = "Book 4", pages = 50,age = 12} + }; + Result r = collection.Add(docs).Execute(); + Assert.AreEqual(4, r.AffectedItemsCount); + var document = collection.GetOne("1"); + var jsonParams = new { _id = 123 }; + + r = collection.Modify("age = :age").Patch(jsonParams). + Bind("age", 18).Execute(); + Assert.AreEqual(0, r.AffectedItemsCount); + + var jsonParams2 = new { _id = 123, title = "Book 4000" }; + + r = collection.Modify("age = :age").Patch(jsonParams2). + Bind("age", 18).Execute(); + Assert.AreEqual(1, r.AffectedItemsCount); + + string jsonParams1 = "{ \"_id\": \"123\"}"; + r = collection.Modify("age = :age").Patch(jsonParams1). + Bind("age", 18).Execute(); + Assert.AreEqual(0, r.AffectedItemsCount); + + jsonParams1 = "{ \"_id\": \"123\",\"title\": \"Book 400\"}"; + r = collection.Modify("age = :age").Patch(jsonParams1). + Bind("age", 18).Execute(); + Assert.AreEqual(1, r.AffectedItemsCount); + } + + [Test, Description("Test modify.patch where the key to be modified has array, dbDoc and normal constant value and condition is matched for all.")] + public void ModifyPatchKeyWithArray() + { + if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher."); + var collection = CreateCollection("test"); + var docs1 = new[] + { + new {_id = 1, title = "Book 1", pages = 20, age = 12,name = "Morgan"}, + }; + var docs2 = + "{\"_id\": \"2\",\"age\": 12,\"name\": \"Alice\", " + + "\"address\": {\"zip\": \"12345\", \"city\": \"Los Angeles\", \"street\": \"32 Main str\"}}"; + + var docs3 = "{\"_id\": \"3\", \"age\": 12,\"name\":[\"Cynthia\"], \"ARR1\":[\"name1\",\"name2\", \"name3\"]}"; + Result r = collection.Add(docs1).Execute(); + Assert.AreEqual(1, r.AffectedItemsCount); + r = collection.Add(docs2).Execute(); + Assert.AreEqual(1, r.AffectedItemsCount); + r = collection.Add(docs3).Execute(); + Assert.AreEqual(1, r.AffectedItemsCount); + var jsonParams = new { name = "Changed" }; + r = collection.Modify("age = :age").Patch(jsonParams).Bind("age", 12).Execute(); + Assert.AreEqual(3, r.AffectedItemsCount); + } + + [Test, Description("Test that documents not matching conditions are not modified.")] + public void ModifyPatchNotMatchingConditions() + { + if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher."); + var collection = CreateCollection("test"); + var docs = new[] + { + new {_id = 1, title = "Book 1", pages = 20, age = 12}, + new {_id = 2, title = "Book 2", pages = 30,age = 18}, + new {_id = 3, title = "Book 3", pages = 40,age = 34}, + new {_id = 4, title = "Book 4", pages = 50,age = 12} + }; + Result r = collection.Add(docs).Execute(); + Assert.AreEqual(4, r.AffectedItemsCount); + var document = collection.GetOne("1"); + var jsonParams = new { title = "Book 100" }; + r = collection.Modify("age = :age").Patch(jsonParams).Bind("age", "19").Execute(); + Assert.AreEqual(0, r.AffectedItemsCount); + string jsonParams1 = "{ \"title\": \"Book 100\"}"; + r = collection.Modify("age = :age").Patch(jsonParams1).Bind("age", "28").Execute(); + Assert.AreEqual(0, r.AffectedItemsCount); + jsonParams1 = "{ \"unknownvalues\": null}"; + r = collection.Modify("age = :age").Patch(jsonParams1).Bind("age", "28").Execute(); + Assert.AreEqual(0, r.AffectedItemsCount); + } + + [Test, Description("Test modify.patch with different types of records(anonymous object,Json String,DbDoc) with same key and try to replace using a patch")] + public void ModifyPatchDifferentTypesSameKey() + { + if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher."); + var collection = CreateCollection("test"); + var docs1 = new[] + { + new {_id = 1, title = "Book 1", pages = 20, age = 12,name = "Morgan"}, + }; + var docs2 = + "{\"_id\": \"2\",\"age\": \"12\",\"name\": \"Alice\", " + + "\"address\": {\"zip\": \"12345\", \"city\": \"Los Angeles\", \"street\": \"32 Main str\"}}"; + + var docs3 = new DbDoc(@"{ ""_id"": 3, ""pages"": 20, ""age"":12,""name"":""Cynthiaa"", + ""books"": [ + {""_id"" : 10, ""title"" : ""Book 10""}, + { ""_id"" : 20, ""title"" : ""Book 20"" } + ] + }"); + Result r = collection.Add(docs1).Execute(); + Assert.AreEqual(1, r.AffectedItemsCount); + r = collection.Add(docs2).Execute(); + Assert.AreEqual(1, r.AffectedItemsCount); + r = collection.Add(docs3).Execute(); + Assert.AreEqual(1, r.AffectedItemsCount); + var jsonParams = new { name = "Changed" }; + r = collection.Modify("age = :age").Patch(jsonParams). + Bind("age", 12).Execute(); + Assert.AreEqual(2, r.AffectedItemsCount);//docs2 age is the string + } + + [Test, Description("GetOne with ExistingID and NewID with doc(Verify the Immutable feature also))")] + public void GetOneAndRemoveOne() + { + if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher."); + var coll = CreateCollection("test"); + var docs = new[] + { + new {_id = 1, title = "Book 1", pages = 20}, + new {_id = 2, title = "Book 2", pages = 30}, + new {_id = 3, title = "Book 3", pages = 40}, + new {_id = 4, title = "Book 4", pages = 50} + }; + var r = coll.Add(docs).Execute(); + Assert.AreEqual(4, r.AffectedItemsCount); + + // Expected exceptions. + Assert.Throws(() => coll.GetOne(null)); + Assert.Throws(() => coll.GetOne("")); + Assert.Throws(() => coll.GetOne(string.Empty)); + Assert.Throws(() => coll.GetOne(" ")); + + // Get document using numeric parameter. + var document = coll.GetOne(1); + Assert.AreEqual(1, document.Id); + Assert.AreEqual("Book 1", document["title"]); + Assert.AreEqual(20, Convert.ToInt32(document["pages"])); + + // Get document using string parameter. + document = coll.GetOne("3"); + Assert.AreEqual(3, document.Id); + Assert.AreEqual("Book 3", document["title"]); + Assert.AreEqual(40, Convert.ToInt32(document["pages"])); + + // Get a non-existing document. + document = coll.GetOne(5); + Assert.AreEqual(null, document); + + coll.Add(new { _id = 5, title = "Book 5", pages = 60 }).Execute(); + Assert.AreEqual(5, coll.Find().Execute().FetchAll().Count); + // Remove sending numeric parameter. + //WL11843-Core API v1 alignment Changes + Assert.AreEqual(1, coll.RemoveOne(1).AffectedItemsCount); + Assert.AreEqual(4, coll.Find().Execute().FetchAll().Count); + + // Remove sending string parameter. + Assert.AreEqual(1, coll.RemoveOne("3").AffectedItemsCount); + Assert.AreEqual(3, coll.Find().Execute().FetchAll().Count); + + // Remove an auto-generated id. + document = coll.Find("pages = 60").Execute().FetchOne(); + Assert.AreEqual(1, coll.RemoveOne(document.Id).AffectedItemsCount); + Assert.AreEqual(2, coll.Find().Execute().FetchAll().Count); + + // Remove a non-existing document. + Assert.AreEqual(0, coll.RemoveOne(5).AffectedItemsCount); + Assert.AreEqual(2, coll.Find().Execute().FetchAll().Count); + + } + + [Test, Description("AddReplaceOne with unique id generated by SQL")] + public void AddReplaceOneUniqueId() + { + if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher."); + var collection = CreateCollection("test"); + var docs = new[] + { + new {_id = 1, name = "foo"}, + new {_id = 2, name = "bar"} + }; + var result = collection.Add(docs).Execute(); + Assert.AreEqual(2, result.AffectedItemsCount); + + // Add unique index. + session.SQL( + "ALTER TABLE test.test ADD COLUMN name VARCHAR(3) GENERATED ALWAYS AS (JSON_UNQUOTE(JSON_EXTRACT(doc, '$.name'))) VIRTUAL UNIQUE KEY NOT NULL") + .Execute(); + Assert.Throws(() => collection.AddOrReplaceOne(1, new { name = "bar" })); + Assert.Throws(() => collection.AddOrReplaceOne(1, new { _id = 3, name = "bar", age = "55" })); + } + + #endregion WL14389 + + } +} diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/CustomTypeTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/CustomTypeTests.cs index 389becd03..33c98ecc6 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/CustomTypeTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/CustomTypeTests.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2023, Oracle and/or its affiliates. +// Copyright © 2023, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/DbDocTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/DbDocTests.cs index 087f0f74d..36c5e8902 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/DbDocTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/DbDocTests.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2015, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/DnsSrvTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/DnsSrvTests.cs index 525911abf..ae65cc357 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/DnsSrvTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/DnsSrvTests.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2019, 2021, Oracle and/or its affiliates. +// Copyright © 2019, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -141,4 +141,4 @@ public void DnsResolverNoHostsPooling() } } } -} \ No newline at end of file +} diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/ExprParserTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/ExprParserTests.cs index 7b7e31cf4..a251cc660 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/ExprParserTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/ExprParserTests.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2015, 2022, Oracle and/or its affiliates. +// Copyright © 2015, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/GenericListener.cs b/MySQL.Data/tests/MySqlX.Data.Tests/GenericListener.cs index 1d9cf00bb..a359f5455 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/GenericListener.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/GenericListener.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/JsonParserTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/JsonParserTests.cs index 6d37b92bf..e7a1b9482 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/JsonParserTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/JsonParserTests.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2017, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/MergePatch.cs b/MySQL.Data/tests/MySqlX.Data.Tests/MergePatch.cs index 26ab3a5d4..6caeeeadd 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/MergePatch.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/MergePatch.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2017, 2021, Oracle and/or its affiliates. +// Copyright © 2017, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/PerformanceTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/PerformanceTests.cs index a5fc6c523..6390cb8a3 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/PerformanceTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/PerformanceTests.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2018, 2021, Oracle and/or its affiliates. +// Copyright © 2018, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/PreparedStatementsTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/PreparedStatementsTests.cs index f6e5fc910..4da250cef 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/PreparedStatementsTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/PreparedStatementsTests.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2018, 2023, Oracle and/or its affiliates. +// Copyright © 2018, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/Properties/AssemblyInfo.cs b/MySQL.Data/tests/MySqlX.Data.Tests/Properties/AssemblyInfo.cs index abfe68df2..97675c386 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/Properties/AssemblyInfo.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/Properties/AssemblyInfo.cs @@ -1,16 +1,16 @@ -// Copyright © 2015, 2019, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2015, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -52,4 +52,4 @@ #if !DEBUG [assembly: AssemblyKeyName("ConnectorNet")] -#endif \ No newline at end of file +#endif diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/ColumnMetadataTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/ColumnMetadataTests.cs index de92ca359..5efb99a58 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/ColumnMetadataTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/ColumnMetadataTests.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2016, 2021, Oracle and/or its affiliates. +// Copyright © 2016, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/DataTypeTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/DataTypeTests.cs index 0790d1b50..62245811d 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/DataTypeTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/DataTypeTests.cs @@ -1,313 +1,313 @@ -// Copyright (c) 2015, 2022, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySql.Data.MySqlClient; -using MySql.Data.MySqlClient.X.XDevAPI.Common; -using MySqlX.XDevAPI.Relational; -using NUnit.Framework; -using System; - -namespace MySqlX.Data.Tests.RelationalTests -{ - public class DataTypeTests : BaseTest - { - [TearDown] - public void TearDown() => ExecuteSQL("DROP TABLE IF EXISTS test"); - - [Test] - public void Float() - { - ExecuteSQL("CREATE TABLE test(rvalue FLOAT(14,8))"); - ExecuteSQL("INSERT INTO test VALUES(23.4), (14.8), (11.9)"); - - RowResult r = ExecuteSelectStatement(GetSession().GetSchema("test").GetTable("test").Select("rvalue")); - var rows = r.FetchAll(); - Assert.That(r.Columns, Has.One.Items); - Assert.AreEqual(typeof(float), r.Columns[0].ClrType); - Assert.AreEqual(14, (int)r.Columns[0].Length); - Assert.AreEqual(8, (int)r.Columns[0].FractionalDigits); - Assert.AreEqual(ColumnType.Float, r.Columns[0].Type); - Assert.AreEqual(3, rows.Count); - Assert.AreEqual(23.4f, (float)rows[0][0]); - Assert.AreEqual(14.8f, rows[1][0]); - Assert.AreEqual(11.9f, rows[2][0]); - } - - [Test] - public void Double() - { - ExecuteSQL("CREATE TABLE test(rvalue DOUBLE(12,4))"); - ExecuteSQL("INSERT INTO test VALUES(23.4), (14.8), (11.9)"); - - RowResult r = ExecuteSelectStatement(GetSession().GetSchema("test").GetTable("test").Select("rvalue")); - var rows = r.FetchAll(); - Assert.That(r.Columns, Has.One.Items); - Assert.AreEqual(typeof(double), r.Columns[0].ClrType); - Assert.AreEqual(ColumnType.Double, r.Columns[0].Type); - Assert.AreEqual(12, (int)r.Columns[0].Length); - Assert.AreEqual(4, (int)r.Columns[0].FractionalDigits); - Assert.AreEqual(3, rows.Count); - Assert.AreEqual(23.4, rows[0][0]); - Assert.AreEqual(14.8, rows[1][0]); - Assert.AreEqual(11.9, rows[2][0]); - } - - [Test] - public void Set() - { - ExecuteSQL("CREATE TABLE test(rvalue SET('A','B','C','D'))"); - ExecuteSQL("INSERT INTO test VALUES('A'), ('B,A'), ('B')"); - - RowResult r = ExecuteSelectStatement(GetSession().GetSchema("test").GetTable("test").Select("rvalue")); - var rows = r.FetchAll(); - Assert.That(r.Columns, Has.One.Items); - Assert.AreEqual(typeof(string), r.Columns[0].ClrType); - Assert.AreEqual(ColumnType.Set, r.Columns[0].Type); - Assert.AreEqual(3, rows.Count); - Assert.AreEqual("A", rows[0][0]); - Assert.AreEqual("A,B", rows[1][0]); - Assert.AreEqual("B", rows[2][0]); - } - - [Test] - public void Enum() - { - ExecuteSQL("CREATE TABLE test(rvalue Enum('Alpha','Beta','C','D'))"); - ExecuteSQL("INSERT INTO test VALUES('Alpha'), ('Beta'), ('C')"); - - RowResult r = ExecuteSelectStatement(GetSession().GetSchema("test").GetTable("test").Select("rvalue")); - var rows = r.FetchAll(); - Assert.That(r.Columns, Has.One.Items); - Assert.AreEqual(typeof(string), r.Columns[0].ClrType); - Assert.AreEqual(ColumnType.Enum, r.Columns[0].Type); - Assert.AreEqual(3, rows.Count); - Assert.AreEqual("Alpha", rows[0][0]); - Assert.AreEqual("Beta", rows[1][0]); - Assert.AreEqual("C", rows[2][0]); - } - - [Test] - public void SignedIntegers() - { - ExecuteSQL("CREATE TABLE test(tinyCol TINYINT, smallCol SMALLINT, mediumCol MEDIUMINT, intCol INT, bigCol BIGINT)"); - ExecuteSQL("INSERT INTO test VALUES(127, 32767, 8388607, 2147483647, 9223372036854775807)"); - ExecuteSQL("INSERT INTO test VALUES(-128, -32768, -8388608, -2147483648, -9223372036854775808)"); - - RowResult r = ExecuteSelectStatement(GetSession().GetSchema("test").GetTable("test").Select()); - var rows = r.FetchAll(); - Assert.AreEqual(5, r.Columns.Count); - Assert.AreEqual(typeof(sbyte), r.Columns[0].ClrType); - Assert.AreEqual(ColumnType.Tinyint, r.Columns[0].Type); - Assert.AreEqual((sbyte)127, rows[0][0]); - Assert.AreEqual((sbyte)-128, rows[1][0]); - Assert.AreEqual(typeof(Int16), r.Columns[1].ClrType); - Assert.AreEqual(ColumnType.Smallint, r.Columns[1].Type); - Assert.AreEqual((short)32767, rows[0][1]); - Assert.AreEqual((short)-32768, rows[1][1]); - Assert.AreEqual(typeof(Int32), r.Columns[2].ClrType); - Assert.AreEqual(ColumnType.Mediumint, r.Columns[2].Type); - Assert.AreEqual(8388607, rows[0][2]); - Assert.AreEqual(-8388608, rows[1][2]); - Assert.AreEqual(typeof(Int32), r.Columns[3].ClrType); - Assert.AreEqual(ColumnType.Int, r.Columns[3].Type); - Assert.AreEqual(2147483647, rows[0][3]); - Assert.AreEqual(-2147483648, rows[1][3]); - Assert.AreEqual(typeof(Int64), r.Columns[4].ClrType); - Assert.AreEqual(ColumnType.Bigint, r.Columns[4].Type); - Assert.AreEqual((long)9223372036854775807, rows[0][4]); - Assert.AreEqual((long)-9223372036854775808, rows[1][4]); - } - - [Test] - public void UnsignedIntegers() - { - ExecuteSQL("CREATE TABLE test(tinyCol TINYINT UNSIGNED, smallCol SMALLINT UNSIGNED, mediumCol MEDIUMINT UNSIGNED, intCol INT UNSIGNED, bigCol BIGINT UNSIGNED)"); - ExecuteSQL("INSERT INTO test VALUES(255, 65535, 16777215, 4294967295, 18446744073709551615)"); - - RowResult r = ExecuteSelectStatement(GetSession().GetSchema("test").GetTable("test").Select()); - var rows = r.FetchAll(); - Assert.AreEqual(5, r.Columns.Count); - Assert.AreEqual(typeof(byte), r.Columns[0].ClrType); - Assert.AreEqual(ColumnType.Tinyint, r.Columns[0].Type); - Assert.AreEqual((byte)255, rows[0][0]); - Assert.AreEqual(typeof(UInt16), r.Columns[1].ClrType); - Assert.AreEqual(ColumnType.Smallint, r.Columns[1].Type); - Assert.AreEqual((ushort)65535, rows[0][1]); - Assert.AreEqual(typeof(UInt32), r.Columns[2].ClrType); - Assert.AreEqual(ColumnType.Mediumint, r.Columns[2].Type); - Assert.AreEqual((uint)16777215, rows[0][2]); - Assert.AreEqual(typeof(UInt32), r.Columns[3].ClrType); - Assert.AreEqual(ColumnType.Int, r.Columns[3].Type); - Assert.AreEqual((uint)4294967295, rows[0][3]); - Assert.AreEqual(typeof(UInt64), r.Columns[4].ClrType); - Assert.AreEqual(ColumnType.Bigint, r.Columns[4].Type); - Assert.AreEqual((ulong)18446744073709551615, rows[0][4]); - } - - [Test] - public void Bit() - { - ExecuteSQL("CREATE TABLE test(bitCol BIT(8))"); - ExecuteSQL("INSERT INTO test VALUES(b'1111111')"); - - RowResult r = ExecuteSelectStatement(GetSession().GetSchema("test").GetTable("test").Select()); - var rows = r.FetchAll(); - Assert.That(r.Columns, Has.One.Items); - Assert.AreEqual(typeof(UInt64), r.Columns[0].ClrType); - Assert.AreEqual(ColumnType.Bit, r.Columns[0].Type); - Assert.AreEqual((ulong)127, rows[0][0]); - } - - [Test] - public void Decimal() - { - ExecuteSQL("CREATE TABLE test(decCol1 DECIMAL(20,9))"); - ExecuteSQL("INSERT INTO test VALUES(-1.23), (-12.345), (5), (43)"); - ExecuteSQL("INSERT INTO test VALUES(14523.2887238), (-8947.8923784)"); - - RowResult r = ExecuteSelectStatement(GetSession().GetSchema("test").GetTable("test").Select()); - var rows = r.FetchAll(); - Assert.That(r.Columns, Has.One.Items); - Assert.AreEqual(typeof(decimal), r.Columns[0].ClrType); - Assert.AreEqual(ColumnType.Decimal, r.Columns[0].Type); - Assert.AreEqual(-1.23m, rows[0][0]); - Assert.AreEqual(-12.345m, rows[1][0]); - Assert.AreEqual(5m, rows[2][0]); - Assert.AreEqual(43m, rows[3][0]); - Assert.AreEqual(14523.2887238m, rows[4][0]); - Assert.AreEqual(-8947.8923784m, rows[5][0]); - } - - [Test] - public void Json() - { - ExecuteSQL("CREATE TABLE test(jdoc JSON)"); - ExecuteSQL("INSERT INTO test VALUES('{ \"id\": 1, \"name\": \"John\" }')"); - ExecuteSQL("INSERT INTO test VALUES('[ \"a\", 1, \"b\", 2 ]')"); - - RowResult r = ExecuteSelectStatement(GetSession().GetSchema("test").GetTable("test").Select()); - var rows = r.FetchAll(); - Assert.That(r.Columns, Has.One.Items); - Assert.AreEqual(typeof(string), r.Columns[0].ClrType); - Assert.AreEqual(ColumnType.Json, r.Columns[0].Type); - Assert.AreEqual("{\"id\": 1, \"name\": \"John\"}", rows[0][0]); - Assert.AreEqual("[\"a\", 1, \"b\", 2]", rows[1][0]); - } - - [Test] - public void Strings() - { - ExecuteSQL("CREATE TABLE test(name VARCHAR(255) COLLATE cp932_japanese_ci)"); - ExecuteSQL("INSERT INTO test VALUES('表')"); - - RowResult r = ExecuteSelectStatement(GetSession().GetSchema("test").GetTable("test").Select()); - var rows = r.FetchAll(); - Assert.That(r.Columns, Has.One.Items); - Assert.AreEqual(typeof(string), r.Columns[0].ClrType); - Assert.AreEqual(ColumnType.String, r.Columns[0].Type); - Assert.AreEqual("表", rows[0][0]); - } - - [Test] - [Ignore("Fix for 8.0.13")] - public void UnsingedZeroFill() - { - ExecuteSQL("CREATE TABLE test(id INT ZEROFILL)"); - ExecuteSQL("INSERT INTO test VALUES(100)"); - - RowResult r = ExecuteSelectStatement(GetSession().GetSchema("test").GetTable("test").Select()); - var rows = r.FetchAll(); - Assert.That(r.Columns, Has.One.Items); - Assert.AreEqual(typeof(UInt32), r.Columns[0].ClrType); - Assert.AreEqual(ColumnType.Int, r.Columns[0].Type); - Assert.False(r.Columns[0].IsNumberSigned); - Assert.True(r.Columns[0].IsPadded); - Assert.AreEqual("0000000100", rows[0][0].ToString()); - } - - [Test] - public void Bytes() - { - ExecuteSQL("CREATE TABLE test(name VARCHAR(255) BINARY)"); - ExecuteSQL("INSERT INTO test VALUES('John')"); - - RowResult r = ExecuteSelectStatement(GetSession().GetSchema("test").GetTable("test").Select()); - var rows = r.FetchAll(); - Assert.That(r.Columns, Has.One.Items); - Assert.AreEqual(typeof(string), r.Columns[0].ClrType); - Assert.AreEqual(ColumnType.String, r.Columns[0].Type); - Assert.AreEqual("John", rows[0][0]); - } - - [Test] - public void BytesUsingCollation() - { - ExecuteSQL("CREATE TABLE test(name VARCHAR(255) COLLATE utf8_bin)"); - ExecuteSQL("INSERT INTO test VALUES('Mark')"); - - RowResult r = ExecuteSelectStatement(GetSession().GetSchema("test").GetTable("test").Select()); - var rows = r.FetchAll(); - Assert.That(r.Columns, Has.One.Items); - Assert.AreEqual(typeof(string), r.Columns[0].ClrType); - Assert.AreEqual(ColumnType.String, r.Columns[0].Type); - Assert.AreEqual("Mark", rows[0][0]); - } - - [Test] - public void Geometry() - { - ExecuteSQL("CREATE TABLE test(line GEOMETRY)"); - ExecuteSQL("INSERT INTO test VALUES(ST_GeomFromText('LINESTRING(0 0, 10 10, 20 25, 50 60)'))"); - - RowResult r = ExecuteSelectStatement(GetSession().GetSchema("test").GetTable("test").Select()); - var rows = r.FetchAll(); - Assert.That(r.Columns, Has.One.Items); - Assert.AreEqual(typeof(byte[]), r.Columns[0].ClrType); - Assert.AreEqual(ColumnType.Geometry, r.Columns[0].Type); - Assert.AreEqual("0000000001020000000400000000000000000000000000000000000000000000000000244000000000000024400000000000003440000000000000394000000000000049400000000000004E40", - BitConverter.ToString((byte[])rows[0][0]).Replace("-", "")); - } - - [Test] - public void BlobTypes() - { - ExecuteSQL("CREATE TABLE test(a BLOB, b TEXT)"); - ExecuteSQL("INSERT INTO test VALUES('Car', 'Plane')"); - - RowResult r = ExecuteSelectStatement(GetSession().GetSchema(schemaName).GetTable("test").Select()); - var rows = r.FetchAll(); - Assert.AreEqual(2, r.Columns.Count); - Assert.AreEqual(typeof(byte[]), r.Columns[0].ClrType); - Assert.AreEqual(typeof(string), r.Columns[1].ClrType); - Assert.AreEqual(ColumnType.Bytes, r.Columns[0].Type); - Assert.AreEqual(ColumnType.String, r.Columns[1].Type); - Assert.AreEqual(CharSetMap.GetEncoding(r.Columns[0].CharacterSetName).GetBytes("Car"), rows[0][0]); - Assert.AreEqual("Plane", rows[0][1]); - } - } -} +// Copyright © 2015, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySql.Data.MySqlClient; +using MySql.Data.MySqlClient.X.XDevAPI.Common; +using MySqlX.XDevAPI.Relational; +using NUnit.Framework; +using System; + +namespace MySqlX.Data.Tests.RelationalTests +{ + public class DataTypeTests : BaseTest + { + [TearDown] + public void TearDown() => ExecuteSQL("DROP TABLE IF EXISTS test"); + + [Test] + public void Float() + { + ExecuteSQL("CREATE TABLE test(rvalue FLOAT(14,8))"); + ExecuteSQL("INSERT INTO test VALUES(23.4), (14.8), (11.9)"); + + RowResult r = ExecuteSelectStatement(GetSession().GetSchema("test").GetTable("test").Select("rvalue")); + var rows = r.FetchAll(); + Assert.That(r.Columns, Has.One.Items); + Assert.AreEqual(typeof(float), r.Columns[0].ClrType); + Assert.AreEqual(14, (int)r.Columns[0].Length); + Assert.AreEqual(8, (int)r.Columns[0].FractionalDigits); + Assert.AreEqual(ColumnType.Float, r.Columns[0].Type); + Assert.AreEqual(3, rows.Count); + Assert.AreEqual(23.4f, (float)rows[0][0]); + Assert.AreEqual(14.8f, rows[1][0]); + Assert.AreEqual(11.9f, rows[2][0]); + } + + [Test] + public void Double() + { + ExecuteSQL("CREATE TABLE test(rvalue DOUBLE(12,4))"); + ExecuteSQL("INSERT INTO test VALUES(23.4), (14.8), (11.9)"); + + RowResult r = ExecuteSelectStatement(GetSession().GetSchema("test").GetTable("test").Select("rvalue")); + var rows = r.FetchAll(); + Assert.That(r.Columns, Has.One.Items); + Assert.AreEqual(typeof(double), r.Columns[0].ClrType); + Assert.AreEqual(ColumnType.Double, r.Columns[0].Type); + Assert.AreEqual(12, (int)r.Columns[0].Length); + Assert.AreEqual(4, (int)r.Columns[0].FractionalDigits); + Assert.AreEqual(3, rows.Count); + Assert.AreEqual(23.4, rows[0][0]); + Assert.AreEqual(14.8, rows[1][0]); + Assert.AreEqual(11.9, rows[2][0]); + } + + [Test] + public void Set() + { + ExecuteSQL("CREATE TABLE test(rvalue SET('A','B','C','D'))"); + ExecuteSQL("INSERT INTO test VALUES('A'), ('B,A'), ('B')"); + + RowResult r = ExecuteSelectStatement(GetSession().GetSchema("test").GetTable("test").Select("rvalue")); + var rows = r.FetchAll(); + Assert.That(r.Columns, Has.One.Items); + Assert.AreEqual(typeof(string), r.Columns[0].ClrType); + Assert.AreEqual(ColumnType.Set, r.Columns[0].Type); + Assert.AreEqual(3, rows.Count); + Assert.AreEqual("A", rows[0][0]); + Assert.AreEqual("A,B", rows[1][0]); + Assert.AreEqual("B", rows[2][0]); + } + + [Test] + public void Enum() + { + ExecuteSQL("CREATE TABLE test(rvalue Enum('Alpha','Beta','C','D'))"); + ExecuteSQL("INSERT INTO test VALUES('Alpha'), ('Beta'), ('C')"); + + RowResult r = ExecuteSelectStatement(GetSession().GetSchema("test").GetTable("test").Select("rvalue")); + var rows = r.FetchAll(); + Assert.That(r.Columns, Has.One.Items); + Assert.AreEqual(typeof(string), r.Columns[0].ClrType); + Assert.AreEqual(ColumnType.Enum, r.Columns[0].Type); + Assert.AreEqual(3, rows.Count); + Assert.AreEqual("Alpha", rows[0][0]); + Assert.AreEqual("Beta", rows[1][0]); + Assert.AreEqual("C", rows[2][0]); + } + + [Test] + public void SignedIntegers() + { + ExecuteSQL("CREATE TABLE test(tinyCol TINYINT, smallCol SMALLINT, mediumCol MEDIUMINT, intCol INT, bigCol BIGINT)"); + ExecuteSQL("INSERT INTO test VALUES(127, 32767, 8388607, 2147483647, 9223372036854775807)"); + ExecuteSQL("INSERT INTO test VALUES(-128, -32768, -8388608, -2147483648, -9223372036854775808)"); + + RowResult r = ExecuteSelectStatement(GetSession().GetSchema("test").GetTable("test").Select()); + var rows = r.FetchAll(); + Assert.AreEqual(5, r.Columns.Count); + Assert.AreEqual(typeof(sbyte), r.Columns[0].ClrType); + Assert.AreEqual(ColumnType.Tinyint, r.Columns[0].Type); + Assert.AreEqual((sbyte)127, rows[0][0]); + Assert.AreEqual((sbyte)-128, rows[1][0]); + Assert.AreEqual(typeof(Int16), r.Columns[1].ClrType); + Assert.AreEqual(ColumnType.Smallint, r.Columns[1].Type); + Assert.AreEqual((short)32767, rows[0][1]); + Assert.AreEqual((short)-32768, rows[1][1]); + Assert.AreEqual(typeof(Int32), r.Columns[2].ClrType); + Assert.AreEqual(ColumnType.Mediumint, r.Columns[2].Type); + Assert.AreEqual(8388607, rows[0][2]); + Assert.AreEqual(-8388608, rows[1][2]); + Assert.AreEqual(typeof(Int32), r.Columns[3].ClrType); + Assert.AreEqual(ColumnType.Int, r.Columns[3].Type); + Assert.AreEqual(2147483647, rows[0][3]); + Assert.AreEqual(-2147483648, rows[1][3]); + Assert.AreEqual(typeof(Int64), r.Columns[4].ClrType); + Assert.AreEqual(ColumnType.Bigint, r.Columns[4].Type); + Assert.AreEqual((long)9223372036854775807, rows[0][4]); + Assert.AreEqual((long)-9223372036854775808, rows[1][4]); + } + + [Test] + public void UnsignedIntegers() + { + ExecuteSQL("CREATE TABLE test(tinyCol TINYINT UNSIGNED, smallCol SMALLINT UNSIGNED, mediumCol MEDIUMINT UNSIGNED, intCol INT UNSIGNED, bigCol BIGINT UNSIGNED)"); + ExecuteSQL("INSERT INTO test VALUES(255, 65535, 16777215, 4294967295, 18446744073709551615)"); + + RowResult r = ExecuteSelectStatement(GetSession().GetSchema("test").GetTable("test").Select()); + var rows = r.FetchAll(); + Assert.AreEqual(5, r.Columns.Count); + Assert.AreEqual(typeof(byte), r.Columns[0].ClrType); + Assert.AreEqual(ColumnType.Tinyint, r.Columns[0].Type); + Assert.AreEqual((byte)255, rows[0][0]); + Assert.AreEqual(typeof(UInt16), r.Columns[1].ClrType); + Assert.AreEqual(ColumnType.Smallint, r.Columns[1].Type); + Assert.AreEqual((ushort)65535, rows[0][1]); + Assert.AreEqual(typeof(UInt32), r.Columns[2].ClrType); + Assert.AreEqual(ColumnType.Mediumint, r.Columns[2].Type); + Assert.AreEqual((uint)16777215, rows[0][2]); + Assert.AreEqual(typeof(UInt32), r.Columns[3].ClrType); + Assert.AreEqual(ColumnType.Int, r.Columns[3].Type); + Assert.AreEqual((uint)4294967295, rows[0][3]); + Assert.AreEqual(typeof(UInt64), r.Columns[4].ClrType); + Assert.AreEqual(ColumnType.Bigint, r.Columns[4].Type); + Assert.AreEqual((ulong)18446744073709551615, rows[0][4]); + } + + [Test] + public void Bit() + { + ExecuteSQL("CREATE TABLE test(bitCol BIT(8))"); + ExecuteSQL("INSERT INTO test VALUES(b'1111111')"); + + RowResult r = ExecuteSelectStatement(GetSession().GetSchema("test").GetTable("test").Select()); + var rows = r.FetchAll(); + Assert.That(r.Columns, Has.One.Items); + Assert.AreEqual(typeof(UInt64), r.Columns[0].ClrType); + Assert.AreEqual(ColumnType.Bit, r.Columns[0].Type); + Assert.AreEqual((ulong)127, rows[0][0]); + } + + [Test] + public void Decimal() + { + ExecuteSQL("CREATE TABLE test(decCol1 DECIMAL(20,9))"); + ExecuteSQL("INSERT INTO test VALUES(-1.23), (-12.345), (5), (43)"); + ExecuteSQL("INSERT INTO test VALUES(14523.2887238), (-8947.8923784)"); + + RowResult r = ExecuteSelectStatement(GetSession().GetSchema("test").GetTable("test").Select()); + var rows = r.FetchAll(); + Assert.That(r.Columns, Has.One.Items); + Assert.AreEqual(typeof(decimal), r.Columns[0].ClrType); + Assert.AreEqual(ColumnType.Decimal, r.Columns[0].Type); + Assert.AreEqual(-1.23m, rows[0][0]); + Assert.AreEqual(-12.345m, rows[1][0]); + Assert.AreEqual(5m, rows[2][0]); + Assert.AreEqual(43m, rows[3][0]); + Assert.AreEqual(14523.2887238m, rows[4][0]); + Assert.AreEqual(-8947.8923784m, rows[5][0]); + } + + [Test] + public void Json() + { + ExecuteSQL("CREATE TABLE test(jdoc JSON)"); + ExecuteSQL("INSERT INTO test VALUES('{ \"id\": 1, \"name\": \"John\" }')"); + ExecuteSQL("INSERT INTO test VALUES('[ \"a\", 1, \"b\", 2 ]')"); + + RowResult r = ExecuteSelectStatement(GetSession().GetSchema("test").GetTable("test").Select()); + var rows = r.FetchAll(); + Assert.That(r.Columns, Has.One.Items); + Assert.AreEqual(typeof(string), r.Columns[0].ClrType); + Assert.AreEqual(ColumnType.Json, r.Columns[0].Type); + Assert.AreEqual("{\"id\": 1, \"name\": \"John\"}", rows[0][0]); + Assert.AreEqual("[\"a\", 1, \"b\", 2]", rows[1][0]); + } + + [Test] + public void Strings() + { + ExecuteSQL("CREATE TABLE test(name VARCHAR(255) COLLATE cp932_japanese_ci)"); + ExecuteSQL("INSERT INTO test VALUES('表')"); + + RowResult r = ExecuteSelectStatement(GetSession().GetSchema("test").GetTable("test").Select()); + var rows = r.FetchAll(); + Assert.That(r.Columns, Has.One.Items); + Assert.AreEqual(typeof(string), r.Columns[0].ClrType); + Assert.AreEqual(ColumnType.String, r.Columns[0].Type); + Assert.AreEqual("表", rows[0][0]); + } + + [Test] + [Ignore("Fix for 8.0.13")] + public void UnsingedZeroFill() + { + ExecuteSQL("CREATE TABLE test(id INT ZEROFILL)"); + ExecuteSQL("INSERT INTO test VALUES(100)"); + + RowResult r = ExecuteSelectStatement(GetSession().GetSchema("test").GetTable("test").Select()); + var rows = r.FetchAll(); + Assert.That(r.Columns, Has.One.Items); + Assert.AreEqual(typeof(UInt32), r.Columns[0].ClrType); + Assert.AreEqual(ColumnType.Int, r.Columns[0].Type); + Assert.False(r.Columns[0].IsNumberSigned); + Assert.True(r.Columns[0].IsPadded); + Assert.AreEqual("0000000100", rows[0][0].ToString()); + } + + [Test] + public void Bytes() + { + ExecuteSQL("CREATE TABLE test(name VARCHAR(255) BINARY)"); + ExecuteSQL("INSERT INTO test VALUES('John')"); + + RowResult r = ExecuteSelectStatement(GetSession().GetSchema("test").GetTable("test").Select()); + var rows = r.FetchAll(); + Assert.That(r.Columns, Has.One.Items); + Assert.AreEqual(typeof(string), r.Columns[0].ClrType); + Assert.AreEqual(ColumnType.String, r.Columns[0].Type); + Assert.AreEqual("John", rows[0][0]); + } + + [Test] + public void BytesUsingCollation() + { + ExecuteSQL("CREATE TABLE test(name VARCHAR(255) COLLATE utf8_bin)"); + ExecuteSQL("INSERT INTO test VALUES('Mark')"); + + RowResult r = ExecuteSelectStatement(GetSession().GetSchema("test").GetTable("test").Select()); + var rows = r.FetchAll(); + Assert.That(r.Columns, Has.One.Items); + Assert.AreEqual(typeof(string), r.Columns[0].ClrType); + Assert.AreEqual(ColumnType.String, r.Columns[0].Type); + Assert.AreEqual("Mark", rows[0][0]); + } + + [Test] + public void Geometry() + { + ExecuteSQL("CREATE TABLE test(line GEOMETRY)"); + ExecuteSQL("INSERT INTO test VALUES(ST_GeomFromText('LINESTRING(0 0, 10 10, 20 25, 50 60)'))"); + + RowResult r = ExecuteSelectStatement(GetSession().GetSchema("test").GetTable("test").Select()); + var rows = r.FetchAll(); + Assert.That(r.Columns, Has.One.Items); + Assert.AreEqual(typeof(byte[]), r.Columns[0].ClrType); + Assert.AreEqual(ColumnType.Geometry, r.Columns[0].Type); + Assert.AreEqual("0000000001020000000400000000000000000000000000000000000000000000000000244000000000000024400000000000003440000000000000394000000000000049400000000000004E40", + BitConverter.ToString((byte[])rows[0][0]).Replace("-", "")); + } + + [Test] + public void BlobTypes() + { + ExecuteSQL("CREATE TABLE test(a BLOB, b TEXT)"); + ExecuteSQL("INSERT INTO test VALUES('Car', 'Plane')"); + + RowResult r = ExecuteSelectStatement(GetSession().GetSchema(schemaName).GetTable("test").Select()); + var rows = r.FetchAll(); + Assert.AreEqual(2, r.Columns.Count); + Assert.AreEqual(typeof(byte[]), r.Columns[0].ClrType); + Assert.AreEqual(typeof(string), r.Columns[1].ClrType); + Assert.AreEqual(ColumnType.Bytes, r.Columns[0].Type); + Assert.AreEqual(ColumnType.String, r.Columns[1].Type); + Assert.AreEqual(CharSetMap.GetEncoding(r.Columns[0].CharacterSetName).GetBytes("Car"), rows[0][0]); + Assert.AreEqual("Plane", rows[0][1]); + } + } +} diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/DateTimeTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/DateTimeTests.cs index 0c36e116b..1894b9040 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/DateTimeTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/DateTimeTests.cs @@ -1,126 +1,126 @@ -// Copyright (c) 2015, 2021, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySql.Data.MySqlClient.X.XDevAPI.Common; -using MySqlX.XDevAPI.Relational; -using NUnit.Framework; -using System; - -namespace MySqlX.Data.Tests.RelationalTests -{ - public class DateTimeTests : BaseTest - { - [TearDown] - public void TearDown() => ExecuteSQL("DROP TABLE IF EXISTS test"); - [Test] - public void DateTime() - { - ExecuteSQL("CREATE TABLE test.test(DT DATETIME)"); - ExecuteSQL("INSERT INTO test.test VALUES('2001-02-03 04:05:06')"); - - RowResult r = ExecuteSelectStatement(GetSession().GetSchema("test").GetTable("test").Select("dt")); - var rows = r.FetchAll(); - Assert.That(r.Columns, Has.One.Items); - Assert.AreEqual(typeof(DateTime), r.Columns[0].ClrType); - Assert.AreEqual(ColumnType.DateTime, r.Columns[0].Type); - Assert.That(rows, Has.One.Items); - DateTime dt = (DateTime)rows[0]["dt"]; - DateTime test = new DateTime(2001, 2, 3, 4, 5, 6); - Assert.AreEqual(test, dt); - } - - [Test] - public void Date() - { - ExecuteSQL("CREATE TABLE test.test(DT DATE)"); - ExecuteSQL("INSERT INTO test.test VALUES('2001-02-03')"); - - RowResult r = ExecuteSelectStatement(GetSession().GetSchema("test").GetTable("test").Select("dt")); - var rows = r.FetchAll(); - Assert.That(r.Columns, Has.One.Items); - Assert.AreEqual(typeof(DateTime), r.Columns[0].ClrType); - Assert.AreEqual(ColumnType.Date, r.Columns[0].Type); - Assert.That(rows, Has.One.Items); - DateTime dt = (DateTime)rows[0]["dt"]; - DateTime test = new DateTime(2001, 2, 3); - Assert.AreEqual(test, dt); - } - - [Test] - public void Timestamp() - { - ExecuteSQL("CREATE TABLE test.test(DT TIMESTAMP)"); - ExecuteSQL("INSERT INTO test.test VALUES('2001-02-03')"); - - RowResult r = ExecuteSelectStatement(GetSession().GetSchema("test").GetTable("test").Select("dt")); - var rows = r.FetchAll(); - Assert.That(r.Columns, Has.One.Items); - Assert.AreEqual(typeof(DateTime), r.Columns[0].ClrType); - //TODO: this should support timestamp - Assert.AreEqual(ColumnType.Timestamp, r.Columns[0].Type); - Assert.That(rows, Has.One.Items); - DateTime dt = (DateTime)rows[0]["dt"]; - DateTime test = new DateTime(2001, 2, 3); - Assert.AreEqual(test, dt); - } - - [Test] - public void Time() - { - ExecuteSQL("CREATE TABLE test.test(DT TIME)"); - ExecuteSQL("INSERT INTO test.test VALUES('01:02:03')"); - - RowResult r = ExecuteSelectStatement(GetSession().GetSchema("test").GetTable("test").Select("dt")); - var rows = r.FetchAll(); - Assert.That(r.Columns, Has.One.Items); - Assert.AreEqual(typeof(TimeSpan), r.Columns[0].ClrType); - Assert.AreEqual(ColumnType.Time, r.Columns[0].Type); - Assert.That(rows, Has.One.Items); - TimeSpan t = (TimeSpan)rows[0]["dt"]; - TimeSpan test = new TimeSpan(1, 2, 3); - Assert.AreEqual(test, t); - } - - [Test] - public void NegativeTime() - { - ExecuteSQL("CREATE TABLE test.test(DT TIME)"); - ExecuteSQL("INSERT INTO test.test VALUES('-01:02:03')"); - - RowResult r = ExecuteSelectStatement(GetSession().GetSchema("test").GetTable("test").Select("dt")); - var rows = r.FetchAll(); - Assert.That(r.Columns, Has.One.Items); - Assert.AreEqual(typeof(TimeSpan), r.Columns[0].ClrType); - Assert.AreEqual(ColumnType.Time, r.Columns[0].Type); - Assert.That(rows, Has.One.Items); - TimeSpan t = (TimeSpan)rows[0]["dt"]; - TimeSpan test = new TimeSpan(-1, 2, 3); - Assert.AreEqual(test, t); - } - } -} +// Copyright © 2015, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySql.Data.MySqlClient.X.XDevAPI.Common; +using MySqlX.XDevAPI.Relational; +using NUnit.Framework; +using System; + +namespace MySqlX.Data.Tests.RelationalTests +{ + public class DateTimeTests : BaseTest + { + [TearDown] + public void TearDown() => ExecuteSQL("DROP TABLE IF EXISTS test"); + [Test] + public void DateTime() + { + ExecuteSQL("CREATE TABLE test.test(DT DATETIME)"); + ExecuteSQL("INSERT INTO test.test VALUES('2001-02-03 04:05:06')"); + + RowResult r = ExecuteSelectStatement(GetSession().GetSchema("test").GetTable("test").Select("dt")); + var rows = r.FetchAll(); + Assert.That(r.Columns, Has.One.Items); + Assert.AreEqual(typeof(DateTime), r.Columns[0].ClrType); + Assert.AreEqual(ColumnType.DateTime, r.Columns[0].Type); + Assert.That(rows, Has.One.Items); + DateTime dt = (DateTime)rows[0]["dt"]; + DateTime test = new DateTime(2001, 2, 3, 4, 5, 6); + Assert.AreEqual(test, dt); + } + + [Test] + public void Date() + { + ExecuteSQL("CREATE TABLE test.test(DT DATE)"); + ExecuteSQL("INSERT INTO test.test VALUES('2001-02-03')"); + + RowResult r = ExecuteSelectStatement(GetSession().GetSchema("test").GetTable("test").Select("dt")); + var rows = r.FetchAll(); + Assert.That(r.Columns, Has.One.Items); + Assert.AreEqual(typeof(DateTime), r.Columns[0].ClrType); + Assert.AreEqual(ColumnType.Date, r.Columns[0].Type); + Assert.That(rows, Has.One.Items); + DateTime dt = (DateTime)rows[0]["dt"]; + DateTime test = new DateTime(2001, 2, 3); + Assert.AreEqual(test, dt); + } + + [Test] + public void Timestamp() + { + ExecuteSQL("CREATE TABLE test.test(DT TIMESTAMP)"); + ExecuteSQL("INSERT INTO test.test VALUES('2001-02-03')"); + + RowResult r = ExecuteSelectStatement(GetSession().GetSchema("test").GetTable("test").Select("dt")); + var rows = r.FetchAll(); + Assert.That(r.Columns, Has.One.Items); + Assert.AreEqual(typeof(DateTime), r.Columns[0].ClrType); + //TODO: this should support timestamp + Assert.AreEqual(ColumnType.Timestamp, r.Columns[0].Type); + Assert.That(rows, Has.One.Items); + DateTime dt = (DateTime)rows[0]["dt"]; + DateTime test = new DateTime(2001, 2, 3); + Assert.AreEqual(test, dt); + } + + [Test] + public void Time() + { + ExecuteSQL("CREATE TABLE test.test(DT TIME)"); + ExecuteSQL("INSERT INTO test.test VALUES('01:02:03')"); + + RowResult r = ExecuteSelectStatement(GetSession().GetSchema("test").GetTable("test").Select("dt")); + var rows = r.FetchAll(); + Assert.That(r.Columns, Has.One.Items); + Assert.AreEqual(typeof(TimeSpan), r.Columns[0].ClrType); + Assert.AreEqual(ColumnType.Time, r.Columns[0].Type); + Assert.That(rows, Has.One.Items); + TimeSpan t = (TimeSpan)rows[0]["dt"]; + TimeSpan test = new TimeSpan(1, 2, 3); + Assert.AreEqual(test, t); + } + + [Test] + public void NegativeTime() + { + ExecuteSQL("CREATE TABLE test.test(DT TIME)"); + ExecuteSQL("INSERT INTO test.test VALUES('-01:02:03')"); + + RowResult r = ExecuteSelectStatement(GetSession().GetSchema("test").GetTable("test").Select("dt")); + var rows = r.FetchAll(); + Assert.That(r.Columns, Has.One.Items); + Assert.AreEqual(typeof(TimeSpan), r.Columns[0].ClrType); + Assert.AreEqual(ColumnType.Time, r.Columns[0].Type); + Assert.That(rows, Has.One.Items); + TimeSpan t = (TimeSpan)rows[0]["dt"]; + TimeSpan test = new TimeSpan(-1, 2, 3); + Assert.AreEqual(test, t); + } + } +} diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/RelationalGCTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/RelationalGCTests.cs index bb6735a3a..40dac96ae 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/RelationalGCTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/RelationalGCTests.cs @@ -1,57 +1,57 @@ -// Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySqlX.XDevAPI.Relational; -using System; -using NUnit.Framework; - -namespace MySqlX.Data.Tests.ResultTests -{ - public class RelationalGCTests : BaseTest - { -#if NETFRAMEWORK - [Test] - public void FetchAllNoReference() - { - ExecuteSQL("CREATE TABLE test(name VARCHAR(40), age INT)"); - Table table = testSchema.GetTable("test"); - - ExecuteInsertStatement(table.Insert("name", "age").Values("Henry", "22").Values("Patric", 30)); - var result = ExecuteSelectStatement(table.Select()); - var rows = result.FetchAll(); - WeakReference wr = new WeakReference(result); - result = null; - GC.Collect(); - Assert.False(wr.IsAlive); - Assert.AreEqual(2, rows.Count); - Assert.AreEqual(22, rows[0]["age"]); - Assert.AreEqual("Patric", rows[1]["name"]); - } -#endif - } -} +// Copyright © 2015, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySqlX.XDevAPI.Relational; +using System; +using NUnit.Framework; + +namespace MySqlX.Data.Tests.ResultTests +{ + public class RelationalGCTests : BaseTest + { +#if NETFRAMEWORK + [Test] + public void FetchAllNoReference() + { + ExecuteSQL("CREATE TABLE test(name VARCHAR(40), age INT)"); + Table table = testSchema.GetTable("test"); + + ExecuteInsertStatement(table.Insert("name", "age").Values("Henry", "22").Values("Patric", 30)); + var result = ExecuteSelectStatement(table.Select()); + var rows = result.FetchAll(); + WeakReference wr = new WeakReference(result); + result = null; + GC.Collect(); + Assert.False(wr.IsAlive); + Assert.AreEqual(2, rows.Count); + Assert.AreEqual(22, rows[0]["age"]); + Assert.AreEqual("Patric", rows[1]["name"]); + } +#endif + } +} diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/RowBufferingTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/RowBufferingTests.cs index 22b2bf019..0f4e02f1e 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/RowBufferingTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/RowBufferingTests.cs @@ -1,56 +1,56 @@ -// Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySqlX.XDevAPI.Relational; -using NUnit.Framework; - -namespace MySqlX.Data.Tests.RelationalTests -{ - public class RowBufferingTests : BaseTest - { - [Test] - public void SmartBuffering() - { - ExecuteSQL("CREATE TABLE test1(id INT)"); - ExecuteSQL("INSERT INTO test1 VALUES (1),(2),(3),(4)"); - ExecuteSQL("CREATE TABLE test2(id INT, val INT)"); - ExecuteSQL("INSERT INTO test2 VALUES (1,0)"); - - var rowResult = ExecuteSelectStatement(testSchema.GetTable("test1").Select("id")); - Assert.AreEqual(0, rowResult.IndexOf("id")); - foreach (var row in rowResult) - { - var result = ExecuteUpdateStatement(testSchema.GetTable("test2").Update().Where("id=1").Set("val", row["id"])); - Assert.AreEqual(1, result.AffectedItemsCount); - } - - Row valRow = ExecuteSelectStatement(testSchema.GetTable("test2").Select("val")).FetchOne(); - Assert.AreEqual(4, valRow[0]); - } - } -} +// Copyright © 2015, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySqlX.XDevAPI.Relational; +using NUnit.Framework; + +namespace MySqlX.Data.Tests.RelationalTests +{ + public class RowBufferingTests : BaseTest + { + [Test] + public void SmartBuffering() + { + ExecuteSQL("CREATE TABLE test1(id INT)"); + ExecuteSQL("INSERT INTO test1 VALUES (1),(2),(3),(4)"); + ExecuteSQL("CREATE TABLE test2(id INT, val INT)"); + ExecuteSQL("INSERT INTO test2 VALUES (1,0)"); + + var rowResult = ExecuteSelectStatement(testSchema.GetTable("test1").Select("id")); + Assert.AreEqual(0, rowResult.IndexOf("id")); + foreach (var row in rowResult) + { + var result = ExecuteUpdateStatement(testSchema.GetTable("test2").Update().Where("id=1").Set("val", row["id"])); + Assert.AreEqual(1, result.AffectedItemsCount); + } + + Row valRow = ExecuteSelectStatement(testSchema.GetTable("test2").Select("val")).FetchOne(); + Assert.AreEqual(4, valRow[0]); + } + } +} diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/SqlTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/SqlTests.cs index f63954835..c6bdb2cbd 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/SqlTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/SqlTests.cs @@ -1,1065 +1,1065 @@ -// Copyright (c) 2015, 2021, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using Google.Protobuf; -using MySql.Data.Common; -using MySql.Data.MySqlClient; -using MySqlX.XDevAPI; -using MySqlX.XDevAPI.Relational; -using NUnit.Framework; -using System.Collections.Generic; - -namespace MySqlX.Data.Tests.RelationalTests -{ - public class SqlTests : BaseTest - { - [TearDown] - public void TearDown() - { - ExecuteSQL("DROP TABLE IF EXISTS test"); - } - - [Test] - public void ReturnSimpleScalar() - { - ExecuteSQL("DROP TABLE IF EXISTS test.test"); - ExecuteSQL("CREATE TABLE test.test(id INT)"); - ExecuteSQL("INSERT INTO test.test VALUES (1)"); - using (var ss = MySQLX.GetSession(ConnectionString)) - { - SqlResult r = ss.SQL("SELECT * FROM test.test").Execute(); - Assert.True(r.Next()); - Assert.AreEqual(1, r[0]); - Assert.False(r.NextResult()); - } - - } - - [Test] - public void ExecuteStoredProcedure() - { - ExecuteSQL("CREATE PROCEDURE `my_proc` () BEGIN SELECT 5; END"); - - Session session = GetSession(true); - var result = ExecuteSQLStatement(session.SQL("CALL my_proc()")); - Assert.True(result.HasData); - var row = result.FetchOne(); - Assert.NotNull(row); - Assert.AreEqual((sbyte)5, row[0]); - Assert.False(result.Next()); - Assert.Null(result.FetchOne()); - Assert.False(result.NextResult()); - } - - [Test] - public void ExecuteStoredProcedureMultipleResults() - { - ExecuteSQL("drop procedure if exists my_proc"); - ExecuteSQL("CREATE PROCEDURE `my_proc` () BEGIN SELECT 5; SELECT 'A'; SELECT 5 * 2; END"); - - Session session = GetSession(true); - var result = ExecuteSQLStatement(session.SQL("CALL my_proc()")); - Assert.True(result.HasData); - var row = result.FetchOne(); - Assert.NotNull(row); - Assert.AreEqual((sbyte)5, row[0]); - Assert.False(result.Next()); - Assert.Null(result.FetchOne()); - - Assert.True(result.NextResult()); - row = result.FetchOne(); - Assert.NotNull(row); - Assert.AreEqual("A", row[0]); - Assert.False(result.Next()); - Assert.Null(result.FetchOne()); - - Assert.True(result.NextResult()); - row = result.FetchOne(); - Assert.NotNull(row); - Assert.AreEqual((sbyte)10, row[0]); - Assert.False(result.Next()); - Assert.Null(result.FetchOne()); - - Assert.False(result.NextResult()); - } - - [Test] - public void Bind() - { - ExecuteSQL("drop table if exists test.test"); - ExecuteSQL("CREATE TABLE test.test(id INT, letter varchar(1))"); - for (int i = 1; i <= 10; i++) - ExecuteSQLStatement(GetSession(true).SQL("INSERT INTO test.test VALUES (?, ?), (?, ?)") - .Bind(i, ((char)('@' + i)).ToString()) - .Bind(++i, ((char)('@' + i)).ToString())); - - SqlResult result = ExecuteSQLStatement(GetSession(true).SQL("select * from test.test where id=?").Bind(5)); - Assert.True(result.Next()); - Assert.That(result.Rows, Has.One.Items); - Assert.AreEqual(5, result[0]); - Assert.AreEqual("E", result[1]); - } - - [Test] - public void BindNull() - { - ExecuteSQL("drop table if exists test.test"); - ExecuteSQL("CREATE TABLE test.test(id INT, letter varchar(1))"); - - var session = GetSession(true); - var result = ExecuteSQLStatement(session.SQL("INSERT INTO test.test VALUES(1, ?), (2, 'B');").Bind(null)); - Assert.AreEqual(2ul, result.AffectedItemsCount); - - var sqlResult = ExecuteSQLStatement(session.SQL("SELECT * FROM test.test WHERE letter is ?").Bind(null)).FetchAll(); - Assert.That(sqlResult, Has.One.Items); - Assert.AreEqual(1, sqlResult[0][0]); - Assert.Null(sqlResult[0][1]); - } - - [Test] - public void Alias() - { - var session = GetSession(true); - var stmt = ExecuteSQLStatement(session.SQL("SELECT 1 AS UNO")); - var result = stmt.FetchAll(); - Assert.AreEqual("UNO", stmt.Columns[0].ColumnLabel); - } - - #region WL14389 - - [Test, Description("call after failed procedure")] - public void ProcedureWithNoTable() - { - ExecuteSQL("create procedure newproc (in p1 int,in p2 char(20)) begin select 1; select 'XXX' from notab; end;"); - - var session = MySQLX.GetSession(ConnectionString + ";database=test;"); - - - var sqlRes = session.SQL("call newproc(?, ?)").Bind(10).Bind("X").Execute(); - var ex = Assert.Throws(() => session.SQL("drop procedure if exists newproc ").Execute()); - StringAssert.AreEqualIgnoringCase("Table 'test.notab' doesn't exist", ex.Message); - } - - [Test, Description("Stored Procedure Table Positive using Session")] - public void TablePositiveSession() - { - MySqlXConnectionStringBuilder sb = new MySqlXConnectionStringBuilder(ConnectionString); - var connectionStringObject = new { connection = "server=" + sb.Server + ";user=" + sb.UserID + ";port=" + sb.Port + ";password=" + sb.Password + ";sslmode=" + MySqlSslMode.Required + ";" }; - using (Session sessionPlain = MySQLX.GetSession(connectionStringObject.connection)) - { - sessionPlain.SQL("DROP DATABASE IF EXISTS DBName").Execute(); - sessionPlain.SQL("CREATE DATABASE DBName").Execute(); - sessionPlain.SQL("USE DBName").Execute(); - sessionPlain.SQL("CREATE TABLE address" + - "(address_number INT NOT NULL AUTO_INCREMENT, " + - "building_name VARCHAR(100) NOT NULL, " + - "district VARCHAR(100) NOT NULL, PRIMARY KEY (address_number)" + ");").Execute(); - sessionPlain.SQL("INSERT INTO address" + - "(address_number,building_name,district)" + - " VALUES " + - "(1573,'MySQL','BGL');").Execute(); - string procI = "CREATE PROCEDURE my_add_one_procedure " + - " (IN address_id INT) " + - "BEGIN " + - "select * from address as a where a.address_number = address_id;" + - "END;"; - sessionPlain.SQL(procI).Execute(); - var res = sessionPlain.SQL("CALL my_add_one_procedure(1573);").Execute(); - if (res.HasData) - { - var row = res.FetchOne(); - if (row != null) - { - do - { - if (row[0] != null) - Assert.IsNotNull(row[0].ToString()); - - if (row[1] != null) - Assert.IsNotNull(row[1].ToString()); - - if (row[2] != null) - Assert.IsNotNull(row[2].ToString()); - - } while (res.Next()); while (res.NextResult()) ; - } - } - sessionPlain.SQL("DROP DATABASE DBName").Execute(); - } - } - - [Test, Description("Stored Procedure Table-StringBuilder and Session")] - public void StoredProcTablePositiveStringBuilderSession() - { - if (!Platform.IsWindows()) Assert.Ignore("This test is for Windows OS only"); - - MySqlXConnectionStringBuilder sb = new MySqlXConnectionStringBuilder(ConnectionString); - var connectionStringObject = new { connection = "server=" + sb.Server + ";user=" + sb.UserID + ";port=" + sb.Port + ";password=" + sb.Password }; - - using (MySqlConnection mysql = new MySqlConnection(ConnectionStringRoot)) - { - mysql.Open(); - System.Text.StringBuilder sql = new System.Text.StringBuilder(); - sql.AppendLine("DROP DATABASE IF EXISTS DBName"); - MySqlScript script = new MySqlScript(mysql, sql.ToString()); - script.Execute(); - sql = new System.Text.StringBuilder(); - sql.AppendLine("CREATE DATABASE DBName"); - script = new MySqlScript(mysql, sql.ToString()); - script.Execute(); - sql = new System.Text.StringBuilder(); - sql.AppendLine("USE DBName"); - script = new MySqlScript(mysql, sql.ToString()); - script.Execute(); - sql = new System.Text.StringBuilder(); - sql.AppendLine("CREATE TABLE address" + - "(address_number INT NOT NULL AUTO_INCREMENT, " + - "building_name VARCHAR(100) NOT NULL, " + - "district VARCHAR(100) NOT NULL, PRIMARY KEY (address_number)" + ");" - ); - script = new MySqlScript(mysql, sql.ToString()); - script.Execute(); - sql = new System.Text.StringBuilder(); - sql.AppendLine("INSERT INTO address" + - "(address_number,building_name,district)" + - " VALUES " + - "(1573,'MySQL','BGL');"); - script = new MySqlScript(mysql, sql.ToString()); - script.Execute(); - sql = new System.Text.StringBuilder(); - sql.AppendLine("INSERT INTO address" + - "(address_number,building_name,district)" + - " VALUES " + - "(1,'MySQLTest1','BGLTest1');"); - script = new MySqlScript(mysql, sql.ToString()); - script.Execute(); - sql = new System.Text.StringBuilder(); - sql.AppendLine("INSERT INTO address" + - "(address_number,building_name,district)" + - " VALUES " + - "(2,'MySQLTest2','BGLTest2');"); - script = new MySqlScript(mysql, sql.ToString()); - script.Execute(); - sql = new System.Text.StringBuilder(); - sql.AppendLine("DELIMITER //"); - sql.AppendLine("CREATE PROCEDURE my_add_one_procedure " + - " (IN address_id INT) " + - "BEGIN " + - "select * from address as a where a.address_number = address_id;" + - "END//"); - script = new MySqlScript(mysql, sql.ToString()); - script.Execute(); - sql = new System.Text.StringBuilder(); - sql.AppendLine("DELIMITER ;"); - script = new MySqlScript(mysql, sql.ToString()); - script.Execute(); - } - - using (Session sessionPlain = MySQLX.GetSession(connectionStringObject.connection)) - { - sessionPlain.SQL("USE DBName").Execute(); - var res = sessionPlain.SQL("CALL my_add_one_procedure(1573);").Execute(); - if (res.HasData) - { - var row = res.FetchOne(); - if (row != null) - { - do - { - if (row[0] != null) - Assert.IsNotNull(row[0].ToString()); - - if (row[1] != null) - Assert.IsNotNull(row[1].ToString()); - - if (row[2] != null) - Assert.IsNotNull(row[2].ToString()); - - } while (res.Next()); while (res.NextResult()) ; - } - } - sessionPlain.SQL("DROP PROCEDURE my_add_one_procedure;").Execute(); - sessionPlain.SQL("DROP TABLE address;").Execute(); - sessionPlain.SQL("DROP DATABASE DBName;").Execute(); - } - } - - [Test, Description("Stored Procedure Table-Negative(procedure returns null)")] - public void StoredProcReturnsNull() - { - if (!Platform.IsWindows()) Assert.Ignore("This test is for Windows OS only"); - - MySqlConnection mysql = new MySqlConnection(ConnectionStringRoot); - mysql.Open(); - System.Text.StringBuilder sql = new System.Text.StringBuilder(); - sql.AppendLine("DROP DATABASE IF EXISTS DBName"); - MySqlScript script = new MySqlScript(mysql, sql.ToString()); - script.Execute(); - sql = new System.Text.StringBuilder(); - sql.AppendLine("CREATE DATABASE DBName"); - script = new MySqlScript(mysql, sql.ToString()); - script.Execute(); - sql = new System.Text.StringBuilder(); - sql.AppendLine("USE DBName"); - script = new MySqlScript(mysql, sql.ToString()); - script.Execute(); - sql = new System.Text.StringBuilder(); - sql.AppendLine("CREATE TABLE address" + - "(address_number INT NOT NULL AUTO_INCREMENT, " + - "building_name VARCHAR(100) NOT NULL, " + - "district VARCHAR(100) NOT NULL, PRIMARY KEY (address_number)" + ");" - ); - script = new MySqlScript(mysql, sql.ToString()); - script.Execute(); - sql = new System.Text.StringBuilder(); - sql.AppendLine("INSERT INTO address" + - "(address_number,building_name,district)" + - " VALUES " + - "(1573,'MySQL','BGL');"); - script = new MySqlScript(mysql, sql.ToString()); - script.Execute(); - sql = new System.Text.StringBuilder(); - sql.AppendLine("INSERT INTO address" + - "(address_number,building_name,district)" + - " VALUES " + - "(1,'MySQLTest1','BGLTest1');"); - script = new MySqlScript(mysql, sql.ToString()); - script.Execute(); - sql = new System.Text.StringBuilder(); - sql.AppendLine("INSERT INTO address" + - "(address_number,building_name,district)" + - " VALUES " + - "(2,'MySQLTest2','BGLTest2');"); - script = new MySqlScript(mysql, sql.ToString()); - script.Execute(); - sql = new System.Text.StringBuilder(); - sql.AppendLine("DELIMITER //"); - sql.AppendLine("CREATE PROCEDURE my_add_one_procedure " + - " (IN address_id INT) " + - "BEGIN " + - "select * from address as a where a.address_number = address_id;" + - "END//"); - script = new MySqlScript(mysql, sql.ToString()); - script.Execute(); - sql = new System.Text.StringBuilder(); - sql.AppendLine("DELIMITER ;"); - script = new MySqlScript(mysql, sql.ToString()); - script.Execute(); - - MySqlXConnectionStringBuilder sb = new MySqlXConnectionStringBuilder(ConnectionString); - var connectionStringObject = new { connection = "server=" + sb.Server + ";user=" + sb.UserID + ";port=" + sb.Port + ";password=" + sb.Password + ";sslmode=" + MySqlSslMode.Required + ";" }; - using (Session sessionPlain = MySQLX.GetSession(connectionStringObject.connection)) - { - sessionPlain.SQL("USE DBName").Execute(); - - var res = sessionPlain.SQL("CALL my_add_one_procedure(1000);").Execute(); - if (res.HasData) - { - var row = res.FetchOne(); - Assert.IsNull(row); - } - res.Next(); - res.NextResult(); - } - } - - //SQLTests - [Test, Description("Bind Support for Session SQL Numeric Datatypes- integer,JSON,tinyint,smallint,mediumint,bigint,float,double,decimal")] - public void BindSupportSessionSQLNumericDatatypes() - { - if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher"); - var connectionString = ConnectionString + ";sslmode=" + MySqlSslMode.Required; - SqlResult myResult; - Row row; - - //integer - using (Session sessionTest = MySQLX.GetSession(connectionString)) - { - sessionTest.SQL("DROP DATABASE IF EXISTS DBName ").Execute(); - sessionTest.SQL("CREATE DATABASE IF NOT EXISTS DBName").Execute(); - sessionTest.SQL("USE DBName").Execute(); - sessionTest.SQL("CREATE PROCEDURE my_add_one_procedure " + - " (INOUT incr_param INT) " + - "BEGIN " + - " SET incr_param = incr_param + 1;" + - "END;").Execute(); - //Uncomment once Bind is implemented in 7.0.2 - sessionTest.SQL("SET @my_var = ?;").Bind(10).Execute(); - sessionTest.SQL("CALL my_add_one_procedure(@my_var);").Execute(); - sessionTest.SQL("DROP PROCEDURE my_add_one_procedure;").Execute(); - // Use a SQL query to get the result - myResult = sessionTest.SQL("SELECT @my_var").Execute(); - // Gets the row and prints the first column - row = myResult.FetchOne(); - Assert.IsNotNull(row[0].ToString()); - sessionTest.SQL("DROP DATABASE DBName").Execute(); - } - - //JSON - using (var sessionTest = MySQLX.GetSession(connectionString)) - { - sessionTest.SQL("CREATE DATABASE IF NOT EXISTS DBName").Execute(); - sessionTest.SQL("USE DBName").Execute(); - sessionTest.SQL("CREATE PROCEDURE my_add_one_procedure " + - " (INOUT incr_param Json) " + - "BEGIN " + - " SET incr_param = incr_param;" + - "END;").Execute(); - //Uncomment once Bind is implemented in 7.0.2 - var jsonParams = "{ \"pages1\" : 30, \"pages2\" : 40 }"; - sessionTest.SQL("SET @my_var = ?;").Bind(jsonParams).Execute(); - sessionTest.SQL("CALL my_add_one_procedure(@my_var);").Execute(); - sessionTest.SQL("DROP PROCEDURE my_add_one_procedure;").Execute(); - // Use a SQL query to get the result - myResult = sessionTest.SQL("SELECT @my_var").Execute(); - // Gets the row and prints the first column - row = myResult.FetchOne(); - Assert.IsNotNull(row[0].ToString()); - sessionTest.SQL("DROP DATABASE DBName").Execute(); - } - - //TINYINT - using (var sessionTest = MySQLX.GetSession(connectionString)) - { - sessionTest.SQL("CREATE DATABASE IF NOT EXISTS DBName").Execute(); - sessionTest.SQL("USE DBName").Execute(); - sessionTest.SQL("CREATE PROCEDURE my_add_one_procedure " + - " (INOUT incr_param TINYINT) " + - "BEGIN " + - " SET incr_param = incr_param + 1;" + - "END;").Execute(); - //Uncomment once Bind is implemented in 7.0.2 - sessionTest.SQL("SET @my_var = ?;").Bind(1).Execute(); - sessionTest.SQL("CALL my_add_one_procedure(@my_var);").Execute(); - sessionTest.SQL("DROP PROCEDURE my_add_one_procedure;").Execute(); - // Use a SQL query to get the result - myResult = sessionTest.SQL("SELECT @my_var").Execute(); - // Gets the row and prints the first column - row = myResult.FetchOne(); - Assert.IsNotNull(row[0].ToString()); - sessionTest.SQL("DROP DATABASE DBName").Execute(); - } - - //SMALLINT - using (var sessionTest = MySQLX.GetSession(connectionString)) - { - sessionTest.SQL("CREATE DATABASE IF NOT EXISTS DBName").Execute(); - sessionTest.SQL("USE DBName").Execute(); - sessionTest.SQL("CREATE PROCEDURE my_add_one_procedure " + - " (INOUT incr_param SMALLINT) " + - "BEGIN " + - " SET incr_param = incr_param + 1;" + - "END;").Execute(); - //Uncomment once Bind is implemented in 7.0.2 - sessionTest.SQL("SET @my_var = ?;").Bind(11111).Execute(); - sessionTest.SQL("CALL my_add_one_procedure(@my_var);").Execute(); - sessionTest.SQL("DROP PROCEDURE my_add_one_procedure;").Execute(); - // Use a SQL query to get the result - myResult = sessionTest.SQL("SELECT @my_var").Execute(); - // Gets the row and prints the first column - row = myResult.FetchOne(); - Assert.IsNotNull(row[0].ToString()); - sessionTest.SQL("DROP DATABASE DBName").Execute(); - } - - //MEDIUMINT - using (var sessionTest = MySQLX.GetSession(connectionString)) - { - sessionTest.SQL("CREATE DATABASE IF NOT EXISTS DBName").Execute(); - sessionTest.SQL("USE DBName").Execute(); - sessionTest.SQL("CREATE PROCEDURE my_add_one_procedure " + - " (INOUT incr_param MEDIUMINT) " + - "BEGIN " + - " SET incr_param = incr_param + 1;" + - "END;").Execute(); - //Uncomment once Bind is implemented in 7.0.2 - sessionTest.SQL("SET @my_var = ?;").Bind(1111).Execute(); - sessionTest.SQL("CALL my_add_one_procedure(@my_var);").Execute(); - sessionTest.SQL("DROP PROCEDURE my_add_one_procedure;").Execute(); - // Use a SQL query to get the result - myResult = sessionTest.SQL("SELECT @my_var").Execute(); - // Gets the row and prints the first column - row = myResult.FetchOne(); - Assert.IsNotNull(row[0].ToString()); - sessionTest.SQL("DROP DATABASE DBName").Execute(); - } - - //FLOATMD - using (var sessionTest = MySQLX.GetSession(connectionString)) - { - sessionTest.SQL("CREATE DATABASE IF NOT EXISTS DBName").Execute(); - sessionTest.SQL("USE DBName").Execute(); - sessionTest.SQL("CREATE PROCEDURE my_add_one_procedure " + - " (INOUT incr_param FLOAT(10,2)) " + - "BEGIN " + - " SET incr_param = incr_param + 1;" + - "END;").Execute(); - //Uncomment once Bind is implemented in 7.0.2 - sessionTest.SQL("SET @my_var = ?;").Bind(100.2).Execute(); - sessionTest.SQL("CALL my_add_one_procedure(@my_var);").Execute(); - sessionTest.SQL("DROP PROCEDURE my_add_one_procedure;").Execute(); - // Use a SQL query to get the result - myResult = sessionTest.SQL("SELECT @my_var").Execute(); - // Gets the row and prints the first column - row = myResult.FetchOne(); - Assert.IsNotNull(row[0].ToString()); - sessionTest.SQL("DROP DATABASE DBName").Execute(); - } - - //DOUBLEMD - using (var sessionTest = MySQLX.GetSession(connectionString)) - { - sessionTest.SQL("CREATE DATABASE IF NOT EXISTS DBName").Execute(); - sessionTest.SQL("USE DBName").Execute(); - sessionTest.SQL("CREATE PROCEDURE my_add_one_procedure " + - " (INOUT incr_param DOUBLE(10,2)) " + - "BEGIN " + - " SET incr_param = incr_param + 1;" + - "END;").Execute(); - //Uncomment once Bind is implemented in 7.0.2 - sessionTest.SQL("SET @my_var = ?;").Bind(1000.2).Execute(); - sessionTest.SQL("CALL my_add_one_procedure(@my_var);").Execute(); - sessionTest.SQL("DROP PROCEDURE my_add_one_procedure;").Execute(); - // Use a SQL query to get the result - myResult = sessionTest.SQL("SELECT @my_var").Execute(); - // Gets the row and prints the first column - row = myResult.FetchOne(); - Assert.IsNotNull(row[0].ToString()); - sessionTest.SQL("DROP DATABASE DBName").Execute(); - } - - //DECIMALMD - using (var sessionTest = MySQLX.GetSession(connectionString)) - { - sessionTest.SQL("CREATE DATABASE IF NOT EXISTS DBName").Execute(); - sessionTest.SQL("USE DBName").Execute(); - sessionTest.SQL("CREATE PROCEDURE my_add_one_procedure " + - " (INOUT incr_param DECIMAL(10,2)) " + - "BEGIN " + - " SET incr_param = incr_param + 1;" + - "END;").Execute(); - //Uncomment once Bind is implemented in 7.0.2 - sessionTest.SQL("SET @my_var = ?;").Bind(10000.2).Execute(); - sessionTest.SQL("CALL my_add_one_procedure(@my_var);").Execute(); - sessionTest.SQL("DROP PROCEDURE my_add_one_procedure;").Execute(); - // Use a SQL query to get the result - myResult = sessionTest.SQL("SELECT @my_var").Execute(); - // Gets the row and prints the first column - row = myResult.FetchOne(); - Assert.IsNotNull(row[0].ToString()); - sessionTest.SQL("DROP DATABASE DBName").Execute(); - } - } - - - [Test, Description("Bind Support for Session SQL DateTime Types- date,datetime,timestamp,time,year(M)")] - public void BindSupportSessionSQLDateTimetypes() - { - if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher"); - //DATE - string connectionString = ConnectionString + ";sslmode=" + MySqlSslMode.Required; - SqlResult myResult; - Row row; - - using (Session sessionTest = MySQLX.GetSession(connectionString)) - { - sessionTest.SQL("DROP DATABASE IF EXISTS DBName ").Execute(); - sessionTest.SQL("CREATE DATABASE IF NOT EXISTS DBName").Execute(); - sessionTest.SQL("USE DBName").Execute(); - sessionTest.SQL("CREATE PROCEDURE my_add_one_procedure " + - " (INOUT incr_param DATE) " + - "BEGIN " + - " SET incr_param = incr_param ;" + - "END;").Execute(); - //Uncomment once Bind is implemented in 7.0.2 - sessionTest.SQL("SET @my_var = ?;").Bind("1973-12-30").Execute(); - sessionTest.SQL("CALL my_add_one_procedure(@my_var);").Execute(); - sessionTest.SQL("DROP PROCEDURE my_add_one_procedure;").Execute(); - // Use a SQL query to get the result - myResult = sessionTest.SQL("SELECT @my_var").Execute(); - // Gets the row and prints the first column - row = myResult.FetchOne(); - Assert.IsNotNull(row[0].ToString()); - sessionTest.SQL("DROP DATABASE DBName").Execute(); - } - - //DATETIME - using (Session sessionTest = MySQLX.GetSession(connectionString)) - { - sessionTest.SQL("CREATE DATABASE IF NOT EXISTS DBName").Execute(); - sessionTest.SQL("USE DBName").Execute(); - sessionTest.SQL("CREATE PROCEDURE my_add_one_procedure " + - " (INOUT incr_param DATETIME) " + - "BEGIN " + - " SET incr_param = incr_param ;" + - "END;").Execute(); - //Uncomment once Bind is implemented in 7.0.2 - sessionTest.SQL("SET @my_var = ?;").Bind("1981-04-10 15:30:00").Execute(); - sessionTest.SQL("CALL my_add_one_procedure(@my_var);").Execute(); - sessionTest.SQL("DROP PROCEDURE my_add_one_procedure;").Execute(); - // Use a SQL query to get the result - myResult = sessionTest.SQL("SELECT @my_var").Execute(); - // Gets the row and prints the first column - row = myResult.FetchOne(); - Assert.IsNotNull(row[0].ToString()); - sessionTest.SQL("DROP DATABASE DBName").Execute(); - } - - //TIMESTAMP - using (Session sessionTest = MySQLX.GetSession(connectionString)) - { - sessionTest.SQL("CREATE DATABASE IF NOT EXISTS DBName").Execute(); - sessionTest.SQL("USE DBName").Execute(); - sessionTest.SQL("CREATE PROCEDURE my_add_one_procedure " + - " (INOUT incr_param TIMESTAMP) " + - "BEGIN " + - " SET incr_param = incr_param ;" + - "END;").Execute(); - //Uncomment once Bind is implemented in 7.0.2 - sessionTest.SQL("SET @my_var = ?;").Bind("20160316153000").Execute(); - sessionTest.SQL("CALL my_add_one_procedure(@my_var);").Execute(); - sessionTest.SQL("DROP PROCEDURE my_add_one_procedure;").Execute(); - // Use a SQL query to get the result - myResult = sessionTest.SQL("SELECT @my_var").Execute(); - // Gets the row and prints the first column - row = myResult.FetchOne(); - Assert.IsNotNull(row[0].ToString()); - sessionTest.SQL("DROP DATABASE DBName").Execute(); - } - - //TIME - using (Session sessionTest = MySQLX.GetSession(connectionString)) - { - sessionTest.SQL("CREATE DATABASE IF NOT EXISTS DBName").Execute(); - sessionTest.SQL("USE DBName").Execute(); - sessionTest.SQL("CREATE PROCEDURE my_add_one_procedure " + - " (INOUT incr_param TIME) " + - "BEGIN " + - " SET incr_param = incr_param ;" + - "END;").Execute(); - //Uncomment once Bind is implemented in 7.0.2 - sessionTest.SQL("SET @my_var = ?;").Bind("12:00:00").Execute(); - sessionTest.SQL("CALL my_add_one_procedure(@my_var);").Execute(); - sessionTest.SQL("DROP PROCEDURE my_add_one_procedure;").Execute(); - // Use a SQL query to get the result - myResult = sessionTest.SQL("SELECT @my_var").Execute(); - // Gets the row and prints the first column - row = myResult.FetchOne(); - Assert.IsNotNull(row[0].ToString()); - sessionTest.SQL("DROP DATABASE DBName").Execute(); - } - - //YEAR - using (Session sessionTest = MySQLX.GetSession(connectionString)) - { - sessionTest.SQL("CREATE DATABASE IF NOT EXISTS DBName").Execute(); - sessionTest.SQL("USE DBName").Execute(); - sessionTest.SQL("CREATE PROCEDURE my_add_one_procedure " + - " (INOUT incr_param YEAR(4)) " + - "BEGIN " + - " SET incr_param = incr_param ;" + - "END;").Execute(); - //Uncomment once Bind is implemented in 7.0.2 - sessionTest.SQL("SET @my_var = ?;").Bind("2111").Execute(); - sessionTest.SQL("CALL my_add_one_procedure(@my_var);").Execute(); - sessionTest.SQL("DROP PROCEDURE my_add_one_procedure;").Execute(); - // Use a SQL query to get the result - myResult = sessionTest.SQL("SELECT @my_var").Execute(); - // Gets the row and prints the first column - row = myResult.FetchOne(); - Assert.IsNotNull(row[0].ToString()); - sessionTest.SQL("DROP DATABASE DBName").Execute(); - } - } - - - [Test, Description("Bind Support for Session SQL String Types- CHAR(M),VARCHAR(M),BLOB,TINYBLOB,MEDIUMBLOB,LONGBLOB,ENUM")] - public void BindSupportSessionSQLStringtypes() - { - if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher"); - //CHAR(20) - string connectionString = ConnectionString + ";sslmode=" + MySqlSslMode.Required; - SqlResult myResult; - Row row; - - using (Session sessionTest = MySQLX.GetSession(connectionString)) - { - sessionTest.SQL("DROP DATABASE IF EXISTS DBName ").Execute(); - sessionTest.SQL("CREATE DATABASE IF NOT EXISTS DBName").Execute(); - sessionTest.SQL("USE DBName").Execute(); - sessionTest.SQL("CREATE PROCEDURE my_add_one_procedure " + - " (INOUT incr_param CHAR(20)) " + - "BEGIN " + - " SET incr_param = incr_param;" + - "END;").Execute(); - //Uncomment once Bind is implemented in 7.0.2 - sessionTest.SQL("SET @my_var = ?;").Bind("ABCDEFGHIJABCDEFGHIJ").Execute(); - sessionTest.SQL("CALL my_add_one_procedure(@my_var);").Execute(); - sessionTest.SQL("DROP PROCEDURE my_add_one_procedure;").Execute(); - // Use a SQL query to get the result - myResult = sessionTest.SQL("SELECT @my_var").Execute(); - // Gets the row and prints the first column - row = myResult.FetchOne(); - Assert.IsNotNull(row[0].ToString()); - sessionTest.SQL("DROP DATABASE DBName").Execute(); - } - - //VARCHAR(20) - using (Session sessionTest = MySQLX.GetSession(connectionString)) - { - sessionTest.SQL("CREATE DATABASE IF NOT EXISTS DBName").Execute(); - sessionTest.SQL("USE DBName").Execute(); - sessionTest.SQL("CREATE PROCEDURE my_add_one_procedure " + - " (INOUT incr_param VARCHAR(20)) " + - "BEGIN " + - " SET incr_param = incr_param;" + - "END;").Execute(); - //Uncomment once Bind is implemented in 7.0.2 - sessionTest.SQL("SET @my_var = ?;").Bind("ABCDEFGHIJABCDEFGHIJ").Execute(); - sessionTest.SQL("CALL my_add_one_procedure(@my_var);").Execute(); - sessionTest.SQL("DROP PROCEDURE my_add_one_procedure;").Execute(); - // Use a SQL query to get the result - myResult = sessionTest.SQL("SELECT @my_var").Execute(); - // Gets the row and prints the first column - row = myResult.FetchOne(); - Assert.IsNotNull(row[0].ToString()); - sessionTest.SQL("DROP DATABASE DBName").Execute(); - } - - //BLOB - using (Session sessionTest = MySQLX.GetSession(connectionString)) - { - sessionTest.SQL("CREATE DATABASE IF NOT EXISTS DBName").Execute(); - sessionTest.SQL("USE DBName").Execute(); - sessionTest.SQL("CREATE PROCEDURE my_add_one_procedure " + - " (INOUT incr_param BLOB) " + - "BEGIN " + - " SET incr_param = incr_param ;" + - "END;").Execute(); - //Uncomment once Bind is implemented in 7.0.2 - sessionTest.SQL("SET @my_var = ?;").Bind(19731230153000).Execute(); - sessionTest.SQL("CALL my_add_one_procedure(@my_var);").Execute(); - sessionTest.SQL("DROP PROCEDURE my_add_one_procedure;").Execute(); - // Use a SQL query to get the result - myResult = sessionTest.SQL("SELECT @my_var").Execute(); - // Gets the row and prints the first column - row = myResult.FetchOne(); - Assert.IsNotNull(row[0].ToString()); - sessionTest.SQL("DROP DATABASE DBName").Execute(); - } - - //TINYBLOB - using (Session sessionTest = MySQLX.GetSession(connectionString)) - { - sessionTest.SQL("CREATE DATABASE IF NOT EXISTS DBName").Execute(); - sessionTest.SQL("USE DBName").Execute(); - sessionTest.SQL("CREATE PROCEDURE my_add_one_procedure " + - " (INOUT incr_param TINYBLOB) " + - "BEGIN " + - " SET incr_param = incr_param ;" + - "END;").Execute(); - //Uncomment once Bind is implemented in 7.0.2 - sessionTest.SQL("SET @my_var = ?;").Bind("12:00:00").Execute(); - sessionTest.SQL("CALL my_add_one_procedure(@my_var);").Execute(); - sessionTest.SQL("DROP PROCEDURE my_add_one_procedure;").Execute(); - // Use a SQL query to get the result - myResult = sessionTest.SQL("SELECT @my_var").Execute(); - // Gets the row and prints the first column - row = myResult.FetchOne(); - Assert.IsNotNull(row[0].ToString()); - sessionTest.SQL("DROP DATABASE DBName").Execute(); - } - - //MEDIUMBLOB - using (Session sessionTest = MySQLX.GetSession(connectionString)) - { - sessionTest.SQL("CREATE DATABASE IF NOT EXISTS DBName").Execute(); - sessionTest.SQL("USE DBName").Execute(); - sessionTest.SQL("CREATE PROCEDURE my_add_one_procedure " + - " (INOUT incr_param MEDIUMBLOB) " + - "BEGIN " + - " SET incr_param = incr_param ;" + - "END;").Execute(); - //Uncomment once Bind is implemented in 7.0.2 - sessionTest.SQL("SET @my_var = ?;").Bind(2111).Execute(); - sessionTest.SQL("CALL my_add_one_procedure(@my_var);").Execute(); - sessionTest.SQL("DROP PROCEDURE my_add_one_procedure;").Execute(); - // Use a SQL query to get the result - myResult = sessionTest.SQL("SELECT @my_var").Execute(); - // Gets the row and prints the first column - row = myResult.FetchOne(); - Assert.IsNotNull(row[0].ToString()); - sessionTest.SQL("DROP DATABASE DBName").Execute(); - } - - //LONGBLOB - using (Session sessionTest = MySQLX.GetSession(connectionString)) - { - sessionTest.SQL("CREATE DATABASE IF NOT EXISTS DBName").Execute(); - sessionTest.SQL("USE DBName").Execute(); - sessionTest.SQL("CREATE PROCEDURE my_add_one_procedure " + - " (INOUT incr_param LONGBLOB) " + - "BEGIN " + - " SET incr_param = incr_param ;" + - "END;").Execute(); - //Uncomment once Bind is implemented in 7.0.2 - sessionTest.SQL("SET @my_var = ?;").Bind(111232).Execute(); - sessionTest.SQL("CALL my_add_one_procedure(@my_var);").Execute(); - sessionTest.SQL("DROP PROCEDURE my_add_one_procedure;").Execute(); - // Use a SQL query to get the result - myResult = sessionTest.SQL("SELECT @my_var").Execute(); - // Gets the row and prints the first column - row = myResult.FetchOne(); - Assert.IsNotNull(row[0].ToString()); - sessionTest.SQL("DROP DATABASE DBName").Execute(); - } - - //ENUM - using (Session sessionTest = MySQLX.GetSession(connectionString)) - { - sessionTest.SQL("CREATE DATABASE IF NOT EXISTS DBName").Execute(); - sessionTest.SQL("USE DBName").Execute(); - sessionTest.SQL("CREATE PROCEDURE my_add_one_procedure " + - " (INOUT incr_param ENUM('x-small', 'small', 'medium', 'large', 'x-large')) " + - "BEGIN " + - " SET incr_param = incr_param ;" + - "END;").Execute(); - //Uncomment once Bind is implemented in 7.0.2 - sessionTest.SQL("SET @my_var = ?;").Bind("large").Execute(); - sessionTest.SQL("CALL my_add_one_procedure(@my_var);").Execute(); - sessionTest.SQL("DROP PROCEDURE my_add_one_procedure;").Execute(); - // Use a SQL query to get the result - myResult = sessionTest.SQL("SELECT @my_var").Execute(); - // Gets the row and prints the first column - row = myResult.FetchOne(); - Assert.IsNotNull(row[0].ToString()); - sessionTest.SQL("DROP DATABASE DBName").Execute(); - } - } - - [Test, Description("Bind Support for Session SQL Negative Tests-Null")] - public void BindSupportSessionSQLNegativeTest1() - { - if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher"); - SqlResult myResult = null; - - //integer - string connectionString = ConnectionString + ";sslmode=" + MySqlSslMode.Required; - Session sessionTest = MySQLX.GetSession(connectionString); - sessionTest.SQL("DROP DATABASE IF EXISTS DBName ").Execute(); - sessionTest.SQL("CREATE DATABASE IF NOT EXISTS DBName").Execute(); - sessionTest.SQL("USE DBName").Execute(); - sessionTest.SQL("CREATE PROCEDURE my_add_one_procedure " + - " (INOUT incr_param INT) " + - "BEGIN " + - " SET incr_param = incr_param+1;" + - "END;").Execute(); - - sessionTest.SQL("SET @my_var = ?;").Bind(null).Execute(); - sessionTest.SQL("CALL my_add_one_procedure(@my_var);").Execute(); - sessionTest.SQL("DROP PROCEDURE my_add_one_procedure;").Execute(); - // Use a SQL query to get the result - myResult = sessionTest.SQL("SELECT @my_var").Execute(); - - Assert.Throws(() => myResult.FetchOne()); - sessionTest.SQL("DROP DATABASE DBName").Execute(); - sessionTest.Close(); - sessionTest.Dispose(); - } - - [Test, Description("Bind Support for Session SQL Negative Tests-Bind Chaining Tests")] - public void BindSupportSessionSQLNegativeTest2() - { - if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher"); - - //integer - string connectionString = ConnectionString + ";sslmode=" + MySqlSslMode.Required; - Session sessionTest = MySQLX.GetSession(connectionString); - sessionTest.SQL("DROP DATABASE IF EXISTS DBName ").Execute(); - sessionTest.SQL("CREATE DATABASE IF NOT EXISTS DBName").Execute(); - sessionTest.SQL("USE DBName").Execute(); - sessionTest.SQL("CREATE PROCEDURE my_add_one_procedure " + - " (INOUT incr_param INT) " + - "BEGIN " + - " SET incr_param = incr_param + 1;" + - "END;").Execute(); - sessionTest.SQL("CREATE TABLE DBName.test(id INT, letter varchar(1))").Execute(); - - for (int i = 1; i <= 100; i++) - - session.SQL("INSERT INTO DBName.test VALUES (?, ?), (?, ?)") - .Bind(1, "a") - .Bind(2, "b") - .Execute(); - - SqlResult result = session.SQL("select * from DBName.test where id=?").Bind(5).Execute(); - - //Uncomment once Bind is implemented in 7.0.2 - Assert.Throws(() => session.SQL("SET @my_var = ?;").Bind(1).Bind(2).Execute()); - sessionTest.SQL("DROP DATABASE DBName").Execute(); - sessionTest.Close(); - sessionTest.Dispose(); - - } - - // Aditional Tests - [Test, Description("Test MySQLX plugin MySQL mixed scenario")] - public void MixedChainedCommands() - { - if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher"); - ExecuteSQL("Drop table if exists test"); - ExecuteSQL("CREATE TABLE test(c1 float(14,8),c2 double GENERATED ALWAYS AS (c1*101/102) Stored COMMENT 'First Gen Col')"); - ExecuteSQL("INSERT INTO test(c1) VALUES (22.7)"); - ExecuteSQL("INSERT INTO test(c1) VALUES (-100000.38984)"); - ExecuteSQL("INSERT INTO test(c1) VALUES (0)"); - - RowResult r = session.GetSchema("test").GetTable("test").Select("c1").Execute(); - var rows = r.FetchAll(); - Assert.AreEqual(1, r.Columns.Count, "Matching"); - Assert.AreEqual(typeof(float).ToString(), r.Columns[0].ClrType.ToString(), "Matching"); - Assert.AreEqual(MySqlDbType.Float.ToString(), r.Columns[0].Type.ToString(), "Matching"); - Assert.AreEqual(14, (int)r.Columns[0].Length, "Matching"); - Assert.AreEqual(8, (int)r.Columns[0].FractionalDigits, "Matching"); - Assert.AreEqual(3, rows.Count, "Matching"); - Assert.AreEqual(22.7f, (float)rows[0][0], "Matching"); - Assert.AreEqual(-100000.38984f, (float)rows[1][0], "Matching"); - Assert.AreEqual(0f, (float)rows[2][0], "Matching"); - } - - [Test, Description("Test MySQLX plugin MySQL Date Time Bug")] - public void DateTimeCheck() - { - if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher"); - ExecuteSQL("CREATE TABLE test.test1212(dt DATETIME(6))"); - ExecuteSQL("INSERT INTO test.test1212 VALUES('2015-10-21 18:01:00.12345678')"); - - RowResult r = session.GetSchema("test").GetTable("test1212").Select("dt").Execute(); - var rows = r.FetchAll(); - Assert.AreEqual(1, r.Columns.Count, "Matching Coulumn Count"); - - } - - [Test, Description("Test MySQLX plugin MySQL Datetime JSON")] - public void DateTimeJSON() - { - if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher"); - ExecuteSQL("DROP TABLE IF EXISTS test.test"); - ExecuteSQL("CREATE TABLE test.test(Id int NOT NULL PRIMARY KEY, jsoncolumn JSON)"); - ExecuteSQL(@"INSERT INTO test.test VALUES(100000,' { ""name"" : ""bob"",""Date"": ""2015-10-09"",""Time"": ""12:18:29.000000"",""DateTimeOfRegistration"": ""2015-10-09 12:18:29.000000"",""age"":12} ')"); - RowResult r = session.GetSchema("test").GetTable("test").Select("jsoncolumn").Execute(); - var rows = r.FetchAll(); - Assert.AreEqual(1, r.Columns.Count, "Matching"); - } - - [Test, Description("Test MySQLX plugin JSON Variant")] - public void JSONVariant() - { - if (!Platform.IsWindows()) Assert.Ignore("This test is for Windows OS only"); - if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher"); - ExecuteSQL("DROP TABLE IF EXISTS Test"); - ExecuteSQL("CREATE TABLE test (Id int NOT NULL PRIMARY KEY, jsoncolumn JSON)"); - ExecuteSQL("INSERT INTO test VALUES (1, '[1]')"); - ExecuteSQL(@"INSERT INTO test VALUES (2, '[""a"", {""b"": [true, false]}, [10, 20]]')"); - ExecuteSQL(@"INSERT INTO test VALUES (3, '{""id"":1,""name"":""test""}')"); - var r = ExecuteSQL(@"SELECT JSON_EXTRACT('{""id"": 1, ""name"": ""test""}','$.name')").FetchOne(); - Assert.AreEqual("\"test\"", r[0]); - } - - [Test, Description("Test MySQLX plugin big int as PK")] - public void BigIntasPK() - { - if (!Platform.IsWindows()) Assert.Ignore("This test is for Windows OS only"); - if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher"); - - ExecuteSQL("DROP TABLE IF EXISTS Test"); - ExecuteSQL("CREATE TABLE test (Id bigint NOT NULL PRIMARY KEY, jsoncolumn JSON)"); - var res = ExecuteSQL("INSERT INTO test VALUES (934157136952, '[1]')"); - Assert.AreEqual(1, res.AffectedItemsCount); - res = ExecuteSQL(@"INSERT INTO test VALUES (9223372036854775807, '[""a"", {""b"": [true, false]}, [10, 20]]')"); - Assert.AreEqual(1, res.AffectedItemsCount); - Assert.Throws(() => ExecuteSQL("INSERT INTO test VALUES ('str1', '[1]')")); - } - - [Test, Description("Test MySQLX plugin tiny int as PK")] - public void TinyIntasPK() - { - if (!Platform.IsWindows()) Assert.Ignore("This test is for Windows OS only"); - if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher"); - - using (var ss = MySQLX.GetSession(ConnectionString)) - { - ss.SQL("DROP TABLE IF EXISTS test.test").Execute(); - ss.SQL("CREATE TABLE test.test (Id tinyint NOT NULL PRIMARY KEY, jsoncolumn JSON)").Execute(); - var res = ss.SQL("INSERT INTO test.test VALUES (1, '[1]')").Execute(); - Assert.AreEqual(1, res.AffectedItemsCount); - res = ss.SQL(@"INSERT INTO test.test VALUES (2, '[""a"", {""b"": [true, false]}, [10, 20]]')").Execute(); - Assert.AreEqual(1, res.AffectedItemsCount); - Assert.Throws(() => ss.SQL("INSERT INTO test.test VALUES ('str1', '[1]')").Execute()); - } - } - - [Test, Description("Test MySQLX plugin small int as PK")] - public void SmallIntasPK() - { - if (!Platform.IsWindows()) Assert.Ignore("This test is for Windows OS only"); - if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher"); - - using (var ss = MySQLX.GetSession(ConnectionString)) - { - ss.SQL("DROP TABLE IF EXISTS test.test").Execute(); - ss.SQL("CREATE TABLE test.test (Id smallint NOT NULL PRIMARY KEY, jsoncolumn JSON)").Execute(); - var res = ss.SQL("INSERT INTO test.test VALUES (99, '[1]')").Execute(); - Assert.AreEqual(1, res.AffectedItemsCount); - res = ss.SQL(@"INSERT INTO test.test VALUES (1, '[""a"", {""b"": [true, false]}, [10, 20]]')").Execute(); - Assert.AreEqual(1, res.AffectedItemsCount); - Assert.Throws(() => ss.SQL("INSERT INTO test.test VALUES ('str1', '[1]')").Execute()); - ss.SQL("DROP TABLE IF EXISTS test.test"); - } - } - - [Test, Description("MySQL sample data insertion and viewing")] - public void DataValidation() - { - ExecuteSQL("DROP TABLE IF EXISTS TEST"); - ExecuteSQL("CREATE TABLE TEST(name VARCHAR(20),id INT NOT NULL,sports VARCHAR(20))"); - ExecuteSQL("INSERT INTO TEST(name,id,sports) VALUES ('Federer',1,'Tennis')"); - ExecuteSQL("INSERT INTO TEST(name,id,sports) VALUES ('Ronaldo',2,'Soccer')"); - ExecuteSQL("INSERT INTO TEST(name,id,sports) VALUES ('Messi',3,'Soccer')"); - var expecteddataValue = new List { "Federer", "Ronaldo", "Messi" }; - using (SqlResult result = ExecuteSQLStatement(session.SQL("SELECT name FROM TEST;"))) - { - while (result.Next()) - { - Assert.That(result.Rows, Has.Exactly(3).Items); - Assert.True(expecteddataValue.Contains(result[0].ToString())); - } - } - } - #endregion - } -} +// Copyright © 2015, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using Google.Protobuf; +using MySql.Data.Common; +using MySql.Data.MySqlClient; +using MySqlX.XDevAPI; +using MySqlX.XDevAPI.Relational; +using NUnit.Framework; +using System.Collections.Generic; + +namespace MySqlX.Data.Tests.RelationalTests +{ + public class SqlTests : BaseTest + { + [TearDown] + public void TearDown() + { + ExecuteSQL("DROP TABLE IF EXISTS test"); + } + + [Test] + public void ReturnSimpleScalar() + { + ExecuteSQL("DROP TABLE IF EXISTS test.test"); + ExecuteSQL("CREATE TABLE test.test(id INT)"); + ExecuteSQL("INSERT INTO test.test VALUES (1)"); + using (var ss = MySQLX.GetSession(ConnectionString)) + { + SqlResult r = ss.SQL("SELECT * FROM test.test").Execute(); + Assert.True(r.Next()); + Assert.AreEqual(1, r[0]); + Assert.False(r.NextResult()); + } + + } + + [Test] + public void ExecuteStoredProcedure() + { + ExecuteSQL("CREATE PROCEDURE `my_proc` () BEGIN SELECT 5; END"); + + Session session = GetSession(true); + var result = ExecuteSQLStatement(session.SQL("CALL my_proc()")); + Assert.True(result.HasData); + var row = result.FetchOne(); + Assert.NotNull(row); + Assert.AreEqual((sbyte)5, row[0]); + Assert.False(result.Next()); + Assert.Null(result.FetchOne()); + Assert.False(result.NextResult()); + } + + [Test] + public void ExecuteStoredProcedureMultipleResults() + { + ExecuteSQL("drop procedure if exists my_proc"); + ExecuteSQL("CREATE PROCEDURE `my_proc` () BEGIN SELECT 5; SELECT 'A'; SELECT 5 * 2; END"); + + Session session = GetSession(true); + var result = ExecuteSQLStatement(session.SQL("CALL my_proc()")); + Assert.True(result.HasData); + var row = result.FetchOne(); + Assert.NotNull(row); + Assert.AreEqual((sbyte)5, row[0]); + Assert.False(result.Next()); + Assert.Null(result.FetchOne()); + + Assert.True(result.NextResult()); + row = result.FetchOne(); + Assert.NotNull(row); + Assert.AreEqual("A", row[0]); + Assert.False(result.Next()); + Assert.Null(result.FetchOne()); + + Assert.True(result.NextResult()); + row = result.FetchOne(); + Assert.NotNull(row); + Assert.AreEqual((sbyte)10, row[0]); + Assert.False(result.Next()); + Assert.Null(result.FetchOne()); + + Assert.False(result.NextResult()); + } + + [Test] + public void Bind() + { + ExecuteSQL("drop table if exists test.test"); + ExecuteSQL("CREATE TABLE test.test(id INT, letter varchar(1))"); + for (int i = 1; i <= 10; i++) + ExecuteSQLStatement(GetSession(true).SQL("INSERT INTO test.test VALUES (?, ?), (?, ?)") + .Bind(i, ((char)('@' + i)).ToString()) + .Bind(++i, ((char)('@' + i)).ToString())); + + SqlResult result = ExecuteSQLStatement(GetSession(true).SQL("select * from test.test where id=?").Bind(5)); + Assert.True(result.Next()); + Assert.That(result.Rows, Has.One.Items); + Assert.AreEqual(5, result[0]); + Assert.AreEqual("E", result[1]); + } + + [Test] + public void BindNull() + { + ExecuteSQL("drop table if exists test.test"); + ExecuteSQL("CREATE TABLE test.test(id INT, letter varchar(1))"); + + var session = GetSession(true); + var result = ExecuteSQLStatement(session.SQL("INSERT INTO test.test VALUES(1, ?), (2, 'B');").Bind(null)); + Assert.AreEqual(2ul, result.AffectedItemsCount); + + var sqlResult = ExecuteSQLStatement(session.SQL("SELECT * FROM test.test WHERE letter is ?").Bind(null)).FetchAll(); + Assert.That(sqlResult, Has.One.Items); + Assert.AreEqual(1, sqlResult[0][0]); + Assert.Null(sqlResult[0][1]); + } + + [Test] + public void Alias() + { + var session = GetSession(true); + var stmt = ExecuteSQLStatement(session.SQL("SELECT 1 AS UNO")); + var result = stmt.FetchAll(); + Assert.AreEqual("UNO", stmt.Columns[0].ColumnLabel); + } + + #region WL14389 + + [Test, Description("call after failed procedure")] + public void ProcedureWithNoTable() + { + ExecuteSQL("create procedure newproc (in p1 int,in p2 char(20)) begin select 1; select 'XXX' from notab; end;"); + + var session = MySQLX.GetSession(ConnectionString + ";database=test;"); + + + var sqlRes = session.SQL("call newproc(?, ?)").Bind(10).Bind("X").Execute(); + var ex = Assert.Throws(() => session.SQL("drop procedure if exists newproc ").Execute()); + StringAssert.AreEqualIgnoringCase("Table 'test.notab' doesn't exist", ex.Message); + } + + [Test, Description("Stored Procedure Table Positive using Session")] + public void TablePositiveSession() + { + MySqlXConnectionStringBuilder sb = new MySqlXConnectionStringBuilder(ConnectionString); + var connectionStringObject = new { connection = "server=" + sb.Server + ";user=" + sb.UserID + ";port=" + sb.Port + ";password=" + sb.Password + ";sslmode=" + MySqlSslMode.Required + ";" }; + using (Session sessionPlain = MySQLX.GetSession(connectionStringObject.connection)) + { + sessionPlain.SQL("DROP DATABASE IF EXISTS DBName").Execute(); + sessionPlain.SQL("CREATE DATABASE DBName").Execute(); + sessionPlain.SQL("USE DBName").Execute(); + sessionPlain.SQL("CREATE TABLE address" + + "(address_number INT NOT NULL AUTO_INCREMENT, " + + "building_name VARCHAR(100) NOT NULL, " + + "district VARCHAR(100) NOT NULL, PRIMARY KEY (address_number)" + ");").Execute(); + sessionPlain.SQL("INSERT INTO address" + + "(address_number,building_name,district)" + + " VALUES " + + "(1573,'MySQL','BGL');").Execute(); + string procI = "CREATE PROCEDURE my_add_one_procedure " + + " (IN address_id INT) " + + "BEGIN " + + "select * from address as a where a.address_number = address_id;" + + "END;"; + sessionPlain.SQL(procI).Execute(); + var res = sessionPlain.SQL("CALL my_add_one_procedure(1573);").Execute(); + if (res.HasData) + { + var row = res.FetchOne(); + if (row != null) + { + do + { + if (row[0] != null) + Assert.IsNotNull(row[0].ToString()); + + if (row[1] != null) + Assert.IsNotNull(row[1].ToString()); + + if (row[2] != null) + Assert.IsNotNull(row[2].ToString()); + + } while (res.Next()); while (res.NextResult()) ; + } + } + sessionPlain.SQL("DROP DATABASE DBName").Execute(); + } + } + + [Test, Description("Stored Procedure Table-StringBuilder and Session")] + public void StoredProcTablePositiveStringBuilderSession() + { + if (!Platform.IsWindows()) Assert.Ignore("This test is for Windows OS only"); + + MySqlXConnectionStringBuilder sb = new MySqlXConnectionStringBuilder(ConnectionString); + var connectionStringObject = new { connection = "server=" + sb.Server + ";user=" + sb.UserID + ";port=" + sb.Port + ";password=" + sb.Password }; + + using (MySqlConnection mysql = new MySqlConnection(ConnectionStringRoot)) + { + mysql.Open(); + System.Text.StringBuilder sql = new System.Text.StringBuilder(); + sql.AppendLine("DROP DATABASE IF EXISTS DBName"); + MySqlScript script = new MySqlScript(mysql, sql.ToString()); + script.Execute(); + sql = new System.Text.StringBuilder(); + sql.AppendLine("CREATE DATABASE DBName"); + script = new MySqlScript(mysql, sql.ToString()); + script.Execute(); + sql = new System.Text.StringBuilder(); + sql.AppendLine("USE DBName"); + script = new MySqlScript(mysql, sql.ToString()); + script.Execute(); + sql = new System.Text.StringBuilder(); + sql.AppendLine("CREATE TABLE address" + + "(address_number INT NOT NULL AUTO_INCREMENT, " + + "building_name VARCHAR(100) NOT NULL, " + + "district VARCHAR(100) NOT NULL, PRIMARY KEY (address_number)" + ");" + ); + script = new MySqlScript(mysql, sql.ToString()); + script.Execute(); + sql = new System.Text.StringBuilder(); + sql.AppendLine("INSERT INTO address" + + "(address_number,building_name,district)" + + " VALUES " + + "(1573,'MySQL','BGL');"); + script = new MySqlScript(mysql, sql.ToString()); + script.Execute(); + sql = new System.Text.StringBuilder(); + sql.AppendLine("INSERT INTO address" + + "(address_number,building_name,district)" + + " VALUES " + + "(1,'MySQLTest1','BGLTest1');"); + script = new MySqlScript(mysql, sql.ToString()); + script.Execute(); + sql = new System.Text.StringBuilder(); + sql.AppendLine("INSERT INTO address" + + "(address_number,building_name,district)" + + " VALUES " + + "(2,'MySQLTest2','BGLTest2');"); + script = new MySqlScript(mysql, sql.ToString()); + script.Execute(); + sql = new System.Text.StringBuilder(); + sql.AppendLine("DELIMITER //"); + sql.AppendLine("CREATE PROCEDURE my_add_one_procedure " + + " (IN address_id INT) " + + "BEGIN " + + "select * from address as a where a.address_number = address_id;" + + "END//"); + script = new MySqlScript(mysql, sql.ToString()); + script.Execute(); + sql = new System.Text.StringBuilder(); + sql.AppendLine("DELIMITER ;"); + script = new MySqlScript(mysql, sql.ToString()); + script.Execute(); + } + + using (Session sessionPlain = MySQLX.GetSession(connectionStringObject.connection)) + { + sessionPlain.SQL("USE DBName").Execute(); + var res = sessionPlain.SQL("CALL my_add_one_procedure(1573);").Execute(); + if (res.HasData) + { + var row = res.FetchOne(); + if (row != null) + { + do + { + if (row[0] != null) + Assert.IsNotNull(row[0].ToString()); + + if (row[1] != null) + Assert.IsNotNull(row[1].ToString()); + + if (row[2] != null) + Assert.IsNotNull(row[2].ToString()); + + } while (res.Next()); while (res.NextResult()) ; + } + } + sessionPlain.SQL("DROP PROCEDURE my_add_one_procedure;").Execute(); + sessionPlain.SQL("DROP TABLE address;").Execute(); + sessionPlain.SQL("DROP DATABASE DBName;").Execute(); + } + } + + [Test, Description("Stored Procedure Table-Negative(procedure returns null)")] + public void StoredProcReturnsNull() + { + if (!Platform.IsWindows()) Assert.Ignore("This test is for Windows OS only"); + + MySqlConnection mysql = new MySqlConnection(ConnectionStringRoot); + mysql.Open(); + System.Text.StringBuilder sql = new System.Text.StringBuilder(); + sql.AppendLine("DROP DATABASE IF EXISTS DBName"); + MySqlScript script = new MySqlScript(mysql, sql.ToString()); + script.Execute(); + sql = new System.Text.StringBuilder(); + sql.AppendLine("CREATE DATABASE DBName"); + script = new MySqlScript(mysql, sql.ToString()); + script.Execute(); + sql = new System.Text.StringBuilder(); + sql.AppendLine("USE DBName"); + script = new MySqlScript(mysql, sql.ToString()); + script.Execute(); + sql = new System.Text.StringBuilder(); + sql.AppendLine("CREATE TABLE address" + + "(address_number INT NOT NULL AUTO_INCREMENT, " + + "building_name VARCHAR(100) NOT NULL, " + + "district VARCHAR(100) NOT NULL, PRIMARY KEY (address_number)" + ");" + ); + script = new MySqlScript(mysql, sql.ToString()); + script.Execute(); + sql = new System.Text.StringBuilder(); + sql.AppendLine("INSERT INTO address" + + "(address_number,building_name,district)" + + " VALUES " + + "(1573,'MySQL','BGL');"); + script = new MySqlScript(mysql, sql.ToString()); + script.Execute(); + sql = new System.Text.StringBuilder(); + sql.AppendLine("INSERT INTO address" + + "(address_number,building_name,district)" + + " VALUES " + + "(1,'MySQLTest1','BGLTest1');"); + script = new MySqlScript(mysql, sql.ToString()); + script.Execute(); + sql = new System.Text.StringBuilder(); + sql.AppendLine("INSERT INTO address" + + "(address_number,building_name,district)" + + " VALUES " + + "(2,'MySQLTest2','BGLTest2');"); + script = new MySqlScript(mysql, sql.ToString()); + script.Execute(); + sql = new System.Text.StringBuilder(); + sql.AppendLine("DELIMITER //"); + sql.AppendLine("CREATE PROCEDURE my_add_one_procedure " + + " (IN address_id INT) " + + "BEGIN " + + "select * from address as a where a.address_number = address_id;" + + "END//"); + script = new MySqlScript(mysql, sql.ToString()); + script.Execute(); + sql = new System.Text.StringBuilder(); + sql.AppendLine("DELIMITER ;"); + script = new MySqlScript(mysql, sql.ToString()); + script.Execute(); + + MySqlXConnectionStringBuilder sb = new MySqlXConnectionStringBuilder(ConnectionString); + var connectionStringObject = new { connection = "server=" + sb.Server + ";user=" + sb.UserID + ";port=" + sb.Port + ";password=" + sb.Password + ";sslmode=" + MySqlSslMode.Required + ";" }; + using (Session sessionPlain = MySQLX.GetSession(connectionStringObject.connection)) + { + sessionPlain.SQL("USE DBName").Execute(); + + var res = sessionPlain.SQL("CALL my_add_one_procedure(1000);").Execute(); + if (res.HasData) + { + var row = res.FetchOne(); + Assert.IsNull(row); + } + res.Next(); + res.NextResult(); + } + } + + //SQLTests + [Test, Description("Bind Support for Session SQL Numeric Datatypes- integer,JSON,tinyint,smallint,mediumint,bigint,float,double,decimal")] + public void BindSupportSessionSQLNumericDatatypes() + { + if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher"); + var connectionString = ConnectionString + ";sslmode=" + MySqlSslMode.Required; + SqlResult myResult; + Row row; + + //integer + using (Session sessionTest = MySQLX.GetSession(connectionString)) + { + sessionTest.SQL("DROP DATABASE IF EXISTS DBName ").Execute(); + sessionTest.SQL("CREATE DATABASE IF NOT EXISTS DBName").Execute(); + sessionTest.SQL("USE DBName").Execute(); + sessionTest.SQL("CREATE PROCEDURE my_add_one_procedure " + + " (INOUT incr_param INT) " + + "BEGIN " + + " SET incr_param = incr_param + 1;" + + "END;").Execute(); + //Uncomment once Bind is implemented in 7.0.2 + sessionTest.SQL("SET @my_var = ?;").Bind(10).Execute(); + sessionTest.SQL("CALL my_add_one_procedure(@my_var);").Execute(); + sessionTest.SQL("DROP PROCEDURE my_add_one_procedure;").Execute(); + // Use a SQL query to get the result + myResult = sessionTest.SQL("SELECT @my_var").Execute(); + // Gets the row and prints the first column + row = myResult.FetchOne(); + Assert.IsNotNull(row[0].ToString()); + sessionTest.SQL("DROP DATABASE DBName").Execute(); + } + + //JSON + using (var sessionTest = MySQLX.GetSession(connectionString)) + { + sessionTest.SQL("CREATE DATABASE IF NOT EXISTS DBName").Execute(); + sessionTest.SQL("USE DBName").Execute(); + sessionTest.SQL("CREATE PROCEDURE my_add_one_procedure " + + " (INOUT incr_param Json) " + + "BEGIN " + + " SET incr_param = incr_param;" + + "END;").Execute(); + //Uncomment once Bind is implemented in 7.0.2 + var jsonParams = "{ \"pages1\" : 30, \"pages2\" : 40 }"; + sessionTest.SQL("SET @my_var = ?;").Bind(jsonParams).Execute(); + sessionTest.SQL("CALL my_add_one_procedure(@my_var);").Execute(); + sessionTest.SQL("DROP PROCEDURE my_add_one_procedure;").Execute(); + // Use a SQL query to get the result + myResult = sessionTest.SQL("SELECT @my_var").Execute(); + // Gets the row and prints the first column + row = myResult.FetchOne(); + Assert.IsNotNull(row[0].ToString()); + sessionTest.SQL("DROP DATABASE DBName").Execute(); + } + + //TINYINT + using (var sessionTest = MySQLX.GetSession(connectionString)) + { + sessionTest.SQL("CREATE DATABASE IF NOT EXISTS DBName").Execute(); + sessionTest.SQL("USE DBName").Execute(); + sessionTest.SQL("CREATE PROCEDURE my_add_one_procedure " + + " (INOUT incr_param TINYINT) " + + "BEGIN " + + " SET incr_param = incr_param + 1;" + + "END;").Execute(); + //Uncomment once Bind is implemented in 7.0.2 + sessionTest.SQL("SET @my_var = ?;").Bind(1).Execute(); + sessionTest.SQL("CALL my_add_one_procedure(@my_var);").Execute(); + sessionTest.SQL("DROP PROCEDURE my_add_one_procedure;").Execute(); + // Use a SQL query to get the result + myResult = sessionTest.SQL("SELECT @my_var").Execute(); + // Gets the row and prints the first column + row = myResult.FetchOne(); + Assert.IsNotNull(row[0].ToString()); + sessionTest.SQL("DROP DATABASE DBName").Execute(); + } + + //SMALLINT + using (var sessionTest = MySQLX.GetSession(connectionString)) + { + sessionTest.SQL("CREATE DATABASE IF NOT EXISTS DBName").Execute(); + sessionTest.SQL("USE DBName").Execute(); + sessionTest.SQL("CREATE PROCEDURE my_add_one_procedure " + + " (INOUT incr_param SMALLINT) " + + "BEGIN " + + " SET incr_param = incr_param + 1;" + + "END;").Execute(); + //Uncomment once Bind is implemented in 7.0.2 + sessionTest.SQL("SET @my_var = ?;").Bind(11111).Execute(); + sessionTest.SQL("CALL my_add_one_procedure(@my_var);").Execute(); + sessionTest.SQL("DROP PROCEDURE my_add_one_procedure;").Execute(); + // Use a SQL query to get the result + myResult = sessionTest.SQL("SELECT @my_var").Execute(); + // Gets the row and prints the first column + row = myResult.FetchOne(); + Assert.IsNotNull(row[0].ToString()); + sessionTest.SQL("DROP DATABASE DBName").Execute(); + } + + //MEDIUMINT + using (var sessionTest = MySQLX.GetSession(connectionString)) + { + sessionTest.SQL("CREATE DATABASE IF NOT EXISTS DBName").Execute(); + sessionTest.SQL("USE DBName").Execute(); + sessionTest.SQL("CREATE PROCEDURE my_add_one_procedure " + + " (INOUT incr_param MEDIUMINT) " + + "BEGIN " + + " SET incr_param = incr_param + 1;" + + "END;").Execute(); + //Uncomment once Bind is implemented in 7.0.2 + sessionTest.SQL("SET @my_var = ?;").Bind(1111).Execute(); + sessionTest.SQL("CALL my_add_one_procedure(@my_var);").Execute(); + sessionTest.SQL("DROP PROCEDURE my_add_one_procedure;").Execute(); + // Use a SQL query to get the result + myResult = sessionTest.SQL("SELECT @my_var").Execute(); + // Gets the row and prints the first column + row = myResult.FetchOne(); + Assert.IsNotNull(row[0].ToString()); + sessionTest.SQL("DROP DATABASE DBName").Execute(); + } + + //FLOATMD + using (var sessionTest = MySQLX.GetSession(connectionString)) + { + sessionTest.SQL("CREATE DATABASE IF NOT EXISTS DBName").Execute(); + sessionTest.SQL("USE DBName").Execute(); + sessionTest.SQL("CREATE PROCEDURE my_add_one_procedure " + + " (INOUT incr_param FLOAT(10,2)) " + + "BEGIN " + + " SET incr_param = incr_param + 1;" + + "END;").Execute(); + //Uncomment once Bind is implemented in 7.0.2 + sessionTest.SQL("SET @my_var = ?;").Bind(100.2).Execute(); + sessionTest.SQL("CALL my_add_one_procedure(@my_var);").Execute(); + sessionTest.SQL("DROP PROCEDURE my_add_one_procedure;").Execute(); + // Use a SQL query to get the result + myResult = sessionTest.SQL("SELECT @my_var").Execute(); + // Gets the row and prints the first column + row = myResult.FetchOne(); + Assert.IsNotNull(row[0].ToString()); + sessionTest.SQL("DROP DATABASE DBName").Execute(); + } + + //DOUBLEMD + using (var sessionTest = MySQLX.GetSession(connectionString)) + { + sessionTest.SQL("CREATE DATABASE IF NOT EXISTS DBName").Execute(); + sessionTest.SQL("USE DBName").Execute(); + sessionTest.SQL("CREATE PROCEDURE my_add_one_procedure " + + " (INOUT incr_param DOUBLE(10,2)) " + + "BEGIN " + + " SET incr_param = incr_param + 1;" + + "END;").Execute(); + //Uncomment once Bind is implemented in 7.0.2 + sessionTest.SQL("SET @my_var = ?;").Bind(1000.2).Execute(); + sessionTest.SQL("CALL my_add_one_procedure(@my_var);").Execute(); + sessionTest.SQL("DROP PROCEDURE my_add_one_procedure;").Execute(); + // Use a SQL query to get the result + myResult = sessionTest.SQL("SELECT @my_var").Execute(); + // Gets the row and prints the first column + row = myResult.FetchOne(); + Assert.IsNotNull(row[0].ToString()); + sessionTest.SQL("DROP DATABASE DBName").Execute(); + } + + //DECIMALMD + using (var sessionTest = MySQLX.GetSession(connectionString)) + { + sessionTest.SQL("CREATE DATABASE IF NOT EXISTS DBName").Execute(); + sessionTest.SQL("USE DBName").Execute(); + sessionTest.SQL("CREATE PROCEDURE my_add_one_procedure " + + " (INOUT incr_param DECIMAL(10,2)) " + + "BEGIN " + + " SET incr_param = incr_param + 1;" + + "END;").Execute(); + //Uncomment once Bind is implemented in 7.0.2 + sessionTest.SQL("SET @my_var = ?;").Bind(10000.2).Execute(); + sessionTest.SQL("CALL my_add_one_procedure(@my_var);").Execute(); + sessionTest.SQL("DROP PROCEDURE my_add_one_procedure;").Execute(); + // Use a SQL query to get the result + myResult = sessionTest.SQL("SELECT @my_var").Execute(); + // Gets the row and prints the first column + row = myResult.FetchOne(); + Assert.IsNotNull(row[0].ToString()); + sessionTest.SQL("DROP DATABASE DBName").Execute(); + } + } + + + [Test, Description("Bind Support for Session SQL DateTime Types- date,datetime,timestamp,time,year(M)")] + public void BindSupportSessionSQLDateTimetypes() + { + if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher"); + //DATE + string connectionString = ConnectionString + ";sslmode=" + MySqlSslMode.Required; + SqlResult myResult; + Row row; + + using (Session sessionTest = MySQLX.GetSession(connectionString)) + { + sessionTest.SQL("DROP DATABASE IF EXISTS DBName ").Execute(); + sessionTest.SQL("CREATE DATABASE IF NOT EXISTS DBName").Execute(); + sessionTest.SQL("USE DBName").Execute(); + sessionTest.SQL("CREATE PROCEDURE my_add_one_procedure " + + " (INOUT incr_param DATE) " + + "BEGIN " + + " SET incr_param = incr_param ;" + + "END;").Execute(); + //Uncomment once Bind is implemented in 7.0.2 + sessionTest.SQL("SET @my_var = ?;").Bind("1973-12-30").Execute(); + sessionTest.SQL("CALL my_add_one_procedure(@my_var);").Execute(); + sessionTest.SQL("DROP PROCEDURE my_add_one_procedure;").Execute(); + // Use a SQL query to get the result + myResult = sessionTest.SQL("SELECT @my_var").Execute(); + // Gets the row and prints the first column + row = myResult.FetchOne(); + Assert.IsNotNull(row[0].ToString()); + sessionTest.SQL("DROP DATABASE DBName").Execute(); + } + + //DATETIME + using (Session sessionTest = MySQLX.GetSession(connectionString)) + { + sessionTest.SQL("CREATE DATABASE IF NOT EXISTS DBName").Execute(); + sessionTest.SQL("USE DBName").Execute(); + sessionTest.SQL("CREATE PROCEDURE my_add_one_procedure " + + " (INOUT incr_param DATETIME) " + + "BEGIN " + + " SET incr_param = incr_param ;" + + "END;").Execute(); + //Uncomment once Bind is implemented in 7.0.2 + sessionTest.SQL("SET @my_var = ?;").Bind("1981-04-10 15:30:00").Execute(); + sessionTest.SQL("CALL my_add_one_procedure(@my_var);").Execute(); + sessionTest.SQL("DROP PROCEDURE my_add_one_procedure;").Execute(); + // Use a SQL query to get the result + myResult = sessionTest.SQL("SELECT @my_var").Execute(); + // Gets the row and prints the first column + row = myResult.FetchOne(); + Assert.IsNotNull(row[0].ToString()); + sessionTest.SQL("DROP DATABASE DBName").Execute(); + } + + //TIMESTAMP + using (Session sessionTest = MySQLX.GetSession(connectionString)) + { + sessionTest.SQL("CREATE DATABASE IF NOT EXISTS DBName").Execute(); + sessionTest.SQL("USE DBName").Execute(); + sessionTest.SQL("CREATE PROCEDURE my_add_one_procedure " + + " (INOUT incr_param TIMESTAMP) " + + "BEGIN " + + " SET incr_param = incr_param ;" + + "END;").Execute(); + //Uncomment once Bind is implemented in 7.0.2 + sessionTest.SQL("SET @my_var = ?;").Bind("20160316153000").Execute(); + sessionTest.SQL("CALL my_add_one_procedure(@my_var);").Execute(); + sessionTest.SQL("DROP PROCEDURE my_add_one_procedure;").Execute(); + // Use a SQL query to get the result + myResult = sessionTest.SQL("SELECT @my_var").Execute(); + // Gets the row and prints the first column + row = myResult.FetchOne(); + Assert.IsNotNull(row[0].ToString()); + sessionTest.SQL("DROP DATABASE DBName").Execute(); + } + + //TIME + using (Session sessionTest = MySQLX.GetSession(connectionString)) + { + sessionTest.SQL("CREATE DATABASE IF NOT EXISTS DBName").Execute(); + sessionTest.SQL("USE DBName").Execute(); + sessionTest.SQL("CREATE PROCEDURE my_add_one_procedure " + + " (INOUT incr_param TIME) " + + "BEGIN " + + " SET incr_param = incr_param ;" + + "END;").Execute(); + //Uncomment once Bind is implemented in 7.0.2 + sessionTest.SQL("SET @my_var = ?;").Bind("12:00:00").Execute(); + sessionTest.SQL("CALL my_add_one_procedure(@my_var);").Execute(); + sessionTest.SQL("DROP PROCEDURE my_add_one_procedure;").Execute(); + // Use a SQL query to get the result + myResult = sessionTest.SQL("SELECT @my_var").Execute(); + // Gets the row and prints the first column + row = myResult.FetchOne(); + Assert.IsNotNull(row[0].ToString()); + sessionTest.SQL("DROP DATABASE DBName").Execute(); + } + + //YEAR + using (Session sessionTest = MySQLX.GetSession(connectionString)) + { + sessionTest.SQL("CREATE DATABASE IF NOT EXISTS DBName").Execute(); + sessionTest.SQL("USE DBName").Execute(); + sessionTest.SQL("CREATE PROCEDURE my_add_one_procedure " + + " (INOUT incr_param YEAR(4)) " + + "BEGIN " + + " SET incr_param = incr_param ;" + + "END;").Execute(); + //Uncomment once Bind is implemented in 7.0.2 + sessionTest.SQL("SET @my_var = ?;").Bind("2111").Execute(); + sessionTest.SQL("CALL my_add_one_procedure(@my_var);").Execute(); + sessionTest.SQL("DROP PROCEDURE my_add_one_procedure;").Execute(); + // Use a SQL query to get the result + myResult = sessionTest.SQL("SELECT @my_var").Execute(); + // Gets the row and prints the first column + row = myResult.FetchOne(); + Assert.IsNotNull(row[0].ToString()); + sessionTest.SQL("DROP DATABASE DBName").Execute(); + } + } + + + [Test, Description("Bind Support for Session SQL String Types- CHAR(M),VARCHAR(M),BLOB,TINYBLOB,MEDIUMBLOB,LONGBLOB,ENUM")] + public void BindSupportSessionSQLStringtypes() + { + if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher"); + //CHAR(20) + string connectionString = ConnectionString + ";sslmode=" + MySqlSslMode.Required; + SqlResult myResult; + Row row; + + using (Session sessionTest = MySQLX.GetSession(connectionString)) + { + sessionTest.SQL("DROP DATABASE IF EXISTS DBName ").Execute(); + sessionTest.SQL("CREATE DATABASE IF NOT EXISTS DBName").Execute(); + sessionTest.SQL("USE DBName").Execute(); + sessionTest.SQL("CREATE PROCEDURE my_add_one_procedure " + + " (INOUT incr_param CHAR(20)) " + + "BEGIN " + + " SET incr_param = incr_param;" + + "END;").Execute(); + //Uncomment once Bind is implemented in 7.0.2 + sessionTest.SQL("SET @my_var = ?;").Bind("ABCDEFGHIJABCDEFGHIJ").Execute(); + sessionTest.SQL("CALL my_add_one_procedure(@my_var);").Execute(); + sessionTest.SQL("DROP PROCEDURE my_add_one_procedure;").Execute(); + // Use a SQL query to get the result + myResult = sessionTest.SQL("SELECT @my_var").Execute(); + // Gets the row and prints the first column + row = myResult.FetchOne(); + Assert.IsNotNull(row[0].ToString()); + sessionTest.SQL("DROP DATABASE DBName").Execute(); + } + + //VARCHAR(20) + using (Session sessionTest = MySQLX.GetSession(connectionString)) + { + sessionTest.SQL("CREATE DATABASE IF NOT EXISTS DBName").Execute(); + sessionTest.SQL("USE DBName").Execute(); + sessionTest.SQL("CREATE PROCEDURE my_add_one_procedure " + + " (INOUT incr_param VARCHAR(20)) " + + "BEGIN " + + " SET incr_param = incr_param;" + + "END;").Execute(); + //Uncomment once Bind is implemented in 7.0.2 + sessionTest.SQL("SET @my_var = ?;").Bind("ABCDEFGHIJABCDEFGHIJ").Execute(); + sessionTest.SQL("CALL my_add_one_procedure(@my_var);").Execute(); + sessionTest.SQL("DROP PROCEDURE my_add_one_procedure;").Execute(); + // Use a SQL query to get the result + myResult = sessionTest.SQL("SELECT @my_var").Execute(); + // Gets the row and prints the first column + row = myResult.FetchOne(); + Assert.IsNotNull(row[0].ToString()); + sessionTest.SQL("DROP DATABASE DBName").Execute(); + } + + //BLOB + using (Session sessionTest = MySQLX.GetSession(connectionString)) + { + sessionTest.SQL("CREATE DATABASE IF NOT EXISTS DBName").Execute(); + sessionTest.SQL("USE DBName").Execute(); + sessionTest.SQL("CREATE PROCEDURE my_add_one_procedure " + + " (INOUT incr_param BLOB) " + + "BEGIN " + + " SET incr_param = incr_param ;" + + "END;").Execute(); + //Uncomment once Bind is implemented in 7.0.2 + sessionTest.SQL("SET @my_var = ?;").Bind(19731230153000).Execute(); + sessionTest.SQL("CALL my_add_one_procedure(@my_var);").Execute(); + sessionTest.SQL("DROP PROCEDURE my_add_one_procedure;").Execute(); + // Use a SQL query to get the result + myResult = sessionTest.SQL("SELECT @my_var").Execute(); + // Gets the row and prints the first column + row = myResult.FetchOne(); + Assert.IsNotNull(row[0].ToString()); + sessionTest.SQL("DROP DATABASE DBName").Execute(); + } + + //TINYBLOB + using (Session sessionTest = MySQLX.GetSession(connectionString)) + { + sessionTest.SQL("CREATE DATABASE IF NOT EXISTS DBName").Execute(); + sessionTest.SQL("USE DBName").Execute(); + sessionTest.SQL("CREATE PROCEDURE my_add_one_procedure " + + " (INOUT incr_param TINYBLOB) " + + "BEGIN " + + " SET incr_param = incr_param ;" + + "END;").Execute(); + //Uncomment once Bind is implemented in 7.0.2 + sessionTest.SQL("SET @my_var = ?;").Bind("12:00:00").Execute(); + sessionTest.SQL("CALL my_add_one_procedure(@my_var);").Execute(); + sessionTest.SQL("DROP PROCEDURE my_add_one_procedure;").Execute(); + // Use a SQL query to get the result + myResult = sessionTest.SQL("SELECT @my_var").Execute(); + // Gets the row and prints the first column + row = myResult.FetchOne(); + Assert.IsNotNull(row[0].ToString()); + sessionTest.SQL("DROP DATABASE DBName").Execute(); + } + + //MEDIUMBLOB + using (Session sessionTest = MySQLX.GetSession(connectionString)) + { + sessionTest.SQL("CREATE DATABASE IF NOT EXISTS DBName").Execute(); + sessionTest.SQL("USE DBName").Execute(); + sessionTest.SQL("CREATE PROCEDURE my_add_one_procedure " + + " (INOUT incr_param MEDIUMBLOB) " + + "BEGIN " + + " SET incr_param = incr_param ;" + + "END;").Execute(); + //Uncomment once Bind is implemented in 7.0.2 + sessionTest.SQL("SET @my_var = ?;").Bind(2111).Execute(); + sessionTest.SQL("CALL my_add_one_procedure(@my_var);").Execute(); + sessionTest.SQL("DROP PROCEDURE my_add_one_procedure;").Execute(); + // Use a SQL query to get the result + myResult = sessionTest.SQL("SELECT @my_var").Execute(); + // Gets the row and prints the first column + row = myResult.FetchOne(); + Assert.IsNotNull(row[0].ToString()); + sessionTest.SQL("DROP DATABASE DBName").Execute(); + } + + //LONGBLOB + using (Session sessionTest = MySQLX.GetSession(connectionString)) + { + sessionTest.SQL("CREATE DATABASE IF NOT EXISTS DBName").Execute(); + sessionTest.SQL("USE DBName").Execute(); + sessionTest.SQL("CREATE PROCEDURE my_add_one_procedure " + + " (INOUT incr_param LONGBLOB) " + + "BEGIN " + + " SET incr_param = incr_param ;" + + "END;").Execute(); + //Uncomment once Bind is implemented in 7.0.2 + sessionTest.SQL("SET @my_var = ?;").Bind(111232).Execute(); + sessionTest.SQL("CALL my_add_one_procedure(@my_var);").Execute(); + sessionTest.SQL("DROP PROCEDURE my_add_one_procedure;").Execute(); + // Use a SQL query to get the result + myResult = sessionTest.SQL("SELECT @my_var").Execute(); + // Gets the row and prints the first column + row = myResult.FetchOne(); + Assert.IsNotNull(row[0].ToString()); + sessionTest.SQL("DROP DATABASE DBName").Execute(); + } + + //ENUM + using (Session sessionTest = MySQLX.GetSession(connectionString)) + { + sessionTest.SQL("CREATE DATABASE IF NOT EXISTS DBName").Execute(); + sessionTest.SQL("USE DBName").Execute(); + sessionTest.SQL("CREATE PROCEDURE my_add_one_procedure " + + " (INOUT incr_param ENUM('x-small', 'small', 'medium', 'large', 'x-large')) " + + "BEGIN " + + " SET incr_param = incr_param ;" + + "END;").Execute(); + //Uncomment once Bind is implemented in 7.0.2 + sessionTest.SQL("SET @my_var = ?;").Bind("large").Execute(); + sessionTest.SQL("CALL my_add_one_procedure(@my_var);").Execute(); + sessionTest.SQL("DROP PROCEDURE my_add_one_procedure;").Execute(); + // Use a SQL query to get the result + myResult = sessionTest.SQL("SELECT @my_var").Execute(); + // Gets the row and prints the first column + row = myResult.FetchOne(); + Assert.IsNotNull(row[0].ToString()); + sessionTest.SQL("DROP DATABASE DBName").Execute(); + } + } + + [Test, Description("Bind Support for Session SQL Negative Tests-Null")] + public void BindSupportSessionSQLNegativeTest1() + { + if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher"); + SqlResult myResult = null; + + //integer + string connectionString = ConnectionString + ";sslmode=" + MySqlSslMode.Required; + Session sessionTest = MySQLX.GetSession(connectionString); + sessionTest.SQL("DROP DATABASE IF EXISTS DBName ").Execute(); + sessionTest.SQL("CREATE DATABASE IF NOT EXISTS DBName").Execute(); + sessionTest.SQL("USE DBName").Execute(); + sessionTest.SQL("CREATE PROCEDURE my_add_one_procedure " + + " (INOUT incr_param INT) " + + "BEGIN " + + " SET incr_param = incr_param+1;" + + "END;").Execute(); + + sessionTest.SQL("SET @my_var = ?;").Bind(null).Execute(); + sessionTest.SQL("CALL my_add_one_procedure(@my_var);").Execute(); + sessionTest.SQL("DROP PROCEDURE my_add_one_procedure;").Execute(); + // Use a SQL query to get the result + myResult = sessionTest.SQL("SELECT @my_var").Execute(); + + Assert.Throws(() => myResult.FetchOne()); + sessionTest.SQL("DROP DATABASE DBName").Execute(); + sessionTest.Close(); + sessionTest.Dispose(); + } + + [Test, Description("Bind Support for Session SQL Negative Tests-Bind Chaining Tests")] + public void BindSupportSessionSQLNegativeTest2() + { + if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher"); + + //integer + string connectionString = ConnectionString + ";sslmode=" + MySqlSslMode.Required; + Session sessionTest = MySQLX.GetSession(connectionString); + sessionTest.SQL("DROP DATABASE IF EXISTS DBName ").Execute(); + sessionTest.SQL("CREATE DATABASE IF NOT EXISTS DBName").Execute(); + sessionTest.SQL("USE DBName").Execute(); + sessionTest.SQL("CREATE PROCEDURE my_add_one_procedure " + + " (INOUT incr_param INT) " + + "BEGIN " + + " SET incr_param = incr_param + 1;" + + "END;").Execute(); + sessionTest.SQL("CREATE TABLE DBName.test(id INT, letter varchar(1))").Execute(); + + for (int i = 1; i <= 100; i++) + + session.SQL("INSERT INTO DBName.test VALUES (?, ?), (?, ?)") + .Bind(1, "a") + .Bind(2, "b") + .Execute(); + + SqlResult result = session.SQL("select * from DBName.test where id=?").Bind(5).Execute(); + + //Uncomment once Bind is implemented in 7.0.2 + Assert.Throws(() => session.SQL("SET @my_var = ?;").Bind(1).Bind(2).Execute()); + sessionTest.SQL("DROP DATABASE DBName").Execute(); + sessionTest.Close(); + sessionTest.Dispose(); + + } + + // Aditional Tests + [Test, Description("Test MySQLX plugin MySQL mixed scenario")] + public void MixedChainedCommands() + { + if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher"); + ExecuteSQL("Drop table if exists test"); + ExecuteSQL("CREATE TABLE test(c1 float(14,8),c2 double GENERATED ALWAYS AS (c1*101/102) Stored COMMENT 'First Gen Col')"); + ExecuteSQL("INSERT INTO test(c1) VALUES (22.7)"); + ExecuteSQL("INSERT INTO test(c1) VALUES (-100000.38984)"); + ExecuteSQL("INSERT INTO test(c1) VALUES (0)"); + + RowResult r = session.GetSchema("test").GetTable("test").Select("c1").Execute(); + var rows = r.FetchAll(); + Assert.AreEqual(1, r.Columns.Count, "Matching"); + Assert.AreEqual(typeof(float).ToString(), r.Columns[0].ClrType.ToString(), "Matching"); + Assert.AreEqual(MySqlDbType.Float.ToString(), r.Columns[0].Type.ToString(), "Matching"); + Assert.AreEqual(14, (int)r.Columns[0].Length, "Matching"); + Assert.AreEqual(8, (int)r.Columns[0].FractionalDigits, "Matching"); + Assert.AreEqual(3, rows.Count, "Matching"); + Assert.AreEqual(22.7f, (float)rows[0][0], "Matching"); + Assert.AreEqual(-100000.38984f, (float)rows[1][0], "Matching"); + Assert.AreEqual(0f, (float)rows[2][0], "Matching"); + } + + [Test, Description("Test MySQLX plugin MySQL Date Time Bug")] + public void DateTimeCheck() + { + if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher"); + ExecuteSQL("CREATE TABLE test.test1212(dt DATETIME(6))"); + ExecuteSQL("INSERT INTO test.test1212 VALUES('2015-10-21 18:01:00.12345678')"); + + RowResult r = session.GetSchema("test").GetTable("test1212").Select("dt").Execute(); + var rows = r.FetchAll(); + Assert.AreEqual(1, r.Columns.Count, "Matching Coulumn Count"); + + } + + [Test, Description("Test MySQLX plugin MySQL Datetime JSON")] + public void DateTimeJSON() + { + if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher"); + ExecuteSQL("DROP TABLE IF EXISTS test.test"); + ExecuteSQL("CREATE TABLE test.test(Id int NOT NULL PRIMARY KEY, jsoncolumn JSON)"); + ExecuteSQL(@"INSERT INTO test.test VALUES(100000,' { ""name"" : ""bob"",""Date"": ""2015-10-09"",""Time"": ""12:18:29.000000"",""DateTimeOfRegistration"": ""2015-10-09 12:18:29.000000"",""age"":12} ')"); + RowResult r = session.GetSchema("test").GetTable("test").Select("jsoncolumn").Execute(); + var rows = r.FetchAll(); + Assert.AreEqual(1, r.Columns.Count, "Matching"); + } + + [Test, Description("Test MySQLX plugin JSON Variant")] + public void JSONVariant() + { + if (!Platform.IsWindows()) Assert.Ignore("This test is for Windows OS only"); + if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher"); + ExecuteSQL("DROP TABLE IF EXISTS Test"); + ExecuteSQL("CREATE TABLE test (Id int NOT NULL PRIMARY KEY, jsoncolumn JSON)"); + ExecuteSQL("INSERT INTO test VALUES (1, '[1]')"); + ExecuteSQL(@"INSERT INTO test VALUES (2, '[""a"", {""b"": [true, false]}, [10, 20]]')"); + ExecuteSQL(@"INSERT INTO test VALUES (3, '{""id"":1,""name"":""test""}')"); + var r = ExecuteSQL(@"SELECT JSON_EXTRACT('{""id"": 1, ""name"": ""test""}','$.name')").FetchOne(); + Assert.AreEqual("\"test\"", r[0]); + } + + [Test, Description("Test MySQLX plugin big int as PK")] + public void BigIntasPK() + { + if (!Platform.IsWindows()) Assert.Ignore("This test is for Windows OS only"); + if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher"); + + ExecuteSQL("DROP TABLE IF EXISTS Test"); + ExecuteSQL("CREATE TABLE test (Id bigint NOT NULL PRIMARY KEY, jsoncolumn JSON)"); + var res = ExecuteSQL("INSERT INTO test VALUES (934157136952, '[1]')"); + Assert.AreEqual(1, res.AffectedItemsCount); + res = ExecuteSQL(@"INSERT INTO test VALUES (9223372036854775807, '[""a"", {""b"": [true, false]}, [10, 20]]')"); + Assert.AreEqual(1, res.AffectedItemsCount); + Assert.Throws(() => ExecuteSQL("INSERT INTO test VALUES ('str1', '[1]')")); + } + + [Test, Description("Test MySQLX plugin tiny int as PK")] + public void TinyIntasPK() + { + if (!Platform.IsWindows()) Assert.Ignore("This test is for Windows OS only"); + if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher"); + + using (var ss = MySQLX.GetSession(ConnectionString)) + { + ss.SQL("DROP TABLE IF EXISTS test.test").Execute(); + ss.SQL("CREATE TABLE test.test (Id tinyint NOT NULL PRIMARY KEY, jsoncolumn JSON)").Execute(); + var res = ss.SQL("INSERT INTO test.test VALUES (1, '[1]')").Execute(); + Assert.AreEqual(1, res.AffectedItemsCount); + res = ss.SQL(@"INSERT INTO test.test VALUES (2, '[""a"", {""b"": [true, false]}, [10, 20]]')").Execute(); + Assert.AreEqual(1, res.AffectedItemsCount); + Assert.Throws(() => ss.SQL("INSERT INTO test.test VALUES ('str1', '[1]')").Execute()); + } + } + + [Test, Description("Test MySQLX plugin small int as PK")] + public void SmallIntasPK() + { + if (!Platform.IsWindows()) Assert.Ignore("This test is for Windows OS only"); + if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher"); + + using (var ss = MySQLX.GetSession(ConnectionString)) + { + ss.SQL("DROP TABLE IF EXISTS test.test").Execute(); + ss.SQL("CREATE TABLE test.test (Id smallint NOT NULL PRIMARY KEY, jsoncolumn JSON)").Execute(); + var res = ss.SQL("INSERT INTO test.test VALUES (99, '[1]')").Execute(); + Assert.AreEqual(1, res.AffectedItemsCount); + res = ss.SQL(@"INSERT INTO test.test VALUES (1, '[""a"", {""b"": [true, false]}, [10, 20]]')").Execute(); + Assert.AreEqual(1, res.AffectedItemsCount); + Assert.Throws(() => ss.SQL("INSERT INTO test.test VALUES ('str1', '[1]')").Execute()); + ss.SQL("DROP TABLE IF EXISTS test.test"); + } + } + + [Test, Description("MySQL sample data insertion and viewing")] + public void DataValidation() + { + ExecuteSQL("DROP TABLE IF EXISTS TEST"); + ExecuteSQL("CREATE TABLE TEST(name VARCHAR(20),id INT NOT NULL,sports VARCHAR(20))"); + ExecuteSQL("INSERT INTO TEST(name,id,sports) VALUES ('Federer',1,'Tennis')"); + ExecuteSQL("INSERT INTO TEST(name,id,sports) VALUES ('Ronaldo',2,'Soccer')"); + ExecuteSQL("INSERT INTO TEST(name,id,sports) VALUES ('Messi',3,'Soccer')"); + var expecteddataValue = new List { "Federer", "Ronaldo", "Messi" }; + using (SqlResult result = ExecuteSQLStatement(session.SQL("SELECT name FROM TEST;"))) + { + while (result.Next()) + { + Assert.That(result.Rows, Has.Exactly(3).Items); + Assert.True(expecteddataValue.Contains(result[0].ToString())); + } + } + } + #endregion + } +} diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/TableAsyncTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/TableAsyncTests.cs index 9fc3ed575..29cfb61b3 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/TableAsyncTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/TableAsyncTests.cs @@ -1,164 +1,164 @@ -// Copyright (c) 2015, 2021, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySql.Data.MySqlClient; -using MySqlX.XDevAPI; -using MySqlX.XDevAPI.Common; -using MySqlX.XDevAPI.Relational; -using NUnit.Framework; -using System; -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; - -namespace MySqlX.Data.Tests.RelationalTests -{ - public class TableAsyncTests : BaseTest - { - [TearDown] - public void TearDown() => ExecuteSQL("DROP TABLE IF EXISTS test"); - - [SetUp] - public void SetUp() => ExecuteSQL("CREATE TABLE test.test(id INT, age INT)"); - - [Test] - public void MultipleTableInsertAsync() - { - Table table = testSchema.GetTable("test"); - List> tasksList = new List>(); - - for (int i = 1; i <= 200; i++) - { - tasksList.Add(table.Insert().Values(i, i % 250).ExecuteAsync()); - } - - Assert.True(Task.WaitAll(tasksList.ToArray(), TimeSpan.FromMinutes(2)), "WaitAll timeout"); - Assert.AreEqual(200, table.Count()); - } - - [Test] - public void MultipleTableSelectAsync() - { - var table = testSchema.GetTable("test"); - int rows = 100; - var insert = table.Insert(); - HashSet validator = new HashSet(); - - for (int i = 1; i <= rows; i++) - { - insert.Values(i, i); - } - var result = ExecuteInsertStatement(insert); - - List> tasksList = new List>(); - - for (int i = 1; i <= rows; i++) - { - tasksList.Add(table.Select().Where("age = :age").Bind("aGe", i).ExecuteAsync()); - } - - Assert.True(Task.WaitAll(tasksList.ToArray(), TimeSpan.FromMinutes(2)), "WaitAll timeout"); - foreach (Task task in tasksList) - { - Assert.AreEqual(2, task.Result.Columns.Count); - Assert.That(task.Result.Rows, Has.One.Items); - int value = (int)task.Result.Rows[0][1]; - Assert.False(validator.Contains(value), value + " value exists"); - validator.Add(value); - } - Assert.AreEqual(rows, validator.Count); - } - #region WL14389 - [Test, Description("Table.Select() with shared lock and Table.Update() ")] - public async Task TableSelectAndUpdateAsync() - { - _ = await SubProcess1(); - _ = await SubProcess2(); - } - - private Task SubProcess1() - { - if (!session.Version.isAtLeast(8, 0, 3)) return Task.FromResult(0); - session.SQL("SET autocommit = 0").Execute(); - using (var session2 = MySQLX.GetSession(ConnectionString)) - { - session2.SQL("SET autocommit = 0").Execute(); - var table = session.Schema.GetTable("test"); - try - { - session.SQL("CREATE UNIQUE INDEX myIndex ON test.test (id)").Execute(); - } - catch (MySqlException ex) - { - Assert.True(ex.Message.Contains("Duplicate")); - } - - var table2 = session2.GetSchema("test").GetTable("test"); - session2.SQL("START TRANSACTION").Execute(); - for (var i = 0; i < 1000; i++) - { - var result = table2.Update().Where("id = 1").Set("age", 2).Execute(); - Assert.IsNotNull(result); - } - } - - session.SQL("SET autocommit = 1").Execute(); - return Task.FromResult(0); - } - - - private Task SubProcess2() - { - Thread.Sleep(1000); - if (!session.InternalSession.GetServerVersion().isAtLeast(8, 0, 3)) return Task.FromResult(0); - session.SQL("SET autocommit = 0").Execute(); - - using (var session2 = MySQLX.GetSession(ConnectionString)) - { - session2.SQL("SET autocommit = 0").Execute(); - var table = session.Schema.GetTable("test"); - try - { - session.SQL("CREATE UNIQUE INDEX myIndex ON test.test (id)").Execute(); - } - catch (MySqlException ex) - { - Assert.True(ex.Message.Contains("Duplicate")); - } - - var table2 = session2.GetSchema("test").GetTable("test"); - session.SQL("START TRANSACTION").Execute(); - var rowResult = table.Select().Where("id = 1").LockExclusive().Execute(); - } - - session.SQL("SET autocommit = 0").Execute(); - return Task.FromResult(0); - } - #endregion WL14389 - } -} +// Copyright © 2015, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySql.Data.MySqlClient; +using MySqlX.XDevAPI; +using MySqlX.XDevAPI.Common; +using MySqlX.XDevAPI.Relational; +using NUnit.Framework; +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; + +namespace MySqlX.Data.Tests.RelationalTests +{ + public class TableAsyncTests : BaseTest + { + [TearDown] + public void TearDown() => ExecuteSQL("DROP TABLE IF EXISTS test"); + + [SetUp] + public void SetUp() => ExecuteSQL("CREATE TABLE test.test(id INT, age INT)"); + + [Test] + public void MultipleTableInsertAsync() + { + Table table = testSchema.GetTable("test"); + List> tasksList = new List>(); + + for (int i = 1; i <= 200; i++) + { + tasksList.Add(table.Insert().Values(i, i % 250).ExecuteAsync()); + } + + Assert.True(Task.WaitAll(tasksList.ToArray(), TimeSpan.FromMinutes(2)), "WaitAll timeout"); + Assert.AreEqual(200, table.Count()); + } + + [Test] + public void MultipleTableSelectAsync() + { + var table = testSchema.GetTable("test"); + int rows = 100; + var insert = table.Insert(); + HashSet validator = new HashSet(); + + for (int i = 1; i <= rows; i++) + { + insert.Values(i, i); + } + var result = ExecuteInsertStatement(insert); + + List> tasksList = new List>(); + + for (int i = 1; i <= rows; i++) + { + tasksList.Add(table.Select().Where("age = :age").Bind("aGe", i).ExecuteAsync()); + } + + Assert.True(Task.WaitAll(tasksList.ToArray(), TimeSpan.FromMinutes(2)), "WaitAll timeout"); + foreach (Task task in tasksList) + { + Assert.AreEqual(2, task.Result.Columns.Count); + Assert.That(task.Result.Rows, Has.One.Items); + int value = (int)task.Result.Rows[0][1]; + Assert.False(validator.Contains(value), value + " value exists"); + validator.Add(value); + } + Assert.AreEqual(rows, validator.Count); + } + #region WL14389 + [Test, Description("Table.Select() with shared lock and Table.Update() ")] + public async Task TableSelectAndUpdateAsync() + { + _ = await SubProcess1(); + _ = await SubProcess2(); + } + + private Task SubProcess1() + { + if (!session.Version.isAtLeast(8, 0, 3)) return Task.FromResult(0); + session.SQL("SET autocommit = 0").Execute(); + using (var session2 = MySQLX.GetSession(ConnectionString)) + { + session2.SQL("SET autocommit = 0").Execute(); + var table = session.Schema.GetTable("test"); + try + { + session.SQL("CREATE UNIQUE INDEX myIndex ON test.test (id)").Execute(); + } + catch (MySqlException ex) + { + Assert.True(ex.Message.Contains("Duplicate")); + } + + var table2 = session2.GetSchema("test").GetTable("test"); + session2.SQL("START TRANSACTION").Execute(); + for (var i = 0; i < 1000; i++) + { + var result = table2.Update().Where("id = 1").Set("age", 2).Execute(); + Assert.IsNotNull(result); + } + } + + session.SQL("SET autocommit = 1").Execute(); + return Task.FromResult(0); + } + + + private Task SubProcess2() + { + Thread.Sleep(1000); + if (!session.InternalSession.GetServerVersion().isAtLeast(8, 0, 3)) return Task.FromResult(0); + session.SQL("SET autocommit = 0").Execute(); + + using (var session2 = MySQLX.GetSession(ConnectionString)) + { + session2.SQL("SET autocommit = 0").Execute(); + var table = session.Schema.GetTable("test"); + try + { + session.SQL("CREATE UNIQUE INDEX myIndex ON test.test (id)").Execute(); + } + catch (MySqlException ex) + { + Assert.True(ex.Message.Contains("Duplicate")); + } + + var table2 = session2.GetSchema("test").GetTable("test"); + session.SQL("START TRANSACTION").Execute(); + var rowResult = table.Select().Where("id = 1").LockExclusive().Execute(); + } + + session.SQL("SET autocommit = 0").Execute(); + return Task.FromResult(0); + } + #endregion WL14389 + } +} diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/TableDeleteTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/TableDeleteTests.cs index 0ee723123..7f0564253 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/TableDeleteTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/TableDeleteTests.cs @@ -1,116 +1,116 @@ -// Copyright (c) 2015, 2021, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySql.Data.MySqlClient; -using MySqlX.XDevAPI.Common; -using MySqlX.XDevAPI.Relational; -using NUnit.Framework; - -namespace MySqlX.Data.Tests.RelationalTests -{ - public class TableDeleteTests : BaseTest - { - [TearDown] - public void TearDown() => ExecuteSQL("DROP TABLE IF EXISTS test"); - - [SetUp] - public void SetUp() - { - ExecuteSQL("CREATE TABLE test.test(id INT, age INT)"); - - var insertStatement = testSchema.GetTable("test").Insert(); - int rowsToInsert = 10; - for (int i = 1; i <= rowsToInsert; i++) - { - insertStatement.Values(i, i); - } - ExecuteInsertStatement(insertStatement); - Assert.AreEqual(rowsToInsert, CountRows()); - } - - private long CountRows() - { - return testSchema.GetTable("test").Count(); - } - - private void ExecuteDelete(TableDeleteStatement statement, int expectedRowsCount) - { - Result result = ExecuteDeleteStatement(statement); - Assert.AreEqual(expectedRowsCount, CountRows()); - } - - [Test] - public void DeleteAllTest() - { - ExecuteDelete(testSchema.GetTable("test").Delete(), 0); - } - - [Test] - public void DeleteConditionTest() - { - ExecuteDelete(testSchema.GetTable("test").Delete().Where("age % 2 = 0"), 5); - } - - [Test] - public void DeleteOrderbyAndLimit() - { - ExecuteDelete(testSchema.GetTable("test").Delete().OrderBy("age Desc").Limit(3), 7); - } - - [Test] - public void DeleteConditionOrderbyAndLimit() - { - ExecuteDelete(testSchema.GetTable("test").Delete().Where("id > 5").OrderBy("id Desc").Limit(2), 8); - } - - [Test] - public void DeleteBindTest() - { - var deleteStmt = testSchema.GetTable("test").Delete().Where("age = :aGe"); - ExecuteDelete(deleteStmt.Bind("Age", 4), 9); - ExecuteDelete(deleteStmt.Bind("age", 6), 8); - } - - [Test] - public void DeleteWithInOperator() - { - Table table = testSchema.GetTable("test"); - Assert.AreEqual(10, CountRows()); - - Assert.AreEqual(2, ExecuteDeleteStatement(table.Delete().Where("id IN (1,2)")).AffectedItemsCount); - Assert.AreEqual(8, CountRows()); - - Assert.Throws(() => ExecuteDeleteStatement(table.Delete().Where("a IN [3]"))); - Assert.Throws(() => ExecuteDeleteStatement(table.Delete().Where("3 IN a"))); - Assert.Throws(() => ExecuteDeleteStatement(table.Delete().Where("age IN [3]"))); - - Assert.AreEqual(1, ExecuteDeleteStatement(table.Delete().Where("age IN (3)")).AffectedItemsCount); - Assert.AreEqual(7, CountRows()); - } - } -} +// Copyright © 2015, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySql.Data.MySqlClient; +using MySqlX.XDevAPI.Common; +using MySqlX.XDevAPI.Relational; +using NUnit.Framework; + +namespace MySqlX.Data.Tests.RelationalTests +{ + public class TableDeleteTests : BaseTest + { + [TearDown] + public void TearDown() => ExecuteSQL("DROP TABLE IF EXISTS test"); + + [SetUp] + public void SetUp() + { + ExecuteSQL("CREATE TABLE test.test(id INT, age INT)"); + + var insertStatement = testSchema.GetTable("test").Insert(); + int rowsToInsert = 10; + for (int i = 1; i <= rowsToInsert; i++) + { + insertStatement.Values(i, i); + } + ExecuteInsertStatement(insertStatement); + Assert.AreEqual(rowsToInsert, CountRows()); + } + + private long CountRows() + { + return testSchema.GetTable("test").Count(); + } + + private void ExecuteDelete(TableDeleteStatement statement, int expectedRowsCount) + { + Result result = ExecuteDeleteStatement(statement); + Assert.AreEqual(expectedRowsCount, CountRows()); + } + + [Test] + public void DeleteAllTest() + { + ExecuteDelete(testSchema.GetTable("test").Delete(), 0); + } + + [Test] + public void DeleteConditionTest() + { + ExecuteDelete(testSchema.GetTable("test").Delete().Where("age % 2 = 0"), 5); + } + + [Test] + public void DeleteOrderbyAndLimit() + { + ExecuteDelete(testSchema.GetTable("test").Delete().OrderBy("age Desc").Limit(3), 7); + } + + [Test] + public void DeleteConditionOrderbyAndLimit() + { + ExecuteDelete(testSchema.GetTable("test").Delete().Where("id > 5").OrderBy("id Desc").Limit(2), 8); + } + + [Test] + public void DeleteBindTest() + { + var deleteStmt = testSchema.GetTable("test").Delete().Where("age = :aGe"); + ExecuteDelete(deleteStmt.Bind("Age", 4), 9); + ExecuteDelete(deleteStmt.Bind("age", 6), 8); + } + + [Test] + public void DeleteWithInOperator() + { + Table table = testSchema.GetTable("test"); + Assert.AreEqual(10, CountRows()); + + Assert.AreEqual(2, ExecuteDeleteStatement(table.Delete().Where("id IN (1,2)")).AffectedItemsCount); + Assert.AreEqual(8, CountRows()); + + Assert.Throws(() => ExecuteDeleteStatement(table.Delete().Where("a IN [3]"))); + Assert.Throws(() => ExecuteDeleteStatement(table.Delete().Where("3 IN a"))); + Assert.Throws(() => ExecuteDeleteStatement(table.Delete().Where("age IN [3]"))); + + Assert.AreEqual(1, ExecuteDeleteStatement(table.Delete().Where("age IN (3)")).AffectedItemsCount); + Assert.AreEqual(7, CountRows()); + } + } +} diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/TableInsertTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/TableInsertTests.cs index 57b592f69..5d1ad8320 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/TableInsertTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/TableInsertTests.cs @@ -1,125 +1,125 @@ -// Copyright (c) 2015, 2022, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySql.Data.MySqlClient; -using MySqlX.XDevAPI.Relational; -using NUnit.Framework; -using System.Linq; - -namespace MySqlX.Data.Tests.RelationalTests -{ - public class TableInsertTests : BaseTest - { - [TearDown] - public void TearDown() => ExecuteSQL("DROP TABLE IF EXISTS test"); - public TableInsertTests() - { - } - - [Test] - public void InsertMultipleValues() - { - ExecuteSQL("CREATE TABLE test.test(name VARCHAR(40), age INT)"); - Table table = testSchema.GetTable("test"); - - var result = ExecuteInsertStatement(table.Insert("name", "age") - .Values("Henry", "22") - .Values("Patric", 30) - ); - Assert.AreEqual(2, result.AffectedItemsCount); - - var selectResult = ExecuteSelectStatement(table.Select()); - while (selectResult.Next()) ; - Assert.AreEqual(2, selectResult.Rows.Count); - Assert.AreEqual("Henry", selectResult.Rows.ToArray()[0][0]); - Assert.AreEqual(22, selectResult.Rows.ToArray()[0][1]); - Assert.AreEqual("Patric", selectResult.Rows.ToArray()[1][0]); - Assert.AreEqual(30, selectResult.Rows.ToArray()[1][1]); - - Assert.AreEqual(2, table.Count()); - } - - [Test] - public void InsertExpressions() - { - ExecuteSQL("CREATE TABLE test.test(name VARCHAR(40), age INT)"); - Table table = testSchema.GetTable("test"); - - var result = ExecuteInsertStatement(table.Insert("name", "age").Values("MARK", "34")); - Assert.AreEqual(1, result.AffectedItemsCount); - - var selectResult = ExecuteSelectStatement(table.Select()); - while (selectResult.Next()) ; - Assert.That(selectResult.Rows, Has.One.Items); - Assert.AreEqual("MARK", selectResult.Rows.ToArray()[0][0]); - Assert.AreEqual(34, selectResult.Rows.ToArray()[0][1]); - } - - [Test] - public void ReuseStatement() - { - ExecuteSQL("CREATE TABLE test(name VARCHAR(40), age INT)"); - Table table = testSchema.GetTable("test"); - - var stmt = table.Insert("name", "age"); - var result = ExecuteInsertStatement(stmt.Values("MARK", "34")); - Assert.AreEqual(1, result.AffectedItemsCount); - // error 5014 - Wrong number of fields in row being inserted - Assert.AreEqual(5014u, Assert.Throws(() => result = ExecuteInsertStatement(stmt.Values("George", 34, 1))).Code); - Assert.AreEqual(5014u, Assert.Throws(() => ExecuteInsertStatement(stmt.Values("George", 34))).Code); - Assert.That(ExecuteSelectStatement(table.Select()).FetchAll(), Has.One.Items); - } - - /// - /// Bug#31692694 - TABLEINSERTSTATEMENT STRING SPECIAL CARAC VALUES OBJECT ARE UNCORRECTLY MANAGED - /// - [TestCase("-")] - [TestCase("+")] - [TestCase("*")] - [TestCase("/")] - [TestCase("\\")] - [TestCase("=")] - [TestCase("(")] - [TestCase(")")] - public void InsertWithExpressionsAlikeValues(string specialChar) - { - ExecuteSQL("CREATE TABLE test(ID INT, COLUMN_TEST VARCHAR(40))"); - string value = $"ImproperFieldNameBug {specialChar} Bug"; - - Table table = testSchema.GetTable("test"); - var insertResult = table.Insert("ID", "COLUMN_TEST").Values("1", value).Execute(); - var selectResult = ExecuteSelectStatement(table.Select()); - while (selectResult.Next()) ; - - Assert.AreEqual(1, insertResult.AffectedItemsCount); - Assert.That(selectResult.Rows, Has.One.Items); - StringAssert.AreEqualIgnoringCase("1", selectResult.Rows.ToArray()[0][0].ToString()); - StringAssert.AreEqualIgnoringCase(value, selectResult.Rows.ToArray()[0][1].ToString()); - } - } -} +// Copyright © 2015, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySql.Data.MySqlClient; +using MySqlX.XDevAPI.Relational; +using NUnit.Framework; +using System.Linq; + +namespace MySqlX.Data.Tests.RelationalTests +{ + public class TableInsertTests : BaseTest + { + [TearDown] + public void TearDown() => ExecuteSQL("DROP TABLE IF EXISTS test"); + public TableInsertTests() + { + } + + [Test] + public void InsertMultipleValues() + { + ExecuteSQL("CREATE TABLE test.test(name VARCHAR(40), age INT)"); + Table table = testSchema.GetTable("test"); + + var result = ExecuteInsertStatement(table.Insert("name", "age") + .Values("Henry", "22") + .Values("Patric", 30) + ); + Assert.AreEqual(2, result.AffectedItemsCount); + + var selectResult = ExecuteSelectStatement(table.Select()); + while (selectResult.Next()) ; + Assert.AreEqual(2, selectResult.Rows.Count); + Assert.AreEqual("Henry", selectResult.Rows.ToArray()[0][0]); + Assert.AreEqual(22, selectResult.Rows.ToArray()[0][1]); + Assert.AreEqual("Patric", selectResult.Rows.ToArray()[1][0]); + Assert.AreEqual(30, selectResult.Rows.ToArray()[1][1]); + + Assert.AreEqual(2, table.Count()); + } + + [Test] + public void InsertExpressions() + { + ExecuteSQL("CREATE TABLE test.test(name VARCHAR(40), age INT)"); + Table table = testSchema.GetTable("test"); + + var result = ExecuteInsertStatement(table.Insert("name", "age").Values("MARK", "34")); + Assert.AreEqual(1, result.AffectedItemsCount); + + var selectResult = ExecuteSelectStatement(table.Select()); + while (selectResult.Next()) ; + Assert.That(selectResult.Rows, Has.One.Items); + Assert.AreEqual("MARK", selectResult.Rows.ToArray()[0][0]); + Assert.AreEqual(34, selectResult.Rows.ToArray()[0][1]); + } + + [Test] + public void ReuseStatement() + { + ExecuteSQL("CREATE TABLE test(name VARCHAR(40), age INT)"); + Table table = testSchema.GetTable("test"); + + var stmt = table.Insert("name", "age"); + var result = ExecuteInsertStatement(stmt.Values("MARK", "34")); + Assert.AreEqual(1, result.AffectedItemsCount); + // error 5014 - Wrong number of fields in row being inserted + Assert.AreEqual(5014u, Assert.Throws(() => result = ExecuteInsertStatement(stmt.Values("George", 34, 1))).Code); + Assert.AreEqual(5014u, Assert.Throws(() => ExecuteInsertStatement(stmt.Values("George", 34))).Code); + Assert.That(ExecuteSelectStatement(table.Select()).FetchAll(), Has.One.Items); + } + + /// + /// Bug#31692694 - TABLEINSERTSTATEMENT STRING SPECIAL CARAC VALUES OBJECT ARE UNCORRECTLY MANAGED + /// + [TestCase("-")] + [TestCase("+")] + [TestCase("*")] + [TestCase("/")] + [TestCase("\\")] + [TestCase("=")] + [TestCase("(")] + [TestCase(")")] + public void InsertWithExpressionsAlikeValues(string specialChar) + { + ExecuteSQL("CREATE TABLE test(ID INT, COLUMN_TEST VARCHAR(40))"); + string value = $"ImproperFieldNameBug {specialChar} Bug"; + + Table table = testSchema.GetTable("test"); + var insertResult = table.Insert("ID", "COLUMN_TEST").Values("1", value).Execute(); + var selectResult = ExecuteSelectStatement(table.Select()); + while (selectResult.Next()) ; + + Assert.AreEqual(1, insertResult.AffectedItemsCount); + Assert.That(selectResult.Rows, Has.One.Items); + StringAssert.AreEqualIgnoringCase("1", selectResult.Rows.ToArray()[0][0].ToString()); + StringAssert.AreEqualIgnoringCase(value, selectResult.Rows.ToArray()[0][1].ToString()); + } + } +} diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/TableSelectTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/TableSelectTests.cs index 2ab6b4033..f16f24d4c 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/TableSelectTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/TableSelectTests.cs @@ -1,1754 +1,1754 @@ -// Copyright (c) 2015, 2022, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySql.Data.Common; -using MySql.Data.MySqlClient; -using MySqlX.XDevAPI; -using MySqlX.XDevAPI.Common; -using MySqlX.XDevAPI.Relational; -using NUnit.Framework; -using System; -using System.Linq; -using System.Text; - -namespace MySqlX.Data.Tests.RelationalTests -{ - public class TableSelectTests : BaseTest - { - object[][] allRows = { - new object[] { 1, "jonh doe", 38, "{\"company\": \"xyz\", \"hobbies\": \"reading\", \"vehicle\": \"bike\"}" }, - new object[] { 2, "milton green", 45, "{\"company\": \"abc\", \"hobbies\": [\"boxing\", \"running\"], \"vehicle\": \"car\"}" }, - new object[] { 3, "larry smith", 24, "{\"company\": \"zxc\", \"hobbies\": \"painting\", \"vehicle\": \"boat\"}" } - }; - - [SetUp] - public void SetUp() - { - ExecuteSQL("CREATE TABLE test.test (id INT, name VARCHAR(45), age INT, additionalinfo JSON)"); - TableInsertStatement stmt = testSchema.GetTable("test").Insert(); - stmt.Values(allRows[0]); - stmt.Values(allRows[1]); - stmt.Values(allRows[2]); - Result result = ExecuteInsertStatement(stmt); - } - - [TearDown] - public void TearDown() - { - ExecuteSQL("DROP TABLE IF EXISTS test"); - ExecuteSQL("DROP TABLE IF EXISTS testDate"); - } - - [Test] - public void FetchOne() - { - Table t = testSchema.GetTable("test"); - Assert.AreEqual(38, ExecuteSelectStatement(t.Select("age")).FetchOne()["age"]); - } - - private void MultiTableSelectTest(TableSelectStatement statement, object[][] expectedValues) - { - RowResult result = ExecuteSelectStatement(statement); - int rowCount = result.FetchAll().Count; - - Assert.AreEqual(expectedValues.Length, rowCount); - Assert.AreEqual(expectedValues.Length, result.Rows.Count); - for (int i = 0; i < expectedValues.Length; i++) - { - for (int j = 0; j < expectedValues[i].Length; j++) - { - Assert.AreEqual(expectedValues[i][j], result.Rows.ToArray()[i][j]); - } - } - } - - [Test] - public void TableSelect() - { - var table = testSchema.GetTable("test"); - - MultiTableSelectTest(table.Select(), allRows); - MultiTableSelectTest(table.Select("name", "age"), - allRows.Select(c => new[] { c[1], c[2] }).ToArray()); - MultiTableSelectTest(table.Select("name", "age").Where("age == 38"), - allRows.Select(c => new[] { c[1], c[2] }).Where(c => (int)c[1] == 38).ToArray()); - MultiTableSelectTest(table.Select().Where("age == 45"), - allRows.Where(c => (int)c[2] == 45).ToArray()); - MultiTableSelectTest(table.Select().OrderBy("age"), - allRows.OrderBy(c => c[2]).ToArray()); - MultiTableSelectTest(table.Select().OrderBy("age desc"), - allRows.OrderByDescending(c => c[2]).ToArray()); - MultiTableSelectTest(table.Select().OrderBy("age desc, name"), - allRows.OrderByDescending(c => c[2]).ThenBy(c => c[1]).ToArray()); - MultiTableSelectTest(table.Select().Limit(1), - allRows.Take(1).ToArray()); - MultiTableSelectTest(table.Select().Limit(10).Offset(1), - allRows.Skip(1).Take(10).ToArray()); - MultiTableSelectTest(table.Select().Limit(1).Offset(1), - allRows.Skip(1).Take(1).ToArray()); - MultiTableSelectTest(table.Select().Where("name like :name").Bind("nAme", "%jon%"), - allRows.Where(c => c[1].ToString().Contains("jon")).ToArray()); - MultiTableSelectTest(table.Select().Where("name like :name").Bind("naMe", "%on%"), - allRows.Where(c => c[1].ToString().Contains("on")).ToArray()); - } - - [Test] - public void AllColumns() - { - var table = testSchema.GetTable("test"); - var select = ExecuteSelectStatement(table.Select("*, 42 as a_number, '43' as a_string")); - var rows = select.FetchAll(); - Assert.AreEqual(6, select.Columns.Count); - Assert.AreEqual(allRows.Length, rows.Count); - Assert.AreEqual(allRows[0][0], rows[0]["id"]); - Assert.AreEqual(allRows[0][1], rows[0]["name"]); - Assert.AreEqual(allRows[0][2], rows[0]["age"]); - Assert.AreEqual(allRows[0][3], rows[0]["additionalinfo"]); - Assert.AreEqual((sbyte)42, rows[0]["a_number"]); - Assert.AreEqual("43", rows[0]["a_string"]); - } - - [Test] - public void CountAllColumns() - { - var table = testSchema.GetTable("test"); - var select = ExecuteSelectStatement(table.Select("count(*) + 10")); - var rows = select.FetchAll(); - Assert.That(select.Columns, Has.One.Items); - Assert.That(rows, Has.One.Items); - Assert.AreEqual(allRows.Length + 10, (long)rows[0][0]); - } - - [Test] - public void MultipleBind() - { - object[] validationRow = allRows[1]; - var table = testSchema.GetTable("test"); - var select = ExecuteSelectStatement(table.Select().Where("Name = :nAme && Age = :aGe").Bind("agE", validationRow[2]).Bind("naMe", validationRow[1])); - var rows = select.FetchAll(); - Assert.That(rows, Has.One.Items); - Assert.AreEqual(validationRow[1], rows[0]["namE"]); - Assert.AreEqual(validationRow[2], rows[0]["AGe"]); - } - - [Test] - public void DatetimeAndMicroseconds() - { - ExecuteSQL("CREATE TABLE test.testDate (id INT, name VARCHAR(45), birthday DATETIME(6))"); - ExecuteSQL("INSERT INTO test.testDate VALUES(1, 'JOHN', '1985-10-21 16:34:22.123456')"); - ExecuteSQL("INSERT INTO test.testDate VALUES(1, 'BILL', '1985-10-21 10:00:45.987')"); - var rows = ExecuteSelectStatement(GetSession().GetSchema("test").GetTable("testDate").Select()).FetchAll(); - Assert.AreEqual(2, rows.Count); - Assert.AreEqual(new DateTime(1985, 10, 21, 16, 34, 22).AddTicks(1234560), (DateTime)rows[0]["birthday"]); - Assert.AreEqual(new DateTime(1985, 10, 21, 10, 0, 45).AddTicks(9870000), (DateTime)rows[1]["birthday"]); - } - - [Test] - public void DatetimeAndMilliseconds() - { - ExecuteSQL("CREATE TABLE test.testDate2 (id INT, name VARCHAR(45), birthday DATETIME(3))"); - ExecuteSQL("INSERT INTO test.testDate2 VALUES(1, 'JOHN', '1985-10-21 16:34:22.123456')"); - ExecuteSQL("INSERT INTO test.testDate2 VALUES(1, 'BILL', '1985-10-21 10:00:45.098')"); - var rows = ExecuteSelectStatement(GetSession().GetSchema("test").GetTable("testDate2").Select()).FetchAll(); - Assert.AreEqual(2, rows.Count); - Assert.AreEqual(new DateTime(1985, 10, 21, 16, 34, 22).AddTicks(1230000), (DateTime)rows[0]["birthday"]); - Assert.AreEqual(new DateTime(1985, 10, 21, 10, 0, 45).AddTicks(980000), (DateTime)rows[1]["birthday"]); - } - - [Test] - public void RowLockingNotSupportedInOlderVersions() - { - if (session.InternalSession.GetServerVersion().isAtLeast(8, 0, 3)) return; - - Table table = session.Schema.GetTable("test"); - - Exception ex = Assert.Throws(() => ExecuteSelectStatement(table.Select().LockShared())); - Assert.AreEqual("This functionality is only supported from server version 8.0.3 onwards.", ex.Message); - - ex = Assert.Throws(() => ExecuteSelectStatement(table.Select().LockExclusive())); - Assert.AreEqual("This functionality is only supported from server version 8.0.3 onwards.", ex.Message); - } - - [Test] - public void SimpleSharedLock() - { - if (!session.InternalSession.GetServerVersion().isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); - - ExecuteSQLStatement(session.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); - using (var session2 = MySQLX.GetSession(ConnectionString)) - { - ExecuteSQLStatement(session2.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); - Table table = session.Schema.GetTable("test"); - Table table2 = session2.GetSchema("test").GetTable("test"); - - ExecuteSQLStatement(session.SQL("START TRANSACTION")); - RowResult rowResult = ExecuteSelectStatement(table.Select().Where("id = 1").LockShared()); - Assert.That(rowResult.FetchAll(), Has.One.Items); - - ExecuteSQLStatement(session2.SQL("START TRANSACTION")); - // Should return immediately since row isn't locked. - rowResult = ExecuteSelectStatement(table2.Select().Where("id = 2").LockShared()); - Assert.That(rowResult.FetchAll(), Has.One.Items); - // Should return immediately due to LockShared() allows reading by other sessions. - rowResult = ExecuteSelectStatement(table2.Select().Where("id = 1").LockShared()); - Assert.That(rowResult.FetchAll(), Has.One.Items); - - ExecuteSQLStatement(session.SQL("ROLLBACK")); - ExecuteSQLStatement(session2.SQL("ROLLBACK")); - } - } - - [Test] - public void SimpleExclusiveLock() - { - if (!session.InternalSession.GetServerVersion().isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); - - ExecuteSQLStatement(session.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); - using (var session2 = MySQLX.GetSession(ConnectionString)) - { - ExecuteSQLStatement(session2.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); - Table table = session.Schema.GetTable("test"); - ExecuteSQLStatement(session.SQL("CREATE UNIQUE INDEX myIndex ON test.test (id)")); - Table table2 = session2.GetSchema("test").GetTable("test"); - - ExecuteSQLStatement(session.SQL("START TRANSACTION")); - RowResult rowResult = ExecuteSelectStatement(table.Select().Where("id = 1").LockExclusive()); - Assert.That(rowResult.FetchAll(), Has.One.Items); - - ExecuteSQLStatement(session2.SQL("START TRANSACTION")); - // Should return immediately since row isn't locked. - rowResult = ExecuteSelectStatement(table2.Select().Where("id = 2").LockExclusive()); - Assert.That(rowResult.FetchAll(), Has.One.Items); - // Session2 blocks due to to LockExclusive() not allowing to read locked rows. - ExecuteSQLStatement(session2.SQL("SET SESSION innodb_lock_wait_timeout=1")); - Exception ex = Assert.Throws(() => ExecuteSelectStatement(table2.Select().Where("id = 1").LockExclusive())); - Assert.AreEqual("Lock wait timeout exceeded; try restarting transaction", ex.Message); - - ExecuteSQLStatement(session.SQL("ROLLBACK")); - ExecuteSQLStatement(session2.SQL("ROLLBACK")); - } - } - - [Test] - public void SharedLockForbidsToModifyDocuments() - { - if (!session.InternalSession.GetServerVersion().isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); - - ExecuteSQLStatement(session.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); - using (var session2 = MySQLX.GetSession(ConnectionString)) - { - ExecuteSQLStatement(session2.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); - Table table = session.Schema.GetTable("test"); - Table table2 = session2.GetSchema("test").GetTable("test"); - - ExecuteSQLStatement(session.SQL("START TRANSACTION")); - RowResult rowResult = ExecuteSelectStatement(table.Select().Where("id = 1").LockShared()); - Assert.That(rowResult.FetchAll(), Has.One.Items); - - ExecuteSQLStatement(session2.SQL("START TRANSACTION")); - // Reading the same row is allowed with LockShared(). - rowResult = ExecuteSelectStatement(table2.Select().Where("id = 1")); - Assert.That(rowResult.FetchAll(), Has.One.Items); - - // Modify() is allowed for non-locked rows. - Result result = ExecuteUpdateStatement(table2.Update().Where("id = 2").Set("age", 2)); - Assert.AreEqual(1, result.AffectedItemsCount); - // Session1 blocks, Modify() is not allowed for locked rows. - ExecuteSQLStatement(session2.SQL("SET SESSION innodb_lock_wait_timeout=1")); - Exception ex = Assert.Throws(() => ExecuteUpdateStatement(table2.Update().Where("id = 1").Set("age", 2))); - Assert.AreEqual("Lock wait timeout exceeded; try restarting transaction", ex.Message); - - ExecuteSQLStatement(session.SQL("ROLLBACK")); - // Modify() is allowed since row isn't locked anymore. - ExecuteUpdateStatement(table2.Update().Where("id = 1").Set("age", 2)); - ExecuteSQLStatement(session2.SQL("COMMIT")); - } - } - - [Test] - public void ExclusiveLockForbidsToModifyDocuments() - { - if (!session.InternalSession.GetServerVersion().isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); - - ExecuteSQLStatement(session.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); - using (var session2 = MySQLX.GetSession(ConnectionString)) - { - ExecuteSQLStatement(session2.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); - Table table = session.Schema.GetTable("test"); - Table table2 = session2.GetSchema("test").GetTable("test"); - - ExecuteSQLStatement(session.SQL("START TRANSACTION")); - RowResult rowResult = ExecuteSelectStatement(table.Select().Where("id = 1").LockExclusive()); - Assert.That(rowResult.FetchAll(), Has.One.Items); - - ExecuteSQLStatement(session2.SQL("START TRANSACTION")); - - // Modify() is allowed for non-locked rows. - Result result = ExecuteUpdateStatement(table2.Update().Where("id = 2").Set("age", 2)); - Assert.AreEqual(1, result.AffectedItemsCount); - // Session1 blocks, Modify() is not allowed for locked rows. - ExecuteSQLStatement(session2.SQL("SET SESSION innodb_lock_wait_timeout=1")); - Exception ex = Assert.Throws(() => ExecuteUpdateStatement(table2.Update().Where("id = 1").Set("age", 2))); - Assert.AreEqual("Lock wait timeout exceeded; try restarting transaction", ex.Message); - - ExecuteSQLStatement(session.SQL("ROLLBACK")); - // Modify() is allowed since row isn't locked anymore. - ExecuteUpdateStatement(table2.Update().Where("id = 1").Set("age", 2)); - ExecuteSQLStatement(session2.SQL("COMMIT")); - } - } - - [Test] - public void SharedLockAfterExclusiveLock() - { - if (!session.InternalSession.GetServerVersion().isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); - - ExecuteSQLStatement(session.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); - using (var session2 = MySQLX.GetSession(ConnectionString)) - { - ExecuteSQLStatement(session2.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); - Table table = session.Schema.GetTable("test"); - ExecuteSQLStatement(session.SQL("CREATE UNIQUE INDEX myIndex ON test.test (id)")); - Table table2 = session2.GetSchema("test").GetTable("test"); - - ExecuteSQLStatement(session.SQL("START TRANSACTION")); - RowResult rowResult = ExecuteSelectStatement(table.Select().Where("id = 1").LockExclusive()); - Assert.That(rowResult.FetchAll(), Has.One.Items); - - ExecuteSQLStatement(session2.SQL("START TRANSACTION")); - // Should return immediately since row isn't locked. - rowResult = ExecuteSelectStatement(table2.Select().Where("id = 2").LockShared()); - Assert.That(rowResult.FetchAll(), Has.One.Items); - // Session2 blocks due to LockExclusive() not allowing to read locked rows. - ExecuteSQLStatement(session2.SQL("SET SESSION innodb_lock_wait_timeout=1")); - Exception ex = Assert.Throws(() => ExecuteSelectStatement(table2.Select().Where("id = 1").LockShared())); - Assert.AreEqual("Lock wait timeout exceeded; try restarting transaction", ex.Message); - - // Session unlocks rows. - ExecuteSQLStatement(session.SQL("ROLLBACK")); - // Row can now be recovered. - rowResult = ExecuteSelectStatement(table2.Select().Where("id = 1").LockShared()); - Assert.That(rowResult.FetchAll(), Has.One.Items); - ExecuteSQLStatement(session2.SQL("ROLLBACK")); - } - } - - [Test] - public void ExclusiveLockAfterSharedLock() - { - if (!session.InternalSession.GetServerVersion().isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); - - ExecuteSQLStatement(session.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); - using (var session2 = MySQLX.GetSession(ConnectionString)) - { - ExecuteSQLStatement(session2.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); - Table table = session.Schema.GetTable("test"); - ExecuteSQLStatement(session.SQL("CREATE UNIQUE INDEX myIndex ON test.test (id)")); - Table table2 = session2.GetSchema("test").GetTable("test"); - - ExecuteSQLStatement(session.SQL("START TRANSACTION")); - RowResult rowResult = ExecuteSelectStatement(table.Select().Where("id in (1, 3)").LockShared()); - Assert.AreEqual(2, rowResult.FetchAll().Count); - - ExecuteSQLStatement(session2.SQL("START TRANSACTION")); - // Should return immediately since row isn't locked. - rowResult = ExecuteSelectStatement(table2.Select().Where("id = 2").LockExclusive()); - // Should return immediately due to LockShared() allows reading by other sessions. - rowResult = ExecuteSelectStatement(table2.Select().Where("id = 2").LockShared()); - Assert.That(rowResult.FetchAll(), Has.One.Items); - // Session2 blocks due to to LockExclusive() not allowing to read locked rows. - ExecuteSQLStatement(session2.SQL("SET SESSION innodb_lock_wait_timeout=1")); - Exception ex = Assert.Throws(() => ExecuteSelectStatement(table2.Select().Where("id = 1").LockExclusive())); - Assert.AreEqual("Lock wait timeout exceeded; try restarting transaction", ex.Message); - - // Session unlocks rows. - ExecuteSQLStatement(session.SQL("ROLLBACK")); - rowResult = ExecuteSelectStatement(table2.Select().Where("id = 1").LockExclusive()); - Assert.That(rowResult.FetchAll(), Has.One.Items); - ExecuteSQLStatement(session2.SQL("ROLLBACK")); - } - } - - [Test] - public void SelectWithInOperator() - { - Table table = testSchema.GetTable("test"); - Assert.AreEqual(3, ExecuteSelectStatement(table.Select()).FetchAll().Count); - - Assert.AreEqual(2, ExecuteSelectStatement(table.Select().Where("name IN (\"jonh doe\", \"milton green\")")).FetchAll().Count); - Assert.That(ExecuteSelectStatement(table.Select().Where("name NOT IN (\"jonh doe\", \"milton green\")")).FetchAll(), Has.One.Items); - CollectionAssert.IsEmpty(ExecuteSelectStatement(table.Select().Where("name IN (\"\", \"\")")).FetchAll()); - CollectionAssert.IsEmpty(ExecuteSelectStatement(table.Select().Where("\"\" IN (1,2,3)")).FetchAll()); - CollectionAssert.IsEmpty(ExecuteSelectStatement(table.Select().Where("name IN ('', '')")).FetchAll()); - CollectionAssert.IsEmpty(ExecuteSelectStatement(table.Select().Where("'' IN (1,2,3)")).FetchAll()); - Assert.AreEqual(3, ExecuteSelectStatement(table.Select().Where("'' IN ('')")).FetchAll().Count); - - Assert.Throws(() => ExecuteSelectStatement(table.Select().Where("name NOT IN [\"jonh doe\", \"milton green\"]")).FetchAll()); - Assert.Throws(() => ExecuteSelectStatement(table.Select().Where("a IN [3]")).FetchAll()); - Assert.Throws(() => ExecuteSelectStatement(table.Select().Where("3 IN a")).FetchAll()); - } - - [Test] - public void Grouping() - { - ExecuteSQLStatement(GetSession().SQL("set sql_mode = 'STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION';")); - Table table = testSchema.GetTable("test"); - - // Insert additonal users. - object[][] additionalUsers = { - new object[] { 4, "mary weinstein", 24, null }, - new object[] { 5, "jerry pratt", 45, null }, - new object[] { 6, "hugh jackman", 20, null }, - new object[] { 7, "elizabeth olsen", 31, null } - }; - var statement = table.Insert(); - foreach (object[] user in additionalUsers) - { - statement = statement.Values(user); - } - - Assert.AreEqual(4, ExecuteInsertStatement(statement).AffectedItemsCount); - - // GroupBy returns 5 rows since age 45 and 24 is repeated. - var result = ExecuteSelectStatement(table.Select().GroupBy("age")); - Assert.AreEqual(5, result.FetchAll().Count); - - // GroupBy with null. - result = ExecuteSelectStatement(table.Select("id as ID", "name as Name", "age as Age").GroupBy(null)); - Assert.AreEqual(7, result.FetchAll().Count); - result = ExecuteSelectStatement(table.Select("id as ID", "name as Name", "age as Age").GroupBy(null, null)); - Assert.AreEqual(7, result.FetchAll().Count); - result = ExecuteSelectStatement(table.Select("id as ID", "name as Name", "age as Age").GroupBy(null, "age")); - Assert.AreEqual(5, result.FetchAll().Count); - - // Having operation. - // Having reduces the original 5 rows to 3 since 2 rows have a cnt=2, due to the repeated names. - result = ExecuteSelectStatement(table.Select("id", "count(name) as cnt", "age").GroupBy("age").Having("cnt = 1")); - Assert.AreEqual(3, result.FetchAll().Count); - - // Having with null. - result = ExecuteSelectStatement(table.Select("id as ID", "count(name) as cnt", "age as Age").GroupBy("age").Having(null)); - Assert.AreEqual(5, result.FetchAll().Count); - - // GroupBy with invalid field name. - var ex = Assert.Throws(() => ExecuteSelectStatement(table.Select("id as ID", "name as Name", "age as Age").GroupBy("none"))); - Assert.AreEqual("Unknown column 'none' in 'group statement'", ex.Message); - - // GroupBy with empty strings. - var ex2 = Assert.Throws(() => ExecuteSelectStatement(table.Select("id as ID", "name as Name", "age as Age").GroupBy(""))); - Assert.AreEqual("No more tokens when expecting one at token pos 0", ex2.Message); - ex2 = Assert.Throws(() => ExecuteSelectStatement(table.Select("id as ID", "name as Name", "age as Age").GroupBy(" "))); - Assert.AreEqual("No more tokens when expecting one at token pos 0", ex2.Message); - ex2 = Assert.Throws(() => ExecuteSelectStatement(table.Select("id as ID", "name as Name", "age as Age").GroupBy(string.Empty))); - Assert.AreEqual("No more tokens when expecting one at token pos 0", ex2.Message); - - // Having with invalid field name. - ex = Assert.Throws(() => ExecuteSelectStatement(table.Select("id as ID", "count(name) as cnt", "age as Age").GroupBy("age").Having("none = 1"))); - Assert.AreEqual("Unknown column 'none' in 'having clause'", ex.Message); - - // Having with empty strings. - ex2 = Assert.Throws(() => ExecuteSelectStatement(table.Select("id as ID", "count(name) as cnt", "age as Age").GroupBy("age").Having(""))); - Assert.AreEqual("Unable to parse query ''", ex2.Message); - Assert.AreEqual("No more tokens when expecting one at token pos 0", ex2.InnerException.Message); - ex2 = Assert.Throws(() => ExecuteSelectStatement(table.Select("id as ID", "count(name) as cnt", "age as Age").GroupBy("age").Having(" "))); - Assert.AreEqual("Unable to parse query ' '", ex2.Message); - Assert.AreEqual("No more tokens when expecting one at token pos 0", ex2.InnerException.Message); - ex2 = Assert.Throws(() => ExecuteSelectStatement(table.Select("id as ID", "count(name) as cnt", "age as Age").GroupBy("age").Having(string.Empty))); - Assert.AreEqual("Unable to parse query ''", ex2.Message); - Assert.AreEqual("No more tokens when expecting one at token pos 0", ex2.InnerException.Message); - } - - /// - /// Bug-29838254 - /// RESULTSET ERROR WHEN SELECT IS ISSUED WITH IN OPERATOR WITH BLANKS WITH 8.0.17 SERVER-C/NET8.0.17TRUNK - /// - [Test] - public void SelectWithInBlanksAndBrackets() - { - Session session = GetSession(); - Schema schema = session.GetSchema("test"); - object[][] allRows = - { - new object[] {1, "john doe", 38}, - new object[] {2, "milton green", 45}, - new object[] {3, "milton blue", 46}, - new object[] {4, "milton red", 47}, - new object[] {5, "milton yellow", 48}, - new object[] {6, "milton check", 49}, - new object[] {7, "milton pink", 14}, - new object[] {8, "milton beize", 25}, - new object[] {9, "milton silver", 35}, - new object[] {10, "milton city", 65} - }; - session.SQL("USE test").Execute(); - session.SQL("DROP table if exists test").Execute(); - var r = session.SQL("CREATE TABLE test.test(id INT,name VARCHAR(45), age INT)").Execute(); - var rows = r.HasData ? r.FetchAll() : null; - testSchema = session.GetSchema("test"); - var insertStatement = testSchema.GetTable("test").Insert(); - var rowsToInsert = 10; - for (var i = 0; i < rowsToInsert; i++) - insertStatement.Values(allRows[i]); - insertStatement.Execute(); - var table = testSchema.GetTable("test"); - int count = 0; - - //Exception expected when square brackets are used instead of parenthesis - Assert.Throws(() => table.Select().Where("name IN ['', ' ']").Execute().FetchAll()); - - // Test using parenthesis should return result - count = table.Select().Where("name IN (\"john doe\", \"milton green\")").Execute().FetchAll().Count; - Assert.True(count > 0); - - // Using parenthesis should return empty resultset for empty parameters - count = table.Select().Where("name IN ('', ' ')").Execute().FetchAll().Count; - Assert.True(count == 0); - } - - [TestCase(":hobbies IN additionalinfo->$.hobbies", "hobbies", "painting", 3)] - [TestCase(":hobbies IN additionalinfo->$.hobbies", "hobbies", "[\"boxing\", \"running\"]", 0)] - [TestCase("[\"boxing\", \"running\"] IN additionalinfo->$.hobbies", null, null, 2)] - [TestCase(":hobbies IN additionalinfo$.hobbies", "hobbies", "painting", 3)] - public void InOperatorBindingJson(string condition, string bind, string value, int id) - { - Table table = testSchema.GetTable("test"); - Assert.AreEqual(3, ExecuteSelectStatement(table.Select()).FetchAll().Count); - - var stmt = table.Select().Where(condition); - if (bind != null) stmt.Bind(bind, value); - var result = ExecuteSelectStatement(stmt).FetchAll(); - Assert.AreEqual(id == 0 ? 0 : 1, result.Count); - if (id > 0) - { - Assert.AreEqual(id, result[0]["id"]); - } - } - - #region WL14389 - - [Test, Description("Reading locked document(lock_shared) in a table using lock_exclusive with DEFAULT waiting option.")] - public void ExclusiveLockAfterSharedLockDefaultWaiting() - { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher"); - - session.SQL("DROP TABLE IF EXISTS test.test").Execute(); - session.SQL("CREATE TABLE test.test (id INT, a INT)").Execute(); - var table1 = testSchema.GetTable("test"); - table1.Insert("id", "a").Values(1, 1).Values(2, 2).Values(3, 3).Execute(); - ExecuteSQLStatement(session.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); - using (var session2 = MySQLX.GetSession(ConnectionString)) - { - ExecuteSQLStatement(session2.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); - var table = session.Schema.GetTable("test"); - session.SQL("CREATE UNIQUE INDEX myIndex ON test.test (id)").Execute(); - var table2 = session2.GetSchema("test").GetTable("test"); - - ExecuteSQLStatement(session.SQL("START TRANSACTION")); - var rowResult = ExecuteSelectStatement(table.Select().Where("id = 1").LockShared()); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); - - ExecuteSQLStatement(session2.SQL("START TRANSACTION")); - - // Should return immediately since document isn't locked. - rowResult = table2.Select().Where("id = 2").LockExclusive(LockContention.Default).Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); - - // Session2 blocks as LockExclusive trying to access locked document - ExecuteSQLStatement(session2.SQL("SET SESSION innodb_lock_wait_timeout=1")); - Exception ex = Assert.Throws(() => ExecuteSelectStatement(table2.Select().Where("id = 1").LockExclusive(LockContention.Default))); - Assert.AreEqual("Lock wait timeout exceeded; try restarting transaction", ex.Message); - - // Session2 blocks due to to LockShared() not allowing to modify locked documents. - Result result1; - ex = Assert.Throws(() => result1 = table2.Update().Where("id = 1").Set("a", 2).Execute()); - Assert.AreEqual("Lock wait timeout exceeded; try restarting transaction", ex.Message); - - // Session2 returns immediately as session is committed. - session.Commit(); - var result = table2.Update().Where("id = 1").Set("a", 2).Execute(); - Assert.AreEqual(1, result.AffectedItemsCount); - - ExecuteSQLStatement(session.SQL("ROLLBACK")); - ExecuteSQLStatement(session2.SQL("ROLLBACK")); - } - } - - [Test, Description("Reading exclusively locked document in a table using lock_shared with NOWAIT waiting option. ")] - public void SharedLockAfterExclusiveLockWithNoWait() - { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher"); - - session.SQL("DROP TABLE IF EXISTS test.test").Execute(); - session.SQL("CREATE TABLE test.test (id INT, a INT)").Execute(); - var table1 = testSchema.GetTable("test"); - table1.Insert("id", "a").Values(1, 1).Values(2, 2).Values(3, 3).Execute(); - ExecuteSQLStatement(session.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); - using (var session2 = MySQLX.GetSession(ConnectionString)) - { - ExecuteSQLStatement(session2.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); - var table = session.Schema.GetTable("test"); - session.SQL("CREATE UNIQUE INDEX myIndex ON test.test (id)").Execute(); - var table2 = session2.GetSchema("test").GetTable("test"); - - session.SQL("START TRANSACTION").Execute(); - var rowResult = table.Select().Where("id = 1").LockExclusive().Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); - - session2.SQL("START TRANSACTION").Execute(); - // Should return immediately since document isn't locked. - rowResult = table2.Select().Where("id = 2").LockShared(LockContention.NoWait).Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); - - // Session2 blocks due to to LockExclusive() not allowing to read locked documents. - ExecuteSQLStatement(session2.SQL("SET SESSION innodb_lock_wait_timeout=1")); - Assert.Throws(() => ExecuteSelectStatement(table2.Select().Where("id = 1").LockShared(LockContention.NoWait))); - - // Session2 blocks due to to LockExclusive() not allowing to modify locked documents. - Result result1; - Assert.Throws(() => result1 = table2.Update().Where("id = 1").Set("a", 2).Execute()); - - session.Commit(); - var result = table2.Update().Where("id = 1").Set("a", 2).Execute(); - Assert.AreEqual(1, result.AffectedItemsCount); - - ExecuteSQLStatement(session.SQL("ROLLBACK")); - ExecuteSQLStatement(session2.SQL("ROLLBACK")); - } - } - - [Test, Description("Testing Non ASCII characters for utf8mb4 characterset")] - public void NonAsciiCharsForUtf8mb4() - { - //Bug28261283 - string record = "{\"name\": \"New\",\"age\": 4 , "; - string name1 = "\u201C\u2199\u2197\u2196\u2198\u201D"; - string name2 = "{\"age\": 1, \"misc\": 1.2, \"name\": \"\u201C\u2199\u2197\u2196\u2198\u201D\"}"; - - session.SQL($"use {schemaName}").Execute(); - session.SQL("drop table if exists newTable").Execute(); - session.SQL("create table newTable(c1 varchar(200), c2 JSON) CHARACTER SET utf8mb4").Execute(); - var db = session.GetSchema(schemaName); - Table tabNew = db.GetTable("newTable"); - - tabNew.Insert("c1", "c2").Values("\u201C\u2199\u2197\u2196\u2198\u201D", "{ \"name\": \"\u201C\u2199\u2197\u2196\u2198\u201D\", \"age\": 1 , \"misc\": 1.2}").Execute(); - tabNew.Insert().Values("abcNew£¢€©§°√", "{ \"name\": \"abcNew£¢€©§°√\", \"age\": 2 , \"misc\": 1.2}").Execute(); - RowResult result = tabNew.Select("c1", "c2").Where("c1 ='\u201C\u2199\u2197\u2196\u2198\u201D'").Execute(); - var r1 = result.FetchOne(); - Assert.AreEqual(name1, r1[0].ToString());//"“↙↗↖↘”" - Assert.AreNotEqual(name2, r1[1].ToString());//"{\"age\": 1, \"misc\": 1.2, \"name\": \"??????????????????\"}" - var t = session.SQL("SELECT c1, CONVERT(c2 USING utf8mb4) FROM newTable WHERE c1 = '\u201C\u2199\u2197\u2196\u2198\u201D'").Execute(); - r1 = t.FetchOne(); - Assert.AreEqual(name1, r1[0].ToString());//"“↙↗↖↘”" - Assert.AreEqual(name2, r1[1].ToString());//"{\"age\": 1, \"misc\": 1.2, \"name\": \"??????????????????\"}" - - Collection coll = CreateCollection("test"); - - int klen = 1024 * 64; - string[] key = new string[klen]; - int dlen = 1024 * 100; - string[] data = new string[dlen]; - Array.Resize(ref key, 'S'); - Array.Resize(ref data, '$'); - string unicodeString = "Maths use \u03a0 (Pi) for calculations"; - // You can convert a string into a byte array - byte[] asciiBytes = Encoding.ASCII.GetBytes(unicodeString); - // You can convert a byte array into a char array - char[] asciiChars = Encoding.ASCII.GetChars(asciiBytes); - string asciiString = new string(asciiChars); - - record = record + "\""; - record = record + "\":\""; - record = record + asciiString; - record = record + "\"}"; - - Result r = coll.Add("{ \"name\": \"\u201C\u2199\u2197\u2196\u2198\u201D\", \"age\": 4 , \"misc\": 1.2}"). - Add("{ \"name\": \"xyz£¢€©§°√\", \"age\": 6 , \"misc\": 10}").Execute(); - var docs = coll.Find("name = '\u201C\u2199\u2197\u2196\u2198\u201D' and age>= 4 and age <= 6").Execute(); - DbDoc doc = docs.FetchOne(); - Assert.AreEqual(name1, doc["name"]); - session.SQL("drop table if exists test").Execute(); - session.SQL("drop table if exists newTable").Execute(); - } - - [Test, Description("Test MySQLX plugin Datatype Tests")] - public void DatatypesOnCreateTable() - { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher"); - - session.SQL($"use {schemaName}"); - session.SQL("create table test1(c1 int,c2 double GENERATED ALWAYS AS (c1*101/102) Stored COMMENT 'First Gen Col',c3 Json GENERATED ALWAYS AS (concat('{\"F1\":',c1,'}')) VIRTUAL COMMENT 'Second Gen /**/Col', c4 bigint GENERATED ALWAYS as (c1*10000) VIRTUAL UNIQUE KEY Comment '3rd Col' NOT NULL)").Execute(); - session.SQL("insert into test1(c1) values(1000)").Execute(); - RowResult r = session.GetSchema(schemaName).GetTable("test1").Select("c1").Execute(); - r.FetchAll(); - Assert.AreEqual("1000", r.Rows[0][0].ToString(), "Matching the values"); - session.SQL("drop table if exists test1").Execute(); - } - - [Test, Description("Test MySQLX plugin Table Expression using Where")] - public void TableExpressionWhereBindGroupBy() - { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher"); - - string match = null; - session.SQL("create table test1(name VARCHAR(40), age INT)").Execute(); - Table table = session.GetSchema(schemaName).GetTable("test1"); - - for (int i = 10; i < 30; i++) - { - int j = 1; - string name = RandomString(i); - var result = table.Insert("name", "age") - .Values(name, i) - .Execute(); - if (i == 28) - match = name; - Assert.AreEqual((ulong)j, result.AffectedItemsCount, "Matching the values"); - j = j + 1; - } - - var whereResult = table.Select("name", "age").Where("age == 28").Execute(); - int rowCount = whereResult.FetchAll().Count; - Assert.AreEqual(1, rowCount, "Matching the row count"); - Assert.AreEqual(match, whereResult.Rows.ToArray()[0][0].ToString(), "Matching the name"); - - whereResult = table.Select("name", "age").Where("age == 100").Execute(); - rowCount = whereResult.FetchAll().Count; - Assert.AreEqual(0, rowCount, "Matching that there is no such value "); - - whereResult = table.Select().Where("name like :name").Bind("nAme", "%ABCDEFGHIJ%").Execute(); - rowCount = whereResult.FetchAll().Count; - for (int i = 0; i < whereResult.Rows.Count; i++) - { - var res = whereResult.Rows.ToArray()[i][0]; - StringAssert.Contains("ABCDEFGHIJ", res.ToString()); - } - - whereResult = table.Select().Where("name like :name").Bind("nAme", "%ABCD%").Execute(); - rowCount = whereResult.FetchAll().Count; - for (int j = 0; j < whereResult.Rows.Count; j++) - { - var res = whereResult.Rows.ToArray()[j][0]; - StringAssert.Contains("ABCD", res.ToString()); - } - } - - [Test, Description("Test MySQLX plugin Table")] - public void TableSelectFetchValuesInOrder() - { - ExecuteSQL("drop table if exists test1"); - ExecuteSQL("create table test1(name VARCHAR(40), age INT)"); - Table table = session.GetSchema(schemaName).GetTable("test1"); - var result = table.Insert("name", "age") - .Values("MARK", 34) - .Execute(); - - Assert.AreEqual((ulong)1, result.AffectedItemsCount, "Matching the values"); - result = table.Insert("name", "age") - .Values("richie", 16) - .Execute(); - Assert.AreEqual((ulong)1, result.AffectedItemsCount, "Matching the values"); - var selectResult = table.Select().Execute(); - - while (selectResult.Next()) ; - Assert.AreEqual(2, selectResult.Rows.Count, "Matching the row count"); - Assert.AreEqual("MARK", selectResult.Rows.ToArray()[0][0].ToString(), "Matching the value MARK"); - Assert.AreEqual(34, (int)selectResult.Rows.ToArray()[0][1], "Matching the age 34"); - Assert.AreEqual("richie", selectResult.Rows.ToArray()[1][0].ToString(), "Matching the value richie"); - Assert.AreEqual(16, (int)selectResult.Rows.ToArray()[1][1], "Matching the age 16"); - - var result1 = testSchema.GetTable("test").Select().OrderBy("age desc").Execute(); - int rowCount = result1.FetchAll().Count; - for (int i = 0; i < rowCount; i++) - { - Assert.AreEqual("45", result1.Rows[0][2].ToString(), "Matching the values"); - Assert.AreEqual("38", result1.Rows[1][2].ToString(), "Matching the values"); - Assert.AreEqual("24", result1.Rows[2][2].ToString(), "Matching the values"); - } - - result1 = testSchema.GetTable("test").Select().OrderBy("age asc").Execute(); - rowCount = result1.FetchAll().Count; - for (int i = 0; i < rowCount; i++) - { - Assert.AreEqual("24", result1.Rows[0][2].ToString(), "Matching the values"); - Assert.AreEqual("38", result1.Rows[1][2].ToString(), "Matching the values"); - Assert.AreEqual("45", result1.Rows[2][2].ToString(), "Matching the values"); - } - } - - [Test, Description("Reading exclusively locked document in a table using lock_exclusive with NOWAIT waiting option. ")] - public void DoubleExclusiveLockWithNoWait() - { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher"); - - session.SQL("DROP TABLE IF EXISTS test.test").Execute(); - session.SQL("CREATE TABLE test.test (id INT, a INT)").Execute(); - var table1 = testSchema.GetTable("test"); - table1.Insert("id", "a").Values(1, 1).Values(2, 2).Values(3, 3).Execute(); - ExecuteSQLStatement(session.SQL("SET autocommit = 0")); - using (var session2 = MySQLX.GetSession(ConnectionString)) - { - ExecuteSQLStatement(session2.SQL("SET autocommit = 0")); - var table = testSchema.GetTable("test"); - session.SQL("CREATE UNIQUE INDEX myIndex ON test.test (id)").Execute(); - var table2 = session2.GetSchema("test").GetTable("test"); - - session.SQL("START TRANSACTION").Execute(); - var rowResult = table.Select().Where("id = 1").LockExclusive().Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); - - session2.SQL("START TRANSACTION").Execute(); - // Should return immediately since document isn't locked. - rowResult = table2.Select().Where("id = 2").LockExclusive(LockContention.NoWait).Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); - - // Session2 blocks due to to LockExclusive() not allowing to read locked documents. - ExecuteSQLStatement(session2.SQL("SET SESSION innodb_lock_wait_timeout=1")); - Assert.Throws(() => ExecuteSelectStatement(table2.Select().Where("id = 1").LockShared(LockContention.NoWait))); - - // Session2 blocks due to to LockExclusive() not allowing to modify locked documents. - Result result1; - Assert.Throws(() => result1 = table2.Update().Where("id = 1").Set("a", 2).Execute()); - - // Session2 returns immediately as session is committed. - session.Commit(); - var result = table2.Update().Where("id = 1").Set("a", 2).Execute(); - Assert.AreEqual(1, result.AffectedItemsCount); - session.SQL("ROLLBACK").Execute(); - session2.SQL("ROLLBACK").Execute(); - } - - ExecuteSQLStatement(session.SQL("SET autocommit = 1")); - } - - [Test, Description("Reading a locked document(lock_shared) in a table using lock_shared with NOWAIT waiting option. ")] - public void DoubleSharedLockWithNoWait() - { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher"); - - session.SQL("DROP TABLE IF EXISTS test.test").Execute(); - session.SQL("CREATE TABLE test.test (id INT, a INT)").Execute(); - var table1 = testSchema.GetTable("test"); - table1.Insert("id", "a").Values(1, 1).Values(2, 2).Values(3, 3).Execute(); - using (var session2 = MySQLX.GetSession(ConnectionString)) - { - var table = session.Schema.GetTable("test"); - var table2 = session2.GetSchema("test").GetTable("test"); - - session.SQL("START TRANSACTION").Execute(); - var rowResult = table.Select().Where("id = 1").LockShared().Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); - - session2.SQL("START TRANSACTION").Execute(); - // Should return immediately since document isn't locked. - rowResult = table2.Select().Where("id = 2").LockShared(LockContention.NoWait).Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); - - // Session2 doesnt block as LockShare trying to read locked(Lock_shared) document - session2.SQL("SET SESSION innodb_lock_wait_timeout=1").Execute(); - rowResult = table2.Select().Where("id = 1").LockShared(LockContention.NoWait).Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); - - // Session2 blocks due to to LockShared() not allowing to modify locked documents. - Result result1; - Assert.Throws(() => result1 = table2.Update().Where("id = 1").Set("a", 2).Execute()); - - // Session2 returns immediately as session is committed. - session.Commit(); - var result = table2.Update().Where("id = 1").Set("a", 2).Execute(); - Assert.AreEqual(1, result.AffectedItemsCount); - session.SQL("ROLLBACK").Execute(); - session2.SQL("ROLLBACK").Execute(); - } - } - - [Test, Description("Reading a locked document(lock_shared) in a table using lock_shared with NOWAIT waiting option. ")] - public void ExclusiveLockAfterSharedLockWithNoWait() - { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher"); - - session.SQL("DROP TABLE IF EXISTS test.test").Execute(); - session.SQL("CREATE TABLE test.test (id INT, a INT)").Execute(); - var table1 = testSchema.GetTable("test"); - table1.Insert("id", "a").Values(1, 1).Values(2, 2).Values(3, 3).Execute(); - - using (var session2 = MySQLX.GetSession(ConnectionString)) - { - var table = session.Schema.GetTable("test"); - session.SQL("CREATE UNIQUE INDEX myIndex ON test.test (id)").Execute(); - var table2 = session2.GetSchema("test").GetTable("test"); - - session.SQL("START TRANSACTION").Execute(); - var rowResult = table.Select().Where("id = 1").LockShared().Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); - - session2.SQL("START TRANSACTION").Execute(); - // Should return immediately since document isn't locked. - rowResult = table2.Select().Where("id = 2").LockExclusive(LockContention.NoWait).Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); - - // Session2 blocks as LockExclusive() trying to access locked(LockShared) documents. - ExecuteSQLStatement(session2.SQL("SET SESSION innodb_lock_wait_timeout=1")); - Assert.Throws(() => ExecuteSelectStatement(table2.Select().Where("id = 1").LockExclusive(LockContention.NoWait))); - - // Session2 blocks due to to LockShared() not allowing to modify locked documents. - Result result1; - Assert.Throws(() => result1 = table2.Update().Where("id = 1").Set("a", 2).Execute()); - - // Session2 returns immediately as session is committed. - session.Commit(); - var result = table2.Update().Where("id = 1").Set("a", 2).Execute(); - Assert.AreEqual(1, result.AffectedItemsCount); - session.SQL("ROLLBACK").Execute(); - session2.SQL("ROLLBACK").Execute(); - } - } - - [Test, Description("Reading exclusively locked document in a table using lock_shared with SKIPLOCK waiting option. ")] - public void SharedLockAfterExclusiveWithSkiplock() - { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher"); - - session.SQL("DROP TABLE IF EXISTS test.test").Execute(); - session.SQL("CREATE TABLE test.test (id INT, a INT)").Execute(); - var table1 = testSchema.GetTable("test"); - table1.Insert("id", "a").Values(1, 1).Values(2, 2).Values(3, 3).Execute(); - - using (var session2 = MySQLX.GetSession(ConnectionString)) - { - var table = session.Schema.GetTable("test"); - session.SQL("CREATE UNIQUE INDEX myIndex ON test.test (id)").Execute(); - var table2 = session2.GetSchema("test").GetTable("test"); - - session.SQL("START TRANSACTION").Execute(); - var rowResult = table.Select().Where("id = 1").LockExclusive().Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); - - session2.SQL("START TRANSACTION").Execute(); - // Should return immediately since document isn't locked. - rowResult = table2.Select().Where("id = 2").LockShared(LockContention.NoWait).Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); - - // Session2 blocks due to to LockExclusive() not allowing to read locked documents. - ExecuteSQLStatement(session2.SQL("SET SESSION innodb_lock_wait_timeout=1")); - rowResult = table2.Select().Where("id = 1").LockShared(LockContention.SkipLocked).Execute(); - Assert.AreEqual(0, rowResult.FetchAll().Count, "Matching the document ID"); - - // Session2 blocks due to to LockExclusive() not allowing to modify locked documents. - Result result1; - Assert.Throws(() => result1 = table2.Update().Where("id = 1").Set("a", 2).Execute()); - - // Session2 returns immediately as session is committed. - session.Commit(); - var result = table2.Update().Where("id = 1").Set("a", 2).Execute(); - Assert.AreEqual(1, (int)result.AffectedItemsCount, "Matching the record count"); - - session.SQL("ROLLBACK").Execute(); - session2.SQL("ROLLBACK").Execute(); - } - } - - [Test, Description("Reading exclusively locked document in a table using lock_exclusive with SKIPLOCK waiting option.")] - public void DoubleExclusiveLockWithSkiplock() - { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher"); - - session.SQL("DROP TABLE IF EXISTS test.test").Execute(); - session.SQL("CREATE TABLE test.test (id INT, a INT)").Execute(); - var table1 = testSchema.GetTable("test"); - table1.Insert("id", "a").Values(1, 1).Values(2, 2).Values(3, 3).Execute(); - - using (var session2 = MySQLX.GetSession(ConnectionString)) - { - var table = session.Schema.GetTable("test"); - session.SQL("CREATE UNIQUE INDEX myIndex ON test.test (id)").Execute(); - var table2 = session2.GetSchema("test").GetTable("test"); - - session.SQL("START TRANSACTION").Execute(); - var rowResult = table.Select().Where("id = 1").LockExclusive().Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); - - session2.SQL("START TRANSACTION").Execute(); - // Should return immediately since document isn't locked. - rowResult = table2.Select().Where("id = 2").LockExclusive(LockContention.SkipLocked).Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); - - // Session2 doesn't block as SKIPLOCK used - ExecuteSQLStatement(session2.SQL("SET SESSION innodb_lock_wait_timeout=1")); - rowResult = table2.Select().Where("id = 1").LockExclusive(LockContention.SkipLocked).Execute(); - Assert.AreEqual(0, rowResult.FetchAll().Count, "Matching the document ID"); - // Session2 blocks due to to LockExclusive() not allowing to modify locked documents. - Result result1; - Assert.Throws(() => result1 = table2.Update().Where("id = 1").Set("a", 2).Execute()); - - // Session2 returns immediately as session is committed. - session.Commit(); - var result = table2.Update().Where("id = 1").Set("a", 2).Execute(); - Assert.AreEqual(1, (int)result.AffectedItemsCount, "Matching the record count"); - session.SQL("ROLLBACK").Execute(); - session2.SQL("ROLLBACK").Execute(); - } - } - - [Test, Description("Reading a locked document(lock_shared) in a table using lock_shared with SKIPLOCK waiting option. ")] - public void DoubleSharedLockWithSkiplock() - { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher"); - - session.SQL("DROP TABLE IF EXISTS test.test").Execute(); - session.SQL("CREATE TABLE test.test (id INT, a INT)").Execute(); - var table1 = testSchema.GetTable("test"); - table1.Insert("id", "a").Values(1, 1).Values(2, 2).Values(3, 3).Execute(); - - using (var session2 = MySQLX.GetSession(ConnectionString)) - { - var table = session.Schema.GetTable("test"); - var table2 = session2.GetSchema("test").GetTable("test"); - - session.SQL("START TRANSACTION").Execute(); - var rowResult = table.Select().Where("id = 1").LockShared().Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); - - session2.SQL("START TRANSACTION").Execute(); - // Should return immediately since document isn't locked. - rowResult = table2.Select().Where("id = 2").LockShared(LockContention.SkipLocked).Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); - - // Session2 doesn't block as SKIPLOCK being used - ExecuteSQLStatement(session2.SQL("SET SESSION innodb_lock_wait_timeout=1")); - rowResult = table2.Select().Where("id = 1").LockShared(LockContention.SkipLocked).Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); - - // Session2 blocks due to to LockShared() not allowing to modify locked documents. - Result result1; - Assert.Throws(() => result1 = table2.Update().Where("id = 1").Set("a", 2).Execute()); - - // Session2 returns immediately as session is committed. - session.Commit(); - var result = table2.Update().Where("id = 1").Set("a", 2).Execute(); - Assert.AreEqual(1, (int)result.AffectedItemsCount, "Matching the record count"); - session.SQL("ROLLBACK").Execute(); - session2.SQL("ROLLBACK").Execute(); - } - } - - [Test, Description("Reading a locked document(lock_shared) in a table using lock_exclusive with SKIPLOCK waiting option.")] - public void ExclusiveLockAfterSharedLockWithSkiplock() - { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher"); - - session.SQL("DROP TABLE IF EXISTS test.test").Execute(); - session.SQL("CREATE TABLE test.test (id INT, a INT)").Execute(); - var table1 = testSchema.GetTable("test"); - table1.Insert("id", "a").Values(1, 1).Values(2, 2).Values(3, 3).Execute(); - - using (var session2 = MySQLX.GetSession(ConnectionString)) - { - var table = session.Schema.GetTable("test"); - session.SQL("CREATE UNIQUE INDEX myIndex ON test.test (id)").Execute(); - var table2 = session2.GetSchema("test").GetTable("test"); - - session.SQL("START TRANSACTION").Execute(); - var rowResult = table.Select().Where("id = 1").LockShared().Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); - - session2.SQL("START TRANSACTION").Execute(); - // Should return immediately since document isn't locked. - rowResult = table2.Select().Where("id = 2").LockExclusive(LockContention.SkipLocked).Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); - - // Session2 doesn't block as SKIPLOCK being used - ExecuteSQLStatement(session2.SQL("SET SESSION innodb_lock_wait_timeout=1")); - rowResult = table2.Select().Where("id = 1").LockExclusive(LockContention.SkipLocked).Execute(); - Assert.AreEqual(0, rowResult.FetchAll().Count, "Matching the document ID"); - - // Session2 blocks due to to LockExclusive() not allowing to modify locked documents. - Result result1; - Assert.Throws(() => result1 = table2.Update().Where("id = 1").Set("a", 2).Execute()); - - // Session2 returns immediately as session is committed. - session.Commit(); - var result = table2.Update().Where("id = 1").Set("a", 2).Execute(); - Assert.AreEqual(1, (int)result.AffectedItemsCount, "Matching the record count"); - session.SQL("ROLLBACK").Execute(); - session2.SQL("ROLLBACK").Execute(); - } - } - - [Test, Description("Reading an exclusively locked document in a table using lock_shared without any waiting option. ")] - public void ExclusiveLockBeforeSharedLockWithoutAwaiting() - { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher"); - - session.SQL("DROP TABLE IF EXISTS test.test").Execute(); - session.SQL("CREATE TABLE test.test (id INT, a INT)").Execute(); - var table1 = testSchema.GetTable("test"); - table1.Insert("id", "a").Values(1, 1).Values(2, 2).Values(3, 3).Execute(); - - using (var session2 = MySQLX.GetSession(ConnectionString)) - { - var table = session.Schema.GetTable("test"); - session.SQL("CREATE UNIQUE INDEX myIndex ON test.test (id)").Execute(); - var table2 = session2.GetSchema("test").GetTable("test"); - - session.SQL("START TRANSACTION").Execute(); - var rowResult = table.Select().Where("id = 1").LockExclusive().Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); - - session2.SQL("START TRANSACTION").Execute(); - // Should return immediately since document isn't locked. - rowResult = table2.Select().Where("id = 2").LockShared().Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); - - // Session2 blocks due to to LockExclusive() not allowing to read locked documents. - ExecuteSQLStatement(session2.SQL("SET SESSION innodb_lock_wait_timeout=1")); - Assert.Throws(() => ExecuteSelectStatement(table2.Select().Where("id = 1").LockShared())); - - // Session2 blocks due to to LockExclusive() not allowing to modify locked documents. - Result result1; - Assert.Throws(() => result1 = table2.Update().Where("id = 1").Set("a", 2).Execute()); - - // Session2 returns immediately as session is committed. - session.Commit(); - var result = table2.Update().Where("id = 1").Set("a", 2).Execute(); - Assert.AreEqual(1, (int)result.AffectedItemsCount, "Matching the record count"); - session.SQL("ROLLBACK").Execute(); - session2.SQL("ROLLBACK").Execute(); - } - } - - [Test, Description("Reading an exclusively locked document in a table using lock_exclusive without any waiting option.")] - public void DoubleExclusiveLockWithoutWaiting() - { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher"); - - using (var session2 = MySQLX.GetSession(ConnectionString)) - { - var table = session.Schema.GetTable("test"); - session.SQL("CREATE UNIQUE INDEX myIndex ON test.test (id)").Execute(); - var table2 = session2.GetSchema("test").GetTable("test"); - - session.SQL("START TRANSACTION").Execute(); - var rowResult = table.Select().Where("id = 1").LockExclusive().Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); - - session2.SQL("START TRANSACTION").Execute(); - // Should return immediately since document isn't locked. - rowResult = table2.Select().Where("id = 2").LockExclusive().Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); - - // Session2 blocks due to to LockExclusive() not allowing to read locked documents. - ExecuteSQLStatement(session2.SQL("SET SESSION innodb_lock_wait_timeout=1")); - Assert.Throws(() => ExecuteSelectStatement(table2.Select().Where("id = 1").LockExclusive())); - - // Session2 blocks due to to LockExclusive() not allowing to modify locked documents. - Result result1; - Assert.Throws(() => result1 = table2.Update().Where("id = 1").Set("age", 2).Execute()); - - // Session2 returns immediately as session is committed. - session.Commit(); - var result = table2.Update().Where("id = 1").Set("age", 2).Execute(); - Assert.AreEqual(1, (int)result.AffectedItemsCount, "Matching the record count"); - session.SQL("ROLLBACK").Execute(); - session2.SQL("ROLLBACK").Execute(); - } - } - - [Test, Description("Reading a locked document(lock_shared) in a table using lock_shared without any waiting option.")] - public void DoubleSharedLockWithoutWaiting() - { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher"); - - session.SQL("DROP TABLE IF EXISTS test.test").Execute(); - session.SQL("CREATE TABLE test.test (id INT, a INT)").Execute(); - var table1 = testSchema.GetTable("test"); - table1.Insert("id", "a").Values(1, 1).Values(2, 2).Values(3, 3).Execute(); - - using (var session2 = MySQLX.GetSession(ConnectionString)) - { - var table = session.Schema.GetTable("test"); - var table2 = session2.GetSchema("test").GetTable("test"); - - session.SQL("START TRANSACTION").Execute(); - var rowResult = table.Select().Where("id = 1").LockShared().Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); - - session2.SQL("START TRANSACTION").Execute(); - // Should return immediately since document isn't locked. - rowResult = table2.Select().Where("id = 2").LockShared().Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); - - ExecuteSQLStatement(session2.SQL("SET SESSION innodb_lock_wait_timeout=1")); - rowResult = table2.Select().Where("id = 1").LockShared().Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); - - // Session2 blocks due to to LockExclusive() not allowing to modify locked documents. - Result result1; - Assert.Throws(() => result1 = table2.Update().Where("id = 1").Set("a", 2).Execute()); - - // Session2 returns immediately as session is committed. - session.Commit(); - var result = table2.Update().Where("id = 1").Set("a", 2).Execute(); - Assert.AreEqual(1, (int)result.AffectedItemsCount, "Matching the record count"); - session.SQL("ROLLBACK").Execute(); - session2.SQL("ROLLBACK").Execute(); - } - } - - [Test, Description("Reading a locked document(lock_shared) in a table using lock_exclusive without any waiting option. ")] - public void SharedLockBeforeExclusiveLockWithoutWaiting() - { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher"); - - session.SQL("DROP TABLE IF EXISTS test.test").Execute(); - session.SQL("CREATE TABLE test.test (id INT, a INT)").Execute(); - var table1 = testSchema.GetTable("test"); - table1.Insert("id", "a").Values(1, 1).Values(2, 2).Values(3, 3).Execute(); - - using (var session2 = MySQLX.GetSession(ConnectionString)) - { - var table = session.Schema.GetTable("test"); - session.SQL("CREATE UNIQUE INDEX myIndex ON test.test (id)").Execute(); - var table2 = session2.GetSchema("test").GetTable("test"); - - session.SQL("START TRANSACTION").Execute(); - var rowResult = table.Select().Where("id = 1").LockShared().Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); - - session2.SQL("START TRANSACTION").Execute(); - // Should return immediately since document isn't locked. - rowResult = table2.Select().Where("id = 2").LockExclusive().Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); - - // Session2 blocks as LockExclusive() is trying to read locked documents. - ExecuteSQLStatement(session2.SQL("SET SESSION innodb_lock_wait_timeout=1")); - Assert.Throws(() => ExecuteSelectStatement(table2.Select().Where("id = 1").LockExclusive())); - - // Session2 blocks due to to LockShared() not allowing to modify locked documents. - Result result1; - Assert.Throws(() => result1 = table2.Update().Where("id = 1").Set("a", 2).Execute()); - - // Session2 returns immediately as session is committed. - session.Commit(); - var result = table2.Update().Where("id = 1").Set("a", 2).Execute(); - Assert.AreEqual(1, (int)result.AffectedItemsCount, "Matching the record count"); - session.SQL("ROLLBACK").Execute(); - session2.SQL("ROLLBACK").Execute(); - } - } - - [Test, Description("Reading a locked document(shared/exclusive) in a table using SKIPLOCK and NOWAIT waiting options when CRUD is happening parallely")] - public void SingleLockExclusiveWithNoWaitAndSkip() - { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher"); - - session.SQL("DROP TABLE IF EXISTS test.test").Execute(); - session.SQL("CREATE TABLE test.test (id INT, a INT)").Execute(); - var table1 = testSchema.GetTable("test"); - table1.Insert("id", "a").Values(1, 1).Values(2, 2).Values(3, 3).Execute(); - - using (var session2 = MySQLX.GetSession(ConnectionString)) - { - var table = session.Schema.GetTable("test"); - session.SQL("CREATE UNIQUE INDEX myIndex ON test.test (id)").Execute(); - var table2 = session2.GetSchema("test").GetTable("test"); - - session.SQL("START TRANSACTION").Execute(); - var result1 = table.Update().Where("id = 1").Set("a", 2).Execute(); - - session2.SQL("START TRANSACTION").Execute(); - // Should return immediately since document isn't locked. - var rowResult1 = table2.Select().Where("id = 2").LockExclusive(LockContention.NoWait).Execute(); - Assert.AreEqual(1, rowResult1.FetchAll().Count, "Matching the document ID"); - - // Session2 blocks due to to LockExclusive() not allowing to read locked documents. - ExecuteSQLStatement(session2.SQL("SET SESSION innodb_lock_wait_timeout=1")); - Assert.Throws(() => ExecuteSelectStatement(table2.Select().Where("id = 1").LockExclusive(LockContention.NoWait))); - Assert.Throws(() => ExecuteSelectStatement(table2.Select().Where("id = 1").LockShared(LockContention.NoWait))); - - var rowResult = table2.Select().Where("id = 1").LockShared(LockContention.SkipLocked).Execute(); - Assert.AreEqual(0, rowResult.FetchAll().Count, "Matching the document ID"); - - rowResult = table2.Select().Where("id = 1").LockExclusive(LockContention.SkipLocked).Execute(); - Assert.AreEqual(0, rowResult.FetchAll().Count, "Matching the document ID"); - - session.SQL("ROLLBACK").Execute(); - session2.SQL("ROLLBACK").Execute(); - } - } - - [Test, Description("Multiple lock calls on a document in table using NOWAIT and SKIPLOCK waiting options")] - public void ChainedExclusiveLocks() - { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher"); - - session.SQL("DROP TABLE IF EXISTS test.test").Execute(); - session.SQL("CREATE TABLE test.test (id INT, a INT)").Execute(); - var table1 = testSchema.GetTable("test"); - table1.Insert("id", "a").Values(1, 1).Values(2, 2).Values(3, 3).Execute(); - - using (var session2 = MySQLX.GetSession(ConnectionString)) - { - var table = session.Schema.GetTable("test"); - session.SQL("CREATE UNIQUE INDEX myIndex ON test.test (id)").Execute(); - var table2 = session2.GetSchema("test").GetTable("test"); - - session.SQL("START TRANSACTION").Execute(); - var rowResult = table.Select().Where("id = 1").LockShared().Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); - - session2.SQL("START TRANSACTION").Execute(); - ExecuteSQLStatement(session2.SQL("SET SESSION innodb_lock_wait_timeout=1")); - Assert.Throws(() => rowResult = table2.Select().Where("id = 1").LockExclusive(LockContention.SkipLocked).LockExclusive(LockContention.NoWait).Execute()); - - Assert.Throws(() => ExecuteSelectStatement(table2.Select().Where("id = 1") - .LockExclusive(LockContention.SkipLocked) - .LockExclusive(LockContention.NoWait))); - - rowResult = table2.Select().Where("id = 1").LockExclusive(LockContention.SkipLocked).LockShared(LockContention.SkipLocked).Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); - - rowResult = table2.Select().Where("id = 1").LockShared(LockContention.SkipLocked).LockExclusive(LockContention.SkipLocked).Execute(); - Assert.AreEqual(0, rowResult.FetchAll().Count, "Matching the document ID"); - session.SQL("ROLLBACK").Execute(); - session2.SQL("ROLLBACK").Execute(); - } - } - - [Test, Description("Test MySQLX plugin - MYSQLCNET 755 Table GetIncrementValue")] - public void TableGetAutoIncrementValue() - { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher"); - - session.SQL("CREATE TABLE address1" + - "(address_number1 MEDIUMINT NOT NULL AUTO_INCREMENT, " + - "address_number2 CHAR(100) NOT NULL, " + - "PRIMARY KEY (address_number1)" + ");").Execute(); - Table table = testSchema.GetTable("address1"); - var result = table.Insert("address_number1", "address_number2") - .Values(100, "Test the document id in address table") - .Execute(); - - var docId = result.AutoIncrementValue; - Assert.AreEqual("100", docId.ToString(), "Matching the value if already it is inserted"); - - result = table.Insert("address_number2") - .Values("Test the document id by 2nd insert without id in address table") - .Execute(); - docId = result.AutoIncrementValue; - Assert.AreEqual("101", docId.ToString(), "Matching the value if already it is inserted"); - - session.SQL("CREATE TABLE address2" + - "(address_number3 INT NOT NULL AUTO_INCREMENT, " + - "address_number4 CHAR(100) NOT NULL, " + - "PRIMARY KEY (address_number3)" + ");").Execute(); - table = testSchema.GetTable("address2"); - result = table.Insert("address_number4") - .Values("Test the document id in address table without unique id") - .Execute(); - - docId = result.AutoIncrementValue; - Assert.AreEqual("1", docId.ToString(), "Matching the auto increment value"); - - session.SQL("CREATE TABLE address3" + - "(address_number5 MEDIUMINT NOT NULL AUTO_INCREMENT, " + - "address_number6 CHAR(100) NOT NULL, " + - "PRIMARY KEY (address_number5)" + ");").Execute(); - table = testSchema.GetTable("address3"); - result = table.Insert("address_number5", "address_number6") - .Values(100, "Test multiple document ids in address table - 1st document") - .Values(200, "Test multiple document ids in address table - 2nd document") - .Values(300, "Test multiple document ids in address table - 3rd document") - .Execute(); - - docId = result.AutoIncrementValue; - Assert.AreEqual("300", docId.ToString(), "Matching the value if more than one documents inserted"); - - result = table.Insert("address_number6") - .Values("Test multiple document ids in address table - 4th document without ID") - .Values("Test multiple document ids in address table - 5th document without ID") - .Values("Test multiple document ids in address table - 6th document without ID") - .Execute(); - - docId = result.AutoIncrementValue; - Assert.AreEqual("301", docId.ToString(), "Matching the value if more than one documents inserted"); - - session.SQL("CREATE TABLE address4" + - "(address_number7 INT NOT NULL AUTO_INCREMENT, " + - "address_number8 CHAR(100) NOT NULL, " + - "PRIMARY KEY (address_number7)" + ");").Execute(); - table = testSchema.GetTable("address4"); - result = table.Insert("address_number8") - .Values("Test the document ids in address table without unique id - 1st document") - .Values("Test the document ids in address table without unique id - 2nd document") - .Values("Test the document ids in address table without unique id - 3rd document") - .Execute(); - - docId = result.AutoIncrementValue; - Assert.AreEqual("1", docId.ToString(), "Matching the auto increment value"); - - result = table.Insert("address_number8") - .Values("Test the document ids in address table without unique id - 4th document") - .Values("Test the document ids in address table without unique id - 5th document") - .Values("Test the document ids in address table without unique id - 6th document") - .Execute(); - - docId = result.AutoIncrementValue; - Assert.AreEqual("4", docId.ToString(), "Matching the auto increment value"); - - session.SQL("CREATE TABLE address5" + - "(address_number9 INT, " + - "address_number10 CHAR(100));").Execute(); - - session.SQL("ALTER TABLE address5 ADD c INT UNSIGNED NOT NULL AUTO_INCREMENT, ADD PRIMARY KEY(c)").Execute(); - - table = testSchema.GetTable("address5"); - result = table.Insert("address_number9", "address_number10") - .Values(100, "Test the document ids in address table without unique id - 1st document") - .Values(200, "Test the document ids in address table without unique id - 2nd document") - .Values(300, "Test the document ids in address table without unique id - 3rd document") - .Execute(); - - docId = result.AutoIncrementValue; - Assert.AreEqual("1", docId.ToString(), "Matching the auto increment value"); - session.SQL("drop table if exists address1").Execute(); - session.SQL("drop table if exists address2").Execute(); - session.SQL("drop table if exists address3").Execute(); - session.SQL("drop table if exists address4").Execute(); - session.SQL("drop table if exists address5").Execute(); - } - - [Test, Description("Test MySQLX plugin - MYSQLCNET_684 Fetchone returns null when no rows")] - public void FetchoneReturnsNullNoRows() - { - ExecuteSQL("CREATE TABLE test1(id INT)"); - ExecuteSQL("INSERT INTO test1 VALUES (1),(2),(3),(4)"); - ExecuteSQL("CREATE TABLE test2(id INT, val INT)"); - ExecuteSQL("INSERT INTO test2 VALUES (1,0)"); - var rowResult = testSchema.GetTable("test1").Select("id").Execute(); - foreach (var row in rowResult) - { - var result = testSchema.GetTable("test2").Update().Where("id=1").Set("val", row["id"]).Execute(); - //WL11843-Core API v1 alignment Changes - Assert.AreEqual(1, result.AffectedItemsCount, "Matching"); - } - - Row valRow = testSchema.GetTable("test2").Select("val").Execute().FetchOne(); - Assert.AreEqual("4", valRow[0].ToString(), "Matching"); - ExecuteSQL("DELETE FROM test2 WHERE id=1"); - valRow = testSchema.GetTable("test2").Select("val").Execute().FetchOne(); - Assert.IsNull(valRow); - ExecuteSQL("DROP TABLE if exists test1"); - ExecuteSQL("DROP TABLE if exists test2"); - } - - [Test, Description("Test MySQLX plugin - MYSQLCNET_684 Fetchone returns null when no table")] - public void FetchoneReturnsNullNoTable() - { - ExecuteSQL("CREATE TABLE test111(id INT)"); - ExecuteSQL("INSERT INTO test111 VALUES (1),(2),(3),(4)"); - ExecuteSQL("CREATE TABLE test222(id INT, val INT)"); - ExecuteSQL("INSERT INTO test222 VALUES (1,0)"); - var rowResult = testSchema.GetTable("test111").Select("id").Execute(); - foreach (var row in rowResult) - { - var result = testSchema.GetTable("test222").Update().Where("id=1").Set("val", row["id"]).Execute(); - //WL11843-Core API v1 alignment Changes - Assert.AreEqual(1, result.AffectedItemsCount, "Matching"); - } - - Row valRow = testSchema.GetTable("test222").Select("val").Execute().FetchOne(); - Assert.AreEqual("4", valRow[0].ToString(), "Matching"); - ExecuteSQL("DROP TABLE test222"); - Assert.Throws(() => valRow = testSchema.GetTable("test222").Select("val").Execute().FetchOne()); - ExecuteSQL("DROP TABLE IF EXISTS test111"); - } - - [Test, Description("MySQLX CNET-Test Table.Select() with exclusive lock and Table.Update() normal from two sessions. ")] - public void DoubleChainedLocksWithTwoSessions_S1() - { - if (!session.InternalSession.GetServerVersion().isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); - - session.SQL("SET autocommit = 0").Execute(); - using (var session2 = MySQLX.GetSession(ConnectionString)) - { - session2.SQL("SET autocommit = 0").Execute(); - var table = session.Schema.GetTable("test"); - session.SQL("CREATE UNIQUE INDEX myIndex ON test.test (id)").Execute(); - var table2 = session2.GetSchema("test").GetTable("test"); - - session.SQL("START TRANSACTION").Execute(); - var rowResult = table.Select().Where("id = 1").LockExclusive().Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the record ID"); - - session2.SQL("START TRANSACTION").Execute(); - // Should return immediately since document isn't locked. - rowResult = table2.Select().Where("id = 2").LockExclusive().Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the record ID"); - - // Session2 blocks due to to LockExclusive() not allowing to read locked documents. - ExecuteSQLStatement(session2.SQL("SET SESSION innodb_lock_wait_timeout=1")); - Assert.Throws(() => ExecuteSelectStatement(table2.Select().Where("id = 1").LockExclusive())); - - // Session2 blocks due to to LockExclusive() not allowing to modify locked documents. - Result result1; - Assert.Throws(() => result1 = table2.Update().Where("id = 1").Set("age", 2).Execute()); - - session.SQL("ROLLBACK").Execute(); - session2.SQL("ROLLBACK").Execute(); - } - - using (var session2 = MySQLX.GetSession(ConnectionString)) - { - session2.SQL("SET autocommit = 0").Execute(); - var table = session.Schema.GetTable("test"); - var table2 = session2.GetSchema("test").GetTable("test"); - - session.SQL("START TRANSACTION").Execute(); - var rowResult = table.Select().Where("id = 1").LockShared().LockExclusive().Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the record ID"); - - session2.SQL("START TRANSACTION").Execute(); - // Should return immediately since document isn't locked. - rowResult = table2.Select().Where("id = 2").LockShared().LockExclusive().Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the record ID"); - - // Session2 blocks due to to LockExclusive() not allowing to read locked documents. - ExecuteSQLStatement(session2.SQL("SET SESSION innodb_lock_wait_timeout=1")); - Assert.Throws(() => ExecuteSelectStatement(table2.Select().Where("id = 1").LockShared().LockExclusive())); - - // Session2 blocks due to to LockExclusive() not allowing to modify locked documents. - Result result1; - Assert.Throws(() => result1 = table2.Update().Where("id = 1").Set("age", 2).Execute()); - session.SQL("ROLLBACK").Execute(); - session2.SQL("ROLLBACK").Execute(); - } - session.SQL("SET autocommit = 1").Execute(); - } - - [Test, Description("MySQLX CNET-Test Table.Select() with shared lock and Table.Update() normal from two sessions. ")] - public void DoubleChainedLocksWithTwoSessions_S2() - { - if (!session.InternalSession.GetServerVersion().isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); - - session.SQL("SET autocommit = 0").Execute(); - using (var session2 = MySQLX.GetSession(ConnectionString)) - { - session2.SQL("SET autocommit = 0").Execute(); - var table = session.Schema.GetTable("test"); - session.SQL("CREATE UNIQUE INDEX myIndex ON test.test (id)").Execute(); - var table2 = session2.GetSchema("test").GetTable("test"); - - session.SQL("START TRANSACTION").Execute(); - var rowResult = table.Select().Where("id = 1").LockShared().Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the record ID"); - - session2.SQL("START TRANSACTION").Execute(); - // Should return immediately since document isn't locked. - rowResult = table2.Select().Where("id = 1").Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the record ID"); - - // Session2 blocks due to to LockExclusive() not allowing to read locked documents. - ExecuteSQLStatement(session2.SQL("SET SESSION innodb_lock_wait_timeout=1")); - var result = table2.Update().Where("id = 2").Set("age", 30).Execute(); - Assert.AreEqual(1, (int)result.AffectedItemsCount, "Match being done"); - Assert.Throws(() => ExecuteSelectStatement(table2.Select().Where("id = 1").LockExclusive())); - - // Session2 blocks due to to LockExclusive() not allowing to modify locked documents. - Result result1; - Assert.Throws(() => result1 = table2.Update().Where("id = 1").Set("age", 2).Execute()); - - session.SQL("ROLLBACK").Execute(); - session2.SQL("ROLLBACK").Execute(); - } - - session.SQL("SET autocommit = 0").Execute(); - using (var session2 = MySQLX.GetSession(ConnectionString)) - { - session2.SQL("SET autocommit = 0").Execute(); - var table = session.Schema.GetTable("test"); - var table2 = session2.GetSchema("test").GetTable("test"); - - session.SQL("START TRANSACTION").Execute(); - var rowResult = table.Select().Where("id = 1").LockExclusive().LockShared().Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the record ID"); - - session2.SQL("START TRANSACTION").Execute(); - // Should return immediately since document isn't locked. - rowResult = table2.Select().Where("id = 1").Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the record ID"); - - // Session2 blocks due to to LockExclusive() not allowing to read locked documents. - session2.SQL("SET SESSION innodb_lock_wait_timeout=1").Execute(); - var result = table2.Update().Where("id = 2").Set("age", 30).Execute(); - Assert.AreEqual(1, (int)result.AffectedItemsCount, "Match being done"); - Assert.Throws(() => ExecuteSelectStatement(table2.Select().Where("id = 1").LockShared().LockExclusive())); - - // Session2 blocks due to to LockExclusive() not allowing to modify locked documents. - Result result1; - Assert.Throws(() => result1 = table2.Update().Where("id = 1").Set("age", 2).Execute()); - session.SQL("ROLLBACK").Execute(); - session2.SQL("ROLLBACK").Execute(); - } - session.SQL("SET autocommit = 1").Execute(); - } - - [Test, Description("MySQLX CNET-Test Table.Select() with exclusive lock from two sessions. ")] - public void SingleExclusiveLock() - { - if (!session.InternalSession.GetServerVersion().isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); - - session.SQL("SET autocommit = 0").Execute(); - using (var session2 = MySQLX.GetSession(ConnectionString)) - { - session2.SQL("SET autocommit = 0").Execute(); - var table = session.Schema.GetTable("test"); - session.SQL("CREATE UNIQUE INDEX myIndex ON test.test (id)").Execute(); - var table2 = session2.GetSchema("test").GetTable("test"); - - session.SQL("START TRANSACTION").Execute(); - var rowResult = table.Select().Where("id = 1").LockExclusive().Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the record ID"); - - session2.SQL("START TRANSACTION").Execute(); - // Should return immediately since document isn't locked. - rowResult = table2.Select().Where("id = 2").Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the record ID"); - - // Session2 blocks due to to LockExclusive() not allowing to read locked documents. - session2.SQL("SET SESSION innodb_lock_wait_timeout=1").Execute(); - Assert.Throws(() => ExecuteSelectStatement(table2.Select().Where("id = 1").LockExclusive())); - session.SQL("ROLLBACK").Execute(); - session2.SQL("ROLLBACK").Execute(); - } - session.SQL("SET autocommit = 1").Execute(); - } - - [Test, Description("MySQLX CNET-Test Table.Select() with exclusive lock and Table.Select() with exclusive lock from two sessions-Select multiple records")] - public void SingleTransactionWithLocks() - { - if (!session.InternalSession.GetServerVersion().isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); - - session.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED").Execute(); - using (var session2 = MySQLX.GetSession(ConnectionString)) - { - session2.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED").Execute(); - session.SQL("CREATE UNIQUE INDEX myIndex ON test.test (id)").Execute(); - var table = session.Schema.GetTable("test"); - var table2 = session2.GetSchema("test").GetTable("test"); - - session.SQL("START TRANSACTION").Execute(); - var rowResult = table.Select().Where("id in (1,3)").LockShared().Execute(); - Assert.AreEqual(2, rowResult.FetchAll().Count, "Matching the record ID"); - - rowResult = table2.Select().Where("id = 2").LockExclusive().Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the record ID"); - rowResult = table2.Select().Where("id = 2").LockShared().Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the record ID"); - // Session2 blocks due to to LockExclusive() not allowing to read locked documents. - session.SQL("SET SESSION innodb_lock_wait_timeout=1").Execute(); - table2.Select().Where("id = 2").LockExclusive().Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the record ID"); - session2.SQL("SET SESSION innodb_lock_wait_timeout=1").Execute(); - Assert.Throws(() => ExecuteSelectStatement(table2.Select().Where("id = 1").LockExclusive())); - - session2.SQL("SET SESSION innodb_lock_wait_timeout=1").Execute(); - // Session2 blocks due to to LockExclusive() not allowing to modify locked documents. - Assert.Throws(() => ExecuteUpdateStatement(table2.Update().Where("id = 1").Set("age", 2))); - - session.SQL("ROLLBACK").Execute(); - rowResult = table2.Select().Where("id = 1").LockExclusive().Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); - session2.SQL("ROLLBACK").Execute(); - rowResult = table.Select().Where("id = 2").LockExclusive().Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); - } - } - - [Test, Description("MySQLX CNET-Test Table.Select() with exclusive lock and Table.Update() normal from two sessions-50 Iterations")] - public void IteratedExclusiveLocks() - { - if (!Platform.IsWindows()) Assert.Ignore("This test is for Windows OS only"); - if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); - - session.SQL("SET autocommit = 0").Execute(); - session.SQL("CREATE UNIQUE INDEX myIndex ON test.test (id)").Execute(); - const int iterations = 30; - for (var i = 0; i < iterations; i++) - { - using (var session2 = MySQLX.GetSession(ConnectionString)) - { - session2.SQL("SET autocommit = 0").Execute(); - var table = session.Schema.GetTable("test"); - - var table2 = session2.GetSchema("test").GetTable("test"); - - session.SQL("START TRANSACTION").Execute(); - var rowResult = table.Select().Where("id = 1").LockExclusive().Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the record ID"); - - session2.SQL("START TRANSACTION").Execute(); - // Should return immediately since document isn't locked. - rowResult = table2.Select().Where("id = 2").LockExclusive().Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the record ID"); - - // Session2 blocks due to to LockExclusive() not allowing to read locked documents. - session2.SQL("SET SESSION innodb_lock_wait_timeout=1").Execute(); - Assert.Throws(() => ExecuteSelectStatement(table2.Select().Where("id = 1").LockExclusive())); - - // Session2 blocks due to to LockExclusive() not allowing to modify locked documents. - Result result1; - Assert.Throws(() => result1 = table2.Update().Where("id = 1").Set("age", 2).Execute()); - session.SQL("ROLLBACK").Execute(); - session2.SQL("ROLLBACK").Execute(); - } - } - session.SQL("SET autocommit = 1").Execute(); - } - - #endregion WL14389 - - #region Methods - public static string RandomString(int length) - { - const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; - const string chars1 = "ABCDEFGHIJ"; - var random = new Random(); - if (length == 20) - { - return chars1; - } - else - { - return new string(Enumerable.Repeat(chars, length) - .Select(s => s[random.Next(s.Length)]).ToArray()); - } - - } - #endregion Methods - } -} +// Copyright © 2015, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySql.Data.Common; +using MySql.Data.MySqlClient; +using MySqlX.XDevAPI; +using MySqlX.XDevAPI.Common; +using MySqlX.XDevAPI.Relational; +using NUnit.Framework; +using System; +using System.Linq; +using System.Text; + +namespace MySqlX.Data.Tests.RelationalTests +{ + public class TableSelectTests : BaseTest + { + object[][] allRows = { + new object[] { 1, "jonh doe", 38, "{\"company\": \"xyz\", \"hobbies\": \"reading\", \"vehicle\": \"bike\"}" }, + new object[] { 2, "milton green", 45, "{\"company\": \"abc\", \"hobbies\": [\"boxing\", \"running\"], \"vehicle\": \"car\"}" }, + new object[] { 3, "larry smith", 24, "{\"company\": \"zxc\", \"hobbies\": \"painting\", \"vehicle\": \"boat\"}" } + }; + + [SetUp] + public void SetUp() + { + ExecuteSQL("CREATE TABLE test.test (id INT, name VARCHAR(45), age INT, additionalinfo JSON)"); + TableInsertStatement stmt = testSchema.GetTable("test").Insert(); + stmt.Values(allRows[0]); + stmt.Values(allRows[1]); + stmt.Values(allRows[2]); + Result result = ExecuteInsertStatement(stmt); + } + + [TearDown] + public void TearDown() + { + ExecuteSQL("DROP TABLE IF EXISTS test"); + ExecuteSQL("DROP TABLE IF EXISTS testDate"); + } + + [Test] + public void FetchOne() + { + Table t = testSchema.GetTable("test"); + Assert.AreEqual(38, ExecuteSelectStatement(t.Select("age")).FetchOne()["age"]); + } + + private void MultiTableSelectTest(TableSelectStatement statement, object[][] expectedValues) + { + RowResult result = ExecuteSelectStatement(statement); + int rowCount = result.FetchAll().Count; + + Assert.AreEqual(expectedValues.Length, rowCount); + Assert.AreEqual(expectedValues.Length, result.Rows.Count); + for (int i = 0; i < expectedValues.Length; i++) + { + for (int j = 0; j < expectedValues[i].Length; j++) + { + Assert.AreEqual(expectedValues[i][j], result.Rows.ToArray()[i][j]); + } + } + } + + [Test] + public void TableSelect() + { + var table = testSchema.GetTable("test"); + + MultiTableSelectTest(table.Select(), allRows); + MultiTableSelectTest(table.Select("name", "age"), + allRows.Select(c => new[] { c[1], c[2] }).ToArray()); + MultiTableSelectTest(table.Select("name", "age").Where("age == 38"), + allRows.Select(c => new[] { c[1], c[2] }).Where(c => (int)c[1] == 38).ToArray()); + MultiTableSelectTest(table.Select().Where("age == 45"), + allRows.Where(c => (int)c[2] == 45).ToArray()); + MultiTableSelectTest(table.Select().OrderBy("age"), + allRows.OrderBy(c => c[2]).ToArray()); + MultiTableSelectTest(table.Select().OrderBy("age desc"), + allRows.OrderByDescending(c => c[2]).ToArray()); + MultiTableSelectTest(table.Select().OrderBy("age desc, name"), + allRows.OrderByDescending(c => c[2]).ThenBy(c => c[1]).ToArray()); + MultiTableSelectTest(table.Select().Limit(1), + allRows.Take(1).ToArray()); + MultiTableSelectTest(table.Select().Limit(10).Offset(1), + allRows.Skip(1).Take(10).ToArray()); + MultiTableSelectTest(table.Select().Limit(1).Offset(1), + allRows.Skip(1).Take(1).ToArray()); + MultiTableSelectTest(table.Select().Where("name like :name").Bind("nAme", "%jon%"), + allRows.Where(c => c[1].ToString().Contains("jon")).ToArray()); + MultiTableSelectTest(table.Select().Where("name like :name").Bind("naMe", "%on%"), + allRows.Where(c => c[1].ToString().Contains("on")).ToArray()); + } + + [Test] + public void AllColumns() + { + var table = testSchema.GetTable("test"); + var select = ExecuteSelectStatement(table.Select("*, 42 as a_number, '43' as a_string")); + var rows = select.FetchAll(); + Assert.AreEqual(6, select.Columns.Count); + Assert.AreEqual(allRows.Length, rows.Count); + Assert.AreEqual(allRows[0][0], rows[0]["id"]); + Assert.AreEqual(allRows[0][1], rows[0]["name"]); + Assert.AreEqual(allRows[0][2], rows[0]["age"]); + Assert.AreEqual(allRows[0][3], rows[0]["additionalinfo"]); + Assert.AreEqual((sbyte)42, rows[0]["a_number"]); + Assert.AreEqual("43", rows[0]["a_string"]); + } + + [Test] + public void CountAllColumns() + { + var table = testSchema.GetTable("test"); + var select = ExecuteSelectStatement(table.Select("count(*) + 10")); + var rows = select.FetchAll(); + Assert.That(select.Columns, Has.One.Items); + Assert.That(rows, Has.One.Items); + Assert.AreEqual(allRows.Length + 10, (long)rows[0][0]); + } + + [Test] + public void MultipleBind() + { + object[] validationRow = allRows[1]; + var table = testSchema.GetTable("test"); + var select = ExecuteSelectStatement(table.Select().Where("Name = :nAme && Age = :aGe").Bind("agE", validationRow[2]).Bind("naMe", validationRow[1])); + var rows = select.FetchAll(); + Assert.That(rows, Has.One.Items); + Assert.AreEqual(validationRow[1], rows[0]["namE"]); + Assert.AreEqual(validationRow[2], rows[0]["AGe"]); + } + + [Test] + public void DatetimeAndMicroseconds() + { + ExecuteSQL("CREATE TABLE test.testDate (id INT, name VARCHAR(45), birthday DATETIME(6))"); + ExecuteSQL("INSERT INTO test.testDate VALUES(1, 'JOHN', '1985-10-21 16:34:22.123456')"); + ExecuteSQL("INSERT INTO test.testDate VALUES(1, 'BILL', '1985-10-21 10:00:45.987')"); + var rows = ExecuteSelectStatement(GetSession().GetSchema("test").GetTable("testDate").Select()).FetchAll(); + Assert.AreEqual(2, rows.Count); + Assert.AreEqual(new DateTime(1985, 10, 21, 16, 34, 22).AddTicks(1234560), (DateTime)rows[0]["birthday"]); + Assert.AreEqual(new DateTime(1985, 10, 21, 10, 0, 45).AddTicks(9870000), (DateTime)rows[1]["birthday"]); + } + + [Test] + public void DatetimeAndMilliseconds() + { + ExecuteSQL("CREATE TABLE test.testDate2 (id INT, name VARCHAR(45), birthday DATETIME(3))"); + ExecuteSQL("INSERT INTO test.testDate2 VALUES(1, 'JOHN', '1985-10-21 16:34:22.123456')"); + ExecuteSQL("INSERT INTO test.testDate2 VALUES(1, 'BILL', '1985-10-21 10:00:45.098')"); + var rows = ExecuteSelectStatement(GetSession().GetSchema("test").GetTable("testDate2").Select()).FetchAll(); + Assert.AreEqual(2, rows.Count); + Assert.AreEqual(new DateTime(1985, 10, 21, 16, 34, 22).AddTicks(1230000), (DateTime)rows[0]["birthday"]); + Assert.AreEqual(new DateTime(1985, 10, 21, 10, 0, 45).AddTicks(980000), (DateTime)rows[1]["birthday"]); + } + + [Test] + public void RowLockingNotSupportedInOlderVersions() + { + if (session.InternalSession.GetServerVersion().isAtLeast(8, 0, 3)) return; + + Table table = session.Schema.GetTable("test"); + + Exception ex = Assert.Throws(() => ExecuteSelectStatement(table.Select().LockShared())); + Assert.AreEqual("This functionality is only supported from server version 8.0.3 onwards.", ex.Message); + + ex = Assert.Throws(() => ExecuteSelectStatement(table.Select().LockExclusive())); + Assert.AreEqual("This functionality is only supported from server version 8.0.3 onwards.", ex.Message); + } + + [Test] + public void SimpleSharedLock() + { + if (!session.InternalSession.GetServerVersion().isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); + + ExecuteSQLStatement(session.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); + using (var session2 = MySQLX.GetSession(ConnectionString)) + { + ExecuteSQLStatement(session2.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); + Table table = session.Schema.GetTable("test"); + Table table2 = session2.GetSchema("test").GetTable("test"); + + ExecuteSQLStatement(session.SQL("START TRANSACTION")); + RowResult rowResult = ExecuteSelectStatement(table.Select().Where("id = 1").LockShared()); + Assert.That(rowResult.FetchAll(), Has.One.Items); + + ExecuteSQLStatement(session2.SQL("START TRANSACTION")); + // Should return immediately since row isn't locked. + rowResult = ExecuteSelectStatement(table2.Select().Where("id = 2").LockShared()); + Assert.That(rowResult.FetchAll(), Has.One.Items); + // Should return immediately due to LockShared() allows reading by other sessions. + rowResult = ExecuteSelectStatement(table2.Select().Where("id = 1").LockShared()); + Assert.That(rowResult.FetchAll(), Has.One.Items); + + ExecuteSQLStatement(session.SQL("ROLLBACK")); + ExecuteSQLStatement(session2.SQL("ROLLBACK")); + } + } + + [Test] + public void SimpleExclusiveLock() + { + if (!session.InternalSession.GetServerVersion().isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); + + ExecuteSQLStatement(session.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); + using (var session2 = MySQLX.GetSession(ConnectionString)) + { + ExecuteSQLStatement(session2.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); + Table table = session.Schema.GetTable("test"); + ExecuteSQLStatement(session.SQL("CREATE UNIQUE INDEX myIndex ON test.test (id)")); + Table table2 = session2.GetSchema("test").GetTable("test"); + + ExecuteSQLStatement(session.SQL("START TRANSACTION")); + RowResult rowResult = ExecuteSelectStatement(table.Select().Where("id = 1").LockExclusive()); + Assert.That(rowResult.FetchAll(), Has.One.Items); + + ExecuteSQLStatement(session2.SQL("START TRANSACTION")); + // Should return immediately since row isn't locked. + rowResult = ExecuteSelectStatement(table2.Select().Where("id = 2").LockExclusive()); + Assert.That(rowResult.FetchAll(), Has.One.Items); + // Session2 blocks due to to LockExclusive() not allowing to read locked rows. + ExecuteSQLStatement(session2.SQL("SET SESSION innodb_lock_wait_timeout=1")); + Exception ex = Assert.Throws(() => ExecuteSelectStatement(table2.Select().Where("id = 1").LockExclusive())); + Assert.AreEqual("Lock wait timeout exceeded; try restarting transaction", ex.Message); + + ExecuteSQLStatement(session.SQL("ROLLBACK")); + ExecuteSQLStatement(session2.SQL("ROLLBACK")); + } + } + + [Test] + public void SharedLockForbidsToModifyDocuments() + { + if (!session.InternalSession.GetServerVersion().isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); + + ExecuteSQLStatement(session.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); + using (var session2 = MySQLX.GetSession(ConnectionString)) + { + ExecuteSQLStatement(session2.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); + Table table = session.Schema.GetTable("test"); + Table table2 = session2.GetSchema("test").GetTable("test"); + + ExecuteSQLStatement(session.SQL("START TRANSACTION")); + RowResult rowResult = ExecuteSelectStatement(table.Select().Where("id = 1").LockShared()); + Assert.That(rowResult.FetchAll(), Has.One.Items); + + ExecuteSQLStatement(session2.SQL("START TRANSACTION")); + // Reading the same row is allowed with LockShared(). + rowResult = ExecuteSelectStatement(table2.Select().Where("id = 1")); + Assert.That(rowResult.FetchAll(), Has.One.Items); + + // Modify() is allowed for non-locked rows. + Result result = ExecuteUpdateStatement(table2.Update().Where("id = 2").Set("age", 2)); + Assert.AreEqual(1, result.AffectedItemsCount); + // Session1 blocks, Modify() is not allowed for locked rows. + ExecuteSQLStatement(session2.SQL("SET SESSION innodb_lock_wait_timeout=1")); + Exception ex = Assert.Throws(() => ExecuteUpdateStatement(table2.Update().Where("id = 1").Set("age", 2))); + Assert.AreEqual("Lock wait timeout exceeded; try restarting transaction", ex.Message); + + ExecuteSQLStatement(session.SQL("ROLLBACK")); + // Modify() is allowed since row isn't locked anymore. + ExecuteUpdateStatement(table2.Update().Where("id = 1").Set("age", 2)); + ExecuteSQLStatement(session2.SQL("COMMIT")); + } + } + + [Test] + public void ExclusiveLockForbidsToModifyDocuments() + { + if (!session.InternalSession.GetServerVersion().isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); + + ExecuteSQLStatement(session.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); + using (var session2 = MySQLX.GetSession(ConnectionString)) + { + ExecuteSQLStatement(session2.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); + Table table = session.Schema.GetTable("test"); + Table table2 = session2.GetSchema("test").GetTable("test"); + + ExecuteSQLStatement(session.SQL("START TRANSACTION")); + RowResult rowResult = ExecuteSelectStatement(table.Select().Where("id = 1").LockExclusive()); + Assert.That(rowResult.FetchAll(), Has.One.Items); + + ExecuteSQLStatement(session2.SQL("START TRANSACTION")); + + // Modify() is allowed for non-locked rows. + Result result = ExecuteUpdateStatement(table2.Update().Where("id = 2").Set("age", 2)); + Assert.AreEqual(1, result.AffectedItemsCount); + // Session1 blocks, Modify() is not allowed for locked rows. + ExecuteSQLStatement(session2.SQL("SET SESSION innodb_lock_wait_timeout=1")); + Exception ex = Assert.Throws(() => ExecuteUpdateStatement(table2.Update().Where("id = 1").Set("age", 2))); + Assert.AreEqual("Lock wait timeout exceeded; try restarting transaction", ex.Message); + + ExecuteSQLStatement(session.SQL("ROLLBACK")); + // Modify() is allowed since row isn't locked anymore. + ExecuteUpdateStatement(table2.Update().Where("id = 1").Set("age", 2)); + ExecuteSQLStatement(session2.SQL("COMMIT")); + } + } + + [Test] + public void SharedLockAfterExclusiveLock() + { + if (!session.InternalSession.GetServerVersion().isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); + + ExecuteSQLStatement(session.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); + using (var session2 = MySQLX.GetSession(ConnectionString)) + { + ExecuteSQLStatement(session2.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); + Table table = session.Schema.GetTable("test"); + ExecuteSQLStatement(session.SQL("CREATE UNIQUE INDEX myIndex ON test.test (id)")); + Table table2 = session2.GetSchema("test").GetTable("test"); + + ExecuteSQLStatement(session.SQL("START TRANSACTION")); + RowResult rowResult = ExecuteSelectStatement(table.Select().Where("id = 1").LockExclusive()); + Assert.That(rowResult.FetchAll(), Has.One.Items); + + ExecuteSQLStatement(session2.SQL("START TRANSACTION")); + // Should return immediately since row isn't locked. + rowResult = ExecuteSelectStatement(table2.Select().Where("id = 2").LockShared()); + Assert.That(rowResult.FetchAll(), Has.One.Items); + // Session2 blocks due to LockExclusive() not allowing to read locked rows. + ExecuteSQLStatement(session2.SQL("SET SESSION innodb_lock_wait_timeout=1")); + Exception ex = Assert.Throws(() => ExecuteSelectStatement(table2.Select().Where("id = 1").LockShared())); + Assert.AreEqual("Lock wait timeout exceeded; try restarting transaction", ex.Message); + + // Session unlocks rows. + ExecuteSQLStatement(session.SQL("ROLLBACK")); + // Row can now be recovered. + rowResult = ExecuteSelectStatement(table2.Select().Where("id = 1").LockShared()); + Assert.That(rowResult.FetchAll(), Has.One.Items); + ExecuteSQLStatement(session2.SQL("ROLLBACK")); + } + } + + [Test] + public void ExclusiveLockAfterSharedLock() + { + if (!session.InternalSession.GetServerVersion().isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); + + ExecuteSQLStatement(session.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); + using (var session2 = MySQLX.GetSession(ConnectionString)) + { + ExecuteSQLStatement(session2.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); + Table table = session.Schema.GetTable("test"); + ExecuteSQLStatement(session.SQL("CREATE UNIQUE INDEX myIndex ON test.test (id)")); + Table table2 = session2.GetSchema("test").GetTable("test"); + + ExecuteSQLStatement(session.SQL("START TRANSACTION")); + RowResult rowResult = ExecuteSelectStatement(table.Select().Where("id in (1, 3)").LockShared()); + Assert.AreEqual(2, rowResult.FetchAll().Count); + + ExecuteSQLStatement(session2.SQL("START TRANSACTION")); + // Should return immediately since row isn't locked. + rowResult = ExecuteSelectStatement(table2.Select().Where("id = 2").LockExclusive()); + // Should return immediately due to LockShared() allows reading by other sessions. + rowResult = ExecuteSelectStatement(table2.Select().Where("id = 2").LockShared()); + Assert.That(rowResult.FetchAll(), Has.One.Items); + // Session2 blocks due to to LockExclusive() not allowing to read locked rows. + ExecuteSQLStatement(session2.SQL("SET SESSION innodb_lock_wait_timeout=1")); + Exception ex = Assert.Throws(() => ExecuteSelectStatement(table2.Select().Where("id = 1").LockExclusive())); + Assert.AreEqual("Lock wait timeout exceeded; try restarting transaction", ex.Message); + + // Session unlocks rows. + ExecuteSQLStatement(session.SQL("ROLLBACK")); + rowResult = ExecuteSelectStatement(table2.Select().Where("id = 1").LockExclusive()); + Assert.That(rowResult.FetchAll(), Has.One.Items); + ExecuteSQLStatement(session2.SQL("ROLLBACK")); + } + } + + [Test] + public void SelectWithInOperator() + { + Table table = testSchema.GetTable("test"); + Assert.AreEqual(3, ExecuteSelectStatement(table.Select()).FetchAll().Count); + + Assert.AreEqual(2, ExecuteSelectStatement(table.Select().Where("name IN (\"jonh doe\", \"milton green\")")).FetchAll().Count); + Assert.That(ExecuteSelectStatement(table.Select().Where("name NOT IN (\"jonh doe\", \"milton green\")")).FetchAll(), Has.One.Items); + CollectionAssert.IsEmpty(ExecuteSelectStatement(table.Select().Where("name IN (\"\", \"\")")).FetchAll()); + CollectionAssert.IsEmpty(ExecuteSelectStatement(table.Select().Where("\"\" IN (1,2,3)")).FetchAll()); + CollectionAssert.IsEmpty(ExecuteSelectStatement(table.Select().Where("name IN ('', '')")).FetchAll()); + CollectionAssert.IsEmpty(ExecuteSelectStatement(table.Select().Where("'' IN (1,2,3)")).FetchAll()); + Assert.AreEqual(3, ExecuteSelectStatement(table.Select().Where("'' IN ('')")).FetchAll().Count); + + Assert.Throws(() => ExecuteSelectStatement(table.Select().Where("name NOT IN [\"jonh doe\", \"milton green\"]")).FetchAll()); + Assert.Throws(() => ExecuteSelectStatement(table.Select().Where("a IN [3]")).FetchAll()); + Assert.Throws(() => ExecuteSelectStatement(table.Select().Where("3 IN a")).FetchAll()); + } + + [Test] + public void Grouping() + { + ExecuteSQLStatement(GetSession().SQL("set sql_mode = 'STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION';")); + Table table = testSchema.GetTable("test"); + + // Insert additonal users. + object[][] additionalUsers = { + new object[] { 4, "mary weinstein", 24, null }, + new object[] { 5, "jerry pratt", 45, null }, + new object[] { 6, "hugh jackman", 20, null }, + new object[] { 7, "elizabeth olsen", 31, null } + }; + var statement = table.Insert(); + foreach (object[] user in additionalUsers) + { + statement = statement.Values(user); + } + + Assert.AreEqual(4, ExecuteInsertStatement(statement).AffectedItemsCount); + + // GroupBy returns 5 rows since age 45 and 24 is repeated. + var result = ExecuteSelectStatement(table.Select().GroupBy("age")); + Assert.AreEqual(5, result.FetchAll().Count); + + // GroupBy with null. + result = ExecuteSelectStatement(table.Select("id as ID", "name as Name", "age as Age").GroupBy(null)); + Assert.AreEqual(7, result.FetchAll().Count); + result = ExecuteSelectStatement(table.Select("id as ID", "name as Name", "age as Age").GroupBy(null, null)); + Assert.AreEqual(7, result.FetchAll().Count); + result = ExecuteSelectStatement(table.Select("id as ID", "name as Name", "age as Age").GroupBy(null, "age")); + Assert.AreEqual(5, result.FetchAll().Count); + + // Having operation. + // Having reduces the original 5 rows to 3 since 2 rows have a cnt=2, due to the repeated names. + result = ExecuteSelectStatement(table.Select("id", "count(name) as cnt", "age").GroupBy("age").Having("cnt = 1")); + Assert.AreEqual(3, result.FetchAll().Count); + + // Having with null. + result = ExecuteSelectStatement(table.Select("id as ID", "count(name) as cnt", "age as Age").GroupBy("age").Having(null)); + Assert.AreEqual(5, result.FetchAll().Count); + + // GroupBy with invalid field name. + var ex = Assert.Throws(() => ExecuteSelectStatement(table.Select("id as ID", "name as Name", "age as Age").GroupBy("none"))); + Assert.AreEqual("Unknown column 'none' in 'group statement'", ex.Message); + + // GroupBy with empty strings. + var ex2 = Assert.Throws(() => ExecuteSelectStatement(table.Select("id as ID", "name as Name", "age as Age").GroupBy(""))); + Assert.AreEqual("No more tokens when expecting one at token pos 0", ex2.Message); + ex2 = Assert.Throws(() => ExecuteSelectStatement(table.Select("id as ID", "name as Name", "age as Age").GroupBy(" "))); + Assert.AreEqual("No more tokens when expecting one at token pos 0", ex2.Message); + ex2 = Assert.Throws(() => ExecuteSelectStatement(table.Select("id as ID", "name as Name", "age as Age").GroupBy(string.Empty))); + Assert.AreEqual("No more tokens when expecting one at token pos 0", ex2.Message); + + // Having with invalid field name. + ex = Assert.Throws(() => ExecuteSelectStatement(table.Select("id as ID", "count(name) as cnt", "age as Age").GroupBy("age").Having("none = 1"))); + Assert.AreEqual("Unknown column 'none' in 'having clause'", ex.Message); + + // Having with empty strings. + ex2 = Assert.Throws(() => ExecuteSelectStatement(table.Select("id as ID", "count(name) as cnt", "age as Age").GroupBy("age").Having(""))); + Assert.AreEqual("Unable to parse query ''", ex2.Message); + Assert.AreEqual("No more tokens when expecting one at token pos 0", ex2.InnerException.Message); + ex2 = Assert.Throws(() => ExecuteSelectStatement(table.Select("id as ID", "count(name) as cnt", "age as Age").GroupBy("age").Having(" "))); + Assert.AreEqual("Unable to parse query ' '", ex2.Message); + Assert.AreEqual("No more tokens when expecting one at token pos 0", ex2.InnerException.Message); + ex2 = Assert.Throws(() => ExecuteSelectStatement(table.Select("id as ID", "count(name) as cnt", "age as Age").GroupBy("age").Having(string.Empty))); + Assert.AreEqual("Unable to parse query ''", ex2.Message); + Assert.AreEqual("No more tokens when expecting one at token pos 0", ex2.InnerException.Message); + } + + /// + /// Bug-29838254 + /// RESULTSET ERROR WHEN SELECT IS ISSUED WITH IN OPERATOR WITH BLANKS WITH 8.0.17 SERVER-C/NET8.0.17TRUNK + /// + [Test] + public void SelectWithInBlanksAndBrackets() + { + Session session = GetSession(); + Schema schema = session.GetSchema("test"); + object[][] allRows = + { + new object[] {1, "john doe", 38}, + new object[] {2, "milton green", 45}, + new object[] {3, "milton blue", 46}, + new object[] {4, "milton red", 47}, + new object[] {5, "milton yellow", 48}, + new object[] {6, "milton check", 49}, + new object[] {7, "milton pink", 14}, + new object[] {8, "milton beize", 25}, + new object[] {9, "milton silver", 35}, + new object[] {10, "milton city", 65} + }; + session.SQL("USE test").Execute(); + session.SQL("DROP table if exists test").Execute(); + var r = session.SQL("CREATE TABLE test.test(id INT,name VARCHAR(45), age INT)").Execute(); + var rows = r.HasData ? r.FetchAll() : null; + testSchema = session.GetSchema("test"); + var insertStatement = testSchema.GetTable("test").Insert(); + var rowsToInsert = 10; + for (var i = 0; i < rowsToInsert; i++) + insertStatement.Values(allRows[i]); + insertStatement.Execute(); + var table = testSchema.GetTable("test"); + int count = 0; + + //Exception expected when square brackets are used instead of parenthesis + Assert.Throws(() => table.Select().Where("name IN ['', ' ']").Execute().FetchAll()); + + // Test using parenthesis should return result + count = table.Select().Where("name IN (\"john doe\", \"milton green\")").Execute().FetchAll().Count; + Assert.True(count > 0); + + // Using parenthesis should return empty resultset for empty parameters + count = table.Select().Where("name IN ('', ' ')").Execute().FetchAll().Count; + Assert.True(count == 0); + } + + [TestCase(":hobbies IN additionalinfo->$.hobbies", "hobbies", "painting", 3)] + [TestCase(":hobbies IN additionalinfo->$.hobbies", "hobbies", "[\"boxing\", \"running\"]", 0)] + [TestCase("[\"boxing\", \"running\"] IN additionalinfo->$.hobbies", null, null, 2)] + [TestCase(":hobbies IN additionalinfo$.hobbies", "hobbies", "painting", 3)] + public void InOperatorBindingJson(string condition, string bind, string value, int id) + { + Table table = testSchema.GetTable("test"); + Assert.AreEqual(3, ExecuteSelectStatement(table.Select()).FetchAll().Count); + + var stmt = table.Select().Where(condition); + if (bind != null) stmt.Bind(bind, value); + var result = ExecuteSelectStatement(stmt).FetchAll(); + Assert.AreEqual(id == 0 ? 0 : 1, result.Count); + if (id > 0) + { + Assert.AreEqual(id, result[0]["id"]); + } + } + + #region WL14389 + + [Test, Description("Reading locked document(lock_shared) in a table using lock_exclusive with DEFAULT waiting option.")] + public void ExclusiveLockAfterSharedLockDefaultWaiting() + { + if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher"); + + session.SQL("DROP TABLE IF EXISTS test.test").Execute(); + session.SQL("CREATE TABLE test.test (id INT, a INT)").Execute(); + var table1 = testSchema.GetTable("test"); + table1.Insert("id", "a").Values(1, 1).Values(2, 2).Values(3, 3).Execute(); + ExecuteSQLStatement(session.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); + using (var session2 = MySQLX.GetSession(ConnectionString)) + { + ExecuteSQLStatement(session2.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); + var table = session.Schema.GetTable("test"); + session.SQL("CREATE UNIQUE INDEX myIndex ON test.test (id)").Execute(); + var table2 = session2.GetSchema("test").GetTable("test"); + + ExecuteSQLStatement(session.SQL("START TRANSACTION")); + var rowResult = ExecuteSelectStatement(table.Select().Where("id = 1").LockShared()); + Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); + + ExecuteSQLStatement(session2.SQL("START TRANSACTION")); + + // Should return immediately since document isn't locked. + rowResult = table2.Select().Where("id = 2").LockExclusive(LockContention.Default).Execute(); + Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); + + // Session2 blocks as LockExclusive trying to access locked document + ExecuteSQLStatement(session2.SQL("SET SESSION innodb_lock_wait_timeout=1")); + Exception ex = Assert.Throws(() => ExecuteSelectStatement(table2.Select().Where("id = 1").LockExclusive(LockContention.Default))); + Assert.AreEqual("Lock wait timeout exceeded; try restarting transaction", ex.Message); + + // Session2 blocks due to to LockShared() not allowing to modify locked documents. + Result result1; + ex = Assert.Throws(() => result1 = table2.Update().Where("id = 1").Set("a", 2).Execute()); + Assert.AreEqual("Lock wait timeout exceeded; try restarting transaction", ex.Message); + + // Session2 returns immediately as session is committed. + session.Commit(); + var result = table2.Update().Where("id = 1").Set("a", 2).Execute(); + Assert.AreEqual(1, result.AffectedItemsCount); + + ExecuteSQLStatement(session.SQL("ROLLBACK")); + ExecuteSQLStatement(session2.SQL("ROLLBACK")); + } + } + + [Test, Description("Reading exclusively locked document in a table using lock_shared with NOWAIT waiting option. ")] + public void SharedLockAfterExclusiveLockWithNoWait() + { + if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher"); + + session.SQL("DROP TABLE IF EXISTS test.test").Execute(); + session.SQL("CREATE TABLE test.test (id INT, a INT)").Execute(); + var table1 = testSchema.GetTable("test"); + table1.Insert("id", "a").Values(1, 1).Values(2, 2).Values(3, 3).Execute(); + ExecuteSQLStatement(session.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); + using (var session2 = MySQLX.GetSession(ConnectionString)) + { + ExecuteSQLStatement(session2.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); + var table = session.Schema.GetTable("test"); + session.SQL("CREATE UNIQUE INDEX myIndex ON test.test (id)").Execute(); + var table2 = session2.GetSchema("test").GetTable("test"); + + session.SQL("START TRANSACTION").Execute(); + var rowResult = table.Select().Where("id = 1").LockExclusive().Execute(); + Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); + + session2.SQL("START TRANSACTION").Execute(); + // Should return immediately since document isn't locked. + rowResult = table2.Select().Where("id = 2").LockShared(LockContention.NoWait).Execute(); + Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); + + // Session2 blocks due to to LockExclusive() not allowing to read locked documents. + ExecuteSQLStatement(session2.SQL("SET SESSION innodb_lock_wait_timeout=1")); + Assert.Throws(() => ExecuteSelectStatement(table2.Select().Where("id = 1").LockShared(LockContention.NoWait))); + + // Session2 blocks due to to LockExclusive() not allowing to modify locked documents. + Result result1; + Assert.Throws(() => result1 = table2.Update().Where("id = 1").Set("a", 2).Execute()); + + session.Commit(); + var result = table2.Update().Where("id = 1").Set("a", 2).Execute(); + Assert.AreEqual(1, result.AffectedItemsCount); + + ExecuteSQLStatement(session.SQL("ROLLBACK")); + ExecuteSQLStatement(session2.SQL("ROLLBACK")); + } + } + + [Test, Description("Testing Non ASCII characters for utf8mb4 characterset")] + public void NonAsciiCharsForUtf8mb4() + { + //Bug28261283 + string record = "{\"name\": \"New\",\"age\": 4 , "; + string name1 = "\u201C\u2199\u2197\u2196\u2198\u201D"; + string name2 = "{\"age\": 1, \"misc\": 1.2, \"name\": \"\u201C\u2199\u2197\u2196\u2198\u201D\"}"; + + session.SQL($"use {schemaName}").Execute(); + session.SQL("drop table if exists newTable").Execute(); + session.SQL("create table newTable(c1 varchar(200), c2 JSON) CHARACTER SET utf8mb4").Execute(); + var db = session.GetSchema(schemaName); + Table tabNew = db.GetTable("newTable"); + + tabNew.Insert("c1", "c2").Values("\u201C\u2199\u2197\u2196\u2198\u201D", "{ \"name\": \"\u201C\u2199\u2197\u2196\u2198\u201D\", \"age\": 1 , \"misc\": 1.2}").Execute(); + tabNew.Insert().Values("abcNew£¢€©§°√", "{ \"name\": \"abcNew£¢€©§°√\", \"age\": 2 , \"misc\": 1.2}").Execute(); + RowResult result = tabNew.Select("c1", "c2").Where("c1 ='\u201C\u2199\u2197\u2196\u2198\u201D'").Execute(); + var r1 = result.FetchOne(); + Assert.AreEqual(name1, r1[0].ToString());//"“↙↗↖↘”" + Assert.AreNotEqual(name2, r1[1].ToString());//"{\"age\": 1, \"misc\": 1.2, \"name\": \"??????????????????\"}" + var t = session.SQL("SELECT c1, CONVERT(c2 USING utf8mb4) FROM newTable WHERE c1 = '\u201C\u2199\u2197\u2196\u2198\u201D'").Execute(); + r1 = t.FetchOne(); + Assert.AreEqual(name1, r1[0].ToString());//"“↙↗↖↘”" + Assert.AreEqual(name2, r1[1].ToString());//"{\"age\": 1, \"misc\": 1.2, \"name\": \"??????????????????\"}" + + Collection coll = CreateCollection("test"); + + int klen = 1024 * 64; + string[] key = new string[klen]; + int dlen = 1024 * 100; + string[] data = new string[dlen]; + Array.Resize(ref key, 'S'); + Array.Resize(ref data, '$'); + string unicodeString = "Maths use \u03a0 (Pi) for calculations"; + // You can convert a string into a byte array + byte[] asciiBytes = Encoding.ASCII.GetBytes(unicodeString); + // You can convert a byte array into a char array + char[] asciiChars = Encoding.ASCII.GetChars(asciiBytes); + string asciiString = new string(asciiChars); + + record = record + "\""; + record = record + "\":\""; + record = record + asciiString; + record = record + "\"}"; + + Result r = coll.Add("{ \"name\": \"\u201C\u2199\u2197\u2196\u2198\u201D\", \"age\": 4 , \"misc\": 1.2}"). + Add("{ \"name\": \"xyz£¢€©§°√\", \"age\": 6 , \"misc\": 10}").Execute(); + var docs = coll.Find("name = '\u201C\u2199\u2197\u2196\u2198\u201D' and age>= 4 and age <= 6").Execute(); + DbDoc doc = docs.FetchOne(); + Assert.AreEqual(name1, doc["name"]); + session.SQL("drop table if exists test").Execute(); + session.SQL("drop table if exists newTable").Execute(); + } + + [Test, Description("Test MySQLX plugin Datatype Tests")] + public void DatatypesOnCreateTable() + { + if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher"); + + session.SQL($"use {schemaName}"); + session.SQL("create table test1(c1 int,c2 double GENERATED ALWAYS AS (c1*101/102) Stored COMMENT 'First Gen Col',c3 Json GENERATED ALWAYS AS (concat('{\"F1\":',c1,'}')) VIRTUAL COMMENT 'Second Gen /**/Col', c4 bigint GENERATED ALWAYS as (c1*10000) VIRTUAL UNIQUE KEY Comment '3rd Col' NOT NULL)").Execute(); + session.SQL("insert into test1(c1) values(1000)").Execute(); + RowResult r = session.GetSchema(schemaName).GetTable("test1").Select("c1").Execute(); + r.FetchAll(); + Assert.AreEqual("1000", r.Rows[0][0].ToString(), "Matching the values"); + session.SQL("drop table if exists test1").Execute(); + } + + [Test, Description("Test MySQLX plugin Table Expression using Where")] + public void TableExpressionWhereBindGroupBy() + { + if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher"); + + string match = null; + session.SQL("create table test1(name VARCHAR(40), age INT)").Execute(); + Table table = session.GetSchema(schemaName).GetTable("test1"); + + for (int i = 10; i < 30; i++) + { + int j = 1; + string name = RandomString(i); + var result = table.Insert("name", "age") + .Values(name, i) + .Execute(); + if (i == 28) + match = name; + Assert.AreEqual((ulong)j, result.AffectedItemsCount, "Matching the values"); + j = j + 1; + } + + var whereResult = table.Select("name", "age").Where("age == 28").Execute(); + int rowCount = whereResult.FetchAll().Count; + Assert.AreEqual(1, rowCount, "Matching the row count"); + Assert.AreEqual(match, whereResult.Rows.ToArray()[0][0].ToString(), "Matching the name"); + + whereResult = table.Select("name", "age").Where("age == 100").Execute(); + rowCount = whereResult.FetchAll().Count; + Assert.AreEqual(0, rowCount, "Matching that there is no such value "); + + whereResult = table.Select().Where("name like :name").Bind("nAme", "%ABCDEFGHIJ%").Execute(); + rowCount = whereResult.FetchAll().Count; + for (int i = 0; i < whereResult.Rows.Count; i++) + { + var res = whereResult.Rows.ToArray()[i][0]; + StringAssert.Contains("ABCDEFGHIJ", res.ToString()); + } + + whereResult = table.Select().Where("name like :name").Bind("nAme", "%ABCD%").Execute(); + rowCount = whereResult.FetchAll().Count; + for (int j = 0; j < whereResult.Rows.Count; j++) + { + var res = whereResult.Rows.ToArray()[j][0]; + StringAssert.Contains("ABCD", res.ToString()); + } + } + + [Test, Description("Test MySQLX plugin Table")] + public void TableSelectFetchValuesInOrder() + { + ExecuteSQL("drop table if exists test1"); + ExecuteSQL("create table test1(name VARCHAR(40), age INT)"); + Table table = session.GetSchema(schemaName).GetTable("test1"); + var result = table.Insert("name", "age") + .Values("MARK", 34) + .Execute(); + + Assert.AreEqual((ulong)1, result.AffectedItemsCount, "Matching the values"); + result = table.Insert("name", "age") + .Values("richie", 16) + .Execute(); + Assert.AreEqual((ulong)1, result.AffectedItemsCount, "Matching the values"); + var selectResult = table.Select().Execute(); + + while (selectResult.Next()) ; + Assert.AreEqual(2, selectResult.Rows.Count, "Matching the row count"); + Assert.AreEqual("MARK", selectResult.Rows.ToArray()[0][0].ToString(), "Matching the value MARK"); + Assert.AreEqual(34, (int)selectResult.Rows.ToArray()[0][1], "Matching the age 34"); + Assert.AreEqual("richie", selectResult.Rows.ToArray()[1][0].ToString(), "Matching the value richie"); + Assert.AreEqual(16, (int)selectResult.Rows.ToArray()[1][1], "Matching the age 16"); + + var result1 = testSchema.GetTable("test").Select().OrderBy("age desc").Execute(); + int rowCount = result1.FetchAll().Count; + for (int i = 0; i < rowCount; i++) + { + Assert.AreEqual("45", result1.Rows[0][2].ToString(), "Matching the values"); + Assert.AreEqual("38", result1.Rows[1][2].ToString(), "Matching the values"); + Assert.AreEqual("24", result1.Rows[2][2].ToString(), "Matching the values"); + } + + result1 = testSchema.GetTable("test").Select().OrderBy("age asc").Execute(); + rowCount = result1.FetchAll().Count; + for (int i = 0; i < rowCount; i++) + { + Assert.AreEqual("24", result1.Rows[0][2].ToString(), "Matching the values"); + Assert.AreEqual("38", result1.Rows[1][2].ToString(), "Matching the values"); + Assert.AreEqual("45", result1.Rows[2][2].ToString(), "Matching the values"); + } + } + + [Test, Description("Reading exclusively locked document in a table using lock_exclusive with NOWAIT waiting option. ")] + public void DoubleExclusiveLockWithNoWait() + { + if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher"); + + session.SQL("DROP TABLE IF EXISTS test.test").Execute(); + session.SQL("CREATE TABLE test.test (id INT, a INT)").Execute(); + var table1 = testSchema.GetTable("test"); + table1.Insert("id", "a").Values(1, 1).Values(2, 2).Values(3, 3).Execute(); + ExecuteSQLStatement(session.SQL("SET autocommit = 0")); + using (var session2 = MySQLX.GetSession(ConnectionString)) + { + ExecuteSQLStatement(session2.SQL("SET autocommit = 0")); + var table = testSchema.GetTable("test"); + session.SQL("CREATE UNIQUE INDEX myIndex ON test.test (id)").Execute(); + var table2 = session2.GetSchema("test").GetTable("test"); + + session.SQL("START TRANSACTION").Execute(); + var rowResult = table.Select().Where("id = 1").LockExclusive().Execute(); + Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); + + session2.SQL("START TRANSACTION").Execute(); + // Should return immediately since document isn't locked. + rowResult = table2.Select().Where("id = 2").LockExclusive(LockContention.NoWait).Execute(); + Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); + + // Session2 blocks due to to LockExclusive() not allowing to read locked documents. + ExecuteSQLStatement(session2.SQL("SET SESSION innodb_lock_wait_timeout=1")); + Assert.Throws(() => ExecuteSelectStatement(table2.Select().Where("id = 1").LockShared(LockContention.NoWait))); + + // Session2 blocks due to to LockExclusive() not allowing to modify locked documents. + Result result1; + Assert.Throws(() => result1 = table2.Update().Where("id = 1").Set("a", 2).Execute()); + + // Session2 returns immediately as session is committed. + session.Commit(); + var result = table2.Update().Where("id = 1").Set("a", 2).Execute(); + Assert.AreEqual(1, result.AffectedItemsCount); + session.SQL("ROLLBACK").Execute(); + session2.SQL("ROLLBACK").Execute(); + } + + ExecuteSQLStatement(session.SQL("SET autocommit = 1")); + } + + [Test, Description("Reading a locked document(lock_shared) in a table using lock_shared with NOWAIT waiting option. ")] + public void DoubleSharedLockWithNoWait() + { + if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher"); + + session.SQL("DROP TABLE IF EXISTS test.test").Execute(); + session.SQL("CREATE TABLE test.test (id INT, a INT)").Execute(); + var table1 = testSchema.GetTable("test"); + table1.Insert("id", "a").Values(1, 1).Values(2, 2).Values(3, 3).Execute(); + using (var session2 = MySQLX.GetSession(ConnectionString)) + { + var table = session.Schema.GetTable("test"); + var table2 = session2.GetSchema("test").GetTable("test"); + + session.SQL("START TRANSACTION").Execute(); + var rowResult = table.Select().Where("id = 1").LockShared().Execute(); + Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); + + session2.SQL("START TRANSACTION").Execute(); + // Should return immediately since document isn't locked. + rowResult = table2.Select().Where("id = 2").LockShared(LockContention.NoWait).Execute(); + Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); + + // Session2 doesnt block as LockShare trying to read locked(Lock_shared) document + session2.SQL("SET SESSION innodb_lock_wait_timeout=1").Execute(); + rowResult = table2.Select().Where("id = 1").LockShared(LockContention.NoWait).Execute(); + Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); + + // Session2 blocks due to to LockShared() not allowing to modify locked documents. + Result result1; + Assert.Throws(() => result1 = table2.Update().Where("id = 1").Set("a", 2).Execute()); + + // Session2 returns immediately as session is committed. + session.Commit(); + var result = table2.Update().Where("id = 1").Set("a", 2).Execute(); + Assert.AreEqual(1, result.AffectedItemsCount); + session.SQL("ROLLBACK").Execute(); + session2.SQL("ROLLBACK").Execute(); + } + } + + [Test, Description("Reading a locked document(lock_shared) in a table using lock_shared with NOWAIT waiting option. ")] + public void ExclusiveLockAfterSharedLockWithNoWait() + { + if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher"); + + session.SQL("DROP TABLE IF EXISTS test.test").Execute(); + session.SQL("CREATE TABLE test.test (id INT, a INT)").Execute(); + var table1 = testSchema.GetTable("test"); + table1.Insert("id", "a").Values(1, 1).Values(2, 2).Values(3, 3).Execute(); + + using (var session2 = MySQLX.GetSession(ConnectionString)) + { + var table = session.Schema.GetTable("test"); + session.SQL("CREATE UNIQUE INDEX myIndex ON test.test (id)").Execute(); + var table2 = session2.GetSchema("test").GetTable("test"); + + session.SQL("START TRANSACTION").Execute(); + var rowResult = table.Select().Where("id = 1").LockShared().Execute(); + Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); + + session2.SQL("START TRANSACTION").Execute(); + // Should return immediately since document isn't locked. + rowResult = table2.Select().Where("id = 2").LockExclusive(LockContention.NoWait).Execute(); + Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); + + // Session2 blocks as LockExclusive() trying to access locked(LockShared) documents. + ExecuteSQLStatement(session2.SQL("SET SESSION innodb_lock_wait_timeout=1")); + Assert.Throws(() => ExecuteSelectStatement(table2.Select().Where("id = 1").LockExclusive(LockContention.NoWait))); + + // Session2 blocks due to to LockShared() not allowing to modify locked documents. + Result result1; + Assert.Throws(() => result1 = table2.Update().Where("id = 1").Set("a", 2).Execute()); + + // Session2 returns immediately as session is committed. + session.Commit(); + var result = table2.Update().Where("id = 1").Set("a", 2).Execute(); + Assert.AreEqual(1, result.AffectedItemsCount); + session.SQL("ROLLBACK").Execute(); + session2.SQL("ROLLBACK").Execute(); + } + } + + [Test, Description("Reading exclusively locked document in a table using lock_shared with SKIPLOCK waiting option. ")] + public void SharedLockAfterExclusiveWithSkiplock() + { + if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher"); + + session.SQL("DROP TABLE IF EXISTS test.test").Execute(); + session.SQL("CREATE TABLE test.test (id INT, a INT)").Execute(); + var table1 = testSchema.GetTable("test"); + table1.Insert("id", "a").Values(1, 1).Values(2, 2).Values(3, 3).Execute(); + + using (var session2 = MySQLX.GetSession(ConnectionString)) + { + var table = session.Schema.GetTable("test"); + session.SQL("CREATE UNIQUE INDEX myIndex ON test.test (id)").Execute(); + var table2 = session2.GetSchema("test").GetTable("test"); + + session.SQL("START TRANSACTION").Execute(); + var rowResult = table.Select().Where("id = 1").LockExclusive().Execute(); + Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); + + session2.SQL("START TRANSACTION").Execute(); + // Should return immediately since document isn't locked. + rowResult = table2.Select().Where("id = 2").LockShared(LockContention.NoWait).Execute(); + Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); + + // Session2 blocks due to to LockExclusive() not allowing to read locked documents. + ExecuteSQLStatement(session2.SQL("SET SESSION innodb_lock_wait_timeout=1")); + rowResult = table2.Select().Where("id = 1").LockShared(LockContention.SkipLocked).Execute(); + Assert.AreEqual(0, rowResult.FetchAll().Count, "Matching the document ID"); + + // Session2 blocks due to to LockExclusive() not allowing to modify locked documents. + Result result1; + Assert.Throws(() => result1 = table2.Update().Where("id = 1").Set("a", 2).Execute()); + + // Session2 returns immediately as session is committed. + session.Commit(); + var result = table2.Update().Where("id = 1").Set("a", 2).Execute(); + Assert.AreEqual(1, (int)result.AffectedItemsCount, "Matching the record count"); + + session.SQL("ROLLBACK").Execute(); + session2.SQL("ROLLBACK").Execute(); + } + } + + [Test, Description("Reading exclusively locked document in a table using lock_exclusive with SKIPLOCK waiting option.")] + public void DoubleExclusiveLockWithSkiplock() + { + if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher"); + + session.SQL("DROP TABLE IF EXISTS test.test").Execute(); + session.SQL("CREATE TABLE test.test (id INT, a INT)").Execute(); + var table1 = testSchema.GetTable("test"); + table1.Insert("id", "a").Values(1, 1).Values(2, 2).Values(3, 3).Execute(); + + using (var session2 = MySQLX.GetSession(ConnectionString)) + { + var table = session.Schema.GetTable("test"); + session.SQL("CREATE UNIQUE INDEX myIndex ON test.test (id)").Execute(); + var table2 = session2.GetSchema("test").GetTable("test"); + + session.SQL("START TRANSACTION").Execute(); + var rowResult = table.Select().Where("id = 1").LockExclusive().Execute(); + Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); + + session2.SQL("START TRANSACTION").Execute(); + // Should return immediately since document isn't locked. + rowResult = table2.Select().Where("id = 2").LockExclusive(LockContention.SkipLocked).Execute(); + Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); + + // Session2 doesn't block as SKIPLOCK used + ExecuteSQLStatement(session2.SQL("SET SESSION innodb_lock_wait_timeout=1")); + rowResult = table2.Select().Where("id = 1").LockExclusive(LockContention.SkipLocked).Execute(); + Assert.AreEqual(0, rowResult.FetchAll().Count, "Matching the document ID"); + // Session2 blocks due to to LockExclusive() not allowing to modify locked documents. + Result result1; + Assert.Throws(() => result1 = table2.Update().Where("id = 1").Set("a", 2).Execute()); + + // Session2 returns immediately as session is committed. + session.Commit(); + var result = table2.Update().Where("id = 1").Set("a", 2).Execute(); + Assert.AreEqual(1, (int)result.AffectedItemsCount, "Matching the record count"); + session.SQL("ROLLBACK").Execute(); + session2.SQL("ROLLBACK").Execute(); + } + } + + [Test, Description("Reading a locked document(lock_shared) in a table using lock_shared with SKIPLOCK waiting option. ")] + public void DoubleSharedLockWithSkiplock() + { + if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher"); + + session.SQL("DROP TABLE IF EXISTS test.test").Execute(); + session.SQL("CREATE TABLE test.test (id INT, a INT)").Execute(); + var table1 = testSchema.GetTable("test"); + table1.Insert("id", "a").Values(1, 1).Values(2, 2).Values(3, 3).Execute(); + + using (var session2 = MySQLX.GetSession(ConnectionString)) + { + var table = session.Schema.GetTable("test"); + var table2 = session2.GetSchema("test").GetTable("test"); + + session.SQL("START TRANSACTION").Execute(); + var rowResult = table.Select().Where("id = 1").LockShared().Execute(); + Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); + + session2.SQL("START TRANSACTION").Execute(); + // Should return immediately since document isn't locked. + rowResult = table2.Select().Where("id = 2").LockShared(LockContention.SkipLocked).Execute(); + Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); + + // Session2 doesn't block as SKIPLOCK being used + ExecuteSQLStatement(session2.SQL("SET SESSION innodb_lock_wait_timeout=1")); + rowResult = table2.Select().Where("id = 1").LockShared(LockContention.SkipLocked).Execute(); + Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); + + // Session2 blocks due to to LockShared() not allowing to modify locked documents. + Result result1; + Assert.Throws(() => result1 = table2.Update().Where("id = 1").Set("a", 2).Execute()); + + // Session2 returns immediately as session is committed. + session.Commit(); + var result = table2.Update().Where("id = 1").Set("a", 2).Execute(); + Assert.AreEqual(1, (int)result.AffectedItemsCount, "Matching the record count"); + session.SQL("ROLLBACK").Execute(); + session2.SQL("ROLLBACK").Execute(); + } + } + + [Test, Description("Reading a locked document(lock_shared) in a table using lock_exclusive with SKIPLOCK waiting option.")] + public void ExclusiveLockAfterSharedLockWithSkiplock() + { + if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher"); + + session.SQL("DROP TABLE IF EXISTS test.test").Execute(); + session.SQL("CREATE TABLE test.test (id INT, a INT)").Execute(); + var table1 = testSchema.GetTable("test"); + table1.Insert("id", "a").Values(1, 1).Values(2, 2).Values(3, 3).Execute(); + + using (var session2 = MySQLX.GetSession(ConnectionString)) + { + var table = session.Schema.GetTable("test"); + session.SQL("CREATE UNIQUE INDEX myIndex ON test.test (id)").Execute(); + var table2 = session2.GetSchema("test").GetTable("test"); + + session.SQL("START TRANSACTION").Execute(); + var rowResult = table.Select().Where("id = 1").LockShared().Execute(); + Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); + + session2.SQL("START TRANSACTION").Execute(); + // Should return immediately since document isn't locked. + rowResult = table2.Select().Where("id = 2").LockExclusive(LockContention.SkipLocked).Execute(); + Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); + + // Session2 doesn't block as SKIPLOCK being used + ExecuteSQLStatement(session2.SQL("SET SESSION innodb_lock_wait_timeout=1")); + rowResult = table2.Select().Where("id = 1").LockExclusive(LockContention.SkipLocked).Execute(); + Assert.AreEqual(0, rowResult.FetchAll().Count, "Matching the document ID"); + + // Session2 blocks due to to LockExclusive() not allowing to modify locked documents. + Result result1; + Assert.Throws(() => result1 = table2.Update().Where("id = 1").Set("a", 2).Execute()); + + // Session2 returns immediately as session is committed. + session.Commit(); + var result = table2.Update().Where("id = 1").Set("a", 2).Execute(); + Assert.AreEqual(1, (int)result.AffectedItemsCount, "Matching the record count"); + session.SQL("ROLLBACK").Execute(); + session2.SQL("ROLLBACK").Execute(); + } + } + + [Test, Description("Reading an exclusively locked document in a table using lock_shared without any waiting option. ")] + public void ExclusiveLockBeforeSharedLockWithoutAwaiting() + { + if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher"); + + session.SQL("DROP TABLE IF EXISTS test.test").Execute(); + session.SQL("CREATE TABLE test.test (id INT, a INT)").Execute(); + var table1 = testSchema.GetTable("test"); + table1.Insert("id", "a").Values(1, 1).Values(2, 2).Values(3, 3).Execute(); + + using (var session2 = MySQLX.GetSession(ConnectionString)) + { + var table = session.Schema.GetTable("test"); + session.SQL("CREATE UNIQUE INDEX myIndex ON test.test (id)").Execute(); + var table2 = session2.GetSchema("test").GetTable("test"); + + session.SQL("START TRANSACTION").Execute(); + var rowResult = table.Select().Where("id = 1").LockExclusive().Execute(); + Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); + + session2.SQL("START TRANSACTION").Execute(); + // Should return immediately since document isn't locked. + rowResult = table2.Select().Where("id = 2").LockShared().Execute(); + Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); + + // Session2 blocks due to to LockExclusive() not allowing to read locked documents. + ExecuteSQLStatement(session2.SQL("SET SESSION innodb_lock_wait_timeout=1")); + Assert.Throws(() => ExecuteSelectStatement(table2.Select().Where("id = 1").LockShared())); + + // Session2 blocks due to to LockExclusive() not allowing to modify locked documents. + Result result1; + Assert.Throws(() => result1 = table2.Update().Where("id = 1").Set("a", 2).Execute()); + + // Session2 returns immediately as session is committed. + session.Commit(); + var result = table2.Update().Where("id = 1").Set("a", 2).Execute(); + Assert.AreEqual(1, (int)result.AffectedItemsCount, "Matching the record count"); + session.SQL("ROLLBACK").Execute(); + session2.SQL("ROLLBACK").Execute(); + } + } + + [Test, Description("Reading an exclusively locked document in a table using lock_exclusive without any waiting option.")] + public void DoubleExclusiveLockWithoutWaiting() + { + if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher"); + + using (var session2 = MySQLX.GetSession(ConnectionString)) + { + var table = session.Schema.GetTable("test"); + session.SQL("CREATE UNIQUE INDEX myIndex ON test.test (id)").Execute(); + var table2 = session2.GetSchema("test").GetTable("test"); + + session.SQL("START TRANSACTION").Execute(); + var rowResult = table.Select().Where("id = 1").LockExclusive().Execute(); + Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); + + session2.SQL("START TRANSACTION").Execute(); + // Should return immediately since document isn't locked. + rowResult = table2.Select().Where("id = 2").LockExclusive().Execute(); + Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); + + // Session2 blocks due to to LockExclusive() not allowing to read locked documents. + ExecuteSQLStatement(session2.SQL("SET SESSION innodb_lock_wait_timeout=1")); + Assert.Throws(() => ExecuteSelectStatement(table2.Select().Where("id = 1").LockExclusive())); + + // Session2 blocks due to to LockExclusive() not allowing to modify locked documents. + Result result1; + Assert.Throws(() => result1 = table2.Update().Where("id = 1").Set("age", 2).Execute()); + + // Session2 returns immediately as session is committed. + session.Commit(); + var result = table2.Update().Where("id = 1").Set("age", 2).Execute(); + Assert.AreEqual(1, (int)result.AffectedItemsCount, "Matching the record count"); + session.SQL("ROLLBACK").Execute(); + session2.SQL("ROLLBACK").Execute(); + } + } + + [Test, Description("Reading a locked document(lock_shared) in a table using lock_shared without any waiting option.")] + public void DoubleSharedLockWithoutWaiting() + { + if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher"); + + session.SQL("DROP TABLE IF EXISTS test.test").Execute(); + session.SQL("CREATE TABLE test.test (id INT, a INT)").Execute(); + var table1 = testSchema.GetTable("test"); + table1.Insert("id", "a").Values(1, 1).Values(2, 2).Values(3, 3).Execute(); + + using (var session2 = MySQLX.GetSession(ConnectionString)) + { + var table = session.Schema.GetTable("test"); + var table2 = session2.GetSchema("test").GetTable("test"); + + session.SQL("START TRANSACTION").Execute(); + var rowResult = table.Select().Where("id = 1").LockShared().Execute(); + Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); + + session2.SQL("START TRANSACTION").Execute(); + // Should return immediately since document isn't locked. + rowResult = table2.Select().Where("id = 2").LockShared().Execute(); + Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); + + ExecuteSQLStatement(session2.SQL("SET SESSION innodb_lock_wait_timeout=1")); + rowResult = table2.Select().Where("id = 1").LockShared().Execute(); + Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); + + // Session2 blocks due to to LockExclusive() not allowing to modify locked documents. + Result result1; + Assert.Throws(() => result1 = table2.Update().Where("id = 1").Set("a", 2).Execute()); + + // Session2 returns immediately as session is committed. + session.Commit(); + var result = table2.Update().Where("id = 1").Set("a", 2).Execute(); + Assert.AreEqual(1, (int)result.AffectedItemsCount, "Matching the record count"); + session.SQL("ROLLBACK").Execute(); + session2.SQL("ROLLBACK").Execute(); + } + } + + [Test, Description("Reading a locked document(lock_shared) in a table using lock_exclusive without any waiting option. ")] + public void SharedLockBeforeExclusiveLockWithoutWaiting() + { + if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher"); + + session.SQL("DROP TABLE IF EXISTS test.test").Execute(); + session.SQL("CREATE TABLE test.test (id INT, a INT)").Execute(); + var table1 = testSchema.GetTable("test"); + table1.Insert("id", "a").Values(1, 1).Values(2, 2).Values(3, 3).Execute(); + + using (var session2 = MySQLX.GetSession(ConnectionString)) + { + var table = session.Schema.GetTable("test"); + session.SQL("CREATE UNIQUE INDEX myIndex ON test.test (id)").Execute(); + var table2 = session2.GetSchema("test").GetTable("test"); + + session.SQL("START TRANSACTION").Execute(); + var rowResult = table.Select().Where("id = 1").LockShared().Execute(); + Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); + + session2.SQL("START TRANSACTION").Execute(); + // Should return immediately since document isn't locked. + rowResult = table2.Select().Where("id = 2").LockExclusive().Execute(); + Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); + + // Session2 blocks as LockExclusive() is trying to read locked documents. + ExecuteSQLStatement(session2.SQL("SET SESSION innodb_lock_wait_timeout=1")); + Assert.Throws(() => ExecuteSelectStatement(table2.Select().Where("id = 1").LockExclusive())); + + // Session2 blocks due to to LockShared() not allowing to modify locked documents. + Result result1; + Assert.Throws(() => result1 = table2.Update().Where("id = 1").Set("a", 2).Execute()); + + // Session2 returns immediately as session is committed. + session.Commit(); + var result = table2.Update().Where("id = 1").Set("a", 2).Execute(); + Assert.AreEqual(1, (int)result.AffectedItemsCount, "Matching the record count"); + session.SQL("ROLLBACK").Execute(); + session2.SQL("ROLLBACK").Execute(); + } + } + + [Test, Description("Reading a locked document(shared/exclusive) in a table using SKIPLOCK and NOWAIT waiting options when CRUD is happening parallely")] + public void SingleLockExclusiveWithNoWaitAndSkip() + { + if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher"); + + session.SQL("DROP TABLE IF EXISTS test.test").Execute(); + session.SQL("CREATE TABLE test.test (id INT, a INT)").Execute(); + var table1 = testSchema.GetTable("test"); + table1.Insert("id", "a").Values(1, 1).Values(2, 2).Values(3, 3).Execute(); + + using (var session2 = MySQLX.GetSession(ConnectionString)) + { + var table = session.Schema.GetTable("test"); + session.SQL("CREATE UNIQUE INDEX myIndex ON test.test (id)").Execute(); + var table2 = session2.GetSchema("test").GetTable("test"); + + session.SQL("START TRANSACTION").Execute(); + var result1 = table.Update().Where("id = 1").Set("a", 2).Execute(); + + session2.SQL("START TRANSACTION").Execute(); + // Should return immediately since document isn't locked. + var rowResult1 = table2.Select().Where("id = 2").LockExclusive(LockContention.NoWait).Execute(); + Assert.AreEqual(1, rowResult1.FetchAll().Count, "Matching the document ID"); + + // Session2 blocks due to to LockExclusive() not allowing to read locked documents. + ExecuteSQLStatement(session2.SQL("SET SESSION innodb_lock_wait_timeout=1")); + Assert.Throws(() => ExecuteSelectStatement(table2.Select().Where("id = 1").LockExclusive(LockContention.NoWait))); + Assert.Throws(() => ExecuteSelectStatement(table2.Select().Where("id = 1").LockShared(LockContention.NoWait))); + + var rowResult = table2.Select().Where("id = 1").LockShared(LockContention.SkipLocked).Execute(); + Assert.AreEqual(0, rowResult.FetchAll().Count, "Matching the document ID"); + + rowResult = table2.Select().Where("id = 1").LockExclusive(LockContention.SkipLocked).Execute(); + Assert.AreEqual(0, rowResult.FetchAll().Count, "Matching the document ID"); + + session.SQL("ROLLBACK").Execute(); + session2.SQL("ROLLBACK").Execute(); + } + } + + [Test, Description("Multiple lock calls on a document in table using NOWAIT and SKIPLOCK waiting options")] + public void ChainedExclusiveLocks() + { + if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher"); + + session.SQL("DROP TABLE IF EXISTS test.test").Execute(); + session.SQL("CREATE TABLE test.test (id INT, a INT)").Execute(); + var table1 = testSchema.GetTable("test"); + table1.Insert("id", "a").Values(1, 1).Values(2, 2).Values(3, 3).Execute(); + + using (var session2 = MySQLX.GetSession(ConnectionString)) + { + var table = session.Schema.GetTable("test"); + session.SQL("CREATE UNIQUE INDEX myIndex ON test.test (id)").Execute(); + var table2 = session2.GetSchema("test").GetTable("test"); + + session.SQL("START TRANSACTION").Execute(); + var rowResult = table.Select().Where("id = 1").LockShared().Execute(); + Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); + + session2.SQL("START TRANSACTION").Execute(); + ExecuteSQLStatement(session2.SQL("SET SESSION innodb_lock_wait_timeout=1")); + Assert.Throws(() => rowResult = table2.Select().Where("id = 1").LockExclusive(LockContention.SkipLocked).LockExclusive(LockContention.NoWait).Execute()); + + Assert.Throws(() => ExecuteSelectStatement(table2.Select().Where("id = 1") + .LockExclusive(LockContention.SkipLocked) + .LockExclusive(LockContention.NoWait))); + + rowResult = table2.Select().Where("id = 1").LockExclusive(LockContention.SkipLocked).LockShared(LockContention.SkipLocked).Execute(); + Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); + + rowResult = table2.Select().Where("id = 1").LockShared(LockContention.SkipLocked).LockExclusive(LockContention.SkipLocked).Execute(); + Assert.AreEqual(0, rowResult.FetchAll().Count, "Matching the document ID"); + session.SQL("ROLLBACK").Execute(); + session2.SQL("ROLLBACK").Execute(); + } + } + + [Test, Description("Test MySQLX plugin - MYSQLCNET 755 Table GetIncrementValue")] + public void TableGetAutoIncrementValue() + { + if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher"); + + session.SQL("CREATE TABLE address1" + + "(address_number1 MEDIUMINT NOT NULL AUTO_INCREMENT, " + + "address_number2 CHAR(100) NOT NULL, " + + "PRIMARY KEY (address_number1)" + ");").Execute(); + Table table = testSchema.GetTable("address1"); + var result = table.Insert("address_number1", "address_number2") + .Values(100, "Test the document id in address table") + .Execute(); + + var docId = result.AutoIncrementValue; + Assert.AreEqual("100", docId.ToString(), "Matching the value if already it is inserted"); + + result = table.Insert("address_number2") + .Values("Test the document id by 2nd insert without id in address table") + .Execute(); + docId = result.AutoIncrementValue; + Assert.AreEqual("101", docId.ToString(), "Matching the value if already it is inserted"); + + session.SQL("CREATE TABLE address2" + + "(address_number3 INT NOT NULL AUTO_INCREMENT, " + + "address_number4 CHAR(100) NOT NULL, " + + "PRIMARY KEY (address_number3)" + ");").Execute(); + table = testSchema.GetTable("address2"); + result = table.Insert("address_number4") + .Values("Test the document id in address table without unique id") + .Execute(); + + docId = result.AutoIncrementValue; + Assert.AreEqual("1", docId.ToString(), "Matching the auto increment value"); + + session.SQL("CREATE TABLE address3" + + "(address_number5 MEDIUMINT NOT NULL AUTO_INCREMENT, " + + "address_number6 CHAR(100) NOT NULL, " + + "PRIMARY KEY (address_number5)" + ");").Execute(); + table = testSchema.GetTable("address3"); + result = table.Insert("address_number5", "address_number6") + .Values(100, "Test multiple document ids in address table - 1st document") + .Values(200, "Test multiple document ids in address table - 2nd document") + .Values(300, "Test multiple document ids in address table - 3rd document") + .Execute(); + + docId = result.AutoIncrementValue; + Assert.AreEqual("300", docId.ToString(), "Matching the value if more than one documents inserted"); + + result = table.Insert("address_number6") + .Values("Test multiple document ids in address table - 4th document without ID") + .Values("Test multiple document ids in address table - 5th document without ID") + .Values("Test multiple document ids in address table - 6th document without ID") + .Execute(); + + docId = result.AutoIncrementValue; + Assert.AreEqual("301", docId.ToString(), "Matching the value if more than one documents inserted"); + + session.SQL("CREATE TABLE address4" + + "(address_number7 INT NOT NULL AUTO_INCREMENT, " + + "address_number8 CHAR(100) NOT NULL, " + + "PRIMARY KEY (address_number7)" + ");").Execute(); + table = testSchema.GetTable("address4"); + result = table.Insert("address_number8") + .Values("Test the document ids in address table without unique id - 1st document") + .Values("Test the document ids in address table without unique id - 2nd document") + .Values("Test the document ids in address table without unique id - 3rd document") + .Execute(); + + docId = result.AutoIncrementValue; + Assert.AreEqual("1", docId.ToString(), "Matching the auto increment value"); + + result = table.Insert("address_number8") + .Values("Test the document ids in address table without unique id - 4th document") + .Values("Test the document ids in address table without unique id - 5th document") + .Values("Test the document ids in address table without unique id - 6th document") + .Execute(); + + docId = result.AutoIncrementValue; + Assert.AreEqual("4", docId.ToString(), "Matching the auto increment value"); + + session.SQL("CREATE TABLE address5" + + "(address_number9 INT, " + + "address_number10 CHAR(100));").Execute(); + + session.SQL("ALTER TABLE address5 ADD c INT UNSIGNED NOT NULL AUTO_INCREMENT, ADD PRIMARY KEY(c)").Execute(); + + table = testSchema.GetTable("address5"); + result = table.Insert("address_number9", "address_number10") + .Values(100, "Test the document ids in address table without unique id - 1st document") + .Values(200, "Test the document ids in address table without unique id - 2nd document") + .Values(300, "Test the document ids in address table without unique id - 3rd document") + .Execute(); + + docId = result.AutoIncrementValue; + Assert.AreEqual("1", docId.ToString(), "Matching the auto increment value"); + session.SQL("drop table if exists address1").Execute(); + session.SQL("drop table if exists address2").Execute(); + session.SQL("drop table if exists address3").Execute(); + session.SQL("drop table if exists address4").Execute(); + session.SQL("drop table if exists address5").Execute(); + } + + [Test, Description("Test MySQLX plugin - MYSQLCNET_684 Fetchone returns null when no rows")] + public void FetchoneReturnsNullNoRows() + { + ExecuteSQL("CREATE TABLE test1(id INT)"); + ExecuteSQL("INSERT INTO test1 VALUES (1),(2),(3),(4)"); + ExecuteSQL("CREATE TABLE test2(id INT, val INT)"); + ExecuteSQL("INSERT INTO test2 VALUES (1,0)"); + var rowResult = testSchema.GetTable("test1").Select("id").Execute(); + foreach (var row in rowResult) + { + var result = testSchema.GetTable("test2").Update().Where("id=1").Set("val", row["id"]).Execute(); + //WL11843-Core API v1 alignment Changes + Assert.AreEqual(1, result.AffectedItemsCount, "Matching"); + } + + Row valRow = testSchema.GetTable("test2").Select("val").Execute().FetchOne(); + Assert.AreEqual("4", valRow[0].ToString(), "Matching"); + ExecuteSQL("DELETE FROM test2 WHERE id=1"); + valRow = testSchema.GetTable("test2").Select("val").Execute().FetchOne(); + Assert.IsNull(valRow); + ExecuteSQL("DROP TABLE if exists test1"); + ExecuteSQL("DROP TABLE if exists test2"); + } + + [Test, Description("Test MySQLX plugin - MYSQLCNET_684 Fetchone returns null when no table")] + public void FetchoneReturnsNullNoTable() + { + ExecuteSQL("CREATE TABLE test111(id INT)"); + ExecuteSQL("INSERT INTO test111 VALUES (1),(2),(3),(4)"); + ExecuteSQL("CREATE TABLE test222(id INT, val INT)"); + ExecuteSQL("INSERT INTO test222 VALUES (1,0)"); + var rowResult = testSchema.GetTable("test111").Select("id").Execute(); + foreach (var row in rowResult) + { + var result = testSchema.GetTable("test222").Update().Where("id=1").Set("val", row["id"]).Execute(); + //WL11843-Core API v1 alignment Changes + Assert.AreEqual(1, result.AffectedItemsCount, "Matching"); + } + + Row valRow = testSchema.GetTable("test222").Select("val").Execute().FetchOne(); + Assert.AreEqual("4", valRow[0].ToString(), "Matching"); + ExecuteSQL("DROP TABLE test222"); + Assert.Throws(() => valRow = testSchema.GetTable("test222").Select("val").Execute().FetchOne()); + ExecuteSQL("DROP TABLE IF EXISTS test111"); + } + + [Test, Description("MySQLX CNET-Test Table.Select() with exclusive lock and Table.Update() normal from two sessions. ")] + public void DoubleChainedLocksWithTwoSessions_S1() + { + if (!session.InternalSession.GetServerVersion().isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); + + session.SQL("SET autocommit = 0").Execute(); + using (var session2 = MySQLX.GetSession(ConnectionString)) + { + session2.SQL("SET autocommit = 0").Execute(); + var table = session.Schema.GetTable("test"); + session.SQL("CREATE UNIQUE INDEX myIndex ON test.test (id)").Execute(); + var table2 = session2.GetSchema("test").GetTable("test"); + + session.SQL("START TRANSACTION").Execute(); + var rowResult = table.Select().Where("id = 1").LockExclusive().Execute(); + Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the record ID"); + + session2.SQL("START TRANSACTION").Execute(); + // Should return immediately since document isn't locked. + rowResult = table2.Select().Where("id = 2").LockExclusive().Execute(); + Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the record ID"); + + // Session2 blocks due to to LockExclusive() not allowing to read locked documents. + ExecuteSQLStatement(session2.SQL("SET SESSION innodb_lock_wait_timeout=1")); + Assert.Throws(() => ExecuteSelectStatement(table2.Select().Where("id = 1").LockExclusive())); + + // Session2 blocks due to to LockExclusive() not allowing to modify locked documents. + Result result1; + Assert.Throws(() => result1 = table2.Update().Where("id = 1").Set("age", 2).Execute()); + + session.SQL("ROLLBACK").Execute(); + session2.SQL("ROLLBACK").Execute(); + } + + using (var session2 = MySQLX.GetSession(ConnectionString)) + { + session2.SQL("SET autocommit = 0").Execute(); + var table = session.Schema.GetTable("test"); + var table2 = session2.GetSchema("test").GetTable("test"); + + session.SQL("START TRANSACTION").Execute(); + var rowResult = table.Select().Where("id = 1").LockShared().LockExclusive().Execute(); + Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the record ID"); + + session2.SQL("START TRANSACTION").Execute(); + // Should return immediately since document isn't locked. + rowResult = table2.Select().Where("id = 2").LockShared().LockExclusive().Execute(); + Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the record ID"); + + // Session2 blocks due to to LockExclusive() not allowing to read locked documents. + ExecuteSQLStatement(session2.SQL("SET SESSION innodb_lock_wait_timeout=1")); + Assert.Throws(() => ExecuteSelectStatement(table2.Select().Where("id = 1").LockShared().LockExclusive())); + + // Session2 blocks due to to LockExclusive() not allowing to modify locked documents. + Result result1; + Assert.Throws(() => result1 = table2.Update().Where("id = 1").Set("age", 2).Execute()); + session.SQL("ROLLBACK").Execute(); + session2.SQL("ROLLBACK").Execute(); + } + session.SQL("SET autocommit = 1").Execute(); + } + + [Test, Description("MySQLX CNET-Test Table.Select() with shared lock and Table.Update() normal from two sessions. ")] + public void DoubleChainedLocksWithTwoSessions_S2() + { + if (!session.InternalSession.GetServerVersion().isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); + + session.SQL("SET autocommit = 0").Execute(); + using (var session2 = MySQLX.GetSession(ConnectionString)) + { + session2.SQL("SET autocommit = 0").Execute(); + var table = session.Schema.GetTable("test"); + session.SQL("CREATE UNIQUE INDEX myIndex ON test.test (id)").Execute(); + var table2 = session2.GetSchema("test").GetTable("test"); + + session.SQL("START TRANSACTION").Execute(); + var rowResult = table.Select().Where("id = 1").LockShared().Execute(); + Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the record ID"); + + session2.SQL("START TRANSACTION").Execute(); + // Should return immediately since document isn't locked. + rowResult = table2.Select().Where("id = 1").Execute(); + Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the record ID"); + + // Session2 blocks due to to LockExclusive() not allowing to read locked documents. + ExecuteSQLStatement(session2.SQL("SET SESSION innodb_lock_wait_timeout=1")); + var result = table2.Update().Where("id = 2").Set("age", 30).Execute(); + Assert.AreEqual(1, (int)result.AffectedItemsCount, "Match being done"); + Assert.Throws(() => ExecuteSelectStatement(table2.Select().Where("id = 1").LockExclusive())); + + // Session2 blocks due to to LockExclusive() not allowing to modify locked documents. + Result result1; + Assert.Throws(() => result1 = table2.Update().Where("id = 1").Set("age", 2).Execute()); + + session.SQL("ROLLBACK").Execute(); + session2.SQL("ROLLBACK").Execute(); + } + + session.SQL("SET autocommit = 0").Execute(); + using (var session2 = MySQLX.GetSession(ConnectionString)) + { + session2.SQL("SET autocommit = 0").Execute(); + var table = session.Schema.GetTable("test"); + var table2 = session2.GetSchema("test").GetTable("test"); + + session.SQL("START TRANSACTION").Execute(); + var rowResult = table.Select().Where("id = 1").LockExclusive().LockShared().Execute(); + Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the record ID"); + + session2.SQL("START TRANSACTION").Execute(); + // Should return immediately since document isn't locked. + rowResult = table2.Select().Where("id = 1").Execute(); + Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the record ID"); + + // Session2 blocks due to to LockExclusive() not allowing to read locked documents. + session2.SQL("SET SESSION innodb_lock_wait_timeout=1").Execute(); + var result = table2.Update().Where("id = 2").Set("age", 30).Execute(); + Assert.AreEqual(1, (int)result.AffectedItemsCount, "Match being done"); + Assert.Throws(() => ExecuteSelectStatement(table2.Select().Where("id = 1").LockShared().LockExclusive())); + + // Session2 blocks due to to LockExclusive() not allowing to modify locked documents. + Result result1; + Assert.Throws(() => result1 = table2.Update().Where("id = 1").Set("age", 2).Execute()); + session.SQL("ROLLBACK").Execute(); + session2.SQL("ROLLBACK").Execute(); + } + session.SQL("SET autocommit = 1").Execute(); + } + + [Test, Description("MySQLX CNET-Test Table.Select() with exclusive lock from two sessions. ")] + public void SingleExclusiveLock() + { + if (!session.InternalSession.GetServerVersion().isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); + + session.SQL("SET autocommit = 0").Execute(); + using (var session2 = MySQLX.GetSession(ConnectionString)) + { + session2.SQL("SET autocommit = 0").Execute(); + var table = session.Schema.GetTable("test"); + session.SQL("CREATE UNIQUE INDEX myIndex ON test.test (id)").Execute(); + var table2 = session2.GetSchema("test").GetTable("test"); + + session.SQL("START TRANSACTION").Execute(); + var rowResult = table.Select().Where("id = 1").LockExclusive().Execute(); + Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the record ID"); + + session2.SQL("START TRANSACTION").Execute(); + // Should return immediately since document isn't locked. + rowResult = table2.Select().Where("id = 2").Execute(); + Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the record ID"); + + // Session2 blocks due to to LockExclusive() not allowing to read locked documents. + session2.SQL("SET SESSION innodb_lock_wait_timeout=1").Execute(); + Assert.Throws(() => ExecuteSelectStatement(table2.Select().Where("id = 1").LockExclusive())); + session.SQL("ROLLBACK").Execute(); + session2.SQL("ROLLBACK").Execute(); + } + session.SQL("SET autocommit = 1").Execute(); + } + + [Test, Description("MySQLX CNET-Test Table.Select() with exclusive lock and Table.Select() with exclusive lock from two sessions-Select multiple records")] + public void SingleTransactionWithLocks() + { + if (!session.InternalSession.GetServerVersion().isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); + + session.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED").Execute(); + using (var session2 = MySQLX.GetSession(ConnectionString)) + { + session2.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED").Execute(); + session.SQL("CREATE UNIQUE INDEX myIndex ON test.test (id)").Execute(); + var table = session.Schema.GetTable("test"); + var table2 = session2.GetSchema("test").GetTable("test"); + + session.SQL("START TRANSACTION").Execute(); + var rowResult = table.Select().Where("id in (1,3)").LockShared().Execute(); + Assert.AreEqual(2, rowResult.FetchAll().Count, "Matching the record ID"); + + rowResult = table2.Select().Where("id = 2").LockExclusive().Execute(); + Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the record ID"); + rowResult = table2.Select().Where("id = 2").LockShared().Execute(); + Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the record ID"); + // Session2 blocks due to to LockExclusive() not allowing to read locked documents. + session.SQL("SET SESSION innodb_lock_wait_timeout=1").Execute(); + table2.Select().Where("id = 2").LockExclusive().Execute(); + Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the record ID"); + session2.SQL("SET SESSION innodb_lock_wait_timeout=1").Execute(); + Assert.Throws(() => ExecuteSelectStatement(table2.Select().Where("id = 1").LockExclusive())); + + session2.SQL("SET SESSION innodb_lock_wait_timeout=1").Execute(); + // Session2 blocks due to to LockExclusive() not allowing to modify locked documents. + Assert.Throws(() => ExecuteUpdateStatement(table2.Update().Where("id = 1").Set("age", 2))); + + session.SQL("ROLLBACK").Execute(); + rowResult = table2.Select().Where("id = 1").LockExclusive().Execute(); + Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); + session2.SQL("ROLLBACK").Execute(); + rowResult = table.Select().Where("id = 2").LockExclusive().Execute(); + Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); + } + } + + [Test, Description("MySQLX CNET-Test Table.Select() with exclusive lock and Table.Update() normal from two sessions-50 Iterations")] + public void IteratedExclusiveLocks() + { + if (!Platform.IsWindows()) Assert.Ignore("This test is for Windows OS only"); + if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); + + session.SQL("SET autocommit = 0").Execute(); + session.SQL("CREATE UNIQUE INDEX myIndex ON test.test (id)").Execute(); + const int iterations = 30; + for (var i = 0; i < iterations; i++) + { + using (var session2 = MySQLX.GetSession(ConnectionString)) + { + session2.SQL("SET autocommit = 0").Execute(); + var table = session.Schema.GetTable("test"); + + var table2 = session2.GetSchema("test").GetTable("test"); + + session.SQL("START TRANSACTION").Execute(); + var rowResult = table.Select().Where("id = 1").LockExclusive().Execute(); + Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the record ID"); + + session2.SQL("START TRANSACTION").Execute(); + // Should return immediately since document isn't locked. + rowResult = table2.Select().Where("id = 2").LockExclusive().Execute(); + Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the record ID"); + + // Session2 blocks due to to LockExclusive() not allowing to read locked documents. + session2.SQL("SET SESSION innodb_lock_wait_timeout=1").Execute(); + Assert.Throws(() => ExecuteSelectStatement(table2.Select().Where("id = 1").LockExclusive())); + + // Session2 blocks due to to LockExclusive() not allowing to modify locked documents. + Result result1; + Assert.Throws(() => result1 = table2.Update().Where("id = 1").Set("age", 2).Execute()); + session.SQL("ROLLBACK").Execute(); + session2.SQL("ROLLBACK").Execute(); + } + } + session.SQL("SET autocommit = 1").Execute(); + } + + #endregion WL14389 + + #region Methods + public static string RandomString(int length) + { + const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + const string chars1 = "ABCDEFGHIJ"; + var random = new Random(); + if (length == 20) + { + return chars1; + } + else + { + return new string(Enumerable.Repeat(chars, length) + .Select(s => s[random.Next(s.Length)]).ToArray()); + } + + } + #endregion Methods + } +} diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/TableUpdateTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/TableUpdateTests.cs index 619b7109e..ab9946777 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/TableUpdateTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/TableUpdateTests.cs @@ -1,367 +1,367 @@ -// Copyright (c) 2015, 2021, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySql.Data.MySqlClient; -using MySqlX.XDevAPI.Common; -using MySqlX.XDevAPI.Relational; -using NUnit.Framework; -using System; -using System.Collections.Generic; -using MySqlX.XDevAPI; - -namespace MySqlX.Data.Tests.RelationalTests -{ - public class TableUpdateTests : BaseTest - { - Table table; - - [TearDown] - public void TearDown() => ExecuteSQL("DROP TABLE IF EXISTS test"); - - [SetUp] - public void SetUp() - { - ExecuteSQL("CREATE TABLE test.test(id INT, name VARCHAR(40), age INT)"); - - table = testSchema.GetTable("test"); - var insertStatement = table.Insert(); - int rowsToInsert = 10; - for (int i = 1; i <= rowsToInsert; i++) - { - insertStatement.Values(i, i, i); - } - ExecuteInsertStatement(insertStatement); - Assert.AreEqual(rowsToInsert, CountRows()); - } - - private int CountRows() - { - return GetRows(null).Count; - } - - private IReadOnlyCollection GetRows(FilterParams filter) - { - var statement = table.Select(); - if (filter != null) - { - statement.FilterData.Condition = filter.Condition; - statement.FilterData.Limit = filter.Limit; - statement.FilterData.OrderBy = filter.OrderBy; - statement.FilterData.Parameters = filter.Parameters; - } - var result = ExecuteSelectStatement(statement); - while (result.Next()) ; - return result.Rows; - } - - private void ValidateUpdate(TableUpdateStatement statement) - { - Dictionary parameters = new Dictionary(statement.FilterData.Parameters); - var result = ExecuteUpdateStatement(statement); - statement.FilterData.Parameters = parameters; - var rows = GetRows(statement.FilterData); - foreach (var row in rows) - { - foreach (var set in statement.updates) - { - Assert.AreEqual(set.Value.ToString(), row.GetString(set.Path)); - } - } - } - - [Test] - public void EmptyUpdateTest() - { - Assert.Throws(() => ExecuteUpdateStatement(table.Update())); - } - - [Test] - public void UpdateConditionTest() - { - ValidateUpdate(table.Update().Where("id = 5").Set("name", "other")); - } - - [Test] - public void UpdateMultiSet() - { - ValidateUpdate(table.Update().Set("name", "other") - .Set("age", 21) - .Set("id", 30) - .Where("id = 3")); - } - - [Test] - public void UpdateMultiRows() - { - ValidateUpdate(table.Update().Set("age", 85).Where("id % 2 = 0")); - } - - [Test] - public void UpdateAllRows() - { - ValidateUpdate(table.Update().Set("age", 32).Set("name", "jonh")); - } - - [Test] - public void UpdateOrderbyAndLimit() - { - ValidateUpdate(table.Update().Set("age", 15).OrderBy("id DES").Limit(5)); - } - - [Test] - public void UpdateBind() - { - var stmt = table.Update().Set("age", 55).Where("id = :id or id = :id or id = :id2"); - ValidateUpdate(stmt.Bind("id", 4).Bind("id2", 7)); - ValidateUpdate(stmt.Bind("id", 5).Bind("id2", 8)); - } - - [Test] - public void UpdateWithInOperator() - { - Table table = testSchema.GetTable("test"); - Assert.AreEqual(10, CountRows()); - - Assert.AreEqual(2, ExecuteUpdateStatement(table.Update().Where("id IN (1,2)").Set("id", 0)).AffectedItemsCount); - Assert.AreEqual(2, ExecuteSelectStatement(table.Select().Where("id = 0")).FetchAll().Count); - - Assert.Throws(() => ExecuteDeleteStatement(table.Delete().Where("a IN [3]"))); - Assert.Throws(() => ExecuteDeleteStatement(table.Delete().Where("3 IN a"))); - Assert.Throws(() => ExecuteUpdateStatement(table.Update().Where("age IN [3]").Set("id", 0))); - - Assert.AreEqual(1, ExecuteUpdateStatement(table.Update().Where("age IN (3)").Set("id", 0)).AffectedItemsCount); - Assert.AreEqual(3, ExecuteSelectStatement(table.Select().Where("id = 0")).FetchAll().Count); - } - - #region WL14389 - - [Test, Description("Collection.Find(condition).GroupBy(SearchExprStr)")] - public void TableSelectGroupBy() - { - ExecuteSQLStatement(session.SQL("set sql_mode = 'STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION';")); - session.SQL("delete from test").Execute(); - Table table = testSchema.GetTable("test"); - var result1 = table.Insert("id", "name", "age") - .Values(1, "jonh doe", 38) - .Values(2, "milton greenh", 45) - .Values(3, "larry smith", 24) - .Values(4, "mary weinstein", 24) - .Values(5, "jerry pratt", 45) - .Values(6, "hugh jackman", 20) - .Values(7, "elizabeth olsen", 31) - .Execute(); - RowResult result = table.Select().OrderBy("age desc").Execute(); - Assert.Throws(() => table.Delete().Limit(1).Offset(3).Execute()); - - var t2 = table.Delete().Limit(1).Offset(0).Execute(); - result1 = table.Insert("id", "name", "age") - .Values(1, "jonh doe", 38) - .Execute(); - - Assert.Throws(() => table.Update().Set("name", "updated").Limit(1).Offset(3).Execute()); - - t2 = table.Update().Set("name", "updated").Limit(1).Offset(0).Execute(); - var t = table.Select().Limit(1).Offset(3).Execute(); - t = table.Select().Limit(10).Offset(3).Execute(); - Assert.Throws(() => ExecuteSelectStatement(table.Select().Limit(-1).Offset(3))); - - t = table.Select().Limit(100000000).Offset(3).Execute(); - t = table.Select().Limit(2).Offset(-1).Execute(); - t = table.Select().Limit(2).Offset(1000000).Execute(); - - result = table.Select().GroupBy("age").Execute(); - Assert.AreEqual(5, result.FetchAll().Count); - - // GroupBy with null. - result = table.Select("id as ID", "name as Name", "age as Age").GroupBy(null).Execute(); - Assert.AreEqual(7, result.FetchAll().Count); - - result = table.Select("id as ID", "name as Name", "age as Age").GroupBy(null, null).Execute(); - Assert.AreEqual(7, result.FetchAll().Count); - - result = table.Select("id as ID", "name as Name", "age as Age").GroupBy(null, "age").Execute(); - Assert.AreEqual(5, result.FetchAll().Count); - - // Having operation. - // Having reduces the original 5 rows to 3 since 2 rows have a cnt=2, due to the repeated names. - result = table.Select("id", "count(name) as cnt", "age").GroupBy("age").Having("cnt = 1").Execute(); - Assert.AreEqual(3, result.FetchAll().Count); - - // Having with null. - result = table.Select("id as ID", "count(name) as cnt", "age as Age").GroupBy("age").Having(null).Execute(); - Assert.AreEqual(5, result.FetchAll().Count); - - // GroupBy with invalid field name. - Exception ex = Assert.Throws(() => ExecuteSelectStatement(table.Select("id as ID", "name as Name", "age as Age").GroupBy("Required"))); - Assert.AreEqual("Unknown column 'Required' in 'group statement'", ex.Message); - - ex = Assert.Throws(() => ExecuteSelectStatement(table.Select("id as ID", "name as Name", "age as Age").GroupBy(""))); - Assert.AreEqual("No more tokens when expecting one at token pos 0", ex.Message); - - ex = Assert.Throws(() => ExecuteSelectStatement(table.Select("id as ID", "name as Name", "age as Age").GroupBy(" "))); - Assert.AreEqual("No more tokens when expecting one at token pos 0", ex.Message); - - ex = Assert.Throws(() => ExecuteSelectStatement(table.Select("id as ID", "name as Name", "age as Age").GroupBy(string.Empty))); - Assert.AreEqual("No more tokens when expecting one at token pos 0", ex.Message); - - ex = Assert.Throws(() => ExecuteSelectStatement(table.Select("id as ID", "count(name) as cnt", "age as Age").GroupBy("age").Having("Required = 1"))); - Assert.AreEqual("Unknown column 'Required' in 'having clause'", ex.Message); - - ex = Assert.Throws(() => ExecuteSelectStatement(table.Select("id as ID", "count(name) as cnt", "age as Age").GroupBy("age").Having(""))); - Assert.AreEqual("Unable to parse query ''", ex.Message); - Assert.AreEqual("No more tokens when expecting one at token pos 0", ex.InnerException.Message); - - Assert.Throws(() => ExecuteSelectStatement(table.Select("id as ID", "count(name) as cnt", "age as Age").GroupBy("age").Having(" "))); - Assert.Throws(() => ExecuteSelectStatement(table.Select("id as ID", "count(name) as cnt", "age as Age").GroupBy("age").Having(string.Empty))); - } - - [Test, Description("Reading exclusively locked document in a table using lock_shared with DEFAULT waiting option.")] - public void ExclusiveLockBeforeSharedLockDefaultWaiting() - { - if (!session.InternalSession.GetServerVersion().isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); - - session.SQL("DROP TABLE IF EXISTS test.test").Execute(); - session.SQL("CREATE TABLE test.test (id INT, a INT)").Execute(); - var table1 = testSchema.GetTable("test"); - table1.Insert("id", "a").Values(1, 1).Values(2, 2).Values(3, 3).Execute(); - using (var session2 = MySQLX.GetSession(ConnectionString)) - { - var table = session.Schema.GetTable("test"); - session.SQL("CREATE UNIQUE INDEX myIndex ON test.test (id)").Execute(); - var table2 = session2.GetSchema("test").GetTable("test"); - - session.SQL("START TRANSACTION").Execute(); - var rowResult = table.Select().Where("id = 1").LockExclusive().Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); - - session2.SQL("START TRANSACTION").Execute(); - // Should return immediately since document isn't locked. - rowResult = table2.Select().Where("id = 2").LockShared(LockContention.Default).Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); - - // Session2 blocks due to to LockExclusive() not allowing to read locked documents. - session2.SQL("SET SESSION innodb_lock_wait_timeout=1").Execute(); - Assert.Throws(() => ExecuteSelectStatement(table2.Select().Where("id = 1").LockShared(LockContention.Default))); - - // Session2 blocks due to to LockExclusive() not allowing to modify locked documents. - Result result1; - Assert.Throws(() => result1 = table2.Update().Where("id = 1").Set("a", 2).Execute()); - - // Session2 returns immediately as session is committed. - session.Commit(); - var result = table2.Update().Where("id = 1").Set("a", 2).Execute(); - Assert.AreEqual(1, (int)result.AffectedItemsCount, "Matching the deleted record count"); - - session.SQL("ROLLBACK").Execute(); - session2.SQL("ROLLBACK").Execute(); - } - } - - [Test, Description("Reading locked document(lock_shared) in a table using lock_shared with DEFAULT waiting option.")] - public void SharedLockDefaultWaiting() - { - if (!session.InternalSession.GetServerVersion().isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); - - session.SQL("DROP TABLE IF EXISTS test.test").Execute(); - session.SQL("CREATE TABLE test.test (id INT, a INT)").Execute(); - var table1 = testSchema.GetTable("test"); - table1.Insert("id", "a").Values(1, 1).Values(2, 2).Values(3, 3).Execute(); - using (var session2 = MySQLX.GetSession(ConnectionString)) - { - var table = session.Schema.GetTable("test"); - var table2 = session2.GetSchema("test").GetTable("test"); - - session.SQL("START TRANSACTION").Execute(); - var rowResult = table.Select().Where("id = 1").LockShared().Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); - - session2.SQL("START TRANSACTION").Execute(); - // Should return immediately since document isn't locked. - rowResult = table2.Select().Where("id = 2").LockShared(LockContention.Default).Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); - - session2.SQL("SET SESSION innodb_lock_wait_timeout=1").Execute(); - rowResult = table2.Select().Where("id = 1").LockShared(LockContention.Default).Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); - // Session2 blocks due to to LockShared() not allowing to modify locked documents. - Result result1; - Assert.Throws(() => result1 = table2.Update().Where("id = 1").Set("a", 2).Execute()); - - // Session2 returns immediately as session is committed. - session.Commit(); - var result = table2.Update().Where("id = 1").Set("a", 2).Execute(); - - session.SQL("ROLLBACK").Execute(); - session2.SQL("ROLLBACK").Execute(); - } - } - - [Test,Description("Reading exclusively locked document in a table using lock_exclusive with DEFAULT waiting option ")] - public void OnlyExclusiveLocksWithDefaultWaiting() - { - if (!session.InternalSession.GetServerVersion().isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); - - session.SQL("DROP TABLE IF EXISTS test.test").Execute(); - session.SQL("CREATE TABLE test.test (id INT, a INT)").Execute(); - var table1 = testSchema.GetTable("test"); - table1.Insert("id", "a").Values(1, 1).Values(2, 2).Values(3, 3).Execute(); - using (var session2 = MySQLX.GetSession(ConnectionString)) - { - var table = session.Schema.GetTable("test"); - session.SQL("CREATE UNIQUE INDEX myIndex ON test.test (id)").Execute(); - var table2 = session2.GetSchema("test").GetTable("test"); - - session.SQL("START TRANSACTION").Execute(); - var rowResult = table.Select().Where("id = 1").LockExclusive().Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); - - session2.SQL("START TRANSACTION").Execute(); - // Should return immediately since document isn't locked. - rowResult = table2.Select().Where("id = 2").LockExclusive(LockContention.Default).Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); - - // Session2 blocks due to to LockExclusive() not allowing to read locked documents. - session2.SQL("SET SESSION innodb_lock_wait_timeout=1").Execute(); - Assert.Throws(() => ExecuteSelectStatement(table2.Select().Where("id = 1").LockExclusive(LockContention.Default))); - - // Session2 blocks due to to LockExclusive() not allowing to modify locked documents. - Result result1; - Assert.Throws(() => result1 = table2.Update().Where("id = 1").Set("a", 2).Execute()); - - // Session2 returns immediately as session is committed. - session.Commit(); - var result = table2.Update().Where("id = 1").Set("a", 2).Execute(); - session.SQL("ROLLBACK").Execute(); - session2.SQL("ROLLBACK").Execute(); - } - } - - #endregion WL14389 - - } -} +// Copyright © 2015, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySql.Data.MySqlClient; +using MySqlX.XDevAPI.Common; +using MySqlX.XDevAPI.Relational; +using NUnit.Framework; +using System; +using System.Collections.Generic; +using MySqlX.XDevAPI; + +namespace MySqlX.Data.Tests.RelationalTests +{ + public class TableUpdateTests : BaseTest + { + Table table; + + [TearDown] + public void TearDown() => ExecuteSQL("DROP TABLE IF EXISTS test"); + + [SetUp] + public void SetUp() + { + ExecuteSQL("CREATE TABLE test.test(id INT, name VARCHAR(40), age INT)"); + + table = testSchema.GetTable("test"); + var insertStatement = table.Insert(); + int rowsToInsert = 10; + for (int i = 1; i <= rowsToInsert; i++) + { + insertStatement.Values(i, i, i); + } + ExecuteInsertStatement(insertStatement); + Assert.AreEqual(rowsToInsert, CountRows()); + } + + private int CountRows() + { + return GetRows(null).Count; + } + + private IReadOnlyCollection GetRows(FilterParams filter) + { + var statement = table.Select(); + if (filter != null) + { + statement.FilterData.Condition = filter.Condition; + statement.FilterData.Limit = filter.Limit; + statement.FilterData.OrderBy = filter.OrderBy; + statement.FilterData.Parameters = filter.Parameters; + } + var result = ExecuteSelectStatement(statement); + while (result.Next()) ; + return result.Rows; + } + + private void ValidateUpdate(TableUpdateStatement statement) + { + Dictionary parameters = new Dictionary(statement.FilterData.Parameters); + var result = ExecuteUpdateStatement(statement); + statement.FilterData.Parameters = parameters; + var rows = GetRows(statement.FilterData); + foreach (var row in rows) + { + foreach (var set in statement.updates) + { + Assert.AreEqual(set.Value.ToString(), row.GetString(set.Path)); + } + } + } + + [Test] + public void EmptyUpdateTest() + { + Assert.Throws(() => ExecuteUpdateStatement(table.Update())); + } + + [Test] + public void UpdateConditionTest() + { + ValidateUpdate(table.Update().Where("id = 5").Set("name", "other")); + } + + [Test] + public void UpdateMultiSet() + { + ValidateUpdate(table.Update().Set("name", "other") + .Set("age", 21) + .Set("id", 30) + .Where("id = 3")); + } + + [Test] + public void UpdateMultiRows() + { + ValidateUpdate(table.Update().Set("age", 85).Where("id % 2 = 0")); + } + + [Test] + public void UpdateAllRows() + { + ValidateUpdate(table.Update().Set("age", 32).Set("name", "jonh")); + } + + [Test] + public void UpdateOrderbyAndLimit() + { + ValidateUpdate(table.Update().Set("age", 15).OrderBy("id DES").Limit(5)); + } + + [Test] + public void UpdateBind() + { + var stmt = table.Update().Set("age", 55).Where("id = :id or id = :id or id = :id2"); + ValidateUpdate(stmt.Bind("id", 4).Bind("id2", 7)); + ValidateUpdate(stmt.Bind("id", 5).Bind("id2", 8)); + } + + [Test] + public void UpdateWithInOperator() + { + Table table = testSchema.GetTable("test"); + Assert.AreEqual(10, CountRows()); + + Assert.AreEqual(2, ExecuteUpdateStatement(table.Update().Where("id IN (1,2)").Set("id", 0)).AffectedItemsCount); + Assert.AreEqual(2, ExecuteSelectStatement(table.Select().Where("id = 0")).FetchAll().Count); + + Assert.Throws(() => ExecuteDeleteStatement(table.Delete().Where("a IN [3]"))); + Assert.Throws(() => ExecuteDeleteStatement(table.Delete().Where("3 IN a"))); + Assert.Throws(() => ExecuteUpdateStatement(table.Update().Where("age IN [3]").Set("id", 0))); + + Assert.AreEqual(1, ExecuteUpdateStatement(table.Update().Where("age IN (3)").Set("id", 0)).AffectedItemsCount); + Assert.AreEqual(3, ExecuteSelectStatement(table.Select().Where("id = 0")).FetchAll().Count); + } + + #region WL14389 + + [Test, Description("Collection.Find(condition).GroupBy(SearchExprStr)")] + public void TableSelectGroupBy() + { + ExecuteSQLStatement(session.SQL("set sql_mode = 'STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION';")); + session.SQL("delete from test").Execute(); + Table table = testSchema.GetTable("test"); + var result1 = table.Insert("id", "name", "age") + .Values(1, "jonh doe", 38) + .Values(2, "milton greenh", 45) + .Values(3, "larry smith", 24) + .Values(4, "mary weinstein", 24) + .Values(5, "jerry pratt", 45) + .Values(6, "hugh jackman", 20) + .Values(7, "elizabeth olsen", 31) + .Execute(); + RowResult result = table.Select().OrderBy("age desc").Execute(); + Assert.Throws(() => table.Delete().Limit(1).Offset(3).Execute()); + + var t2 = table.Delete().Limit(1).Offset(0).Execute(); + result1 = table.Insert("id", "name", "age") + .Values(1, "jonh doe", 38) + .Execute(); + + Assert.Throws(() => table.Update().Set("name", "updated").Limit(1).Offset(3).Execute()); + + t2 = table.Update().Set("name", "updated").Limit(1).Offset(0).Execute(); + var t = table.Select().Limit(1).Offset(3).Execute(); + t = table.Select().Limit(10).Offset(3).Execute(); + Assert.Throws(() => ExecuteSelectStatement(table.Select().Limit(-1).Offset(3))); + + t = table.Select().Limit(100000000).Offset(3).Execute(); + t = table.Select().Limit(2).Offset(-1).Execute(); + t = table.Select().Limit(2).Offset(1000000).Execute(); + + result = table.Select().GroupBy("age").Execute(); + Assert.AreEqual(5, result.FetchAll().Count); + + // GroupBy with null. + result = table.Select("id as ID", "name as Name", "age as Age").GroupBy(null).Execute(); + Assert.AreEqual(7, result.FetchAll().Count); + + result = table.Select("id as ID", "name as Name", "age as Age").GroupBy(null, null).Execute(); + Assert.AreEqual(7, result.FetchAll().Count); + + result = table.Select("id as ID", "name as Name", "age as Age").GroupBy(null, "age").Execute(); + Assert.AreEqual(5, result.FetchAll().Count); + + // Having operation. + // Having reduces the original 5 rows to 3 since 2 rows have a cnt=2, due to the repeated names. + result = table.Select("id", "count(name) as cnt", "age").GroupBy("age").Having("cnt = 1").Execute(); + Assert.AreEqual(3, result.FetchAll().Count); + + // Having with null. + result = table.Select("id as ID", "count(name) as cnt", "age as Age").GroupBy("age").Having(null).Execute(); + Assert.AreEqual(5, result.FetchAll().Count); + + // GroupBy with invalid field name. + Exception ex = Assert.Throws(() => ExecuteSelectStatement(table.Select("id as ID", "name as Name", "age as Age").GroupBy("Required"))); + Assert.AreEqual("Unknown column 'Required' in 'group statement'", ex.Message); + + ex = Assert.Throws(() => ExecuteSelectStatement(table.Select("id as ID", "name as Name", "age as Age").GroupBy(""))); + Assert.AreEqual("No more tokens when expecting one at token pos 0", ex.Message); + + ex = Assert.Throws(() => ExecuteSelectStatement(table.Select("id as ID", "name as Name", "age as Age").GroupBy(" "))); + Assert.AreEqual("No more tokens when expecting one at token pos 0", ex.Message); + + ex = Assert.Throws(() => ExecuteSelectStatement(table.Select("id as ID", "name as Name", "age as Age").GroupBy(string.Empty))); + Assert.AreEqual("No more tokens when expecting one at token pos 0", ex.Message); + + ex = Assert.Throws(() => ExecuteSelectStatement(table.Select("id as ID", "count(name) as cnt", "age as Age").GroupBy("age").Having("Required = 1"))); + Assert.AreEqual("Unknown column 'Required' in 'having clause'", ex.Message); + + ex = Assert.Throws(() => ExecuteSelectStatement(table.Select("id as ID", "count(name) as cnt", "age as Age").GroupBy("age").Having(""))); + Assert.AreEqual("Unable to parse query ''", ex.Message); + Assert.AreEqual("No more tokens when expecting one at token pos 0", ex.InnerException.Message); + + Assert.Throws(() => ExecuteSelectStatement(table.Select("id as ID", "count(name) as cnt", "age as Age").GroupBy("age").Having(" "))); + Assert.Throws(() => ExecuteSelectStatement(table.Select("id as ID", "count(name) as cnt", "age as Age").GroupBy("age").Having(string.Empty))); + } + + [Test, Description("Reading exclusively locked document in a table using lock_shared with DEFAULT waiting option.")] + public void ExclusiveLockBeforeSharedLockDefaultWaiting() + { + if (!session.InternalSession.GetServerVersion().isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); + + session.SQL("DROP TABLE IF EXISTS test.test").Execute(); + session.SQL("CREATE TABLE test.test (id INT, a INT)").Execute(); + var table1 = testSchema.GetTable("test"); + table1.Insert("id", "a").Values(1, 1).Values(2, 2).Values(3, 3).Execute(); + using (var session2 = MySQLX.GetSession(ConnectionString)) + { + var table = session.Schema.GetTable("test"); + session.SQL("CREATE UNIQUE INDEX myIndex ON test.test (id)").Execute(); + var table2 = session2.GetSchema("test").GetTable("test"); + + session.SQL("START TRANSACTION").Execute(); + var rowResult = table.Select().Where("id = 1").LockExclusive().Execute(); + Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); + + session2.SQL("START TRANSACTION").Execute(); + // Should return immediately since document isn't locked. + rowResult = table2.Select().Where("id = 2").LockShared(LockContention.Default).Execute(); + Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); + + // Session2 blocks due to to LockExclusive() not allowing to read locked documents. + session2.SQL("SET SESSION innodb_lock_wait_timeout=1").Execute(); + Assert.Throws(() => ExecuteSelectStatement(table2.Select().Where("id = 1").LockShared(LockContention.Default))); + + // Session2 blocks due to to LockExclusive() not allowing to modify locked documents. + Result result1; + Assert.Throws(() => result1 = table2.Update().Where("id = 1").Set("a", 2).Execute()); + + // Session2 returns immediately as session is committed. + session.Commit(); + var result = table2.Update().Where("id = 1").Set("a", 2).Execute(); + Assert.AreEqual(1, (int)result.AffectedItemsCount, "Matching the deleted record count"); + + session.SQL("ROLLBACK").Execute(); + session2.SQL("ROLLBACK").Execute(); + } + } + + [Test, Description("Reading locked document(lock_shared) in a table using lock_shared with DEFAULT waiting option.")] + public void SharedLockDefaultWaiting() + { + if (!session.InternalSession.GetServerVersion().isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); + + session.SQL("DROP TABLE IF EXISTS test.test").Execute(); + session.SQL("CREATE TABLE test.test (id INT, a INT)").Execute(); + var table1 = testSchema.GetTable("test"); + table1.Insert("id", "a").Values(1, 1).Values(2, 2).Values(3, 3).Execute(); + using (var session2 = MySQLX.GetSession(ConnectionString)) + { + var table = session.Schema.GetTable("test"); + var table2 = session2.GetSchema("test").GetTable("test"); + + session.SQL("START TRANSACTION").Execute(); + var rowResult = table.Select().Where("id = 1").LockShared().Execute(); + Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); + + session2.SQL("START TRANSACTION").Execute(); + // Should return immediately since document isn't locked. + rowResult = table2.Select().Where("id = 2").LockShared(LockContention.Default).Execute(); + Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); + + session2.SQL("SET SESSION innodb_lock_wait_timeout=1").Execute(); + rowResult = table2.Select().Where("id = 1").LockShared(LockContention.Default).Execute(); + Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); + // Session2 blocks due to to LockShared() not allowing to modify locked documents. + Result result1; + Assert.Throws(() => result1 = table2.Update().Where("id = 1").Set("a", 2).Execute()); + + // Session2 returns immediately as session is committed. + session.Commit(); + var result = table2.Update().Where("id = 1").Set("a", 2).Execute(); + + session.SQL("ROLLBACK").Execute(); + session2.SQL("ROLLBACK").Execute(); + } + } + + [Test,Description("Reading exclusively locked document in a table using lock_exclusive with DEFAULT waiting option ")] + public void OnlyExclusiveLocksWithDefaultWaiting() + { + if (!session.InternalSession.GetServerVersion().isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); + + session.SQL("DROP TABLE IF EXISTS test.test").Execute(); + session.SQL("CREATE TABLE test.test (id INT, a INT)").Execute(); + var table1 = testSchema.GetTable("test"); + table1.Insert("id", "a").Values(1, 1).Values(2, 2).Values(3, 3).Execute(); + using (var session2 = MySQLX.GetSession(ConnectionString)) + { + var table = session.Schema.GetTable("test"); + session.SQL("CREATE UNIQUE INDEX myIndex ON test.test (id)").Execute(); + var table2 = session2.GetSchema("test").GetTable("test"); + + session.SQL("START TRANSACTION").Execute(); + var rowResult = table.Select().Where("id = 1").LockExclusive().Execute(); + Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); + + session2.SQL("START TRANSACTION").Execute(); + // Should return immediately since document isn't locked. + rowResult = table2.Select().Where("id = 2").LockExclusive(LockContention.Default).Execute(); + Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); + + // Session2 blocks due to to LockExclusive() not allowing to read locked documents. + session2.SQL("SET SESSION innodb_lock_wait_timeout=1").Execute(); + Assert.Throws(() => ExecuteSelectStatement(table2.Select().Where("id = 1").LockExclusive(LockContention.Default))); + + // Session2 blocks due to to LockExclusive() not allowing to modify locked documents. + Result result1; + Assert.Throws(() => result1 = table2.Update().Where("id = 1").Set("a", 2).Execute()); + + // Session2 returns immediately as session is committed. + session.Commit(); + var result = table2.Update().Where("id = 1").Set("a", 2).Execute(); + session.SQL("ROLLBACK").Execute(); + session2.SQL("ROLLBACK").Execute(); + } + } + + #endregion WL14389 + + } +} diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/ViewTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/ViewTests.cs index dd1975c2d..859193436 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/ViewTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/ViewTests.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2016, 2021, Oracle and/or its affiliates. +// Copyright © 2016, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/SchemaTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/SchemaTests.cs index a2151ce2c..517bcac3e 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/SchemaTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/SchemaTests.cs @@ -1,297 +1,297 @@ -// Copyright (c) 2015, 2021, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySql.Data.MySqlClient; -using MySqlX.XDevAPI; -using MySqlX.XDevAPI.Common; -using MySqlX.XDevAPI.Relational; -using NUnit.Framework; -using System; -using System.Collections.Generic; -using System.Linq; - -namespace MySqlX.Data.Tests -{ - public class SchemaTests : BaseTest - { - [TearDown] - public void TearDown() => ExecuteSQL("DROP TABLE IF EXISTS test"); - [Test] - public void GetSchemas() - { - Session session = GetSession(); - List schemas = session.GetSchemas(); - - Assert.True(schemas.Exists(s => s.Name == base.testSchema.Name)); - - Schema schema = session.GetSchema(schemaName); - Assert.AreEqual(schemaName, schema.Name); - schema = session.GetSchema(null); - Assert.IsNull(schema.Name); - } - - [Test] - public void GetInvalidSchema() - { - Session s = GetSession(); - Schema schema = s.GetSchema("test-schema"); - Assert.False(SchemaExistsInDatabase(schema)); - } - - [Test] - public void GetAllTables() - { - ExecuteSQL("DROP TABLE IF EXISTS test"); - ExecuteSQL("CREATE TABLE test(id int)"); - - List
tables = testSchema.GetTables(); - Assert.True(tables.Count == 1); - } - - [Test] - public void GetAllViews() - { - CreateCollection("coll"); - - ExecuteSQL("DROP TABLE IF EXISTS test"); - ExecuteSQL("CREATE TABLE test(id int)"); - ExecuteSQL("CREATE VIEW view1 AS select * from test"); - ExecuteSQL("CREATE VIEW view2 AS select * from test"); - - List
tables = testSchema.GetTables(); - Assert.AreEqual(3, tables.Count); - Assert.AreEqual(1, tables.Count(i => !i.IsView)); - Assert.AreEqual(2, tables.Count(i => i.IsView)); - - List colls = testSchema.GetCollections(); - Assert.That(colls, Has.One.Items); - } - - [Test] - [Ignore("Fix for 8.0.13")] - public void GetCollectionAsTable() - { - Collection testCollection = CreateCollection("test"); - - Result r = ExecuteAddStatement(testCollection.Add(@"{ ""_id"": 1, ""foo"": 1 }")); - Assert.AreEqual(1, r.AffectedItemsCount); - - Table test = testSchema.GetCollectionAsTable("test"); - Assert.True(TableExistsInDatabase(test)); - - RowResult result = ExecuteSelectStatement(test.Select("_id")); - Assert.True(result.Next()); - Assert.AreEqual("1", result[0]); - } - - [Test] - public void DropSchema() - { - string schemaName = "testDrop"; - Session session = GetSession(); - session.CreateSchema(schemaName); - Schema schema = session.GetSchema(schemaName); - Assert.True(SchemaExistsInDatabase(schema)); - - // Drop existing schema. - session.DropSchema(schemaName); - Assert.False(SchemaExistsInDatabase(schema)); - - // Drop non-existing schema. - session.DropSchema(schemaName); - Assert.False(SchemaExistsInDatabase(schema)); - - // Empty, whitespace and null schema name. - Assert.Throws(() => session.DropSchema(string.Empty)); - Assert.Throws(() => session.DropSchema(" ")); - Assert.Throws(() => session.DropSchema(" ")); - Assert.Throws(() => session.DropSchema(null)); - } - - #region WL14389 - - [Test, Description("Test MySQLX plugin Exception Handling Scenario 1")] - public void ExceptionHandlingSchema() - { - Session sessionPlain = MySQLX.GetSession(ConnectionString); - sessionPlain.DropSchema("test1"); - var db = sessionPlain.CreateSchema("test1"); - db = sessionPlain.GetSchema("test1"); - if (db.ExistsInDatabase()) - { - sessionPlain.DropSchema("test1"); - db = sessionPlain.CreateSchema("test1"); - db.DropCollection("test"); - var coll = db.CreateCollection("test"); - var res = coll.Add("{\"_id\":null,\"FLD1\":\"nulldata\"}").Execute(); - var docIds = res.GeneratedIds.Count; - - var docs = coll.Find("$.FLD1 == 'nulldata'").Execute(); - while (docs.Next()) - { - Assert.Throws(() => docs.Current["_id"].ToString()); - } - } - else { db = sessionPlain.CreateSchema("test1"); } - Assert.Throws(() => sessionPlain.CreateSchema("test1")); - sessionPlain.SQL(@"drop database if exists test1;").Execute(); - - sessionPlain.SQL(@"drop database if exists `test\84`;").Execute(); - db = sessionPlain.CreateSchema("test\\84"); - - sessionPlain.SQL(@"drop database if exists `test\84`;").Execute(); - db = sessionPlain.CreateSchema(@"test\84"); - - sessionPlain.SQL(@"drop database if exists `test\84`;").Execute(); - } - - [Test, Description("Test MySQLX plugin Exception Handling Scenario 2")] - public void ExceptionHandlingCollection() - { - if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher."); - - Session sessionPlain = MySQLX.GetSession(ConnectionString); - - if (sessionPlain.GetSchema("test_collection_123456789").ExistsInDatabase()) - { - sessionPlain.DropSchema("test_collection_123456789"); - } - var db = sessionPlain.CreateSchema("test_collection_123456789"); - if (db.GetCollection("my_collection_123456789").ExistsInDatabase()) - { - db.DropCollection("my_collection_123456789"); - } - db.CreateCollection("my_collection_123456789"); - Assert.Throws(() => db.CreateCollection("my_collection_123456789")); - - sessionPlain.DropSchema("test_collection_123456789"); - } - - [Test, Description("GetSession Create Schema Valid Name(Session and Session)")] - public void CreateValidSchema() - { - Schema db = session.GetSchema("test_123456789"); - if (db.ExistsInDatabase()) - { - session.DropSchema("test_123456789"); - db = session.CreateSchema("test_123456789"); - } - else { db = session.CreateSchema("test_123456789"); } - Assert.True(db.ExistsInDatabase()); - Assert.Throws(() => session.CreateSchema("test_123456789")); - session.DropSchema("test_123456789"); - Assert.Throws(() => session.CreateSchema("test_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789")); - Assert.Throws(() => session.CreateSchema(null)); - } - - [Test, Description("Set Node Schema")] - public void SessionSetSchema() - { - if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher."); - if (!session.GetSchema("test1").ExistsInDatabase()) - session.CreateSchema("test1"); - Assert.DoesNotThrow(() => session.SetCurrentSchema("test1")); - Assert.AreEqual("test1", session.Schema.Name); - // Retry the same schema - Assert.DoesNotThrow(() => session.SetCurrentSchema("test1")); - Assert.AreEqual("test1", session.Schema.Name); - session.Schema.CreateCollection("my_collection_123456789"); - session.Schema.DropCollection("my_collection_123456789"); - //Exceptions - Assert.Throws(() => session.SQL("USE nonExistingSchema").Execute()); - Assert.Throws(() => session.SetCurrentSchema("nonExistingSchema")); - Assert.Throws(() => session.SetCurrentSchema(null)); - session.DropSchema("test1"); - //No Active Schema - using (Session sessionPlain = MySQLX.GetSession(ConnectionString)) - { - Assert.IsNull(sessionPlain.GetCurrentSchema()); - } - } - - [Test, Description("Session Status before Execution - Negative")] - public void SessionClosedBeforeExecution() - { - if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher."); - Schema schema = null; - Session sessionPlain = MySQLX.GetSession(ConnectionString); - schema = sessionPlain.GetSchema(schemaName); - schema.CreateCollection("test123"); - schema.DropCollection("test123"); - sessionPlain.Close(); - Assert.Throws(() => schema.CreateCollection("test123")); - sessionPlain.Dispose(); - } - - [Test, Description("Session Switch-SetCurrentSchema(Same and Different Session)")] - public void SessionChangeCurrentSchema() - { - using (Session session = MySQLX.GetSession(ConnectionString)) - { - session.SQL("DROP DATABASE IF EXISTS dbname1").Execute(); - session.SQL("CREATE DATABASE dbname1").Execute(); - session.SQL("USE dbname1").Execute(); - StringAssert.AreEqualIgnoringCase("dbname1", session.GetCurrentSchema().Name); - session.SQL("CREATE TABLE address1" + - "(address_number INT NOT NULL AUTO_INCREMENT, " + - "building_name VARCHAR(100) NOT NULL, " + - "district VARCHAR(100) NOT NULL, PRIMARY KEY (address_number)" + ");").Execute(); - session.SQL("INSERT INTO address1" + - "(address_number,building_name,district)" + - " VALUES " + - "(1,'MySQL1','BGL1');").Execute(); - - session.SQL("DROP DATABASE IF EXISTS dbname2").Execute(); - session.SQL("CREATE DATABASE dbname2").Execute(); - session.SQL("USE dbname2").Execute(); - StringAssert.AreEqualIgnoringCase("dbname2", session.GetCurrentSchema().Name); - session.SQL("CREATE TABLE address2" + - "(address_number INT NOT NULL AUTO_INCREMENT, " + - "building_name VARCHAR(100) NOT NULL, " + - "district VARCHAR(100) NOT NULL, PRIMARY KEY (address_number)" + ");").Execute(); - session.SQL("INSERT INTO address2" + - "(address_number,building_name,district)" + - " VALUES " + - "(2,'MySQL2','BGL2');").Execute(); - session.SetCurrentSchema("dbname1"); - Assert.AreEqual("dbname1", session.Schema.Name); - session.SQL("SELECT * FROM address1").Execute(); - session.SQL("DROP TABLE address1").Execute(); - session.SetCurrentSchema("dbname2"); - StringAssert.AreEqualIgnoringCase("dbName2", session.Schema.Name); - session.SQL("SELECT * FROM address2").Execute(); - session.SQL("DROP TABLE address2").Execute(); - session.SQL("DROP DATABASE dbname1").Execute(); - session.SQL("DROP DATABASE dbname2").Execute(); - session.Close(); - session.Dispose(); - } - } - #endregion WL14389 - } -} +// Copyright © 2015, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySql.Data.MySqlClient; +using MySqlX.XDevAPI; +using MySqlX.XDevAPI.Common; +using MySqlX.XDevAPI.Relational; +using NUnit.Framework; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace MySqlX.Data.Tests +{ + public class SchemaTests : BaseTest + { + [TearDown] + public void TearDown() => ExecuteSQL("DROP TABLE IF EXISTS test"); + [Test] + public void GetSchemas() + { + Session session = GetSession(); + List schemas = session.GetSchemas(); + + Assert.True(schemas.Exists(s => s.Name == base.testSchema.Name)); + + Schema schema = session.GetSchema(schemaName); + Assert.AreEqual(schemaName, schema.Name); + schema = session.GetSchema(null); + Assert.IsNull(schema.Name); + } + + [Test] + public void GetInvalidSchema() + { + Session s = GetSession(); + Schema schema = s.GetSchema("test-schema"); + Assert.False(SchemaExistsInDatabase(schema)); + } + + [Test] + public void GetAllTables() + { + ExecuteSQL("DROP TABLE IF EXISTS test"); + ExecuteSQL("CREATE TABLE test(id int)"); + + List
tables = testSchema.GetTables(); + Assert.True(tables.Count == 1); + } + + [Test] + public void GetAllViews() + { + CreateCollection("coll"); + + ExecuteSQL("DROP TABLE IF EXISTS test"); + ExecuteSQL("CREATE TABLE test(id int)"); + ExecuteSQL("CREATE VIEW view1 AS select * from test"); + ExecuteSQL("CREATE VIEW view2 AS select * from test"); + + List
tables = testSchema.GetTables(); + Assert.AreEqual(3, tables.Count); + Assert.AreEqual(1, tables.Count(i => !i.IsView)); + Assert.AreEqual(2, tables.Count(i => i.IsView)); + + List colls = testSchema.GetCollections(); + Assert.That(colls, Has.One.Items); + } + + [Test] + [Ignore("Fix for 8.0.13")] + public void GetCollectionAsTable() + { + Collection testCollection = CreateCollection("test"); + + Result r = ExecuteAddStatement(testCollection.Add(@"{ ""_id"": 1, ""foo"": 1 }")); + Assert.AreEqual(1, r.AffectedItemsCount); + + Table test = testSchema.GetCollectionAsTable("test"); + Assert.True(TableExistsInDatabase(test)); + + RowResult result = ExecuteSelectStatement(test.Select("_id")); + Assert.True(result.Next()); + Assert.AreEqual("1", result[0]); + } + + [Test] + public void DropSchema() + { + string schemaName = "testDrop"; + Session session = GetSession(); + session.CreateSchema(schemaName); + Schema schema = session.GetSchema(schemaName); + Assert.True(SchemaExistsInDatabase(schema)); + + // Drop existing schema. + session.DropSchema(schemaName); + Assert.False(SchemaExistsInDatabase(schema)); + + // Drop non-existing schema. + session.DropSchema(schemaName); + Assert.False(SchemaExistsInDatabase(schema)); + + // Empty, whitespace and null schema name. + Assert.Throws(() => session.DropSchema(string.Empty)); + Assert.Throws(() => session.DropSchema(" ")); + Assert.Throws(() => session.DropSchema(" ")); + Assert.Throws(() => session.DropSchema(null)); + } + + #region WL14389 + + [Test, Description("Test MySQLX plugin Exception Handling Scenario 1")] + public void ExceptionHandlingSchema() + { + Session sessionPlain = MySQLX.GetSession(ConnectionString); + sessionPlain.DropSchema("test1"); + var db = sessionPlain.CreateSchema("test1"); + db = sessionPlain.GetSchema("test1"); + if (db.ExistsInDatabase()) + { + sessionPlain.DropSchema("test1"); + db = sessionPlain.CreateSchema("test1"); + db.DropCollection("test"); + var coll = db.CreateCollection("test"); + var res = coll.Add("{\"_id\":null,\"FLD1\":\"nulldata\"}").Execute(); + var docIds = res.GeneratedIds.Count; + + var docs = coll.Find("$.FLD1 == 'nulldata'").Execute(); + while (docs.Next()) + { + Assert.Throws(() => docs.Current["_id"].ToString()); + } + } + else { db = sessionPlain.CreateSchema("test1"); } + Assert.Throws(() => sessionPlain.CreateSchema("test1")); + sessionPlain.SQL(@"drop database if exists test1;").Execute(); + + sessionPlain.SQL(@"drop database if exists `test\84`;").Execute(); + db = sessionPlain.CreateSchema("test\\84"); + + sessionPlain.SQL(@"drop database if exists `test\84`;").Execute(); + db = sessionPlain.CreateSchema(@"test\84"); + + sessionPlain.SQL(@"drop database if exists `test\84`;").Execute(); + } + + [Test, Description("Test MySQLX plugin Exception Handling Scenario 2")] + public void ExceptionHandlingCollection() + { + if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher."); + + Session sessionPlain = MySQLX.GetSession(ConnectionString); + + if (sessionPlain.GetSchema("test_collection_123456789").ExistsInDatabase()) + { + sessionPlain.DropSchema("test_collection_123456789"); + } + var db = sessionPlain.CreateSchema("test_collection_123456789"); + if (db.GetCollection("my_collection_123456789").ExistsInDatabase()) + { + db.DropCollection("my_collection_123456789"); + } + db.CreateCollection("my_collection_123456789"); + Assert.Throws(() => db.CreateCollection("my_collection_123456789")); + + sessionPlain.DropSchema("test_collection_123456789"); + } + + [Test, Description("GetSession Create Schema Valid Name(Session and Session)")] + public void CreateValidSchema() + { + Schema db = session.GetSchema("test_123456789"); + if (db.ExistsInDatabase()) + { + session.DropSchema("test_123456789"); + db = session.CreateSchema("test_123456789"); + } + else { db = session.CreateSchema("test_123456789"); } + Assert.True(db.ExistsInDatabase()); + Assert.Throws(() => session.CreateSchema("test_123456789")); + session.DropSchema("test_123456789"); + Assert.Throws(() => session.CreateSchema("test_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789")); + Assert.Throws(() => session.CreateSchema(null)); + } + + [Test, Description("Set Node Schema")] + public void SessionSetSchema() + { + if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher."); + if (!session.GetSchema("test1").ExistsInDatabase()) + session.CreateSchema("test1"); + Assert.DoesNotThrow(() => session.SetCurrentSchema("test1")); + Assert.AreEqual("test1", session.Schema.Name); + // Retry the same schema + Assert.DoesNotThrow(() => session.SetCurrentSchema("test1")); + Assert.AreEqual("test1", session.Schema.Name); + session.Schema.CreateCollection("my_collection_123456789"); + session.Schema.DropCollection("my_collection_123456789"); + //Exceptions + Assert.Throws(() => session.SQL("USE nonExistingSchema").Execute()); + Assert.Throws(() => session.SetCurrentSchema("nonExistingSchema")); + Assert.Throws(() => session.SetCurrentSchema(null)); + session.DropSchema("test1"); + //No Active Schema + using (Session sessionPlain = MySQLX.GetSession(ConnectionString)) + { + Assert.IsNull(sessionPlain.GetCurrentSchema()); + } + } + + [Test, Description("Session Status before Execution - Negative")] + public void SessionClosedBeforeExecution() + { + if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher."); + Schema schema = null; + Session sessionPlain = MySQLX.GetSession(ConnectionString); + schema = sessionPlain.GetSchema(schemaName); + schema.CreateCollection("test123"); + schema.DropCollection("test123"); + sessionPlain.Close(); + Assert.Throws(() => schema.CreateCollection("test123")); + sessionPlain.Dispose(); + } + + [Test, Description("Session Switch-SetCurrentSchema(Same and Different Session)")] + public void SessionChangeCurrentSchema() + { + using (Session session = MySQLX.GetSession(ConnectionString)) + { + session.SQL("DROP DATABASE IF EXISTS dbname1").Execute(); + session.SQL("CREATE DATABASE dbname1").Execute(); + session.SQL("USE dbname1").Execute(); + StringAssert.AreEqualIgnoringCase("dbname1", session.GetCurrentSchema().Name); + session.SQL("CREATE TABLE address1" + + "(address_number INT NOT NULL AUTO_INCREMENT, " + + "building_name VARCHAR(100) NOT NULL, " + + "district VARCHAR(100) NOT NULL, PRIMARY KEY (address_number)" + ");").Execute(); + session.SQL("INSERT INTO address1" + + "(address_number,building_name,district)" + + " VALUES " + + "(1,'MySQL1','BGL1');").Execute(); + + session.SQL("DROP DATABASE IF EXISTS dbname2").Execute(); + session.SQL("CREATE DATABASE dbname2").Execute(); + session.SQL("USE dbname2").Execute(); + StringAssert.AreEqualIgnoringCase("dbname2", session.GetCurrentSchema().Name); + session.SQL("CREATE TABLE address2" + + "(address_number INT NOT NULL AUTO_INCREMENT, " + + "building_name VARCHAR(100) NOT NULL, " + + "district VARCHAR(100) NOT NULL, PRIMARY KEY (address_number)" + ");").Execute(); + session.SQL("INSERT INTO address2" + + "(address_number,building_name,district)" + + " VALUES " + + "(2,'MySQL2','BGL2');").Execute(); + session.SetCurrentSchema("dbname1"); + Assert.AreEqual("dbname1", session.Schema.Name); + session.SQL("SELECT * FROM address1").Execute(); + session.SQL("DROP TABLE address1").Execute(); + session.SetCurrentSchema("dbname2"); + StringAssert.AreEqualIgnoringCase("dbName2", session.Schema.Name); + session.SQL("SELECT * FROM address2").Execute(); + session.SQL("DROP TABLE address2").Execute(); + session.SQL("DROP DATABASE dbname1").Execute(); + session.SQL("DROP DATABASE dbname2").Execute(); + session.Close(); + session.Dispose(); + } + } + #endregion WL14389 + } +} diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/SessionTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/SessionTests.cs index 9ad0e0057..9d497395e 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/SessionTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/SessionTests.cs @@ -1,2389 +1,2389 @@ -// Copyright (c) 2015, 2022, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySql.Data; -using MySql.Data.Common; -using MySql.Data.MySqlClient; -using MySqlX.XDevAPI; -using MySqlX.XDevAPI.Relational; -using NUnit.Framework; -using System; -using System.Collections.Generic; -using System.Data; -using System.Diagnostics; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace MySqlX.Data.Tests -{ - public class SessionTests : BaseTest - { - [Test] - [Property("Category", "Security")] - public void CanCloseSession() - { - Session s = MySQLX.GetSession(ConnectionString); - Assert.True(s.InternalSession.SessionState == SessionState.Open); - s.Close(); - Assert.AreEqual(s.InternalSession.SessionState, SessionState.Closed); - } - - [Test] - [Property("Category", "Security")] - public void NoPassword() - { - Session session = MySQLX.GetSession(ConnectionStringNoPassword); - Assert.True(session.InternalSession.SessionState == SessionState.Open); - session.Close(); - Assert.AreEqual(session.InternalSession.SessionState, SessionState.Closed); - } - - [Test] - [Property("Category", "Security")] - public void SessionClose() - { - Session session = MySQLX.GetSession(ConnectionString); - Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); - session.Close(); - Assert.AreEqual(SessionState.Closed, session.InternalSession.SessionState); - } - - [Test] - [Property("Category", "Security")] - [Ignore("Check this. Result is not always the same")] - public void CountClosedSession() - { - int sessions, newSessions; - - using (Session nodeSession = MySQLX.GetSession(ConnectionString)) - { - sessions = ExecuteSQLStatement(nodeSession.SQL("show processlist")).FetchAll().Count; - - for (int i = 0; i < 20; i++) - { - Session session = MySQLX.GetSession(ConnectionString); - Assert.True(session.InternalSession.SessionState == SessionState.Open); - session.Close(); - Assert.AreEqual(session.InternalSession.SessionState, SessionState.Closed); - } - - newSessions = ExecuteSQLStatement(nodeSession.SQL("show processlist")).FetchAll().Count; - } - - Assert.AreEqual(sessions, newSessions); - } - - [Test] - [Property("Category", "Security")] - public void ConnectionStringAsAnonymousType() - { - var connstring = new - { - server = session.Settings.Server, - port = session.Settings.Port, - user = session.Settings.UserID, - password = session.Settings.Password - }; - - using (var testSession = MySQLX.GetSession(connstring)) - { - Assert.AreEqual(SessionState.Open, testSession.InternalSession.SessionState); - } - } - - [Test] - [Property("Category", "Security")] - public void SessionGetSetCurrentSchema() - { - using (Session testSession = MySQLX.GetSession(ConnectionString)) - { - Assert.AreEqual(SessionState.Open, testSession.InternalSession.SessionState); - Assert.Null(testSession.GetCurrentSchema()); - Assert.Throws(() => testSession.SetCurrentSchema("")); - testSession.SetCurrentSchema(schemaName); - Assert.AreEqual(schemaName, testSession.Schema.Name); - Assert.AreEqual(schemaName, testSession.GetCurrentSchema().Name); - } - } - - [Test] - [Property("Category", "Security")] - public void SessionUsingSchema() - { - using (Session mySession = MySQLX.GetSession(ConnectionString + $";database={schemaName};")) - { - Assert.AreEqual(SessionState.Open, mySession.InternalSession.SessionState); - Assert.AreEqual(schemaName, mySession.Schema.Name); - Assert.AreEqual(schemaName, mySession.GetCurrentSchema().Name); - Assert.True(SchemaExistsInDatabase(mySession.Schema)); - } - } - - [Test] - [Property("Category", "Security")] - public void SessionUsingDefaultSchema() - { - using (Session mySession = MySQLX.GetSession(ConnectionString + $";database={schemaName};")) - { - Assert.AreEqual(SessionState.Open, mySession.InternalSession.SessionState); - Assert.AreEqual(schemaName, mySession.DefaultSchema.Name); - Assert.AreEqual(schemaName, mySession.GetCurrentSchema().Name); - Assert.True(mySession.Schema.ExistsInDatabase()); - mySession.SetCurrentSchema("mysql"); - Assert.AreNotEqual(mySession.DefaultSchema.Name, mySession.Schema.Name); - } - - // DefaultSchema is null because no database was provided in the connection string/URI. - using (Session mySession = MySQLX.GetSession(ConnectionString)) - { - Assert.AreEqual(SessionState.Open, mySession.InternalSession.SessionState); - Assert.Null(mySession.DefaultSchema); - } - } - - [Test] - [Property("Category", "Security")] - public void SessionUsingDefaultSchemaWithAnonymousObject() - { - var globalSession = GetSession(); - - using (var internalSession = MySQLX.GetSession(new - { - server = globalSession.Settings.Server, - port = globalSession.Settings.Port, - user = globalSession.Settings.UserID, - password = globalSession.Settings.Password, - sslmode = MySqlSslMode.Required, - database = "mysql" - })) - { - Assert.AreEqual("mysql", internalSession.DefaultSchema.Name); - } - - // DefaultSchema is null when no database is provided. - using (var internalSession = MySQLX.GetSession(new - { - server = globalSession.Settings.Server, - port = globalSession.Settings.Port, - user = globalSession.Settings.UserID, - password = globalSession.Settings.Password, - sslmode = MySqlSslMode.Required, - })) - { - Assert.Null(internalSession.DefaultSchema); - } - - // Access denied error is raised when database does not exist for servers 8.0.12 and below. - // This behavior was fixed since MySql Server 8.0.13 version. Now the error - // shows the proper message, "Unknown database..." - if (session.InternalSession.GetServerVersion().isAtLeast(8, 0, 13)) return; - var exception = Assert.Throws(() => MySQLX.GetSession(new - { - server = globalSession.Settings.Server, - port = globalSession.Settings.Port, - user = globalSession.Settings.UserID, - password = globalSession.Settings.Password, - sslmode = MySqlSslMode.Required, - database = "test1" - } - )); - - if (session.InternalSession.GetServerVersion().isAtLeast(8, 0, 13)) - StringAssert.StartsWith(string.Format("Unknown database 'test1'"), exception.Message); - else - StringAssert.StartsWith(string.Format("Access denied"), exception.Message); - } - - [Test] - [Property("Category", "Security")] - public void SessionUsingDefaultSchemaWithConnectionURI() - { - using (var session = MySQLX.GetSession(ConnectionStringUri + "?database=mysql")) - { - Assert.AreEqual("mysql", session.DefaultSchema.Name); - } - } - - [Test] - [Property("Category", "Security")] - public void CheckConnectionUri() - { - CheckConnectionData($"mysqlx://myuser:password@{Host}:{XPort}", "myuser", "password", Host, uint.Parse(XPort)); - CheckConnectionData($"mysqlx://my%3Auser:p%40ssword@{Host}:{XPort}", "my:user", "p@ssword", Host, uint.Parse(XPort)); - CheckConnectionData($"mysqlx://my%20user:p%40ss%20word@{Host}:{XPort}", "my user", "p@ss word", Host, uint.Parse(XPort)); - CheckConnectionData($"mysqlx:// myuser : p%40ssword@{Host}:{XPort}", "myuser", "p@ssword", Host, uint.Parse(XPort)); - CheckConnectionData($"mysqlx://myuser@{Host}:{XPort}", "myuser", "", Host, uint.Parse(XPort)); - CheckConnectionData($"mysqlx://myuser:p%40ssword@{Host}", "myuser", "p@ssword", Host, uint.Parse(XPort)); - CheckConnectionData($"mysqlx://myuser:p%40ssw%40rd@{Host}", "myuser", "p@ssw@rd", Host, uint.Parse(XPort)); - CheckConnectionData($"mysqlx://my%40user:p%40ssword@{Host}", "my@user", "p@ssword", Host, uint.Parse(XPort)); - CheckConnectionData($"mysqlx://myuser@{Host}", "myuser", "", Host, uint.Parse(XPort)); - CheckConnectionData($"mysqlx://myuser@{Host}", "myuser", "", Host, uint.Parse(XPort)); - CheckConnectionData("mysqlx://myuser@[::1]", "myuser", "", "[::1]", uint.Parse(XPort)); - CheckConnectionData("mysqlx://myuser:password@[2606:b400:440:1040:bd41:e449:45ee:2e1a]", "myuser", "password", "[2606:b400:440:1040:bd41:e449:45ee:2e1a]", uint.Parse(XPort)); - CheckConnectionData($"mysqlx://myuser:password@[2606:b400:440:1040:bd41:e449:45ee:2e1a]:{XPort}", "myuser", "password", "[2606:b400:440:1040:bd41:e449:45ee:2e1a]", uint.Parse(XPort)); - Assert.Throws(() => CheckConnectionData("mysqlx://myuser:password@[2606:b400:440:1040:bd41:e449:45ee:2e1a:33060]", "myuser", "password", "[2606:b400:440:1040:bd41:e449:45ee:2e1a]", uint.Parse(XPort))); - Assert.Throws(() => CheckConnectionData($"mysqlx://myuser:password@2606:b400:440:1040:bd41:e449:45ee:2e1a:{XPort}", "myuser", "password", "[2606:b400:440:1040:bd41:e449:45ee:2e1a]", uint.Parse(XPort))); - CheckConnectionData("mysqlx://myuser:password@[fe80::bd41:e449:45ee:2e1a%17]", "myuser", "password", "[fe80::bd41:e449:45ee:2e1a]", uint.Parse(XPort)); - CheckConnectionData("mysqlx://myuser:password@[(address=[fe80::bd41:e449:45ee:2e1a%17],priority=100)]", "myuser", "password", "[fe80::bd41:e449:45ee:2e1a]", uint.Parse(XPort)); - CheckConnectionData("mysqlx://myuser:password@[(address=[fe80::bd41:e449:45ee:2e1a%17]:3305,priority=100)]", "myuser", "password", "[fe80::bd41:e449:45ee:2e1a]", 3305); - Assert.Throws(() => CheckConnectionData("mysqlx://myuser:password@[(address=fe80::bd41:e449:45ee:2e1a%17,priority=100)]", "myuser", "password", "[fe80::bd41:e449:45ee:2e1a]", 33060)); - CheckConnectionData("mysqlx://myuser@localhost/test", "myuser", "", "localhost", 33060, "database", schemaName); -#if NET7_0 - CheckConnectionData("mysqlx://myuser@localhost/test?ssl%20mode=disabled&connecttimeout=10", "myuser", "", "localhost", 33060, "database", schemaName, "ssl mode", "None", "connecttimeout", "10"); -#else - CheckConnectionData("mysqlx://myuser@localhost/test?ssl%20mode=disabled&connecttimeout=10", "myuser", "", "localhost", 33060, "database", schemaName, "ssl mode", "Disabled", "connecttimeout", "10"); -#endif - CheckConnectionData("mysqlx://_%21%22%23%24s%26%2F%3D-%25r@localhost", "_!\"#$s&/=-%r", "", "localhost", 33060); - CheckConnectionData("mysql://myuser@localhost", "", "", "", 33060); - CheckConnectionData("myuser@localhost", "", "", "", 33060); - Assert.Throws(() => CheckConnectionData("mysqlx://uid=myuser;server=localhost", "", "", "", 33060)); - CheckConnectionData("mysqlx://user:password@server.example.com/", "user", "password", "server.example.com", 33060, "ssl mode", "Required"); - CheckConnectionData("mysqlx://user:password@server.example.com/?ssl-ca=(c:%5Cclient.pfx)", "user", "password", "server.example.com", 33060, "ssl mode", "Required", "ssl-ca", "c:\\client.pfx"); - Assert.Throws(() => CheckConnectionData("mysqlx://user:password@server.example.com/?ssl-crl=(c:%5Ccrl.pfx)", "user", "password", "server.example.com", 33060, "ssl mode", "Required", "ssl-crl", "(c:\\crl.pfx)")); - // tls-version - CheckConnectionData("mysqlx://myuser:password@localhost:33060?tls-version=TlSv1.2", "myuser", "password", "localhost", 33060, "tls-version", "Tls12"); - CheckConnectionData("mysqlx://myuser:password@localhost:33060?tls-version=TlS1.2", "myuser", "password", "localhost", 33060, "tls-version", "Tls12"); - CheckConnectionData("mysqlx://myuser:password@localhost:33060?tls-version=TlSv12", "myuser", "password", "localhost", 33060, "tls-version", "Tls12"); - CheckConnectionData("mysqlx://myuser:password@localhost:33060?tls-version=TlS12", "myuser", "password", "localhost", 33060, "tls-version", "Tls12"); - CheckConnectionData("mysqlx://myuser:password@localhost:33060?tls-version=[ TlSv1.2 ,tLsV11, TLSv1.0 , tls13 ]", "myuser", "password", "localhost", 33060, "tls-version", "Tls12, Tls13"); - CheckConnectionData("mysqlx://myuser:password@localhost:33060?tls-version=( TlSv1.2 ,tLsV11, TLSv1 , tls13 )", "myuser", "password", "localhost", 33060, "tls-version", "Tls12, Tls13"); - CheckConnectionData("mysqlx://myuser:password@localhost:33060?tls-version= TlSv1.2 ,tLsV11, TLSv10 , tls13", "myuser", "password", "localhost", 33060, "tls-version", "Tls12, Tls13"); - Assert.Throws(() => CheckConnectionData("mysqlx://myuser:password@localhost:33060?tls-version=SSL3", "myuser", "password", "localhost", 33060, "tls-version", "")); - } - - [Test] - [Property("Category", "Security")] - public void ConnectionUsingUri() - { - using (var session = MySQLX.GetSession(ConnectionStringUri)) - { - Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); - } - } - - [Test] - [Property("Category", "Security")] - public void ConnectionStringNull() - { - Assert.Throws(() => MySQLX.GetSession(null)); - } - - [Test] - [Property("Category", "Security")] - public void IPv6() - { - var csBuilder = new MySqlXConnectionStringBuilder(ConnectionString); - csBuilder.Server = GetMySqlServerIp(true); - csBuilder.Port = uint.Parse(XPort); - - if (string.IsNullOrEmpty(csBuilder.Server)) Assert.Ignore("No IPv6 available."); - - using (var session = MySQLX.GetSession(csBuilder.ToString())) - { - Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); - } - } - - [Test] - [Property("Category", "Security")] - public void IPv6AsUrl() - { - var csBuilder = new MySqlXConnectionStringBuilder(ConnectionString); - string ipv6 = GetMySqlServerIp(true); - if (string.IsNullOrEmpty(ipv6)) Assert.Ignore("No IPv6 available."); - - string connString = $"mysqlx://{csBuilder.UserID}:{csBuilder.Password}@[{ipv6}]:{XPort}"; - using (Session session = MySQLX.GetSession(connString)) - { - Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); - } - } - - [Test] - [Property("Category", "Security")] - public void IPv6AsAnonymous() - { - var csBuilder = new MySqlXConnectionStringBuilder(ConnectionString); - string ipv6 = GetMySqlServerIp(true); - if (string.IsNullOrEmpty(ipv6)) Assert.Ignore("No IPv6 available."); - - using (Session session = MySQLX.GetSession(new { server = ipv6, user = csBuilder.UserID, password = csBuilder.Password, port = XPort })) - { - Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); - } - } - - [Test] - [Property("Category", "Security")] - public void CreateSessionWithUnsupportedOptions() - { - var errorMessage = "Option not supported."; - var connectionUri = string.Format("{0}?", ConnectionStringUri); - - // Use a connection URI. - var ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "pipe=MYSQL")); - StringAssert.StartsWith(errorMessage, ex.Message); - ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "compress=true")); - StringAssert.StartsWith(errorMessage, ex.Message); - ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "allow batch=false")); - StringAssert.StartsWith(errorMessage, ex.Message); - ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "logging=true")); - StringAssert.StartsWith(errorMessage, ex.Message); - ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "sharedmemoryname=MYSQL")); - StringAssert.StartsWith(errorMessage, ex.Message); - ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "defaultcommandtimeout=30")); - StringAssert.StartsWith(errorMessage, ex.Message); - ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "usedefaultcommandtimeoutforef=true")); - StringAssert.StartsWith(errorMessage, ex.Message); - ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "persistsecurityinfo=false")); - StringAssert.StartsWith(errorMessage, ex.Message); - ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "encrypt=false")); - StringAssert.StartsWith(errorMessage, ex.Message); - ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "integratedsecurity=true")); - StringAssert.StartsWith(errorMessage, ex.Message); - ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "allowpublickeyretrieval=false")); - StringAssert.StartsWith(errorMessage, ex.Message); - ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "autoenlist=true")); - StringAssert.StartsWith(errorMessage, ex.Message); - ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "includesecurityasserts=false")); - StringAssert.StartsWith(errorMessage, ex.Message); - ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "allowzerodatetime=true")); - StringAssert.StartsWith(errorMessage, ex.Message); - ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "convert zero datetime=false")); - StringAssert.StartsWith(errorMessage, ex.Message); - ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "useusageadvisor=true")); - StringAssert.StartsWith(errorMessage, ex.Message); - ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "procedurecachesize=50")); - StringAssert.StartsWith(errorMessage, ex.Message); - ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "useperformancemonitor=true")); - StringAssert.StartsWith(errorMessage, ex.Message); - ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "respectbinaryflags=true")); - StringAssert.StartsWith(errorMessage, ex.Message); - ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "treat tiny as boolean=false")); - StringAssert.StartsWith(errorMessage, ex.Message); - ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "allowuservariables=true")); - StringAssert.StartsWith(errorMessage, ex.Message); - ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "interactive=false")); - StringAssert.StartsWith(errorMessage, ex.Message); - ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "functionsreturnstring=true")); - StringAssert.StartsWith(errorMessage, ex.Message); - ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "useaffectedrows=false")); - StringAssert.StartsWith(errorMessage, ex.Message); - ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "oldguids=true")); - StringAssert.StartsWith(errorMessage, ex.Message); - ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "sqlservermode=false")); - StringAssert.StartsWith(errorMessage, ex.Message); - ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "tablecaching=true")); - StringAssert.StartsWith(errorMessage, ex.Message); - ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "defaulttablecacheage=60")); - StringAssert.StartsWith(errorMessage, ex.Message); - ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "checkparameters=true")); - StringAssert.StartsWith(errorMessage, ex.Message); - ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "replication=replication_group")); - StringAssert.StartsWith(errorMessage, ex.Message); - ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "exceptioninterceptors=none")); - StringAssert.StartsWith(errorMessage, ex.Message); - ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "commandinterceptors=none")); - StringAssert.StartsWith(errorMessage, ex.Message); - ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "connectionlifetime=100")); - StringAssert.StartsWith(errorMessage, ex.Message); - ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "pooling=false")); - StringAssert.StartsWith(errorMessage, ex.Message); - ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "minpoolsize=0")); - StringAssert.StartsWith(errorMessage, ex.Message); - ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "maxpoolsize=20")); - StringAssert.StartsWith(errorMessage, ex.Message); - ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "connectionreset=false")); - StringAssert.StartsWith(errorMessage, ex.Message); - ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "cacheserverproperties=true")); - StringAssert.StartsWith(errorMessage, ex.Message); - - // Use a connection string. - ex = Assert.Throws(() => MySQLX.GetSession("treatblobsasutf8=false")); - StringAssert.StartsWith(errorMessage, ex.Message); - ex = Assert.Throws(() => MySQLX.GetSession("blobasutf8includepattern=pattern")); - StringAssert.StartsWith(errorMessage, ex.Message); - ex = Assert.Throws(() => MySQLX.GetSession("blobasutf8excludepattern=pattern")); - StringAssert.StartsWith(errorMessage, ex.Message); - } - - [Test] - [Property("Category", "Security")] - public void CreateBuilderWithUnsupportedOptions() - { - var errorMessage = "Option not supported."; - var ex = Assert.Throws(() => new MySqlXConnectionStringBuilder("pipe=MYSQL")); - StringAssert.StartsWith(errorMessage, ex.Message); - ex = Assert.Throws(() => new MySqlXConnectionStringBuilder("allow batch=false")); - StringAssert.StartsWith(errorMessage, ex.Message); - ex = Assert.Throws(() => new MySqlXConnectionStringBuilder("respectbinaryflags=true")); - StringAssert.StartsWith(errorMessage, ex.Message); - ex = Assert.Throws(() => new MySqlXConnectionStringBuilder("pooling=false")); - StringAssert.StartsWith(errorMessage, ex.Message); - ex = Assert.Throws(() => new MySqlXConnectionStringBuilder("cacheserverproperties=true")); - StringAssert.StartsWith(errorMessage, ex.Message); - } - - [Test] - [Property("Category", "Security")] - public void GetUri() - { - using (var internalSession = MySQLX.GetSession(session.Uri)) - { - // Validate that all properties keep their original value. - foreach (var connectionOption in session.Settings.values) - { - // SslCrl connection option is skipped since it isn't currently supported. - if (connectionOption.Key == "sslcrl") - continue; - - try - { - Assert.AreEqual(session.Settings[connectionOption.Key], internalSession.Settings[connectionOption.Key]); - } - catch (ArgumentException ex) - { - StringAssert.StartsWith("Option not supported.", ex.Message); - } - } - } - } - - /// - /// WL #12177 Implement connect timeout - /// - [Test] - [Property("Category", "Security")] - public void ConnectTimeout() - { - if (Platform.IsMacOSX()) Assert.Ignore("Check failure on MacOS: (() => MySQLX.GetSession(conn)); - TimeSpan diff = DateTime.Now.Subtract(start); - Assert.True(diff.TotalSeconds > 19 && diff.TotalSeconds < 21, String.Format("Timeout exceeded ({0}). Actual time: {1}", "Fail over failure", diff)); - - // Valid session no time out - start = DateTime.Now; - using (Session session = MySQLX.GetSession(ConnectionStringUri + "?connecttimeout=2000")) - session.SQL("SELECT SLEEP(10)").Execute(); - diff = DateTime.Now.Subtract(start); - Assert.True(diff.TotalSeconds > 10); - - //Invalid Values for Connection Timeout parameter - var ex = Assert.Throws(() => MySQLX.GetSession(ConnectionString + ";connect-timeout=-1;")); - Assert.AreEqual(ResourcesX.InvalidConnectionTimeoutValue, ex.Message); - - ex = Assert.Throws(() => MySQLX.GetSession(ConnectionString + ";connect-timeout=foo;")); - Assert.AreEqual(ResourcesX.InvalidConnectionTimeoutValue, ex.Message); - - ex = Assert.Throws(() => MySQLX.GetSession(ConnectionString + ";connect-timeout='';")); - Assert.AreEqual(ResourcesX.InvalidConnectionTimeoutValue, ex.Message); - - ex = Assert.Throws(() => MySQLX.GetSession(ConnectionString + ";connect-timeout=10.5;")); - Assert.AreEqual(ResourcesX.InvalidConnectionTimeoutValue, ex.Message); - - ex = Assert.Throws(() => MySQLX.GetSession(ConnectionString + ";connect-timeout=" + Int32.MaxValue + 1)); - Assert.AreEqual(ResourcesX.InvalidConnectionTimeoutValue, ex.Message); - - ex = Assert.Throws(() => MySQLX.GetSession(ConnectionString + ";connect-timeout=10.5;")); - Assert.AreEqual(ResourcesX.InvalidConnectionTimeoutValue, ex.Message); - - ex = Assert.Throws(() => MySQLX.GetSession(ConnectionString + ";connect-timeout=;")); - Assert.AreEqual(ResourcesX.InvalidConnectionTimeoutValue, ex.Message); - - ex = Assert.Throws(() => MySQLX.GetSession(ConnectionStringUri + "?connect-timeout= ")); - Assert.AreEqual(ResourcesX.InvalidConnectionTimeoutValue, ex.Message); - - ex = Assert.Throws(() => MySQLX.GetSession(ConnectionStringUri + "?connecttimeout=")); - Assert.AreEqual(ResourcesX.InvalidConnectionTimeoutValue, ex.Message); - - // Valid value for ConnectionTimeout, invalid credentials - var exception = Assert.Throws(() => MySQLX.GetSession($"server={Host};user=test;password=noPass;port={XPort};connect-timeout=2000;")); - Assert.NotNull(exception); - } - - private void TestConnectTimeoutFailureTimeout(String connString, int minTime, int maxTime, string test) - { - DateTime start = DateTime.Now; - Assert.Throws(() => MySQLX.GetSession(connString)); - TimeSpan diff = DateTime.Now.Subtract(start); - Assert.True(diff.TotalSeconds > minTime && diff.TotalSeconds < maxTime, String.Format("Timeout exceeded ({0}). Actual time: {1}", test, diff)); - } - - private void TestConnectTimeoutSuccessTimeout(String connString, int minTime, int maxTime, string test) - { - DateTime start = DateTime.Now; - MySQLX.GetSession(connString); - TimeSpan diff = DateTime.Now.Subtract(start); - Assert.True(diff.TotalSeconds > minTime && diff.TotalSeconds < maxTime, String.Format("Timeout exceeded ({0}). Actual time: {1}", test, diff)); - } - - [Test] - [Property("Category", "Security")] - public void MaxConnections() - { - try - { - List sessions = new List(); - ExecuteSqlAsRoot("SET @@global.mysqlx_max_connections = 2"); - for (int i = 0; i <= 2; i++) - { - Session newSession = MySQLX.GetSession(ConnectionString); - sessions.Add(newSession); - } - Assert.False(true, "MySqlException should be thrown"); - } - catch (MySqlException ex) - { - Assert.AreEqual(ResourcesX.UnableToOpenSession, ex.Message); - } - finally - { - ExecuteSqlAsRoot("SET @@global.mysqlx_max_connections = 100"); - } - } - - protected void CheckConnectionData(string connectionData, string user, string password, string server, uint port, params string[] parameters) - { - string result = this.session.ParseConnectionData(connectionData); - var csbuilder = new MySqlXConnectionStringBuilder(result); - Assert.True(user == csbuilder.UserID, string.Format("Expected:{0} Current:{1} in {2}", user, csbuilder.UserID, connectionData)); - Assert.True(password == csbuilder.Password, string.Format("Expected:{0} Current:{1} in {2}", password, csbuilder.Password, connectionData)); - Assert.True(server == csbuilder.Server, string.Format("Expected:{0} Current:{1} in {2}", server, csbuilder.Server, connectionData)); - Assert.True(port == csbuilder.Port, string.Format("Expected:{0} Current:{1} in {2}", port, csbuilder.Port, connectionData)); - if (parameters != null) - { - if (parameters.Length % 2 != 0) - throw new ArgumentOutOfRangeException(); - for (int i = 0; i < parameters.Length; i += 2) - { - Assert.True(csbuilder.ContainsKey(parameters[i])); - Assert.AreEqual(parameters[i + 1], csbuilder[parameters[i]].ToString()); - } - } - } - - /// - /// WL12514 - DevAPI: Support session-connect-attributes - /// - [Test] - [Property("Category", "Security")] - public void ConnectionAttributes() - { - if (!(session.Version.isAtLeast(8, 0, 16))) return; - - // Validate that MySQLX.GetSession() supports a new 'connection-attributes' query parameter - // with default values and all the client attributes starts with a '_'. - TestConnectionAttributes(ConnectionString + ";connection-attributes=true;"); - TestConnectionAttributes(ConnectionStringUri + "?connectionattributes"); - - // Validate that no attributes, client or user defined, are sent to server when the value is "false". - TestConnectionAttributes(ConnectionString + ";connection-attributes=false;"); - TestConnectionAttributes(ConnectionStringUri + "?connectionattributes=false"); - - // Validate default behavior with different scenarios. - TestConnectionAttributes(ConnectionString + ";connection-attributes;"); - TestConnectionAttributes(ConnectionStringUri + "?connectionattributes=true"); - TestConnectionAttributes(ConnectionString + ";connection-attributes=;"); - TestConnectionAttributes(ConnectionStringUri + "?connectionattributes=[]"); - - // Validate user-defined attributes to be sent to server. - Dictionary userAttrs = new Dictionary - { - { "foo", "bar" }, - { "quua", "qux" }, - { "key", null } - }; - TestConnectionAttributes(ConnectionString + ";connection-attributes=[foo=bar,quua=qux,key]", userAttrs); - TestConnectionAttributes(ConnectionStringUri + "?connectionattributes=[foo=bar,quua=qux,key=]", userAttrs); - - // Errors - var ex = Assert.Throws(() => MySQLX.GetSession(ConnectionString + ";connection-attributes=[_key=value]")); - Assert.AreEqual(ResourcesX.InvalidUserDefinedAttribute, ex.Message); - - ex = Assert.Throws(() => MySQLX.GetSession(ConnectionString + ";connection-attributes=123")); - Assert.AreEqual(ResourcesX.InvalidConnectionAttributes, ex.Message); - - ex = Assert.Throws(() => MySQLX.GetSession(ConnectionString + ";connection-attributes=[key=value,key=value2]")); - Assert.AreEqual(string.Format(ResourcesX.DuplicateUserDefinedAttribute, "key"), ex.Message); - - ex = Assert.Throws(() => MySQLX.GetSession(new { server = Host, port = XPort, user = RootUser, connectionattributes = "=" })); - - ex = Assert.Throws(() => MySQLX.GetSession(ConnectionString + ";connectionattributes=[=bar]")); - Assert.AreEqual(string.Format(ResourcesX.EmptyKeyConnectionAttribute), ex.Message); - } - - private void TestConnectionAttributes(string connString, Dictionary userAttrs = null) - { - string sql = "SELECT * FROM performance_schema.session_account_connect_attrs WHERE PROCESSLIST_ID = connection_id()"; - - using (Session session = MySQLX.GetSession(connString)) - { - Assert.AreEqual(SessionState.Open, session.XSession.SessionState); - var result = session.SQL(sql).Execute().FetchAll(); - - if (session.Settings.ConnectionAttributes == "false") - CollectionAssert.IsEmpty(result); - else - { - CollectionAssert.IsNotEmpty(result); - MySqlConnectAttrs clientAttrs = new MySqlConnectAttrs(); - - if (userAttrs == null) - { - Assert.AreEqual(8, result.Count); - - foreach (Row row in result) - StringAssert.StartsWith("_", row[1].ToString()); - } - else - { - Assert.AreEqual(11, result.Count); - - for (int i = 0; i < userAttrs.Count; i++) - { - Assert.True(userAttrs.ContainsKey(result.ElementAt(i)[1].ToString())); - Assert.True(userAttrs.ContainsValue(result.ElementAt(i)[2])); - } - } - } - } - } - - [TestCase("localhost")] - [TestCase("127.0.0.1")] - [TestCase("[::1]")] - [Description("IPv6 connection Scenario [localhost],[127.0.0.1]")] - public void ConnectionTest(string serverName) - { - if (!Platform.IsWindows()) Assert.Ignore("This test only applies foe Windows OS."); - - serverName = serverName.Replace("localhost", Host); - - MySqlXConnectionStringBuilder sb = new MySqlXConnectionStringBuilder(ConnectionString); - string connStr = "server=" + Host + ";user=" + sb.UserID + ";port=" + XPort + ";password=" + sb.Password + ";" + "sslmode=" + MySqlSslMode.Required; - - using (var sessionTest = MySQLX.GetSession(connStr)) - { - Assert.AreEqual(SessionState.Open, sessionTest.InternalSession.SessionState); - } - - using (var sessionTest = MySQLX.GetSession("mysqlx://" + sb.UserID + ":" + sb.Password + "@" + serverName + ":" + XPort)) - { - Assert.AreEqual(SessionState.Open, sessionTest.InternalSession.SessionState); - } - - using (var sessionTest = MySQLX.GetSession(new { server = serverName, port = XPort, user = sb.UserID, password = sb.Password })) - { - Assert.AreEqual(SessionState.Open, sessionTest.InternalSession.SessionState); - } - //wrong port - connStr = "server=" + sb.Server + ";user=" + sb.UserID + ";port=" + 33090 + ";password=" + sb.Password + ";" + "sslmode=" + MySqlSslMode.Required; - Assert.Throws(() => MySQLX.GetSession(connStr)); - - } - - [TestCase("[::$]")] - [TestCase("[::11]")] - [Description("IPv6 connection server * and ::$,invalid hostname")] - public void IPv6ConnectionExceptions(string serverName) - { - if (!Platform.IsWindows()) return; - - Session sessionTest = null; - string connStr = "server=" + serverName + ";user=test;port=" + XPort + ";password=test;sslmode=" + MySqlSslMode.Required; - Assert.Catch(() => sessionTest = MySQLX.GetSession(connStr)); - Assert.Catch(() => sessionTest = MySQLX.GetSession("mysqlx://test:test@" + serverName + ":" + XPort)); - Assert.Catch(() => sessionTest = MySQLX.GetSession(new { server = serverName, port = XPort, user = schemaName, password = schemaName })); - } - - [Test, Description("Unified connection string refinement-Negative Scenarios")] - public void ConnectionNegativeScenarios() - { - if (!Platform.IsWindows()) Assert.Ignore("This test is for Windows OS only"); - var ipv6HostName2 = GetIPV6Address(); - string ipAddress = GetMySqlServerIp(); - - Session session1 = null; - Assert.Catch(() => session1 = MySQLX.GetSession("mysql:x//test:test@" + ipAddress + ":" + XPort)); - Assert.Catch(() => session1 = MySQLX.GetSession("my:sqlx//test:test@" + ipAddress + ":" + XPort)); - Assert.Catch(() => session1 = MySQLX.GetSession("mysqlx:://test:test@" + ipAddress + ":" + XPort)); - string ipv6address = "f345::" + GetIPV6Address() + ":1xde"; - Assert.Catch(() => session1 = MySQLX.GetSession("mysqlx://test:test@[" + ipv6address + "]:" + XPort)); - Assert.Catch(() => session1 = MySQLX.GetSession("mysqlx://test:test@" + ipAddress + ":" + XPort + "/" + "unknowndatabase")); - string connStr = "mysqlx://test:test@" + session.Settings.Server + ":" + XPort + "/?" + "ssl-mode=VerifyFull&ssl-ca=" + sslCa + "&ssl-ca-pwd=wrongpass"; - Assert.Catch(() => session1 = MySQLX.GetSession(connStr)); - } - - [Test, Description("Session.Uri")] - public void SessionUriAndDefaultSchemaTest() - { - if (!Platform.IsWindows()) return; - - using (var session1 = MySQLX.GetSession(ConnectionString)) - { - Assert.IsNotNull(session1.Uri); - } - - MySqlXConnectionStringBuilder sb = new MySqlXConnectionStringBuilder(ConnectionString); - var connectionString = ConnectionStringUserWithSSLPEM + ";protocol=TCP;database=" - + sb.Database + ";characterset=utf8mb4;sslmode=Required;connect-timeout=10;keepalive=10;auth=PLAIN"; - using (var session1 = MySQLX.GetSession(connectionString)) - { - Assert.IsNotNull(session1.Uri); - } - - using (var session1 = MySQLX.GetSession(new - { - server = sb.Server, - port = XPort, - user = sb.UserID, - password = sb.Password, - sslmode = MySqlSslMode.Required - })) - { - Assert.IsNotNull(session1.Uri); - } - - var conn = new MySqlConnectionStringBuilder(); - conn.Server = sb.Server; - conn.UserID = sb.UserID; - conn.Password = sb.Password; - conn.Port = Convert.ToUInt32(XPort); - conn.Database = schemaName; - conn.CharacterSet = "utf8mb4"; - conn.SslMode = MySqlSslMode.VerifyCA; - conn.SslCa = sslCa; - conn.CertificatePassword = sslCertificatePassword; - conn.Keepalive = 10; - conn.ConnectionProtocol = MySqlConnectionProtocol.Tcp; - - using (var session1 = MySQLX.GetSession(conn.ConnectionString)) - { - Assert.IsNotNull(session1.Uri); - } - - using (var session1 = MySQLX.GetSession(ConnectionStringUri + "/?ssl-mode=Required;")) - { - Assert.IsNotNull(session1.Uri); - } - - conn = new MySqlConnectionStringBuilder(); - conn.Server = sb.Server; - conn.UserID = sb.UserID; - conn.Password = sb.Password; - conn.Port = Convert.ToUInt32(XPort); - conn.ConnectionProtocol = MySqlConnectionProtocol.Tcp; - conn.Database = schemaName; - conn.CharacterSet = "utf8mb4"; - conn.SslMode = MySqlSslMode.Required; - conn.SslCa = sslCa; - conn.CertificatePassword = sslCertificatePassword; - conn.Keepalive = 10; - connectionString = conn.ConnectionString; - using (var session1 = MySQLX.GetSession(connectionString)) - { - Assert.AreEqual(schemaName, session1.DefaultSchema.Name); - Assert.IsNotNull(session1.Uri); - } - - conn = new MySqlConnectionStringBuilder(); - conn.Server = sb.Server; - conn.UserID = sb.UserID; - conn.Password = sb.Password; - conn.Port = Convert.ToUInt32(XPort); - conn.ConnectionProtocol = MySqlConnectionProtocol.Tcp; - conn.Database = schemaName; - conn.CharacterSet = "utf8mb4"; - conn.SslMode = MySqlSslMode.VerifyCA; - conn.SslCa = sslCa; - conn.CertificatePassword = sslCertificatePassword; - conn.Keepalive = 10; - connectionString = conn.ConnectionString; - using (var session1 = MySQLX.GetSession(connectionString)) - { - Assert.AreEqual(schemaName, session1.DefaultSchema.Name); - Assert.IsNotNull(session1.Uri); - } - - conn = new MySqlConnectionStringBuilder(); - conn.Server = sb.Server; - conn.UserID = sb.UserID; - conn.Password = sb.Password; - conn.Port = Convert.ToUInt32(XPort); - conn.ConnectionProtocol = MySqlConnectionProtocol.Tcp; - conn.Database = schemaName; - conn.CharacterSet = "utf8mb4"; - conn.Keepalive = 10; - connectionString = conn.ConnectionString; - using (var session1 = MySQLX.GetSession(connectionString)) - { - Assert.AreEqual(schemaName, session1.DefaultSchema.Name); - Assert.IsNotNull(session1.Uri); - session1.DropSchema("㭋玤䂜蚌"); - session1.CreateSchema("㭋玤䂜蚌"); - session1.SQL("USE 㭋玤䂜蚌").Execute(); - Assert.AreEqual(schemaName, session1.DefaultSchema.Name); - } - - conn.Database = "㭋玤䂜蚌"; - connectionString = conn.ConnectionString; - using (var session1 = MySQLX.GetSession(connectionString)) - { - Assert.AreEqual("㭋玤䂜蚌", session1.DefaultSchema.Name); - Assert.IsNotNull(session1.Uri); - } - - conn.Server = sb.Server; - conn.UserID = sb.UserID; - conn.Password = sb.Password; - conn.Port = Convert.ToUInt32(XPort); - conn.ConnectionProtocol = MySqlConnectionProtocol.Tcp; - conn.Database = "㭋玤䂜蚌"; - conn.CharacterSet = "utf8mb4"; - conn.SslMode = MySqlSslMode.VerifyCA; - conn.SslCa = sslCa; - conn.CertificatePassword = sslCertificatePassword; - conn.Keepalive = 10; - connectionString = conn.ConnectionString; - using (var session1 = MySQLX.GetSession(connectionString)) - { - Assert.AreEqual("㭋玤䂜蚌", session1.DefaultSchema.Name); - Assert.IsNotNull(session1.Uri); - session1.DropSchema("㭋玤䂜蚌"); - } - - } - - [Test, Description("Test MySqlX plugin Connection for user with wrong password")] - public void GetSessionWithWrongPassword() - { - MySqlXConnectionStringBuilder sb = new MySqlXConnectionStringBuilder(ConnectionString); - sb.Password = "wrongPassword"; - Assert.Throws(() => MySQLX.GetSession(sb.ConnectionString)); - } - - [Test, Description("Test MySqlX plugin Connection for user with correct password but non MysqlX Server")] - public void GetSessionWithWrongPort() - { - MySqlXConnectionStringBuilder sb = new MySqlXConnectionStringBuilder(ConnectionString); - sb.Port = Convert.ToUInt32(Port); - Assert.Throws(() => MySQLX.GetSession(sb.ConnectionString)); - } - - [Test, Description("Test MySqlX plugin Issue a drop command after session already closed")] - public void GetSessionDropAlreadyClosedConnection() - { - Session testSession = MySQLX.GetSession(ConnectionString); - testSession.Close(); - testSession.Close();//works and behaviour expected but any input command should fail - Assert.Throws(() => testSession.DropSchema(schemaName)); - - testSession = MySQLX.GetSession(ConnectionStringNoPassword); - testSession.Close(); - testSession.Close();//works and behaviour expected but any input command should fail - Assert.Throws(() => testSession.DropSchema(schemaName)); - } - - [Test, Description("Session.DefaultSchema")] - public void SessionDefaultSchema() - { - if (!Platform.IsWindows()) return; - - MySqlXConnectionStringBuilder sb = new MySqlXConnectionStringBuilder(ConnectionString); - sb.Database = null; - var session1 = MySQLX.GetSession(sb.ConnectionString); - Assert.AreEqual(null, session1.DefaultSchema); - string connectionString = ConnectionString + ";protocol=Socket;database=" + schemaName + ";characterset=utf8mb4;sslmode=VerifyCA;ssl-ca=" + - sslCa + ";certificatepassword=" + sslCertificatePassword + ";connect-timeout=10;keepalive=10;auth=PLAIN"; - session1 = MySQLX.GetSession(connectionString); - Assert.AreEqual(schemaName, session1.DefaultSchema.Name); - - session1 = MySQLX.GetSession(ConnectionStringUri + "/" + schemaName + "?" + "auth=PLAIN&characterset=utf8mb4"); - Assert.AreEqual(schemaName, session1.DefaultSchema.Name); - - session1 = MySQLX.GetSession(new - { - server = sb.Server, - port = XPort, - user = sb.UserID, - password = sb.Password, - sslmode = MySqlSslMode.Required, - database = schemaName - }); - Assert.AreEqual(schemaName, session1.DefaultSchema.Name); - session1.DefaultSchema.CreateCollection("tester"); - session1.DefaultSchema.DropCollection("tester"); - Assert.AreEqual(schemaName, session1.DefaultSchema.Session.DefaultSchema.Name); - - var conn = new MySqlConnectionStringBuilder(); - session1.DropSchema("㭋玤䂜蚌"); - session1.CreateSchema("㭋玤䂜蚌"); - session1.SQL("USE 㭋玤䂜蚌").Execute(); - Assert.AreEqual(schemaName, session1.DefaultSchema.Name); - session1.Dispose(); - conn.Server = sb.Server; - conn.UserID = sb.UserID; - conn.Password = sb.Password; - conn.Port = Convert.ToUInt32(XPort); - conn.ConnectionProtocol = MySqlConnectionProtocol.Tcp; - conn.Database = "㭋玤䂜蚌"; - conn.CharacterSet = "utf8mb4"; - conn.SslMode = MySqlSslMode.Required; - conn.SslCa = sslCa; - conn.CertificatePassword = sslCertificatePassword; - conn.Keepalive = 10; - connectionString = conn.ConnectionString; - session1 = MySQLX.GetSession(connectionString); - Assert.AreEqual("㭋玤䂜蚌", session1.DefaultSchema.Name); - StringAssert.Contains("㭋玤䂜蚌", session1.Uri); - - conn.Server = sb.Server; - conn.UserID = sb.UserID; - conn.Password = sb.Password; - conn.Port = Convert.ToUInt32(XPort); - conn.ConnectionProtocol = MySqlConnectionProtocol.Tcp; - conn.Database = "㭋玤䂜蚌"; - conn.CharacterSet = "utf8mb4"; - conn.SslMode = MySqlSslMode.Required; - conn.SslCa = sslCa; - conn.CertificatePassword = sslCertificatePassword; - conn.Keepalive = 10; - connectionString = conn.ConnectionString; - session1 = MySQLX.GetSession(connectionString); - Assert.AreEqual("㭋玤䂜蚌", session1.DefaultSchema.Name); - StringAssert.Contains("㭋玤䂜蚌", session1.Uri); - session1.DefaultSchema.CreateCollection("tester"); - session1.DefaultSchema.DropCollection("tester"); - Assert.AreEqual("㭋玤䂜蚌", session1.DefaultSchema.Session.DefaultSchema.Name); - } - - [Test, Description("Session BaseString/MySQLXConnectionString Builder")] - public void ConnectionStringBuilderXpluginTests() - { - if (!Platform.IsWindows()) return; - - MySqlXConnectionStringBuilder mysqlx0 = new MySqlXConnectionStringBuilder(ConnectionString); - mysqlx0.ConnectionProtocol = MySqlConnectionProtocol.Tcp; - mysqlx0.CharacterSet = "utf8mb4"; - mysqlx0.SslMode = MySqlSslMode.Required; - mysqlx0.ConnectTimeout = 10; - mysqlx0.Keepalive = 10; - mysqlx0.CertificateFile = sslCa; - mysqlx0.CertificatePassword = sslCertificatePassword; - mysqlx0.CertificateStoreLocation = MySqlCertificateStoreLocation.LocalMachine; - mysqlx0.CertificateThumbprint = ""; - - - using (var xpluginconn = MySQLX.GetSession(mysqlx0.ConnectionString)) - { - Assert.AreEqual(SessionState.Open, xpluginconn.InternalSession.SessionState); - } - - mysqlx0 = new MySqlXConnectionStringBuilder(ConnectionString); - mysqlx0.Server = "::1"; - mysqlx0.Database = schemaName; - mysqlx0.CharacterSet = "utf8mb4"; - mysqlx0.ConnectionProtocol = MySqlConnectionProtocol.Tcp; - mysqlx0.SslMode = MySqlSslMode.Required; - mysqlx0.ConnectTimeout = 10; - mysqlx0.Keepalive = 10; - mysqlx0.CertificateFile = sslCa; - mysqlx0.CertificatePassword = sslCertificatePassword; - mysqlx0.CertificateStoreLocation = MySqlCertificateStoreLocation.LocalMachine; - mysqlx0.CertificateThumbprint = sslCertificatePassword; - - using (var xpluginconn = MySQLX.GetSession(mysqlx0.ConnectionString)) - { - Assert.AreEqual(SessionState.Open, xpluginconn.InternalSession.SessionState); - } - - mysqlx0 = new MySqlXConnectionStringBuilder(ConnectionString); - mysqlx0.Database = schemaName; - mysqlx0.ConnectionProtocol = MySqlConnectionProtocol.Tcp; - mysqlx0.CharacterSet = "utf8mb4"; - mysqlx0.SslMode = MySqlSslMode.VerifyCA; - mysqlx0.ConnectTimeout = 10; - mysqlx0.Keepalive = 10; - mysqlx0.CertificateFile = sslCa; - mysqlx0.CertificatePassword = "pass"; - mysqlx0.CertificateStoreLocation = MySqlCertificateStoreLocation.LocalMachine; - mysqlx0.CertificateThumbprint = ""; - - using (var xpluginconn = MySQLX.GetSession(mysqlx0.ConnectionString)) - { - Assert.AreEqual(SessionState.Open, xpluginconn.InternalSession.SessionState); - } - - mysqlx0 = new MySqlXConnectionStringBuilder(ConnectionString); - mysqlx0.Database = schemaName; - mysqlx0.ConnectionProtocol = MySqlConnectionProtocol.Tcp; - mysqlx0.CharacterSet = "utf8mb4"; - mysqlx0.SslMode = MySqlSslMode.Required; - mysqlx0.ConnectTimeout = 10; - mysqlx0.Keepalive = 10; - - using (var xpluginconn = MySQLX.GetSession(mysqlx0.ConnectionString)) - { - Assert.AreEqual(SessionState.Open, xpluginconn.InternalSession.SessionState); - } - - //Scenario-2 - string valid = "server=" + mysqlx0.Server + ";user id=" + mysqlx0.UserID + ";password=" + mysqlx0.Password + ";port=" + XPort + ";protocol=Socket;database=" + schemaName + ";characterset=utf8mb4;sslmode=Required;certificatefile=" + sslCa + ";certificatepassword=" + sslCertificatePassword + ";connect-timeout=10;keepalive=10;certificatestorelocation=LocalMachine;certificatethumbprint=;"; - using (var xpluginconn = MySQLX.GetSession(valid)) - { - Assert.AreEqual(SessionState.Open, xpluginconn.InternalSession.SessionState); - } - - //Scenario-3 - mysqlx0 = new MySqlXConnectionStringBuilder(ConnectionString); - mysqlx0.Database = schemaName; - mysqlx0.ConnectionProtocol = MySqlConnectionProtocol.Tcp; - mysqlx0.CharacterSet = "utf8mb4"; - mysqlx0.SslMode = MySqlSslMode.Required; - mysqlx0.ConnectTimeout = 10; - mysqlx0.Keepalive = 10; - mysqlx0.CertificateFile = sslCa; - mysqlx0.CertificatePassword = sslCertificatePassword; - mysqlx0.CertificateStoreLocation = MySqlCertificateStoreLocation.LocalMachine; - mysqlx0.CertificateThumbprint = ""; - mysqlx0.Auth = MySqlAuthenticationMode.AUTO; - mysqlx0.SslCa = sslCa; - using (var xpluginconn = MySQLX.GetSession(mysqlx0.ConnectionString)) - { - Assert.AreEqual(SessionState.Open, xpluginconn.InternalSession.SessionState); - } - - //Basic Scenarios - var connectionstr = "server=" + mysqlx0.Server + ";database=" + mysqlx0.Database + ";port=" - + XPort + ";userid=" + mysqlx0.UserID + ";password=" - + mysqlx0.Password - + ";characterset=utf8mb4;sslmode=Required;connect-timeout=20000;keepalive=20000;certificatefile=" - + sslCa + ";certificatepassword=" + sslCertificatePassword - + ";certificatestorelocation=LocalMachine;certificatethumbprint="; - using (var xpluginconn = MySQLX.GetSession(connectionstr)) - { - Assert.AreEqual(SessionState.Open, xpluginconn.InternalSession.SessionState); - } - - connectionstr = "mysqlx://" + mysqlx0.Server + ":" + XPort + "/" + - schemaName + "?connect-timeout=10&userid=" + mysqlx0.UserID + "&password=" - + mysqlx0.Password + "&sslca=" + sslCa + "&certificatepassword=" - + sslCertificatePassword + "&keepalive=10&characterset=utf8mb4"; - - using (var xpluginconn = MySQLX.GetSession(connectionstr)) - { - Assert.AreEqual(SessionState.Open, xpluginconn.InternalSession.SessionState); - } - - using (var xpluginconn = MySQLX.GetSession(new - { - server = mysqlx0.Server, - port = XPort, - user = mysqlx0.UserID, - password = mysqlx0.Password - })) - { - Assert.AreEqual(SessionState.Open, xpluginconn.InternalSession.SessionState); - } - - } - - [Test, Description("Connection Measurement Test")] - public void ConnectionTimeTest() - { - int secondsExpected = 15; - var connObject = new { server = Host, port = XPort, user = session.Settings.UserID, password = session.Settings.Password }; - MeasureConnectionString(ConnectionString, secondsExpected, "Connection String", 5); - MeasureConnectionString(ConnectionStringUri, secondsExpected, "Connection String URI", 5); - MeasureConnectionObject(connObject, secondsExpected, "Connection Object", 5); - } - - [Test, Description("Connection time with Database set")] - public void ConnectionTimeWithDatabaseTest() - { - int secondsExpected = 15; - var connString = ConnectionString + ";database=test"; - var connStringURI = ConnectionStringUri + "/?database=test"; - MySqlXConnectionStringBuilder sb = new MySqlXConnectionStringBuilder(ConnectionString); - var connectionObject = new - { - server = sb.Server, - port = XPort, - user = sb.UserID, - password = sb.Password, - database = schemaName - }; - MeasureConnectionString(connString, secondsExpected, "Connection String", 5); - MeasureConnectionString(connStringURI, secondsExpected, "Connection String URI", 5); - MeasureConnectionObject(connectionObject, secondsExpected, "Connection Object", 5); - } - - [Test, Description("REFACTOR PARSING OF CONNECTION STRING IN X DEVAPI")] - [Ignore("Uncomment to execute")] - public void ParseConnectionStringBenchmark_S1() - { - long transactions = 0; - long startTime = 0; - long endTime = 0; - long queryRunTime = 0; - int iterations = 10; - long NANO_TO_MILLI = 1000000; - long elapsedTime = 0; - long conTime = 0; - int i = 0; - - string connStr = ConnectionString; - - var session = MySQLX.GetSession(connStr); - session.Close(); - - for (int j = 0; j < 1; j++) - { - transactions = 0; - startTime = 0; - endTime = 0; - queryRunTime = 0; - iterations = 20; - elapsedTime = 0; - conTime = 0; - connStr = ConnectionStringUri; - startTime = NanoTime(); - for (i = 0; i < iterations; i++) - { - queryRunTime = queryRunTime + DoConnectString(connStr); - } - endTime = NanoTime(); - transactions = i; - elapsedTime = (endTime - startTime); //in nano - conTime = (elapsedTime / NANO_TO_MILLI) - (queryRunTime / NANO_TO_MILLI); - var t = CalculateTPS(conTime, transactions); - var log = ("Connected to MySQL using URI with iterations " + iterations + " with TPS:" + t); - Assert.IsNotNull(t); - - transactions = 0; - startTime = 0; - endTime = 0; - queryRunTime = 0; - iterations = 20; - elapsedTime = 0; - conTime = 0; - connStr = ConnectionString; - startTime = NanoTime(); - for (i = 0; i < iterations; i++) - { - queryRunTime = queryRunTime + DoConnectString(connStr); - } - endTime = NanoTime(); - transactions = i; - elapsedTime = (endTime - startTime); //in nano - conTime = (elapsedTime / NANO_TO_MILLI) - (queryRunTime / NANO_TO_MILLI); - t = CalculateTPS(conTime, transactions); - log = ("Connected to MySQL using connection string with iterations " + iterations + " with TPS:" + t); - Console.WriteLine(log); - Assert.IsNotNull(t); - - transactions = 0; - startTime = 0; - endTime = 0; - queryRunTime = 0; - iterations = 20; - elapsedTime = 0; - conTime = 0; - MySqlXConnectionStringBuilder sb = new MySqlXConnectionStringBuilder(ConnectionString); - var conn = new - { - server = sb.Server, - port = XPort, - user = sb.UserID, - password = sb.Password - }; - startTime = NanoTime(); - for (i = 0; i < iterations; i++) - { - queryRunTime = queryRunTime + DoConnectObject(conn); - } - endTime = NanoTime(); - transactions = i; - elapsedTime = (endTime - startTime); //in nano - conTime = (elapsedTime / NANO_TO_MILLI) - (queryRunTime / NANO_TO_MILLI); - t = CalculateTPS(conTime, transactions); - log = ("Connected to MySQL using Anonymous with iterations " - + iterations + - " with TPS:" + t); - } - } - - [Test, Description("REFACTOR PARSING OF CONNECTION STRING IN X DEVAPI")] - [Ignore("Uncomment to execute")] - public void ParseConnectionStringBenchmark_S2() - { - var connStr = ConnectionStringUri; - long queryStartTime = 0, queryRunTime = 0; - queryStartTime = NanoTime(); - var session1 = MySQLX.GetSession(connStr); - queryRunTime = NanoTime() - queryStartTime; - session1.Close(); - for (int j = 0; j < 20; j++) - { - connStr = ConnectionStringUri; - queryStartTime = 0; queryRunTime = 0; - queryStartTime = NanoTime(); - session1 = MySQLX.GetSession(connStr); - queryRunTime = NanoTime() - queryStartTime; - session1.Close(); - session1.Dispose(); - var log = ("Connected to MySQL using URI:" + queryRunTime / 1000000); - - connStr = ConnectionString; - queryStartTime = 0; queryRunTime = 0; - queryStartTime = NanoTime(); - session1 = MySQLX.GetSession(connStr); - queryRunTime = NanoTime() - queryStartTime; - session1.Close(); - session1.Dispose(); - log = ("Connected to MySQL using connection string:" + queryRunTime / 1000000); - - MySqlXConnectionStringBuilder sb = new MySqlXConnectionStringBuilder(ConnectionString); - var conn = new - { - server = sb.Server, - port = XPort, - user = sb.UserID, - password = sb.Password - }; - queryStartTime = 0; queryRunTime = 0; - queryStartTime = NanoTime(); - session1 = MySQLX.GetSession(conn); - queryRunTime = NanoTime() - queryStartTime; - session1.Close(); - session1.Dispose(); - log = ("Connected to MySQL using Connection Object:" + queryRunTime / 1000000); - } - } - - [Test, Description("Getsession/Session-URI")] - public void GetSessionUriPositiveTests() - { - string[] positiveStringList = new string[6]; - MySqlXConnectionStringBuilder sb = new MySqlXConnectionStringBuilder(ConnectionString); - positiveStringList[0] = "mysqlx://" + sb.UserID + ":" + sb.Password + "@" + sb.Server + ":" + XPort + "/?ssl-mode=Required"; - positiveStringList[1] = "mysqlx://" + sb.UserID + ":" + sb.Password + "@" + Host + ":" + XPort + "/?ssl-mode=Required"; - positiveStringList[2] = "mysqlx://" + sb.UserID + ":" + sb.Password + "@" + Host + ":" + XPort + "/" + schemaName + "?ssl-mode=Required"; - positiveStringList[3] = "mysqlx://" + sb.UserID + ":" + sb.Password + "@" + sb.Server + ":" + XPort + "/" + schemaName + "?ssl-mode=Required&auth=SHA256_MEMORY"; - positiveStringList[4] = "mysqlx://" + sb.UserID + ":" + sb.Password + "@" + sb.Server + ":" + XPort + "/" + schemaName + "?ssl-mode=Required&characterset=utf8mb4"; - positiveStringList[5] = "mysqlx://" + sb.UserID + ":" + sb.Password + "@" + sb.Server + ":" + XPort + "/" + schemaName + "?" + "ssl-mode=Required"; - - foreach (var connStr in positiveStringList) - { - using (Session c = MySQLX.GetSession(connStr)) - { - Assert.AreEqual(SessionState.Open, c.InternalSession.SessionState); - } - } - } - - [Test, Description("Getsession/Session-URI Negative Scenarios")] - public void GetSessionUriNegativeTests() - { - string[] NegativeStringList = new string[8]; - MySqlXConnectionStringBuilder sb = new MySqlXConnectionStringBuilder(ConnectionString); - NegativeStringList[0] = "mysqlx://" + sb.UserID + ":" + sb.Password + "@" + sb.Server + ":" + 9999 + ";ssl-mode=required"; - NegativeStringList[1] = "mysqlx://" + sb.UserID + ":" + sb.Password + "@" + "129.0.0.1" + ":" + XPort + ";ssl-mode=required"; - NegativeStringList[2] = "mysqlx://" + sb.UserID + ":" + "wrongpassword" + "@" + "localhost" + ":" + XPort + "/" + schemaName + "?ssl-mode=required"; - NegativeStringList[3] = "mysqlxyzzzz://" + sb.UserID + ":" + sb.Password + "@" + sb.Server + ":" + XPort + "/" + schemaName + "?ssl-mode=required"; - NegativeStringList[4] = "mysqlx://" + "wrongsb.UserID" + ":" + sb.Password + "@" + sb.Server + ":" + XPort + "/" + schemaName + "?ssl-mode=required"; - NegativeStringList[5] = "mysqlx://" + sb.UserID + ":" + sb.Password + "@" + "wronglocalhost" + "/" + schemaName + "?sslmode=required"; - NegativeStringList[6] = "mysqlx://" + sb.UserID + ":" + sb.Password + "@" + sb.Server + ":" + XPort + "/" + schemaName + "?" + "ssl-mode*&^%$#@!invalidvalues123*()"; - NegativeStringList[7] = "mysqlx://" + sb.UserID + ":" + sb.Password + "@" + sb.Server + ":" + XPort + "/" + schemaName + "?" + "invalidvalues123invalidvalues123invalidvalues123invalidvalues123invalidvalues123invalidvalues123invalidvalues123invalidvalues123" + ";ssl-mode=required"; - - foreach (var connStr in NegativeStringList) - { - Assert.Catch(() => MySQLX.GetSession(connStr)); - } - } - - [Test, Description("Getsession using Anonymous Type Negative-Wrong Password")] - public void GetSessionAnonymousTypeNegative() - { - var connectionStringObject = new { connection = $"server={Host};user={session.Settings.UserID};port={XPort};password=wrong_password;sslmode={MySqlSslMode.Required}" }; - Assert.Throws(() => MySQLX.GetSession(connectionStringObject.connection)); - } - - [Test, Description("Support Session Anonymous as uri string Positive")] - public void GetSessionWithAnonymousObjectURI() - { - var connectionStringObject = new { connection = ConnectionStringUri }; - using (Session sessionPlain = MySQLX.GetSession(connectionStringObject.connection)) - { - var db = sessionPlain.GetSchema(schemaName); - var col = db.GetCollection("my_collection_123456789"); - if (col.ExistsInDatabase()) - { - db.DropCollection("my_collection_123456789"); - db.CreateCollection("my_collection_123456789"); - } - else { db.CreateCollection("my_collection_123456789"); } - db.DropCollection("my_collection_123456789"); - } - if (Convert.ToInt32(XPort) == 33060)//Connect to server on localhost with user userx using URI string default port - { - MySqlXConnectionStringBuilder sb = new MySqlXConnectionStringBuilder(ConnectionString); - connectionStringObject = new { connection = "mysqlx://" + sb.UserID + ":" + sb.Password + "@" + sb.Server }; - using (Session sessionPlain = MySQLX.GetSession(connectionStringObject.connection)) - { - var db = sessionPlain.GetSchema(schemaName); - var col = db.GetCollection("my_collection_123456789"); - if (col.ExistsInDatabase()) - { - db.DropCollection("my_collection_123456789"); - db.CreateCollection("my_collection_123456789"); - } - else { db.CreateCollection("my_collection_123456789"); } - db.DropCollection("my_collection_123456789"); - } - } - } - - [Test, Description("Support Session connection string as uri string Negative-Invalid Password")] - public void GetSessionURIWrongPassword() - { - string invalidPassword = "invalid"; - MySqlXConnectionStringBuilder sb = new MySqlXConnectionStringBuilder(ConnectionString); - string connectionString = "mysqlx://" + sb.UserID + ":" + invalidPassword + "@" + sb.Server + ":" + XPort; - Assert.Throws(() => MySQLX.GetSession(connectionString)); - connectionString = "mysqlx://" + sb.UserID + ":" + invalidPassword + "@" + sb.Server; - Assert.Throws(() => MySQLX.GetSession(connectionString)); - } - - // Connection Timeout Tests - [Test, Description("Remote offline host without connect-timeout parameter.Mysql getclient with pooling and maxsize 2 and queue timeout 2000 milliseconds")] - public void TimeoutUsingClientAndPooling_S1() - { - MySqlXConnectionStringBuilder sb = new MySqlXConnectionStringBuilder(ConnectionString); - string serverName = "10.10.10.10"; - string connStr = "server=" + serverName + ";user=" + sb.UserID + ";port=" + XPort + ";password=" - + sb.Password + ";"; - var connectionpooling = "{ \"pooling\": { \"maxSize\": 1, \"queueTimeout\": 2000 , \"maxIdleTime\":1000, \"enabled\": true} }"; - var connectionpoolingObject = new { pooling = new { enabled = true, maxSize = 1, queueTimeout = 2000, maxIdleTime = 1000 } }; - Client client = MySQLX.GetClient(connStr, connectionpoolingObject); - TestFailureTimeout(client, 9, 11, "Timeout value between 9 and 11 seconds"); - var connStrUri = "mysqlx://" + sb.UserID + ":" + sb.Password + "@" + serverName + ":" + XPort; - client = MySQLX.GetClient(connStrUri, connectionpoolingObject); - TestFailureTimeout(client, 9, 11, "Timeout value between 9 and 11 seconds"); - var connObj = new { server = serverName, port = XPort, user = sb.UserID, password = sb.Password }; - client = MySQLX.GetClient(connObj, connectionpoolingObject); - TestFailureTimeout(client, 9, 11, "Timeout value between 9 and 11 seconds"); - client = MySQLX.GetClient(connStr, connectionpooling); - TestFailureTimeout(client, 9, 11, "Timeout value between 9 and 11 seconds"); - client = MySQLX.GetClient(connStrUri, connectionpooling); - TestFailureTimeout(client, 9, 11, "Timeout value between 9 and 11 seconds"); - client = MySQLX.GetClient(connObj, connectionpooling); - TestFailureTimeout(client, 9, 11, "Timeout value between 9 and 11 seconds"); - } - - [Test, Description("failover connection string with one offline host and one online host and disable connect - timeout parameter(set to 0) " + - ".Mysql getclient with pooling and maxsize 2 and queue timeout 2000 milliseconds.Both the session should be successful after" + - "waiting for the respective lower layer socket timeout")] - public void TimeoutUsingClientAndPooling_S2() - { - int connectTimeout = 1; - string hostList = string.Empty; - string localIP = session.Settings.Server; - int minTime = 0; - int maxTime = 30; - session.Settings.UserID = "testAnyhost"; - string connStr = "server=10.10.10.10," + localIP + ";port=" + XPort + ";uid=" + session.Settings.UserID + ";" + "password=" + session.Settings.Password + - ";connect-timeout=" + connectTimeout; - var connectionpoolingObject = new { pooling = new { enabled = true, maxSize = 1, queueTimeout = 20000, maxIdleTime = 1000 } }; - - TestClientSuccessTimeout(minTime, maxTime, $"Timeout value between {minTime} and {maxTime} seconds", connStr, connectionpoolingObject); - - var connStrUri = "mysqlx://" + session.Settings.UserID + ":" + session.Settings.Password + "@[192.1.10.10," + localIP + ":" + XPort + "]" + "/?connect-timeout=" + connectTimeout; - TestClientSuccessTimeout(minTime, maxTime, $"Timeout value between {minTime} and {maxTime} seconds", connStr, connectionpoolingObject); - - } - - [Test, Description("connect - timeout parameter set as 1000 milliseconds.Create a pool of two sessions." + - "pooling(enabled:true,maxSize:2,queueTimeout: 2000 milliseconds).Try to create a third connection and verify the behaviour(Queue timeout expected)")] - public void TimeoutReachingMaxSizePool() - { - int connectTimeout = 1000; - string hostList = string.Empty; - string localIP = session.Settings.Server; - string connStr = "server=" + localIP + ";port=" + XPort + ";uid=" + session.Settings.UserID + ";" + "password=" + session.Settings.Password + - ";connect-timeout=" + connectTimeout; - var connectionpooling = "{ \"pooling\": { \"maxSize\": 2, \"queueTimeout\": 2000 , \"maxIdleTime\":1000, \"enabled\": true} }"; - var connectionpoolingObject = new { pooling = new { enabled = true, maxSize = 2, queueTimeout = 2000, maxIdleTime = 1000 } }; - using (Client client = MySQLX.GetClient(connStr, connectionpoolingObject)) - { - var session1 = client.GetSession(); - var session2 = client.GetSession(); - TestClientQueueTimeout(client, 1, 3, "Test queue timeout"); - } - var connStrUri = "mysqlx://" + session.Settings.UserID + ":" + session.Settings.Password + "@[" + localIP + ":" + XPort + "]" + "/?connect-timeout=" + connectTimeout; - using (var client = MySQLX.GetClient(connStrUri, connectionpoolingObject)) - { - - var session1 = client.GetSession(); - var session2 = client.GetSession(); - TestClientQueueTimeout(client, 1, 3, "Test queue timeout"); - } - var connObj = new { server = "" + localIP, port = XPort, uid = session.Settings.UserID, password = session.Settings.Password, connecttimeout = connectTimeout }; - using (var client = MySQLX.GetClient(connObj, connectionpoolingObject)) - { - var session1 = client.GetSession(); - var session2 = client.GetSession(); - TestClientQueueTimeout(client, 1, 3, "Test queue timeout"); - } - - using (Client client = MySQLX.GetClient(connStr, connectionpooling)) - { - var session1 = client.GetSession(); - var session2 = client.GetSession(); - TestClientQueueTimeout(client, 1, 3, "Test queue timeout"); - } - using (var client = MySQLX.GetClient(connStrUri, connectionpooling)) - { - var session1 = client.GetSession(); - var session2 = client.GetSession(); - TestClientQueueTimeout(client, 1, 3, "Test queue timeout"); - } - using (var client = MySQLX.GetClient(connObj, connectionpooling)) - { - var session1 = client.GetSession(); - var session2 = client.GetSession(); - TestClientQueueTimeout(client, 1, 3, "Test queue timeout"); - } - for (var i = 1; i <= 2; i++) - { - hostList = "(address=143.24.20.36,priority=1),(address=" + localIP + ",priority=0)"; - } - connStr = "server=" + hostList + ";user=" + session.Settings.UserID + ";port=" + XPort + ";password=" - + session.Settings.Password + ";connect-timeout=" + connectTimeout; - - using (var client = MySQLX.GetClient(connStr, connectionpoolingObject)) - { - var session1 = client.GetSession(); - var session2 = client.GetSession(); - TestClientQueueTimeout(client, 1, 3, "Test queue timeout X"); - } - - var connObj1 = new { server = hostList, port = XPort, user = session.Settings.UserID, password = session.Settings.Password, connecttimeout = connectTimeout }; - using (var client = MySQLX.GetClient(connObj1, connectionpoolingObject)) - { - var session1 = client.GetSession(); - var session2 = client.GetSession(); - TestClientQueueTimeout(client, 1, 3, "Test queue timeout Y"); - } - using (var client = MySQLX.GetClient(connStr, connectionpooling)) - { - var session1 = client.GetSession(); - var session2 = client.GetSession(); - TestClientQueueTimeout(client, 1, 3, "Test queue timeout X"); - } - connObj1 = new { server = hostList, port = XPort, user = session.Settings.UserID, password = session.Settings.Password, connecttimeout = connectTimeout }; - using (var client = MySQLX.GetClient(connObj1, connectionpooling)) - { - var session1 = client.GetSession(); - var session2 = client.GetSession(); - TestClientQueueTimeout(client, 1, 3, "Test queue timeout A"); - } - - } - - [Test, Description("scenario 0(connectionString,connectionUri,Anonymous Object)-Without connect timeout and max timeout should be 10s")] - public void TimeoutWithWrongHost() - { - string serverName = "vigdis07.no.oracle.com"; - string connStr = "server=" + serverName + ";user=" + session.Settings.UserID + ";port=" + XPort + ";password=" - + session.Settings.Password + ";"; - TestConnectStringTimeoutFailureTimeout(connStr, 0, 11, "Timeout value between 9 and 11 seconds"); - connStr = "mysqlx://" + session.Settings.UserID + ":" + session.Settings.Password + "@" + serverName + ":" + XPort; - TestConnectStringTimeoutFailureTimeout(connStr, 0, 11, "Timeout value between 9 and 11 seconds"); - var connObj = new { server = serverName, port = XPort, user = session.Settings.UserID, password = session.Settings.Password }; - TestConnectObjTimeoutFailureTimeout(connObj, 0, 11, "Timeout value between 9 and 11 seconds"); - - } - - [Test, Description("scenario 1(connectionString,connectionUri,Anonymous Object)")] - public void MeasureNoTimeoutResponse() - { - string connStr = "server=" + session.Settings.Server + ";user=" + session.Settings.UserID + ";port=" + XPort + ";password=" - + session.Settings.Password + ";" + "connect-timeout=90;"; - TestConnectStringTimeoutSuccessTimeout(connStr, 0, 3, "Timeout value between 0 and 1 second"); - connStr = "mysqlx://" + session.Settings.UserID + ":" + session.Settings.Password + "@" + session.Settings.Server + ":" + XPort + "?connect-timeout=900;"; - TestConnectStringTimeoutSuccessTimeout(connStr, 0, 3, "Timeout value between 0 and 1 second"); - var connObj = new { server = session.Settings.Server, port = XPort, user = session.Settings.UserID, password = session.Settings.Password, connecttimeout = 9000 }; - TestConnectObjectTimeoutSuccessTimeout(connObj, 0, 3, "Timeout value between 0 and 1 second"); - } - - [Test, Description("scenario 2(connectionString,connectionUri,Anonymous Object with all options)")] - public void NoTimeoutWithManyOptions() - { - if (!Platform.IsWindows()) return; - string connStr = "server=" + session.Settings.Server + ";user id=" + session.Settings.UserID + ";password=" + - session.Settings.Password + ";port=" + XPort + ";protocol=Socket;" + - "database=" + schemaName + ";characterset=utf8mb4;sslmode=VerifyCA;ssl-ca=" - + sslCa + ";certificatepassword=pass;keepalive=10;auth=PLAIN;" - + "connect-timeout=900;"; - TestConnectStringTimeoutSuccessTimeout(connStr, 0, 1, "Timeout value between 0 and 1 second"); - connStr = "mysqlx://" + session.Settings.Server + ":" + XPort + "/" + schemaName - + "?" + "user id=" + session.Settings.UserID + "&password=" + session.Settings.Password + "&sslca=" - + sslCa + "&certificatepassword=pass&keepalive=10&characterset=utf8mb4&auth=PLAIN&connect-timeout=900"; - TestConnectStringTimeoutSuccessTimeout(connStr, 0, 1, "Timeout value between 0 and 1 second"); - var connObj = - new - { - server = session.Settings.Server, - port = XPort, - user = session.Settings.UserID, - password = session.Settings.Password, - sslmode = MySqlSslMode.VerifyCA, - CertificateFile = sslCa, - CertificatePassword = sslCertificatePassword, - database = schemaName, - keepalive = 10, - characterset = "utf8mb4", - auth = MySqlAuthenticationMode.PLAIN, - connecttimeout = 9000 - }; - TestConnectStringTimeoutSuccessTimeout(connStr, 0, 1, "Timeout value between 0 and 1 second"); - } - - [Test, Description("scenario 1(MysqlxStringBuilder)")] - public void TimeoutSuccessWithStringBuilder() - { - var connStrBuilder = new MySqlXConnectionStringBuilder(); - connStrBuilder.ConnectTimeout = 9000; - connStrBuilder.UserID = session.Settings.UserID; - connStrBuilder.Password = session.Settings.Password; - connStrBuilder.Port = Convert.ToUInt32(XPort); - connStrBuilder.Server = session.Settings.Server; - TestConnectStringTimeoutSuccessTimeout(connStrBuilder.ConnectionString, 0, 3, "Timeout value between 0 and 3 second"); - string connStr = "server=" + session.Settings.Server + ";user=" + session.Settings.UserID + ";port=" + XPort + ";password=" - + session.Settings.Password + ";" + "connect-timeout=9000;"; - connStrBuilder = new MySqlXConnectionStringBuilder(connStr); - TestConnectStringTimeoutSuccessTimeout(connStrBuilder.ConnectionString, 0, 3, "Timeout value between 0 and 3 second"); - } - - [Test, Description("scenario 2(MysqlxStringBuilder with all options)")] - public void TimeoutSuccessWithStringBuilderAllOptions() - { - string connStr = null; - MySqlXConnectionStringBuilder mysqlx0 = null; - if (!Platform.IsWindows()) return; - connStr = "server=" + session.Settings.Server + ";user id=" + session.Settings.UserID + ";password=" + - session.Settings.Password + ";port=" + XPort + ";protocol=Socket;" + - "database=" + schemaName + ";characterset=utf8mb4;sslmode=Required;ssl-ca=" - + sslCa + $";certificatepassword={sslCertificatePassword};certificatestorelocation=LocalMachine;" - + ";keepalive =10;auth=PLAIN;certificatethumbprint=;" - + "connect-timeout=" + 9000; - mysqlx0 = new MySqlXConnectionStringBuilder(connStr); - TestConnectStringTimeoutSuccessTimeout(mysqlx0.ConnectionString, 0, 1, "Timeout value between 0 and 1 second"); - mysqlx0 = new MySqlXConnectionStringBuilder(); - mysqlx0.Server = session.Settings.Server; - mysqlx0.UserID = session.Settings.UserID; - mysqlx0.Password = session.Settings.Password; - mysqlx0.Port = Convert.ToUInt32(XPort); - mysqlx0.ConnectionProtocol = MySqlConnectionProtocol.Tcp; - mysqlx0.Database = schemaName; - mysqlx0.CharacterSet = "utf8mb4"; - mysqlx0.SslMode = MySqlSslMode.Required; - mysqlx0.SslCa = sslCa; - mysqlx0.CertificatePassword = sslCertificatePassword; - mysqlx0.CertificateStoreLocation = MySqlCertificateStoreLocation.LocalMachine; - mysqlx0.Keepalive = 10; - mysqlx0.Auth = MySqlAuthenticationMode.PLAIN; - mysqlx0.CertificateThumbprint = ""; - mysqlx0.ConnectTimeout = (uint)90000; - TestConnectStringTimeoutSuccessTimeout(mysqlx0.ConnectionString, 0, 1, "Timeout value between 0 and 1 second"); - } - - [Test, Description("scenario 3(MysqlxStringBuilder with all options-set minimum timeout to 1 and keep on increasing till gets connected)")] - public void TimeoutIncreasingUntilConnect() - { - string connStr = null; - MySqlXConnectionStringBuilder mysqlx0 = null; - - for (int i = 1; i < 20; i++) - { - connStr = ConnectionString + ";protocol=Socket;" + - "database=" + schemaName + ";characterset=utf8mb4;sslmode=VerifyCA;ssl-ca=" - + sslCa + $";certificatepassword={sslCertificatePassword};certificatestorelocation=LocalMachine;" - + ";auth=PLAIN;certificatethumbprint=;" - + "connect-timeout=" + i; - mysqlx0 = new MySqlXConnectionStringBuilder(connStr); - using (var conn = MySQLX.GetSession(mysqlx0.ConnectionString)) - { - Assert.IsNotNull(conn.Uri); - } - break; - } - - for (int i = 1; i < 20; i++) - { - mysqlx0 = new MySqlXConnectionStringBuilder(); - mysqlx0.Server = session.Settings.Server; - mysqlx0.UserID = session.Settings.UserID; - mysqlx0.Password = session.Settings.Password; - mysqlx0.Port = Convert.ToUInt32(XPort); - mysqlx0.ConnectionProtocol = MySqlConnectionProtocol.Tcp; - mysqlx0.Database = schemaName; - mysqlx0.CharacterSet = "utf8mb4"; - mysqlx0.SslMode = MySqlSslMode.VerifyCA; - mysqlx0.SslCa = sslCa; - mysqlx0.CertificatePassword = sslCertificatePassword; - mysqlx0.CertificateStoreLocation = MySqlCertificateStoreLocation.LocalMachine; - mysqlx0.Auth = MySqlAuthenticationMode.PLAIN; - mysqlx0.CertificateThumbprint = ""; - mysqlx0.ConnectTimeout = (uint)i; - - using (var conn = MySQLX.GetSession(mysqlx0.ConnectionString)) - { - Assert.IsNotNull(conn.Uri); - } - break; - } - } - - [Test, Description("scenario 1(connectionString,connectionUri,Anonymous Object with default timeout)")] - public void ValidateDefaultTimeoutParameter() - { - uint defaultTimeout = 1; - string connStr = ConnectionString + ";" + "connect-timeout=" + defaultTimeout; - for (int i = 0; i < 10; i++) - { - using (var conn = MySQLX.GetSession(connStr)) - { - Assert.AreEqual(conn.Settings.ConnectTimeout, defaultTimeout); - } - } - connStr = "mysqlx://" + session.Settings.UserID + ":" + session.Settings.Password + "@" + session.Settings.Server + ":" + XPort + "?connect-timeout=" + defaultTimeout; - for (int i = 0; i < 10; i++) - { - using (var conn = MySQLX.GetSession(connStr)) - { - Assert.AreEqual(conn.Settings.ConnectTimeout, defaultTimeout); - } - } - var connObj1 = new { server = session.Settings.Server, port = XPort, user = session.Settings.UserID, password = session.Settings.Password, connecttimeout = defaultTimeout }; - for (int i = 0; i < 10; i++) - { - using (var conn = MySQLX.GetSession(connObj1)) - { - Assert.AreEqual(conn.Settings.ConnectTimeout, defaultTimeout); - } - } - } - - [Test, Description("scenario 2(MysqlxStringBuilder with default timeout)")] - public void ValidateDefaultTimeoutParameterWithStringBuilder() - { - uint defaultTimeout = 1; - var connStrBuilder = new MySqlXConnectionStringBuilder(); - connStrBuilder.ConnectTimeout = defaultTimeout; - connStrBuilder.UserID = session.Settings.UserID; - connStrBuilder.Password = session.Settings.Password; - connStrBuilder.Port = Convert.ToUInt32(XPort); - connStrBuilder.Server = session.Settings.Server; - for (int i = 0; i < 10; i++) - { - using (var conn = MySQLX.GetSession(connStrBuilder.ConnectionString)) - { - Assert.AreEqual(conn.Settings.ConnectTimeout, defaultTimeout); - } - } - string connStr = ConnectionString + ";" + "connect-timeout=" + defaultTimeout; - connStrBuilder = new MySqlXConnectionStringBuilder(connStr); - for (int i = 0; i < 10; i++) - { - using (var conn = MySQLX.GetSession(connStrBuilder.ConnectionString)) - { - Assert.AreEqual(conn.Settings.ConnectTimeout, defaultTimeout); - } - } - } - - [Test, Description("scenario 1(MysqlxStringBuilder with connect timeout option for offline server)")] - public void TimeoutOfflineServerWithStringBuilder() - { - int connectionTimeout = 2000; - string serverName = "vigdis07.no.oracle.com"; - var connStrBuilder = new MySqlXConnectionStringBuilder(); - connStrBuilder.ConnectTimeout = (uint)connectionTimeout; - connStrBuilder.UserID = session.Settings.UserID; - connStrBuilder.Password = session.Settings.Password; - connStrBuilder.Port = Convert.ToUInt32(XPort); - connStrBuilder.Server = serverName; - TestConnectStringTimeoutFailureTimeout(connStrBuilder.ConnectionString, 0, 21, "Offline host timeout value in between 1 and 21 seconds"); - - string connStr = "server=" + serverName + ";user=" + session.Settings.UserID + ";port=" + XPort + ";password=" - + session.Settings.Password + ";" + "connect-timeout=" + connectionTimeout; - connStrBuilder = new MySqlXConnectionStringBuilder(connStr); - TestConnectStringTimeoutFailureTimeout(connStrBuilder.ConnectionString, 0, 21, "Offline host timeout value in between 1 and 21 seconds"); - } - - [Test, Description("scenario 1(connectionString,connectionUri,Anonymous Object,MysqlxStringBuilder with connect timeout option=1 for online server)")] - public void TimeoutSuccessConnectOptionOne() - { - int connectionTimeout = 1; - string connStr = ConnectionString + ";" + "connect-timeout=" + connectionTimeout; - TestConnectStringTimeoutSuccessTimeout(connStr, 0, 5, "Checking the timeout between 0 to 5 seconds"); - connStr = ConnectionStringUri + "?connect-timeout=" + connectionTimeout; - TestConnectStringTimeoutSuccessTimeout(connStr, 0, 5, "Checking the timeout between 0 to 5 seconds"); - var connectionObj = new { server = session.Settings.Server, port = XPort, user = session.Settings.UserID, password = session.Settings.Password, connecttimeout = connectionTimeout }; - TestConnectObjectTimeoutSuccessTimeout(connectionObj, 0, 5, "Checking the timeout between 0 to 5 seconds"); - - var connStrBuilder = new MySqlXConnectionStringBuilder(); - connStrBuilder.ConnectTimeout = (uint)connectionTimeout; - connStrBuilder.UserID = session.Settings.UserID; - connStrBuilder.Password = session.Settings.Password; - connStrBuilder.Port = Convert.ToUInt32(XPort); - connStrBuilder.Server = session.Settings.Server; - TestConnectStringTimeoutSuccessTimeout(connStrBuilder.ConnectionString, 0, 5, "Checking the timeout between 0 to 5 seconds"); - - connStr = ConnectionString + ";" + "connect-timeout=" + connectionTimeout; - connStrBuilder = new MySqlXConnectionStringBuilder(connStr); - TestConnectStringTimeoutSuccessTimeout(connStrBuilder.ConnectionString, 0, 5, "Checking the timeout between 0 to 5 seconds"); - - } - - [Test, Description("scenario 1(connectionString,connectionUri,Anonymous Object,MysqlxStringBuilder with connect timeout option=0 for offline server)")] - public void TimeoutOfflineServerConnectOptionZero() - { - int connectionTimeout = 0; - string serverName = "vigdis07.no.oracle.com"; - - string connStr = "server=" + serverName + ";user=" + session.Settings.UserID + ";port=" + XPort + ";password=" - + session.Settings.Password + ";" + "connect-timeout=" + connectionTimeout; - TestConnectStringTimeoutFailureTimeout(connStr, 0, 50000, "Checking the timeout between 0 to 50000 milliseconds"); - - connStr = "mysqlx://" + session.Settings.UserID + ":" + session.Settings.Password + "@" + serverName + ":" + XPort + "?connect-timeout=" + connectionTimeout; - TestConnectStringTimeoutFailureTimeout(connStr, 0, 50000, "Checking the timeout between 0 to 50000 milliseconds"); - - var connObj = new { server = serverName, port = XPort, user = session.Settings.UserID, password = session.Settings.Password, connecttimeout = connectionTimeout }; - TestConnectObjTimeoutFailureTimeout(connObj, 0, 50000, "Checking the timeout between 0 to 50000 milliseconds"); - - var connStrBuilder = new MySqlXConnectionStringBuilder(); - connStrBuilder.ConnectTimeout = (uint)connectionTimeout; - connStrBuilder.UserID = session.Settings.UserID; - connStrBuilder.Password = session.Settings.Password; - connStrBuilder.Port = Convert.ToUInt32(XPort); - connStrBuilder.Server = serverName; - TestConnectStringTimeoutFailureTimeout(connStr, 0, 50000, "Checking the timeout between 0 to 50000 milliseconds"); - - connStr = "server=" + serverName + ";user=" + session.Settings.UserID + ";port=" + XPort + ";password=" - + session.Settings.Password + ";" + "connect-timeout=" + connectionTimeout; - connStrBuilder = new MySqlXConnectionStringBuilder(connStr); - TestConnectStringTimeoutFailureTimeout(connStr, 0, 50000, "Checking the timeout between 0 to 50000 milliseconds"); - - } - - [Test, Description("(connectionString,connectionUri,Anonymous Object.Test that the timeout will be reset for each connection attempt in a failover scenario")] - public void ConnectTimeoutSeveralAddreses() - { - StringBuilder hostList = new StringBuilder(); - int connectionTimeout = 1000; - var priority = 100; - for (var i = 1; i <= 101; i++) - { - hostList.Append("(address=server" + i + ".example,priority=" + (priority != 0 ? priority-- : 0) + "),"); - if (i == 101) hostList.Append($"(address={Host},priority=0)"); - } - - using (var session1 = MySQLX.GetSession("server=" + hostList + ";port=" + XPort + ";uid=" + - session.Settings.UserID + ";password=" + session.Settings.Password + ";connect-timeout=" + - connectionTimeout + ";ssl-mode=required")) - { - Assert.AreEqual(SessionState.Open, session1.InternalSession.SessionState); - var schema = session1.GetSchema("test"); - Assert.IsNotNull(schema); - } - - var connStr = "mysqlx://" + session.Settings.UserID + ":" + session.Settings.Password + "@[" + hostList + "]/?connect-timeout=" + connectionTimeout; - using (var session1 = MySQLX.GetSession(connStr)) - { - Assert.AreEqual(SessionState.Open, session1.InternalSession.SessionState); - var schema = session1.GetSchema("test"); - Assert.IsNotNull(schema); - } - - using (var session1 = MySQLX.GetSession(new - { - server = hostList.ToString(), - port = XPort, - user = session.Settings.UserID, - password = session.Settings.Password, - sslmode = MySqlSslMode.Required - })) - { - Assert.AreEqual(SessionState.Open, session1.InternalSession.SessionState); - var schema = session1.GetSchema("test"); - Assert.IsNotNull(schema); - } - - var strList = "(address=143.24.20.36,priority=0),(address=10.172.165.157,priority=1)"; - connectionTimeout = 2000; - var connString = "server=" + strList + ";port=" + XPort + ";uid=" + - session.Settings.UserID + ";password=" + session.Settings.Password + ";connect-timeout=" + - connectionTimeout + ";ssl-mode=required"; - Stopwatch sw = new Stopwatch(); - sw.Start(); - Assert.Throws(() => MySQLX.GetSession(connString)); - sw.Stop(); - Assert.True(sw.Elapsed.Seconds > 0 && sw.Elapsed.Seconds < 21); - - connStr = "mysqlx://" + session.Settings.UserID + ":" + session.Settings.Password + "@[" + strList + "]" + "/?connect-timeout=" + connectionTimeout; - sw = new Stopwatch(); - sw.Start(); - Assert.Throws(() => MySQLX.GetSession(connString)); - sw.Stop(); - Assert.True(sw.Elapsed.Seconds > 0 && sw.Elapsed.Seconds < 21); - - var connObj1 = new - { - server = strList, - port = XPort, - user = session.Settings.UserID, - password = session.Settings.Password, - connecttimeout = connectionTimeout - }; - sw = new Stopwatch(); - sw.Start(); - Assert.Throws(() => MySQLX.GetSession(connString)); - sw.Stop(); - Assert.True(sw.Elapsed.Seconds > 0 && sw.Elapsed.Seconds < 21); - } - - [Test, Description("(connectionString,connectionUri,Anonymous Object.Test that the timeout will be reset for each connection attempt in a failover scenario")] - public void ConnectTimeoutWithFailoverAndNotValidHost() - { - string hostList = "(address=143.24.20.36,priority=0),(address=143.24.70.98,priority=1)"; - int connectionTimeout = 2000; - // URL - var connString = "server=" + hostList + ";port=" + XPort + ";uid=" + - session.Settings.UserID + ";password=" + session.Settings.Password + ";connect-timeout=" + - connectionTimeout; - Stopwatch sw = new Stopwatch(); - sw.Start(); - Assert.Throws(() => MySQLX.GetSession(connString)); - sw.Stop(); - Assert.True(sw.Elapsed.Seconds > 0 && sw.Elapsed.Seconds < 10); - // URI - var connStr = "mysqlx://" + session.Settings.UserID + ":" + session.Settings.Password + "@[" + hostList + "]" + "/?connect-timeout=" + connectionTimeout; - sw = new Stopwatch(); - sw.Start(); - Assert.Throws(() => MySQLX.GetSession(connString)); - sw.Stop(); - Assert.True(sw.Elapsed.Seconds > 0 && sw.Elapsed.Seconds < 10); - - // Object - var connObj = new - { - server = hostList, - port = XPort, - user = session.Settings.UserID, - password = session.Settings.Password, - connecttimeout = connectionTimeout - }; - sw = new Stopwatch(); - sw.Start(); - Assert.Throws(() => MySQLX.GetSession(connString)); - sw.Stop(); - Assert.True(sw.Elapsed.Seconds > 0 && sw.Elapsed.Seconds < 10); - } - - [Test, Description("Confirm that the timeout is only applied to the connection process, not to any subsequent operation after the connection is established")] - public void ValidateConnectTimeoutScope() - { - if (!Platform.IsWindows()) return; - string connStr = null; - connStr = "server=" + session.Settings.Server + ";user=" + session.Settings.UserID + ";port=" + XPort + ";password=" - + session.Settings.Password + ";" + "connect-timeout=10000;"; - using (var conn = MySQLX.GetSession(connStr)) - { - conn.SQL("SELECT SLEEP(10)").Execute(); - var res = conn.SQL("select @@port").Execute().FirstOrDefault(); - Assert.IsNotNull(res); - } - - connStr = "mysqlx://" + session.Settings.UserID + ":" + session.Settings.Password + "@" + session.Settings.Server + ":" + XPort + "?connect-timeout=10000;"; - using (var conn = MySQLX.GetSession(connStr)) - { - conn.SQL("SELECT SLEEP(10)").Execute(); - var res = conn.SQL("select @@port").Execute().FirstOrDefault(); - Assert.IsNotNull(res); - } - - var connObj = new - { - server = session.Settings.Server, - port = XPort, - user = session.Settings.UserID, - password = session.Settings.Password, - connecttimeout = 10000 - }; - using (var conn = MySQLX.GetSession(connObj)) - { - conn.SQL("SELECT SLEEP(10)").Execute(); - var res = conn.SQL("select @@port").Execute().FirstOrDefault(); - Assert.IsNotNull(res); - } - - var connStrBuilder = new MySqlXConnectionStringBuilder(); - connStrBuilder.ConnectTimeout = 10000; - connStrBuilder.UserID = session.Settings.UserID; - connStrBuilder.Password = session.Settings.Password; - connStrBuilder.Port = Convert.ToUInt32(XPort); - connStrBuilder.Server = session.Settings.Server; - using (var conn = MySQLX.GetSession(connStrBuilder.ConnectionString)) - { - conn.SQL("SELECT SLEEP(10)").Execute(); - var res = conn.SQL("select @@port").Execute().FirstOrDefault(); - Assert.IsNotNull(res); - } - - connStr = "server=" + session.Settings.Server + ";user=" + session.Settings.UserID + ";port=" + XPort + ";password=" - + session.Settings.Password + ";" + "connect-timeout=10000;"; - connStrBuilder = new MySqlXConnectionStringBuilder(connStr); - using (var conn = MySQLX.GetSession(connStrBuilder.ConnectionString)) - { - conn.SQL("SELECT SLEEP(10)").Execute(); - var res = conn.SQL("select @@port").Execute().FirstOrDefault(); - Assert.IsNotNull(res); - } - - connStr = ConnectionString + ";protocol=Socket;" + - "database=" + schemaName + ";characterset=utf8mb4;sslmode=Required;ssl-ca=" - + sslCa + $";certificatepassword={sslCertificatePassword};certificatestorelocation=LocalMachine;" - + ";keepalive =10;auth=PLAIN;certificatethumbprint=;" - + "connect-timeout=" + 10000; - var mysqlx0 = new MySqlXConnectionStringBuilder(connStr); - using (var conn = MySQLX.GetSession(mysqlx0.ConnectionString)) - { - conn.SQL("SELECT SLEEP(10)").Execute(); - var res = conn.SQL("select @@port").Execute().FirstOrDefault(); - Assert.IsNotNull(res); - } - - mysqlx0 = new MySqlXConnectionStringBuilder(); - mysqlx0.UserID = session.Settings.UserID; - mysqlx0.Password = session.Settings.Password; - mysqlx0.Port = Convert.ToUInt32(XPort); - mysqlx0.Server = session.Settings.Server; - mysqlx0.ConnectionProtocol = MySqlConnectionProtocol.Tcp; - mysqlx0.Database = schemaName; - mysqlx0.CharacterSet = "utf8mb4"; - mysqlx0.SslMode = MySqlSslMode.Required; - mysqlx0.SslCa = sslCa; - mysqlx0.CertificatePassword = sslCertificatePassword; - mysqlx0.CertificateStoreLocation = MySqlCertificateStoreLocation.LocalMachine; - mysqlx0.Keepalive = 10; - mysqlx0.Auth = MySqlAuthenticationMode.PLAIN; - mysqlx0.CertificateThumbprint = ""; - mysqlx0.ConnectTimeout = (uint)10000; - - using (var conn = MySQLX.GetSession(mysqlx0.ConnectionString)) - { - conn.SQL("SELECT SLEEP(10)").Execute(); - var res = conn.SQL("select @@port").Execute().FirstOrDefault(); - Assert.IsNotNull(res); - } - } - - [Test, Description("Test that if an unexpected error occurs during the specified time frame, the execution should stop and the error must be reported to the user")] - public void WrongPasswordException() - { - string connStr = null; - string password = "wrongpassword"; - Object[] ConnectTimeout = new Object[] { 10000 }; - for (int i = 0; i < ConnectTimeout.Length; i++) - { - // Connection String - connStr = "server=" + session.Settings.Server + ";user=" + session.Settings.UserID + ";port=" + XPort + ";password=" - + password + ";" + "connect-timeout=" + ConnectTimeout[i]; - Assert.Throws(() => MySQLX.GetSession(connStr)); - //String Builder - var connStrBuilder = new MySqlXConnectionStringBuilder(connStr); - Assert.Throws(() => MySQLX.GetSession(connStrBuilder.ConnectionString)); - // Uri - connStr = "mysqlx://" + session.Settings.UserID + ":" + password + "@" + session.Settings.Server + ":" + XPort + "?connect-timeout=" + ConnectTimeout[i]; - Assert.Throws(() => MySQLX.GetSession(connStr)); - // Anonymous Object - var connObj = new { server = session.Settings.Server, port = XPort, user = session.Settings.UserID, password = password, connecttimeout = ConnectTimeout[i] }; - Assert.Throws(() => MySQLX.GetSession(connStr)); - } - } - - [Test, Description("Test the default connect timeout with offline server with concurrent connections")] - [Ignore("Test its not well implemented")] // TO DO - public async Task ConnectTimeoutConcurrentConnections() - { - await Task.Run(() => SubThread1()); - await Task.Run(() => SubThread2()); - } - - private void SubThread1() - { - string serverName = "vigdis07.no.oracle.com"; - for (int i = 0; i < 5; i++) - { - string connStr = "server=" + serverName + ";user=" + session.Settings.UserID + ";port=" + XPort + ";password=" - + session.Settings.Password + ";" + "connect-timeout=2000;"; - TestConnectStringTimeoutFailureTimeout(connStr, 0, 5, "Timeout value between 1 and 3 second"); - } - } - - private void SubThread2() - { - string serverName = "vigdis07.no.oracle.com"; - for (int i = 0; i < 5; i++) - { - string connStr = "server=" + serverName + ";user=" + session.Settings.UserID + ";port=" + XPort + ";password=" - + session.Settings.Password + ";" + "connect-timeout=2000;"; - TestConnectStringTimeoutFailureTimeout(connStr, 0, 5, "Timeout value between 1 and 3 second"); - } - } - - - [Test, Description("CONNECT-TIMEOUT WORKS WITH BLANK VALUES FOR CONNECTION STRING AND URI")] - public void ConnectTimeoutBlankValues() - { - var connObj = new { server = session.Settings.Server, port = XPort, user = session.Settings.UserID, password = session.Settings.Password, connecttimeout = "" }; - Assert.Throws(() => MySQLX.GetSession(connObj)); - - connObj = new { server = session.Settings.Server, port = XPort, user = session.Settings.UserID, password = session.Settings.Password, connecttimeout = " " }; - Assert.Throws(() => MySQLX.GetSession(connObj)); - - var connStr = $"server={session.Settings.Server};user={session.Settings.UserID};port={XPort};password={session.Settings.Password};connect-timeout=''"; - Assert.Throws(() => MySQLX.GetSession(connStr)); - - connStr = $"server={session.Settings.Server};user={session.Settings.UserID};port={XPort};password={session.Settings.Password};connect-timeout=' '"; - Assert.Throws(() => MySQLX.GetSession(connStr)); - - connStr = $"server={session.Settings.Server};user={session.Settings.UserID};port={XPort};password={session.Settings.Password};connect-timeout="; - Assert.Throws(() => MySQLX.GetSession(connStr)); - - connStr = $"server={session.Settings.Server};user={session.Settings.UserID};port={XPort};password={session.Settings.Password};connect-timeout= "; - Assert.Throws(() => MySQLX.GetSession(connStr)); - - connStr = $"mysqlx://{session.Settings.UserID}:{session.Settings.Password}@{session.Settings.Server}:{XPort}?connect-timeout="; - Assert.Throws(() => MySQLX.GetSession(connStr)); - - connStr = $"mysqlx://{session.Settings.UserID}:{session.Settings.Password}@{session.Settings.Server}:{XPort}?connect-timeout= "; - Assert.Throws(() => MySQLX.GetSession(connStr)); - } - - /// - /// Bug28624010 - /// - [Test, Description("CONNECTIONTIMEOUT OPT WORKS WITH XPLUGN IF A CLASSIC CONN IS ESTABLISD")] - public void TimeoutWithClassicConnection() - { - int connectionTimeout = 10; - var connStr1 = $"server={session.Settings.Server};user={session.Settings.UserID};port={Port};password={session.Settings.Password};sslmode={MySqlSslMode.Required}"; - var conn = new MySqlConnection(connStr1); - conn.Open(); - conn.Close(); - var connStr = $"server={session.Settings.Server};user={session.Settings.UserID};port={XPort};password={session.Settings.Password};connectiontimeout={connectionTimeout}"; - Assert.Throws(() => MySQLX.GetSession(connStr)); - - connStr = $"mysqlx://{session.Settings.UserID}:{session.Settings.Password}@{session.Settings.Server}:{XPort}?connectiontimeout={connectionTimeout} "; - Assert.Throws(() => MySQLX.GetSession(connStr)); - - var connObj = new { server = session.Settings.Server, port = XPort, user = session.Settings.UserID, password = session.Settings.Password, connectiontimeout = connectionTimeout }; - Assert.Throws(() => MySQLX.GetSession(connObj)); - } - - [Test, Description("MySQLX Session Stress test")] - public void SessionStressTest() - { - for (int i = 0; i < 1000; i++) - { - using (Session session1 = MySQLX.GetSession(ConnectionString)) - { - Assert.AreEqual(SessionState.Open, session1.InternalSession.SessionState); - session1.Close(); - } - } - } - - [Test, Description("Getsession using Anonymous Type-Positive")] - public void GetSessionAnonymousTypePositiveStress() - { - for (int i = 0; i < 200; i++) - { - var connectionStringObject = new { connection = $"server={Host};user={session.Settings.UserID};port={XPort};password={session.Settings.Password};sslmode={MySqlSslMode.Required};" }; - using (Session sessionPlain = MySQLX.GetSession(connectionStringObject.connection)) - { - var db = sessionPlain.GetSchema(schemaName); - var col = CreateCollection("my_collection_123456789"); - sessionPlain.Close(); - } - } - } - - [Test, Description("Test Audit Plugin")] - public void SessionAuditPluginTest() - { - using (var mysqlx = MySQLX.GetSession(ConnectionString)) - { - Assert.AreEqual(SessionState.Open, mysqlx.InternalSession.SessionState); - mysqlx.Close(); - } - using (var mysql = new MySqlConnection($"server={Host};user={session.Settings.UserID};port={Port};password={session.Settings.Password}")) - { - mysql.Open(); - Assert.AreEqual(ConnectionState.Open, mysql.connectionState); - mysql.Close(); - } - Assert.Throws(() => MySQLX.GetSession($"server={Host};user={session.Settings.UserID};port={XPort};password=wrong")); - } - - [Test, Description("Classic Client with xprotocol server")] - public void ClassicClientXProtocol() - { - if (!Platform.IsWindows()) Assert.Ignore("This test is for Windows OS only"); - if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher"); - - string connectionString = $"server={Host};user={session.Settings.UserID};port={XPort};password={session.Settings.Password}"; - using (var session1 = new MySqlConnection(connectionString)) - { - Exception ex = Assert.Throws(() => session1.Open()); - Assert.AreEqual("Unsupported protocol version.", ex.Message); - } - } - - #region Methods - - public void TestConnectObjectTimeoutSuccessTimeout(object connString, int minTime, int maxTime, string test) - { - Stopwatch sw = new Stopwatch(); - sw.Start(); - var conn = MySQLX.GetSession(connString); - sw.Stop(); - Assert.True(sw.Elapsed.Seconds >= minTime && sw.Elapsed.Seconds <= maxTime, String.Format("Timeout exceeded ({0}). Actual time: {1}", test, sw.Elapsed)); - } - - public void TestConnectStringTimeoutSuccessTimeout(String connString, int minTime, int maxTime, string test) - { - Stopwatch sw = new Stopwatch(); - sw.Start(); - var conn = MySQLX.GetSession(connString); - sw.Stop(); - Assert.True(sw.Elapsed.Seconds >= minTime && sw.Elapsed.Seconds <= maxTime, String.Format("Timeout exceeded ({0}). Actual time: {1}", test, sw.Elapsed)); - } - - public void TestConnectObjTimeoutFailureTimeout(object connString, int minTime, int maxTime, string test) - { - Stopwatch sw = new Stopwatch(); - sw.Start(); - Assert.Catch(() => MySQLX.GetSession(connString)); - sw.Stop(); - Assert.True(sw.Elapsed.Seconds >= minTime && sw.Elapsed.Seconds < maxTime, String.Format("Timeout exceeded ({0}). Actual time: {1}", test, sw.Elapsed)); - } - - public void TestConnectStringTimeoutFailureTimeout(String connString, int minTime, int maxTime, string test) - { - Stopwatch sw = new Stopwatch(); - sw.Start(); - Assert.Catch(() => MySQLX.GetSession(connString)); - sw.Stop(); - Assert.True(sw.Elapsed.Seconds >= minTime && sw.Elapsed.Seconds < maxTime, String.Format("Timeout exceeded ({0}). Actual time: {1}", test, sw.Elapsed)); - } - - public void TestClientQueueTimeout(Client client, int minTime, int maxTime, string test) - { - Stopwatch sw = new Stopwatch(); - sw.Start(); - Assert.Throws(() => client.GetSession()); - sw.Stop(); - Assert.True(sw.Elapsed.Seconds >= minTime && sw.Elapsed.Seconds < maxTime, - String.Format("Timeout exceeded ({0}). Actual time: {1}", test, sw.Elapsed)); - } - - public void TestClientSuccessTimeout(int minTime, int maxTime, string test, string connectionString, object poolingObject) - { - using (var client = MySQLX.GetClient(connectionString, poolingObject)) - { - Stopwatch sw = new Stopwatch(); - sw.Start(); - client.GetSession(); - sw.Stop(); - Assert.True(sw.Elapsed.Seconds >= minTime && sw.Elapsed.Seconds < maxTime, String.Format("Timeout exceeded ({0}). Actual time: {1}", test, sw.Elapsed)); - } - } - - public void TestClientSuccessTimeout(int minTime, int maxTime, string test, object connectionObject, object poolingObject) - { - using (var client = MySQLX.GetClient(connectionObject, poolingObject)) - { - Stopwatch sw = new Stopwatch(); - sw.Start(); - client.GetSession(); - sw.Stop(); - Assert.True(sw.Elapsed.Seconds >= minTime && sw.Elapsed.Seconds < maxTime, String.Format("Timeout exceeded ({0}). Actual time: {1}", test, sw.Elapsed)); - } - } - public void TestFailureTimeout(Client client, int minTime, int maxTime, string test) - { - DateTime start = DateTime.Now; - Assert.Catch(() => client.GetSession()); - TimeSpan diff = DateTime.Now.Subtract(start); - Assert.True(diff.TotalSeconds >= minTime && diff.TotalSeconds < maxTime, String.Format("Timeout exceeded ({0}). Actual time: {1}", test, diff)); - } - - private void MeasureConnectionString(string connStr, int maxTime, string test, int iteration) - { - Stopwatch sw = new Stopwatch(); - sw.Start(); - - for (int i = 0; i < iteration; i++) - { - using Session conn = MySQLX.GetSession(connStr); - } - - sw.Stop(); - Assert.True(sw.Elapsed.Seconds < maxTime, String.Format("Timeout exceeded ({0}). Actual time: {1}", test, sw.Elapsed)); - } - - private void MeasureConnectionObject(object connStr, int maxTime, string test, int iteration) - { - Stopwatch sw = new Stopwatch(); - sw.Start(); - - for (int i = 0; i < iteration; i++) - { - using Session conn = MySQLX.GetSession(connStr); - } - - sw.Stop(); - Assert.True(sw.Elapsed.Seconds < maxTime, String.Format("Timeout exceeded ({0}). Actual time: {1}", test, sw.Elapsed)); - } - - public long NanoTime() - { - long nano = 10000L * Stopwatch.GetTimestamp(); - nano /= TimeSpan.TicksPerMillisecond; - nano *= 100L; - return nano; - } - - public long DoConnectString(string connectionString) - { - long queryStartTime, queryRunTime = 0; - queryStartTime = NanoTime(); - var session = MySQLX.GetSession(connectionString); - queryRunTime = NanoTime() - queryStartTime; - session.Close(); - session.Dispose(); - return queryRunTime; - } - - public long DoConnectObject(object connectionString) - { - long queryStartTime, queryRunTime = 0; - queryStartTime = NanoTime(); - var session = MySQLX.GetSession(connectionString); - queryRunTime = NanoTime() - queryStartTime; - session.Close(); - session.Dispose(); - return queryRunTime; - } - - /// - /// Calculate the Connection per second - /// Total execution time.(Connection+query execution time) - /// Query execution time - public float CalculateTPS(long elapsedTime, long transactions) - { - float tps = 0; - if (elapsedTime > 0.0) - { - tps = (float)transactions / elapsedTime; - tps = tps * 1000; - } - return tps; - } - - #endregion Methods - - } -} +// Copyright © 2015, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySql.Data; +using MySql.Data.Common; +using MySql.Data.MySqlClient; +using MySqlX.XDevAPI; +using MySqlX.XDevAPI.Relational; +using NUnit.Framework; +using System; +using System.Collections.Generic; +using System.Data; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace MySqlX.Data.Tests +{ + public class SessionTests : BaseTest + { + [Test] + [Property("Category", "Security")] + public void CanCloseSession() + { + Session s = MySQLX.GetSession(ConnectionString); + Assert.True(s.InternalSession.SessionState == SessionState.Open); + s.Close(); + Assert.AreEqual(s.InternalSession.SessionState, SessionState.Closed); + } + + [Test] + [Property("Category", "Security")] + public void NoPassword() + { + Session session = MySQLX.GetSession(ConnectionStringNoPassword); + Assert.True(session.InternalSession.SessionState == SessionState.Open); + session.Close(); + Assert.AreEqual(session.InternalSession.SessionState, SessionState.Closed); + } + + [Test] + [Property("Category", "Security")] + public void SessionClose() + { + Session session = MySQLX.GetSession(ConnectionString); + Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); + session.Close(); + Assert.AreEqual(SessionState.Closed, session.InternalSession.SessionState); + } + + [Test] + [Property("Category", "Security")] + [Ignore("Check this. Result is not always the same")] + public void CountClosedSession() + { + int sessions, newSessions; + + using (Session nodeSession = MySQLX.GetSession(ConnectionString)) + { + sessions = ExecuteSQLStatement(nodeSession.SQL("show processlist")).FetchAll().Count; + + for (int i = 0; i < 20; i++) + { + Session session = MySQLX.GetSession(ConnectionString); + Assert.True(session.InternalSession.SessionState == SessionState.Open); + session.Close(); + Assert.AreEqual(session.InternalSession.SessionState, SessionState.Closed); + } + + newSessions = ExecuteSQLStatement(nodeSession.SQL("show processlist")).FetchAll().Count; + } + + Assert.AreEqual(sessions, newSessions); + } + + [Test] + [Property("Category", "Security")] + public void ConnectionStringAsAnonymousType() + { + var connstring = new + { + server = session.Settings.Server, + port = session.Settings.Port, + user = session.Settings.UserID, + password = session.Settings.Password + }; + + using (var testSession = MySQLX.GetSession(connstring)) + { + Assert.AreEqual(SessionState.Open, testSession.InternalSession.SessionState); + } + } + + [Test] + [Property("Category", "Security")] + public void SessionGetSetCurrentSchema() + { + using (Session testSession = MySQLX.GetSession(ConnectionString)) + { + Assert.AreEqual(SessionState.Open, testSession.InternalSession.SessionState); + Assert.Null(testSession.GetCurrentSchema()); + Assert.Throws(() => testSession.SetCurrentSchema("")); + testSession.SetCurrentSchema(schemaName); + Assert.AreEqual(schemaName, testSession.Schema.Name); + Assert.AreEqual(schemaName, testSession.GetCurrentSchema().Name); + } + } + + [Test] + [Property("Category", "Security")] + public void SessionUsingSchema() + { + using (Session mySession = MySQLX.GetSession(ConnectionString + $";database={schemaName};")) + { + Assert.AreEqual(SessionState.Open, mySession.InternalSession.SessionState); + Assert.AreEqual(schemaName, mySession.Schema.Name); + Assert.AreEqual(schemaName, mySession.GetCurrentSchema().Name); + Assert.True(SchemaExistsInDatabase(mySession.Schema)); + } + } + + [Test] + [Property("Category", "Security")] + public void SessionUsingDefaultSchema() + { + using (Session mySession = MySQLX.GetSession(ConnectionString + $";database={schemaName};")) + { + Assert.AreEqual(SessionState.Open, mySession.InternalSession.SessionState); + Assert.AreEqual(schemaName, mySession.DefaultSchema.Name); + Assert.AreEqual(schemaName, mySession.GetCurrentSchema().Name); + Assert.True(mySession.Schema.ExistsInDatabase()); + mySession.SetCurrentSchema("mysql"); + Assert.AreNotEqual(mySession.DefaultSchema.Name, mySession.Schema.Name); + } + + // DefaultSchema is null because no database was provided in the connection string/URI. + using (Session mySession = MySQLX.GetSession(ConnectionString)) + { + Assert.AreEqual(SessionState.Open, mySession.InternalSession.SessionState); + Assert.Null(mySession.DefaultSchema); + } + } + + [Test] + [Property("Category", "Security")] + public void SessionUsingDefaultSchemaWithAnonymousObject() + { + var globalSession = GetSession(); + + using (var internalSession = MySQLX.GetSession(new + { + server = globalSession.Settings.Server, + port = globalSession.Settings.Port, + user = globalSession.Settings.UserID, + password = globalSession.Settings.Password, + sslmode = MySqlSslMode.Required, + database = "mysql" + })) + { + Assert.AreEqual("mysql", internalSession.DefaultSchema.Name); + } + + // DefaultSchema is null when no database is provided. + using (var internalSession = MySQLX.GetSession(new + { + server = globalSession.Settings.Server, + port = globalSession.Settings.Port, + user = globalSession.Settings.UserID, + password = globalSession.Settings.Password, + sslmode = MySqlSslMode.Required, + })) + { + Assert.Null(internalSession.DefaultSchema); + } + + // Access denied error is raised when database does not exist for servers 8.0.12 and below. + // This behavior was fixed since MySql Server 8.0.13 version. Now the error + // shows the proper message, "Unknown database..." + if (session.InternalSession.GetServerVersion().isAtLeast(8, 0, 13)) return; + var exception = Assert.Throws(() => MySQLX.GetSession(new + { + server = globalSession.Settings.Server, + port = globalSession.Settings.Port, + user = globalSession.Settings.UserID, + password = globalSession.Settings.Password, + sslmode = MySqlSslMode.Required, + database = "test1" + } + )); + + if (session.InternalSession.GetServerVersion().isAtLeast(8, 0, 13)) + StringAssert.StartsWith(string.Format("Unknown database 'test1'"), exception.Message); + else + StringAssert.StartsWith(string.Format("Access denied"), exception.Message); + } + + [Test] + [Property("Category", "Security")] + public void SessionUsingDefaultSchemaWithConnectionURI() + { + using (var session = MySQLX.GetSession(ConnectionStringUri + "?database=mysql")) + { + Assert.AreEqual("mysql", session.DefaultSchema.Name); + } + } + + [Test] + [Property("Category", "Security")] + public void CheckConnectionUri() + { + CheckConnectionData($"mysqlx://myuser:password@{Host}:{XPort}", "myuser", "password", Host, uint.Parse(XPort)); + CheckConnectionData($"mysqlx://my%3Auser:p%40ssword@{Host}:{XPort}", "my:user", "p@ssword", Host, uint.Parse(XPort)); + CheckConnectionData($"mysqlx://my%20user:p%40ss%20word@{Host}:{XPort}", "my user", "p@ss word", Host, uint.Parse(XPort)); + CheckConnectionData($"mysqlx:// myuser : p%40ssword@{Host}:{XPort}", "myuser", "p@ssword", Host, uint.Parse(XPort)); + CheckConnectionData($"mysqlx://myuser@{Host}:{XPort}", "myuser", "", Host, uint.Parse(XPort)); + CheckConnectionData($"mysqlx://myuser:p%40ssword@{Host}", "myuser", "p@ssword", Host, uint.Parse(XPort)); + CheckConnectionData($"mysqlx://myuser:p%40ssw%40rd@{Host}", "myuser", "p@ssw@rd", Host, uint.Parse(XPort)); + CheckConnectionData($"mysqlx://my%40user:p%40ssword@{Host}", "my@user", "p@ssword", Host, uint.Parse(XPort)); + CheckConnectionData($"mysqlx://myuser@{Host}", "myuser", "", Host, uint.Parse(XPort)); + CheckConnectionData($"mysqlx://myuser@{Host}", "myuser", "", Host, uint.Parse(XPort)); + CheckConnectionData("mysqlx://myuser@[::1]", "myuser", "", "[::1]", uint.Parse(XPort)); + CheckConnectionData("mysqlx://myuser:password@[2606:b400:440:1040:bd41:e449:45ee:2e1a]", "myuser", "password", "[2606:b400:440:1040:bd41:e449:45ee:2e1a]", uint.Parse(XPort)); + CheckConnectionData($"mysqlx://myuser:password@[2606:b400:440:1040:bd41:e449:45ee:2e1a]:{XPort}", "myuser", "password", "[2606:b400:440:1040:bd41:e449:45ee:2e1a]", uint.Parse(XPort)); + Assert.Throws(() => CheckConnectionData("mysqlx://myuser:password@[2606:b400:440:1040:bd41:e449:45ee:2e1a:33060]", "myuser", "password", "[2606:b400:440:1040:bd41:e449:45ee:2e1a]", uint.Parse(XPort))); + Assert.Throws(() => CheckConnectionData($"mysqlx://myuser:password@2606:b400:440:1040:bd41:e449:45ee:2e1a:{XPort}", "myuser", "password", "[2606:b400:440:1040:bd41:e449:45ee:2e1a]", uint.Parse(XPort))); + CheckConnectionData("mysqlx://myuser:password@[fe80::bd41:e449:45ee:2e1a%17]", "myuser", "password", "[fe80::bd41:e449:45ee:2e1a]", uint.Parse(XPort)); + CheckConnectionData("mysqlx://myuser:password@[(address=[fe80::bd41:e449:45ee:2e1a%17],priority=100)]", "myuser", "password", "[fe80::bd41:e449:45ee:2e1a]", uint.Parse(XPort)); + CheckConnectionData("mysqlx://myuser:password@[(address=[fe80::bd41:e449:45ee:2e1a%17]:3305,priority=100)]", "myuser", "password", "[fe80::bd41:e449:45ee:2e1a]", 3305); + Assert.Throws(() => CheckConnectionData("mysqlx://myuser:password@[(address=fe80::bd41:e449:45ee:2e1a%17,priority=100)]", "myuser", "password", "[fe80::bd41:e449:45ee:2e1a]", 33060)); + CheckConnectionData("mysqlx://myuser@localhost/test", "myuser", "", "localhost", 33060, "database", schemaName); +#if NET7_0 + CheckConnectionData("mysqlx://myuser@localhost/test?ssl%20mode=disabled&connecttimeout=10", "myuser", "", "localhost", 33060, "database", schemaName, "ssl mode", "None", "connecttimeout", "10"); +#else + CheckConnectionData("mysqlx://myuser@localhost/test?ssl%20mode=disabled&connecttimeout=10", "myuser", "", "localhost", 33060, "database", schemaName, "ssl mode", "Disabled", "connecttimeout", "10"); +#endif + CheckConnectionData("mysqlx://_%21%22%23%24s%26%2F%3D-%25r@localhost", "_!\"#$s&/=-%r", "", "localhost", 33060); + CheckConnectionData("mysql://myuser@localhost", "", "", "", 33060); + CheckConnectionData("myuser@localhost", "", "", "", 33060); + Assert.Throws(() => CheckConnectionData("mysqlx://uid=myuser;server=localhost", "", "", "", 33060)); + CheckConnectionData("mysqlx://user:password@server.example.com/", "user", "password", "server.example.com", 33060, "ssl mode", "Required"); + CheckConnectionData("mysqlx://user:password@server.example.com/?ssl-ca=(c:%5Cclient.pfx)", "user", "password", "server.example.com", 33060, "ssl mode", "Required", "ssl-ca", "c:\\client.pfx"); + Assert.Throws(() => CheckConnectionData("mysqlx://user:password@server.example.com/?ssl-crl=(c:%5Ccrl.pfx)", "user", "password", "server.example.com", 33060, "ssl mode", "Required", "ssl-crl", "(c:\\crl.pfx)")); + // tls-version + CheckConnectionData("mysqlx://myuser:password@localhost:33060?tls-version=TlSv1.2", "myuser", "password", "localhost", 33060, "tls-version", "Tls12"); + CheckConnectionData("mysqlx://myuser:password@localhost:33060?tls-version=TlS1.2", "myuser", "password", "localhost", 33060, "tls-version", "Tls12"); + CheckConnectionData("mysqlx://myuser:password@localhost:33060?tls-version=TlSv12", "myuser", "password", "localhost", 33060, "tls-version", "Tls12"); + CheckConnectionData("mysqlx://myuser:password@localhost:33060?tls-version=TlS12", "myuser", "password", "localhost", 33060, "tls-version", "Tls12"); + CheckConnectionData("mysqlx://myuser:password@localhost:33060?tls-version=[ TlSv1.2 ,tLsV11, TLSv1.0 , tls13 ]", "myuser", "password", "localhost", 33060, "tls-version", "Tls12, Tls13"); + CheckConnectionData("mysqlx://myuser:password@localhost:33060?tls-version=( TlSv1.2 ,tLsV11, TLSv1 , tls13 )", "myuser", "password", "localhost", 33060, "tls-version", "Tls12, Tls13"); + CheckConnectionData("mysqlx://myuser:password@localhost:33060?tls-version= TlSv1.2 ,tLsV11, TLSv10 , tls13", "myuser", "password", "localhost", 33060, "tls-version", "Tls12, Tls13"); + Assert.Throws(() => CheckConnectionData("mysqlx://myuser:password@localhost:33060?tls-version=SSL3", "myuser", "password", "localhost", 33060, "tls-version", "")); + } + + [Test] + [Property("Category", "Security")] + public void ConnectionUsingUri() + { + using (var session = MySQLX.GetSession(ConnectionStringUri)) + { + Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); + } + } + + [Test] + [Property("Category", "Security")] + public void ConnectionStringNull() + { + Assert.Throws(() => MySQLX.GetSession(null)); + } + + [Test] + [Property("Category", "Security")] + public void IPv6() + { + var csBuilder = new MySqlXConnectionStringBuilder(ConnectionString); + csBuilder.Server = GetMySqlServerIp(true); + csBuilder.Port = uint.Parse(XPort); + + if (string.IsNullOrEmpty(csBuilder.Server)) Assert.Ignore("No IPv6 available."); + + using (var session = MySQLX.GetSession(csBuilder.ToString())) + { + Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); + } + } + + [Test] + [Property("Category", "Security")] + public void IPv6AsUrl() + { + var csBuilder = new MySqlXConnectionStringBuilder(ConnectionString); + string ipv6 = GetMySqlServerIp(true); + if (string.IsNullOrEmpty(ipv6)) Assert.Ignore("No IPv6 available."); + + string connString = $"mysqlx://{csBuilder.UserID}:{csBuilder.Password}@[{ipv6}]:{XPort}"; + using (Session session = MySQLX.GetSession(connString)) + { + Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); + } + } + + [Test] + [Property("Category", "Security")] + public void IPv6AsAnonymous() + { + var csBuilder = new MySqlXConnectionStringBuilder(ConnectionString); + string ipv6 = GetMySqlServerIp(true); + if (string.IsNullOrEmpty(ipv6)) Assert.Ignore("No IPv6 available."); + + using (Session session = MySQLX.GetSession(new { server = ipv6, user = csBuilder.UserID, password = csBuilder.Password, port = XPort })) + { + Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); + } + } + + [Test] + [Property("Category", "Security")] + public void CreateSessionWithUnsupportedOptions() + { + var errorMessage = "Option not supported."; + var connectionUri = string.Format("{0}?", ConnectionStringUri); + + // Use a connection URI. + var ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "pipe=MYSQL")); + StringAssert.StartsWith(errorMessage, ex.Message); + ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "compress=true")); + StringAssert.StartsWith(errorMessage, ex.Message); + ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "allow batch=false")); + StringAssert.StartsWith(errorMessage, ex.Message); + ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "logging=true")); + StringAssert.StartsWith(errorMessage, ex.Message); + ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "sharedmemoryname=MYSQL")); + StringAssert.StartsWith(errorMessage, ex.Message); + ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "defaultcommandtimeout=30")); + StringAssert.StartsWith(errorMessage, ex.Message); + ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "usedefaultcommandtimeoutforef=true")); + StringAssert.StartsWith(errorMessage, ex.Message); + ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "persistsecurityinfo=false")); + StringAssert.StartsWith(errorMessage, ex.Message); + ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "encrypt=false")); + StringAssert.StartsWith(errorMessage, ex.Message); + ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "integratedsecurity=true")); + StringAssert.StartsWith(errorMessage, ex.Message); + ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "allowpublickeyretrieval=false")); + StringAssert.StartsWith(errorMessage, ex.Message); + ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "autoenlist=true")); + StringAssert.StartsWith(errorMessage, ex.Message); + ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "includesecurityasserts=false")); + StringAssert.StartsWith(errorMessage, ex.Message); + ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "allowzerodatetime=true")); + StringAssert.StartsWith(errorMessage, ex.Message); + ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "convert zero datetime=false")); + StringAssert.StartsWith(errorMessage, ex.Message); + ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "useusageadvisor=true")); + StringAssert.StartsWith(errorMessage, ex.Message); + ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "procedurecachesize=50")); + StringAssert.StartsWith(errorMessage, ex.Message); + ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "useperformancemonitor=true")); + StringAssert.StartsWith(errorMessage, ex.Message); + ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "respectbinaryflags=true")); + StringAssert.StartsWith(errorMessage, ex.Message); + ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "treat tiny as boolean=false")); + StringAssert.StartsWith(errorMessage, ex.Message); + ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "allowuservariables=true")); + StringAssert.StartsWith(errorMessage, ex.Message); + ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "interactive=false")); + StringAssert.StartsWith(errorMessage, ex.Message); + ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "functionsreturnstring=true")); + StringAssert.StartsWith(errorMessage, ex.Message); + ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "useaffectedrows=false")); + StringAssert.StartsWith(errorMessage, ex.Message); + ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "oldguids=true")); + StringAssert.StartsWith(errorMessage, ex.Message); + ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "sqlservermode=false")); + StringAssert.StartsWith(errorMessage, ex.Message); + ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "tablecaching=true")); + StringAssert.StartsWith(errorMessage, ex.Message); + ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "defaulttablecacheage=60")); + StringAssert.StartsWith(errorMessage, ex.Message); + ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "checkparameters=true")); + StringAssert.StartsWith(errorMessage, ex.Message); + ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "replication=replication_group")); + StringAssert.StartsWith(errorMessage, ex.Message); + ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "exceptioninterceptors=none")); + StringAssert.StartsWith(errorMessage, ex.Message); + ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "commandinterceptors=none")); + StringAssert.StartsWith(errorMessage, ex.Message); + ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "connectionlifetime=100")); + StringAssert.StartsWith(errorMessage, ex.Message); + ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "pooling=false")); + StringAssert.StartsWith(errorMessage, ex.Message); + ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "minpoolsize=0")); + StringAssert.StartsWith(errorMessage, ex.Message); + ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "maxpoolsize=20")); + StringAssert.StartsWith(errorMessage, ex.Message); + ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "connectionreset=false")); + StringAssert.StartsWith(errorMessage, ex.Message); + ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "cacheserverproperties=true")); + StringAssert.StartsWith(errorMessage, ex.Message); + + // Use a connection string. + ex = Assert.Throws(() => MySQLX.GetSession("treatblobsasutf8=false")); + StringAssert.StartsWith(errorMessage, ex.Message); + ex = Assert.Throws(() => MySQLX.GetSession("blobasutf8includepattern=pattern")); + StringAssert.StartsWith(errorMessage, ex.Message); + ex = Assert.Throws(() => MySQLX.GetSession("blobasutf8excludepattern=pattern")); + StringAssert.StartsWith(errorMessage, ex.Message); + } + + [Test] + [Property("Category", "Security")] + public void CreateBuilderWithUnsupportedOptions() + { + var errorMessage = "Option not supported."; + var ex = Assert.Throws(() => new MySqlXConnectionStringBuilder("pipe=MYSQL")); + StringAssert.StartsWith(errorMessage, ex.Message); + ex = Assert.Throws(() => new MySqlXConnectionStringBuilder("allow batch=false")); + StringAssert.StartsWith(errorMessage, ex.Message); + ex = Assert.Throws(() => new MySqlXConnectionStringBuilder("respectbinaryflags=true")); + StringAssert.StartsWith(errorMessage, ex.Message); + ex = Assert.Throws(() => new MySqlXConnectionStringBuilder("pooling=false")); + StringAssert.StartsWith(errorMessage, ex.Message); + ex = Assert.Throws(() => new MySqlXConnectionStringBuilder("cacheserverproperties=true")); + StringAssert.StartsWith(errorMessage, ex.Message); + } + + [Test] + [Property("Category", "Security")] + public void GetUri() + { + using (var internalSession = MySQLX.GetSession(session.Uri)) + { + // Validate that all properties keep their original value. + foreach (var connectionOption in session.Settings.values) + { + // SslCrl connection option is skipped since it isn't currently supported. + if (connectionOption.Key == "sslcrl") + continue; + + try + { + Assert.AreEqual(session.Settings[connectionOption.Key], internalSession.Settings[connectionOption.Key]); + } + catch (ArgumentException ex) + { + StringAssert.StartsWith("Option not supported.", ex.Message); + } + } + } + } + + /// + /// WL #12177 Implement connect timeout + /// + [Test] + [Property("Category", "Security")] + public void ConnectTimeout() + { + if (Platform.IsMacOSX()) Assert.Ignore("Check failure on MacOS: (() => MySQLX.GetSession(conn)); + TimeSpan diff = DateTime.Now.Subtract(start); + Assert.True(diff.TotalSeconds > 19 && diff.TotalSeconds < 21, String.Format("Timeout exceeded ({0}). Actual time: {1}", "Fail over failure", diff)); + + // Valid session no time out + start = DateTime.Now; + using (Session session = MySQLX.GetSession(ConnectionStringUri + "?connecttimeout=2000")) + session.SQL("SELECT SLEEP(10)").Execute(); + diff = DateTime.Now.Subtract(start); + Assert.True(diff.TotalSeconds > 10); + + //Invalid Values for Connection Timeout parameter + var ex = Assert.Throws(() => MySQLX.GetSession(ConnectionString + ";connect-timeout=-1;")); + Assert.AreEqual(ResourcesX.InvalidConnectionTimeoutValue, ex.Message); + + ex = Assert.Throws(() => MySQLX.GetSession(ConnectionString + ";connect-timeout=foo;")); + Assert.AreEqual(ResourcesX.InvalidConnectionTimeoutValue, ex.Message); + + ex = Assert.Throws(() => MySQLX.GetSession(ConnectionString + ";connect-timeout='';")); + Assert.AreEqual(ResourcesX.InvalidConnectionTimeoutValue, ex.Message); + + ex = Assert.Throws(() => MySQLX.GetSession(ConnectionString + ";connect-timeout=10.5;")); + Assert.AreEqual(ResourcesX.InvalidConnectionTimeoutValue, ex.Message); + + ex = Assert.Throws(() => MySQLX.GetSession(ConnectionString + ";connect-timeout=" + Int32.MaxValue + 1)); + Assert.AreEqual(ResourcesX.InvalidConnectionTimeoutValue, ex.Message); + + ex = Assert.Throws(() => MySQLX.GetSession(ConnectionString + ";connect-timeout=10.5;")); + Assert.AreEqual(ResourcesX.InvalidConnectionTimeoutValue, ex.Message); + + ex = Assert.Throws(() => MySQLX.GetSession(ConnectionString + ";connect-timeout=;")); + Assert.AreEqual(ResourcesX.InvalidConnectionTimeoutValue, ex.Message); + + ex = Assert.Throws(() => MySQLX.GetSession(ConnectionStringUri + "?connect-timeout= ")); + Assert.AreEqual(ResourcesX.InvalidConnectionTimeoutValue, ex.Message); + + ex = Assert.Throws(() => MySQLX.GetSession(ConnectionStringUri + "?connecttimeout=")); + Assert.AreEqual(ResourcesX.InvalidConnectionTimeoutValue, ex.Message); + + // Valid value for ConnectionTimeout, invalid credentials + var exception = Assert.Throws(() => MySQLX.GetSession($"server={Host};user=test;password=noPass;port={XPort};connect-timeout=2000;")); + Assert.NotNull(exception); + } + + private void TestConnectTimeoutFailureTimeout(String connString, int minTime, int maxTime, string test) + { + DateTime start = DateTime.Now; + Assert.Throws(() => MySQLX.GetSession(connString)); + TimeSpan diff = DateTime.Now.Subtract(start); + Assert.True(diff.TotalSeconds > minTime && diff.TotalSeconds < maxTime, String.Format("Timeout exceeded ({0}). Actual time: {1}", test, diff)); + } + + private void TestConnectTimeoutSuccessTimeout(String connString, int minTime, int maxTime, string test) + { + DateTime start = DateTime.Now; + MySQLX.GetSession(connString); + TimeSpan diff = DateTime.Now.Subtract(start); + Assert.True(diff.TotalSeconds > minTime && diff.TotalSeconds < maxTime, String.Format("Timeout exceeded ({0}). Actual time: {1}", test, diff)); + } + + [Test] + [Property("Category", "Security")] + public void MaxConnections() + { + try + { + List sessions = new List(); + ExecuteSqlAsRoot("SET @@global.mysqlx_max_connections = 2"); + for (int i = 0; i <= 2; i++) + { + Session newSession = MySQLX.GetSession(ConnectionString); + sessions.Add(newSession); + } + Assert.False(true, "MySqlException should be thrown"); + } + catch (MySqlException ex) + { + Assert.AreEqual(ResourcesX.UnableToOpenSession, ex.Message); + } + finally + { + ExecuteSqlAsRoot("SET @@global.mysqlx_max_connections = 100"); + } + } + + protected void CheckConnectionData(string connectionData, string user, string password, string server, uint port, params string[] parameters) + { + string result = this.session.ParseConnectionData(connectionData); + var csbuilder = new MySqlXConnectionStringBuilder(result); + Assert.True(user == csbuilder.UserID, string.Format("Expected:{0} Current:{1} in {2}", user, csbuilder.UserID, connectionData)); + Assert.True(password == csbuilder.Password, string.Format("Expected:{0} Current:{1} in {2}", password, csbuilder.Password, connectionData)); + Assert.True(server == csbuilder.Server, string.Format("Expected:{0} Current:{1} in {2}", server, csbuilder.Server, connectionData)); + Assert.True(port == csbuilder.Port, string.Format("Expected:{0} Current:{1} in {2}", port, csbuilder.Port, connectionData)); + if (parameters != null) + { + if (parameters.Length % 2 != 0) + throw new ArgumentOutOfRangeException(); + for (int i = 0; i < parameters.Length; i += 2) + { + Assert.True(csbuilder.ContainsKey(parameters[i])); + Assert.AreEqual(parameters[i + 1], csbuilder[parameters[i]].ToString()); + } + } + } + + /// + /// WL12514 - DevAPI: Support session-connect-attributes + /// + [Test] + [Property("Category", "Security")] + public void ConnectionAttributes() + { + if (!(session.Version.isAtLeast(8, 0, 16))) return; + + // Validate that MySQLX.GetSession() supports a new 'connection-attributes' query parameter + // with default values and all the client attributes starts with a '_'. + TestConnectionAttributes(ConnectionString + ";connection-attributes=true;"); + TestConnectionAttributes(ConnectionStringUri + "?connectionattributes"); + + // Validate that no attributes, client or user defined, are sent to server when the value is "false". + TestConnectionAttributes(ConnectionString + ";connection-attributes=false;"); + TestConnectionAttributes(ConnectionStringUri + "?connectionattributes=false"); + + // Validate default behavior with different scenarios. + TestConnectionAttributes(ConnectionString + ";connection-attributes;"); + TestConnectionAttributes(ConnectionStringUri + "?connectionattributes=true"); + TestConnectionAttributes(ConnectionString + ";connection-attributes=;"); + TestConnectionAttributes(ConnectionStringUri + "?connectionattributes=[]"); + + // Validate user-defined attributes to be sent to server. + Dictionary userAttrs = new Dictionary + { + { "foo", "bar" }, + { "quua", "qux" }, + { "key", null } + }; + TestConnectionAttributes(ConnectionString + ";connection-attributes=[foo=bar,quua=qux,key]", userAttrs); + TestConnectionAttributes(ConnectionStringUri + "?connectionattributes=[foo=bar,quua=qux,key=]", userAttrs); + + // Errors + var ex = Assert.Throws(() => MySQLX.GetSession(ConnectionString + ";connection-attributes=[_key=value]")); + Assert.AreEqual(ResourcesX.InvalidUserDefinedAttribute, ex.Message); + + ex = Assert.Throws(() => MySQLX.GetSession(ConnectionString + ";connection-attributes=123")); + Assert.AreEqual(ResourcesX.InvalidConnectionAttributes, ex.Message); + + ex = Assert.Throws(() => MySQLX.GetSession(ConnectionString + ";connection-attributes=[key=value,key=value2]")); + Assert.AreEqual(string.Format(ResourcesX.DuplicateUserDefinedAttribute, "key"), ex.Message); + + ex = Assert.Throws(() => MySQLX.GetSession(new { server = Host, port = XPort, user = RootUser, connectionattributes = "=" })); + + ex = Assert.Throws(() => MySQLX.GetSession(ConnectionString + ";connectionattributes=[=bar]")); + Assert.AreEqual(string.Format(ResourcesX.EmptyKeyConnectionAttribute), ex.Message); + } + + private void TestConnectionAttributes(string connString, Dictionary userAttrs = null) + { + string sql = "SELECT * FROM performance_schema.session_account_connect_attrs WHERE PROCESSLIST_ID = connection_id()"; + + using (Session session = MySQLX.GetSession(connString)) + { + Assert.AreEqual(SessionState.Open, session.XSession.SessionState); + var result = session.SQL(sql).Execute().FetchAll(); + + if (session.Settings.ConnectionAttributes == "false") + CollectionAssert.IsEmpty(result); + else + { + CollectionAssert.IsNotEmpty(result); + MySqlConnectAttrs clientAttrs = new MySqlConnectAttrs(); + + if (userAttrs == null) + { + Assert.AreEqual(8, result.Count); + + foreach (Row row in result) + StringAssert.StartsWith("_", row[1].ToString()); + } + else + { + Assert.AreEqual(11, result.Count); + + for (int i = 0; i < userAttrs.Count; i++) + { + Assert.True(userAttrs.ContainsKey(result.ElementAt(i)[1].ToString())); + Assert.True(userAttrs.ContainsValue(result.ElementAt(i)[2])); + } + } + } + } + } + + [TestCase("localhost")] + [TestCase("127.0.0.1")] + [TestCase("[::1]")] + [Description("IPv6 connection Scenario [localhost],[127.0.0.1]")] + public void ConnectionTest(string serverName) + { + if (!Platform.IsWindows()) Assert.Ignore("This test only applies foe Windows OS."); + + serverName = serverName.Replace("localhost", Host); + + MySqlXConnectionStringBuilder sb = new MySqlXConnectionStringBuilder(ConnectionString); + string connStr = "server=" + Host + ";user=" + sb.UserID + ";port=" + XPort + ";password=" + sb.Password + ";" + "sslmode=" + MySqlSslMode.Required; + + using (var sessionTest = MySQLX.GetSession(connStr)) + { + Assert.AreEqual(SessionState.Open, sessionTest.InternalSession.SessionState); + } + + using (var sessionTest = MySQLX.GetSession("mysqlx://" + sb.UserID + ":" + sb.Password + "@" + serverName + ":" + XPort)) + { + Assert.AreEqual(SessionState.Open, sessionTest.InternalSession.SessionState); + } + + using (var sessionTest = MySQLX.GetSession(new { server = serverName, port = XPort, user = sb.UserID, password = sb.Password })) + { + Assert.AreEqual(SessionState.Open, sessionTest.InternalSession.SessionState); + } + //wrong port + connStr = "server=" + sb.Server + ";user=" + sb.UserID + ";port=" + 33090 + ";password=" + sb.Password + ";" + "sslmode=" + MySqlSslMode.Required; + Assert.Throws(() => MySQLX.GetSession(connStr)); + + } + + [TestCase("[::$]")] + [TestCase("[::11]")] + [Description("IPv6 connection server * and ::$,invalid hostname")] + public void IPv6ConnectionExceptions(string serverName) + { + if (!Platform.IsWindows()) return; + + Session sessionTest = null; + string connStr = "server=" + serverName + ";user=test;port=" + XPort + ";password=test;sslmode=" + MySqlSslMode.Required; + Assert.Catch(() => sessionTest = MySQLX.GetSession(connStr)); + Assert.Catch(() => sessionTest = MySQLX.GetSession("mysqlx://test:test@" + serverName + ":" + XPort)); + Assert.Catch(() => sessionTest = MySQLX.GetSession(new { server = serverName, port = XPort, user = schemaName, password = schemaName })); + } + + [Test, Description("Unified connection string refinement-Negative Scenarios")] + public void ConnectionNegativeScenarios() + { + if (!Platform.IsWindows()) Assert.Ignore("This test is for Windows OS only"); + var ipv6HostName2 = GetIPV6Address(); + string ipAddress = GetMySqlServerIp(); + + Session session1 = null; + Assert.Catch(() => session1 = MySQLX.GetSession("mysql:x//test:test@" + ipAddress + ":" + XPort)); + Assert.Catch(() => session1 = MySQLX.GetSession("my:sqlx//test:test@" + ipAddress + ":" + XPort)); + Assert.Catch(() => session1 = MySQLX.GetSession("mysqlx:://test:test@" + ipAddress + ":" + XPort)); + string ipv6address = "f345::" + GetIPV6Address() + ":1xde"; + Assert.Catch(() => session1 = MySQLX.GetSession("mysqlx://test:test@[" + ipv6address + "]:" + XPort)); + Assert.Catch(() => session1 = MySQLX.GetSession("mysqlx://test:test@" + ipAddress + ":" + XPort + "/" + "unknowndatabase")); + string connStr = "mysqlx://test:test@" + session.Settings.Server + ":" + XPort + "/?" + "ssl-mode=VerifyFull&ssl-ca=" + sslCa + "&ssl-ca-pwd=wrongpass"; + Assert.Catch(() => session1 = MySQLX.GetSession(connStr)); + } + + [Test, Description("Session.Uri")] + public void SessionUriAndDefaultSchemaTest() + { + if (!Platform.IsWindows()) return; + + using (var session1 = MySQLX.GetSession(ConnectionString)) + { + Assert.IsNotNull(session1.Uri); + } + + MySqlXConnectionStringBuilder sb = new MySqlXConnectionStringBuilder(ConnectionString); + var connectionString = ConnectionStringUserWithSSLPEM + ";protocol=TCP;database=" + + sb.Database + ";characterset=utf8mb4;sslmode=Required;connect-timeout=10;keepalive=10;auth=PLAIN"; + using (var session1 = MySQLX.GetSession(connectionString)) + { + Assert.IsNotNull(session1.Uri); + } + + using (var session1 = MySQLX.GetSession(new + { + server = sb.Server, + port = XPort, + user = sb.UserID, + password = sb.Password, + sslmode = MySqlSslMode.Required + })) + { + Assert.IsNotNull(session1.Uri); + } + + var conn = new MySqlConnectionStringBuilder(); + conn.Server = sb.Server; + conn.UserID = sb.UserID; + conn.Password = sb.Password; + conn.Port = Convert.ToUInt32(XPort); + conn.Database = schemaName; + conn.CharacterSet = "utf8mb4"; + conn.SslMode = MySqlSslMode.VerifyCA; + conn.SslCa = sslCa; + conn.CertificatePassword = sslCertificatePassword; + conn.Keepalive = 10; + conn.ConnectionProtocol = MySqlConnectionProtocol.Tcp; + + using (var session1 = MySQLX.GetSession(conn.ConnectionString)) + { + Assert.IsNotNull(session1.Uri); + } + + using (var session1 = MySQLX.GetSession(ConnectionStringUri + "/?ssl-mode=Required;")) + { + Assert.IsNotNull(session1.Uri); + } + + conn = new MySqlConnectionStringBuilder(); + conn.Server = sb.Server; + conn.UserID = sb.UserID; + conn.Password = sb.Password; + conn.Port = Convert.ToUInt32(XPort); + conn.ConnectionProtocol = MySqlConnectionProtocol.Tcp; + conn.Database = schemaName; + conn.CharacterSet = "utf8mb4"; + conn.SslMode = MySqlSslMode.Required; + conn.SslCa = sslCa; + conn.CertificatePassword = sslCertificatePassword; + conn.Keepalive = 10; + connectionString = conn.ConnectionString; + using (var session1 = MySQLX.GetSession(connectionString)) + { + Assert.AreEqual(schemaName, session1.DefaultSchema.Name); + Assert.IsNotNull(session1.Uri); + } + + conn = new MySqlConnectionStringBuilder(); + conn.Server = sb.Server; + conn.UserID = sb.UserID; + conn.Password = sb.Password; + conn.Port = Convert.ToUInt32(XPort); + conn.ConnectionProtocol = MySqlConnectionProtocol.Tcp; + conn.Database = schemaName; + conn.CharacterSet = "utf8mb4"; + conn.SslMode = MySqlSslMode.VerifyCA; + conn.SslCa = sslCa; + conn.CertificatePassword = sslCertificatePassword; + conn.Keepalive = 10; + connectionString = conn.ConnectionString; + using (var session1 = MySQLX.GetSession(connectionString)) + { + Assert.AreEqual(schemaName, session1.DefaultSchema.Name); + Assert.IsNotNull(session1.Uri); + } + + conn = new MySqlConnectionStringBuilder(); + conn.Server = sb.Server; + conn.UserID = sb.UserID; + conn.Password = sb.Password; + conn.Port = Convert.ToUInt32(XPort); + conn.ConnectionProtocol = MySqlConnectionProtocol.Tcp; + conn.Database = schemaName; + conn.CharacterSet = "utf8mb4"; + conn.Keepalive = 10; + connectionString = conn.ConnectionString; + using (var session1 = MySQLX.GetSession(connectionString)) + { + Assert.AreEqual(schemaName, session1.DefaultSchema.Name); + Assert.IsNotNull(session1.Uri); + session1.DropSchema("㭋玤䂜蚌"); + session1.CreateSchema("㭋玤䂜蚌"); + session1.SQL("USE 㭋玤䂜蚌").Execute(); + Assert.AreEqual(schemaName, session1.DefaultSchema.Name); + } + + conn.Database = "㭋玤䂜蚌"; + connectionString = conn.ConnectionString; + using (var session1 = MySQLX.GetSession(connectionString)) + { + Assert.AreEqual("㭋玤䂜蚌", session1.DefaultSchema.Name); + Assert.IsNotNull(session1.Uri); + } + + conn.Server = sb.Server; + conn.UserID = sb.UserID; + conn.Password = sb.Password; + conn.Port = Convert.ToUInt32(XPort); + conn.ConnectionProtocol = MySqlConnectionProtocol.Tcp; + conn.Database = "㭋玤䂜蚌"; + conn.CharacterSet = "utf8mb4"; + conn.SslMode = MySqlSslMode.VerifyCA; + conn.SslCa = sslCa; + conn.CertificatePassword = sslCertificatePassword; + conn.Keepalive = 10; + connectionString = conn.ConnectionString; + using (var session1 = MySQLX.GetSession(connectionString)) + { + Assert.AreEqual("㭋玤䂜蚌", session1.DefaultSchema.Name); + Assert.IsNotNull(session1.Uri); + session1.DropSchema("㭋玤䂜蚌"); + } + + } + + [Test, Description("Test MySqlX plugin Connection for user with wrong password")] + public void GetSessionWithWrongPassword() + { + MySqlXConnectionStringBuilder sb = new MySqlXConnectionStringBuilder(ConnectionString); + sb.Password = "wrongPassword"; + Assert.Throws(() => MySQLX.GetSession(sb.ConnectionString)); + } + + [Test, Description("Test MySqlX plugin Connection for user with correct password but non MysqlX Server")] + public void GetSessionWithWrongPort() + { + MySqlXConnectionStringBuilder sb = new MySqlXConnectionStringBuilder(ConnectionString); + sb.Port = Convert.ToUInt32(Port); + Assert.Throws(() => MySQLX.GetSession(sb.ConnectionString)); + } + + [Test, Description("Test MySqlX plugin Issue a drop command after session already closed")] + public void GetSessionDropAlreadyClosedConnection() + { + Session testSession = MySQLX.GetSession(ConnectionString); + testSession.Close(); + testSession.Close();//works and behaviour expected but any input command should fail + Assert.Throws(() => testSession.DropSchema(schemaName)); + + testSession = MySQLX.GetSession(ConnectionStringNoPassword); + testSession.Close(); + testSession.Close();//works and behaviour expected but any input command should fail + Assert.Throws(() => testSession.DropSchema(schemaName)); + } + + [Test, Description("Session.DefaultSchema")] + public void SessionDefaultSchema() + { + if (!Platform.IsWindows()) return; + + MySqlXConnectionStringBuilder sb = new MySqlXConnectionStringBuilder(ConnectionString); + sb.Database = null; + var session1 = MySQLX.GetSession(sb.ConnectionString); + Assert.AreEqual(null, session1.DefaultSchema); + string connectionString = ConnectionString + ";protocol=Socket;database=" + schemaName + ";characterset=utf8mb4;sslmode=VerifyCA;ssl-ca=" + + sslCa + ";certificatepassword=" + sslCertificatePassword + ";connect-timeout=10;keepalive=10;auth=PLAIN"; + session1 = MySQLX.GetSession(connectionString); + Assert.AreEqual(schemaName, session1.DefaultSchema.Name); + + session1 = MySQLX.GetSession(ConnectionStringUri + "/" + schemaName + "?" + "auth=PLAIN&characterset=utf8mb4"); + Assert.AreEqual(schemaName, session1.DefaultSchema.Name); + + session1 = MySQLX.GetSession(new + { + server = sb.Server, + port = XPort, + user = sb.UserID, + password = sb.Password, + sslmode = MySqlSslMode.Required, + database = schemaName + }); + Assert.AreEqual(schemaName, session1.DefaultSchema.Name); + session1.DefaultSchema.CreateCollection("tester"); + session1.DefaultSchema.DropCollection("tester"); + Assert.AreEqual(schemaName, session1.DefaultSchema.Session.DefaultSchema.Name); + + var conn = new MySqlConnectionStringBuilder(); + session1.DropSchema("㭋玤䂜蚌"); + session1.CreateSchema("㭋玤䂜蚌"); + session1.SQL("USE 㭋玤䂜蚌").Execute(); + Assert.AreEqual(schemaName, session1.DefaultSchema.Name); + session1.Dispose(); + conn.Server = sb.Server; + conn.UserID = sb.UserID; + conn.Password = sb.Password; + conn.Port = Convert.ToUInt32(XPort); + conn.ConnectionProtocol = MySqlConnectionProtocol.Tcp; + conn.Database = "㭋玤䂜蚌"; + conn.CharacterSet = "utf8mb4"; + conn.SslMode = MySqlSslMode.Required; + conn.SslCa = sslCa; + conn.CertificatePassword = sslCertificatePassword; + conn.Keepalive = 10; + connectionString = conn.ConnectionString; + session1 = MySQLX.GetSession(connectionString); + Assert.AreEqual("㭋玤䂜蚌", session1.DefaultSchema.Name); + StringAssert.Contains("㭋玤䂜蚌", session1.Uri); + + conn.Server = sb.Server; + conn.UserID = sb.UserID; + conn.Password = sb.Password; + conn.Port = Convert.ToUInt32(XPort); + conn.ConnectionProtocol = MySqlConnectionProtocol.Tcp; + conn.Database = "㭋玤䂜蚌"; + conn.CharacterSet = "utf8mb4"; + conn.SslMode = MySqlSslMode.Required; + conn.SslCa = sslCa; + conn.CertificatePassword = sslCertificatePassword; + conn.Keepalive = 10; + connectionString = conn.ConnectionString; + session1 = MySQLX.GetSession(connectionString); + Assert.AreEqual("㭋玤䂜蚌", session1.DefaultSchema.Name); + StringAssert.Contains("㭋玤䂜蚌", session1.Uri); + session1.DefaultSchema.CreateCollection("tester"); + session1.DefaultSchema.DropCollection("tester"); + Assert.AreEqual("㭋玤䂜蚌", session1.DefaultSchema.Session.DefaultSchema.Name); + } + + [Test, Description("Session BaseString/MySQLXConnectionString Builder")] + public void ConnectionStringBuilderXpluginTests() + { + if (!Platform.IsWindows()) return; + + MySqlXConnectionStringBuilder mysqlx0 = new MySqlXConnectionStringBuilder(ConnectionString); + mysqlx0.ConnectionProtocol = MySqlConnectionProtocol.Tcp; + mysqlx0.CharacterSet = "utf8mb4"; + mysqlx0.SslMode = MySqlSslMode.Required; + mysqlx0.ConnectTimeout = 10; + mysqlx0.Keepalive = 10; + mysqlx0.CertificateFile = sslCa; + mysqlx0.CertificatePassword = sslCertificatePassword; + mysqlx0.CertificateStoreLocation = MySqlCertificateStoreLocation.LocalMachine; + mysqlx0.CertificateThumbprint = ""; + + + using (var xpluginconn = MySQLX.GetSession(mysqlx0.ConnectionString)) + { + Assert.AreEqual(SessionState.Open, xpluginconn.InternalSession.SessionState); + } + + mysqlx0 = new MySqlXConnectionStringBuilder(ConnectionString); + mysqlx0.Server = "::1"; + mysqlx0.Database = schemaName; + mysqlx0.CharacterSet = "utf8mb4"; + mysqlx0.ConnectionProtocol = MySqlConnectionProtocol.Tcp; + mysqlx0.SslMode = MySqlSslMode.Required; + mysqlx0.ConnectTimeout = 10; + mysqlx0.Keepalive = 10; + mysqlx0.CertificateFile = sslCa; + mysqlx0.CertificatePassword = sslCertificatePassword; + mysqlx0.CertificateStoreLocation = MySqlCertificateStoreLocation.LocalMachine; + mysqlx0.CertificateThumbprint = sslCertificatePassword; + + using (var xpluginconn = MySQLX.GetSession(mysqlx0.ConnectionString)) + { + Assert.AreEqual(SessionState.Open, xpluginconn.InternalSession.SessionState); + } + + mysqlx0 = new MySqlXConnectionStringBuilder(ConnectionString); + mysqlx0.Database = schemaName; + mysqlx0.ConnectionProtocol = MySqlConnectionProtocol.Tcp; + mysqlx0.CharacterSet = "utf8mb4"; + mysqlx0.SslMode = MySqlSslMode.VerifyCA; + mysqlx0.ConnectTimeout = 10; + mysqlx0.Keepalive = 10; + mysqlx0.CertificateFile = sslCa; + mysqlx0.CertificatePassword = "pass"; + mysqlx0.CertificateStoreLocation = MySqlCertificateStoreLocation.LocalMachine; + mysqlx0.CertificateThumbprint = ""; + + using (var xpluginconn = MySQLX.GetSession(mysqlx0.ConnectionString)) + { + Assert.AreEqual(SessionState.Open, xpluginconn.InternalSession.SessionState); + } + + mysqlx0 = new MySqlXConnectionStringBuilder(ConnectionString); + mysqlx0.Database = schemaName; + mysqlx0.ConnectionProtocol = MySqlConnectionProtocol.Tcp; + mysqlx0.CharacterSet = "utf8mb4"; + mysqlx0.SslMode = MySqlSslMode.Required; + mysqlx0.ConnectTimeout = 10; + mysqlx0.Keepalive = 10; + + using (var xpluginconn = MySQLX.GetSession(mysqlx0.ConnectionString)) + { + Assert.AreEqual(SessionState.Open, xpluginconn.InternalSession.SessionState); + } + + //Scenario-2 + string valid = "server=" + mysqlx0.Server + ";user id=" + mysqlx0.UserID + ";password=" + mysqlx0.Password + ";port=" + XPort + ";protocol=Socket;database=" + schemaName + ";characterset=utf8mb4;sslmode=Required;certificatefile=" + sslCa + ";certificatepassword=" + sslCertificatePassword + ";connect-timeout=10;keepalive=10;certificatestorelocation=LocalMachine;certificatethumbprint=;"; + using (var xpluginconn = MySQLX.GetSession(valid)) + { + Assert.AreEqual(SessionState.Open, xpluginconn.InternalSession.SessionState); + } + + //Scenario-3 + mysqlx0 = new MySqlXConnectionStringBuilder(ConnectionString); + mysqlx0.Database = schemaName; + mysqlx0.ConnectionProtocol = MySqlConnectionProtocol.Tcp; + mysqlx0.CharacterSet = "utf8mb4"; + mysqlx0.SslMode = MySqlSslMode.Required; + mysqlx0.ConnectTimeout = 10; + mysqlx0.Keepalive = 10; + mysqlx0.CertificateFile = sslCa; + mysqlx0.CertificatePassword = sslCertificatePassword; + mysqlx0.CertificateStoreLocation = MySqlCertificateStoreLocation.LocalMachine; + mysqlx0.CertificateThumbprint = ""; + mysqlx0.Auth = MySqlAuthenticationMode.AUTO; + mysqlx0.SslCa = sslCa; + using (var xpluginconn = MySQLX.GetSession(mysqlx0.ConnectionString)) + { + Assert.AreEqual(SessionState.Open, xpluginconn.InternalSession.SessionState); + } + + //Basic Scenarios + var connectionstr = "server=" + mysqlx0.Server + ";database=" + mysqlx0.Database + ";port=" + + XPort + ";userid=" + mysqlx0.UserID + ";password=" + + mysqlx0.Password + + ";characterset=utf8mb4;sslmode=Required;connect-timeout=20000;keepalive=20000;certificatefile=" + + sslCa + ";certificatepassword=" + sslCertificatePassword + + ";certificatestorelocation=LocalMachine;certificatethumbprint="; + using (var xpluginconn = MySQLX.GetSession(connectionstr)) + { + Assert.AreEqual(SessionState.Open, xpluginconn.InternalSession.SessionState); + } + + connectionstr = "mysqlx://" + mysqlx0.Server + ":" + XPort + "/" + + schemaName + "?connect-timeout=10&userid=" + mysqlx0.UserID + "&password=" + + mysqlx0.Password + "&sslca=" + sslCa + "&certificatepassword=" + + sslCertificatePassword + "&keepalive=10&characterset=utf8mb4"; + + using (var xpluginconn = MySQLX.GetSession(connectionstr)) + { + Assert.AreEqual(SessionState.Open, xpluginconn.InternalSession.SessionState); + } + + using (var xpluginconn = MySQLX.GetSession(new + { + server = mysqlx0.Server, + port = XPort, + user = mysqlx0.UserID, + password = mysqlx0.Password + })) + { + Assert.AreEqual(SessionState.Open, xpluginconn.InternalSession.SessionState); + } + + } + + [Test, Description("Connection Measurement Test")] + public void ConnectionTimeTest() + { + int secondsExpected = 15; + var connObject = new { server = Host, port = XPort, user = session.Settings.UserID, password = session.Settings.Password }; + MeasureConnectionString(ConnectionString, secondsExpected, "Connection String", 5); + MeasureConnectionString(ConnectionStringUri, secondsExpected, "Connection String URI", 5); + MeasureConnectionObject(connObject, secondsExpected, "Connection Object", 5); + } + + [Test, Description("Connection time with Database set")] + public void ConnectionTimeWithDatabaseTest() + { + int secondsExpected = 15; + var connString = ConnectionString + ";database=test"; + var connStringURI = ConnectionStringUri + "/?database=test"; + MySqlXConnectionStringBuilder sb = new MySqlXConnectionStringBuilder(ConnectionString); + var connectionObject = new + { + server = sb.Server, + port = XPort, + user = sb.UserID, + password = sb.Password, + database = schemaName + }; + MeasureConnectionString(connString, secondsExpected, "Connection String", 5); + MeasureConnectionString(connStringURI, secondsExpected, "Connection String URI", 5); + MeasureConnectionObject(connectionObject, secondsExpected, "Connection Object", 5); + } + + [Test, Description("REFACTOR PARSING OF CONNECTION STRING IN X DEVAPI")] + [Ignore("Uncomment to execute")] + public void ParseConnectionStringBenchmark_S1() + { + long transactions = 0; + long startTime = 0; + long endTime = 0; + long queryRunTime = 0; + int iterations = 10; + long NANO_TO_MILLI = 1000000; + long elapsedTime = 0; + long conTime = 0; + int i = 0; + + string connStr = ConnectionString; + + var session = MySQLX.GetSession(connStr); + session.Close(); + + for (int j = 0; j < 1; j++) + { + transactions = 0; + startTime = 0; + endTime = 0; + queryRunTime = 0; + iterations = 20; + elapsedTime = 0; + conTime = 0; + connStr = ConnectionStringUri; + startTime = NanoTime(); + for (i = 0; i < iterations; i++) + { + queryRunTime = queryRunTime + DoConnectString(connStr); + } + endTime = NanoTime(); + transactions = i; + elapsedTime = (endTime - startTime); //in nano + conTime = (elapsedTime / NANO_TO_MILLI) - (queryRunTime / NANO_TO_MILLI); + var t = CalculateTPS(conTime, transactions); + var log = ("Connected to MySQL using URI with iterations " + iterations + " with TPS:" + t); + Assert.IsNotNull(t); + + transactions = 0; + startTime = 0; + endTime = 0; + queryRunTime = 0; + iterations = 20; + elapsedTime = 0; + conTime = 0; + connStr = ConnectionString; + startTime = NanoTime(); + for (i = 0; i < iterations; i++) + { + queryRunTime = queryRunTime + DoConnectString(connStr); + } + endTime = NanoTime(); + transactions = i; + elapsedTime = (endTime - startTime); //in nano + conTime = (elapsedTime / NANO_TO_MILLI) - (queryRunTime / NANO_TO_MILLI); + t = CalculateTPS(conTime, transactions); + log = ("Connected to MySQL using connection string with iterations " + iterations + " with TPS:" + t); + Console.WriteLine(log); + Assert.IsNotNull(t); + + transactions = 0; + startTime = 0; + endTime = 0; + queryRunTime = 0; + iterations = 20; + elapsedTime = 0; + conTime = 0; + MySqlXConnectionStringBuilder sb = new MySqlXConnectionStringBuilder(ConnectionString); + var conn = new + { + server = sb.Server, + port = XPort, + user = sb.UserID, + password = sb.Password + }; + startTime = NanoTime(); + for (i = 0; i < iterations; i++) + { + queryRunTime = queryRunTime + DoConnectObject(conn); + } + endTime = NanoTime(); + transactions = i; + elapsedTime = (endTime - startTime); //in nano + conTime = (elapsedTime / NANO_TO_MILLI) - (queryRunTime / NANO_TO_MILLI); + t = CalculateTPS(conTime, transactions); + log = ("Connected to MySQL using Anonymous with iterations " + + iterations + + " with TPS:" + t); + } + } + + [Test, Description("REFACTOR PARSING OF CONNECTION STRING IN X DEVAPI")] + [Ignore("Uncomment to execute")] + public void ParseConnectionStringBenchmark_S2() + { + var connStr = ConnectionStringUri; + long queryStartTime = 0, queryRunTime = 0; + queryStartTime = NanoTime(); + var session1 = MySQLX.GetSession(connStr); + queryRunTime = NanoTime() - queryStartTime; + session1.Close(); + for (int j = 0; j < 20; j++) + { + connStr = ConnectionStringUri; + queryStartTime = 0; queryRunTime = 0; + queryStartTime = NanoTime(); + session1 = MySQLX.GetSession(connStr); + queryRunTime = NanoTime() - queryStartTime; + session1.Close(); + session1.Dispose(); + var log = ("Connected to MySQL using URI:" + queryRunTime / 1000000); + + connStr = ConnectionString; + queryStartTime = 0; queryRunTime = 0; + queryStartTime = NanoTime(); + session1 = MySQLX.GetSession(connStr); + queryRunTime = NanoTime() - queryStartTime; + session1.Close(); + session1.Dispose(); + log = ("Connected to MySQL using connection string:" + queryRunTime / 1000000); + + MySqlXConnectionStringBuilder sb = new MySqlXConnectionStringBuilder(ConnectionString); + var conn = new + { + server = sb.Server, + port = XPort, + user = sb.UserID, + password = sb.Password + }; + queryStartTime = 0; queryRunTime = 0; + queryStartTime = NanoTime(); + session1 = MySQLX.GetSession(conn); + queryRunTime = NanoTime() - queryStartTime; + session1.Close(); + session1.Dispose(); + log = ("Connected to MySQL using Connection Object:" + queryRunTime / 1000000); + } + } + + [Test, Description("Getsession/Session-URI")] + public void GetSessionUriPositiveTests() + { + string[] positiveStringList = new string[6]; + MySqlXConnectionStringBuilder sb = new MySqlXConnectionStringBuilder(ConnectionString); + positiveStringList[0] = "mysqlx://" + sb.UserID + ":" + sb.Password + "@" + sb.Server + ":" + XPort + "/?ssl-mode=Required"; + positiveStringList[1] = "mysqlx://" + sb.UserID + ":" + sb.Password + "@" + Host + ":" + XPort + "/?ssl-mode=Required"; + positiveStringList[2] = "mysqlx://" + sb.UserID + ":" + sb.Password + "@" + Host + ":" + XPort + "/" + schemaName + "?ssl-mode=Required"; + positiveStringList[3] = "mysqlx://" + sb.UserID + ":" + sb.Password + "@" + sb.Server + ":" + XPort + "/" + schemaName + "?ssl-mode=Required&auth=SHA256_MEMORY"; + positiveStringList[4] = "mysqlx://" + sb.UserID + ":" + sb.Password + "@" + sb.Server + ":" + XPort + "/" + schemaName + "?ssl-mode=Required&characterset=utf8mb4"; + positiveStringList[5] = "mysqlx://" + sb.UserID + ":" + sb.Password + "@" + sb.Server + ":" + XPort + "/" + schemaName + "?" + "ssl-mode=Required"; + + foreach (var connStr in positiveStringList) + { + using (Session c = MySQLX.GetSession(connStr)) + { + Assert.AreEqual(SessionState.Open, c.InternalSession.SessionState); + } + } + } + + [Test, Description("Getsession/Session-URI Negative Scenarios")] + public void GetSessionUriNegativeTests() + { + string[] NegativeStringList = new string[8]; + MySqlXConnectionStringBuilder sb = new MySqlXConnectionStringBuilder(ConnectionString); + NegativeStringList[0] = "mysqlx://" + sb.UserID + ":" + sb.Password + "@" + sb.Server + ":" + 9999 + ";ssl-mode=required"; + NegativeStringList[1] = "mysqlx://" + sb.UserID + ":" + sb.Password + "@" + "129.0.0.1" + ":" + XPort + ";ssl-mode=required"; + NegativeStringList[2] = "mysqlx://" + sb.UserID + ":" + "wrongpassword" + "@" + "localhost" + ":" + XPort + "/" + schemaName + "?ssl-mode=required"; + NegativeStringList[3] = "mysqlxyzzzz://" + sb.UserID + ":" + sb.Password + "@" + sb.Server + ":" + XPort + "/" + schemaName + "?ssl-mode=required"; + NegativeStringList[4] = "mysqlx://" + "wrongsb.UserID" + ":" + sb.Password + "@" + sb.Server + ":" + XPort + "/" + schemaName + "?ssl-mode=required"; + NegativeStringList[5] = "mysqlx://" + sb.UserID + ":" + sb.Password + "@" + "wronglocalhost" + "/" + schemaName + "?sslmode=required"; + NegativeStringList[6] = "mysqlx://" + sb.UserID + ":" + sb.Password + "@" + sb.Server + ":" + XPort + "/" + schemaName + "?" + "ssl-mode*&^%$#@!invalidvalues123*()"; + NegativeStringList[7] = "mysqlx://" + sb.UserID + ":" + sb.Password + "@" + sb.Server + ":" + XPort + "/" + schemaName + "?" + "invalidvalues123invalidvalues123invalidvalues123invalidvalues123invalidvalues123invalidvalues123invalidvalues123invalidvalues123" + ";ssl-mode=required"; + + foreach (var connStr in NegativeStringList) + { + Assert.Catch(() => MySQLX.GetSession(connStr)); + } + } + + [Test, Description("Getsession using Anonymous Type Negative-Wrong Password")] + public void GetSessionAnonymousTypeNegative() + { + var connectionStringObject = new { connection = $"server={Host};user={session.Settings.UserID};port={XPort};password=wrong_password;sslmode={MySqlSslMode.Required}" }; + Assert.Throws(() => MySQLX.GetSession(connectionStringObject.connection)); + } + + [Test, Description("Support Session Anonymous as uri string Positive")] + public void GetSessionWithAnonymousObjectURI() + { + var connectionStringObject = new { connection = ConnectionStringUri }; + using (Session sessionPlain = MySQLX.GetSession(connectionStringObject.connection)) + { + var db = sessionPlain.GetSchema(schemaName); + var col = db.GetCollection("my_collection_123456789"); + if (col.ExistsInDatabase()) + { + db.DropCollection("my_collection_123456789"); + db.CreateCollection("my_collection_123456789"); + } + else { db.CreateCollection("my_collection_123456789"); } + db.DropCollection("my_collection_123456789"); + } + if (Convert.ToInt32(XPort) == 33060)//Connect to server on localhost with user userx using URI string default port + { + MySqlXConnectionStringBuilder sb = new MySqlXConnectionStringBuilder(ConnectionString); + connectionStringObject = new { connection = "mysqlx://" + sb.UserID + ":" + sb.Password + "@" + sb.Server }; + using (Session sessionPlain = MySQLX.GetSession(connectionStringObject.connection)) + { + var db = sessionPlain.GetSchema(schemaName); + var col = db.GetCollection("my_collection_123456789"); + if (col.ExistsInDatabase()) + { + db.DropCollection("my_collection_123456789"); + db.CreateCollection("my_collection_123456789"); + } + else { db.CreateCollection("my_collection_123456789"); } + db.DropCollection("my_collection_123456789"); + } + } + } + + [Test, Description("Support Session connection string as uri string Negative-Invalid Password")] + public void GetSessionURIWrongPassword() + { + string invalidPassword = "invalid"; + MySqlXConnectionStringBuilder sb = new MySqlXConnectionStringBuilder(ConnectionString); + string connectionString = "mysqlx://" + sb.UserID + ":" + invalidPassword + "@" + sb.Server + ":" + XPort; + Assert.Throws(() => MySQLX.GetSession(connectionString)); + connectionString = "mysqlx://" + sb.UserID + ":" + invalidPassword + "@" + sb.Server; + Assert.Throws(() => MySQLX.GetSession(connectionString)); + } + + // Connection Timeout Tests + [Test, Description("Remote offline host without connect-timeout parameter.Mysql getclient with pooling and maxsize 2 and queue timeout 2000 milliseconds")] + public void TimeoutUsingClientAndPooling_S1() + { + MySqlXConnectionStringBuilder sb = new MySqlXConnectionStringBuilder(ConnectionString); + string serverName = "10.10.10.10"; + string connStr = "server=" + serverName + ";user=" + sb.UserID + ";port=" + XPort + ";password=" + + sb.Password + ";"; + var connectionpooling = "{ \"pooling\": { \"maxSize\": 1, \"queueTimeout\": 2000 , \"maxIdleTime\":1000, \"enabled\": true} }"; + var connectionpoolingObject = new { pooling = new { enabled = true, maxSize = 1, queueTimeout = 2000, maxIdleTime = 1000 } }; + Client client = MySQLX.GetClient(connStr, connectionpoolingObject); + TestFailureTimeout(client, 9, 11, "Timeout value between 9 and 11 seconds"); + var connStrUri = "mysqlx://" + sb.UserID + ":" + sb.Password + "@" + serverName + ":" + XPort; + client = MySQLX.GetClient(connStrUri, connectionpoolingObject); + TestFailureTimeout(client, 9, 11, "Timeout value between 9 and 11 seconds"); + var connObj = new { server = serverName, port = XPort, user = sb.UserID, password = sb.Password }; + client = MySQLX.GetClient(connObj, connectionpoolingObject); + TestFailureTimeout(client, 9, 11, "Timeout value between 9 and 11 seconds"); + client = MySQLX.GetClient(connStr, connectionpooling); + TestFailureTimeout(client, 9, 11, "Timeout value between 9 and 11 seconds"); + client = MySQLX.GetClient(connStrUri, connectionpooling); + TestFailureTimeout(client, 9, 11, "Timeout value between 9 and 11 seconds"); + client = MySQLX.GetClient(connObj, connectionpooling); + TestFailureTimeout(client, 9, 11, "Timeout value between 9 and 11 seconds"); + } + + [Test, Description("failover connection string with one offline host and one online host and disable connect - timeout parameter(set to 0) " + + ".Mysql getclient with pooling and maxsize 2 and queue timeout 2000 milliseconds.Both the session should be successful after" + + "waiting for the respective lower layer socket timeout")] + public void TimeoutUsingClientAndPooling_S2() + { + int connectTimeout = 1; + string hostList = string.Empty; + string localIP = session.Settings.Server; + int minTime = 0; + int maxTime = 30; + session.Settings.UserID = "testAnyhost"; + string connStr = "server=10.10.10.10," + localIP + ";port=" + XPort + ";uid=" + session.Settings.UserID + ";" + "password=" + session.Settings.Password + + ";connect-timeout=" + connectTimeout; + var connectionpoolingObject = new { pooling = new { enabled = true, maxSize = 1, queueTimeout = 20000, maxIdleTime = 1000 } }; + + TestClientSuccessTimeout(minTime, maxTime, $"Timeout value between {minTime} and {maxTime} seconds", connStr, connectionpoolingObject); + + var connStrUri = "mysqlx://" + session.Settings.UserID + ":" + session.Settings.Password + "@[192.1.10.10," + localIP + ":" + XPort + "]" + "/?connect-timeout=" + connectTimeout; + TestClientSuccessTimeout(minTime, maxTime, $"Timeout value between {minTime} and {maxTime} seconds", connStr, connectionpoolingObject); + + } + + [Test, Description("connect - timeout parameter set as 1000 milliseconds.Create a pool of two sessions." + + "pooling(enabled:true,maxSize:2,queueTimeout: 2000 milliseconds).Try to create a third connection and verify the behaviour(Queue timeout expected)")] + public void TimeoutReachingMaxSizePool() + { + int connectTimeout = 1000; + string hostList = string.Empty; + string localIP = session.Settings.Server; + string connStr = "server=" + localIP + ";port=" + XPort + ";uid=" + session.Settings.UserID + ";" + "password=" + session.Settings.Password + + ";connect-timeout=" + connectTimeout; + var connectionpooling = "{ \"pooling\": { \"maxSize\": 2, \"queueTimeout\": 2000 , \"maxIdleTime\":1000, \"enabled\": true} }"; + var connectionpoolingObject = new { pooling = new { enabled = true, maxSize = 2, queueTimeout = 2000, maxIdleTime = 1000 } }; + using (Client client = MySQLX.GetClient(connStr, connectionpoolingObject)) + { + var session1 = client.GetSession(); + var session2 = client.GetSession(); + TestClientQueueTimeout(client, 1, 3, "Test queue timeout"); + } + var connStrUri = "mysqlx://" + session.Settings.UserID + ":" + session.Settings.Password + "@[" + localIP + ":" + XPort + "]" + "/?connect-timeout=" + connectTimeout; + using (var client = MySQLX.GetClient(connStrUri, connectionpoolingObject)) + { + + var session1 = client.GetSession(); + var session2 = client.GetSession(); + TestClientQueueTimeout(client, 1, 3, "Test queue timeout"); + } + var connObj = new { server = "" + localIP, port = XPort, uid = session.Settings.UserID, password = session.Settings.Password, connecttimeout = connectTimeout }; + using (var client = MySQLX.GetClient(connObj, connectionpoolingObject)) + { + var session1 = client.GetSession(); + var session2 = client.GetSession(); + TestClientQueueTimeout(client, 1, 3, "Test queue timeout"); + } + + using (Client client = MySQLX.GetClient(connStr, connectionpooling)) + { + var session1 = client.GetSession(); + var session2 = client.GetSession(); + TestClientQueueTimeout(client, 1, 3, "Test queue timeout"); + } + using (var client = MySQLX.GetClient(connStrUri, connectionpooling)) + { + var session1 = client.GetSession(); + var session2 = client.GetSession(); + TestClientQueueTimeout(client, 1, 3, "Test queue timeout"); + } + using (var client = MySQLX.GetClient(connObj, connectionpooling)) + { + var session1 = client.GetSession(); + var session2 = client.GetSession(); + TestClientQueueTimeout(client, 1, 3, "Test queue timeout"); + } + for (var i = 1; i <= 2; i++) + { + hostList = "(address=143.24.20.36,priority=1),(address=" + localIP + ",priority=0)"; + } + connStr = "server=" + hostList + ";user=" + session.Settings.UserID + ";port=" + XPort + ";password=" + + session.Settings.Password + ";connect-timeout=" + connectTimeout; + + using (var client = MySQLX.GetClient(connStr, connectionpoolingObject)) + { + var session1 = client.GetSession(); + var session2 = client.GetSession(); + TestClientQueueTimeout(client, 1, 3, "Test queue timeout X"); + } + + var connObj1 = new { server = hostList, port = XPort, user = session.Settings.UserID, password = session.Settings.Password, connecttimeout = connectTimeout }; + using (var client = MySQLX.GetClient(connObj1, connectionpoolingObject)) + { + var session1 = client.GetSession(); + var session2 = client.GetSession(); + TestClientQueueTimeout(client, 1, 3, "Test queue timeout Y"); + } + using (var client = MySQLX.GetClient(connStr, connectionpooling)) + { + var session1 = client.GetSession(); + var session2 = client.GetSession(); + TestClientQueueTimeout(client, 1, 3, "Test queue timeout X"); + } + connObj1 = new { server = hostList, port = XPort, user = session.Settings.UserID, password = session.Settings.Password, connecttimeout = connectTimeout }; + using (var client = MySQLX.GetClient(connObj1, connectionpooling)) + { + var session1 = client.GetSession(); + var session2 = client.GetSession(); + TestClientQueueTimeout(client, 1, 3, "Test queue timeout A"); + } + + } + + [Test, Description("scenario 0(connectionString,connectionUri,Anonymous Object)-Without connect timeout and max timeout should be 10s")] + public void TimeoutWithWrongHost() + { + string serverName = "vigdis07.no.oracle.com"; + string connStr = "server=" + serverName + ";user=" + session.Settings.UserID + ";port=" + XPort + ";password=" + + session.Settings.Password + ";"; + TestConnectStringTimeoutFailureTimeout(connStr, 0, 11, "Timeout value between 9 and 11 seconds"); + connStr = "mysqlx://" + session.Settings.UserID + ":" + session.Settings.Password + "@" + serverName + ":" + XPort; + TestConnectStringTimeoutFailureTimeout(connStr, 0, 11, "Timeout value between 9 and 11 seconds"); + var connObj = new { server = serverName, port = XPort, user = session.Settings.UserID, password = session.Settings.Password }; + TestConnectObjTimeoutFailureTimeout(connObj, 0, 11, "Timeout value between 9 and 11 seconds"); + + } + + [Test, Description("scenario 1(connectionString,connectionUri,Anonymous Object)")] + public void MeasureNoTimeoutResponse() + { + string connStr = "server=" + session.Settings.Server + ";user=" + session.Settings.UserID + ";port=" + XPort + ";password=" + + session.Settings.Password + ";" + "connect-timeout=90;"; + TestConnectStringTimeoutSuccessTimeout(connStr, 0, 3, "Timeout value between 0 and 1 second"); + connStr = "mysqlx://" + session.Settings.UserID + ":" + session.Settings.Password + "@" + session.Settings.Server + ":" + XPort + "?connect-timeout=900;"; + TestConnectStringTimeoutSuccessTimeout(connStr, 0, 3, "Timeout value between 0 and 1 second"); + var connObj = new { server = session.Settings.Server, port = XPort, user = session.Settings.UserID, password = session.Settings.Password, connecttimeout = 9000 }; + TestConnectObjectTimeoutSuccessTimeout(connObj, 0, 3, "Timeout value between 0 and 1 second"); + } + + [Test, Description("scenario 2(connectionString,connectionUri,Anonymous Object with all options)")] + public void NoTimeoutWithManyOptions() + { + if (!Platform.IsWindows()) return; + string connStr = "server=" + session.Settings.Server + ";user id=" + session.Settings.UserID + ";password=" + + session.Settings.Password + ";port=" + XPort + ";protocol=Socket;" + + "database=" + schemaName + ";characterset=utf8mb4;sslmode=VerifyCA;ssl-ca=" + + sslCa + ";certificatepassword=pass;keepalive=10;auth=PLAIN;" + + "connect-timeout=900;"; + TestConnectStringTimeoutSuccessTimeout(connStr, 0, 1, "Timeout value between 0 and 1 second"); + connStr = "mysqlx://" + session.Settings.Server + ":" + XPort + "/" + schemaName + + "?" + "user id=" + session.Settings.UserID + "&password=" + session.Settings.Password + "&sslca=" + + sslCa + "&certificatepassword=pass&keepalive=10&characterset=utf8mb4&auth=PLAIN&connect-timeout=900"; + TestConnectStringTimeoutSuccessTimeout(connStr, 0, 1, "Timeout value between 0 and 1 second"); + var connObj = + new + { + server = session.Settings.Server, + port = XPort, + user = session.Settings.UserID, + password = session.Settings.Password, + sslmode = MySqlSslMode.VerifyCA, + CertificateFile = sslCa, + CertificatePassword = sslCertificatePassword, + database = schemaName, + keepalive = 10, + characterset = "utf8mb4", + auth = MySqlAuthenticationMode.PLAIN, + connecttimeout = 9000 + }; + TestConnectStringTimeoutSuccessTimeout(connStr, 0, 1, "Timeout value between 0 and 1 second"); + } + + [Test, Description("scenario 1(MysqlxStringBuilder)")] + public void TimeoutSuccessWithStringBuilder() + { + var connStrBuilder = new MySqlXConnectionStringBuilder(); + connStrBuilder.ConnectTimeout = 9000; + connStrBuilder.UserID = session.Settings.UserID; + connStrBuilder.Password = session.Settings.Password; + connStrBuilder.Port = Convert.ToUInt32(XPort); + connStrBuilder.Server = session.Settings.Server; + TestConnectStringTimeoutSuccessTimeout(connStrBuilder.ConnectionString, 0, 3, "Timeout value between 0 and 3 second"); + string connStr = "server=" + session.Settings.Server + ";user=" + session.Settings.UserID + ";port=" + XPort + ";password=" + + session.Settings.Password + ";" + "connect-timeout=9000;"; + connStrBuilder = new MySqlXConnectionStringBuilder(connStr); + TestConnectStringTimeoutSuccessTimeout(connStrBuilder.ConnectionString, 0, 3, "Timeout value between 0 and 3 second"); + } + + [Test, Description("scenario 2(MysqlxStringBuilder with all options)")] + public void TimeoutSuccessWithStringBuilderAllOptions() + { + string connStr = null; + MySqlXConnectionStringBuilder mysqlx0 = null; + if (!Platform.IsWindows()) return; + connStr = "server=" + session.Settings.Server + ";user id=" + session.Settings.UserID + ";password=" + + session.Settings.Password + ";port=" + XPort + ";protocol=Socket;" + + "database=" + schemaName + ";characterset=utf8mb4;sslmode=Required;ssl-ca=" + + sslCa + $";certificatepassword={sslCertificatePassword};certificatestorelocation=LocalMachine;" + + ";keepalive =10;auth=PLAIN;certificatethumbprint=;" + + "connect-timeout=" + 9000; + mysqlx0 = new MySqlXConnectionStringBuilder(connStr); + TestConnectStringTimeoutSuccessTimeout(mysqlx0.ConnectionString, 0, 1, "Timeout value between 0 and 1 second"); + mysqlx0 = new MySqlXConnectionStringBuilder(); + mysqlx0.Server = session.Settings.Server; + mysqlx0.UserID = session.Settings.UserID; + mysqlx0.Password = session.Settings.Password; + mysqlx0.Port = Convert.ToUInt32(XPort); + mysqlx0.ConnectionProtocol = MySqlConnectionProtocol.Tcp; + mysqlx0.Database = schemaName; + mysqlx0.CharacterSet = "utf8mb4"; + mysqlx0.SslMode = MySqlSslMode.Required; + mysqlx0.SslCa = sslCa; + mysqlx0.CertificatePassword = sslCertificatePassword; + mysqlx0.CertificateStoreLocation = MySqlCertificateStoreLocation.LocalMachine; + mysqlx0.Keepalive = 10; + mysqlx0.Auth = MySqlAuthenticationMode.PLAIN; + mysqlx0.CertificateThumbprint = ""; + mysqlx0.ConnectTimeout = (uint)90000; + TestConnectStringTimeoutSuccessTimeout(mysqlx0.ConnectionString, 0, 1, "Timeout value between 0 and 1 second"); + } + + [Test, Description("scenario 3(MysqlxStringBuilder with all options-set minimum timeout to 1 and keep on increasing till gets connected)")] + public void TimeoutIncreasingUntilConnect() + { + string connStr = null; + MySqlXConnectionStringBuilder mysqlx0 = null; + + for (int i = 1; i < 20; i++) + { + connStr = ConnectionString + ";protocol=Socket;" + + "database=" + schemaName + ";characterset=utf8mb4;sslmode=VerifyCA;ssl-ca=" + + sslCa + $";certificatepassword={sslCertificatePassword};certificatestorelocation=LocalMachine;" + + ";auth=PLAIN;certificatethumbprint=;" + + "connect-timeout=" + i; + mysqlx0 = new MySqlXConnectionStringBuilder(connStr); + using (var conn = MySQLX.GetSession(mysqlx0.ConnectionString)) + { + Assert.IsNotNull(conn.Uri); + } + break; + } + + for (int i = 1; i < 20; i++) + { + mysqlx0 = new MySqlXConnectionStringBuilder(); + mysqlx0.Server = session.Settings.Server; + mysqlx0.UserID = session.Settings.UserID; + mysqlx0.Password = session.Settings.Password; + mysqlx0.Port = Convert.ToUInt32(XPort); + mysqlx0.ConnectionProtocol = MySqlConnectionProtocol.Tcp; + mysqlx0.Database = schemaName; + mysqlx0.CharacterSet = "utf8mb4"; + mysqlx0.SslMode = MySqlSslMode.VerifyCA; + mysqlx0.SslCa = sslCa; + mysqlx0.CertificatePassword = sslCertificatePassword; + mysqlx0.CertificateStoreLocation = MySqlCertificateStoreLocation.LocalMachine; + mysqlx0.Auth = MySqlAuthenticationMode.PLAIN; + mysqlx0.CertificateThumbprint = ""; + mysqlx0.ConnectTimeout = (uint)i; + + using (var conn = MySQLX.GetSession(mysqlx0.ConnectionString)) + { + Assert.IsNotNull(conn.Uri); + } + break; + } + } + + [Test, Description("scenario 1(connectionString,connectionUri,Anonymous Object with default timeout)")] + public void ValidateDefaultTimeoutParameter() + { + uint defaultTimeout = 1; + string connStr = ConnectionString + ";" + "connect-timeout=" + defaultTimeout; + for (int i = 0; i < 10; i++) + { + using (var conn = MySQLX.GetSession(connStr)) + { + Assert.AreEqual(conn.Settings.ConnectTimeout, defaultTimeout); + } + } + connStr = "mysqlx://" + session.Settings.UserID + ":" + session.Settings.Password + "@" + session.Settings.Server + ":" + XPort + "?connect-timeout=" + defaultTimeout; + for (int i = 0; i < 10; i++) + { + using (var conn = MySQLX.GetSession(connStr)) + { + Assert.AreEqual(conn.Settings.ConnectTimeout, defaultTimeout); + } + } + var connObj1 = new { server = session.Settings.Server, port = XPort, user = session.Settings.UserID, password = session.Settings.Password, connecttimeout = defaultTimeout }; + for (int i = 0; i < 10; i++) + { + using (var conn = MySQLX.GetSession(connObj1)) + { + Assert.AreEqual(conn.Settings.ConnectTimeout, defaultTimeout); + } + } + } + + [Test, Description("scenario 2(MysqlxStringBuilder with default timeout)")] + public void ValidateDefaultTimeoutParameterWithStringBuilder() + { + uint defaultTimeout = 1; + var connStrBuilder = new MySqlXConnectionStringBuilder(); + connStrBuilder.ConnectTimeout = defaultTimeout; + connStrBuilder.UserID = session.Settings.UserID; + connStrBuilder.Password = session.Settings.Password; + connStrBuilder.Port = Convert.ToUInt32(XPort); + connStrBuilder.Server = session.Settings.Server; + for (int i = 0; i < 10; i++) + { + using (var conn = MySQLX.GetSession(connStrBuilder.ConnectionString)) + { + Assert.AreEqual(conn.Settings.ConnectTimeout, defaultTimeout); + } + } + string connStr = ConnectionString + ";" + "connect-timeout=" + defaultTimeout; + connStrBuilder = new MySqlXConnectionStringBuilder(connStr); + for (int i = 0; i < 10; i++) + { + using (var conn = MySQLX.GetSession(connStrBuilder.ConnectionString)) + { + Assert.AreEqual(conn.Settings.ConnectTimeout, defaultTimeout); + } + } + } + + [Test, Description("scenario 1(MysqlxStringBuilder with connect timeout option for offline server)")] + public void TimeoutOfflineServerWithStringBuilder() + { + int connectionTimeout = 2000; + string serverName = "vigdis07.no.oracle.com"; + var connStrBuilder = new MySqlXConnectionStringBuilder(); + connStrBuilder.ConnectTimeout = (uint)connectionTimeout; + connStrBuilder.UserID = session.Settings.UserID; + connStrBuilder.Password = session.Settings.Password; + connStrBuilder.Port = Convert.ToUInt32(XPort); + connStrBuilder.Server = serverName; + TestConnectStringTimeoutFailureTimeout(connStrBuilder.ConnectionString, 0, 21, "Offline host timeout value in between 1 and 21 seconds"); + + string connStr = "server=" + serverName + ";user=" + session.Settings.UserID + ";port=" + XPort + ";password=" + + session.Settings.Password + ";" + "connect-timeout=" + connectionTimeout; + connStrBuilder = new MySqlXConnectionStringBuilder(connStr); + TestConnectStringTimeoutFailureTimeout(connStrBuilder.ConnectionString, 0, 21, "Offline host timeout value in between 1 and 21 seconds"); + } + + [Test, Description("scenario 1(connectionString,connectionUri,Anonymous Object,MysqlxStringBuilder with connect timeout option=1 for online server)")] + public void TimeoutSuccessConnectOptionOne() + { + int connectionTimeout = 1; + string connStr = ConnectionString + ";" + "connect-timeout=" + connectionTimeout; + TestConnectStringTimeoutSuccessTimeout(connStr, 0, 5, "Checking the timeout between 0 to 5 seconds"); + connStr = ConnectionStringUri + "?connect-timeout=" + connectionTimeout; + TestConnectStringTimeoutSuccessTimeout(connStr, 0, 5, "Checking the timeout between 0 to 5 seconds"); + var connectionObj = new { server = session.Settings.Server, port = XPort, user = session.Settings.UserID, password = session.Settings.Password, connecttimeout = connectionTimeout }; + TestConnectObjectTimeoutSuccessTimeout(connectionObj, 0, 5, "Checking the timeout between 0 to 5 seconds"); + + var connStrBuilder = new MySqlXConnectionStringBuilder(); + connStrBuilder.ConnectTimeout = (uint)connectionTimeout; + connStrBuilder.UserID = session.Settings.UserID; + connStrBuilder.Password = session.Settings.Password; + connStrBuilder.Port = Convert.ToUInt32(XPort); + connStrBuilder.Server = session.Settings.Server; + TestConnectStringTimeoutSuccessTimeout(connStrBuilder.ConnectionString, 0, 5, "Checking the timeout between 0 to 5 seconds"); + + connStr = ConnectionString + ";" + "connect-timeout=" + connectionTimeout; + connStrBuilder = new MySqlXConnectionStringBuilder(connStr); + TestConnectStringTimeoutSuccessTimeout(connStrBuilder.ConnectionString, 0, 5, "Checking the timeout between 0 to 5 seconds"); + + } + + [Test, Description("scenario 1(connectionString,connectionUri,Anonymous Object,MysqlxStringBuilder with connect timeout option=0 for offline server)")] + public void TimeoutOfflineServerConnectOptionZero() + { + int connectionTimeout = 0; + string serverName = "vigdis07.no.oracle.com"; + + string connStr = "server=" + serverName + ";user=" + session.Settings.UserID + ";port=" + XPort + ";password=" + + session.Settings.Password + ";" + "connect-timeout=" + connectionTimeout; + TestConnectStringTimeoutFailureTimeout(connStr, 0, 50000, "Checking the timeout between 0 to 50000 milliseconds"); + + connStr = "mysqlx://" + session.Settings.UserID + ":" + session.Settings.Password + "@" + serverName + ":" + XPort + "?connect-timeout=" + connectionTimeout; + TestConnectStringTimeoutFailureTimeout(connStr, 0, 50000, "Checking the timeout between 0 to 50000 milliseconds"); + + var connObj = new { server = serverName, port = XPort, user = session.Settings.UserID, password = session.Settings.Password, connecttimeout = connectionTimeout }; + TestConnectObjTimeoutFailureTimeout(connObj, 0, 50000, "Checking the timeout between 0 to 50000 milliseconds"); + + var connStrBuilder = new MySqlXConnectionStringBuilder(); + connStrBuilder.ConnectTimeout = (uint)connectionTimeout; + connStrBuilder.UserID = session.Settings.UserID; + connStrBuilder.Password = session.Settings.Password; + connStrBuilder.Port = Convert.ToUInt32(XPort); + connStrBuilder.Server = serverName; + TestConnectStringTimeoutFailureTimeout(connStr, 0, 50000, "Checking the timeout between 0 to 50000 milliseconds"); + + connStr = "server=" + serverName + ";user=" + session.Settings.UserID + ";port=" + XPort + ";password=" + + session.Settings.Password + ";" + "connect-timeout=" + connectionTimeout; + connStrBuilder = new MySqlXConnectionStringBuilder(connStr); + TestConnectStringTimeoutFailureTimeout(connStr, 0, 50000, "Checking the timeout between 0 to 50000 milliseconds"); + + } + + [Test, Description("(connectionString,connectionUri,Anonymous Object.Test that the timeout will be reset for each connection attempt in a failover scenario")] + public void ConnectTimeoutSeveralAddreses() + { + StringBuilder hostList = new StringBuilder(); + int connectionTimeout = 1000; + var priority = 100; + for (var i = 1; i <= 101; i++) + { + hostList.Append("(address=server" + i + ".example,priority=" + (priority != 0 ? priority-- : 0) + "),"); + if (i == 101) hostList.Append($"(address={Host},priority=0)"); + } + + using (var session1 = MySQLX.GetSession("server=" + hostList + ";port=" + XPort + ";uid=" + + session.Settings.UserID + ";password=" + session.Settings.Password + ";connect-timeout=" + + connectionTimeout + ";ssl-mode=required")) + { + Assert.AreEqual(SessionState.Open, session1.InternalSession.SessionState); + var schema = session1.GetSchema("test"); + Assert.IsNotNull(schema); + } + + var connStr = "mysqlx://" + session.Settings.UserID + ":" + session.Settings.Password + "@[" + hostList + "]/?connect-timeout=" + connectionTimeout; + using (var session1 = MySQLX.GetSession(connStr)) + { + Assert.AreEqual(SessionState.Open, session1.InternalSession.SessionState); + var schema = session1.GetSchema("test"); + Assert.IsNotNull(schema); + } + + using (var session1 = MySQLX.GetSession(new + { + server = hostList.ToString(), + port = XPort, + user = session.Settings.UserID, + password = session.Settings.Password, + sslmode = MySqlSslMode.Required + })) + { + Assert.AreEqual(SessionState.Open, session1.InternalSession.SessionState); + var schema = session1.GetSchema("test"); + Assert.IsNotNull(schema); + } + + var strList = "(address=143.24.20.36,priority=0),(address=10.172.165.157,priority=1)"; + connectionTimeout = 2000; + var connString = "server=" + strList + ";port=" + XPort + ";uid=" + + session.Settings.UserID + ";password=" + session.Settings.Password + ";connect-timeout=" + + connectionTimeout + ";ssl-mode=required"; + Stopwatch sw = new Stopwatch(); + sw.Start(); + Assert.Throws(() => MySQLX.GetSession(connString)); + sw.Stop(); + Assert.True(sw.Elapsed.Seconds > 0 && sw.Elapsed.Seconds < 21); + + connStr = "mysqlx://" + session.Settings.UserID + ":" + session.Settings.Password + "@[" + strList + "]" + "/?connect-timeout=" + connectionTimeout; + sw = new Stopwatch(); + sw.Start(); + Assert.Throws(() => MySQLX.GetSession(connString)); + sw.Stop(); + Assert.True(sw.Elapsed.Seconds > 0 && sw.Elapsed.Seconds < 21); + + var connObj1 = new + { + server = strList, + port = XPort, + user = session.Settings.UserID, + password = session.Settings.Password, + connecttimeout = connectionTimeout + }; + sw = new Stopwatch(); + sw.Start(); + Assert.Throws(() => MySQLX.GetSession(connString)); + sw.Stop(); + Assert.True(sw.Elapsed.Seconds > 0 && sw.Elapsed.Seconds < 21); + } + + [Test, Description("(connectionString,connectionUri,Anonymous Object.Test that the timeout will be reset for each connection attempt in a failover scenario")] + public void ConnectTimeoutWithFailoverAndNotValidHost() + { + string hostList = "(address=143.24.20.36,priority=0),(address=143.24.70.98,priority=1)"; + int connectionTimeout = 2000; + // URL + var connString = "server=" + hostList + ";port=" + XPort + ";uid=" + + session.Settings.UserID + ";password=" + session.Settings.Password + ";connect-timeout=" + + connectionTimeout; + Stopwatch sw = new Stopwatch(); + sw.Start(); + Assert.Throws(() => MySQLX.GetSession(connString)); + sw.Stop(); + Assert.True(sw.Elapsed.Seconds > 0 && sw.Elapsed.Seconds < 10); + // URI + var connStr = "mysqlx://" + session.Settings.UserID + ":" + session.Settings.Password + "@[" + hostList + "]" + "/?connect-timeout=" + connectionTimeout; + sw = new Stopwatch(); + sw.Start(); + Assert.Throws(() => MySQLX.GetSession(connString)); + sw.Stop(); + Assert.True(sw.Elapsed.Seconds > 0 && sw.Elapsed.Seconds < 10); + + // Object + var connObj = new + { + server = hostList, + port = XPort, + user = session.Settings.UserID, + password = session.Settings.Password, + connecttimeout = connectionTimeout + }; + sw = new Stopwatch(); + sw.Start(); + Assert.Throws(() => MySQLX.GetSession(connString)); + sw.Stop(); + Assert.True(sw.Elapsed.Seconds > 0 && sw.Elapsed.Seconds < 10); + } + + [Test, Description("Confirm that the timeout is only applied to the connection process, not to any subsequent operation after the connection is established")] + public void ValidateConnectTimeoutScope() + { + if (!Platform.IsWindows()) return; + string connStr = null; + connStr = "server=" + session.Settings.Server + ";user=" + session.Settings.UserID + ";port=" + XPort + ";password=" + + session.Settings.Password + ";" + "connect-timeout=10000;"; + using (var conn = MySQLX.GetSession(connStr)) + { + conn.SQL("SELECT SLEEP(10)").Execute(); + var res = conn.SQL("select @@port").Execute().FirstOrDefault(); + Assert.IsNotNull(res); + } + + connStr = "mysqlx://" + session.Settings.UserID + ":" + session.Settings.Password + "@" + session.Settings.Server + ":" + XPort + "?connect-timeout=10000;"; + using (var conn = MySQLX.GetSession(connStr)) + { + conn.SQL("SELECT SLEEP(10)").Execute(); + var res = conn.SQL("select @@port").Execute().FirstOrDefault(); + Assert.IsNotNull(res); + } + + var connObj = new + { + server = session.Settings.Server, + port = XPort, + user = session.Settings.UserID, + password = session.Settings.Password, + connecttimeout = 10000 + }; + using (var conn = MySQLX.GetSession(connObj)) + { + conn.SQL("SELECT SLEEP(10)").Execute(); + var res = conn.SQL("select @@port").Execute().FirstOrDefault(); + Assert.IsNotNull(res); + } + + var connStrBuilder = new MySqlXConnectionStringBuilder(); + connStrBuilder.ConnectTimeout = 10000; + connStrBuilder.UserID = session.Settings.UserID; + connStrBuilder.Password = session.Settings.Password; + connStrBuilder.Port = Convert.ToUInt32(XPort); + connStrBuilder.Server = session.Settings.Server; + using (var conn = MySQLX.GetSession(connStrBuilder.ConnectionString)) + { + conn.SQL("SELECT SLEEP(10)").Execute(); + var res = conn.SQL("select @@port").Execute().FirstOrDefault(); + Assert.IsNotNull(res); + } + + connStr = "server=" + session.Settings.Server + ";user=" + session.Settings.UserID + ";port=" + XPort + ";password=" + + session.Settings.Password + ";" + "connect-timeout=10000;"; + connStrBuilder = new MySqlXConnectionStringBuilder(connStr); + using (var conn = MySQLX.GetSession(connStrBuilder.ConnectionString)) + { + conn.SQL("SELECT SLEEP(10)").Execute(); + var res = conn.SQL("select @@port").Execute().FirstOrDefault(); + Assert.IsNotNull(res); + } + + connStr = ConnectionString + ";protocol=Socket;" + + "database=" + schemaName + ";characterset=utf8mb4;sslmode=Required;ssl-ca=" + + sslCa + $";certificatepassword={sslCertificatePassword};certificatestorelocation=LocalMachine;" + + ";keepalive =10;auth=PLAIN;certificatethumbprint=;" + + "connect-timeout=" + 10000; + var mysqlx0 = new MySqlXConnectionStringBuilder(connStr); + using (var conn = MySQLX.GetSession(mysqlx0.ConnectionString)) + { + conn.SQL("SELECT SLEEP(10)").Execute(); + var res = conn.SQL("select @@port").Execute().FirstOrDefault(); + Assert.IsNotNull(res); + } + + mysqlx0 = new MySqlXConnectionStringBuilder(); + mysqlx0.UserID = session.Settings.UserID; + mysqlx0.Password = session.Settings.Password; + mysqlx0.Port = Convert.ToUInt32(XPort); + mysqlx0.Server = session.Settings.Server; + mysqlx0.ConnectionProtocol = MySqlConnectionProtocol.Tcp; + mysqlx0.Database = schemaName; + mysqlx0.CharacterSet = "utf8mb4"; + mysqlx0.SslMode = MySqlSslMode.Required; + mysqlx0.SslCa = sslCa; + mysqlx0.CertificatePassword = sslCertificatePassword; + mysqlx0.CertificateStoreLocation = MySqlCertificateStoreLocation.LocalMachine; + mysqlx0.Keepalive = 10; + mysqlx0.Auth = MySqlAuthenticationMode.PLAIN; + mysqlx0.CertificateThumbprint = ""; + mysqlx0.ConnectTimeout = (uint)10000; + + using (var conn = MySQLX.GetSession(mysqlx0.ConnectionString)) + { + conn.SQL("SELECT SLEEP(10)").Execute(); + var res = conn.SQL("select @@port").Execute().FirstOrDefault(); + Assert.IsNotNull(res); + } + } + + [Test, Description("Test that if an unexpected error occurs during the specified time frame, the execution should stop and the error must be reported to the user")] + public void WrongPasswordException() + { + string connStr = null; + string password = "wrongpassword"; + Object[] ConnectTimeout = new Object[] { 10000 }; + for (int i = 0; i < ConnectTimeout.Length; i++) + { + // Connection String + connStr = "server=" + session.Settings.Server + ";user=" + session.Settings.UserID + ";port=" + XPort + ";password=" + + password + ";" + "connect-timeout=" + ConnectTimeout[i]; + Assert.Throws(() => MySQLX.GetSession(connStr)); + //String Builder + var connStrBuilder = new MySqlXConnectionStringBuilder(connStr); + Assert.Throws(() => MySQLX.GetSession(connStrBuilder.ConnectionString)); + // Uri + connStr = "mysqlx://" + session.Settings.UserID + ":" + password + "@" + session.Settings.Server + ":" + XPort + "?connect-timeout=" + ConnectTimeout[i]; + Assert.Throws(() => MySQLX.GetSession(connStr)); + // Anonymous Object + var connObj = new { server = session.Settings.Server, port = XPort, user = session.Settings.UserID, password = password, connecttimeout = ConnectTimeout[i] }; + Assert.Throws(() => MySQLX.GetSession(connStr)); + } + } + + [Test, Description("Test the default connect timeout with offline server with concurrent connections")] + [Ignore("Test its not well implemented")] // TO DO + public async Task ConnectTimeoutConcurrentConnections() + { + await Task.Run(() => SubThread1()); + await Task.Run(() => SubThread2()); + } + + private void SubThread1() + { + string serverName = "vigdis07.no.oracle.com"; + for (int i = 0; i < 5; i++) + { + string connStr = "server=" + serverName + ";user=" + session.Settings.UserID + ";port=" + XPort + ";password=" + + session.Settings.Password + ";" + "connect-timeout=2000;"; + TestConnectStringTimeoutFailureTimeout(connStr, 0, 5, "Timeout value between 1 and 3 second"); + } + } + + private void SubThread2() + { + string serverName = "vigdis07.no.oracle.com"; + for (int i = 0; i < 5; i++) + { + string connStr = "server=" + serverName + ";user=" + session.Settings.UserID + ";port=" + XPort + ";password=" + + session.Settings.Password + ";" + "connect-timeout=2000;"; + TestConnectStringTimeoutFailureTimeout(connStr, 0, 5, "Timeout value between 1 and 3 second"); + } + } + + + [Test, Description("CONNECT-TIMEOUT WORKS WITH BLANK VALUES FOR CONNECTION STRING AND URI")] + public void ConnectTimeoutBlankValues() + { + var connObj = new { server = session.Settings.Server, port = XPort, user = session.Settings.UserID, password = session.Settings.Password, connecttimeout = "" }; + Assert.Throws(() => MySQLX.GetSession(connObj)); + + connObj = new { server = session.Settings.Server, port = XPort, user = session.Settings.UserID, password = session.Settings.Password, connecttimeout = " " }; + Assert.Throws(() => MySQLX.GetSession(connObj)); + + var connStr = $"server={session.Settings.Server};user={session.Settings.UserID};port={XPort};password={session.Settings.Password};connect-timeout=''"; + Assert.Throws(() => MySQLX.GetSession(connStr)); + + connStr = $"server={session.Settings.Server};user={session.Settings.UserID};port={XPort};password={session.Settings.Password};connect-timeout=' '"; + Assert.Throws(() => MySQLX.GetSession(connStr)); + + connStr = $"server={session.Settings.Server};user={session.Settings.UserID};port={XPort};password={session.Settings.Password};connect-timeout="; + Assert.Throws(() => MySQLX.GetSession(connStr)); + + connStr = $"server={session.Settings.Server};user={session.Settings.UserID};port={XPort};password={session.Settings.Password};connect-timeout= "; + Assert.Throws(() => MySQLX.GetSession(connStr)); + + connStr = $"mysqlx://{session.Settings.UserID}:{session.Settings.Password}@{session.Settings.Server}:{XPort}?connect-timeout="; + Assert.Throws(() => MySQLX.GetSession(connStr)); + + connStr = $"mysqlx://{session.Settings.UserID}:{session.Settings.Password}@{session.Settings.Server}:{XPort}?connect-timeout= "; + Assert.Throws(() => MySQLX.GetSession(connStr)); + } + + /// + /// Bug28624010 + /// + [Test, Description("CONNECTIONTIMEOUT OPT WORKS WITH XPLUGN IF A CLASSIC CONN IS ESTABLISD")] + public void TimeoutWithClassicConnection() + { + int connectionTimeout = 10; + var connStr1 = $"server={session.Settings.Server};user={session.Settings.UserID};port={Port};password={session.Settings.Password};sslmode={MySqlSslMode.Required}"; + var conn = new MySqlConnection(connStr1); + conn.Open(); + conn.Close(); + var connStr = $"server={session.Settings.Server};user={session.Settings.UserID};port={XPort};password={session.Settings.Password};connectiontimeout={connectionTimeout}"; + Assert.Throws(() => MySQLX.GetSession(connStr)); + + connStr = $"mysqlx://{session.Settings.UserID}:{session.Settings.Password}@{session.Settings.Server}:{XPort}?connectiontimeout={connectionTimeout} "; + Assert.Throws(() => MySQLX.GetSession(connStr)); + + var connObj = new { server = session.Settings.Server, port = XPort, user = session.Settings.UserID, password = session.Settings.Password, connectiontimeout = connectionTimeout }; + Assert.Throws(() => MySQLX.GetSession(connObj)); + } + + [Test, Description("MySQLX Session Stress test")] + public void SessionStressTest() + { + for (int i = 0; i < 1000; i++) + { + using (Session session1 = MySQLX.GetSession(ConnectionString)) + { + Assert.AreEqual(SessionState.Open, session1.InternalSession.SessionState); + session1.Close(); + } + } + } + + [Test, Description("Getsession using Anonymous Type-Positive")] + public void GetSessionAnonymousTypePositiveStress() + { + for (int i = 0; i < 200; i++) + { + var connectionStringObject = new { connection = $"server={Host};user={session.Settings.UserID};port={XPort};password={session.Settings.Password};sslmode={MySqlSslMode.Required};" }; + using (Session sessionPlain = MySQLX.GetSession(connectionStringObject.connection)) + { + var db = sessionPlain.GetSchema(schemaName); + var col = CreateCollection("my_collection_123456789"); + sessionPlain.Close(); + } + } + } + + [Test, Description("Test Audit Plugin")] + public void SessionAuditPluginTest() + { + using (var mysqlx = MySQLX.GetSession(ConnectionString)) + { + Assert.AreEqual(SessionState.Open, mysqlx.InternalSession.SessionState); + mysqlx.Close(); + } + using (var mysql = new MySqlConnection($"server={Host};user={session.Settings.UserID};port={Port};password={session.Settings.Password}")) + { + mysql.Open(); + Assert.AreEqual(ConnectionState.Open, mysql.connectionState); + mysql.Close(); + } + Assert.Throws(() => MySQLX.GetSession($"server={Host};user={session.Settings.UserID};port={XPort};password=wrong")); + } + + [Test, Description("Classic Client with xprotocol server")] + public void ClassicClientXProtocol() + { + if (!Platform.IsWindows()) Assert.Ignore("This test is for Windows OS only"); + if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher"); + + string connectionString = $"server={Host};user={session.Settings.UserID};port={XPort};password={session.Settings.Password}"; + using (var session1 = new MySqlConnection(connectionString)) + { + Exception ex = Assert.Throws(() => session1.Open()); + Assert.AreEqual("Unsupported protocol version.", ex.Message); + } + } + + #region Methods + + public void TestConnectObjectTimeoutSuccessTimeout(object connString, int minTime, int maxTime, string test) + { + Stopwatch sw = new Stopwatch(); + sw.Start(); + var conn = MySQLX.GetSession(connString); + sw.Stop(); + Assert.True(sw.Elapsed.Seconds >= minTime && sw.Elapsed.Seconds <= maxTime, String.Format("Timeout exceeded ({0}). Actual time: {1}", test, sw.Elapsed)); + } + + public void TestConnectStringTimeoutSuccessTimeout(String connString, int minTime, int maxTime, string test) + { + Stopwatch sw = new Stopwatch(); + sw.Start(); + var conn = MySQLX.GetSession(connString); + sw.Stop(); + Assert.True(sw.Elapsed.Seconds >= minTime && sw.Elapsed.Seconds <= maxTime, String.Format("Timeout exceeded ({0}). Actual time: {1}", test, sw.Elapsed)); + } + + public void TestConnectObjTimeoutFailureTimeout(object connString, int minTime, int maxTime, string test) + { + Stopwatch sw = new Stopwatch(); + sw.Start(); + Assert.Catch(() => MySQLX.GetSession(connString)); + sw.Stop(); + Assert.True(sw.Elapsed.Seconds >= minTime && sw.Elapsed.Seconds < maxTime, String.Format("Timeout exceeded ({0}). Actual time: {1}", test, sw.Elapsed)); + } + + public void TestConnectStringTimeoutFailureTimeout(String connString, int minTime, int maxTime, string test) + { + Stopwatch sw = new Stopwatch(); + sw.Start(); + Assert.Catch(() => MySQLX.GetSession(connString)); + sw.Stop(); + Assert.True(sw.Elapsed.Seconds >= minTime && sw.Elapsed.Seconds < maxTime, String.Format("Timeout exceeded ({0}). Actual time: {1}", test, sw.Elapsed)); + } + + public void TestClientQueueTimeout(Client client, int minTime, int maxTime, string test) + { + Stopwatch sw = new Stopwatch(); + sw.Start(); + Assert.Throws(() => client.GetSession()); + sw.Stop(); + Assert.True(sw.Elapsed.Seconds >= minTime && sw.Elapsed.Seconds < maxTime, + String.Format("Timeout exceeded ({0}). Actual time: {1}", test, sw.Elapsed)); + } + + public void TestClientSuccessTimeout(int minTime, int maxTime, string test, string connectionString, object poolingObject) + { + using (var client = MySQLX.GetClient(connectionString, poolingObject)) + { + Stopwatch sw = new Stopwatch(); + sw.Start(); + client.GetSession(); + sw.Stop(); + Assert.True(sw.Elapsed.Seconds >= minTime && sw.Elapsed.Seconds < maxTime, String.Format("Timeout exceeded ({0}). Actual time: {1}", test, sw.Elapsed)); + } + } + + public void TestClientSuccessTimeout(int minTime, int maxTime, string test, object connectionObject, object poolingObject) + { + using (var client = MySQLX.GetClient(connectionObject, poolingObject)) + { + Stopwatch sw = new Stopwatch(); + sw.Start(); + client.GetSession(); + sw.Stop(); + Assert.True(sw.Elapsed.Seconds >= minTime && sw.Elapsed.Seconds < maxTime, String.Format("Timeout exceeded ({0}). Actual time: {1}", test, sw.Elapsed)); + } + } + public void TestFailureTimeout(Client client, int minTime, int maxTime, string test) + { + DateTime start = DateTime.Now; + Assert.Catch(() => client.GetSession()); + TimeSpan diff = DateTime.Now.Subtract(start); + Assert.True(diff.TotalSeconds >= minTime && diff.TotalSeconds < maxTime, String.Format("Timeout exceeded ({0}). Actual time: {1}", test, diff)); + } + + private void MeasureConnectionString(string connStr, int maxTime, string test, int iteration) + { + Stopwatch sw = new Stopwatch(); + sw.Start(); + + for (int i = 0; i < iteration; i++) + { + using Session conn = MySQLX.GetSession(connStr); + } + + sw.Stop(); + Assert.True(sw.Elapsed.Seconds < maxTime, String.Format("Timeout exceeded ({0}). Actual time: {1}", test, sw.Elapsed)); + } + + private void MeasureConnectionObject(object connStr, int maxTime, string test, int iteration) + { + Stopwatch sw = new Stopwatch(); + sw.Start(); + + for (int i = 0; i < iteration; i++) + { + using Session conn = MySQLX.GetSession(connStr); + } + + sw.Stop(); + Assert.True(sw.Elapsed.Seconds < maxTime, String.Format("Timeout exceeded ({0}). Actual time: {1}", test, sw.Elapsed)); + } + + public long NanoTime() + { + long nano = 10000L * Stopwatch.GetTimestamp(); + nano /= TimeSpan.TicksPerMillisecond; + nano *= 100L; + return nano; + } + + public long DoConnectString(string connectionString) + { + long queryStartTime, queryRunTime = 0; + queryStartTime = NanoTime(); + var session = MySQLX.GetSession(connectionString); + queryRunTime = NanoTime() - queryStartTime; + session.Close(); + session.Dispose(); + return queryRunTime; + } + + public long DoConnectObject(object connectionString) + { + long queryStartTime, queryRunTime = 0; + queryStartTime = NanoTime(); + var session = MySQLX.GetSession(connectionString); + queryRunTime = NanoTime() - queryStartTime; + session.Close(); + session.Dispose(); + return queryRunTime; + } + + /// + /// Calculate the Connection per second + /// Total execution time.(Connection+query execution time) + /// Query execution time + public float CalculateTPS(long elapsedTime, long transactions) + { + float tps = 0; + if (elapsedTime > 0.0) + { + tps = (float)transactions / elapsedTime; + tps = tps * 1000; + } + return tps; + } + + #endregion Methods + + } +} diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/SslTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/SslTests.cs index f445b4cc9..f52be59cc 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/SslTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/SslTests.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2018, 2022, Oracle and/or its affiliates. +// Copyright © 2018, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the @@ -1544,4 +1544,4 @@ public void SslRequiredAndDisabled() Assert.AreEqual(SessionState.Open, sessionUriRequired.InternalSession.SessionState); } } -} \ No newline at end of file +} diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/TransactionTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/TransactionTests.cs index 03394d22a..bcd4d6266 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/TransactionTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/TransactionTests.cs @@ -1,996 +1,996 @@ -// Copyright (c) 2015, 2023, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySql.Data.MySqlClient; -using MySqlX.XDevAPI; -using MySqlX.XDevAPI.Common; -using MySqlX.XDevAPI.CRUD; -using MySqlX.XDevAPI.Relational; -using NUnit.Framework; -using System; -using System.Linq; - -namespace MySqlX.Data.Tests -{ - public class TransactionTests : BaseTest - { - private string collName = "collSp"; - - [TearDown] - public void TearDown() => session.Schema.DropCollection(collName); - - [Test] - public void Commit() - { - Collection coll = CreateCollection("test"); - var docs = new[] - { - new { _id = 1, title = "Book 1", pages = 20 }, - new { _id = 2, title = "Book 2", pages = 30 }, - new { _id = 3, title = "Book 3", pages = 40 }, - new { _id = 4, title = "Book 4", pages = 50 }, - }; - - // start the transaction - coll.Session.StartTransaction(); - - Result r = ExecuteAddStatement(coll.Add(docs)); - Assert.AreEqual(4, r.AffectedItemsCount); - - // now roll it back - coll.Session.Commit(); - - var foundDocs = ExecuteFindStatement(coll.Find()); - Assert.True(foundDocs.Next()); - Assert.True(foundDocs.Next()); - Assert.True(foundDocs.Next()); - Assert.True(foundDocs.Next()); - Assert.False(foundDocs.Next()); - } - - [Test] - public void Rollback() - { - Collection coll = CreateCollection("test"); - var docs = new[] - { - new { _id = 1, title = "Book 1", pages = 20 }, - new { _id = 2, title = "Book 2", pages = 30 }, - new { _id = 3, title = "Book 3", pages = 40 }, - new { _id = 4, title = "Book 4", pages = 50 }, - }; - - // start the transaction - coll.Session.StartTransaction(); - - Result r = ExecuteAddStatement(coll.Add(docs)); - Assert.AreEqual(4, r.AffectedItemsCount); - - // now roll it back - coll.Session.Rollback(); - - var foundDocs = ExecuteFindStatement(coll.Find()); - Assert.False(foundDocs.Next()); - } - - #region Savepoints - - [Test] - public void CreateUnnamedSavepoint() - { - using (var session = MySQLX.GetSession(ConnectionString)) - { - session.StartTransaction(); - - string spName = session.SetSavepoint(); - Assert.False(string.IsNullOrWhiteSpace(spName)); - - session.Rollback(); - } - } - - [Test] - public void RollbackToSavepoint() - { - using (var session = MySQLX.GetSession(ConnectionString)) - { - var schema = session.GetSchema("test"); - schema.DropCollection("collSP"); - var coll = schema.CreateCollection("collSP"); - - session.StartTransaction(); - - ExecuteAddStatement(coll.Add("{ \"test\": \"test\" }")); - var sp = session.SetSavepoint(); - ExecuteAddStatement(coll.Add("{ \"test\": \"test\" }")); - Assert.AreEqual(2, ExecuteFindStatement(coll.Find()).FetchAll().Count); - session.RollbackTo(sp); - Assert.That(ExecuteFindStatement(coll.Find()).FetchAll(), Has.One.Items); - - session.Rollback(); - } - } - - [Test] - public void ReleaseSavepoint() - { - using (var sessionTest = MySQLX.GetSession(ConnectionString)) - { - var coll = CreateCollection("test"); - sessionTest.StartTransaction(); - ExecuteAddStatement(coll.Add("{ \"test\": \"test\" }")); - var sp = sessionTest.SetSavepoint(); - ExecuteAddStatement(coll.Add("{ \"test2\": \"test2\" }")); - Assert.AreEqual(2, ExecuteFindStatement(coll.Find()).FetchAll().Count); - sessionTest.ReleaseSavepoint(sp); - Assert.AreEqual(2, ExecuteFindStatement(coll.Find()).FetchAll().Count); - sessionTest.Rollback(); - } - } - - [Test] - public void CreateNamedSavepoint() - { - using (var session = MySQLX.GetSession(ConnectionString)) - { - session.StartTransaction(); - - string spName = session.SetSavepoint("mySavedPoint"); - Assert.False(string.IsNullOrWhiteSpace(spName)); - - session.Rollback(); - } - } - - [Test] - public void RollbackToNamedSavepoint() - { - using (var session = MySQLX.GetSession(ConnectionString)) - { - var schema = session.GetSchema("test"); - schema.DropCollection("collSP"); - var coll = schema.CreateCollection("collSP"); - session.StartTransaction(); - ExecuteAddStatement(coll.Add("{ \"test\": \"test\" }")); - var sp = session.SetSavepoint("mySavedPoint"); - ExecuteAddStatement(coll.Add("{ \"test2\": \"test2\" }")); - Assert.AreEqual(2, ExecuteFindStatement(coll.Find()).FetchAll().Count); - session.RollbackTo(sp); - Assert.That(ExecuteFindStatement(coll.Find()).FetchAll(), Has.One.Items); - session.Rollback(); - } - } - - [Test] - public void ReleaseNamedSavepoint() - { - using (var session = MySQLX.GetSession(ConnectionString)) - { - var schema = session.GetSchema("test"); - schema.DropCollection("test"); - var coll = schema.CreateCollection("test"); - session.StartTransaction(); - ExecuteAddStatement(coll.Add("{ \"test\": \"test\" }")); - var sp = session.SetSavepoint("mySavedPoint"); - ExecuteAddStatement(coll.Add("{ \"test2\": \"test2\" }")); - Assert.AreEqual(2, ExecuteFindStatement(coll.Find()).FetchAll().Count); - session.ReleaseSavepoint(sp); - Assert.AreEqual(2, ExecuteFindStatement(coll.Find()).FetchAll().Count); - session.Rollback(); - } - } - - [Test] - public void NonExistentSavepoint() - { - using (var session = MySQLX.GetSession(ConnectionString)) - { - session.StartTransaction(); - - Exception exception = Assert.Throws(() => session.RollbackTo("nonExistentSavePoint")); - Assert.AreEqual("SAVEPOINT nonExistentSavePoint does not exist", exception.Message); - - exception = Assert.Throws(() => session.ReleaseSavepoint("nonExistentSavePoint")); - Assert.AreEqual("SAVEPOINT nonExistentSavePoint does not exist", exception.Message); - - session.Rollback(); - } - } - - [Test] - public void CreateSavepointWithWeirdNames() - { - using (var session = MySQLX.GetSession(ConnectionString)) - { - string errorMessage = "You have an error in your SQL syntax"; - session.StartTransaction(); - - Exception ex = Assert.Throws(() => session.SetSavepoint("")); - StringAssert.StartsWith(errorMessage, ex.Message); - ex = Assert.Throws(() => session.SetSavepoint(" ")); - StringAssert.StartsWith(errorMessage, ex.Message); - ex = Assert.Throws(() => session.SetSavepoint(null)); - StringAssert.StartsWith(errorMessage, ex.Message); - ex = Assert.Throws(() => session.SetSavepoint("-")); - StringAssert.StartsWith(errorMessage, ex.Message); - ex = Assert.Throws(() => session.SetSavepoint("mysp+")); - StringAssert.StartsWith(errorMessage, ex.Message); - ex = Assert.Throws(() => session.SetSavepoint("3306")); - StringAssert.StartsWith(errorMessage, ex.Message); - - var sp = session.SetSavepoint("_"); - session.RollbackTo(sp); - sp = session.SetSavepoint("mysql3306"); - session.RollbackTo(sp); - - session.Rollback(); - } - } - - [Test] - public void OverwriteSavepoint() - { - using (var session = MySQLX.GetSession(ConnectionString)) - { - var schema = session.GetSchema("test"); - var coll = schema.CreateCollection(collName); - - session.StartTransaction(); - - ExecuteAddStatement(coll.Add("{ \"test\": \"test\" }")); - var sp = session.SetSavepoint("mySP"); - ExecuteAddStatement(coll.Add("{ \"test2\": \"test2\" }")); - sp = session.SetSavepoint("mySP"); - ExecuteAddStatement(coll.Add("{ \"test3\": \"test3\" }")); - sp = session.SetSavepoint("mySP"); - ExecuteAddStatement(coll.Add("{ \"test4\": \"test4\" }")); - sp = session.SetSavepoint("mySP"); - session.RollbackTo(sp); - Assert.AreEqual(4, ExecuteFindStatement(coll.Find()).FetchAll().Count); - - session.Rollback(); - } - } - - [Test] - public void MultipleReleasesForSavepoint() - { - using (var session = MySQLX.GetSession(ConnectionString)) - { - session.StartTransaction(); - - var sp = session.SetSavepoint("mySP"); - session.ReleaseSavepoint(sp); - Exception exception = Assert.Throws(() => session.ReleaseSavepoint(sp)); - Assert.AreEqual(string.Format("SAVEPOINT {0} does not exist", sp), exception.Message); - - session.Rollback(); - } - } - - [Test] - public void RollbackAndReleaseAfterTransactionCommit() - { - using (var sessionTest = MySQLX.GetSession(ConnectionString)) - { - var coll = CreateCollection("collSP"); - sessionTest.StartTransaction(); - var sp = sessionTest.SetSavepoint("mySP"); - ExecuteAddStatement(coll.Add("{ \"test\": \"test\" }")); - sessionTest.Commit(); - Exception exception = Assert.Throws(() => sessionTest.RollbackTo(sp)); - Assert.AreEqual(string.Format("SAVEPOINT {0} does not exist", sp), exception.Message); - exception = Assert.Throws(() => sessionTest.ReleaseSavepoint(sp)); - Assert.AreEqual(string.Format("SAVEPOINT {0} does not exist", sp), exception.Message); - } - } - - [Test] - public void RollbackAndReleaseAfterTransactionRollback() - { - using (var sessionTest = MySQLX.GetSession(ConnectionString)) - { - var coll = CreateCollection("collSP"); - sessionTest.StartTransaction(); - - var sp = sessionTest.SetSavepoint("mySP"); - ExecuteAddStatement(coll.Add("{ \"test\": \"test\" }")); - - sessionTest.Rollback(); - - Exception exception = Assert.Throws(() => sessionTest.RollbackTo(sp)); - Assert.AreEqual(string.Format("SAVEPOINT {0} does not exist", sp), exception.Message); - - exception = Assert.Throws(() => sessionTest.ReleaseSavepoint(sp)); - Assert.AreEqual(string.Format("SAVEPOINT {0} does not exist", sp), exception.Message); - } - } - - #endregion - - #region WL14389 - - [Test, Description("Session Close Transaction")] - public void SessionCloseTransaction() - { - if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher."); - using (Session sessionTest = MySQLX.GetSession(ConnectionString)) - { - Schema db = null; - db = sessionTest.GetSchema("test"); - sessionTest.StartTransaction(); - - if (db.GetCollection("my_collection_1").ExistsInDatabase()) - { - db.DropCollection("my_collection_1"); - } - Collection col = db.CreateCollection("my_collection_1"); - sessionTest.Close(); - Assert.Throws(() => sessionTest.Rollback()); - } - } - - [Test, Description("Valid Commit and Check Warning ")] - public void CommitValidWarning() - { - if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher."); - using (Session sessionPlain = MySQLX.GetSession(ConnectionString)) - { - sessionPlain.SetCurrentSchema("test"); - sessionPlain.SQL("drop table if exists temp").Execute(); - sessionPlain.SQL("CREATE TABLE temp(id INT primary key)").Execute(); - Table table = sessionPlain.Schema.GetTable("temp"); - sessionPlain.StartTransaction(); - table.Insert().Values(5).Execute(); - sessionPlain.Commit(); - Assert.AreEqual(1, table.Count()); - } - } - - /// - /// Bug 23542005 - /// - [Test, Description("Invalid Commit and Check Warning ")] - public void CommitInvalidWarning() - { - if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher."); - using (Session sessionPlain = MySQLX.GetSession(ConnectionString)) - { - sessionPlain.SetCurrentSchema("test"); - sessionPlain.SQL("CREATE TABLE temp(v VARCHAR(4))").Execute(); - Table table = sessionPlain.Schema.GetTable("temp"); - sessionPlain.StartTransaction(); - Assert.Throws(() => sessionPlain.GetSchema("test").GetTable("temp").Insert().Values("abcdef").Execute()); - sessionPlain.Commit(); - Assert.AreEqual(0, table.Count()); - var warnings = sessionPlain.SQL("DROP TABLE IF EXISTS temp1").Execute().Warnings; - Assert.IsTrue(warnings.Count > 0); - sessionPlain.Commit(); - } - } - - - [Test, Description("Valid Rollback and Check Warning ")] - public void RollbackValidWarning() - { - if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher."); - using (Session sessionPlain = MySQLX.GetSession(ConnectionString)) - { - sessionPlain.SetCurrentSchema("test"); - sessionPlain.SQL("DROP TABLE IF EXISTS temp").Execute(); - sessionPlain.SQL("CREATE TABLE temp(id INT primary key)").Execute(); - Table table = sessionPlain.Schema.GetTable("temp"); - sessionPlain.StartTransaction(); - var res = table.Insert().Values(5).Execute(); - sessionPlain.Rollback(); - Assert.AreEqual(0, table.Count()); - Assert.AreEqual(0, res.Warnings.Count); - } - } - - /// - /// Bug 23542005 - /// - [Test, Description("Invalid Rollback and Check Warning ")] - public void RollbackInvalidWarning() - { - if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher."); - using (Session sessionPlain = MySQLX.GetSession(ConnectionString)) - { - sessionPlain.SetCurrentSchema("test"); - sessionPlain.SQL("DROP TABLE IF EXISTS temp").Execute(); - sessionPlain.SQL("CREATE TABLE temp(v VARCHAR(4))").Execute(); - Table table = sessionPlain.Schema.GetTable("temp"); - sessionPlain.StartTransaction(); - Assert.Throws(() => sessionPlain.GetSchema("test").GetTable("temp").Insert().Values("abcdef").Execute()); - sessionPlain.Rollback(); - Assert.AreEqual(0, table.Count()); - var res = sessionPlain.SQL("DROP TABLE IF EXISTS temp1").Execute(); - Assert.IsTrue(res.Warnings.Count > 0); - } - } - - /// - /// Bug 23542005 - /// - [Test, Description("Commit Rollback Invalid Warning")] - public void CommitRollbackInvalidWarning() - { - if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher."); - Collection coll = CreateCollection("test"); - var docs1 = new[] - { - new { _id = 1, title = "Book 1", pages = 20 }, - new { _id = 2, title = "Book 2", pages = 30 }, - }; - - var docs2 = new[] - { - new { _id = 3, title = "Book 3", pages = 40 }, - new { _id = 4, title = "Book 4", pages = 50 }, - }; - - var docs3 = new[] - - { - new { _id = 5, title = "Book 5", pages = 60 }, - new { _id = 6, title = "Book 6", pages = 70 }, - }; - - // start the transaction - coll.Session.StartTransaction(); - - Result r = coll.Add(docs1).Execute(); - Assert.AreEqual(2, r.AffectedItemsCount); - - r = coll.Add(docs2).Execute(); - Assert.AreEqual(2, r.AffectedItemsCount); - - r = coll.Add(docs3).Execute(); - Assert.Throws(() => coll.Add(docs3).Execute()); - coll.Session.Commit(); - Assert.AreEqual(6, coll.Count()); - // now Rollback - coll.Session.Rollback(); - Assert.AreEqual(6, coll.Count()); - - var foundDocs = coll.Find().Execute(); - Assert.IsNotNull(foundDocs); - } - - [Test, Description("MySQLX plugin Warnings")] - public void Warnings() - { - if (!session.Version.isAtLeast(8, 0, 0)) return; - using (Session sessionTest = MySQLX.GetSession(ConnectionString)) - { - Schema schema = sessionTest.GetSchema("test"); - Collection coll = CreateCollection("test"); - - Result r = coll.Add("{ \"foo\": 1 }").Execute(); - Assert.AreEqual(1, r.AffectedItemsCount); - Assert.AreEqual(1, coll.Count()); - r = coll.Add("{ \"fool\": 2 }").Execute(); - Assert.AreEqual(0, r.Warnings.Count); - r = coll.Add("{ \"fool\": 10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 }").Execute(); - Assert.AreEqual(0, r.Warnings.Count); - - sessionTest.SQL("use test").Execute(); - sessionTest.SQL("CREATE TABLE nontrac(id INT primary key) ENGINE=MyISAM;").Execute(); - Table table = schema.GetTable("nontrac"); - sessionTest.StartTransaction(); - table.Insert().Values(5).Execute(); - - schema = sessionTest.GetSchema(schemaName); - sessionTest.StartTransaction(); - - var res = sessionTest.SQL("drop table if exists t1, t2").Execute(); - Assert.AreEqual(2, res.Warnings.Count); - Assert.AreEqual(1051, res.Warnings[0].Code); - - Assert.AreEqual(1051, res.Warnings[1].Code); - - res = sessionTest.SQL("create table t1 (a int) engine=innodb").Execute(); - Assert.AreEqual(0, res.Warnings.Count); - res = sessionTest.SQL("create table t2 (a int) engine=myisam").Execute(); - Assert.AreEqual(0, res.Warnings.Count); - res = sessionTest.SQL("insert into t1 values(1)").Execute(); - Assert.AreEqual(0, res.Warnings.Count); - res = sessionTest.SQL("insert into t2 select * from t1").Execute(); - Assert.AreEqual(1, res.Warnings.Count); - sessionTest.Commit(); - - } - } - - //Savepoints - [Test, Description("Rollback to same savepoint multiple times")] - public void RollbackToSameSavepoint() - { - if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher."); - - var col = CreateCollection("my_collection"); - session.StartTransaction(); - object[] data = new object[] - { - new { _id = 1, title = "Book 1", pages = 30 }, - new { _id = 2, title = "Book 2", pages = 50 }, - }; - Result result = col.Add(data).Execute(); - var sp = session.SetSavepoint("SavePoint1"); - data = new object[] - { - new { _id = 3, title = "Book 3", pages = 30 }, - new { _id = 4, title = "Book 4", pages = 50 }, - }; - result = col.Add(data).Execute(); - var sp1 = session.SetSavepoint("SavePoint2"); - - session.RollbackTo(sp); - data = new object[] - { - new { _id = 5, title = "Book 5", pages = 30 }, - new { _id = 6, title = "Book 6", pages = 50 }, - }; - result = col.Add(data).Execute(); - session.RollbackTo(sp); - var doc = col.Find().Execute(); - var docs = doc.FetchAll().Count(); - Assert.AreEqual(2, docs); - } - - - [Test, Description("Releasing a savepoint multiple times")] - public void ReleaseSavepointMoreThanOnce() - { - if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher."); - using (Session sessionTest = MySQLX.GetSession(ConnectionString)) - { - var col = CreateCollection("my_collection"); - sessionTest.StartTransaction(); - object[] data = new object[] - { - new { _id = 1, title = "Book 1", pages = 30 }, - new { _id = 2, title = "Book 2", pages = 50 }, - }; - Result result = col.Add(data).Execute(); - var sp = sessionTest.SetSavepoint("SavePoint1"); - data = new object[] - { - new { _id = 3, title = "Book 3", pages = 30 }, - new { _id = 4, title = "Book 4", pages = 50 }, - }; - result = col.Add(data).Execute(); - sessionTest.ReleaseSavepoint(sp); - data = new object[] - { - new { _id = 5, title = "Book 5", pages = 30 }, - new { _id = 6, title = "Book 6", pages = 50 }, - }; - result = col.Add(data).Execute(); - var ex = Assert.Throws(() => sessionTest.ReleaseSavepoint(sp)); - sessionTest.Rollback(); - } - } - - [TestCase("Savepoint1", "Savepoint2")] - [TestCase("", "")] - [Description("Creating multiple savepoints with SetSavepoint([name]) and rolling back to a specific one")] - public void MultipleSavepointsAndRollback(string savePoint1, string savePoint2) - { - if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher."); - var col = CreateCollection("my_collection"); - session.StartTransaction(); - object[] data = new object[] - { - new { _id = 1, title = "Book 1", pages = 30 }, - new { _id = 2, title = "Book 2", pages = 50 }, - }; - Result result = col.Add(data).Execute(); - var sp = string.IsNullOrEmpty(savePoint1) ? session.SetSavepoint() : session.SetSavepoint(savePoint1); - data = new object[] - { - new { _id = 3, title = "Book 3", pages = 30 }, - new { _id = 4, title = "Book 4", pages = 50 }, - }; - result = col.Add(data).Execute(); - var sp2 = string.IsNullOrEmpty(savePoint2) ? session.SetSavepoint() : session.SetSavepoint(savePoint2); - session.RollbackTo(sp); - var doc = col.Find().Execute(); - var docs = doc.FetchAll().Count(); - Assert.AreEqual(2, docs); - } - - [Test, Description("Test creating a savepoint without starting a transaction")] - public void SavepointWithoutTransaction() - { - if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher."); - var col = CreateCollection("my_collection"); - object[] data = new object[] - { - new { _id = 1, title = "Book 1", pages = 30 }, - new { _id = 2, title = "Book 2", pages = 50 }, - }; - Result result = col.Add(data).Execute(); - var sp = ""; - sp = session.SetSavepoint("SP"); - data = new object[] - { - new { _id =3, title = "Book 3", pages = 30 }, - new { _id =4, title = "Book 4", pages = 50 }, - }; - result = col.Add(data).Execute(); - var sp1 = session.SetSavepoint("SP"); - Assert.Throws(() => session.ReleaseSavepoint(sp1)); - } - - [Test, Description("Validate that further savepoints get released once you release a preceding savepoint")] - public void ValidateSavepointsReleased() - { - if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher."); - var col = CreateCollection("my_collection"); - session.StartTransaction(); - - object[] data = new object[] - { - new { _id = 1, title = "Book 1", pages = 30 }, - new { _id = 2, title = "Book 2", pages = 50 }, - }; - Result result = col.Add(data).Execute(); - var sp = session.SetSavepoint("SavePoint1"); - data = new object[] - { - new { _id = 3, title = "Book 3", pages = 30 }, - new { _id = 4, title = "Book 4", pages = 50 }, - }; - result = col.Add(data).Execute(); - var sp1 = session.SetSavepoint("SavePoint2"); - session.ReleaseSavepoint(sp); - Assert.Throws(() => session.ReleaseSavepoint(sp1)); - - var doc = col.Find().Execute(); - var docs = doc.FetchAll().Count(); - Assert.AreEqual(4, docs); - - } - - - [Test, Description("Validate Nested-transactions with multiple savepoints")] - public void NestedTransactions() - { - if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher."); - var col = CreateCollection("my_collection"); - session.StartTransaction(); - object[] data = new object[] - { - new { _id = 1, title = "Book 1", pages = 30 }, - new { _id = 2, title = "Book 2", pages = 50 }, - }; - Result result = col.Add(data).Execute(); - var sp = session.SetSavepoint("Savepoint1"); - session.StartTransaction(); - - data = new object[] - { - new { _id = 3, title = "Book 3", pages = 30 }, - new { _id = 4, title = "Book 4", pages = 50 }, - }; - result = col.Add(data).Execute(); - var sp1 = session.SetSavepoint("Savepoint2"); - session.Rollback(); - var doc = col.Find().Execute(); - var docs = doc.FetchAll().Count(); - Assert.AreEqual(2, docs); - } - - [Test, Description("Test the behaviour of Savepoints created immediately after one another")] - public void SavepointsCreatedImmediately() - { - if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher."); - var col = CreateCollection("my_collection"); - session.StartTransaction(); - object[] data = new object[] - { - new { _id = 1, title = "Book 1", pages = 30 }, - new { _id = 2, title = "Book 2", pages = 50 }, - }; - Result result = col.Add(data).Execute(); - var sp = session.SetSavepoint("Savepoint1"); - var sp1 = session.SetSavepoint("Savepoint2"); - session.RollbackTo(sp); - var doc = col.Find().Execute(); - var docs = doc.FetchAll().Count(); - Assert.AreEqual(2, docs); - } - - [Test, Description("Test MySQLX plugin Commit After Commit")] - public void CommitAfterCommit() - { - if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher."); - Collection coll = CreateCollection("test"); - var docs1 = new[] - { - new { _id = 1, title = "Book 1", pages = 20 }, - new { _id = 2, title = "Book 2", pages = 30 }, - }; - - var docs2 = new[] - { - new { _id = 3, title = "Book 3", pages = 40 }, - new { _id = 4, title = "Book 4", pages = 50 }, - }; - - var docs3 = new[] - { - new { _id = 5, title = "Book 5", pages = 60 }, - new { _id = 6, title = "Book 6", pages = 70 }, - }; - - var docs4 = new[] - { - new { _id = 7, title = "Book 7", pages = 80 }, - new { _id = 8, title = "Book 8", pages = 90 }, - }; - - // start the transaction - coll.Session.StartTransaction(); - - Result r = coll.Add(docs1).Execute(); - Assert.AreEqual(2, r.AffectedItemsCount, "Matching"); - - r = coll.Add(docs2).Execute(); - Assert.AreEqual(2, r.AffectedItemsCount, "Matching"); - - r = coll.Add(docs3).Execute(); - Assert.AreEqual(2, r.AffectedItemsCount, "Matching"); - - // now Commit - coll.Session.Commit(); - // start the transaction - coll.Session.StartTransaction(); - r = coll.Add(docs4).Execute(); - Assert.AreEqual(2, r.AffectedItemsCount, "Matching"); - // now Commit Again - coll.Session.Commit(); - - var foundDocs = coll.Find().Execute(); - Assert.AreEqual(true, foundDocs.Next(), "Matching"); - Assert.AreEqual(true, foundDocs.Next(), "Matching"); - Assert.AreEqual(true, foundDocs.Next(), "Matching"); - Assert.AreEqual(true, foundDocs.Next(), "Matching"); - Assert.AreEqual(true, foundDocs.Next(), "Matching"); - Assert.AreEqual(true, foundDocs.Next(), "Matching"); - Assert.AreEqual(true, foundDocs.Next(), "Matching"); - Assert.AreEqual(true, foundDocs.Next(), "Matching"); - Assert.AreEqual(false, foundDocs.Next(), "Matching"); - - } - - [Test, Description("Test MySQLX plugin Rollback Multiple")] - public void RollBackMultiple() - { - if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher."); - Collection coll = CreateCollection("test"); - var docs1 = new[] - { - new { _id = 1, title = "Book 1", pages = 20 }, - new { _id = 2, title = "Book 2", pages = 30 }, - }; - - var docs2 = new[] - { - new { _id = 3, title = "Book 3", pages = 40 }, - new { _id = 4, title = "Book 4", pages = 50 }, - }; - - var docs3 = new[] - { - new { _id = 5, title = "Book 5", pages = 60 }, - new { _id = 6, title = "Book 6", pages = 70 }, - }; - - // start the transaction - coll.Session.StartTransaction(); - - Result r = coll.Add(docs1).Execute(); - Assert.AreEqual(2, r.AffectedItemsCount, "Matching"); - - r = coll.Add(docs2).Execute(); - Assert.AreEqual(2, r.AffectedItemsCount, "Matching"); - - r = coll.Add(docs3).Execute(); - Assert.AreEqual(2, r.AffectedItemsCount, "Matching"); - - // now Rollback - coll.Session.Rollback(); - - var foundDocs = coll.Find().Execute(); - Assert.AreEqual(false, foundDocs.Next(), "Matching"); - - } - - [Test, Description("Test MySQLX plugin Rollback after RollBack")] - public void RollBackAfterRollBack() - { - if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher."); - Collection coll = CreateCollection("test"); - var docs1 = new[] - { - new { _id = 1, title = "Book 1", pages = 20 }, - new { _id = 2, title = "Book 2", pages = 30 }, - }; - - var docs2 = new[] - { - new { _id = 3, title = "Book 3", pages = 40 }, - new { _id = 4, title = "Book 4", pages = 50 }, - }; - - var docs3 = new[] - { - new { _id = 5, title = "Book 5", pages = 60 }, - new { _id = 6, title = "Book 6", pages = 70 }, - }; - - var docs4 = new[] - { - new { _id = 7, title = "Book 7", pages = 80 }, - new { _id = 8, title = "Book 8", pages = 90 }, - }; - - // start the transaction - coll.Session.StartTransaction(); - - Result r = coll.Add(docs1).Execute(); - //WL11843-Core API v1 alignment Changes - Assert.AreEqual(2, r.AffectedItemsCount, "Matching"); - - r = coll.Add(docs2).Execute(); - Assert.AreEqual(2, r.AffectedItemsCount, "Matching"); - - r = coll.Add(docs3).Execute(); - Assert.AreEqual(2, r.AffectedItemsCount, "Matching"); - - // now Rollback - coll.Session.Rollback(); - - // start the transaction - coll.Session.StartTransaction(); - - r = coll.Add(docs4).Execute(); - Assert.AreEqual(2, r.AffectedItemsCount, "Matching"); - - // now Rollback Again - coll.Session.Rollback(); - - var foundDocs = coll.Find().Execute(); - Assert.AreEqual(false, foundDocs.Next(), "Matching"); - - } - - [Test, Description("Test MySQLX plugin Commit Rollback")] - public void CommitRollBack() - { - if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher."); - Collection coll = CreateCollection("test"); - var docs1 = new[] - { - new { _id = 1, title = "Book 1", pages = 20 }, - new { _id = 2, title = "Book 2", pages = 30 }, - }; - - var docs2 = new[] - { - new { _id = 3, title = "Book 3", pages = 40 }, - new { _id = 4, title = "Book 4", pages = 50 }, - }; - - var docs3 = new[] - { - new { _id = 5, title = "Book 5", pages = 60 }, - new { _id = 6, title = "Book 6", pages = 70 }, - }; - - // start the transaction - coll.Session.StartTransaction(); - - Result r = coll.Add(docs1).Execute(); - //WL11843-Core API v1 alignment Changes - Assert.AreEqual(2, r.AffectedItemsCount, "Matching"); - - r = coll.Add(docs2).Execute(); - Assert.AreEqual(2, r.AffectedItemsCount, "Matching"); - - r = coll.Add(docs3).Execute(); - Assert.AreEqual(2, r.AffectedItemsCount, "Matching"); - - //now Commit - coll.Session.Commit(); - // now Rollback - coll.Session.Rollback(); - - var foundDocs = coll.Find().Execute(); - Assert.AreEqual(true, foundDocs.Next(), "Matching"); - Assert.AreEqual(true, foundDocs.Next(), "Matching"); - Assert.AreEqual(true, foundDocs.Next(), "Matching"); - Assert.AreEqual(true, foundDocs.Next(), "Matching"); - Assert.AreEqual(true, foundDocs.Next(), "Matching"); - Assert.AreEqual(true, foundDocs.Next(), "Matching"); - Assert.AreEqual(false, foundDocs.Next(), "Matching"); - - } - - [Test, Description("Test MySQLX plugin RollBack Commit")] - public void RollBackCommit() - { - if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher."); - Collection coll = CreateCollection("test"); - var docs1 = new[] - { - new { _id = 1, title = "Book 1", pages = 20 }, - new { _id = 2, title = "Book 2", pages = 30 }, - }; - - var docs2 = new[] - { - new { _id = 3, title = "Book 3", pages = 40 }, - new { _id = 4, title = "Book 4", pages = 50 }, - }; - - var docs3 = new[] - { - new { _id = 5, title = "Book 5", pages = 60 }, - new { _id = 6, title = "Book 6", pages = 70 }, - }; - - // start the transaction - coll.Session.StartTransaction(); - Result r = coll.Add(docs1).Execute(); - Assert.AreEqual(2, r.AffectedItemsCount, "Matching"); - - // now Rollback - coll.Session.Rollback(); - r = coll.Add(docs2).Execute(); - Assert.AreEqual(2, r.AffectedItemsCount, "Matching"); - r = coll.Add(docs3).Execute(); - Assert.AreEqual(2, r.AffectedItemsCount, "Matching"); - //now Commit - coll.Session.Commit(); - var foundDocs = coll.Find().Execute(); - Assert.AreEqual(true, foundDocs.Next(), "Matching"); - Assert.AreEqual(true, foundDocs.Next(), "Matching"); - Assert.AreEqual(true, foundDocs.Next(), "Matching"); - Assert.AreEqual(true, foundDocs.Next(), "Matching"); - Assert.AreEqual(false, foundDocs.Next(), "Matching"); - - } - - #endregion - - } -} +// Copyright © 2015, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySql.Data.MySqlClient; +using MySqlX.XDevAPI; +using MySqlX.XDevAPI.Common; +using MySqlX.XDevAPI.CRUD; +using MySqlX.XDevAPI.Relational; +using NUnit.Framework; +using System; +using System.Linq; + +namespace MySqlX.Data.Tests +{ + public class TransactionTests : BaseTest + { + private string collName = "collSp"; + + [TearDown] + public void TearDown() => session.Schema.DropCollection(collName); + + [Test] + public void Commit() + { + Collection coll = CreateCollection("test"); + var docs = new[] + { + new { _id = 1, title = "Book 1", pages = 20 }, + new { _id = 2, title = "Book 2", pages = 30 }, + new { _id = 3, title = "Book 3", pages = 40 }, + new { _id = 4, title = "Book 4", pages = 50 }, + }; + + // start the transaction + coll.Session.StartTransaction(); + + Result r = ExecuteAddStatement(coll.Add(docs)); + Assert.AreEqual(4, r.AffectedItemsCount); + + // now roll it back + coll.Session.Commit(); + + var foundDocs = ExecuteFindStatement(coll.Find()); + Assert.True(foundDocs.Next()); + Assert.True(foundDocs.Next()); + Assert.True(foundDocs.Next()); + Assert.True(foundDocs.Next()); + Assert.False(foundDocs.Next()); + } + + [Test] + public void Rollback() + { + Collection coll = CreateCollection("test"); + var docs = new[] + { + new { _id = 1, title = "Book 1", pages = 20 }, + new { _id = 2, title = "Book 2", pages = 30 }, + new { _id = 3, title = "Book 3", pages = 40 }, + new { _id = 4, title = "Book 4", pages = 50 }, + }; + + // start the transaction + coll.Session.StartTransaction(); + + Result r = ExecuteAddStatement(coll.Add(docs)); + Assert.AreEqual(4, r.AffectedItemsCount); + + // now roll it back + coll.Session.Rollback(); + + var foundDocs = ExecuteFindStatement(coll.Find()); + Assert.False(foundDocs.Next()); + } + + #region Savepoints + + [Test] + public void CreateUnnamedSavepoint() + { + using (var session = MySQLX.GetSession(ConnectionString)) + { + session.StartTransaction(); + + string spName = session.SetSavepoint(); + Assert.False(string.IsNullOrWhiteSpace(spName)); + + session.Rollback(); + } + } + + [Test] + public void RollbackToSavepoint() + { + using (var session = MySQLX.GetSession(ConnectionString)) + { + var schema = session.GetSchema("test"); + schema.DropCollection("collSP"); + var coll = schema.CreateCollection("collSP"); + + session.StartTransaction(); + + ExecuteAddStatement(coll.Add("{ \"test\": \"test\" }")); + var sp = session.SetSavepoint(); + ExecuteAddStatement(coll.Add("{ \"test\": \"test\" }")); + Assert.AreEqual(2, ExecuteFindStatement(coll.Find()).FetchAll().Count); + session.RollbackTo(sp); + Assert.That(ExecuteFindStatement(coll.Find()).FetchAll(), Has.One.Items); + + session.Rollback(); + } + } + + [Test] + public void ReleaseSavepoint() + { + using (var sessionTest = MySQLX.GetSession(ConnectionString)) + { + var coll = CreateCollection("test"); + sessionTest.StartTransaction(); + ExecuteAddStatement(coll.Add("{ \"test\": \"test\" }")); + var sp = sessionTest.SetSavepoint(); + ExecuteAddStatement(coll.Add("{ \"test2\": \"test2\" }")); + Assert.AreEqual(2, ExecuteFindStatement(coll.Find()).FetchAll().Count); + sessionTest.ReleaseSavepoint(sp); + Assert.AreEqual(2, ExecuteFindStatement(coll.Find()).FetchAll().Count); + sessionTest.Rollback(); + } + } + + [Test] + public void CreateNamedSavepoint() + { + using (var session = MySQLX.GetSession(ConnectionString)) + { + session.StartTransaction(); + + string spName = session.SetSavepoint("mySavedPoint"); + Assert.False(string.IsNullOrWhiteSpace(spName)); + + session.Rollback(); + } + } + + [Test] + public void RollbackToNamedSavepoint() + { + using (var session = MySQLX.GetSession(ConnectionString)) + { + var schema = session.GetSchema("test"); + schema.DropCollection("collSP"); + var coll = schema.CreateCollection("collSP"); + session.StartTransaction(); + ExecuteAddStatement(coll.Add("{ \"test\": \"test\" }")); + var sp = session.SetSavepoint("mySavedPoint"); + ExecuteAddStatement(coll.Add("{ \"test2\": \"test2\" }")); + Assert.AreEqual(2, ExecuteFindStatement(coll.Find()).FetchAll().Count); + session.RollbackTo(sp); + Assert.That(ExecuteFindStatement(coll.Find()).FetchAll(), Has.One.Items); + session.Rollback(); + } + } + + [Test] + public void ReleaseNamedSavepoint() + { + using (var session = MySQLX.GetSession(ConnectionString)) + { + var schema = session.GetSchema("test"); + schema.DropCollection("test"); + var coll = schema.CreateCollection("test"); + session.StartTransaction(); + ExecuteAddStatement(coll.Add("{ \"test\": \"test\" }")); + var sp = session.SetSavepoint("mySavedPoint"); + ExecuteAddStatement(coll.Add("{ \"test2\": \"test2\" }")); + Assert.AreEqual(2, ExecuteFindStatement(coll.Find()).FetchAll().Count); + session.ReleaseSavepoint(sp); + Assert.AreEqual(2, ExecuteFindStatement(coll.Find()).FetchAll().Count); + session.Rollback(); + } + } + + [Test] + public void NonExistentSavepoint() + { + using (var session = MySQLX.GetSession(ConnectionString)) + { + session.StartTransaction(); + + Exception exception = Assert.Throws(() => session.RollbackTo("nonExistentSavePoint")); + Assert.AreEqual("SAVEPOINT nonExistentSavePoint does not exist", exception.Message); + + exception = Assert.Throws(() => session.ReleaseSavepoint("nonExistentSavePoint")); + Assert.AreEqual("SAVEPOINT nonExistentSavePoint does not exist", exception.Message); + + session.Rollback(); + } + } + + [Test] + public void CreateSavepointWithWeirdNames() + { + using (var session = MySQLX.GetSession(ConnectionString)) + { + string errorMessage = "You have an error in your SQL syntax"; + session.StartTransaction(); + + Exception ex = Assert.Throws(() => session.SetSavepoint("")); + StringAssert.StartsWith(errorMessage, ex.Message); + ex = Assert.Throws(() => session.SetSavepoint(" ")); + StringAssert.StartsWith(errorMessage, ex.Message); + ex = Assert.Throws(() => session.SetSavepoint(null)); + StringAssert.StartsWith(errorMessage, ex.Message); + ex = Assert.Throws(() => session.SetSavepoint("-")); + StringAssert.StartsWith(errorMessage, ex.Message); + ex = Assert.Throws(() => session.SetSavepoint("mysp+")); + StringAssert.StartsWith(errorMessage, ex.Message); + ex = Assert.Throws(() => session.SetSavepoint("3306")); + StringAssert.StartsWith(errorMessage, ex.Message); + + var sp = session.SetSavepoint("_"); + session.RollbackTo(sp); + sp = session.SetSavepoint("mysql3306"); + session.RollbackTo(sp); + + session.Rollback(); + } + } + + [Test] + public void OverwriteSavepoint() + { + using (var session = MySQLX.GetSession(ConnectionString)) + { + var schema = session.GetSchema("test"); + var coll = schema.CreateCollection(collName); + + session.StartTransaction(); + + ExecuteAddStatement(coll.Add("{ \"test\": \"test\" }")); + var sp = session.SetSavepoint("mySP"); + ExecuteAddStatement(coll.Add("{ \"test2\": \"test2\" }")); + sp = session.SetSavepoint("mySP"); + ExecuteAddStatement(coll.Add("{ \"test3\": \"test3\" }")); + sp = session.SetSavepoint("mySP"); + ExecuteAddStatement(coll.Add("{ \"test4\": \"test4\" }")); + sp = session.SetSavepoint("mySP"); + session.RollbackTo(sp); + Assert.AreEqual(4, ExecuteFindStatement(coll.Find()).FetchAll().Count); + + session.Rollback(); + } + } + + [Test] + public void MultipleReleasesForSavepoint() + { + using (var session = MySQLX.GetSession(ConnectionString)) + { + session.StartTransaction(); + + var sp = session.SetSavepoint("mySP"); + session.ReleaseSavepoint(sp); + Exception exception = Assert.Throws(() => session.ReleaseSavepoint(sp)); + Assert.AreEqual(string.Format("SAVEPOINT {0} does not exist", sp), exception.Message); + + session.Rollback(); + } + } + + [Test] + public void RollbackAndReleaseAfterTransactionCommit() + { + using (var sessionTest = MySQLX.GetSession(ConnectionString)) + { + var coll = CreateCollection("collSP"); + sessionTest.StartTransaction(); + var sp = sessionTest.SetSavepoint("mySP"); + ExecuteAddStatement(coll.Add("{ \"test\": \"test\" }")); + sessionTest.Commit(); + Exception exception = Assert.Throws(() => sessionTest.RollbackTo(sp)); + Assert.AreEqual(string.Format("SAVEPOINT {0} does not exist", sp), exception.Message); + exception = Assert.Throws(() => sessionTest.ReleaseSavepoint(sp)); + Assert.AreEqual(string.Format("SAVEPOINT {0} does not exist", sp), exception.Message); + } + } + + [Test] + public void RollbackAndReleaseAfterTransactionRollback() + { + using (var sessionTest = MySQLX.GetSession(ConnectionString)) + { + var coll = CreateCollection("collSP"); + sessionTest.StartTransaction(); + + var sp = sessionTest.SetSavepoint("mySP"); + ExecuteAddStatement(coll.Add("{ \"test\": \"test\" }")); + + sessionTest.Rollback(); + + Exception exception = Assert.Throws(() => sessionTest.RollbackTo(sp)); + Assert.AreEqual(string.Format("SAVEPOINT {0} does not exist", sp), exception.Message); + + exception = Assert.Throws(() => sessionTest.ReleaseSavepoint(sp)); + Assert.AreEqual(string.Format("SAVEPOINT {0} does not exist", sp), exception.Message); + } + } + + #endregion + + #region WL14389 + + [Test, Description("Session Close Transaction")] + public void SessionCloseTransaction() + { + if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher."); + using (Session sessionTest = MySQLX.GetSession(ConnectionString)) + { + Schema db = null; + db = sessionTest.GetSchema("test"); + sessionTest.StartTransaction(); + + if (db.GetCollection("my_collection_1").ExistsInDatabase()) + { + db.DropCollection("my_collection_1"); + } + Collection col = db.CreateCollection("my_collection_1"); + sessionTest.Close(); + Assert.Throws(() => sessionTest.Rollback()); + } + } + + [Test, Description("Valid Commit and Check Warning ")] + public void CommitValidWarning() + { + if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher."); + using (Session sessionPlain = MySQLX.GetSession(ConnectionString)) + { + sessionPlain.SetCurrentSchema("test"); + sessionPlain.SQL("drop table if exists temp").Execute(); + sessionPlain.SQL("CREATE TABLE temp(id INT primary key)").Execute(); + Table table = sessionPlain.Schema.GetTable("temp"); + sessionPlain.StartTransaction(); + table.Insert().Values(5).Execute(); + sessionPlain.Commit(); + Assert.AreEqual(1, table.Count()); + } + } + + /// + /// Bug 23542005 + /// + [Test, Description("Invalid Commit and Check Warning ")] + public void CommitInvalidWarning() + { + if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher."); + using (Session sessionPlain = MySQLX.GetSession(ConnectionString)) + { + sessionPlain.SetCurrentSchema("test"); + sessionPlain.SQL("CREATE TABLE temp(v VARCHAR(4))").Execute(); + Table table = sessionPlain.Schema.GetTable("temp"); + sessionPlain.StartTransaction(); + Assert.Throws(() => sessionPlain.GetSchema("test").GetTable("temp").Insert().Values("abcdef").Execute()); + sessionPlain.Commit(); + Assert.AreEqual(0, table.Count()); + var warnings = sessionPlain.SQL("DROP TABLE IF EXISTS temp1").Execute().Warnings; + Assert.IsTrue(warnings.Count > 0); + sessionPlain.Commit(); + } + } + + + [Test, Description("Valid Rollback and Check Warning ")] + public void RollbackValidWarning() + { + if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher."); + using (Session sessionPlain = MySQLX.GetSession(ConnectionString)) + { + sessionPlain.SetCurrentSchema("test"); + sessionPlain.SQL("DROP TABLE IF EXISTS temp").Execute(); + sessionPlain.SQL("CREATE TABLE temp(id INT primary key)").Execute(); + Table table = sessionPlain.Schema.GetTable("temp"); + sessionPlain.StartTransaction(); + var res = table.Insert().Values(5).Execute(); + sessionPlain.Rollback(); + Assert.AreEqual(0, table.Count()); + Assert.AreEqual(0, res.Warnings.Count); + } + } + + /// + /// Bug 23542005 + /// + [Test, Description("Invalid Rollback and Check Warning ")] + public void RollbackInvalidWarning() + { + if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher."); + using (Session sessionPlain = MySQLX.GetSession(ConnectionString)) + { + sessionPlain.SetCurrentSchema("test"); + sessionPlain.SQL("DROP TABLE IF EXISTS temp").Execute(); + sessionPlain.SQL("CREATE TABLE temp(v VARCHAR(4))").Execute(); + Table table = sessionPlain.Schema.GetTable("temp"); + sessionPlain.StartTransaction(); + Assert.Throws(() => sessionPlain.GetSchema("test").GetTable("temp").Insert().Values("abcdef").Execute()); + sessionPlain.Rollback(); + Assert.AreEqual(0, table.Count()); + var res = sessionPlain.SQL("DROP TABLE IF EXISTS temp1").Execute(); + Assert.IsTrue(res.Warnings.Count > 0); + } + } + + /// + /// Bug 23542005 + /// + [Test, Description("Commit Rollback Invalid Warning")] + public void CommitRollbackInvalidWarning() + { + if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher."); + Collection coll = CreateCollection("test"); + var docs1 = new[] + { + new { _id = 1, title = "Book 1", pages = 20 }, + new { _id = 2, title = "Book 2", pages = 30 }, + }; + + var docs2 = new[] + { + new { _id = 3, title = "Book 3", pages = 40 }, + new { _id = 4, title = "Book 4", pages = 50 }, + }; + + var docs3 = new[] + + { + new { _id = 5, title = "Book 5", pages = 60 }, + new { _id = 6, title = "Book 6", pages = 70 }, + }; + + // start the transaction + coll.Session.StartTransaction(); + + Result r = coll.Add(docs1).Execute(); + Assert.AreEqual(2, r.AffectedItemsCount); + + r = coll.Add(docs2).Execute(); + Assert.AreEqual(2, r.AffectedItemsCount); + + r = coll.Add(docs3).Execute(); + Assert.Throws(() => coll.Add(docs3).Execute()); + coll.Session.Commit(); + Assert.AreEqual(6, coll.Count()); + // now Rollback + coll.Session.Rollback(); + Assert.AreEqual(6, coll.Count()); + + var foundDocs = coll.Find().Execute(); + Assert.IsNotNull(foundDocs); + } + + [Test, Description("MySQLX plugin Warnings")] + public void Warnings() + { + if (!session.Version.isAtLeast(8, 0, 0)) return; + using (Session sessionTest = MySQLX.GetSession(ConnectionString)) + { + Schema schema = sessionTest.GetSchema("test"); + Collection coll = CreateCollection("test"); + + Result r = coll.Add("{ \"foo\": 1 }").Execute(); + Assert.AreEqual(1, r.AffectedItemsCount); + Assert.AreEqual(1, coll.Count()); + r = coll.Add("{ \"fool\": 2 }").Execute(); + Assert.AreEqual(0, r.Warnings.Count); + r = coll.Add("{ \"fool\": 10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 }").Execute(); + Assert.AreEqual(0, r.Warnings.Count); + + sessionTest.SQL("use test").Execute(); + sessionTest.SQL("CREATE TABLE nontrac(id INT primary key) ENGINE=MyISAM;").Execute(); + Table table = schema.GetTable("nontrac"); + sessionTest.StartTransaction(); + table.Insert().Values(5).Execute(); + + schema = sessionTest.GetSchema(schemaName); + sessionTest.StartTransaction(); + + var res = sessionTest.SQL("drop table if exists t1, t2").Execute(); + Assert.AreEqual(2, res.Warnings.Count); + Assert.AreEqual(1051, res.Warnings[0].Code); + + Assert.AreEqual(1051, res.Warnings[1].Code); + + res = sessionTest.SQL("create table t1 (a int) engine=innodb").Execute(); + Assert.AreEqual(0, res.Warnings.Count); + res = sessionTest.SQL("create table t2 (a int) engine=myisam").Execute(); + Assert.AreEqual(0, res.Warnings.Count); + res = sessionTest.SQL("insert into t1 values(1)").Execute(); + Assert.AreEqual(0, res.Warnings.Count); + res = sessionTest.SQL("insert into t2 select * from t1").Execute(); + Assert.AreEqual(1, res.Warnings.Count); + sessionTest.Commit(); + + } + } + + //Savepoints + [Test, Description("Rollback to same savepoint multiple times")] + public void RollbackToSameSavepoint() + { + if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher."); + + var col = CreateCollection("my_collection"); + session.StartTransaction(); + object[] data = new object[] + { + new { _id = 1, title = "Book 1", pages = 30 }, + new { _id = 2, title = "Book 2", pages = 50 }, + }; + Result result = col.Add(data).Execute(); + var sp = session.SetSavepoint("SavePoint1"); + data = new object[] + { + new { _id = 3, title = "Book 3", pages = 30 }, + new { _id = 4, title = "Book 4", pages = 50 }, + }; + result = col.Add(data).Execute(); + var sp1 = session.SetSavepoint("SavePoint2"); + + session.RollbackTo(sp); + data = new object[] + { + new { _id = 5, title = "Book 5", pages = 30 }, + new { _id = 6, title = "Book 6", pages = 50 }, + }; + result = col.Add(data).Execute(); + session.RollbackTo(sp); + var doc = col.Find().Execute(); + var docs = doc.FetchAll().Count(); + Assert.AreEqual(2, docs); + } + + + [Test, Description("Releasing a savepoint multiple times")] + public void ReleaseSavepointMoreThanOnce() + { + if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher."); + using (Session sessionTest = MySQLX.GetSession(ConnectionString)) + { + var col = CreateCollection("my_collection"); + sessionTest.StartTransaction(); + object[] data = new object[] + { + new { _id = 1, title = "Book 1", pages = 30 }, + new { _id = 2, title = "Book 2", pages = 50 }, + }; + Result result = col.Add(data).Execute(); + var sp = sessionTest.SetSavepoint("SavePoint1"); + data = new object[] + { + new { _id = 3, title = "Book 3", pages = 30 }, + new { _id = 4, title = "Book 4", pages = 50 }, + }; + result = col.Add(data).Execute(); + sessionTest.ReleaseSavepoint(sp); + data = new object[] + { + new { _id = 5, title = "Book 5", pages = 30 }, + new { _id = 6, title = "Book 6", pages = 50 }, + }; + result = col.Add(data).Execute(); + var ex = Assert.Throws(() => sessionTest.ReleaseSavepoint(sp)); + sessionTest.Rollback(); + } + } + + [TestCase("Savepoint1", "Savepoint2")] + [TestCase("", "")] + [Description("Creating multiple savepoints with SetSavepoint([name]) and rolling back to a specific one")] + public void MultipleSavepointsAndRollback(string savePoint1, string savePoint2) + { + if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher."); + var col = CreateCollection("my_collection"); + session.StartTransaction(); + object[] data = new object[] + { + new { _id = 1, title = "Book 1", pages = 30 }, + new { _id = 2, title = "Book 2", pages = 50 }, + }; + Result result = col.Add(data).Execute(); + var sp = string.IsNullOrEmpty(savePoint1) ? session.SetSavepoint() : session.SetSavepoint(savePoint1); + data = new object[] + { + new { _id = 3, title = "Book 3", pages = 30 }, + new { _id = 4, title = "Book 4", pages = 50 }, + }; + result = col.Add(data).Execute(); + var sp2 = string.IsNullOrEmpty(savePoint2) ? session.SetSavepoint() : session.SetSavepoint(savePoint2); + session.RollbackTo(sp); + var doc = col.Find().Execute(); + var docs = doc.FetchAll().Count(); + Assert.AreEqual(2, docs); + } + + [Test, Description("Test creating a savepoint without starting a transaction")] + public void SavepointWithoutTransaction() + { + if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher."); + var col = CreateCollection("my_collection"); + object[] data = new object[] + { + new { _id = 1, title = "Book 1", pages = 30 }, + new { _id = 2, title = "Book 2", pages = 50 }, + }; + Result result = col.Add(data).Execute(); + var sp = ""; + sp = session.SetSavepoint("SP"); + data = new object[] + { + new { _id =3, title = "Book 3", pages = 30 }, + new { _id =4, title = "Book 4", pages = 50 }, + }; + result = col.Add(data).Execute(); + var sp1 = session.SetSavepoint("SP"); + Assert.Throws(() => session.ReleaseSavepoint(sp1)); + } + + [Test, Description("Validate that further savepoints get released once you release a preceding savepoint")] + public void ValidateSavepointsReleased() + { + if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher."); + var col = CreateCollection("my_collection"); + session.StartTransaction(); + + object[] data = new object[] + { + new { _id = 1, title = "Book 1", pages = 30 }, + new { _id = 2, title = "Book 2", pages = 50 }, + }; + Result result = col.Add(data).Execute(); + var sp = session.SetSavepoint("SavePoint1"); + data = new object[] + { + new { _id = 3, title = "Book 3", pages = 30 }, + new { _id = 4, title = "Book 4", pages = 50 }, + }; + result = col.Add(data).Execute(); + var sp1 = session.SetSavepoint("SavePoint2"); + session.ReleaseSavepoint(sp); + Assert.Throws(() => session.ReleaseSavepoint(sp1)); + + var doc = col.Find().Execute(); + var docs = doc.FetchAll().Count(); + Assert.AreEqual(4, docs); + + } + + + [Test, Description("Validate Nested-transactions with multiple savepoints")] + public void NestedTransactions() + { + if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher."); + var col = CreateCollection("my_collection"); + session.StartTransaction(); + object[] data = new object[] + { + new { _id = 1, title = "Book 1", pages = 30 }, + new { _id = 2, title = "Book 2", pages = 50 }, + }; + Result result = col.Add(data).Execute(); + var sp = session.SetSavepoint("Savepoint1"); + session.StartTransaction(); + + data = new object[] + { + new { _id = 3, title = "Book 3", pages = 30 }, + new { _id = 4, title = "Book 4", pages = 50 }, + }; + result = col.Add(data).Execute(); + var sp1 = session.SetSavepoint("Savepoint2"); + session.Rollback(); + var doc = col.Find().Execute(); + var docs = doc.FetchAll().Count(); + Assert.AreEqual(2, docs); + } + + [Test, Description("Test the behaviour of Savepoints created immediately after one another")] + public void SavepointsCreatedImmediately() + { + if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher."); + var col = CreateCollection("my_collection"); + session.StartTransaction(); + object[] data = new object[] + { + new { _id = 1, title = "Book 1", pages = 30 }, + new { _id = 2, title = "Book 2", pages = 50 }, + }; + Result result = col.Add(data).Execute(); + var sp = session.SetSavepoint("Savepoint1"); + var sp1 = session.SetSavepoint("Savepoint2"); + session.RollbackTo(sp); + var doc = col.Find().Execute(); + var docs = doc.FetchAll().Count(); + Assert.AreEqual(2, docs); + } + + [Test, Description("Test MySQLX plugin Commit After Commit")] + public void CommitAfterCommit() + { + if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher."); + Collection coll = CreateCollection("test"); + var docs1 = new[] + { + new { _id = 1, title = "Book 1", pages = 20 }, + new { _id = 2, title = "Book 2", pages = 30 }, + }; + + var docs2 = new[] + { + new { _id = 3, title = "Book 3", pages = 40 }, + new { _id = 4, title = "Book 4", pages = 50 }, + }; + + var docs3 = new[] + { + new { _id = 5, title = "Book 5", pages = 60 }, + new { _id = 6, title = "Book 6", pages = 70 }, + }; + + var docs4 = new[] + { + new { _id = 7, title = "Book 7", pages = 80 }, + new { _id = 8, title = "Book 8", pages = 90 }, + }; + + // start the transaction + coll.Session.StartTransaction(); + + Result r = coll.Add(docs1).Execute(); + Assert.AreEqual(2, r.AffectedItemsCount, "Matching"); + + r = coll.Add(docs2).Execute(); + Assert.AreEqual(2, r.AffectedItemsCount, "Matching"); + + r = coll.Add(docs3).Execute(); + Assert.AreEqual(2, r.AffectedItemsCount, "Matching"); + + // now Commit + coll.Session.Commit(); + // start the transaction + coll.Session.StartTransaction(); + r = coll.Add(docs4).Execute(); + Assert.AreEqual(2, r.AffectedItemsCount, "Matching"); + // now Commit Again + coll.Session.Commit(); + + var foundDocs = coll.Find().Execute(); + Assert.AreEqual(true, foundDocs.Next(), "Matching"); + Assert.AreEqual(true, foundDocs.Next(), "Matching"); + Assert.AreEqual(true, foundDocs.Next(), "Matching"); + Assert.AreEqual(true, foundDocs.Next(), "Matching"); + Assert.AreEqual(true, foundDocs.Next(), "Matching"); + Assert.AreEqual(true, foundDocs.Next(), "Matching"); + Assert.AreEqual(true, foundDocs.Next(), "Matching"); + Assert.AreEqual(true, foundDocs.Next(), "Matching"); + Assert.AreEqual(false, foundDocs.Next(), "Matching"); + + } + + [Test, Description("Test MySQLX plugin Rollback Multiple")] + public void RollBackMultiple() + { + if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher."); + Collection coll = CreateCollection("test"); + var docs1 = new[] + { + new { _id = 1, title = "Book 1", pages = 20 }, + new { _id = 2, title = "Book 2", pages = 30 }, + }; + + var docs2 = new[] + { + new { _id = 3, title = "Book 3", pages = 40 }, + new { _id = 4, title = "Book 4", pages = 50 }, + }; + + var docs3 = new[] + { + new { _id = 5, title = "Book 5", pages = 60 }, + new { _id = 6, title = "Book 6", pages = 70 }, + }; + + // start the transaction + coll.Session.StartTransaction(); + + Result r = coll.Add(docs1).Execute(); + Assert.AreEqual(2, r.AffectedItemsCount, "Matching"); + + r = coll.Add(docs2).Execute(); + Assert.AreEqual(2, r.AffectedItemsCount, "Matching"); + + r = coll.Add(docs3).Execute(); + Assert.AreEqual(2, r.AffectedItemsCount, "Matching"); + + // now Rollback + coll.Session.Rollback(); + + var foundDocs = coll.Find().Execute(); + Assert.AreEqual(false, foundDocs.Next(), "Matching"); + + } + + [Test, Description("Test MySQLX plugin Rollback after RollBack")] + public void RollBackAfterRollBack() + { + if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher."); + Collection coll = CreateCollection("test"); + var docs1 = new[] + { + new { _id = 1, title = "Book 1", pages = 20 }, + new { _id = 2, title = "Book 2", pages = 30 }, + }; + + var docs2 = new[] + { + new { _id = 3, title = "Book 3", pages = 40 }, + new { _id = 4, title = "Book 4", pages = 50 }, + }; + + var docs3 = new[] + { + new { _id = 5, title = "Book 5", pages = 60 }, + new { _id = 6, title = "Book 6", pages = 70 }, + }; + + var docs4 = new[] + { + new { _id = 7, title = "Book 7", pages = 80 }, + new { _id = 8, title = "Book 8", pages = 90 }, + }; + + // start the transaction + coll.Session.StartTransaction(); + + Result r = coll.Add(docs1).Execute(); + //WL11843-Core API v1 alignment Changes + Assert.AreEqual(2, r.AffectedItemsCount, "Matching"); + + r = coll.Add(docs2).Execute(); + Assert.AreEqual(2, r.AffectedItemsCount, "Matching"); + + r = coll.Add(docs3).Execute(); + Assert.AreEqual(2, r.AffectedItemsCount, "Matching"); + + // now Rollback + coll.Session.Rollback(); + + // start the transaction + coll.Session.StartTransaction(); + + r = coll.Add(docs4).Execute(); + Assert.AreEqual(2, r.AffectedItemsCount, "Matching"); + + // now Rollback Again + coll.Session.Rollback(); + + var foundDocs = coll.Find().Execute(); + Assert.AreEqual(false, foundDocs.Next(), "Matching"); + + } + + [Test, Description("Test MySQLX plugin Commit Rollback")] + public void CommitRollBack() + { + if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher."); + Collection coll = CreateCollection("test"); + var docs1 = new[] + { + new { _id = 1, title = "Book 1", pages = 20 }, + new { _id = 2, title = "Book 2", pages = 30 }, + }; + + var docs2 = new[] + { + new { _id = 3, title = "Book 3", pages = 40 }, + new { _id = 4, title = "Book 4", pages = 50 }, + }; + + var docs3 = new[] + { + new { _id = 5, title = "Book 5", pages = 60 }, + new { _id = 6, title = "Book 6", pages = 70 }, + }; + + // start the transaction + coll.Session.StartTransaction(); + + Result r = coll.Add(docs1).Execute(); + //WL11843-Core API v1 alignment Changes + Assert.AreEqual(2, r.AffectedItemsCount, "Matching"); + + r = coll.Add(docs2).Execute(); + Assert.AreEqual(2, r.AffectedItemsCount, "Matching"); + + r = coll.Add(docs3).Execute(); + Assert.AreEqual(2, r.AffectedItemsCount, "Matching"); + + //now Commit + coll.Session.Commit(); + // now Rollback + coll.Session.Rollback(); + + var foundDocs = coll.Find().Execute(); + Assert.AreEqual(true, foundDocs.Next(), "Matching"); + Assert.AreEqual(true, foundDocs.Next(), "Matching"); + Assert.AreEqual(true, foundDocs.Next(), "Matching"); + Assert.AreEqual(true, foundDocs.Next(), "Matching"); + Assert.AreEqual(true, foundDocs.Next(), "Matching"); + Assert.AreEqual(true, foundDocs.Next(), "Matching"); + Assert.AreEqual(false, foundDocs.Next(), "Matching"); + + } + + [Test, Description("Test MySQLX plugin RollBack Commit")] + public void RollBackCommit() + { + if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher."); + Collection coll = CreateCollection("test"); + var docs1 = new[] + { + new { _id = 1, title = "Book 1", pages = 20 }, + new { _id = 2, title = "Book 2", pages = 30 }, + }; + + var docs2 = new[] + { + new { _id = 3, title = "Book 3", pages = 40 }, + new { _id = 4, title = "Book 4", pages = 50 }, + }; + + var docs3 = new[] + { + new { _id = 5, title = "Book 5", pages = 60 }, + new { _id = 6, title = "Book 6", pages = 70 }, + }; + + // start the transaction + coll.Session.StartTransaction(); + Result r = coll.Add(docs1).Execute(); + Assert.AreEqual(2, r.AffectedItemsCount, "Matching"); + + // now Rollback + coll.Session.Rollback(); + r = coll.Add(docs2).Execute(); + Assert.AreEqual(2, r.AffectedItemsCount, "Matching"); + r = coll.Add(docs3).Execute(); + Assert.AreEqual(2, r.AffectedItemsCount, "Matching"); + //now Commit + coll.Session.Commit(); + var foundDocs = coll.Find().Execute(); + Assert.AreEqual(true, foundDocs.Next(), "Matching"); + Assert.AreEqual(true, foundDocs.Next(), "Matching"); + Assert.AreEqual(true, foundDocs.Next(), "Matching"); + Assert.AreEqual(true, foundDocs.Next(), "Matching"); + Assert.AreEqual(false, foundDocs.Next(), "Matching"); + + } + + #endregion + + } +} diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/UnixSocketsTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/UnixSocketsTests.cs index c0c2bda15..89e41fa4e 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/UnixSocketsTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/UnixSocketsTests.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2017, 2022, Oracle and/or its affiliates. +// Copyright © 2017, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/XAuth.cs b/MySQL.Data/tests/MySqlX.Data.Tests/XAuth.cs index 1dd754717..49d70e524 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/XAuth.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/XAuth.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2021, 2022, Oracle and/or its affiliates. +// Copyright © 2021, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/XConnectionStringBuilderTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/XConnectionStringBuilderTests.cs index 711d0e338..bc535e2f0 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/XConnectionStringBuilderTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/XConnectionStringBuilderTests.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2018, 2022, Oracle and/or its affiliates. +// Copyright © 2018, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySql.Web/src/Application.cs b/MySql.Web/src/Application.cs index 69b8e074c..65c923e7a 100644 --- a/MySql.Web/src/Application.cs +++ b/MySql.Web/src/Application.cs @@ -1,94 +1,94 @@ -// Copyright (c) 2009, 2020, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySql.Data.MySqlClient; -using System; -using System.Configuration.Provider; - -namespace MySql.Web.General -{ - internal class Application - { - private long _id; - private string _desc; - - public Application(string name, string desc) - { - Id = -1; - Name = name; - Description = desc; - } - public long Id - { - get { return _id; } - private set { _id = value; } - } - public string Name; - - public string Description - { - get { return _desc; } - private set { _desc = value; } - } - - public long FetchId(MySqlConnection connection) - { - if (Id == -1) - { - MySqlCommand cmd = new MySqlCommand( - @"SELECT id FROM my_aspnet_applications WHERE name=@name", connection); - cmd.Parameters.AddWithValue("@name", Name); - object id = cmd.ExecuteScalar(); - Id = id == null ? -1 : Convert.ToInt64(id); - } - return Id; - } - - /// - /// Creates the or fetch application id. - /// - /// The connection. - public long EnsureId(MySqlConnection connection) - { - // first try and retrieve the existing id - if (FetchId(connection) <= 0) - { - MySqlCommand cmd = new MySqlCommand( - "INSERT INTO my_aspnet_applications VALUES (NULL, @appName, @appDesc)", connection); - cmd.Parameters.AddWithValue("@appName", Name); - cmd.Parameters.AddWithValue("@appDesc", Description); - int recordsAffected = cmd.ExecuteNonQuery(); - if (recordsAffected != 1) - throw new ProviderException(Properties.Resources.UnableToCreateApplication); - - Id = cmd.LastInsertedId; - } - return Id; - } - } -} +// Copyright © 2009, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySql.Data.MySqlClient; +using System; +using System.Configuration.Provider; + +namespace MySql.Web.General +{ + internal class Application + { + private long _id; + private string _desc; + + public Application(string name, string desc) + { + Id = -1; + Name = name; + Description = desc; + } + public long Id + { + get { return _id; } + private set { _id = value; } + } + public string Name; + + public string Description + { + get { return _desc; } + private set { _desc = value; } + } + + public long FetchId(MySqlConnection connection) + { + if (Id == -1) + { + MySqlCommand cmd = new MySqlCommand( + @"SELECT id FROM my_aspnet_applications WHERE name=@name", connection); + cmd.Parameters.AddWithValue("@name", Name); + object id = cmd.ExecuteScalar(); + Id = id == null ? -1 : Convert.ToInt64(id); + } + return Id; + } + + /// + /// Creates the or fetch application id. + /// + /// The connection. + public long EnsureId(MySqlConnection connection) + { + // first try and retrieve the existing id + if (FetchId(connection) <= 0) + { + MySqlCommand cmd = new MySqlCommand( + "INSERT INTO my_aspnet_applications VALUES (NULL, @appName, @appDesc)", connection); + cmd.Parameters.AddWithValue("@appName", Name); + cmd.Parameters.AddWithValue("@appDesc", Description); + int recordsAffected = cmd.ExecuteNonQuery(); + if (recordsAffected != 1) + throw new ProviderException(Properties.Resources.UnableToCreateApplication); + + Id = cmd.LastInsertedId; + } + return Id; + } + } +} diff --git a/MySql.Web/src/ConfigUtility.cs b/MySql.Web/src/ConfigUtility.cs index 28a094812..5c03f1fa7 100644 --- a/MySql.Web/src/ConfigUtility.cs +++ b/MySql.Web/src/ConfigUtility.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2017, 2020, Oracle and/or its affiliates. +// Copyright © 2017, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySql.Web/src/MembershipProvider.cs b/MySql.Web/src/MembershipProvider.cs index 400dc8ea3..3f77544f8 100644 --- a/MySql.Web/src/MembershipProvider.cs +++ b/MySql.Web/src/MembershipProvider.cs @@ -1,1727 +1,1727 @@ -// Copyright (c) 2004, 2021, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -// This code was contributed by Sean Wright (srwright@alcor.concordia.ca) on 2007-01-12 -// The copyright was assigned and transferred under the terms of -// the MySQL Contributor License Agreement (CLA) - -using MySql.Data.MySqlClient; -using MySql.Web.Common; -using MySql.Web.General; -using MySql.Web.Profile; -using System; -using System.Collections.Specialized; -using System.Configuration.Provider; -using System.Data; -using System.Diagnostics; -using System.Security.Cryptography; -using System.Text; -using System.Text.RegularExpressions; -using System.Web.Hosting; -using System.Web.Security; - -namespace MySql.Web.Security -{ - /// - /// Manages storage of membership information for an ASP.NET application in a MySQL database. - /// - /// - /// - /// This class is used by the and classes - /// to provide membership services for ASP.NET applications using a MySQL database. - /// - /// - /// - /// - /// configuration> - /// connectionStrings> - /// add name = "LocalMySqlService" connectionString="server=localhost;user id=myuser;password=mypass;database=test" /> - /// /connectionStrings> - /// system.web> - /// authentication mode = "Forms" > - /// forms loginUrl="login.aspx" name=".ASPXFORMSAUTH" /> - /// /authentication> - /// authorization> - /// deny users = "?" /> - /// /authorization> - /// membership defaultProvider="MySQLProvider" userIsOnlineTimeWindow="15"> - /// providers> - /// add - /// name = "MySQLProvider" - /// type="MySql.Web.Security.MySQLMembershipProvider" - /// connectionStringName="LocalMySqlService" - /// applicationName="MyApplication" - /// enablePasswordRetrieval="false" - /// enablePasswordReset="true" - /// requiresQuestionAndAnswer="true" - /// requiresUniqueEmail="false" - /// passwordFormat="Hashed" - /// maxInvalidPasswordAttempts="5" - /// passwordAttemptWindow="10" /> - /// /providers> - /// /membership> - /// /system.web> - /// /configuration> - /// - /// - public sealed class MySQLMembershipProvider : MembershipProvider - { - private int newPasswordLength = 8; - private string eventSource = "MySQLMembershipProvider"; - private string eventLog = "Application"; - private string exceptionMessage = "An exception occurred. Please check the Event Log."; - private string connectionString; - private int minRequiredPasswordLength; - private bool writeExceptionsToEventLog; - private bool enablePasswordReset; - private bool enablePasswordRetrieval; - private bool requiresQuestionAndAnswer; - private bool requiresUniqueEmail; - private int maxInvalidPasswordAttempts; - private int passwordAttemptWindow; - private MembershipPasswordFormat passwordFormat; - private int minRequiredNonAlphanumericCharacters; - private string passwordStrengthRegularExpression; - private Application app; - - /// - /// Initializes the MySQL membership provider with the property values specified in the - /// ASP.NET application's configuration file. This method is not intended to be used directly - /// from your code. - /// - /// The name of the instance to initialize. - /// A collection of the name/value pairs representing the - /// provider-specific attributes specified in the configuration for this provider. - /// config is a null reference. - /// An attempt is made to call on a provider after the provider has already been initialized. - /// - public override void Initialize(string name, NameValueCollection config) - { - if (config == null) - { - throw new ArgumentNullException("config"); - } - if (name == null || name.Length == 0) - { - name = "MySQLMembershipProvider"; - } - if (string.IsNullOrEmpty(config["description"])) - { - config.Remove("description"); - config.Add("description", "MySQL default application"); - } - base.Initialize(name, config); - - string applicationName = GetConfigValue(config["applicationName"], - HostingEnvironment.ApplicationVirtualPath); - maxInvalidPasswordAttempts = Convert.ToInt32(GetConfigValue(config["maxInvalidPasswordAttempts"], "5")); - passwordAttemptWindow = Convert.ToInt32(GetConfigValue(config["passwordAttemptWindow"], "10")); - minRequiredNonAlphanumericCharacters = - Convert.ToInt32(GetConfigValue(config["minRequiredNonalphanumericCharacters"], "1")); - minRequiredPasswordLength = Convert.ToInt32(GetConfigValue(config["minRequiredPasswordLength"], "7")); - passwordStrengthRegularExpression = - Convert.ToString(GetConfigValue(config["passwordStrengthRegularExpression"], "")); - enablePasswordReset = Convert.ToBoolean(GetConfigValue(config["enablePasswordReset"], "True")); - enablePasswordRetrieval = Convert.ToBoolean( - GetConfigValue(config["enablePasswordRetrieval"], "False")); - requiresQuestionAndAnswer = Convert.ToBoolean(GetConfigValue(config["requiresQuestionAndAnswer"], "False")); - requiresUniqueEmail = Convert.ToBoolean(GetConfigValue(config["requiresUniqueEmail"], "True")); - writeExceptionsToEventLog = Convert.ToBoolean(GetConfigValue(config["writeExceptionsToEventLog"], "True")); - string temp_format = config["passwordFormat"]; - - if (temp_format == null) - temp_format = "hashed"; - else - temp_format = temp_format.ToLowerInvariant(); - - if (temp_format == "hashed") - passwordFormat = MembershipPasswordFormat.Hashed; - else if (temp_format == "encrypted") - passwordFormat = MembershipPasswordFormat.Encrypted; - else if (temp_format == "clear") - passwordFormat = MembershipPasswordFormat.Clear; - else - throw new ProviderException("Password format not supported."); - - // if the user is asking for the ability to retrieve hashed passwords, then let - // them know we can't - if (PasswordFormat == MembershipPasswordFormat.Hashed) - { - if (EnablePasswordRetrieval) - throw new ProviderException(Properties.Resources.CannotRetrieveHashedPasswords); - } - - connectionString = ConfigUtility.GetConnectionString(config); - if (String.IsNullOrEmpty(connectionString)) return; - - // make sure we have the correct schema - SchemaManager.CheckSchema(connectionString, config); - - app = new Application(applicationName, base.Description); - } - - private static string GetConfigValue(string configValue, string defaultValue) - { - if (string.IsNullOrEmpty(configValue)) - { - return defaultValue; - } - return configValue; - } - - #region Properties - - /// - /// The name of the application using the MySQL membership provider. - /// - /// The name of the application using the MySQL membership provider. The default is the - /// application virtual path. - /// The ApplicationName is used by the MySqlMembershipProvider to separate - /// membership information for multiple applications. Using different application names, - /// applications can use the same membership database. - /// Likewise, multiple applications can make use of the same membership data by simply using - /// the same application name. - /// Caution should be taken with multiple applications as the ApplicationName property is not - /// thread safe during writes. - /// - /// - /// The following example shows the membership element being used in an applications web.config file. - /// The application name setting is being used. - /// - /// membership defaultProvider="MySQLMembershipProvider"> - /// providers> - /// add name="MySqlMembershipProvider" - /// type="MySql.Web.Security.MySQLMembershipProvider" - /// connectionStringName="LocalMySqlServer" - /// enablePasswordRetrieval="true" - /// enablePasswordReset="false" - /// requiresQuestionAndAnswer="true" - /// requiresUniqueEmail="false" - /// passwordFormat="Encrypted" - /// maxInvalidPasswordAttempts="3" - /// passwordAttemptWindow="20" - /// minRequiredNonAlphanumericCharacters="1" - /// minRequiredPasswordLength="11" - /// applicationName="MyApplication" /> - /// /providers> - /// /membership> - /// - /// - public override string ApplicationName - { - get { return app.Name; } - set - { - lock (this) - { - if (value.ToLowerInvariant() == app.Name.ToLowerInvariant()) return; - app = new Application(value, String.Empty); - } - } - } - - /// - /// Indicates whether the membership provider is configured to allow users to reset their passwords. - /// - /// true if the membership provider supports password reset; otherwise, false. The default is true. - /// Allows the user to replace their password with a new, randomly generated password. - /// This can be especially handy when using hashed passwords since hashed passwords cannot be - /// retrieved. - /// - /// The following example shows the membership element being used in an applications web.config file. - /// - /// membership defaultProvider="MySQLMembershipProvider"> - /// providers> - /// add name="MySqlMembershipProvider" - /// type="MySql.Web.Security.MySQLMembershipProvider" - /// connectionStringName="LocalMySqlServer" - /// enablePasswordRetrieval="true" - /// enablePasswordReset="false" - /// requiresQuestionAndAnswer="true" - /// requiresUniqueEmail="false" - /// passwordFormat="Encrypted" - /// maxInvalidPasswordAttempts="3" - /// passwordAttemptWindow="20" - /// minRequiredNonAlphanumericCharacters="1" - /// minRequiredPasswordLength="11" - /// applicationName="MyApplication" /> - /// /providers> - /// /membership> - /// - /// - public override bool EnablePasswordReset - { - get { return enablePasswordReset; } - } - - /// - /// Indicates whether the membership provider is configured to allow users to retrieve - /// their passwords. - /// - /// true if the membership provider is configured to support password retrieval; - /// otherwise, false. The default is false. - /// If the system is configured to use hashed passwords, then retrieval is not possible. - /// If the user attempts to initialize the provider with hashed passwords and enable password retrieval - /// set to true then a is thrown. - /// - /// The following example shows the membership element being used in an applications web.config file. - /// - /// membership defaultProvider="MySQLMembershipProvider"> - /// providers> - /// add name="MySqlMembershipProvider" - /// type="MySql.Web.Security.MySQLMembershipProvider" - /// connectionStringName="LocalMySqlServer" - /// enablePasswordRetrieval="true" - /// enablePasswordReset="false" - /// requiresQuestionAndAnswer="true" - /// requiresUniqueEmail="false" - /// passwordFormat="Encrypted" - /// maxInvalidPasswordAttempts="3" - /// passwordAttemptWindow="20" - /// minRequiredNonAlphanumericCharacters="1" - /// minRequiredPasswordLength="11" - /// applicationName="MyApplication" /> - /// /providers> - /// /membership> - /// - /// - public override bool EnablePasswordRetrieval - { - get { return enablePasswordRetrieval; } - } - - /// - /// Gets a value indicating whether the membership provider is - /// configured to require the user to answer a password question - /// for password reset and retrieval. - /// - /// true if a password answer is required for password - /// reset and retrieval; otherwise, false. The default is false. - /// - /// The following example shows the membership element being used in an applications web.config file. - /// - /// membership defaultProvider="MySQLMembershipProvider"> - /// providers> - /// add name="MySqlMembershipProvider" - /// type="MySql.Web.Security.MySQLMembershipProvider" - /// connectionStringName="LocalMySqlServer" - /// enablePasswordRetrieval="true" - /// enablePasswordReset="false" - /// requiresQuestionAndAnswer="true" - /// requiresUniqueEmail="false" - /// passwordFormat="Encrypted" - /// maxInvalidPasswordAttempts="3" - /// passwordAttemptWindow="20" - /// minRequiredNonAlphanumericCharacters="1" - /// minRequiredPasswordLength="11" - /// applicationName="MyApplication" /> - /// /providers> - /// /membership> - /// - /// - public override bool RequiresQuestionAndAnswer - { - get { return requiresQuestionAndAnswer; } - } - - /// - /// Gets a value indicating whether the membership provider is configured - /// to require a unique e-mail address for each user name. - /// - /// true if the membership provider requires a unique e-mail address; - /// otherwise, false. The default is true. - /// - /// The following example shows the membership element being used in an applications web.config file. - /// - /// membership defaultProvider="MySQLMembershipProvider"> - /// providers> - /// add name="MySqlMembershipProvider" - /// type="MySql.Web.Security.MySQLMembershipProvider" - /// connectionStringName="LocalMySqlServer" - /// enablePasswordRetrieval="true" - /// enablePasswordReset="false" - /// requiresQuestionAndAnswer="true" - /// requiresUniqueEmail="false" - /// passwordFormat="Encrypted" - /// maxInvalidPasswordAttempts="3" - /// passwordAttemptWindow="20" - /// minRequiredNonAlphanumericCharacters="1" - /// minRequiredPasswordLength="11" - /// applicationName="MyApplication" /> - /// /providers> - /// /membership> - /// - /// - public override bool RequiresUniqueEmail - { - get { return requiresUniqueEmail; } - } - - /// - /// Gets the number of invalid password or password-answer attempts allowed - /// before the membership user is locked out. - /// - /// The number of invalid password or password-answer attempts allowed - /// before the membership user is locked out. - /// - /// The following example shows the membership element being used in an applications web.config file. - /// - /// membership defaultProvider="MySQLMembershipProvider"> - /// providers> - /// add name="MySqlMembershipProvider" - /// type="MySql.Web.Security.MySQLMembershipProvider" - /// connectionStringName="LocalMySqlServer" - /// enablePasswordRetrieval="true" - /// enablePasswordReset="false" - /// requiresQuestionAndAnswer="true" - /// requiresUniqueEmail="false" - /// passwordFormat="Encrypted" - /// maxInvalidPasswordAttempts="3" - /// passwordAttemptWindow="20" - /// minRequiredNonAlphanumericCharacters="1" - /// minRequiredPasswordLength="11" - /// applicationName="MyApplication" /> - /// /providers> - /// /membership> - /// - /// - public override int MaxInvalidPasswordAttempts - { - get { return maxInvalidPasswordAttempts; } - } - - /// - /// Gets the number of minutes in which a maximum number of invalid password or - /// password-answer attempts are allowed before the membership user is locked out. - /// - /// The number of minutes in which a maximum number of invalid password or - /// password-answer attempts are allowed before the membership user is locked out. - /// - /// The following example shows the membership element being used in an applications web.config file. - /// - /// membership defaultProvider="MySQLMembershipProvider"> - /// providers> - /// add name="MySqlMembershipProvider" - /// type="MySql.Web.Security.MySQLMembershipProvider" - /// connectionStringName="LocalMySqlServer" - /// enablePasswordRetrieval="true" - /// enablePasswordReset="false" - /// requiresQuestionAndAnswer="true" - /// requiresUniqueEmail="false" - /// passwordFormat="Encrypted" - /// maxInvalidPasswordAttempts="3" - /// passwordAttemptWindow="20" - /// minRequiredNonAlphanumericCharacters="1" - /// minRequiredPasswordLength="11" - /// applicationName="MyApplication" /> - /// /providers> - /// /membership> - /// - /// - public override int PasswordAttemptWindow - { - get { return passwordAttemptWindow; } - } - - /// - /// Gets a value indicating the format for storing passwords in the membership data store. - /// - /// One of the - /// values indicating the format for storing passwords in the data store. - /// - /// The following example shows the membership element being used in an applications web.config file. - /// - /// membership defaultProvider="MySQLMembershipProvider"> - /// providers> - /// add name="MySqlMembershipProvider" - /// type="MySql.Web.Security.MySQLMembershipProvider" - /// connectionStringName="LocalMySqlServer" - /// enablePasswordRetrieval="true" - /// enablePasswordReset="false" - /// requiresQuestionAndAnswer="true" - /// requiresUniqueEmail="false" - /// passwordFormat="Encrypted" - /// maxInvalidPasswordAttempts="3" - /// passwordAttemptWindow="20" - /// minRequiredNonAlphanumericCharacters="1" - /// minRequiredPasswordLength="11" - /// applicationName="MyApplication" /> - /// /providers> - /// /membership> - /// - /// - public override MembershipPasswordFormat PasswordFormat - { - get { return passwordFormat; } - } - - /// - /// Gets the minimum number of special characters that must be present in a valid password. - /// - /// The minimum number of special characters that must be present - /// in a valid password. - /// - /// The following example shows the membership element being used in an applications web.config file. - /// - /// membership defaultProvider="MySQLMembershipProvider"> - /// providers> - /// add name="MySqlMembershipProvider" - /// type="MySql.Web.Security.MySQLMembershipProvider" - /// connectionStringName="LocalMySqlServer" - /// enablePasswordRetrieval="true" - /// enablePasswordReset="false" - /// requiresQuestionAndAnswer="true" - /// requiresUniqueEmail="false" - /// passwordFormat="Encrypted" - /// maxInvalidPasswordAttempts="3" - /// passwordAttemptWindow="20" - /// minRequiredNonAlphanumericCharacters="1" - /// minRequiredPasswordLength="11" - /// applicationName="MyApplication" /> - /// /providers> - /// /membership> - /// - /// - public override int MinRequiredNonAlphanumericCharacters - { - get { return minRequiredNonAlphanumericCharacters; } - } - - /// - /// Gets the minimum length required for a password. - /// - /// The minimum length required for a password. - /// - /// The following example shows the membership element being used in an applications web.config file. - /// - /// membership defaultProvider="MySQLMembershipProvider"> - /// providers> - /// add name="MySqlMembershipProvider" - /// type="MySql.Web.Security.MySQLMembershipProvider" - /// connectionStringName="LocalMySqlServer" - /// enablePasswordRetrieval="true" - /// enablePasswordReset="false" - /// requiresQuestionAndAnswer="true" - /// requiresUniqueEmail="false" - /// passwordFormat="Encrypted" - /// maxInvalidPasswordAttempts="3" - /// passwordAttemptWindow="20" - /// minRequiredNonAlphanumericCharacters="1" - /// minRequiredPasswordLength="11" - /// applicationName="MyApplication" /> - /// /providers> - /// /membership> - /// - /// - public override int MinRequiredPasswordLength - { - get { return minRequiredPasswordLength; } - } - - /// - /// Gets the regular expression used to evaluate a password. - /// - /// A regular expression used to evaluate a password. - /// - /// The following example shows the membership element being used in an applications web.config file. - /// In this example, the regular expression specifies that the password must meet the following - /// criteria: - /// * Is at least seven characters. - /// * Contains at least one digit. - /// * Contains at least one special (non-alphanumeric) character. - /// - /// membership defaultProvider="MySQLMembershipProvider"> - /// providers> - /// add name="MySqlMembershipProvider" - /// type="MySql.Web.Security.MySQLMembershipProvider" - /// connectionStringName="LocalMySqlServer" - /// enablePasswordRetrieval="true" - /// enablePasswordReset="false" - /// requiresQuestionAndAnswer="true" - /// requiresUniqueEmail="false" - /// passwordFormat="Encrypted" - /// maxInvalidPasswordAttempts="3" - /// passwordAttemptWindow="20" - /// minRequiredNonAlphanumericCharacters="1" - /// minRequiredPasswordLength="11" - /// applicationName="MyApplication" /> - /// /providers> - /// /membership> - /// - /// - public override string PasswordStrengthRegularExpression - { - get { return passwordStrengthRegularExpression; } - } - - /// - /// Gets or sets a value indicating whether exceptions are written to the event log. - /// - /// - /// true if exceptions should be written to the log; otherwise, false. - /// - public bool WriteExceptionsToEventLog - { - get { return writeExceptionsToEventLog; } - set { writeExceptionsToEventLog = value; } - } - - #endregion - - #region Public Methods - - /// - /// Changes the password. - /// - /// The username. - /// The old password. - /// The new password. - /// true if the password was updated successfully; false if the supplied old password - /// is invalid, the user is locked out, or the user does not exist in the database. - public override bool ChangePassword(string username, string oldPassword, string newPassword) - { - // this will return false if the username doesn't exist - if (!(ValidateUser(username, oldPassword))) - return false; - - ValidatePasswordEventArgs args = new ValidatePasswordEventArgs(username, newPassword, true); - OnValidatingPassword(args); - if (args.Cancel) - { - if (!(args.FailureInformation == null)) - throw args.FailureInformation; - else - throw new ProviderException(Properties.Resources.ChangePasswordCanceled); - } - - // validate the password according to current guidelines - if (!ValidatePassword(newPassword, "newPassword", true)) - return false; - - try - { - using (MySqlConnection connection = new MySqlConnection(connectionString)) - { - connection.Open(); - - // retrieve the existing key and format for this user - string passwordKey; - MembershipPasswordFormat passwordFormat; - int userId = GetUserId(connection, username); - - GetPasswordInfo(connection, userId, out passwordKey, out passwordFormat); - - MySqlCommand cmd = new MySqlCommand( - @"UPDATE my_aspnet_membership - SET Password = @pass, LastPasswordChangedDate = @lastPasswordChangedDate - WHERE userId=@userId", connection); - cmd.Parameters.AddWithValue("@pass", - EncodePassword(newPassword, passwordKey, passwordFormat)); - cmd.Parameters.AddWithValue("@lastPasswordChangedDate", DateTime.Now); - cmd.Parameters.AddWithValue("@userId", userId); - return cmd.ExecuteNonQuery() > 0; - } - } - catch (MySqlException e) - { - if (WriteExceptionsToEventLog) - WriteToEventLog(e, "ChangePassword"); - throw new ProviderException(exceptionMessage, e); - } - } - - /// - /// Changes the password question and answer. - /// - /// The user name. - /// The password. - /// The new password question. - /// The new password answer. - /// true if the update was successful; otherwise, false. A value of false is - /// also returned if the password is incorrect, the user is locked out, or the user - /// does not exist in the database. - public override bool ChangePasswordQuestionAndAnswer(string username, - string password, string newPwdQuestion, string newPwdAnswer) - { - // this handles the case where the username doesn't exist - if (!(ValidateUser(username, password))) - return false; - - try - { - using (MySqlConnection connection = new MySqlConnection(connectionString)) - { - connection.Open(); - - string passwordKey; - MembershipPasswordFormat passwordFormat; - int userId = GetUserId(connection, username); - - GetPasswordInfo(connection, userId, out passwordKey, out passwordFormat); - - - MySqlCommand cmd = new MySqlCommand( - @"UPDATE my_aspnet_membership - SET PasswordQuestion = @passwordQuestion, PasswordAnswer = @passwordAnswer - WHERE userId=@userId", connection); - cmd.Parameters.AddWithValue("@passwordQuestion", newPwdQuestion); - cmd.Parameters.AddWithValue("@passwordAnswer", - EncodePassword(newPwdAnswer, passwordKey, passwordFormat)); - cmd.Parameters.AddWithValue("@userId", userId); - return cmd.ExecuteNonQuery() > 0; - } - } - catch (MySqlException e) - { - if (WriteExceptionsToEventLog) - WriteToEventLog(e, "ChangePasswordQuestionAndAnswer"); - throw new ProviderException(exceptionMessage, e); - } - } - - /// - /// Adds a new membership user to the data source. - /// - /// The user name for the new user. - /// The password for the new user. - /// The e-mail address for the new user. - /// The password question for the new user. - /// The password answer for the new user - /// Whether or not the new user is approved to be validated. - /// The unique identifier from the membership data source for the user. - /// A enumeration value indicating whether the user was created successfully. - /// - /// A object populated with the information for the newly created user. - /// - public override MembershipUser CreateUser(string username, string password, - string email, string passwordQuestion, string passwordAnswer, - bool isApproved, object providerUserKey, out MembershipCreateStatus status) - { - //basis on MSDN documentation we should trim all the paramater values: http://msdn.microsoft.com/en-us/library/d8t4h2es%28v=vs.110%29.aspx - TrimParametersValues(ref username, ref password, ref email, ref passwordQuestion, ref passwordAnswer); - - ValidatePasswordEventArgs Args = new ValidatePasswordEventArgs(username, password, true); - OnValidatingPassword(Args); - if (Args.Cancel) - { - status = MembershipCreateStatus.InvalidPassword; - return null; - } - if (RequiresUniqueEmail && !String.IsNullOrEmpty(GetUserNameByEmail(email))) - { - status = MembershipCreateStatus.DuplicateEmail; - return null; - } - - ValidateQA(passwordQuestion, passwordAnswer); - - // now try to validate the password - if (!ValidatePassword(password, "password", false)) - { - status = MembershipCreateStatus.InvalidPassword; - return null; - } - - // now check to see if we already have a member by this name - MembershipUser u = GetUser(username, false); - if (u != null) - { - status = MembershipCreateStatus.DuplicateUserName; - return null; - } - - string passwordKey = GetPasswordKey(); - DateTime createDate = DateTime.Now; - MySqlTransaction transaction = null; - - using (MySqlConnection connection = new MySqlConnection(connectionString)) - { - try - { - connection.Open(); - transaction = connection.BeginTransaction(); - - // either create a new user or fetch the existing user id - long userId = SchemaManager.CreateOrFetchUserId(connection, username, - app.EnsureId(connection), true); - - MySqlCommand cmd = new MySqlCommand( - @"INSERT INTO my_aspnet_membership - VALUES(@userId, @email, @comment, @password, @passwordKey, - @passwordFormat, @passwordQuestion, @passwordAnswer, - @isApproved, @lastActivityDate, @lastLoginDate, - @lastPasswordChangedDate, @creationDate, - @isLockedOut, @lastLockedOutDate, @failedPasswordAttemptCount, - @failedPasswordAttemptWindowStart, @failedPasswordAnswerAttemptCount, - @failedPasswordAnswerAttemptWindowStart)", - connection); - cmd.Parameters.AddWithValue("@userId", userId); - cmd.Parameters.AddWithValue("@email", email); - cmd.Parameters.AddWithValue("@comment", ""); - cmd.Parameters.AddWithValue("@password", - EncodePassword(password, passwordKey, PasswordFormat)); - cmd.Parameters.AddWithValue("@passwordKey", passwordKey); - cmd.Parameters.AddWithValue("@passwordFormat", PasswordFormat); - cmd.Parameters.AddWithValue("@passwordQuestion", passwordQuestion); - cmd.Parameters.AddWithValue("@passwordAnswer", - EncodePassword(passwordAnswer, passwordKey, PasswordFormat)); - cmd.Parameters.AddWithValue("@isApproved", isApproved); - cmd.Parameters.AddWithValue("@lastActivityDate", createDate); - cmd.Parameters.AddWithValue("@lastLoginDate", createDate); - cmd.Parameters.AddWithValue("@lastPasswordChangedDate", createDate); - cmd.Parameters.AddWithValue("@creationDate", createDate); - cmd.Parameters.AddWithValue("@isLockedOut", false); - cmd.Parameters.AddWithValue("@lastLockedOutDate", createDate); - cmd.Parameters.AddWithValue("@failedPasswordAttemptCount", 0); - cmd.Parameters.AddWithValue("@failedPasswordAttemptWindowStart", createDate); - cmd.Parameters.AddWithValue("@failedPasswordAnswerAttemptCount", 0); - cmd.Parameters.AddWithValue("@failedPasswordAnswerAttemptWindowStart", createDate); - - int recAdded = cmd.ExecuteNonQuery(); - if (recAdded > 0) - status = MembershipCreateStatus.Success; - else - status = MembershipCreateStatus.UserRejected; - transaction.Commit(); - } - catch (MySqlException e) - { - if (WriteExceptionsToEventLog) - WriteToEventLog(e, "CreateUser"); - status = MembershipCreateStatus.ProviderError; - if (transaction != null) - transaction.Rollback(); - return null; - } - } - - return GetUser(username, false); - } - - /// - /// Removes a user from the membership data source. - /// - /// The name of the user to delete. - /// true to delete data related to the user from the database; false to leave data related to the user in the database. - /// - /// true if the user was successfully deleted; otherwise, false. - /// - public override bool DeleteUser(string username, bool deleteAllRelatedData) - { - try - { - using (MySqlConnection conn = new MySqlConnection(connectionString)) - { - conn.Open(); - - int userId = GetUserId(conn, username); - if (-1 == userId) return false; - - // if we are supposed to delete all related data, then delegate that to those providers - if (deleteAllRelatedData) - { - MySQLRoleProvider.DeleteUserData(conn, userId); - MySQLProfileProvider.DeleteUserData(conn, userId); - } - - string sql = @"DELETE {0}m - FROM my_aspnet_users u, my_aspnet_membership m - WHERE u.id=m.userId AND u.id=@userId"; - - MySqlCommand cmd = new MySqlCommand( - String.Format(sql, deleteAllRelatedData ? "u," : ""), conn); - cmd.Parameters.AddWithValue("@appId", app.FetchId(conn)); - cmd.Parameters.AddWithValue("@userId", userId); - return cmd.ExecuteNonQuery() > 0; - } - } - catch (MySqlException e) - { - if (WriteExceptionsToEventLog) - WriteToEventLog(e, "DeleteUser"); - throw new ProviderException(exceptionMessage, e); - } - } - - /// - /// Gets a collection of all the users in the data source in pages of data. - /// - /// The index of the page of results to return. is zero-based. - /// The size of the page of results to return. - /// The total number of matched users. - /// - /// A collection that contains a page of objects beginning at the page specified by . - /// - public override MembershipUserCollection GetAllUsers(int pageIndex, - int pageSize, out int totalRecords) - { - return GetUsers(null, null, pageIndex, pageSize, out totalRecords); - } - - /// - /// Gets the number of users currently accessing the application. - /// - /// - /// The number of users currently accessing the application. - /// - public override int GetNumberOfUsersOnline() - { - TimeSpan onlineSpan = new TimeSpan(0, Membership.UserIsOnlineTimeWindow, 0); - DateTime compareTime = DateTime.Now.Subtract(onlineSpan); - - try - { - using (MySqlConnection connection = new MySqlConnection(connectionString)) - { - connection.Open(); - MySqlCommand cmd = new MySqlCommand( - @"SELECT COUNT(*) FROM my_aspnet_membership m JOIN my_aspnet_users u - ON m.userId=u.id WHERE m.LastActivityDate > @date AND u.applicationId=@appId", - connection); - cmd.Parameters.AddWithValue("@date", compareTime); - cmd.Parameters.AddWithValue("@appId", app.FetchId(connection)); - return Convert.ToInt32(cmd.ExecuteScalar()); - } - } - catch (MySqlException e) - { - if (WriteExceptionsToEventLog) - WriteToEventLog(e, "GetNumberOfUsersOnline"); - throw new ProviderException(exceptionMessage, e); - } - } - - /// - /// Gets the password for the specified user name from the data source. - /// - /// The user to retrieve the password for. - /// The password answer for the user. - /// - /// The password for the specified user name. - /// - public override string GetPassword(string username, string answer) - { - if (!EnablePasswordRetrieval) - throw new ProviderException(Properties.Resources.PasswordRetrievalNotEnabled); - - try - { - using (MySqlConnection connection = new MySqlConnection(connectionString)) - { - connection.Open(); - - int userId = GetUserId(connection, username); - if (-1 == userId) - throw new ProviderException("Username not found."); - - string sql = @"SELECT Password, PasswordAnswer, PasswordKey, PasswordFormat, - IsLockedOut FROM my_aspnet_membership WHERE userId=@userId"; - MySqlCommand cmd = new MySqlCommand(sql, connection); - cmd.Parameters.AddWithValue("@userId", userId); - - using (MySqlDataReader reader = cmd.ExecuteReader(CommandBehavior.SingleRow)) - { - reader.Read(); - if (reader.GetBoolean("IsLockedOut")) - throw new MembershipPasswordException(Properties.Resources.UserIsLockedOut); - - string password = reader.GetString("Password"); - string passwordAnswer = reader.GetValue(reader.GetOrdinal("PasswordAnswer")).ToString(); - string passwordKey = reader.GetString("PasswordKey"); - MembershipPasswordFormat format = (MembershipPasswordFormat)reader.GetInt32(3); - reader.Close(); - - if (RequiresQuestionAndAnswer && - !(CheckPassword(answer, passwordAnswer, passwordKey, format))) - { - UpdateFailureCount(userId, "PasswordAnswer", connection); - throw new MembershipPasswordException(Properties.Resources.IncorrectPasswordAnswer); - } - if (PasswordFormat == MembershipPasswordFormat.Encrypted) - { - password = UnEncodePassword(password, format); - } - return password; - } - } - } - catch (MySqlException e) - { - if (WriteExceptionsToEventLog) - WriteToEventLog(e, "GetPassword"); - throw new ProviderException(exceptionMessage, e); - } - } - - /// - /// Gets information from the data source for a user. Provides an option to update the last-activity date/time stamp for the user. - /// - /// The name of the user to get information for. - /// true to update the last-activity date/time stamp for the user; false to return user information without updating the last-activity date/time stamp for the user. - /// - /// A object populated with the specified user's information from the data source. - /// - public override MembershipUser GetUser(string username, bool userIsOnline) - { - try - { - int userId = -1; - using (MySqlConnection connection = new MySqlConnection(connectionString)) - { - connection.Open(); - - userId = GetUserId(connection, username); - if (-1 == userId) return null; - } - - return GetUser(userId, userIsOnline); - } - catch (MySqlException e) - { - if (WriteExceptionsToEventLog) - WriteToEventLog(e, "GetUser(String, Boolean)"); - throw new ProviderException(exceptionMessage, e); - } - } - - /// - /// Gets user information from the data source based on the unique identifier for the membership user. Provides an option to update the last-activity date/time stamp for the user. - /// - /// The unique identifier for the membership user to get information for. - /// true to update the last-activity date/time stamp for the user; false to return user information without updating the last-activity date/time stamp for the user. - /// - /// A object populated with the specified user's information from the data source. - /// - public override MembershipUser GetUser(object providerUserKey, bool userIsOnline) - { - MySqlTransaction txn = null; - - try - { - using (MySqlConnection connection = new MySqlConnection(connectionString)) - { - connection.Open(); - - txn = connection.BeginTransaction(); - MySqlCommand cmd = new MySqlCommand("", connection); - cmd.Parameters.AddWithValue("@userId", providerUserKey); - - if (userIsOnline) - { - cmd.CommandText = - @"UPDATE my_aspnet_users SET lastActivityDate = @date WHERE id=@userId"; - cmd.Parameters.AddWithValue("@date", DateTime.Now); - cmd.ExecuteNonQuery(); - - cmd.CommandText = "UPDATE my_aspnet_membership SET LastActivityDate=@date WHERE userId=@userId"; - cmd.ExecuteNonQuery(); - } - - cmd.CommandText = @"SELECT m.*,u.name - FROM my_aspnet_membership m JOIN my_aspnet_users u ON m.userId=u.id - WHERE u.id=@userId"; - - MembershipUser user; - using (MySqlDataReader reader = cmd.ExecuteReader()) - { - if (!reader.Read()) return null; - user = GetUserFromReader(reader); - } - txn.Commit(); - return user; - } - } - catch (MySqlException e) - { - if (txn != null) - txn.Rollback(); - if (WriteExceptionsToEventLog) - WriteToEventLog(e, "GetUser(Object, Boolean)"); - throw new ProviderException(exceptionMessage); - } - } - - /// - /// Unlocks the user. - /// - /// The username. - /// true if the membership user was successfully unlocked; - /// otherwise, false. A value of false is also returned if the user - /// does not exist in the database. - public override bool UnlockUser(string username) - { - try - { - using (MySqlConnection conn = new MySqlConnection(connectionString)) - { - conn.Open(); - - int userId = GetUserId(conn, username); - if (-1 == userId) return false; - - string sql = @"UPDATE my_aspnet_membership - SET IsLockedOut = false, LastLockedOutDate = @lastDate - WHERE userId=@userId"; - - MySqlCommand cmd = new MySqlCommand(sql, conn); - cmd.Parameters.AddWithValue("@lastDate", DateTime.Now); - cmd.Parameters.AddWithValue("@userId", userId); - return cmd.ExecuteNonQuery() > 0; - } - } - catch (MySqlException e) - { - if (WriteExceptionsToEventLog) - WriteToEventLog(e, "UnlockUser"); - throw new ProviderException(exceptionMessage, e); - } - } - - /// - /// Gets the user name associated with the specified e-mail address. - /// - /// The e-mail address to search for. - /// - /// The user name associated with the specified e-mail address. If no match is found, return null. - /// - public override string GetUserNameByEmail(string email) - { - try - { - using (MySqlConnection conn = new MySqlConnection(connectionString)) - { - conn.Open(); - - string sql = @"SELECT u.name FROM my_aspnet_users u - JOIN my_aspnet_membership m ON m.userid=u.id - WHERE m.Email = @email AND u.applicationId=@appId"; - MySqlCommand cmd = new MySqlCommand(sql, conn); - cmd.Parameters.AddWithValue("@email", email); - cmd.Parameters.AddWithValue("@appId", app.FetchId(conn)); - return (string)cmd.ExecuteScalar(); - } - } - catch (MySqlException e) - { - if (WriteExceptionsToEventLog) - WriteToEventLog(e, "GetUserNameByEmail"); - throw new ProviderException(exceptionMessage); - } - } - - /// - /// Resets a user's password to a new, automatically generated password. - /// - /// The user to reset the password for. - /// The password answer for the specified user. - /// The new password for the specified user. - public override string ResetPassword(string username, string answer) - { - if (!(EnablePasswordReset)) - throw new NotSupportedException(Properties.Resources.PasswordResetNotEnabled); - - try - { - using (MySqlConnection connection = new MySqlConnection(connectionString)) - { - connection.Open(); - - // fetch the userid first - int userId = GetUserId(connection, username); - if (-1 == userId) - throw new ProviderException(Properties.Resources.UsernameNotFound); - - if (answer == null && RequiresQuestionAndAnswer) - { - UpdateFailureCount(userId, "PasswordAnswer", connection); - throw new ProviderException(Properties.Resources.PasswordRequiredForReset); - } - - string newPassword = Membership.GeneratePassword(newPasswordLength, MinRequiredNonAlphanumericCharacters); - ValidatePasswordEventArgs Args = new ValidatePasswordEventArgs(username, newPassword, true); - OnValidatingPassword(Args); - if (Args.Cancel) - { - if (!(Args.FailureInformation == null)) - throw Args.FailureInformation; - else - throw new MembershipPasswordException(Properties.Resources.PasswordResetCanceledNotValid); - } - - MySqlCommand cmd = new MySqlCommand(@"SELECT PasswordAnswer, - PasswordKey, PasswordFormat, IsLockedOut - FROM my_aspnet_membership WHERE userId=@userId", connection); - cmd.Parameters.AddWithValue("@userId", userId); - - string passwordKey = String.Empty; - MembershipPasswordFormat format; - using (MySqlDataReader reader = cmd.ExecuteReader(CommandBehavior.SingleRow)) - { - reader.Read(); - if (reader.GetBoolean("IsLockedOut")) - throw new MembershipPasswordException(Properties.Resources.UserIsLockedOut); - - object passwordAnswer = reader.GetValue(reader.GetOrdinal("PasswordAnswer")); - passwordKey = reader.GetString("PasswordKey"); - format = (MembershipPasswordFormat)reader.GetByte("PasswordFormat"); - reader.Close(); - - if (RequiresQuestionAndAnswer) - { - if (!CheckPassword(answer, (string)passwordAnswer, passwordKey, format)) - { - UpdateFailureCount(userId, "PasswordAnswer", connection); - throw new MembershipPasswordException(Properties.Resources.IncorrectPasswordAnswer); - } - } - } - - cmd.CommandText = @"UPDATE my_aspnet_membership - SET Password = @pass, LastPasswordChangedDate = @lastPassChange - WHERE userId=@userId"; - - cmd.Parameters.AddWithValue("@pass", - EncodePassword(newPassword, passwordKey, format)); - cmd.Parameters.AddWithValue("@lastPassChange", DateTime.Now); - int rowsAffected = cmd.ExecuteNonQuery(); - if (rowsAffected != 1) - throw new MembershipPasswordException(Properties.Resources.ErrorResettingPassword); - return newPassword; - } - } - catch (MySqlException e) - { - if (WriteExceptionsToEventLog) - WriteToEventLog(e, "ResetPassword"); - throw new ProviderException(exceptionMessage, e); - } - } - - /// - /// Updates information about a user in the data source. - /// - /// A object - /// that represents the user to update and the updated information for the user. - public override void UpdateUser(MembershipUser user) - { - try - { - using (MySqlConnection conn = new MySqlConnection(connectionString)) - { - conn.Open(); - - int userId = GetUserId(conn, user.UserName); - if (-1 == userId) - throw new ProviderException(Properties.Resources.UsernameNotFound); - - string sql = @"UPDATE my_aspnet_membership m, my_aspnet_users u - SET m.Email=@email, m.Comment=@comment, m.IsApproved=@isApproved, - m.LastLoginDate=@lastLoginDate, u.lastActivityDate=@lastActivityDate, - m.LastActivityDate=@lastActivityDate - WHERE m.userId=u.id AND u.name LIKE @name AND u.applicationId=@appId"; - MySqlCommand cmd = new MySqlCommand(sql, conn); - cmd.Parameters.AddWithValue("@Email", user.Email); - cmd.Parameters.AddWithValue("@Comment", user.Comment); - cmd.Parameters.AddWithValue("@isApproved", user.IsApproved); - cmd.Parameters.AddWithValue("@lastLoginDate", user.LastLoginDate); - cmd.Parameters.AddWithValue("@lastActivityDate", user.LastActivityDate); - cmd.Parameters.AddWithValue("@name", user.UserName); - cmd.Parameters.AddWithValue("@appId", app.FetchId(conn)); - cmd.ExecuteNonQuery(); - } - } - catch (MySqlException e) - { - if (WriteExceptionsToEventLog) - WriteToEventLog(e, "UpdateUser"); - throw new ProviderException(exceptionMessage); - } - } - - /// - /// Verifies that the specified user name and password exist in the data source. - /// - /// The name of the user to validate. - /// The password for the specified user. - /// - /// true if the specified username and password are valid; otherwise, false. - /// - public override bool ValidateUser(string username, string password) - { - bool isValid = false; - try - { - using (MySqlConnection connection = new MySqlConnection(connectionString)) - { - connection.Open(); - - // first get the user id. If that is -1, then the user doesn't exist - // so we just return false since we can't bump any counters - int userId = GetUserId(connection, username); - if (-1 == userId) return false; - - string sql = @"SELECT Password, PasswordKey, PasswordFormat, IsApproved, - Islockedout FROM my_aspnet_membership WHERE userId=@userId"; - MySqlCommand cmd = new MySqlCommand(sql, connection); - cmd.Parameters.AddWithValue("@userId", userId); - - using (MySqlDataReader reader = cmd.ExecuteReader(CommandBehavior.SingleRow)) - { - if (!reader.HasRows) return false; - reader.Read(); - if (reader.GetBoolean("IsLockedOut")) return false; - - string pwd = reader.GetString(0); - string passwordKey = reader.GetString(1); - MembershipPasswordFormat format = (MembershipPasswordFormat) - reader.GetInt32(2); - bool isApproved = reader.GetBoolean(3); - reader.Close(); - - if (!CheckPassword(password, pwd, passwordKey, format)) - UpdateFailureCount(userId, "Password", connection); - else if (isApproved) - { - isValid = true; - DateTime currentDate = DateTime.Now; - MySqlCommand updateCmd = new MySqlCommand( - @"UPDATE my_aspnet_membership m, my_aspnet_users u - SET m.LastLoginDate = @lastLoginDate, u.lastActivityDate = @date, - m.LastActivityDate=@date - WHERE m.userId=@userid AND u.id=@userid", connection); - updateCmd.Parameters.AddWithValue("@lastLoginDate", currentDate); - updateCmd.Parameters.AddWithValue("@date", currentDate); - updateCmd.Parameters.AddWithValue("@userid", userId); - updateCmd.ExecuteNonQuery(); - } - } - return isValid; - } - } - catch (MySqlException e) - { - if (WriteExceptionsToEventLog) - WriteToEventLog(e, "ValidateUser"); - throw new ProviderException(exceptionMessage, e); - } - } - - /// - /// Gets a collection of membership users where the user name contains the specified user name to match. - /// - /// The user name to search for. - /// The index of the page of results to return. is zero-based. - /// The size of the page of results to return. - /// The total number of matched users. - /// - /// A collection that contains a page of objects beginning at the page specified by . - /// - public override MembershipUserCollection FindUsersByName(string usernameToMatch, - int pageIndex, int pageSize, out int totalRecords) - { - return GetUsers(usernameToMatch, null, pageIndex, pageSize, out totalRecords); - } - - /// - /// Gets a collection of membership users where the e-mail address contains the specified e-mail address to match. - /// - /// The e-mail address to search for. - /// The index of the page of results to return. is zero-based. - /// The size of the page of results to return. - /// The total number of matched users. - /// - /// A collection that contains a page of objects beginning at the page specified by . - /// - public override MembershipUserCollection FindUsersByEmail(string emailToMatch, int pageIndex, - int pageSize, out int totalRecords) - { - return GetUsers(null, emailToMatch, pageIndex, pageSize, out totalRecords); - } - - #endregion - - #region Private Methods - - private int GetUserId(MySqlConnection connection, string username) - { - MySqlCommand cmd = new MySqlCommand( - "SELECT id FROM my_aspnet_users WHERE name = @name AND applicationId=@appId", connection); - cmd.Parameters.AddWithValue("@name", username); - cmd.Parameters.AddWithValue("@appId", app.FetchId(connection)); - object id = cmd.ExecuteScalar(); - if (id == null) return -1; - return (int)id; - } - - private void WriteToEventLog(Exception e, string action) - { - using (EventLog log = new EventLog()) - { - log.Source = eventSource; - log.Log = eventLog; - string message = "An exception occurred communicating with the data source." + - Environment.NewLine + Environment.NewLine; - message += "Action: " + action + Environment.NewLine + Environment.NewLine; - message += "Exception: " + e; - log.WriteEntry(message); - } - } - - private MembershipUser GetUserFromReader(MySqlDataReader reader) - { - object providerUserKey = reader.GetInt32("userId"); - string username = reader.GetString("name"); - - string email = null; - if (!reader.IsDBNull(reader.GetOrdinal("Email"))) - email = reader.GetString("Email"); - - string passwordQuestion = ""; - if (!(reader.GetValue(reader.GetOrdinal("PasswordQuestion")) == DBNull.Value)) - passwordQuestion = reader.GetString("PasswordQuestion"); - - string comment = ""; - if (!(reader.GetValue(reader.GetOrdinal("Comment")) == DBNull.Value)) - comment = reader.GetString("Comment"); - - bool isApproved = reader.GetBoolean("IsApproved"); - bool isLockedOut = reader.GetBoolean("IsLockedOut"); - DateTime creationDate = reader.GetDateTime("CreationDate"); - DateTime lastLoginDate = new DateTime(); - if (!(reader.GetValue(reader.GetOrdinal("LastLoginDate")) == DBNull.Value)) - lastLoginDate = reader.GetDateTime("LastLoginDate"); - - DateTime lastActivityDate = reader.GetDateTime("LastActivityDate"); - DateTime lastPasswordChangedDate = reader.GetDateTime("LastPasswordChangedDate"); - DateTime lastLockedOutDate = new DateTime(); - if (!(reader.GetValue(reader.GetOrdinal("LastLockedoutDate")) == DBNull.Value)) - lastLockedOutDate = reader.GetDateTime("LastLockedoutDate"); - - MembershipUser u = - new MembershipUser(Name, username, providerUserKey, email, passwordQuestion, comment, isApproved, - isLockedOut, creationDate, lastLoginDate, lastActivityDate, lastPasswordChangedDate, - lastLockedOutDate); - return u; - } - - private string UnEncodePassword(string encodedPassword, MembershipPasswordFormat format) - { - string password = encodedPassword; - if (format == MembershipPasswordFormat.Clear) - return encodedPassword; - else if (format == MembershipPasswordFormat.Encrypted) - return Encoding.Unicode.GetString(DecryptPassword( - Convert.FromBase64String(password))); - else if (format == MembershipPasswordFormat.Hashed) - throw new ProviderException(Properties.Resources.CannotUnencodeHashedPwd); - else - throw new ProviderException(Properties.Resources.UnsupportedPasswordFormat); - } - - private string GetPasswordKey() - { - RNGCryptoServiceProvider cryptoProvider = - new RNGCryptoServiceProvider(); - byte[] key = new byte[16]; - cryptoProvider.GetBytes(key); - return Convert.ToBase64String(key); - } - - /// - /// this method is only necessary because early versions of Mono did not support - /// the HashAlgorithmType property - /// - /// - /// - /// - private string HashPasswordBytes(byte[] key, byte[] bytes) - { - HashAlgorithm hash = HashAlgorithm.Create(Membership.HashAlgorithmType); - - if (hash is KeyedHashAlgorithm) - { - KeyedHashAlgorithm keyedHash = hash as KeyedHashAlgorithm; - keyedHash.Key = key; - } - return Convert.ToBase64String(hash.ComputeHash(bytes)); - } - - private string EncodePassword(string password, string passwordKey, - MembershipPasswordFormat format) - { - if (password == null) - return null; - if (format == MembershipPasswordFormat.Clear) - return password; - - byte[] passwordBytes = Encoding.Unicode.GetBytes(password); - byte[] keyBytes = Convert.FromBase64String(passwordKey); - byte[] keyedBytes = new byte[passwordBytes.Length + keyBytes.Length]; - Array.Copy(keyBytes, keyedBytes, keyBytes.Length); - Array.Copy(passwordBytes, 0, keyedBytes, keyBytes.Length, passwordBytes.Length); - - if (format == MembershipPasswordFormat.Encrypted) - { - byte[] encryptedBytes = EncryptPassword(passwordBytes); - return Convert.ToBase64String(encryptedBytes); - } - else if (format == MembershipPasswordFormat.Hashed) - return HashPasswordBytes(keyBytes, keyedBytes); - else - throw new ProviderException(Properties.Resources.UnsupportedPasswordFormat); - } - - private void UpdateFailureCount(int userId, string failureType, MySqlConnection connection) - { - MySqlCommand cmd = new MySqlCommand( - @"SELECT FailedPasswordAttemptCount, - FailedPasswordAttemptWindowStart, FailedPasswordAnswerAttemptCount, - FailedPasswordAnswerAttemptWindowStart FROM my_aspnet_membership - WHERE userId=@userId", connection); - cmd.Parameters.AddWithValue("@userId", userId); - - DateTime windowStart = new DateTime(); - int failureCount = 0; - try - { - using (MySqlDataReader reader = cmd.ExecuteReader(CommandBehavior.SingleRow)) - { - if (!reader.HasRows) - throw new ProviderException(Properties.Resources.UnableToUpdateFailureCount); - - reader.Read(); - if (failureType == "Password") - { - failureCount = reader.GetInt32(0); - windowStart = reader.GetDateTime(1); - } - if (failureType == "PasswordAnswer") - { - failureCount = reader.GetInt32(2); - windowStart = reader.GetDateTime(3); - } - } - - DateTime windowEnd = windowStart.AddMinutes(PasswordAttemptWindow); - if (failureCount == 0 || DateTime.Now > windowEnd) - { - if (failureType == "Password") - { - cmd.CommandText = - @"UPDATE my_aspnet_membership - SET FailedPasswordAttemptCount = @count, - FailedPasswordAttemptWindowStart = @windowStart - WHERE userId=@userId"; - } - if (failureType == "PasswordAnswer") - { - cmd.CommandText = - @"UPDATE my_aspnet_membership - SET FailedPasswordAnswerAttemptCount = @count, - FailedPasswordAnswerAttemptWindowStart = @windowStart - WHERE userId = @userId"; - } - cmd.Parameters.Clear(); - cmd.Parameters.AddWithValue("@count", 1); - cmd.Parameters.AddWithValue("@windowStart", DateTime.Now); - cmd.Parameters.AddWithValue("@userId", userId); - if (cmd.ExecuteNonQuery() < 0) - throw new ProviderException(Properties.Resources.UnableToUpdateFailureCount); - } - else - { - failureCount += 1; - if (failureCount >= MaxInvalidPasswordAttempts) - { - cmd.CommandText = - @"UPDATE my_aspnet_membership SET IsLockedOut = @isLockedOut, - LastLockedOutDate = @lastLockedOutDate WHERE userId=@userId"; - cmd.Parameters.Clear(); - cmd.Parameters.AddWithValue("@isLockedOut", true); - cmd.Parameters.AddWithValue("@lastLockedOutDate", DateTime.Now); - cmd.Parameters.AddWithValue("@userId", userId); - if (cmd.ExecuteNonQuery() < 0) - throw new ProviderException(Properties.Resources.UnableToLockOutUser); - } - else - { - if (failureType == "Password") - { - cmd.CommandText = - @"UPDATE my_aspnet_membership - SET FailedPasswordAttemptCount = @count WHERE userId=@userId"; - } - if (failureType == "PasswordAnswer") - { - cmd.CommandText = - @"UPDATE my_aspnet_membership - SET FailedPasswordAnswerAttemptCount = @count - WHERE userId=@userId"; - } - cmd.Parameters.Clear(); - cmd.Parameters.AddWithValue("@count", failureCount); - cmd.Parameters.AddWithValue("@userId", userId); - if (cmd.ExecuteNonQuery() < 0) - throw new ProviderException("Unable to update failure count."); - } - } - } - catch (MySqlException e) - { - if (WriteExceptionsToEventLog) - WriteToEventLog(e, "UpdateFailureCount"); - throw new ProviderException(exceptionMessage, e); - } - } - - private bool CheckPassword(string password, string dbpassword, - string passwordKey, MembershipPasswordFormat format) - { - password = EncodePassword(password, passwordKey, format); - return password == dbpassword; - } - - private void GetPasswordInfo(MySqlConnection connection, int userId, - out string passwordKey, out MembershipPasswordFormat passwordFormat) - { - MySqlCommand cmd = new MySqlCommand( - @"SELECT PasswordKey, PasswordFormat FROM my_aspnet_membership WHERE - userId=@userId", connection); - cmd.Parameters.AddWithValue("@userId", userId); - using (MySqlDataReader reader = cmd.ExecuteReader()) - { - reader.Read(); - passwordKey = reader.GetString(reader.GetOrdinal("PasswordKey")); - passwordFormat = (MembershipPasswordFormat)reader.GetByte( - reader.GetOrdinal("PasswordFormat")); - } - } - - private MembershipUserCollection GetUsers(string username, string email, - int pageIndex, int pageSize, out int totalRecords) - { - MembershipUserCollection users = new MembershipUserCollection(); - try - { - using (MySqlConnection connection = new MySqlConnection(connectionString)) - { - connection.Open(); - MySqlCommand cmd = new MySqlCommand(); - cmd.Connection = connection; - - string sql = @"SELECT SQL_CALC_FOUND_ROWS u.name,m.* FROM my_aspnet_users u - JOIN my_aspnet_membership m ON m.userId=u.id - WHERE u.applicationId=@appId"; - - if (username != null) - { - sql += " AND u.name LIKE @name"; - cmd.Parameters.AddWithValue("@name", username); - } - else if (email != null) - { - sql += " AND m.Email LIKE @email"; - cmd.Parameters.AddWithValue("@email", email); - } - sql += " ORDER BY u.id ASC LIMIT {0},{1}"; - cmd.CommandText = String.Format(sql, pageIndex * pageSize, pageSize); - cmd.Parameters.AddWithValue("@appId", app.FetchId(connection)); - using (MySqlDataReader reader = cmd.ExecuteReader()) - { - while (reader.Read()) - users.Add(GetUserFromReader(reader)); - } - cmd.CommandText = "SELECT FOUND_ROWS()"; - cmd.Parameters.Clear(); - totalRecords = Convert.ToInt32(cmd.ExecuteScalar()); - } - return users; - } - catch (MySqlException e) - { - if (WriteExceptionsToEventLog) - WriteToEventLog(e, "GetUsers"); - throw new ProviderException(exceptionMessage); - } - } - - private void ValidateQA(string question, string answer) - { - if (RequiresQuestionAndAnswer && String.IsNullOrEmpty(question)) - throw new ArgumentException(Properties.Resources.PasswordQuestionInvalid); - if (RequiresQuestionAndAnswer && String.IsNullOrEmpty(answer)) - throw new ArgumentException(Properties.Resources.PasswordAnswerInvalid); - } - - private bool ValidatePassword(string password, string argumentName, bool throwExceptions) - { - string exceptionString = null; - object correctValue = MinRequiredPasswordLength; - - if (password.Length < MinRequiredPasswordLength) - exceptionString = Properties.Resources.PasswordNotLongEnough; - else - { - int count = 0; - foreach (char c in password) - if (!char.IsLetterOrDigit(c)) - count++; - if (count < MinRequiredNonAlphanumericCharacters) - exceptionString = Properties.Resources.NotEnoughNonAlphaNumericInPwd; - correctValue = MinRequiredNonAlphanumericCharacters; - } - - if (exceptionString != null) - { - if (throwExceptions) - throw new ArgumentException( - string.Format(exceptionString, argumentName, correctValue), - argumentName); - else - return false; - } - - if (PasswordStrengthRegularExpression.Length > 0) - if (!Regex.IsMatch(password, PasswordStrengthRegularExpression)) - return false; - - return true; - } - - private void TrimParametersValues(ref string username, ref string password, ref string email, ref string passwordQuestion, ref string passwordAnswer) - { - username = string.IsNullOrEmpty(username) ? username : username.Trim(); - password = string.IsNullOrEmpty(password) ? password : password.Trim(); - email = string.IsNullOrEmpty(email) ? email : email.Trim(); - passwordQuestion = string.IsNullOrEmpty(passwordQuestion) ? passwordQuestion : passwordQuestion.Trim(); - passwordAnswer = string.IsNullOrEmpty(passwordAnswer) ? passwordAnswer : passwordAnswer.Trim(); - } - - #endregion - } -} +// Copyright © 2004, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +// This code was contributed by Sean Wright (srwright@alcor.concordia.ca) on 2007-01-12 +// The copyright was assigned and transferred under the terms of +// the MySQL Contributor License Agreement (CLA) + +using MySql.Data.MySqlClient; +using MySql.Web.Common; +using MySql.Web.General; +using MySql.Web.Profile; +using System; +using System.Collections.Specialized; +using System.Configuration.Provider; +using System.Data; +using System.Diagnostics; +using System.Security.Cryptography; +using System.Text; +using System.Text.RegularExpressions; +using System.Web.Hosting; +using System.Web.Security; + +namespace MySql.Web.Security +{ + /// + /// Manages storage of membership information for an ASP.NET application in a MySQL database. + /// + /// + /// + /// This class is used by the and classes + /// to provide membership services for ASP.NET applications using a MySQL database. + /// + /// + /// + /// + /// configuration> + /// connectionStrings> + /// add name = "LocalMySqlService" connectionString="server=localhost;user id=myuser;password=mypass;database=test" /> + /// /connectionStrings> + /// system.web> + /// authentication mode = "Forms" > + /// forms loginUrl="login.aspx" name=".ASPXFORMSAUTH" /> + /// /authentication> + /// authorization> + /// deny users = "?" /> + /// /authorization> + /// membership defaultProvider="MySQLProvider" userIsOnlineTimeWindow="15"> + /// providers> + /// add + /// name = "MySQLProvider" + /// type="MySql.Web.Security.MySQLMembershipProvider" + /// connectionStringName="LocalMySqlService" + /// applicationName="MyApplication" + /// enablePasswordRetrieval="false" + /// enablePasswordReset="true" + /// requiresQuestionAndAnswer="true" + /// requiresUniqueEmail="false" + /// passwordFormat="Hashed" + /// maxInvalidPasswordAttempts="5" + /// passwordAttemptWindow="10" /> + /// /providers> + /// /membership> + /// /system.web> + /// /configuration> + /// + /// + public sealed class MySQLMembershipProvider : MembershipProvider + { + private int newPasswordLength = 8; + private string eventSource = "MySQLMembershipProvider"; + private string eventLog = "Application"; + private string exceptionMessage = "An exception occurred. Please check the Event Log."; + private string connectionString; + private int minRequiredPasswordLength; + private bool writeExceptionsToEventLog; + private bool enablePasswordReset; + private bool enablePasswordRetrieval; + private bool requiresQuestionAndAnswer; + private bool requiresUniqueEmail; + private int maxInvalidPasswordAttempts; + private int passwordAttemptWindow; + private MembershipPasswordFormat passwordFormat; + private int minRequiredNonAlphanumericCharacters; + private string passwordStrengthRegularExpression; + private Application app; + + /// + /// Initializes the MySQL membership provider with the property values specified in the + /// ASP.NET application's configuration file. This method is not intended to be used directly + /// from your code. + /// + /// The name of the instance to initialize. + /// A collection of the name/value pairs representing the + /// provider-specific attributes specified in the configuration for this provider. + /// config is a null reference. + /// An attempt is made to call on a provider after the provider has already been initialized. + /// + public override void Initialize(string name, NameValueCollection config) + { + if (config == null) + { + throw new ArgumentNullException("config"); + } + if (name == null || name.Length == 0) + { + name = "MySQLMembershipProvider"; + } + if (string.IsNullOrEmpty(config["description"])) + { + config.Remove("description"); + config.Add("description", "MySQL default application"); + } + base.Initialize(name, config); + + string applicationName = GetConfigValue(config["applicationName"], + HostingEnvironment.ApplicationVirtualPath); + maxInvalidPasswordAttempts = Convert.ToInt32(GetConfigValue(config["maxInvalidPasswordAttempts"], "5")); + passwordAttemptWindow = Convert.ToInt32(GetConfigValue(config["passwordAttemptWindow"], "10")); + minRequiredNonAlphanumericCharacters = + Convert.ToInt32(GetConfigValue(config["minRequiredNonalphanumericCharacters"], "1")); + minRequiredPasswordLength = Convert.ToInt32(GetConfigValue(config["minRequiredPasswordLength"], "7")); + passwordStrengthRegularExpression = + Convert.ToString(GetConfigValue(config["passwordStrengthRegularExpression"], "")); + enablePasswordReset = Convert.ToBoolean(GetConfigValue(config["enablePasswordReset"], "True")); + enablePasswordRetrieval = Convert.ToBoolean( + GetConfigValue(config["enablePasswordRetrieval"], "False")); + requiresQuestionAndAnswer = Convert.ToBoolean(GetConfigValue(config["requiresQuestionAndAnswer"], "False")); + requiresUniqueEmail = Convert.ToBoolean(GetConfigValue(config["requiresUniqueEmail"], "True")); + writeExceptionsToEventLog = Convert.ToBoolean(GetConfigValue(config["writeExceptionsToEventLog"], "True")); + string temp_format = config["passwordFormat"]; + + if (temp_format == null) + temp_format = "hashed"; + else + temp_format = temp_format.ToLowerInvariant(); + + if (temp_format == "hashed") + passwordFormat = MembershipPasswordFormat.Hashed; + else if (temp_format == "encrypted") + passwordFormat = MembershipPasswordFormat.Encrypted; + else if (temp_format == "clear") + passwordFormat = MembershipPasswordFormat.Clear; + else + throw new ProviderException("Password format not supported."); + + // if the user is asking for the ability to retrieve hashed passwords, then let + // them know we can't + if (PasswordFormat == MembershipPasswordFormat.Hashed) + { + if (EnablePasswordRetrieval) + throw new ProviderException(Properties.Resources.CannotRetrieveHashedPasswords); + } + + connectionString = ConfigUtility.GetConnectionString(config); + if (String.IsNullOrEmpty(connectionString)) return; + + // make sure we have the correct schema + SchemaManager.CheckSchema(connectionString, config); + + app = new Application(applicationName, base.Description); + } + + private static string GetConfigValue(string configValue, string defaultValue) + { + if (string.IsNullOrEmpty(configValue)) + { + return defaultValue; + } + return configValue; + } + + #region Properties + + /// + /// The name of the application using the MySQL membership provider. + /// + /// The name of the application using the MySQL membership provider. The default is the + /// application virtual path. + /// The ApplicationName is used by the MySqlMembershipProvider to separate + /// membership information for multiple applications. Using different application names, + /// applications can use the same membership database. + /// Likewise, multiple applications can make use of the same membership data by simply using + /// the same application name. + /// Caution should be taken with multiple applications as the ApplicationName property is not + /// thread safe during writes. + /// + /// + /// The following example shows the membership element being used in an applications web.config file. + /// The application name setting is being used. + /// + /// membership defaultProvider="MySQLMembershipProvider"> + /// providers> + /// add name="MySqlMembershipProvider" + /// type="MySql.Web.Security.MySQLMembershipProvider" + /// connectionStringName="LocalMySqlServer" + /// enablePasswordRetrieval="true" + /// enablePasswordReset="false" + /// requiresQuestionAndAnswer="true" + /// requiresUniqueEmail="false" + /// passwordFormat="Encrypted" + /// maxInvalidPasswordAttempts="3" + /// passwordAttemptWindow="20" + /// minRequiredNonAlphanumericCharacters="1" + /// minRequiredPasswordLength="11" + /// applicationName="MyApplication" /> + /// /providers> + /// /membership> + /// + /// + public override string ApplicationName + { + get { return app.Name; } + set + { + lock (this) + { + if (value.ToLowerInvariant() == app.Name.ToLowerInvariant()) return; + app = new Application(value, String.Empty); + } + } + } + + /// + /// Indicates whether the membership provider is configured to allow users to reset their passwords. + /// + /// true if the membership provider supports password reset; otherwise, false. The default is true. + /// Allows the user to replace their password with a new, randomly generated password. + /// This can be especially handy when using hashed passwords since hashed passwords cannot be + /// retrieved. + /// + /// The following example shows the membership element being used in an applications web.config file. + /// + /// membership defaultProvider="MySQLMembershipProvider"> + /// providers> + /// add name="MySqlMembershipProvider" + /// type="MySql.Web.Security.MySQLMembershipProvider" + /// connectionStringName="LocalMySqlServer" + /// enablePasswordRetrieval="true" + /// enablePasswordReset="false" + /// requiresQuestionAndAnswer="true" + /// requiresUniqueEmail="false" + /// passwordFormat="Encrypted" + /// maxInvalidPasswordAttempts="3" + /// passwordAttemptWindow="20" + /// minRequiredNonAlphanumericCharacters="1" + /// minRequiredPasswordLength="11" + /// applicationName="MyApplication" /> + /// /providers> + /// /membership> + /// + /// + public override bool EnablePasswordReset + { + get { return enablePasswordReset; } + } + + /// + /// Indicates whether the membership provider is configured to allow users to retrieve + /// their passwords. + /// + /// true if the membership provider is configured to support password retrieval; + /// otherwise, false. The default is false. + /// If the system is configured to use hashed passwords, then retrieval is not possible. + /// If the user attempts to initialize the provider with hashed passwords and enable password retrieval + /// set to true then a is thrown. + /// + /// The following example shows the membership element being used in an applications web.config file. + /// + /// membership defaultProvider="MySQLMembershipProvider"> + /// providers> + /// add name="MySqlMembershipProvider" + /// type="MySql.Web.Security.MySQLMembershipProvider" + /// connectionStringName="LocalMySqlServer" + /// enablePasswordRetrieval="true" + /// enablePasswordReset="false" + /// requiresQuestionAndAnswer="true" + /// requiresUniqueEmail="false" + /// passwordFormat="Encrypted" + /// maxInvalidPasswordAttempts="3" + /// passwordAttemptWindow="20" + /// minRequiredNonAlphanumericCharacters="1" + /// minRequiredPasswordLength="11" + /// applicationName="MyApplication" /> + /// /providers> + /// /membership> + /// + /// + public override bool EnablePasswordRetrieval + { + get { return enablePasswordRetrieval; } + } + + /// + /// Gets a value indicating whether the membership provider is + /// configured to require the user to answer a password question + /// for password reset and retrieval. + /// + /// true if a password answer is required for password + /// reset and retrieval; otherwise, false. The default is false. + /// + /// The following example shows the membership element being used in an applications web.config file. + /// + /// membership defaultProvider="MySQLMembershipProvider"> + /// providers> + /// add name="MySqlMembershipProvider" + /// type="MySql.Web.Security.MySQLMembershipProvider" + /// connectionStringName="LocalMySqlServer" + /// enablePasswordRetrieval="true" + /// enablePasswordReset="false" + /// requiresQuestionAndAnswer="true" + /// requiresUniqueEmail="false" + /// passwordFormat="Encrypted" + /// maxInvalidPasswordAttempts="3" + /// passwordAttemptWindow="20" + /// minRequiredNonAlphanumericCharacters="1" + /// minRequiredPasswordLength="11" + /// applicationName="MyApplication" /> + /// /providers> + /// /membership> + /// + /// + public override bool RequiresQuestionAndAnswer + { + get { return requiresQuestionAndAnswer; } + } + + /// + /// Gets a value indicating whether the membership provider is configured + /// to require a unique e-mail address for each user name. + /// + /// true if the membership provider requires a unique e-mail address; + /// otherwise, false. The default is true. + /// + /// The following example shows the membership element being used in an applications web.config file. + /// + /// membership defaultProvider="MySQLMembershipProvider"> + /// providers> + /// add name="MySqlMembershipProvider" + /// type="MySql.Web.Security.MySQLMembershipProvider" + /// connectionStringName="LocalMySqlServer" + /// enablePasswordRetrieval="true" + /// enablePasswordReset="false" + /// requiresQuestionAndAnswer="true" + /// requiresUniqueEmail="false" + /// passwordFormat="Encrypted" + /// maxInvalidPasswordAttempts="3" + /// passwordAttemptWindow="20" + /// minRequiredNonAlphanumericCharacters="1" + /// minRequiredPasswordLength="11" + /// applicationName="MyApplication" /> + /// /providers> + /// /membership> + /// + /// + public override bool RequiresUniqueEmail + { + get { return requiresUniqueEmail; } + } + + /// + /// Gets the number of invalid password or password-answer attempts allowed + /// before the membership user is locked out. + /// + /// The number of invalid password or password-answer attempts allowed + /// before the membership user is locked out. + /// + /// The following example shows the membership element being used in an applications web.config file. + /// + /// membership defaultProvider="MySQLMembershipProvider"> + /// providers> + /// add name="MySqlMembershipProvider" + /// type="MySql.Web.Security.MySQLMembershipProvider" + /// connectionStringName="LocalMySqlServer" + /// enablePasswordRetrieval="true" + /// enablePasswordReset="false" + /// requiresQuestionAndAnswer="true" + /// requiresUniqueEmail="false" + /// passwordFormat="Encrypted" + /// maxInvalidPasswordAttempts="3" + /// passwordAttemptWindow="20" + /// minRequiredNonAlphanumericCharacters="1" + /// minRequiredPasswordLength="11" + /// applicationName="MyApplication" /> + /// /providers> + /// /membership> + /// + /// + public override int MaxInvalidPasswordAttempts + { + get { return maxInvalidPasswordAttempts; } + } + + /// + /// Gets the number of minutes in which a maximum number of invalid password or + /// password-answer attempts are allowed before the membership user is locked out. + /// + /// The number of minutes in which a maximum number of invalid password or + /// password-answer attempts are allowed before the membership user is locked out. + /// + /// The following example shows the membership element being used in an applications web.config file. + /// + /// membership defaultProvider="MySQLMembershipProvider"> + /// providers> + /// add name="MySqlMembershipProvider" + /// type="MySql.Web.Security.MySQLMembershipProvider" + /// connectionStringName="LocalMySqlServer" + /// enablePasswordRetrieval="true" + /// enablePasswordReset="false" + /// requiresQuestionAndAnswer="true" + /// requiresUniqueEmail="false" + /// passwordFormat="Encrypted" + /// maxInvalidPasswordAttempts="3" + /// passwordAttemptWindow="20" + /// minRequiredNonAlphanumericCharacters="1" + /// minRequiredPasswordLength="11" + /// applicationName="MyApplication" /> + /// /providers> + /// /membership> + /// + /// + public override int PasswordAttemptWindow + { + get { return passwordAttemptWindow; } + } + + /// + /// Gets a value indicating the format for storing passwords in the membership data store. + /// + /// One of the + /// values indicating the format for storing passwords in the data store. + /// + /// The following example shows the membership element being used in an applications web.config file. + /// + /// membership defaultProvider="MySQLMembershipProvider"> + /// providers> + /// add name="MySqlMembershipProvider" + /// type="MySql.Web.Security.MySQLMembershipProvider" + /// connectionStringName="LocalMySqlServer" + /// enablePasswordRetrieval="true" + /// enablePasswordReset="false" + /// requiresQuestionAndAnswer="true" + /// requiresUniqueEmail="false" + /// passwordFormat="Encrypted" + /// maxInvalidPasswordAttempts="3" + /// passwordAttemptWindow="20" + /// minRequiredNonAlphanumericCharacters="1" + /// minRequiredPasswordLength="11" + /// applicationName="MyApplication" /> + /// /providers> + /// /membership> + /// + /// + public override MembershipPasswordFormat PasswordFormat + { + get { return passwordFormat; } + } + + /// + /// Gets the minimum number of special characters that must be present in a valid password. + /// + /// The minimum number of special characters that must be present + /// in a valid password. + /// + /// The following example shows the membership element being used in an applications web.config file. + /// + /// membership defaultProvider="MySQLMembershipProvider"> + /// providers> + /// add name="MySqlMembershipProvider" + /// type="MySql.Web.Security.MySQLMembershipProvider" + /// connectionStringName="LocalMySqlServer" + /// enablePasswordRetrieval="true" + /// enablePasswordReset="false" + /// requiresQuestionAndAnswer="true" + /// requiresUniqueEmail="false" + /// passwordFormat="Encrypted" + /// maxInvalidPasswordAttempts="3" + /// passwordAttemptWindow="20" + /// minRequiredNonAlphanumericCharacters="1" + /// minRequiredPasswordLength="11" + /// applicationName="MyApplication" /> + /// /providers> + /// /membership> + /// + /// + public override int MinRequiredNonAlphanumericCharacters + { + get { return minRequiredNonAlphanumericCharacters; } + } + + /// + /// Gets the minimum length required for a password. + /// + /// The minimum length required for a password. + /// + /// The following example shows the membership element being used in an applications web.config file. + /// + /// membership defaultProvider="MySQLMembershipProvider"> + /// providers> + /// add name="MySqlMembershipProvider" + /// type="MySql.Web.Security.MySQLMembershipProvider" + /// connectionStringName="LocalMySqlServer" + /// enablePasswordRetrieval="true" + /// enablePasswordReset="false" + /// requiresQuestionAndAnswer="true" + /// requiresUniqueEmail="false" + /// passwordFormat="Encrypted" + /// maxInvalidPasswordAttempts="3" + /// passwordAttemptWindow="20" + /// minRequiredNonAlphanumericCharacters="1" + /// minRequiredPasswordLength="11" + /// applicationName="MyApplication" /> + /// /providers> + /// /membership> + /// + /// + public override int MinRequiredPasswordLength + { + get { return minRequiredPasswordLength; } + } + + /// + /// Gets the regular expression used to evaluate a password. + /// + /// A regular expression used to evaluate a password. + /// + /// The following example shows the membership element being used in an applications web.config file. + /// In this example, the regular expression specifies that the password must meet the following + /// criteria: + /// * Is at least seven characters. + /// * Contains at least one digit. + /// * Contains at least one special (non-alphanumeric) character. + /// + /// membership defaultProvider="MySQLMembershipProvider"> + /// providers> + /// add name="MySqlMembershipProvider" + /// type="MySql.Web.Security.MySQLMembershipProvider" + /// connectionStringName="LocalMySqlServer" + /// enablePasswordRetrieval="true" + /// enablePasswordReset="false" + /// requiresQuestionAndAnswer="true" + /// requiresUniqueEmail="false" + /// passwordFormat="Encrypted" + /// maxInvalidPasswordAttempts="3" + /// passwordAttemptWindow="20" + /// minRequiredNonAlphanumericCharacters="1" + /// minRequiredPasswordLength="11" + /// applicationName="MyApplication" /> + /// /providers> + /// /membership> + /// + /// + public override string PasswordStrengthRegularExpression + { + get { return passwordStrengthRegularExpression; } + } + + /// + /// Gets or sets a value indicating whether exceptions are written to the event log. + /// + /// + /// true if exceptions should be written to the log; otherwise, false. + /// + public bool WriteExceptionsToEventLog + { + get { return writeExceptionsToEventLog; } + set { writeExceptionsToEventLog = value; } + } + + #endregion + + #region Public Methods + + /// + /// Changes the password. + /// + /// The username. + /// The old password. + /// The new password. + /// true if the password was updated successfully; false if the supplied old password + /// is invalid, the user is locked out, or the user does not exist in the database. + public override bool ChangePassword(string username, string oldPassword, string newPassword) + { + // this will return false if the username doesn't exist + if (!(ValidateUser(username, oldPassword))) + return false; + + ValidatePasswordEventArgs args = new ValidatePasswordEventArgs(username, newPassword, true); + OnValidatingPassword(args); + if (args.Cancel) + { + if (!(args.FailureInformation == null)) + throw args.FailureInformation; + else + throw new ProviderException(Properties.Resources.ChangePasswordCanceled); + } + + // validate the password according to current guidelines + if (!ValidatePassword(newPassword, "newPassword", true)) + return false; + + try + { + using (MySqlConnection connection = new MySqlConnection(connectionString)) + { + connection.Open(); + + // retrieve the existing key and format for this user + string passwordKey; + MembershipPasswordFormat passwordFormat; + int userId = GetUserId(connection, username); + + GetPasswordInfo(connection, userId, out passwordKey, out passwordFormat); + + MySqlCommand cmd = new MySqlCommand( + @"UPDATE my_aspnet_membership + SET Password = @pass, LastPasswordChangedDate = @lastPasswordChangedDate + WHERE userId=@userId", connection); + cmd.Parameters.AddWithValue("@pass", + EncodePassword(newPassword, passwordKey, passwordFormat)); + cmd.Parameters.AddWithValue("@lastPasswordChangedDate", DateTime.Now); + cmd.Parameters.AddWithValue("@userId", userId); + return cmd.ExecuteNonQuery() > 0; + } + } + catch (MySqlException e) + { + if (WriteExceptionsToEventLog) + WriteToEventLog(e, "ChangePassword"); + throw new ProviderException(exceptionMessage, e); + } + } + + /// + /// Changes the password question and answer. + /// + /// The user name. + /// The password. + /// The new password question. + /// The new password answer. + /// true if the update was successful; otherwise, false. A value of false is + /// also returned if the password is incorrect, the user is locked out, or the user + /// does not exist in the database. + public override bool ChangePasswordQuestionAndAnswer(string username, + string password, string newPwdQuestion, string newPwdAnswer) + { + // this handles the case where the username doesn't exist + if (!(ValidateUser(username, password))) + return false; + + try + { + using (MySqlConnection connection = new MySqlConnection(connectionString)) + { + connection.Open(); + + string passwordKey; + MembershipPasswordFormat passwordFormat; + int userId = GetUserId(connection, username); + + GetPasswordInfo(connection, userId, out passwordKey, out passwordFormat); + + + MySqlCommand cmd = new MySqlCommand( + @"UPDATE my_aspnet_membership + SET PasswordQuestion = @passwordQuestion, PasswordAnswer = @passwordAnswer + WHERE userId=@userId", connection); + cmd.Parameters.AddWithValue("@passwordQuestion", newPwdQuestion); + cmd.Parameters.AddWithValue("@passwordAnswer", + EncodePassword(newPwdAnswer, passwordKey, passwordFormat)); + cmd.Parameters.AddWithValue("@userId", userId); + return cmd.ExecuteNonQuery() > 0; + } + } + catch (MySqlException e) + { + if (WriteExceptionsToEventLog) + WriteToEventLog(e, "ChangePasswordQuestionAndAnswer"); + throw new ProviderException(exceptionMessage, e); + } + } + + /// + /// Adds a new membership user to the data source. + /// + /// The user name for the new user. + /// The password for the new user. + /// The e-mail address for the new user. + /// The password question for the new user. + /// The password answer for the new user + /// Whether or not the new user is approved to be validated. + /// The unique identifier from the membership data source for the user. + /// A enumeration value indicating whether the user was created successfully. + /// + /// A object populated with the information for the newly created user. + /// + public override MembershipUser CreateUser(string username, string password, + string email, string passwordQuestion, string passwordAnswer, + bool isApproved, object providerUserKey, out MembershipCreateStatus status) + { + //basis on MSDN documentation we should trim all the paramater values: http://msdn.microsoft.com/en-us/library/d8t4h2es%28v=vs.110%29.aspx + TrimParametersValues(ref username, ref password, ref email, ref passwordQuestion, ref passwordAnswer); + + ValidatePasswordEventArgs Args = new ValidatePasswordEventArgs(username, password, true); + OnValidatingPassword(Args); + if (Args.Cancel) + { + status = MembershipCreateStatus.InvalidPassword; + return null; + } + if (RequiresUniqueEmail && !String.IsNullOrEmpty(GetUserNameByEmail(email))) + { + status = MembershipCreateStatus.DuplicateEmail; + return null; + } + + ValidateQA(passwordQuestion, passwordAnswer); + + // now try to validate the password + if (!ValidatePassword(password, "password", false)) + { + status = MembershipCreateStatus.InvalidPassword; + return null; + } + + // now check to see if we already have a member by this name + MembershipUser u = GetUser(username, false); + if (u != null) + { + status = MembershipCreateStatus.DuplicateUserName; + return null; + } + + string passwordKey = GetPasswordKey(); + DateTime createDate = DateTime.Now; + MySqlTransaction transaction = null; + + using (MySqlConnection connection = new MySqlConnection(connectionString)) + { + try + { + connection.Open(); + transaction = connection.BeginTransaction(); + + // either create a new user or fetch the existing user id + long userId = SchemaManager.CreateOrFetchUserId(connection, username, + app.EnsureId(connection), true); + + MySqlCommand cmd = new MySqlCommand( + @"INSERT INTO my_aspnet_membership + VALUES(@userId, @email, @comment, @password, @passwordKey, + @passwordFormat, @passwordQuestion, @passwordAnswer, + @isApproved, @lastActivityDate, @lastLoginDate, + @lastPasswordChangedDate, @creationDate, + @isLockedOut, @lastLockedOutDate, @failedPasswordAttemptCount, + @failedPasswordAttemptWindowStart, @failedPasswordAnswerAttemptCount, + @failedPasswordAnswerAttemptWindowStart)", + connection); + cmd.Parameters.AddWithValue("@userId", userId); + cmd.Parameters.AddWithValue("@email", email); + cmd.Parameters.AddWithValue("@comment", ""); + cmd.Parameters.AddWithValue("@password", + EncodePassword(password, passwordKey, PasswordFormat)); + cmd.Parameters.AddWithValue("@passwordKey", passwordKey); + cmd.Parameters.AddWithValue("@passwordFormat", PasswordFormat); + cmd.Parameters.AddWithValue("@passwordQuestion", passwordQuestion); + cmd.Parameters.AddWithValue("@passwordAnswer", + EncodePassword(passwordAnswer, passwordKey, PasswordFormat)); + cmd.Parameters.AddWithValue("@isApproved", isApproved); + cmd.Parameters.AddWithValue("@lastActivityDate", createDate); + cmd.Parameters.AddWithValue("@lastLoginDate", createDate); + cmd.Parameters.AddWithValue("@lastPasswordChangedDate", createDate); + cmd.Parameters.AddWithValue("@creationDate", createDate); + cmd.Parameters.AddWithValue("@isLockedOut", false); + cmd.Parameters.AddWithValue("@lastLockedOutDate", createDate); + cmd.Parameters.AddWithValue("@failedPasswordAttemptCount", 0); + cmd.Parameters.AddWithValue("@failedPasswordAttemptWindowStart", createDate); + cmd.Parameters.AddWithValue("@failedPasswordAnswerAttemptCount", 0); + cmd.Parameters.AddWithValue("@failedPasswordAnswerAttemptWindowStart", createDate); + + int recAdded = cmd.ExecuteNonQuery(); + if (recAdded > 0) + status = MembershipCreateStatus.Success; + else + status = MembershipCreateStatus.UserRejected; + transaction.Commit(); + } + catch (MySqlException e) + { + if (WriteExceptionsToEventLog) + WriteToEventLog(e, "CreateUser"); + status = MembershipCreateStatus.ProviderError; + if (transaction != null) + transaction.Rollback(); + return null; + } + } + + return GetUser(username, false); + } + + /// + /// Removes a user from the membership data source. + /// + /// The name of the user to delete. + /// true to delete data related to the user from the database; false to leave data related to the user in the database. + /// + /// true if the user was successfully deleted; otherwise, false. + /// + public override bool DeleteUser(string username, bool deleteAllRelatedData) + { + try + { + using (MySqlConnection conn = new MySqlConnection(connectionString)) + { + conn.Open(); + + int userId = GetUserId(conn, username); + if (-1 == userId) return false; + + // if we are supposed to delete all related data, then delegate that to those providers + if (deleteAllRelatedData) + { + MySQLRoleProvider.DeleteUserData(conn, userId); + MySQLProfileProvider.DeleteUserData(conn, userId); + } + + string sql = @"DELETE {0}m + FROM my_aspnet_users u, my_aspnet_membership m + WHERE u.id=m.userId AND u.id=@userId"; + + MySqlCommand cmd = new MySqlCommand( + String.Format(sql, deleteAllRelatedData ? "u," : ""), conn); + cmd.Parameters.AddWithValue("@appId", app.FetchId(conn)); + cmd.Parameters.AddWithValue("@userId", userId); + return cmd.ExecuteNonQuery() > 0; + } + } + catch (MySqlException e) + { + if (WriteExceptionsToEventLog) + WriteToEventLog(e, "DeleteUser"); + throw new ProviderException(exceptionMessage, e); + } + } + + /// + /// Gets a collection of all the users in the data source in pages of data. + /// + /// The index of the page of results to return. is zero-based. + /// The size of the page of results to return. + /// The total number of matched users. + /// + /// A collection that contains a page of objects beginning at the page specified by . + /// + public override MembershipUserCollection GetAllUsers(int pageIndex, + int pageSize, out int totalRecords) + { + return GetUsers(null, null, pageIndex, pageSize, out totalRecords); + } + + /// + /// Gets the number of users currently accessing the application. + /// + /// + /// The number of users currently accessing the application. + /// + public override int GetNumberOfUsersOnline() + { + TimeSpan onlineSpan = new TimeSpan(0, Membership.UserIsOnlineTimeWindow, 0); + DateTime compareTime = DateTime.Now.Subtract(onlineSpan); + + try + { + using (MySqlConnection connection = new MySqlConnection(connectionString)) + { + connection.Open(); + MySqlCommand cmd = new MySqlCommand( + @"SELECT COUNT(*) FROM my_aspnet_membership m JOIN my_aspnet_users u + ON m.userId=u.id WHERE m.LastActivityDate > @date AND u.applicationId=@appId", + connection); + cmd.Parameters.AddWithValue("@date", compareTime); + cmd.Parameters.AddWithValue("@appId", app.FetchId(connection)); + return Convert.ToInt32(cmd.ExecuteScalar()); + } + } + catch (MySqlException e) + { + if (WriteExceptionsToEventLog) + WriteToEventLog(e, "GetNumberOfUsersOnline"); + throw new ProviderException(exceptionMessage, e); + } + } + + /// + /// Gets the password for the specified user name from the data source. + /// + /// The user to retrieve the password for. + /// The password answer for the user. + /// + /// The password for the specified user name. + /// + public override string GetPassword(string username, string answer) + { + if (!EnablePasswordRetrieval) + throw new ProviderException(Properties.Resources.PasswordRetrievalNotEnabled); + + try + { + using (MySqlConnection connection = new MySqlConnection(connectionString)) + { + connection.Open(); + + int userId = GetUserId(connection, username); + if (-1 == userId) + throw new ProviderException("Username not found."); + + string sql = @"SELECT Password, PasswordAnswer, PasswordKey, PasswordFormat, + IsLockedOut FROM my_aspnet_membership WHERE userId=@userId"; + MySqlCommand cmd = new MySqlCommand(sql, connection); + cmd.Parameters.AddWithValue("@userId", userId); + + using (MySqlDataReader reader = cmd.ExecuteReader(CommandBehavior.SingleRow)) + { + reader.Read(); + if (reader.GetBoolean("IsLockedOut")) + throw new MembershipPasswordException(Properties.Resources.UserIsLockedOut); + + string password = reader.GetString("Password"); + string passwordAnswer = reader.GetValue(reader.GetOrdinal("PasswordAnswer")).ToString(); + string passwordKey = reader.GetString("PasswordKey"); + MembershipPasswordFormat format = (MembershipPasswordFormat)reader.GetInt32(3); + reader.Close(); + + if (RequiresQuestionAndAnswer && + !(CheckPassword(answer, passwordAnswer, passwordKey, format))) + { + UpdateFailureCount(userId, "PasswordAnswer", connection); + throw new MembershipPasswordException(Properties.Resources.IncorrectPasswordAnswer); + } + if (PasswordFormat == MembershipPasswordFormat.Encrypted) + { + password = UnEncodePassword(password, format); + } + return password; + } + } + } + catch (MySqlException e) + { + if (WriteExceptionsToEventLog) + WriteToEventLog(e, "GetPassword"); + throw new ProviderException(exceptionMessage, e); + } + } + + /// + /// Gets information from the data source for a user. Provides an option to update the last-activity date/time stamp for the user. + /// + /// The name of the user to get information for. + /// true to update the last-activity date/time stamp for the user; false to return user information without updating the last-activity date/time stamp for the user. + /// + /// A object populated with the specified user's information from the data source. + /// + public override MembershipUser GetUser(string username, bool userIsOnline) + { + try + { + int userId = -1; + using (MySqlConnection connection = new MySqlConnection(connectionString)) + { + connection.Open(); + + userId = GetUserId(connection, username); + if (-1 == userId) return null; + } + + return GetUser(userId, userIsOnline); + } + catch (MySqlException e) + { + if (WriteExceptionsToEventLog) + WriteToEventLog(e, "GetUser(String, Boolean)"); + throw new ProviderException(exceptionMessage, e); + } + } + + /// + /// Gets user information from the data source based on the unique identifier for the membership user. Provides an option to update the last-activity date/time stamp for the user. + /// + /// The unique identifier for the membership user to get information for. + /// true to update the last-activity date/time stamp for the user; false to return user information without updating the last-activity date/time stamp for the user. + /// + /// A object populated with the specified user's information from the data source. + /// + public override MembershipUser GetUser(object providerUserKey, bool userIsOnline) + { + MySqlTransaction txn = null; + + try + { + using (MySqlConnection connection = new MySqlConnection(connectionString)) + { + connection.Open(); + + txn = connection.BeginTransaction(); + MySqlCommand cmd = new MySqlCommand("", connection); + cmd.Parameters.AddWithValue("@userId", providerUserKey); + + if (userIsOnline) + { + cmd.CommandText = + @"UPDATE my_aspnet_users SET lastActivityDate = @date WHERE id=@userId"; + cmd.Parameters.AddWithValue("@date", DateTime.Now); + cmd.ExecuteNonQuery(); + + cmd.CommandText = "UPDATE my_aspnet_membership SET LastActivityDate=@date WHERE userId=@userId"; + cmd.ExecuteNonQuery(); + } + + cmd.CommandText = @"SELECT m.*,u.name + FROM my_aspnet_membership m JOIN my_aspnet_users u ON m.userId=u.id + WHERE u.id=@userId"; + + MembershipUser user; + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + if (!reader.Read()) return null; + user = GetUserFromReader(reader); + } + txn.Commit(); + return user; + } + } + catch (MySqlException e) + { + if (txn != null) + txn.Rollback(); + if (WriteExceptionsToEventLog) + WriteToEventLog(e, "GetUser(Object, Boolean)"); + throw new ProviderException(exceptionMessage); + } + } + + /// + /// Unlocks the user. + /// + /// The username. + /// true if the membership user was successfully unlocked; + /// otherwise, false. A value of false is also returned if the user + /// does not exist in the database. + public override bool UnlockUser(string username) + { + try + { + using (MySqlConnection conn = new MySqlConnection(connectionString)) + { + conn.Open(); + + int userId = GetUserId(conn, username); + if (-1 == userId) return false; + + string sql = @"UPDATE my_aspnet_membership + SET IsLockedOut = false, LastLockedOutDate = @lastDate + WHERE userId=@userId"; + + MySqlCommand cmd = new MySqlCommand(sql, conn); + cmd.Parameters.AddWithValue("@lastDate", DateTime.Now); + cmd.Parameters.AddWithValue("@userId", userId); + return cmd.ExecuteNonQuery() > 0; + } + } + catch (MySqlException e) + { + if (WriteExceptionsToEventLog) + WriteToEventLog(e, "UnlockUser"); + throw new ProviderException(exceptionMessage, e); + } + } + + /// + /// Gets the user name associated with the specified e-mail address. + /// + /// The e-mail address to search for. + /// + /// The user name associated with the specified e-mail address. If no match is found, return null. + /// + public override string GetUserNameByEmail(string email) + { + try + { + using (MySqlConnection conn = new MySqlConnection(connectionString)) + { + conn.Open(); + + string sql = @"SELECT u.name FROM my_aspnet_users u + JOIN my_aspnet_membership m ON m.userid=u.id + WHERE m.Email = @email AND u.applicationId=@appId"; + MySqlCommand cmd = new MySqlCommand(sql, conn); + cmd.Parameters.AddWithValue("@email", email); + cmd.Parameters.AddWithValue("@appId", app.FetchId(conn)); + return (string)cmd.ExecuteScalar(); + } + } + catch (MySqlException e) + { + if (WriteExceptionsToEventLog) + WriteToEventLog(e, "GetUserNameByEmail"); + throw new ProviderException(exceptionMessage); + } + } + + /// + /// Resets a user's password to a new, automatically generated password. + /// + /// The user to reset the password for. + /// The password answer for the specified user. + /// The new password for the specified user. + public override string ResetPassword(string username, string answer) + { + if (!(EnablePasswordReset)) + throw new NotSupportedException(Properties.Resources.PasswordResetNotEnabled); + + try + { + using (MySqlConnection connection = new MySqlConnection(connectionString)) + { + connection.Open(); + + // fetch the userid first + int userId = GetUserId(connection, username); + if (-1 == userId) + throw new ProviderException(Properties.Resources.UsernameNotFound); + + if (answer == null && RequiresQuestionAndAnswer) + { + UpdateFailureCount(userId, "PasswordAnswer", connection); + throw new ProviderException(Properties.Resources.PasswordRequiredForReset); + } + + string newPassword = Membership.GeneratePassword(newPasswordLength, MinRequiredNonAlphanumericCharacters); + ValidatePasswordEventArgs Args = new ValidatePasswordEventArgs(username, newPassword, true); + OnValidatingPassword(Args); + if (Args.Cancel) + { + if (!(Args.FailureInformation == null)) + throw Args.FailureInformation; + else + throw new MembershipPasswordException(Properties.Resources.PasswordResetCanceledNotValid); + } + + MySqlCommand cmd = new MySqlCommand(@"SELECT PasswordAnswer, + PasswordKey, PasswordFormat, IsLockedOut + FROM my_aspnet_membership WHERE userId=@userId", connection); + cmd.Parameters.AddWithValue("@userId", userId); + + string passwordKey = String.Empty; + MembershipPasswordFormat format; + using (MySqlDataReader reader = cmd.ExecuteReader(CommandBehavior.SingleRow)) + { + reader.Read(); + if (reader.GetBoolean("IsLockedOut")) + throw new MembershipPasswordException(Properties.Resources.UserIsLockedOut); + + object passwordAnswer = reader.GetValue(reader.GetOrdinal("PasswordAnswer")); + passwordKey = reader.GetString("PasswordKey"); + format = (MembershipPasswordFormat)reader.GetByte("PasswordFormat"); + reader.Close(); + + if (RequiresQuestionAndAnswer) + { + if (!CheckPassword(answer, (string)passwordAnswer, passwordKey, format)) + { + UpdateFailureCount(userId, "PasswordAnswer", connection); + throw new MembershipPasswordException(Properties.Resources.IncorrectPasswordAnswer); + } + } + } + + cmd.CommandText = @"UPDATE my_aspnet_membership + SET Password = @pass, LastPasswordChangedDate = @lastPassChange + WHERE userId=@userId"; + + cmd.Parameters.AddWithValue("@pass", + EncodePassword(newPassword, passwordKey, format)); + cmd.Parameters.AddWithValue("@lastPassChange", DateTime.Now); + int rowsAffected = cmd.ExecuteNonQuery(); + if (rowsAffected != 1) + throw new MembershipPasswordException(Properties.Resources.ErrorResettingPassword); + return newPassword; + } + } + catch (MySqlException e) + { + if (WriteExceptionsToEventLog) + WriteToEventLog(e, "ResetPassword"); + throw new ProviderException(exceptionMessage, e); + } + } + + /// + /// Updates information about a user in the data source. + /// + /// A object + /// that represents the user to update and the updated information for the user. + public override void UpdateUser(MembershipUser user) + { + try + { + using (MySqlConnection conn = new MySqlConnection(connectionString)) + { + conn.Open(); + + int userId = GetUserId(conn, user.UserName); + if (-1 == userId) + throw new ProviderException(Properties.Resources.UsernameNotFound); + + string sql = @"UPDATE my_aspnet_membership m, my_aspnet_users u + SET m.Email=@email, m.Comment=@comment, m.IsApproved=@isApproved, + m.LastLoginDate=@lastLoginDate, u.lastActivityDate=@lastActivityDate, + m.LastActivityDate=@lastActivityDate + WHERE m.userId=u.id AND u.name LIKE @name AND u.applicationId=@appId"; + MySqlCommand cmd = new MySqlCommand(sql, conn); + cmd.Parameters.AddWithValue("@Email", user.Email); + cmd.Parameters.AddWithValue("@Comment", user.Comment); + cmd.Parameters.AddWithValue("@isApproved", user.IsApproved); + cmd.Parameters.AddWithValue("@lastLoginDate", user.LastLoginDate); + cmd.Parameters.AddWithValue("@lastActivityDate", user.LastActivityDate); + cmd.Parameters.AddWithValue("@name", user.UserName); + cmd.Parameters.AddWithValue("@appId", app.FetchId(conn)); + cmd.ExecuteNonQuery(); + } + } + catch (MySqlException e) + { + if (WriteExceptionsToEventLog) + WriteToEventLog(e, "UpdateUser"); + throw new ProviderException(exceptionMessage); + } + } + + /// + /// Verifies that the specified user name and password exist in the data source. + /// + /// The name of the user to validate. + /// The password for the specified user. + /// + /// true if the specified username and password are valid; otherwise, false. + /// + public override bool ValidateUser(string username, string password) + { + bool isValid = false; + try + { + using (MySqlConnection connection = new MySqlConnection(connectionString)) + { + connection.Open(); + + // first get the user id. If that is -1, then the user doesn't exist + // so we just return false since we can't bump any counters + int userId = GetUserId(connection, username); + if (-1 == userId) return false; + + string sql = @"SELECT Password, PasswordKey, PasswordFormat, IsApproved, + Islockedout FROM my_aspnet_membership WHERE userId=@userId"; + MySqlCommand cmd = new MySqlCommand(sql, connection); + cmd.Parameters.AddWithValue("@userId", userId); + + using (MySqlDataReader reader = cmd.ExecuteReader(CommandBehavior.SingleRow)) + { + if (!reader.HasRows) return false; + reader.Read(); + if (reader.GetBoolean("IsLockedOut")) return false; + + string pwd = reader.GetString(0); + string passwordKey = reader.GetString(1); + MembershipPasswordFormat format = (MembershipPasswordFormat) + reader.GetInt32(2); + bool isApproved = reader.GetBoolean(3); + reader.Close(); + + if (!CheckPassword(password, pwd, passwordKey, format)) + UpdateFailureCount(userId, "Password", connection); + else if (isApproved) + { + isValid = true; + DateTime currentDate = DateTime.Now; + MySqlCommand updateCmd = new MySqlCommand( + @"UPDATE my_aspnet_membership m, my_aspnet_users u + SET m.LastLoginDate = @lastLoginDate, u.lastActivityDate = @date, + m.LastActivityDate=@date + WHERE m.userId=@userid AND u.id=@userid", connection); + updateCmd.Parameters.AddWithValue("@lastLoginDate", currentDate); + updateCmd.Parameters.AddWithValue("@date", currentDate); + updateCmd.Parameters.AddWithValue("@userid", userId); + updateCmd.ExecuteNonQuery(); + } + } + return isValid; + } + } + catch (MySqlException e) + { + if (WriteExceptionsToEventLog) + WriteToEventLog(e, "ValidateUser"); + throw new ProviderException(exceptionMessage, e); + } + } + + /// + /// Gets a collection of membership users where the user name contains the specified user name to match. + /// + /// The user name to search for. + /// The index of the page of results to return. is zero-based. + /// The size of the page of results to return. + /// The total number of matched users. + /// + /// A collection that contains a page of objects beginning at the page specified by . + /// + public override MembershipUserCollection FindUsersByName(string usernameToMatch, + int pageIndex, int pageSize, out int totalRecords) + { + return GetUsers(usernameToMatch, null, pageIndex, pageSize, out totalRecords); + } + + /// + /// Gets a collection of membership users where the e-mail address contains the specified e-mail address to match. + /// + /// The e-mail address to search for. + /// The index of the page of results to return. is zero-based. + /// The size of the page of results to return. + /// The total number of matched users. + /// + /// A collection that contains a page of objects beginning at the page specified by . + /// + public override MembershipUserCollection FindUsersByEmail(string emailToMatch, int pageIndex, + int pageSize, out int totalRecords) + { + return GetUsers(null, emailToMatch, pageIndex, pageSize, out totalRecords); + } + + #endregion + + #region Private Methods + + private int GetUserId(MySqlConnection connection, string username) + { + MySqlCommand cmd = new MySqlCommand( + "SELECT id FROM my_aspnet_users WHERE name = @name AND applicationId=@appId", connection); + cmd.Parameters.AddWithValue("@name", username); + cmd.Parameters.AddWithValue("@appId", app.FetchId(connection)); + object id = cmd.ExecuteScalar(); + if (id == null) return -1; + return (int)id; + } + + private void WriteToEventLog(Exception e, string action) + { + using (EventLog log = new EventLog()) + { + log.Source = eventSource; + log.Log = eventLog; + string message = "An exception occurred communicating with the data source." + + Environment.NewLine + Environment.NewLine; + message += "Action: " + action + Environment.NewLine + Environment.NewLine; + message += "Exception: " + e; + log.WriteEntry(message); + } + } + + private MembershipUser GetUserFromReader(MySqlDataReader reader) + { + object providerUserKey = reader.GetInt32("userId"); + string username = reader.GetString("name"); + + string email = null; + if (!reader.IsDBNull(reader.GetOrdinal("Email"))) + email = reader.GetString("Email"); + + string passwordQuestion = ""; + if (!(reader.GetValue(reader.GetOrdinal("PasswordQuestion")) == DBNull.Value)) + passwordQuestion = reader.GetString("PasswordQuestion"); + + string comment = ""; + if (!(reader.GetValue(reader.GetOrdinal("Comment")) == DBNull.Value)) + comment = reader.GetString("Comment"); + + bool isApproved = reader.GetBoolean("IsApproved"); + bool isLockedOut = reader.GetBoolean("IsLockedOut"); + DateTime creationDate = reader.GetDateTime("CreationDate"); + DateTime lastLoginDate = new DateTime(); + if (!(reader.GetValue(reader.GetOrdinal("LastLoginDate")) == DBNull.Value)) + lastLoginDate = reader.GetDateTime("LastLoginDate"); + + DateTime lastActivityDate = reader.GetDateTime("LastActivityDate"); + DateTime lastPasswordChangedDate = reader.GetDateTime("LastPasswordChangedDate"); + DateTime lastLockedOutDate = new DateTime(); + if (!(reader.GetValue(reader.GetOrdinal("LastLockedoutDate")) == DBNull.Value)) + lastLockedOutDate = reader.GetDateTime("LastLockedoutDate"); + + MembershipUser u = + new MembershipUser(Name, username, providerUserKey, email, passwordQuestion, comment, isApproved, + isLockedOut, creationDate, lastLoginDate, lastActivityDate, lastPasswordChangedDate, + lastLockedOutDate); + return u; + } + + private string UnEncodePassword(string encodedPassword, MembershipPasswordFormat format) + { + string password = encodedPassword; + if (format == MembershipPasswordFormat.Clear) + return encodedPassword; + else if (format == MembershipPasswordFormat.Encrypted) + return Encoding.Unicode.GetString(DecryptPassword( + Convert.FromBase64String(password))); + else if (format == MembershipPasswordFormat.Hashed) + throw new ProviderException(Properties.Resources.CannotUnencodeHashedPwd); + else + throw new ProviderException(Properties.Resources.UnsupportedPasswordFormat); + } + + private string GetPasswordKey() + { + RNGCryptoServiceProvider cryptoProvider = + new RNGCryptoServiceProvider(); + byte[] key = new byte[16]; + cryptoProvider.GetBytes(key); + return Convert.ToBase64String(key); + } + + /// + /// this method is only necessary because early versions of Mono did not support + /// the HashAlgorithmType property + /// + /// + /// + /// + private string HashPasswordBytes(byte[] key, byte[] bytes) + { + HashAlgorithm hash = HashAlgorithm.Create(Membership.HashAlgorithmType); + + if (hash is KeyedHashAlgorithm) + { + KeyedHashAlgorithm keyedHash = hash as KeyedHashAlgorithm; + keyedHash.Key = key; + } + return Convert.ToBase64String(hash.ComputeHash(bytes)); + } + + private string EncodePassword(string password, string passwordKey, + MembershipPasswordFormat format) + { + if (password == null) + return null; + if (format == MembershipPasswordFormat.Clear) + return password; + + byte[] passwordBytes = Encoding.Unicode.GetBytes(password); + byte[] keyBytes = Convert.FromBase64String(passwordKey); + byte[] keyedBytes = new byte[passwordBytes.Length + keyBytes.Length]; + Array.Copy(keyBytes, keyedBytes, keyBytes.Length); + Array.Copy(passwordBytes, 0, keyedBytes, keyBytes.Length, passwordBytes.Length); + + if (format == MembershipPasswordFormat.Encrypted) + { + byte[] encryptedBytes = EncryptPassword(passwordBytes); + return Convert.ToBase64String(encryptedBytes); + } + else if (format == MembershipPasswordFormat.Hashed) + return HashPasswordBytes(keyBytes, keyedBytes); + else + throw new ProviderException(Properties.Resources.UnsupportedPasswordFormat); + } + + private void UpdateFailureCount(int userId, string failureType, MySqlConnection connection) + { + MySqlCommand cmd = new MySqlCommand( + @"SELECT FailedPasswordAttemptCount, + FailedPasswordAttemptWindowStart, FailedPasswordAnswerAttemptCount, + FailedPasswordAnswerAttemptWindowStart FROM my_aspnet_membership + WHERE userId=@userId", connection); + cmd.Parameters.AddWithValue("@userId", userId); + + DateTime windowStart = new DateTime(); + int failureCount = 0; + try + { + using (MySqlDataReader reader = cmd.ExecuteReader(CommandBehavior.SingleRow)) + { + if (!reader.HasRows) + throw new ProviderException(Properties.Resources.UnableToUpdateFailureCount); + + reader.Read(); + if (failureType == "Password") + { + failureCount = reader.GetInt32(0); + windowStart = reader.GetDateTime(1); + } + if (failureType == "PasswordAnswer") + { + failureCount = reader.GetInt32(2); + windowStart = reader.GetDateTime(3); + } + } + + DateTime windowEnd = windowStart.AddMinutes(PasswordAttemptWindow); + if (failureCount == 0 || DateTime.Now > windowEnd) + { + if (failureType == "Password") + { + cmd.CommandText = + @"UPDATE my_aspnet_membership + SET FailedPasswordAttemptCount = @count, + FailedPasswordAttemptWindowStart = @windowStart + WHERE userId=@userId"; + } + if (failureType == "PasswordAnswer") + { + cmd.CommandText = + @"UPDATE my_aspnet_membership + SET FailedPasswordAnswerAttemptCount = @count, + FailedPasswordAnswerAttemptWindowStart = @windowStart + WHERE userId = @userId"; + } + cmd.Parameters.Clear(); + cmd.Parameters.AddWithValue("@count", 1); + cmd.Parameters.AddWithValue("@windowStart", DateTime.Now); + cmd.Parameters.AddWithValue("@userId", userId); + if (cmd.ExecuteNonQuery() < 0) + throw new ProviderException(Properties.Resources.UnableToUpdateFailureCount); + } + else + { + failureCount += 1; + if (failureCount >= MaxInvalidPasswordAttempts) + { + cmd.CommandText = + @"UPDATE my_aspnet_membership SET IsLockedOut = @isLockedOut, + LastLockedOutDate = @lastLockedOutDate WHERE userId=@userId"; + cmd.Parameters.Clear(); + cmd.Parameters.AddWithValue("@isLockedOut", true); + cmd.Parameters.AddWithValue("@lastLockedOutDate", DateTime.Now); + cmd.Parameters.AddWithValue("@userId", userId); + if (cmd.ExecuteNonQuery() < 0) + throw new ProviderException(Properties.Resources.UnableToLockOutUser); + } + else + { + if (failureType == "Password") + { + cmd.CommandText = + @"UPDATE my_aspnet_membership + SET FailedPasswordAttemptCount = @count WHERE userId=@userId"; + } + if (failureType == "PasswordAnswer") + { + cmd.CommandText = + @"UPDATE my_aspnet_membership + SET FailedPasswordAnswerAttemptCount = @count + WHERE userId=@userId"; + } + cmd.Parameters.Clear(); + cmd.Parameters.AddWithValue("@count", failureCount); + cmd.Parameters.AddWithValue("@userId", userId); + if (cmd.ExecuteNonQuery() < 0) + throw new ProviderException("Unable to update failure count."); + } + } + } + catch (MySqlException e) + { + if (WriteExceptionsToEventLog) + WriteToEventLog(e, "UpdateFailureCount"); + throw new ProviderException(exceptionMessage, e); + } + } + + private bool CheckPassword(string password, string dbpassword, + string passwordKey, MembershipPasswordFormat format) + { + password = EncodePassword(password, passwordKey, format); + return password == dbpassword; + } + + private void GetPasswordInfo(MySqlConnection connection, int userId, + out string passwordKey, out MembershipPasswordFormat passwordFormat) + { + MySqlCommand cmd = new MySqlCommand( + @"SELECT PasswordKey, PasswordFormat FROM my_aspnet_membership WHERE + userId=@userId", connection); + cmd.Parameters.AddWithValue("@userId", userId); + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + reader.Read(); + passwordKey = reader.GetString(reader.GetOrdinal("PasswordKey")); + passwordFormat = (MembershipPasswordFormat)reader.GetByte( + reader.GetOrdinal("PasswordFormat")); + } + } + + private MembershipUserCollection GetUsers(string username, string email, + int pageIndex, int pageSize, out int totalRecords) + { + MembershipUserCollection users = new MembershipUserCollection(); + try + { + using (MySqlConnection connection = new MySqlConnection(connectionString)) + { + connection.Open(); + MySqlCommand cmd = new MySqlCommand(); + cmd.Connection = connection; + + string sql = @"SELECT SQL_CALC_FOUND_ROWS u.name,m.* FROM my_aspnet_users u + JOIN my_aspnet_membership m ON m.userId=u.id + WHERE u.applicationId=@appId"; + + if (username != null) + { + sql += " AND u.name LIKE @name"; + cmd.Parameters.AddWithValue("@name", username); + } + else if (email != null) + { + sql += " AND m.Email LIKE @email"; + cmd.Parameters.AddWithValue("@email", email); + } + sql += " ORDER BY u.id ASC LIMIT {0},{1}"; + cmd.CommandText = String.Format(sql, pageIndex * pageSize, pageSize); + cmd.Parameters.AddWithValue("@appId", app.FetchId(connection)); + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + while (reader.Read()) + users.Add(GetUserFromReader(reader)); + } + cmd.CommandText = "SELECT FOUND_ROWS()"; + cmd.Parameters.Clear(); + totalRecords = Convert.ToInt32(cmd.ExecuteScalar()); + } + return users; + } + catch (MySqlException e) + { + if (WriteExceptionsToEventLog) + WriteToEventLog(e, "GetUsers"); + throw new ProviderException(exceptionMessage); + } + } + + private void ValidateQA(string question, string answer) + { + if (RequiresQuestionAndAnswer && String.IsNullOrEmpty(question)) + throw new ArgumentException(Properties.Resources.PasswordQuestionInvalid); + if (RequiresQuestionAndAnswer && String.IsNullOrEmpty(answer)) + throw new ArgumentException(Properties.Resources.PasswordAnswerInvalid); + } + + private bool ValidatePassword(string password, string argumentName, bool throwExceptions) + { + string exceptionString = null; + object correctValue = MinRequiredPasswordLength; + + if (password.Length < MinRequiredPasswordLength) + exceptionString = Properties.Resources.PasswordNotLongEnough; + else + { + int count = 0; + foreach (char c in password) + if (!char.IsLetterOrDigit(c)) + count++; + if (count < MinRequiredNonAlphanumericCharacters) + exceptionString = Properties.Resources.NotEnoughNonAlphaNumericInPwd; + correctValue = MinRequiredNonAlphanumericCharacters; + } + + if (exceptionString != null) + { + if (throwExceptions) + throw new ArgumentException( + string.Format(exceptionString, argumentName, correctValue), + argumentName); + else + return false; + } + + if (PasswordStrengthRegularExpression.Length > 0) + if (!Regex.IsMatch(password, PasswordStrengthRegularExpression)) + return false; + + return true; + } + + private void TrimParametersValues(ref string username, ref string password, ref string email, ref string passwordQuestion, ref string passwordAnswer) + { + username = string.IsNullOrEmpty(username) ? username : username.Trim(); + password = string.IsNullOrEmpty(password) ? password : password.Trim(); + email = string.IsNullOrEmpty(email) ? email : email.Trim(); + passwordQuestion = string.IsNullOrEmpty(passwordQuestion) ? passwordQuestion : passwordQuestion.Trim(); + passwordAnswer = string.IsNullOrEmpty(passwordAnswer) ? passwordAnswer : passwordAnswer.Trim(); + } + + #endregion + } +} diff --git a/MySql.Web/src/MySqlDatabaseWrapper.cs b/MySql.Web/src/MySqlDatabaseWrapper.cs index 54c0eeba7..99dfadc59 100644 --- a/MySql.Web/src/MySqlDatabaseWrapper.cs +++ b/MySql.Web/src/MySqlDatabaseWrapper.cs @@ -1,208 +1,208 @@ -// Copyright (c) 2014, 2020, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySql.Data.MySqlClient; -using System; -using System.Collections.Generic; -using System.Data; -using System.Linq; - -namespace MySql.Web.Security -{ - /// - /// Perform basic operations against a Database - /// - internal class MySqlDatabaseWrapper : IDisposable - { - private MySqlConnection _conn; - #region Public - /// - /// Initialize a new instance of the class - /// - /// Connection String - public MySqlDatabaseWrapper(string connectionString) - { - _conn = new MySqlConnection(connectionString); - } - ~MySqlDatabaseWrapper() - { - this.Dispose(true); - } - /// - /// Close the current instance - /// - public void Close() - { - this.Dispose(); - } - /// - /// Dispose the current instance - /// - public void Dispose() - { - this.Dispose(true); - GC.SuppressFinalize(this); - } - - /// - /// Execute given query on the database - /// - /// Query to exeute - /// Parameters used in the query - /// Query resultset - public IEnumerable ExecuteQuery(string cmdText, params object[] parametersValues) - { - CheckIsConnectionOpen(); - MySqlCommand cmd = _conn.CreateCommand(); - cmd.CommandText = cmdText; - AddParameters(cmd, parametersValues); - DataTable result = new DataTable(); - MySqlDataAdapter adapter = new MySqlDataAdapter(cmd); - adapter.Fill(result); - foreach (DataRow row in result.Rows) - { - yield return row; - } - } - - /// - /// Execute given query on the database - /// - /// Query to exeute - /// Parameters used in the query - /// First record in the Query resultset - public DataRow ExecuteQuerySingleRecord(string cmdText, params object[] parametersValues) - { - return ExecuteQuery(cmdText, parametersValues).FirstOrDefault(); - } - - /// - /// Execute given query on the database - /// - /// Query to exeute - /// Parameters used in the query - /// Rows affected by the query - public int ExecuteNonQuery(string cmdText, params object[] parametersValues) - { - CheckIsConnectionOpen(); - MySqlCommand cmd = _conn.CreateCommand(); - cmd.CommandText = cmdText; - AddParameters(cmd, parametersValues); - return cmd.ExecuteNonQuery(); - } - - /// - /// Execute given query on the database - /// - /// Query to exeute - /// Parameters used in the query - /// Value of the first column in the first row in the query resulset - public object ExecuteScalar(string cmdText, params object[] parametersValues) - { - CheckIsConnectionOpen(); - MySqlCommand cmd = _conn.CreateCommand(); - cmd.CommandText = cmdText; - AddParameters(cmd, parametersValues); - return cmd.ExecuteScalar(); - } - - /// - /// Execute all given queries on the database inside of a transaction - /// - /// Queries to exeute - /// If queries were successfully executed - public bool ExecuteInTransaction(IEnumerable> commands) - { - CheckIsConnectionOpen(); - MySqlTransaction tran = _conn.BeginTransaction(); - try - { - foreach (var command in commands) - { - MySqlCommand cmd = _conn.CreateCommand(); - cmd.CommandText = command.Item1; - AddParameters(cmd, command.Item2); - cmd.ExecuteNonQuery(); - } - tran.Commit(); - return true; - } - catch (Exception) - { - tran.Rollback(); - return false; - } - } - #endregion - - #region Protected - protected virtual void Dispose(bool disposing) - { - if (disposing && (this._conn != null)) - { - if (_conn.State != ConnectionState.Closed) - _conn.Close(); - - _conn = null; - } - } - #endregion - - #region Private - /// - /// Verifies if the current connection is open, if not is opened - /// - private void CheckIsConnectionOpen() - { - if (this._conn.State != ConnectionState.Open) - { - this._conn.Open(); - } - } - - /// - /// Add parameters to a command, nomenclature name used for the parameters are 'param[n]' - /// - /// Command that will stores the parameters - /// Parameters values - private void AddParameters(MySqlCommand cmd, object[] values) - { - int ctr = 1; - foreach (object value in values) - { - cmd.Parameters.Add(new MySqlParameter() - { - ParameterName = string.Format("param{0}", ctr), - Value = value ?? DBNull.Value - }); - ctr++; - } - } - #endregion - } -} +// Copyright © 2014, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySql.Data.MySqlClient; +using System; +using System.Collections.Generic; +using System.Data; +using System.Linq; + +namespace MySql.Web.Security +{ + /// + /// Perform basic operations against a Database + /// + internal class MySqlDatabaseWrapper : IDisposable + { + private MySqlConnection _conn; + #region Public + /// + /// Initialize a new instance of the class + /// + /// Connection String + public MySqlDatabaseWrapper(string connectionString) + { + _conn = new MySqlConnection(connectionString); + } + ~MySqlDatabaseWrapper() + { + this.Dispose(true); + } + /// + /// Close the current instance + /// + public void Close() + { + this.Dispose(); + } + /// + /// Dispose the current instance + /// + public void Dispose() + { + this.Dispose(true); + GC.SuppressFinalize(this); + } + + /// + /// Execute given query on the database + /// + /// Query to exeute + /// Parameters used in the query + /// Query resultset + public IEnumerable ExecuteQuery(string cmdText, params object[] parametersValues) + { + CheckIsConnectionOpen(); + MySqlCommand cmd = _conn.CreateCommand(); + cmd.CommandText = cmdText; + AddParameters(cmd, parametersValues); + DataTable result = new DataTable(); + MySqlDataAdapter adapter = new MySqlDataAdapter(cmd); + adapter.Fill(result); + foreach (DataRow row in result.Rows) + { + yield return row; + } + } + + /// + /// Execute given query on the database + /// + /// Query to exeute + /// Parameters used in the query + /// First record in the Query resultset + public DataRow ExecuteQuerySingleRecord(string cmdText, params object[] parametersValues) + { + return ExecuteQuery(cmdText, parametersValues).FirstOrDefault(); + } + + /// + /// Execute given query on the database + /// + /// Query to exeute + /// Parameters used in the query + /// Rows affected by the query + public int ExecuteNonQuery(string cmdText, params object[] parametersValues) + { + CheckIsConnectionOpen(); + MySqlCommand cmd = _conn.CreateCommand(); + cmd.CommandText = cmdText; + AddParameters(cmd, parametersValues); + return cmd.ExecuteNonQuery(); + } + + /// + /// Execute given query on the database + /// + /// Query to exeute + /// Parameters used in the query + /// Value of the first column in the first row in the query resulset + public object ExecuteScalar(string cmdText, params object[] parametersValues) + { + CheckIsConnectionOpen(); + MySqlCommand cmd = _conn.CreateCommand(); + cmd.CommandText = cmdText; + AddParameters(cmd, parametersValues); + return cmd.ExecuteScalar(); + } + + /// + /// Execute all given queries on the database inside of a transaction + /// + /// Queries to exeute + /// If queries were successfully executed + public bool ExecuteInTransaction(IEnumerable> commands) + { + CheckIsConnectionOpen(); + MySqlTransaction tran = _conn.BeginTransaction(); + try + { + foreach (var command in commands) + { + MySqlCommand cmd = _conn.CreateCommand(); + cmd.CommandText = command.Item1; + AddParameters(cmd, command.Item2); + cmd.ExecuteNonQuery(); + } + tran.Commit(); + return true; + } + catch (Exception) + { + tran.Rollback(); + return false; + } + } + #endregion + + #region Protected + protected virtual void Dispose(bool disposing) + { + if (disposing && (this._conn != null)) + { + if (_conn.State != ConnectionState.Closed) + _conn.Close(); + + _conn = null; + } + } + #endregion + + #region Private + /// + /// Verifies if the current connection is open, if not is opened + /// + private void CheckIsConnectionOpen() + { + if (this._conn.State != ConnectionState.Open) + { + this._conn.Open(); + } + } + + /// + /// Add parameters to a command, nomenclature name used for the parameters are 'param[n]' + /// + /// Command that will stores the parameters + /// Parameters values + private void AddParameters(MySqlCommand cmd, object[] values) + { + int ctr = 1; + foreach (object value in values) + { + cmd.Parameters.Add(new MySqlParameter() + { + ParameterName = string.Format("param{0}", ctr), + Value = value ?? DBNull.Value + }); + ctr++; + } + } + #endregion + } +} diff --git a/MySql.Web/src/MySqlWebSecurity.cs b/MySql.Web/src/MySqlWebSecurity.cs index 39ecff096..ced44eeeb 100644 --- a/MySql.Web/src/MySqlWebSecurity.cs +++ b/MySql.Web/src/MySqlWebSecurity.cs @@ -1,577 +1,577 @@ -// Copyright (c) 2014, 2020, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySql.Web.Properties; -using System; -using System.Collections.Generic; -using System.Collections.Specialized; -using System.Configuration; -using System.Net; -using System.Web; -using System.Web.Routing; -using System.Web.Security; -using System.Web.WebPages; - -namespace MySql.Web.Security -{ - /// - /// Provides security features for web projects implementing a MySql database. - /// - public static class MySqlWebSecurity - { - /// - /// Name of the key required to enable simple membership. - /// - public static readonly string EnableSimpleMembershipKey = "enableSimpleMembership"; - private static readonly string MySqlMembershipProviderName = "MySqlMembershipProvider"; - private static readonly string MySqlRoleProviderName = "MySQLRoleProvider"; - - #region Public - /// - /// Changes the password for the user provided. - /// - /// The user name. - /// The current pasword. - /// The new Password. - /// - public static bool ChangePassword(string userName, string oldPassword, string newPassword) - { - ValidProvider(); - var user = Membership.GetUser(userName, true); - return user.ChangePassword(oldPassword, newPassword); - } - - /// - /// Confirms user by confirmation token. - /// - /// The confirmation token. - /// true if the user was confirmed; otherwise, false. - public static bool ConfirmAccount(string confirmationToken) - { - var provider = ValidProvider(); - return provider.ConfirmAccount(confirmationToken); - } - - /// - /// Confirms user by confirmation token and user name. - /// - /// The user name. - /// The confirmation token. - /// true if the user was confirmed; otherwise, false. - public static bool ConfirmAccount(string userName, string confirmationToken) - { - var provider = ValidProvider(); - return provider.ConfirmAccount(userName, confirmationToken); - } - - /// - /// Creates a user account. - /// - /// The user name. - /// The user password. - /// Flag to indicate if a confirmation token is required. - /// A confirmation token if required. - public static string CreateAccount(string userName, string password, bool requireConfirmationToken = false) - { - var provider = ValidProvider(); - return provider.CreateAccount(userName, password, requireConfirmationToken); - } - - /// - /// Creates user and account. - /// - /// The user name. - /// The user password. - /// Additional data for user table. - /// Flag to indicate if a confirmation token is required. - /// A confirmation token if required. - public static string CreateUserAndAccount(string userName, string password, object additionalUserAttributes = null, bool requireConfirmationToken = false) - { - var provider = ValidProvider(); - IDictionary userAttrs = additionalUserAttributes as RouteValueDictionary; - - if (userAttrs == null && additionalUserAttributes != null) - { - var attrs = additionalUserAttributes as IDictionary; - userAttrs = attrs != null ? new RouteValueDictionary(attrs) : new RouteValueDictionary(additionalUserAttributes); - } - - return provider.CreateUserAndAccount(userName, password, requireConfirmationToken, userAttrs); - } - - /// - /// Gets the date when the specified user was created. - /// - /// The user name. - /// Date created or minimum date value if the user was not found. - public static DateTime GetCreateDate(string userName) - { - var provider = ValidProvider(); - return provider.GetCreateDate(userName); - } - - /// - /// Gets the last date when password fails. - /// - /// The user name. - /// Last failure date or minimum date value if the user was not found. - public static DateTime GetLastPasswordFailureDate(string userName) - { - var provider = ValidProvider(); - return provider.GetLastPasswordFailureDate(userName); - } - - /// - /// Gets the date when password was changed. - /// - /// The user name. - /// Last password changed date or minimum date value if the user was not found. - public static DateTime GetPasswordChangedDate(string userName) - { - var provider = ValidProvider(); - return provider.GetPasswordChangedDate(userName); - } - - /// - /// Gets the password failures since last success. - /// - /// The user name. - /// The number of failures since last success. - public static int GetPasswordFailuresSinceLastSuccess(string userName) - { - var provider = ValidProvider(); - return provider.GetPasswordFailuresSinceLastSuccess(userName); - } - - /// - /// Generates password reset token for a confirmed user. - /// - /// The user name. - /// The time that the token will be valid. - /// A generated token or null if the user is not confirmed or does not have a token. - public static string GeneratePasswordResetToken(string userName, int tokenExpirationInMinutesFromNow = 1440) - { - var provider = ValidProvider(); - return provider.GeneratePasswordResetToken(userName, tokenExpirationInMinutesFromNow); - } - - /// - /// Gets the user id. - /// - /// The user name. - /// The user id. -1 if the user doesn't exists - public static int GetUserId(string userName) - { - ValidProvider(); - var user = Membership.GetUser(userName); - return user != null ? (int)user.ProviderUserKey : -1; - } - - /// - /// Gets the user id from the password reset token. - /// - /// The reset token. - /// The user id. 0 if the user doesn't exists. - public static int GetUserIdFromPasswordResetToken(string resetToken) - { - var provider = ValidProvider(); - return provider.GetUserIdFromPasswordResetToken(resetToken); - } - - /// - /// Initializes the simple membership provider with the values given. - /// - /// The connection string name defined in the config file. - /// The table name defined to create new users. - /// The column name defined to store the user ids. - /// The column name defined to store the user name. - /// Flag indicating if the tables should be created. - /// Flag indicating to check if the database has been initialized. - public static void InitializeDatabaseConnection(string connectionStringName, string userTableName, string userIdColumn, string userNameColumn, bool createTables, bool checkIfInitialized = false) - { - InitializeMembershipProvider(connectionStringName, null, null, userTableName, userIdColumn, userNameColumn, createTables, checkIfInitialized); - InitializeRoleProvider(connectionStringName, null, null, userTableName, userIdColumn, userNameColumn, createTables, checkIfInitialized); - Initialized = true; - } - - /// - /// Initializes the simple membership provider with the values given. - /// - /// The connection string. - /// The name of the provider. - /// The table name defined to create new users. - /// The column name defined to store the user ids. - /// The column name defined to store the user name. - /// Flag indicating if the tables should be created. - /// Flag indicating to check if the database has been initialized. - public static void InitializeDatabaseConnection(string connectionString, string providerName, string userTableName, string userIdColumn, string userNameColumn, bool createTables, bool checkIfInitialized = false) - { - InitializeMembershipProvider(null, connectionString, providerName, userTableName, userIdColumn, userNameColumn, createTables, checkIfInitialized); - InitializeRoleProvider(null, connectionString, providerName, userTableName, userIdColumn, userNameColumn, createTables, checkIfInitialized); - Initialized = true; - } - - /// - /// Determines if the account is locked out. - /// - /// The name of the user. - /// The number of allowed password attempts. - /// true if the account is locked; otherwise, false. - public static bool IsAccountLockedOut(string userName, int allowedPasswordAttempts, int intervalInSeconds) - { - return IsAccountLockedOut(userName, allowedPasswordAttempts, TimeSpan.FromSeconds(intervalInSeconds)); - } - - /// - /// Determines if the account is locked out. - /// - /// The name of the user. - /// The number of allowed password attempts. - /// true if the account is locked; otherwise, false. - public static bool IsAccountLockedOut(string userName, int allowedPasswordAttempts, TimeSpan interval) - { - var provider = ValidProvider(); - return (provider.GetUser(userName, false) != null && provider.GetPasswordFailuresSinceLastSuccess(userName) > allowedPasswordAttempts && provider.GetLastPasswordFailureDate(userName).Add(interval) > DateTime.UtcNow); - } - - /// - /// Determines if the user has been confirmed. - /// - /// The user name. - /// true if the user is confirmed; otherwise false. - public static bool IsConfirmed(string userName) - { - var provider = ValidProvider(); - return provider.IsConfirmed(userName); - } - - /// - /// Determines if the is the same as the provided user name. - /// - /// The user name. - /// true if the user matches the ; otherwise, false. - public static bool IsCurrentUser(string userName) - { - ValidProvider(); - return string.Equals(CurrentUserName, userName, StringComparison.OrdinalIgnoreCase); - } - - /// - /// Determines if the matches the provided user id. - /// - /// The user id to match. - /// true if the id matches the ; otherwise, false. - public static bool IsUseLoggedOn(int userId) - { - ValidProvider(); - return CurrentUserId == userId; - } - - /// - /// Performs a login for the specified user. - /// - /// The user name. - /// The user password. - /// Flag to indicate if a persistent cookie should be created. - /// true if the login was successful; otherwise, false. - public static bool Login(string userName, string password, bool createPersistentCookie = false) - { - var curentProvider = ValidProvider(); - bool loginSuccessful = false; - if (curentProvider != null) - loginSuccessful = curentProvider.ValidateUser(userName, password); - else - loginSuccessful = Membership.ValidateUser(userName, password); - - if (loginSuccessful) - { - FormsAuthentication.SetAuthCookie(userName, createPersistentCookie); - } - return loginSuccessful; - } - - /// - /// Performs a logout for the current item. - /// - public static void Logout() - { - ValidProvider(); - FormsAuthentication.SignOut(); - } - - /// - /// Evalutes if the user is authenticated. - /// - public static void RequireAuthenticatedUser() - { - ValidProvider(); - var user = CurrentContext.User; - if (user == null || !user.Identity.IsAuthenticated) - { - CurrentContext.Response.SetStatus(HttpStatusCode.Unauthorized); - } - } - - /// - /// Evaluates if the user belongs to the specified roles. - /// - /// - public static void RequireRoles(params string[] roles) - { - ValidProvider(); - foreach (var role in roles) - { - if (!Roles.IsUserInRole(CurrentUserName, role)) - { - CurrentContext.Response.SetStatus(HttpStatusCode.Unauthorized); - } - } - } - - /// - /// Evaluates if the user is logged on. - /// - /// - public static void RequiresUser(int userId) - { - ValidProvider(); - if (!IsUseLoggedOn(userId)) - { - CurrentContext.Response.SetStatus(HttpStatusCode.Unauthorized); - } - } - - /// - /// Evaluates if the provided user name matches the . - /// - /// - public static void RequiresUser(string userName) - { - ValidProvider(); - if (!string.Equals(CurrentUserName, userName, StringComparison.OrdinalIgnoreCase)) - { - CurrentContext.Response.SetStatus(HttpStatusCode.Unauthorized); - } - } - - /// - /// Resets the password identified by the provided password reset token. - /// - /// The password reset token. - /// The new password. - /// true if the password reset was successful; otherwise, false. - public static bool ResetPassword(string passwordResetToken, string newPassword) - { - var provider = ValidProvider(); - return provider.ResetPasswordWithToken(passwordResetToken, newPassword); - } - - /// - /// Determines if the user exists. - /// - /// The user name. - /// true if the user exists; otherwise, false. - public static bool UserExists(string username) - { - var curentProvider = ValidProvider(); - if (curentProvider != null) - return curentProvider.GetUser(username, false) != null; - else - return Membership.GetUser(username) != null; - } - #endregion - - /// - /// Gets the initialized status. - /// - #region Properties - public static bool Initialized - { - get; - private set; - } - - /// - /// Gets the current user id. - /// - public static int CurrentUserId - { - get { return GetUserId(CurrentUserName); } - } - - /// - /// Gets the current user name. - /// - public static string CurrentUserName - { - get { return CurrentContext.User.Identity.Name; } - } - - /// - /// Gets a flag indicating if there is an associated user id. - /// - public static bool HasUserId - { - get { return CurrentUserId != -1; } - } - - /// - /// Gets a flag indicating if the user is authenticated. - /// - public static bool IsAuthenticated - { - get { return CurrentContext.Request.IsAuthenticated; } - } - #endregion - - #region Private_Internal - - private static MySqlSimpleMembershipProvider CreateSimpleMembershipProvider(string name, MySQLMembershipProvider currentDefault) - { - MySqlSimpleMembershipProvider simpleProvider = new MySqlSimpleMembershipProvider(currentDefault); - NameValueCollection config = new NameValueCollection(); - simpleProvider.Initialize(name, config); - return simpleProvider; - } - - private static MySqlSimpleRoleProvider CreateSimpleRoleProvider(string name, MySQLRoleProvider currentDefault) - { - MySqlSimpleRoleProvider simpleProvider = new MySqlSimpleRoleProvider(currentDefault); - NameValueCollection config = new NameValueCollection(); - simpleProvider.Initialize(name, config); - return simpleProvider; - } - - private static MySqlSimpleMembershipProvider ValidProvider() - { - if (_provider.Initialized) - return _provider; - - throw new Exception(Resources.SimpleMembershipNotInitialized); - } - - private static void InitializeMembershipProvider(string connectionStringName, string connectionString, string providerName, string userTableName, string userIdColumn, string userNameColumn, bool createTables, bool checkIfInitialized = false) - { - if (checkIfInitialized) - { - if (_provider != null) - return; - } - - MySqlSimpleMembershipProvider simpleMembership = new MySqlSimpleMembershipProvider(Membership.Provider); - if (_provider != null && _provider.Initialized) - { - throw new InvalidOperationException(Resources.SimpleMembershipAlreadyInitialized); - } - simpleMembership.ConnectionStringName = connectionStringName; - simpleMembership.ConnectionString = connectionString; - simpleMembership.ProviderName = providerName; - simpleMembership.UserTableName = userTableName; - simpleMembership.UserIdColumn = userIdColumn; - simpleMembership.UserNameColumn = userNameColumn; - if (createTables) - { - simpleMembership.CreateTables(); - } - else - { - simpleMembership.ValidateUserTable(); - } - simpleMembership.Initialized = true; - _provider = simpleMembership; - } - - private static void InitializeRoleProvider(string connectionStringName, string connectionString, string providerName, string userTableName, string userIdColumn, string userNameColumn, bool createTables, bool checkIfInitialized = false) - { - if (checkIfInitialized) - { - if (_roleprovider != null) - return; - } - - MySqlSimpleRoleProvider roleProvider = new MySqlSimpleRoleProvider(Roles.Provider); - if (_roleprovider != null && _roleprovider.Initialized) - { - throw new InvalidOperationException(Resources.SimpleRoleAlreadyInitialized); - } - roleProvider.ConnectionStringName = connectionStringName; - roleProvider.ConnectionString = connectionString; - roleProvider.UserTableName = userTableName; - roleProvider.UserIdColumn = userIdColumn; - roleProvider.UserNameColumn = userNameColumn; - if (createTables) - { - roleProvider.CreateTables(); - } - roleProvider.Initialized = true; - _roleprovider = roleProvider; - } - - private static bool IsSimpleMembershipEnabled() - { - string config = ConfigurationManager.AppSettings[EnableSimpleMembershipKey]; - bool isEnabled = false; - if (!string.IsNullOrEmpty(config)) - { - bool.TryParse(config, out isEnabled); - } - return isEnabled; - } - - internal static void PreAppStartInit() - { - if (IsSimpleMembershipEnabled()) - { - MembershipProvider provider = Membership.Providers[MySqlMembershipProviderName]; - if (provider != null) - { - MySqlSimpleMembershipProvider mysqlProvider = CreateSimpleMembershipProvider(MySqlMembershipProviderName, (MySQLMembershipProvider)provider); - Membership.Providers.Remove(MySqlMembershipProviderName); - Membership.Providers.Add(mysqlProvider); - } - Roles.Enabled = true; - RoleProvider roleProvider = Roles.Providers[MySqlRoleProviderName]; - if (roleProvider != null) - { - MySqlSimpleRoleProvider simpleRoleProv = CreateSimpleRoleProvider(MySqlRoleProviderName, (MySQLRoleProvider)roleProvider); - Roles.Providers.Remove(MySqlRoleProviderName); - Roles.Providers.Add(simpleRoleProv); - } - } - } - - internal static HttpContextBase CurrentContext - { - get { return new HttpContextWrapper(HttpContext.Current); } - } - - private static MySqlSimpleMembershipProvider _provider; - private static MySqlSimpleRoleProvider _roleprovider; - #endregion - } -} +// Copyright © 2014, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySql.Web.Properties; +using System; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.Configuration; +using System.Net; +using System.Web; +using System.Web.Routing; +using System.Web.Security; +using System.Web.WebPages; + +namespace MySql.Web.Security +{ + /// + /// Provides security features for web projects implementing a MySql database. + /// + public static class MySqlWebSecurity + { + /// + /// Name of the key required to enable simple membership. + /// + public static readonly string EnableSimpleMembershipKey = "enableSimpleMembership"; + private static readonly string MySqlMembershipProviderName = "MySqlMembershipProvider"; + private static readonly string MySqlRoleProviderName = "MySQLRoleProvider"; + + #region Public + /// + /// Changes the password for the user provided. + /// + /// The user name. + /// The current pasword. + /// The new Password. + /// + public static bool ChangePassword(string userName, string oldPassword, string newPassword) + { + ValidProvider(); + var user = Membership.GetUser(userName, true); + return user.ChangePassword(oldPassword, newPassword); + } + + /// + /// Confirms user by confirmation token. + /// + /// The confirmation token. + /// true if the user was confirmed; otherwise, false. + public static bool ConfirmAccount(string confirmationToken) + { + var provider = ValidProvider(); + return provider.ConfirmAccount(confirmationToken); + } + + /// + /// Confirms user by confirmation token and user name. + /// + /// The user name. + /// The confirmation token. + /// true if the user was confirmed; otherwise, false. + public static bool ConfirmAccount(string userName, string confirmationToken) + { + var provider = ValidProvider(); + return provider.ConfirmAccount(userName, confirmationToken); + } + + /// + /// Creates a user account. + /// + /// The user name. + /// The user password. + /// Flag to indicate if a confirmation token is required. + /// A confirmation token if required. + public static string CreateAccount(string userName, string password, bool requireConfirmationToken = false) + { + var provider = ValidProvider(); + return provider.CreateAccount(userName, password, requireConfirmationToken); + } + + /// + /// Creates user and account. + /// + /// The user name. + /// The user password. + /// Additional data for user table. + /// Flag to indicate if a confirmation token is required. + /// A confirmation token if required. + public static string CreateUserAndAccount(string userName, string password, object additionalUserAttributes = null, bool requireConfirmationToken = false) + { + var provider = ValidProvider(); + IDictionary userAttrs = additionalUserAttributes as RouteValueDictionary; + + if (userAttrs == null && additionalUserAttributes != null) + { + var attrs = additionalUserAttributes as IDictionary; + userAttrs = attrs != null ? new RouteValueDictionary(attrs) : new RouteValueDictionary(additionalUserAttributes); + } + + return provider.CreateUserAndAccount(userName, password, requireConfirmationToken, userAttrs); + } + + /// + /// Gets the date when the specified user was created. + /// + /// The user name. + /// Date created or minimum date value if the user was not found. + public static DateTime GetCreateDate(string userName) + { + var provider = ValidProvider(); + return provider.GetCreateDate(userName); + } + + /// + /// Gets the last date when password fails. + /// + /// The user name. + /// Last failure date or minimum date value if the user was not found. + public static DateTime GetLastPasswordFailureDate(string userName) + { + var provider = ValidProvider(); + return provider.GetLastPasswordFailureDate(userName); + } + + /// + /// Gets the date when password was changed. + /// + /// The user name. + /// Last password changed date or minimum date value if the user was not found. + public static DateTime GetPasswordChangedDate(string userName) + { + var provider = ValidProvider(); + return provider.GetPasswordChangedDate(userName); + } + + /// + /// Gets the password failures since last success. + /// + /// The user name. + /// The number of failures since last success. + public static int GetPasswordFailuresSinceLastSuccess(string userName) + { + var provider = ValidProvider(); + return provider.GetPasswordFailuresSinceLastSuccess(userName); + } + + /// + /// Generates password reset token for a confirmed user. + /// + /// The user name. + /// The time that the token will be valid. + /// A generated token or null if the user is not confirmed or does not have a token. + public static string GeneratePasswordResetToken(string userName, int tokenExpirationInMinutesFromNow = 1440) + { + var provider = ValidProvider(); + return provider.GeneratePasswordResetToken(userName, tokenExpirationInMinutesFromNow); + } + + /// + /// Gets the user id. + /// + /// The user name. + /// The user id. -1 if the user doesn't exists + public static int GetUserId(string userName) + { + ValidProvider(); + var user = Membership.GetUser(userName); + return user != null ? (int)user.ProviderUserKey : -1; + } + + /// + /// Gets the user id from the password reset token. + /// + /// The reset token. + /// The user id. 0 if the user doesn't exists. + public static int GetUserIdFromPasswordResetToken(string resetToken) + { + var provider = ValidProvider(); + return provider.GetUserIdFromPasswordResetToken(resetToken); + } + + /// + /// Initializes the simple membership provider with the values given. + /// + /// The connection string name defined in the config file. + /// The table name defined to create new users. + /// The column name defined to store the user ids. + /// The column name defined to store the user name. + /// Flag indicating if the tables should be created. + /// Flag indicating to check if the database has been initialized. + public static void InitializeDatabaseConnection(string connectionStringName, string userTableName, string userIdColumn, string userNameColumn, bool createTables, bool checkIfInitialized = false) + { + InitializeMembershipProvider(connectionStringName, null, null, userTableName, userIdColumn, userNameColumn, createTables, checkIfInitialized); + InitializeRoleProvider(connectionStringName, null, null, userTableName, userIdColumn, userNameColumn, createTables, checkIfInitialized); + Initialized = true; + } + + /// + /// Initializes the simple membership provider with the values given. + /// + /// The connection string. + /// The name of the provider. + /// The table name defined to create new users. + /// The column name defined to store the user ids. + /// The column name defined to store the user name. + /// Flag indicating if the tables should be created. + /// Flag indicating to check if the database has been initialized. + public static void InitializeDatabaseConnection(string connectionString, string providerName, string userTableName, string userIdColumn, string userNameColumn, bool createTables, bool checkIfInitialized = false) + { + InitializeMembershipProvider(null, connectionString, providerName, userTableName, userIdColumn, userNameColumn, createTables, checkIfInitialized); + InitializeRoleProvider(null, connectionString, providerName, userTableName, userIdColumn, userNameColumn, createTables, checkIfInitialized); + Initialized = true; + } + + /// + /// Determines if the account is locked out. + /// + /// The name of the user. + /// The number of allowed password attempts. + /// true if the account is locked; otherwise, false. + public static bool IsAccountLockedOut(string userName, int allowedPasswordAttempts, int intervalInSeconds) + { + return IsAccountLockedOut(userName, allowedPasswordAttempts, TimeSpan.FromSeconds(intervalInSeconds)); + } + + /// + /// Determines if the account is locked out. + /// + /// The name of the user. + /// The number of allowed password attempts. + /// true if the account is locked; otherwise, false. + public static bool IsAccountLockedOut(string userName, int allowedPasswordAttempts, TimeSpan interval) + { + var provider = ValidProvider(); + return (provider.GetUser(userName, false) != null && provider.GetPasswordFailuresSinceLastSuccess(userName) > allowedPasswordAttempts && provider.GetLastPasswordFailureDate(userName).Add(interval) > DateTime.UtcNow); + } + + /// + /// Determines if the user has been confirmed. + /// + /// The user name. + /// true if the user is confirmed; otherwise false. + public static bool IsConfirmed(string userName) + { + var provider = ValidProvider(); + return provider.IsConfirmed(userName); + } + + /// + /// Determines if the is the same as the provided user name. + /// + /// The user name. + /// true if the user matches the ; otherwise, false. + public static bool IsCurrentUser(string userName) + { + ValidProvider(); + return string.Equals(CurrentUserName, userName, StringComparison.OrdinalIgnoreCase); + } + + /// + /// Determines if the matches the provided user id. + /// + /// The user id to match. + /// true if the id matches the ; otherwise, false. + public static bool IsUseLoggedOn(int userId) + { + ValidProvider(); + return CurrentUserId == userId; + } + + /// + /// Performs a login for the specified user. + /// + /// The user name. + /// The user password. + /// Flag to indicate if a persistent cookie should be created. + /// true if the login was successful; otherwise, false. + public static bool Login(string userName, string password, bool createPersistentCookie = false) + { + var curentProvider = ValidProvider(); + bool loginSuccessful = false; + if (curentProvider != null) + loginSuccessful = curentProvider.ValidateUser(userName, password); + else + loginSuccessful = Membership.ValidateUser(userName, password); + + if (loginSuccessful) + { + FormsAuthentication.SetAuthCookie(userName, createPersistentCookie); + } + return loginSuccessful; + } + + /// + /// Performs a logout for the current item. + /// + public static void Logout() + { + ValidProvider(); + FormsAuthentication.SignOut(); + } + + /// + /// Evalutes if the user is authenticated. + /// + public static void RequireAuthenticatedUser() + { + ValidProvider(); + var user = CurrentContext.User; + if (user == null || !user.Identity.IsAuthenticated) + { + CurrentContext.Response.SetStatus(HttpStatusCode.Unauthorized); + } + } + + /// + /// Evaluates if the user belongs to the specified roles. + /// + /// + public static void RequireRoles(params string[] roles) + { + ValidProvider(); + foreach (var role in roles) + { + if (!Roles.IsUserInRole(CurrentUserName, role)) + { + CurrentContext.Response.SetStatus(HttpStatusCode.Unauthorized); + } + } + } + + /// + /// Evaluates if the user is logged on. + /// + /// + public static void RequiresUser(int userId) + { + ValidProvider(); + if (!IsUseLoggedOn(userId)) + { + CurrentContext.Response.SetStatus(HttpStatusCode.Unauthorized); + } + } + + /// + /// Evaluates if the provided user name matches the . + /// + /// + public static void RequiresUser(string userName) + { + ValidProvider(); + if (!string.Equals(CurrentUserName, userName, StringComparison.OrdinalIgnoreCase)) + { + CurrentContext.Response.SetStatus(HttpStatusCode.Unauthorized); + } + } + + /// + /// Resets the password identified by the provided password reset token. + /// + /// The password reset token. + /// The new password. + /// true if the password reset was successful; otherwise, false. + public static bool ResetPassword(string passwordResetToken, string newPassword) + { + var provider = ValidProvider(); + return provider.ResetPasswordWithToken(passwordResetToken, newPassword); + } + + /// + /// Determines if the user exists. + /// + /// The user name. + /// true if the user exists; otherwise, false. + public static bool UserExists(string username) + { + var curentProvider = ValidProvider(); + if (curentProvider != null) + return curentProvider.GetUser(username, false) != null; + else + return Membership.GetUser(username) != null; + } + #endregion + + /// + /// Gets the initialized status. + /// + #region Properties + public static bool Initialized + { + get; + private set; + } + + /// + /// Gets the current user id. + /// + public static int CurrentUserId + { + get { return GetUserId(CurrentUserName); } + } + + /// + /// Gets the current user name. + /// + public static string CurrentUserName + { + get { return CurrentContext.User.Identity.Name; } + } + + /// + /// Gets a flag indicating if there is an associated user id. + /// + public static bool HasUserId + { + get { return CurrentUserId != -1; } + } + + /// + /// Gets a flag indicating if the user is authenticated. + /// + public static bool IsAuthenticated + { + get { return CurrentContext.Request.IsAuthenticated; } + } + #endregion + + #region Private_Internal + + private static MySqlSimpleMembershipProvider CreateSimpleMembershipProvider(string name, MySQLMembershipProvider currentDefault) + { + MySqlSimpleMembershipProvider simpleProvider = new MySqlSimpleMembershipProvider(currentDefault); + NameValueCollection config = new NameValueCollection(); + simpleProvider.Initialize(name, config); + return simpleProvider; + } + + private static MySqlSimpleRoleProvider CreateSimpleRoleProvider(string name, MySQLRoleProvider currentDefault) + { + MySqlSimpleRoleProvider simpleProvider = new MySqlSimpleRoleProvider(currentDefault); + NameValueCollection config = new NameValueCollection(); + simpleProvider.Initialize(name, config); + return simpleProvider; + } + + private static MySqlSimpleMembershipProvider ValidProvider() + { + if (_provider.Initialized) + return _provider; + + throw new Exception(Resources.SimpleMembershipNotInitialized); + } + + private static void InitializeMembershipProvider(string connectionStringName, string connectionString, string providerName, string userTableName, string userIdColumn, string userNameColumn, bool createTables, bool checkIfInitialized = false) + { + if (checkIfInitialized) + { + if (_provider != null) + return; + } + + MySqlSimpleMembershipProvider simpleMembership = new MySqlSimpleMembershipProvider(Membership.Provider); + if (_provider != null && _provider.Initialized) + { + throw new InvalidOperationException(Resources.SimpleMembershipAlreadyInitialized); + } + simpleMembership.ConnectionStringName = connectionStringName; + simpleMembership.ConnectionString = connectionString; + simpleMembership.ProviderName = providerName; + simpleMembership.UserTableName = userTableName; + simpleMembership.UserIdColumn = userIdColumn; + simpleMembership.UserNameColumn = userNameColumn; + if (createTables) + { + simpleMembership.CreateTables(); + } + else + { + simpleMembership.ValidateUserTable(); + } + simpleMembership.Initialized = true; + _provider = simpleMembership; + } + + private static void InitializeRoleProvider(string connectionStringName, string connectionString, string providerName, string userTableName, string userIdColumn, string userNameColumn, bool createTables, bool checkIfInitialized = false) + { + if (checkIfInitialized) + { + if (_roleprovider != null) + return; + } + + MySqlSimpleRoleProvider roleProvider = new MySqlSimpleRoleProvider(Roles.Provider); + if (_roleprovider != null && _roleprovider.Initialized) + { + throw new InvalidOperationException(Resources.SimpleRoleAlreadyInitialized); + } + roleProvider.ConnectionStringName = connectionStringName; + roleProvider.ConnectionString = connectionString; + roleProvider.UserTableName = userTableName; + roleProvider.UserIdColumn = userIdColumn; + roleProvider.UserNameColumn = userNameColumn; + if (createTables) + { + roleProvider.CreateTables(); + } + roleProvider.Initialized = true; + _roleprovider = roleProvider; + } + + private static bool IsSimpleMembershipEnabled() + { + string config = ConfigurationManager.AppSettings[EnableSimpleMembershipKey]; + bool isEnabled = false; + if (!string.IsNullOrEmpty(config)) + { + bool.TryParse(config, out isEnabled); + } + return isEnabled; + } + + internal static void PreAppStartInit() + { + if (IsSimpleMembershipEnabled()) + { + MembershipProvider provider = Membership.Providers[MySqlMembershipProviderName]; + if (provider != null) + { + MySqlSimpleMembershipProvider mysqlProvider = CreateSimpleMembershipProvider(MySqlMembershipProviderName, (MySQLMembershipProvider)provider); + Membership.Providers.Remove(MySqlMembershipProviderName); + Membership.Providers.Add(mysqlProvider); + } + Roles.Enabled = true; + RoleProvider roleProvider = Roles.Providers[MySqlRoleProviderName]; + if (roleProvider != null) + { + MySqlSimpleRoleProvider simpleRoleProv = CreateSimpleRoleProvider(MySqlRoleProviderName, (MySQLRoleProvider)roleProvider); + Roles.Providers.Remove(MySqlRoleProviderName); + Roles.Providers.Add(simpleRoleProv); + } + } + } + + internal static HttpContextBase CurrentContext + { + get { return new HttpContextWrapper(HttpContext.Current); } + } + + private static MySqlSimpleMembershipProvider _provider; + private static MySqlSimpleRoleProvider _roleprovider; + #endregion + } +} diff --git a/MySql.Web/src/PersonalizationConnectionHelper.cs b/MySql.Web/src/PersonalizationConnectionHelper.cs index e4b610583..f8363d7bb 100644 --- a/MySql.Web/src/PersonalizationConnectionHelper.cs +++ b/MySql.Web/src/PersonalizationConnectionHelper.cs @@ -1,86 +1,86 @@ -// Copyright (c) 2014, 2020, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySql.Data.MySqlClient; -using System; -using System.Web.Hosting; - -namespace MySql.Web -{ - internal sealed class MySQLPersonalizationConnectionHelper - { - private MySqlConnection _connection; - - public MySqlConnection Connection - { - get { - return _connection; - } - } - - public bool Opened - { - get { - return _connection.State == System.Data.ConnectionState.Open; - } - } - - internal MySQLPersonalizationConnectionHelper(string connectionString) - { - if (string.IsNullOrEmpty(connectionString)) - { - throw new ArgumentNullException("connectionString"); - } - - _connection = new MySqlConnection(connectionString); - } - - internal void OpenConnection(bool impersonateContext) - { - if (_connection.State != System.Data.ConnectionState.Open) - { - if (impersonateContext) - { - using (HostingEnvironment.Impersonate()) - { - _connection.Open(); - } - } - else - _connection.Open(); - } - } - - internal void CloseConnection() - { - if (_connection.State != System.Data.ConnectionState.Closed) - _connection.Close(); - } - - } -} +// Copyright © 2014, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySql.Data.MySqlClient; +using System; +using System.Web.Hosting; + +namespace MySql.Web +{ + internal sealed class MySQLPersonalizationConnectionHelper + { + private MySqlConnection _connection; + + public MySqlConnection Connection + { + get { + return _connection; + } + } + + public bool Opened + { + get { + return _connection.State == System.Data.ConnectionState.Open; + } + } + + internal MySQLPersonalizationConnectionHelper(string connectionString) + { + if (string.IsNullOrEmpty(connectionString)) + { + throw new ArgumentNullException("connectionString"); + } + + _connection = new MySqlConnection(connectionString); + } + + internal void OpenConnection(bool impersonateContext) + { + if (_connection.State != System.Data.ConnectionState.Open) + { + if (impersonateContext) + { + using (HostingEnvironment.Impersonate()) + { + _connection.Open(); + } + } + else + _connection.Open(); + } + } + + internal void CloseConnection() + { + if (_connection.State != System.Data.ConnectionState.Closed) + _connection.Close(); + } + + } +} diff --git a/MySql.Web/src/PersonalizationProvider.cs b/MySql.Web/src/PersonalizationProvider.cs index a78fdb0f6..f98a96859 100644 --- a/MySql.Web/src/PersonalizationProvider.cs +++ b/MySql.Web/src/PersonalizationProvider.cs @@ -1,569 +1,569 @@ -// Copyright (c) 2014, 2020, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySql.Data.MySqlClient; -using MySql.Web.Common; -using MySql.Web.General; -using System; -using System.Diagnostics; -using System.Web.Hosting; -using System.Web.UI.WebControls.WebParts; - -namespace MySql.Web.Personalization -{ - /// - /// Implementation for Personalization Provider to use web parts in ASP.NET websites. - /// - public class MySqlPersonalizationProvider : PersonalizationProvider - { - - string connectionString; - - - string eventSource = "MySQLPersonalizationProvider"; - string eventLog = "Application"; - string exceptionMessage = "An exception occurred. Please check the event log."; - bool writeExceptionsToEventLog = false; - - Application app; - - /// - /// Gets or sets the application name. - /// - public override string ApplicationName - { - get { return app.Name; } - set { app.Name = value; } - } - - private long ApplicationId - { - get { return app.Id; } - } - - private enum ResetUserStateMode - { - PerInactiveDate, - PerPaths, - PerUsers - } - - - /// - /// Initializes settings values for Personalization Provider. - /// - /// The name of the provider. - /// A named value collection representing the configurations for this provider. - public override void Initialize(string name, System.Collections.Specialized.NameValueCollection config) - { - if (config == null) - throw new ArgumentNullException("config"); - - if (string.IsNullOrEmpty(name)) - { - name = "MySqlPersonalizationProvider"; - } - - if (string.IsNullOrEmpty(config["description"])) - { - config.Remove("description"); - config.Add("description", "MySql Personalization provider"); - } - - base.Initialize(name, config); - - string applicationName = HostingEnvironment.ApplicationVirtualPath; - if (!String.IsNullOrEmpty(config["applicationName"])) - applicationName = config["applicationName"]; - - - if (!(config["writeExceptionsToEventLog"] == null)) - { - if (config["writeExceptionsToEventLog"].ToUpper() == "TRUE") - { - writeExceptionsToEventLog = true; - } - } - connectionString = ConfigUtility.GetConnectionString(config); - if (String.IsNullOrEmpty(connectionString)) return; - - // Make sure we have the correct schema. - SchemaManager.CheckSchema(connectionString, config); - - app = new Application(applicationName, base.Description); - - // Get the application id. - try - { - using (MySqlConnection conn = new MySqlConnection(connectionString)) - { - conn.Open(); - app.EnsureId(conn); - } - } - catch (Exception ex) - { - if (writeExceptionsToEventLog) - WriteToEventLog(ex, "MySQLPersonalizationProvider - Initialize"); - throw; - } - } - - /// - /// Returns a collection of PersonalizationStateInfo objects containing administrative information regarding records in the database that match the specified criteria. - /// - /// The personalization scope. - /// The set of query parameters. - /// The index of the page. - /// The size of the page. - /// The total number of records to return. - /// For example, records corresponding to users named Jeff* that have been modified since January 1, 2005. Wildcard support is provider-dependent. - public override PersonalizationStateInfoCollection FindState(PersonalizationScope scope, PersonalizationStateQuery query, int pageIndex, int pageSize, out int totalRecords) - { - - if (query == null) - throw new ArgumentNullException("query"); - - if (pageIndex < 0) - throw new ArgumentOutOfRangeException("pageIndex"); - - if (pageSize < 1) - throw new ArgumentOutOfRangeException("pageSize"); - - if (query.PathToMatch == null) - throw new ArgumentNullException("query.PathToMatch"); - - if (query.UsernameToMatch == null) - throw new ArgumentNullException("query.UserToMatch"); - - DateTime inactiveSinceDate = query.UserInactiveSinceDate; - - if (scope == PersonalizationScope.User) - { - return FindUserState(query.PathToMatch.Trim(), inactiveSinceDate, query.UsernameToMatch.Trim(), pageIndex, pageSize, out totalRecords); - } - else - { - return FindSharedState(query.PathToMatch.Trim(), pageIndex, pageSize, out totalRecords); - } - } - - - /// - /// Returns the number of records in the database that match the specified criteria. - /// - /// The personalization scope. - /// The set of query parameters. - /// For example, records corresponding to users named Jeff* that haven't been modified since January 1, 2005. Wildcard support is provider-dependent. - public override int GetCountOfState(PersonalizationScope scope, PersonalizationStateQuery query) - { - if (query == null) - throw new ArgumentNullException("query"); - - if (scope == PersonalizationScope.User) - { - return GetCountUserState(query.PathToMatch.Trim(), query.UserInactiveSinceDate, query.UsernameToMatch); - } - else - { - return GetCountOfSharedState(query.PathToMatch.Trim()); - } - } - - - /// - /// Retrieves personalization state as opaque blobs from the data source. - /// - /// The web part manager. - /// The path indicating where to save the data. - /// The user name. - /// A byte array containing the user shared data to loaded. - /// A byte array containing the user data to be loaded. - /// Retrieves both shared and user personalization state corresponding to a specified user and a specified page. - protected override void LoadPersonalizationBlobs(WebPartManager webPartManager, string path, string userName, ref Byte[] sharedDataBlob, ref Byte[] userDataBlob) - { - sharedDataBlob = null; - userDataBlob = null; - MySQLPersonalizationConnectionHelper connection = new MySQLPersonalizationConnectionHelper(connectionString); - connection.OpenConnection(true); - try - { - sharedDataBlob = PersonalizationProviderProcedures.my_aspnet_PersonalizationAllUsers_GetPageSettings( - ApplicationId, path, connection); - if (!String.IsNullOrEmpty(userName)) - { - userDataBlob = PersonalizationProviderProcedures.my_aspnet_PersonalizationPerUser_GetPageSettings( - ApplicationId, path, userName, DateTime.UtcNow, connection); - } - - connection.CloseConnection(); - } - catch (Exception ex) - { - if (writeExceptionsToEventLog) - WriteToEventLog(ex, "MySQLPersonalizationProvider - LoadPersonazalitionBlobs"); - throw; - } - finally - { - connection.CloseConnection(); - } - } - - /// - /// Deletes personalization state corresponding to a specified user and a specified page from the database. - /// - /// The web part manager. - /// The path indicating where to save the data. - /// The user name. - protected override void ResetPersonalizationBlob(WebPartManager webPartManager, string path, string userName) - { - MySQLPersonalizationConnectionHelper connection = new MySQLPersonalizationConnectionHelper(connectionString); - connection.OpenConnection(true); - try - { - if (string.IsNullOrEmpty(userName)) - { - PersonalizationProviderProcedures.my_aspnet_PersonalizationAllUsers_ResetPageSettings(ApplicationId, path, connection); - } - else - { - PersonalizationProviderProcedures.my_aspnet_PersonalizationPerUser_ResetPageSettings(ApplicationId, userName, path, DateTime.UtcNow, connection); - } - } - catch (Exception ex) - { - if (writeExceptionsToEventLog) - WriteToEventLog(ex, "MySQLPersonalizationProvider - ResetPersonalizationBlob"); - throw; - } - finally - { - connection.CloseConnection(); - } - } - - /// - /// Deletes personalization state corresponding to the specified users and specified pages from the database. - /// - /// The personalization scope. - /// The paths indicating where to save the data. - /// The user names. - /// - public override int ResetState(PersonalizationScope scope, string[] paths, string[] usernames) - { - - bool hasPaths = !(paths == null || paths.Length == 0); - bool hasUsers = !(usernames == null || usernames.Length == 0); - - var count = 0; - - var connection = new MySQLPersonalizationConnectionHelper(connectionString); - connection.OpenConnection(true); - - if (scope == PersonalizationScope.Shared) - { - try - { - if (paths == null) // reset all state - { - return PersonalizationProviderProcedures.my_aspnet_PersonalizationAdministration_DeleteAllState(true, ApplicationId, connection); - } - else - { - return PersonalizationProviderProcedures.my_aspnet_PersonalizationAdministration_ResetSharedState(ApplicationId, paths, connection); - } - } - catch (Exception ex) - { - if (writeExceptionsToEventLog) - WriteToEventLog(ex, "MySQLPersonalizationProvider - ResetState"); - throw; - } - finally - { - connection.CloseConnection(); - } - } - else - { - DateTime dateTime = Convert.ToDateTime("2038-01-19 03:14:07.999999"); // MySQL TimeStamp MaxValue - - if (!hasPaths && !hasUsers) - { - count = PersonalizationProviderProcedures.my_aspnet_PersonalizationAdministration_DeleteAllState(true, ApplicationId, connection); - } - else if (!hasUsers) - { - count = ResetUserState(ResetUserStateMode.PerPaths, dateTime, paths, null); - } - else - { - count = ResetUserState(ResetUserStateMode.PerUsers, dateTime, paths, usernames); - } - } - return count; - } - - - /// - /// Deletes user personalization state corresponding to the specified pages and that hasn't been updated since a specified date from the database. - /// - /// The path indicating where to retrieve the user state from. - /// A time and date indicating since when the user has been inactive. - /// - public override int ResetUserState(string path, DateTime userInactiveSinceDate) - { - if (string.IsNullOrEmpty(path)) - return 0; - - string[] paths = (path == null) ? null : new string[] { path }; - try - { - return ResetUserState(ResetUserStateMode.PerInactiveDate, userInactiveSinceDate, paths, null); - } - catch (Exception ex) - { - if (writeExceptionsToEventLog) - WriteToEventLog(ex, "MySQLPersonalizationProvider - ResetUserState"); - throw; - } - } - - /// - /// Writes personalization state corresponding to a specified user and a specified page as an opaque blob to the database. - /// - /// The web part manager. - /// The path indicating where to save the data. - /// The user name. - /// A byte array containing the data to be saved. - /// If userName is null, then the personalization state is shared state and is not keyed by user name. - protected override void SavePersonalizationBlob(WebPartManager webPartManager, string path, string userName, Byte[] dataBlob) - { - - MySQLPersonalizationConnectionHelper connection = new MySQLPersonalizationConnectionHelper(connectionString); - - try - { - MySqlCommand cmd = new MySqlCommand(); - connection.OpenConnection(true); - if (!string.IsNullOrEmpty(userName)) - { - PersonalizationProviderProcedures.my_aspnet_PersonalizationPerUser_SetPageSettings(ApplicationId, userName, path, dataBlob, DateTime.UtcNow, connection); - } - else - { - PersonalizationProviderProcedures.my_aspnet_PersonalizationAllUsers_SetPageSettings(ApplicationId, path, dataBlob, DateTime.UtcNow, connection); - } - } - catch (Exception ex) - { - if (writeExceptionsToEventLog) - WriteToEventLog(ex, "MySQLPersonalizationProvider - SavePersonalizationBlob"); - throw; - } - } - - private PersonalizationStateInfoCollection FindSharedState(string path, int pageIndex, int pageSize, out int totalRecords) - { - MySQLPersonalizationConnectionHelper connection = new MySQLPersonalizationConnectionHelper(connectionString); - - try - { - MySqlCommand cmd = new MySqlCommand(); - connection.OpenConnection(true); - totalRecords = PersonalizationProviderProcedures.myaspnet_PersonalizationAdministration_FindState(true, ApplicationId, ApplicationName, pageIndex, pageSize, - path, null, DateTime.MinValue, connection, ref cmd); - - PersonalizationStateInfoCollection sharedStateInfoCollection = new PersonalizationStateInfoCollection(); - - using (var reader = cmd.ExecuteReader()) - { - while (reader.Read()) - { - string pathQuery = reader.GetString("Path"); - DateTime lastUpdatedDate = (reader.IsDBNull(1)) ? DateTime.MinValue : - DateTime.SpecifyKind(reader.GetDateTime(1), DateTimeKind.Utc); - int size = (reader.IsDBNull(2)) ? 0 : reader.GetInt32("SharedDataLength"); - int userDataLength = (reader.IsDBNull(3)) ? 0 : reader.GetInt32("UserDataLength"); - int userCount = (reader.IsDBNull(4)) ? 0 : reader.GetInt32("UserCount"); - - sharedStateInfoCollection.Add(new SharedPersonalizationStateInfo( - pathQuery, lastUpdatedDate, size, userDataLength, userCount)); - } - } - connection.CloseConnection(); - return sharedStateInfoCollection; - } - catch (Exception ex) - { - if (writeExceptionsToEventLog) - WriteToEventLog(ex, "MySQLPersonalizationProvider - FindSharedState"); - throw; - } - finally - { - connection.CloseConnection(); - } - } - - private PersonalizationStateInfoCollection FindUserState(string path, DateTime inactiveSinceDate, string userName, int pageIndex, int pageSize, out int totalRecords) - { - MySQLPersonalizationConnectionHelper connection = new MySQLPersonalizationConnectionHelper(connectionString); - - try - { - - MySqlCommand cmd = new MySqlCommand(); - connection.OpenConnection(true); - totalRecords = PersonalizationProviderProcedures.myaspnet_PersonalizationAdministration_FindState(false, ApplicationId, ApplicationName, pageIndex, pageSize, - path, userName, inactiveSinceDate, connection, ref cmd); - - PersonalizationStateInfoCollection stateInfoCollection = new PersonalizationStateInfoCollection(); - - using (var reader = cmd.ExecuteReader()) - { - while (reader.Read()) - { - string pathQuery = reader.GetString("Path"); - DateTime lastUpdatedDate = DateTime.SpecifyKind(reader.GetDateTime("LastUpdatedDate"), DateTimeKind.Utc); - int size = reader.GetInt32("Size"); - string usernameQuery = reader.GetString("name"); - DateTime lastActivityDate = DateTime.SpecifyKind(reader.GetDateTime("LastActivityDate"), DateTimeKind.Utc); - stateInfoCollection.Add(new UserPersonalizationStateInfo(pathQuery, lastActivityDate, size, usernameQuery, lastActivityDate)); - } - } - connection.CloseConnection(); - - return stateInfoCollection; - } - catch (Exception ex) - { - if (writeExceptionsToEventLog) - WriteToEventLog(ex, "MySQLPersonalizationProvider - FindUserState"); - throw; - } - finally - { - connection.CloseConnection(); - } - } - - private int GetCountOfSharedState(string path) - { - MySQLPersonalizationConnectionHelper connection = new MySQLPersonalizationConnectionHelper(connectionString); - try - { - MySqlCommand cmd = new MySqlCommand(); - connection.OpenConnection(true); - return PersonalizationProviderProcedures.myaspnet_PersonalizationAdministration_GetCountOfState( - true, ApplicationName, ApplicationId, path, - null, DateTime.MinValue, connection); - } - catch (Exception ex) - { - if (writeExceptionsToEventLog) - WriteToEventLog(ex, "MySQLPersonalizationProvider - GetCountOfSharedState"); - throw; - } - finally - { - connection.CloseConnection(); - } - } - - private int GetCountUserState(string path, DateTime userInactiveSinceDate, string userName) - { - MySQLPersonalizationConnectionHelper connection = new MySQLPersonalizationConnectionHelper(connectionString); - try - { - MySqlCommand cmd = new MySqlCommand(); - connection.OpenConnection(true); - return PersonalizationProviderProcedures.myaspnet_PersonalizationAdministration_GetCountOfState( - false, ApplicationName, ApplicationId, path, - userName, userInactiveSinceDate, connection); - } - catch (Exception ex) - { - if (writeExceptionsToEventLog) - WriteToEventLog(ex, "MySQLPersonalizationProvider - GetCountUserState"); - throw; - } - finally - { - connection.CloseConnection(); - } - } - - private int ResetUserState(ResetUserStateMode mode, DateTime userInactiveSinceDate, string[] paths, string[] usernames) - { - var connection = new MySQLPersonalizationConnectionHelper(connectionString); - connection.OpenConnection(true); - - try - { - if (ResetUserStateMode.PerInactiveDate == mode) - { - return PersonalizationProviderProcedures.my_aspnet_PersonalizationAdministration_ResetUserState(ApplicationId, userInactiveSinceDate.ToUniversalTime(), null, null, connection); - } - if (ResetUserStateMode.PerPaths == mode) - { - return PersonalizationProviderProcedures.my_aspnet_PersonalizationAdministration_ResetUserState(ApplicationId, userInactiveSinceDate, null, paths, connection); - } - else - { - return PersonalizationProviderProcedures.my_aspnet_PersonalizationAdministration_ResetUserState(ApplicationId, userInactiveSinceDate, usernames, paths, connection); - } - } - catch (Exception ex) - { - if (writeExceptionsToEventLog) - WriteToEventLog(ex, "MySQLPersonalizationProvider - ResetUserState"); - throw; - } - finally - { - connection.CloseConnection(); - } - } - - private void WriteToEventLog(Exception e, string action) - { - using (EventLog log = new EventLog()) - { - log.Source = eventSource; - log.Log = eventLog; - string message = exceptionMessage + Environment.NewLine + Environment.NewLine; - message += "Action: " + action + Environment.NewLine + Environment.NewLine; - message += "Exception: " + e; - log.WriteEntry(message); - } - } - - } -} +// Copyright © 2014, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySql.Data.MySqlClient; +using MySql.Web.Common; +using MySql.Web.General; +using System; +using System.Diagnostics; +using System.Web.Hosting; +using System.Web.UI.WebControls.WebParts; + +namespace MySql.Web.Personalization +{ + /// + /// Implementation for Personalization Provider to use web parts in ASP.NET websites. + /// + public class MySqlPersonalizationProvider : PersonalizationProvider + { + + string connectionString; + + + string eventSource = "MySQLPersonalizationProvider"; + string eventLog = "Application"; + string exceptionMessage = "An exception occurred. Please check the event log."; + bool writeExceptionsToEventLog = false; + + Application app; + + /// + /// Gets or sets the application name. + /// + public override string ApplicationName + { + get { return app.Name; } + set { app.Name = value; } + } + + private long ApplicationId + { + get { return app.Id; } + } + + private enum ResetUserStateMode + { + PerInactiveDate, + PerPaths, + PerUsers + } + + + /// + /// Initializes settings values for Personalization Provider. + /// + /// The name of the provider. + /// A named value collection representing the configurations for this provider. + public override void Initialize(string name, System.Collections.Specialized.NameValueCollection config) + { + if (config == null) + throw new ArgumentNullException("config"); + + if (string.IsNullOrEmpty(name)) + { + name = "MySqlPersonalizationProvider"; + } + + if (string.IsNullOrEmpty(config["description"])) + { + config.Remove("description"); + config.Add("description", "MySql Personalization provider"); + } + + base.Initialize(name, config); + + string applicationName = HostingEnvironment.ApplicationVirtualPath; + if (!String.IsNullOrEmpty(config["applicationName"])) + applicationName = config["applicationName"]; + + + if (!(config["writeExceptionsToEventLog"] == null)) + { + if (config["writeExceptionsToEventLog"].ToUpper() == "TRUE") + { + writeExceptionsToEventLog = true; + } + } + connectionString = ConfigUtility.GetConnectionString(config); + if (String.IsNullOrEmpty(connectionString)) return; + + // Make sure we have the correct schema. + SchemaManager.CheckSchema(connectionString, config); + + app = new Application(applicationName, base.Description); + + // Get the application id. + try + { + using (MySqlConnection conn = new MySqlConnection(connectionString)) + { + conn.Open(); + app.EnsureId(conn); + } + } + catch (Exception ex) + { + if (writeExceptionsToEventLog) + WriteToEventLog(ex, "MySQLPersonalizationProvider - Initialize"); + throw; + } + } + + /// + /// Returns a collection of PersonalizationStateInfo objects containing administrative information regarding records in the database that match the specified criteria. + /// + /// The personalization scope. + /// The set of query parameters. + /// The index of the page. + /// The size of the page. + /// The total number of records to return. + /// For example, records corresponding to users named Jeff* that have been modified since January 1, 2005. Wildcard support is provider-dependent. + public override PersonalizationStateInfoCollection FindState(PersonalizationScope scope, PersonalizationStateQuery query, int pageIndex, int pageSize, out int totalRecords) + { + + if (query == null) + throw new ArgumentNullException("query"); + + if (pageIndex < 0) + throw new ArgumentOutOfRangeException("pageIndex"); + + if (pageSize < 1) + throw new ArgumentOutOfRangeException("pageSize"); + + if (query.PathToMatch == null) + throw new ArgumentNullException("query.PathToMatch"); + + if (query.UsernameToMatch == null) + throw new ArgumentNullException("query.UserToMatch"); + + DateTime inactiveSinceDate = query.UserInactiveSinceDate; + + if (scope == PersonalizationScope.User) + { + return FindUserState(query.PathToMatch.Trim(), inactiveSinceDate, query.UsernameToMatch.Trim(), pageIndex, pageSize, out totalRecords); + } + else + { + return FindSharedState(query.PathToMatch.Trim(), pageIndex, pageSize, out totalRecords); + } + } + + + /// + /// Returns the number of records in the database that match the specified criteria. + /// + /// The personalization scope. + /// The set of query parameters. + /// For example, records corresponding to users named Jeff* that haven't been modified since January 1, 2005. Wildcard support is provider-dependent. + public override int GetCountOfState(PersonalizationScope scope, PersonalizationStateQuery query) + { + if (query == null) + throw new ArgumentNullException("query"); + + if (scope == PersonalizationScope.User) + { + return GetCountUserState(query.PathToMatch.Trim(), query.UserInactiveSinceDate, query.UsernameToMatch); + } + else + { + return GetCountOfSharedState(query.PathToMatch.Trim()); + } + } + + + /// + /// Retrieves personalization state as opaque blobs from the data source. + /// + /// The web part manager. + /// The path indicating where to save the data. + /// The user name. + /// A byte array containing the user shared data to loaded. + /// A byte array containing the user data to be loaded. + /// Retrieves both shared and user personalization state corresponding to a specified user and a specified page. + protected override void LoadPersonalizationBlobs(WebPartManager webPartManager, string path, string userName, ref Byte[] sharedDataBlob, ref Byte[] userDataBlob) + { + sharedDataBlob = null; + userDataBlob = null; + MySQLPersonalizationConnectionHelper connection = new MySQLPersonalizationConnectionHelper(connectionString); + connection.OpenConnection(true); + try + { + sharedDataBlob = PersonalizationProviderProcedures.my_aspnet_PersonalizationAllUsers_GetPageSettings( + ApplicationId, path, connection); + if (!String.IsNullOrEmpty(userName)) + { + userDataBlob = PersonalizationProviderProcedures.my_aspnet_PersonalizationPerUser_GetPageSettings( + ApplicationId, path, userName, DateTime.UtcNow, connection); + } + + connection.CloseConnection(); + } + catch (Exception ex) + { + if (writeExceptionsToEventLog) + WriteToEventLog(ex, "MySQLPersonalizationProvider - LoadPersonazalitionBlobs"); + throw; + } + finally + { + connection.CloseConnection(); + } + } + + /// + /// Deletes personalization state corresponding to a specified user and a specified page from the database. + /// + /// The web part manager. + /// The path indicating where to save the data. + /// The user name. + protected override void ResetPersonalizationBlob(WebPartManager webPartManager, string path, string userName) + { + MySQLPersonalizationConnectionHelper connection = new MySQLPersonalizationConnectionHelper(connectionString); + connection.OpenConnection(true); + try + { + if (string.IsNullOrEmpty(userName)) + { + PersonalizationProviderProcedures.my_aspnet_PersonalizationAllUsers_ResetPageSettings(ApplicationId, path, connection); + } + else + { + PersonalizationProviderProcedures.my_aspnet_PersonalizationPerUser_ResetPageSettings(ApplicationId, userName, path, DateTime.UtcNow, connection); + } + } + catch (Exception ex) + { + if (writeExceptionsToEventLog) + WriteToEventLog(ex, "MySQLPersonalizationProvider - ResetPersonalizationBlob"); + throw; + } + finally + { + connection.CloseConnection(); + } + } + + /// + /// Deletes personalization state corresponding to the specified users and specified pages from the database. + /// + /// The personalization scope. + /// The paths indicating where to save the data. + /// The user names. + /// + public override int ResetState(PersonalizationScope scope, string[] paths, string[] usernames) + { + + bool hasPaths = !(paths == null || paths.Length == 0); + bool hasUsers = !(usernames == null || usernames.Length == 0); + + var count = 0; + + var connection = new MySQLPersonalizationConnectionHelper(connectionString); + connection.OpenConnection(true); + + if (scope == PersonalizationScope.Shared) + { + try + { + if (paths == null) // reset all state + { + return PersonalizationProviderProcedures.my_aspnet_PersonalizationAdministration_DeleteAllState(true, ApplicationId, connection); + } + else + { + return PersonalizationProviderProcedures.my_aspnet_PersonalizationAdministration_ResetSharedState(ApplicationId, paths, connection); + } + } + catch (Exception ex) + { + if (writeExceptionsToEventLog) + WriteToEventLog(ex, "MySQLPersonalizationProvider - ResetState"); + throw; + } + finally + { + connection.CloseConnection(); + } + } + else + { + DateTime dateTime = Convert.ToDateTime("2038-01-19 03:14:07.999999"); // MySQL TimeStamp MaxValue + + if (!hasPaths && !hasUsers) + { + count = PersonalizationProviderProcedures.my_aspnet_PersonalizationAdministration_DeleteAllState(true, ApplicationId, connection); + } + else if (!hasUsers) + { + count = ResetUserState(ResetUserStateMode.PerPaths, dateTime, paths, null); + } + else + { + count = ResetUserState(ResetUserStateMode.PerUsers, dateTime, paths, usernames); + } + } + return count; + } + + + /// + /// Deletes user personalization state corresponding to the specified pages and that hasn't been updated since a specified date from the database. + /// + /// The path indicating where to retrieve the user state from. + /// A time and date indicating since when the user has been inactive. + /// + public override int ResetUserState(string path, DateTime userInactiveSinceDate) + { + if (string.IsNullOrEmpty(path)) + return 0; + + string[] paths = (path == null) ? null : new string[] { path }; + try + { + return ResetUserState(ResetUserStateMode.PerInactiveDate, userInactiveSinceDate, paths, null); + } + catch (Exception ex) + { + if (writeExceptionsToEventLog) + WriteToEventLog(ex, "MySQLPersonalizationProvider - ResetUserState"); + throw; + } + } + + /// + /// Writes personalization state corresponding to a specified user and a specified page as an opaque blob to the database. + /// + /// The web part manager. + /// The path indicating where to save the data. + /// The user name. + /// A byte array containing the data to be saved. + /// If userName is null, then the personalization state is shared state and is not keyed by user name. + protected override void SavePersonalizationBlob(WebPartManager webPartManager, string path, string userName, Byte[] dataBlob) + { + + MySQLPersonalizationConnectionHelper connection = new MySQLPersonalizationConnectionHelper(connectionString); + + try + { + MySqlCommand cmd = new MySqlCommand(); + connection.OpenConnection(true); + if (!string.IsNullOrEmpty(userName)) + { + PersonalizationProviderProcedures.my_aspnet_PersonalizationPerUser_SetPageSettings(ApplicationId, userName, path, dataBlob, DateTime.UtcNow, connection); + } + else + { + PersonalizationProviderProcedures.my_aspnet_PersonalizationAllUsers_SetPageSettings(ApplicationId, path, dataBlob, DateTime.UtcNow, connection); + } + } + catch (Exception ex) + { + if (writeExceptionsToEventLog) + WriteToEventLog(ex, "MySQLPersonalizationProvider - SavePersonalizationBlob"); + throw; + } + } + + private PersonalizationStateInfoCollection FindSharedState(string path, int pageIndex, int pageSize, out int totalRecords) + { + MySQLPersonalizationConnectionHelper connection = new MySQLPersonalizationConnectionHelper(connectionString); + + try + { + MySqlCommand cmd = new MySqlCommand(); + connection.OpenConnection(true); + totalRecords = PersonalizationProviderProcedures.myaspnet_PersonalizationAdministration_FindState(true, ApplicationId, ApplicationName, pageIndex, pageSize, + path, null, DateTime.MinValue, connection, ref cmd); + + PersonalizationStateInfoCollection sharedStateInfoCollection = new PersonalizationStateInfoCollection(); + + using (var reader = cmd.ExecuteReader()) + { + while (reader.Read()) + { + string pathQuery = reader.GetString("Path"); + DateTime lastUpdatedDate = (reader.IsDBNull(1)) ? DateTime.MinValue : + DateTime.SpecifyKind(reader.GetDateTime(1), DateTimeKind.Utc); + int size = (reader.IsDBNull(2)) ? 0 : reader.GetInt32("SharedDataLength"); + int userDataLength = (reader.IsDBNull(3)) ? 0 : reader.GetInt32("UserDataLength"); + int userCount = (reader.IsDBNull(4)) ? 0 : reader.GetInt32("UserCount"); + + sharedStateInfoCollection.Add(new SharedPersonalizationStateInfo( + pathQuery, lastUpdatedDate, size, userDataLength, userCount)); + } + } + connection.CloseConnection(); + return sharedStateInfoCollection; + } + catch (Exception ex) + { + if (writeExceptionsToEventLog) + WriteToEventLog(ex, "MySQLPersonalizationProvider - FindSharedState"); + throw; + } + finally + { + connection.CloseConnection(); + } + } + + private PersonalizationStateInfoCollection FindUserState(string path, DateTime inactiveSinceDate, string userName, int pageIndex, int pageSize, out int totalRecords) + { + MySQLPersonalizationConnectionHelper connection = new MySQLPersonalizationConnectionHelper(connectionString); + + try + { + + MySqlCommand cmd = new MySqlCommand(); + connection.OpenConnection(true); + totalRecords = PersonalizationProviderProcedures.myaspnet_PersonalizationAdministration_FindState(false, ApplicationId, ApplicationName, pageIndex, pageSize, + path, userName, inactiveSinceDate, connection, ref cmd); + + PersonalizationStateInfoCollection stateInfoCollection = new PersonalizationStateInfoCollection(); + + using (var reader = cmd.ExecuteReader()) + { + while (reader.Read()) + { + string pathQuery = reader.GetString("Path"); + DateTime lastUpdatedDate = DateTime.SpecifyKind(reader.GetDateTime("LastUpdatedDate"), DateTimeKind.Utc); + int size = reader.GetInt32("Size"); + string usernameQuery = reader.GetString("name"); + DateTime lastActivityDate = DateTime.SpecifyKind(reader.GetDateTime("LastActivityDate"), DateTimeKind.Utc); + stateInfoCollection.Add(new UserPersonalizationStateInfo(pathQuery, lastActivityDate, size, usernameQuery, lastActivityDate)); + } + } + connection.CloseConnection(); + + return stateInfoCollection; + } + catch (Exception ex) + { + if (writeExceptionsToEventLog) + WriteToEventLog(ex, "MySQLPersonalizationProvider - FindUserState"); + throw; + } + finally + { + connection.CloseConnection(); + } + } + + private int GetCountOfSharedState(string path) + { + MySQLPersonalizationConnectionHelper connection = new MySQLPersonalizationConnectionHelper(connectionString); + try + { + MySqlCommand cmd = new MySqlCommand(); + connection.OpenConnection(true); + return PersonalizationProviderProcedures.myaspnet_PersonalizationAdministration_GetCountOfState( + true, ApplicationName, ApplicationId, path, + null, DateTime.MinValue, connection); + } + catch (Exception ex) + { + if (writeExceptionsToEventLog) + WriteToEventLog(ex, "MySQLPersonalizationProvider - GetCountOfSharedState"); + throw; + } + finally + { + connection.CloseConnection(); + } + } + + private int GetCountUserState(string path, DateTime userInactiveSinceDate, string userName) + { + MySQLPersonalizationConnectionHelper connection = new MySQLPersonalizationConnectionHelper(connectionString); + try + { + MySqlCommand cmd = new MySqlCommand(); + connection.OpenConnection(true); + return PersonalizationProviderProcedures.myaspnet_PersonalizationAdministration_GetCountOfState( + false, ApplicationName, ApplicationId, path, + userName, userInactiveSinceDate, connection); + } + catch (Exception ex) + { + if (writeExceptionsToEventLog) + WriteToEventLog(ex, "MySQLPersonalizationProvider - GetCountUserState"); + throw; + } + finally + { + connection.CloseConnection(); + } + } + + private int ResetUserState(ResetUserStateMode mode, DateTime userInactiveSinceDate, string[] paths, string[] usernames) + { + var connection = new MySQLPersonalizationConnectionHelper(connectionString); + connection.OpenConnection(true); + + try + { + if (ResetUserStateMode.PerInactiveDate == mode) + { + return PersonalizationProviderProcedures.my_aspnet_PersonalizationAdministration_ResetUserState(ApplicationId, userInactiveSinceDate.ToUniversalTime(), null, null, connection); + } + if (ResetUserStateMode.PerPaths == mode) + { + return PersonalizationProviderProcedures.my_aspnet_PersonalizationAdministration_ResetUserState(ApplicationId, userInactiveSinceDate, null, paths, connection); + } + else + { + return PersonalizationProviderProcedures.my_aspnet_PersonalizationAdministration_ResetUserState(ApplicationId, userInactiveSinceDate, usernames, paths, connection); + } + } + catch (Exception ex) + { + if (writeExceptionsToEventLog) + WriteToEventLog(ex, "MySQLPersonalizationProvider - ResetUserState"); + throw; + } + finally + { + connection.CloseConnection(); + } + } + + private void WriteToEventLog(Exception e, string action) + { + using (EventLog log = new EventLog()) + { + log.Source = eventSource; + log.Log = eventLog; + string message = exceptionMessage + Environment.NewLine + Environment.NewLine; + message += "Action: " + action + Environment.NewLine + Environment.NewLine; + message += "Exception: " + e; + log.WriteEntry(message); + } + } + + } +} diff --git a/MySql.Web/src/PersonalizationProviderProcedures.cs b/MySql.Web/src/PersonalizationProviderProcedures.cs index ca43fd268..1e5750d18 100644 --- a/MySql.Web/src/PersonalizationProviderProcedures.cs +++ b/MySql.Web/src/PersonalizationProviderProcedures.cs @@ -1,698 +1,698 @@ -// Copyright (c) 2014, 2020, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySql.Data.MySqlClient; -using System; -using System.Globalization; - -namespace MySql.Web.Personalization -{ - internal class PersonalizationProviderProcedures - { - - /// - /// Retrieves profile data from my_aspnet_PersonalizationAllUsers or my_aspnet_PersonalizationPerUser meeting several input criteria. - /// - internal static int myaspnet_PersonalizationAdministration_FindState(bool allUsersScope, long applicationId, string applicationName, int pageIndex, int pageSize, string path, string userName, - DateTime inactiveSinceDate, MySQLPersonalizationConnectionHelper connection, ref MySqlCommand findStateCommand) - { - // create memory table to store results - - var sql = "CREATE TEMPORARY TABLE IF NOT EXISTS pageIndexResults(" + - "IndexId int AUTO_INCREMENT NOT NULL PRIMARY KEY, " + - "ItemId int not null)"; - - if (!connection.Opened) - throw new Exception("Error: Connection should be open"); - - var cmd = new MySqlCommand(sql, connection.Connection); - cmd.ExecuteNonQuery(); - - //make sure table is empty - cmd.CommandText = "TRUNCATE TABLE pageIndexResults"; - cmd.Connection = connection.Connection; - cmd.ExecuteNonQuery(); - - int pageLowerBound = pageSize * pageIndex; - int pageUpperBound = pageSize - 1 + pageLowerBound; - - - if (allUsersScope) - { - - var query = "INSERT INTO pageIndexResults (ItemId) (" + - "SELECT myaspnet_Paths.PathId " + - "FROM myaspnet_Paths, " + - "((SELECT aspnet_Paths.PathId " + - "FROM myaspnet_PersonalizationAllUsers, aspnet_Paths " + - "WHERE myaspnet_Paths.ApplicationId = @ApplicationId " + - "AND aspnet_PersonalizationAllUsers.PathId = aspnet_Paths.PathId " + - "AND (@Path IS NULL OR aspnet_Paths.LoweredPath LIKE @Path) " + - ") AS SharedDataPerPath " + - "FULL OUTER JOIN " + - "(SELECT DISTINCT aspnet_Paths.PathId " + - "FROM my_aspnet_personalizationperuser, my_aspnet_paths " + - "WHERE my_aspnet_paths.ApplicationId = @ApplicationId " + - "AND my_aspnet_personalizationperuser.PathId = aspnet_Paths.PathId " + - "AND (@Path IS NULL OR my_aspnet_paths.LoweredPath LIKE @Path) " + - ") AS UserDataPerPath " + - "ON SharedDataPerPath.PathId = UserDataPerPath.PathId " + - ") " + - "WHERE my_aspnet_Paths.PathId = SharedDataPerPath.PathId OR my_aspnet_Paths.PathId = UserDataPerPath.PathId " + - "ORDER BY my_aspnet_Paths.Path ASC)"; - - cmd.CommandText = query; - cmd.Parameters.AddWithValue("@ApplicationId", applicationId); - cmd.Parameters.AddWithValue("@Path", path); - cmd.Connection = connection.Connection; - cmd.ExecuteNonQuery(); - - cmd.CommandText = "SELECT Count(PathId) FROM pageIndexResults"; - cmd.Connection = connection.Connection; - int totalRecords = (int)cmd.ExecuteScalar(); - - query = "SELECT my_aspnet_Paths.Path, " + - "SharedDataPerPath.LastUpdatedDate, " + - "SharedDataPerPath.SharedDataLength, " + - "UserDataPerPath.UserDataLength, " + - "UserDataPerPath.UserCount " + - "FROM aspnet_Paths, " + - "((SELECT pageIndexResults.ItemId AS PathId, " + - "aspnet_PersonalizationAllUsers.LastUpdatedDate AS LastUpdatedDate, " + - "LENGTH(aspnet_PersonalizationAllUsers.PageSettings) AS SharedDataLength " + - "FROM my_aspnet_personalizationallusers, PageIndex " + - "WHERE my_aspnet_personalizationallusers.PathId = pageIndexResults.IndexId " + - "AND pageIndexResults.IndexId >= @PageLowerBound AND pageIndexResults.IndexId <= @PageUpperBound " + - ") AS SharedDataPerPath " + - "FULL OUTER JOIN " + - "(SELECT pageIndexResults.ItemId AS PathId, " + - "SUM(LENGTH(my_aspnet_personalizationperuser.PageSettings)) AS UserDataLength, " + - "COUNT(*) AS UserCount " + - "FROM my_aspnet_personalizationperuser, pageIndexResults " + - "WHERE my_aspnet_personalizationperuser.PathId = pageIndexResults.IndexId " + - "AND pageIndexResults.IndexId >= @PageLowerBound AND pageIndexResults.IndexId <= @PageUpperBound " + - "GROUP BY pageIndexResults.IndexId " + - ") AS UserDataPerPath " + - "ON SharedDataPerPath.PathId = UserDataPerPath.PathId " + - ") " + - "WHERE aspnet_Paths.PathId = SharedDataPerPath.PathId OR aspnet_Paths.PathId = UserDataPerPath.PathId " + - "ORDER BY my_aspnet_Paths.Path ASC "; - - findStateCommand.CommandText = query; - findStateCommand.Connection = connection.Connection; - findStateCommand.Parameters.AddWithValue("@PageLowerBound", pageLowerBound); - findStateCommand.Parameters.AddWithValue("@PageUpperBound", pageUpperBound); - - return totalRecords; - } - else - { - var query = "INSERT INTO pageIndexResults (ItemId) (" + - "SELECT my_aspnet_personalizationperuser.Id " + - "FROM my_aspnet_personalizationperuser, my_aspnet_users, my_aspnet_paths " + - "WHERE my_aspnet_paths.ApplicationId = @ApplicationId " + - "AND my_aspnet_personalizationperuser.UserId = my_aspnet_Users.Id " + - "AND my_aspnet_personalizationperuser.PathId = my_aspnet_Paths.PathId " + - "AND (@Path IS NULL OR my_aspnet_paths.LoweredPath LIKE @Path) " + - "AND (@UserName IS NULL OR my_aspnet_users.name LIKE @UserName) " + - "AND (@InactiveSinceDate IS NULL OR my_aspnet_users.LastActivityDate <= @InactiveSinceDate) " + - "ORDER BY my_aspnet_paths.Path ASC, my_aspnet_users.name ASC )"; - - cmd.CommandText = query; - cmd.Parameters.AddWithValue("@ApplicationId", applicationId); - cmd.Parameters.AddWithValue("@Path", path); - cmd.Parameters.AddWithValue("@UserName", userName); - cmd.Parameters.AddWithValue("@InactiveSinceDate", inactiveSinceDate); - cmd.Connection = connection.Connection; - cmd.ExecuteNonQuery(); - - cmd.CommandText = "SELECT Count(IndexId) FROM pageIndexResults"; - cmd.Connection = connection.Connection; - var totalRecords = cmd.ExecuteScalar().ToString(); - - query = "SELECT my_aspnet_Paths.Path, my_aspnet_personalizationperuser.LastUpdatedDate, LENGTH(my_aspnet_personalizationperuser.PageSettings) as Size, my_aspnet_Users.Name, my_aspnet_Users.LastActivityDate " + - "FROM my_aspnet_personalizationperuser, my_aspnet_users, my_aspnet_paths, pageIndexResults " + - "WHERE my_aspnet_personalizationperuser.Id = PageIndexResults.IndexId " + - "AND my_aspnet_personalizationperuser.UserId = my_aspnet_users.Id " + - "AND my_aspnet_personalizationperuser.PathId = my_aspnet_paths.PathId " + - "AND pageIndexResults.ItemId >= @PageLowerBound AND PageIndexResults.ItemId <= @PageUpperBound " + - "ORDER BY my_aspnet_paths.Path ASC, my_aspnet_users.name ASC "; - - findStateCommand.CommandText = query; - findStateCommand.Parameters.AddWithValue("@PageUpperBound", pageUpperBound); - findStateCommand.Parameters.AddWithValue("@PageLowerBound", pageLowerBound); - findStateCommand.Connection = connection.Connection; - - return int.Parse(totalRecords, CultureInfo.InvariantCulture); - } - } - - - internal static int myaspnet_PersonalizationAdministration_GetCountOfState(bool allUsersScope, string applicationName, long applicationId, string path, string userName, DateTime inactiveSinceDate, MySQLPersonalizationConnectionHelper connection) - { - if (applicationId <= 0) - return 0; - - if (!connection.Opened) - throw new Exception("Error: Connection should be open"); - - if (allUsersScope) - { - - MySqlCommand cmd = new MySqlCommand("Select count(*) from my_aspnet_personalizationallusers, my_aspnet_paths " + - "where my_aspnet_paths.applicationId = @ApplicationId and " + - "my_aspnet_personalizationallusers.pathid = my_aspnet_paths.pathid and " + - "(@Path is null or my_aspnet_paths.loweredpath like lower(@Path))", connection.Connection); - - cmd.Parameters.AddWithValue("@ApplicationId", applicationId); - cmd.Parameters.AddWithValue("@Path", path); - cmd.Connection = connection.Connection; - var count = cmd.ExecuteScalar().ToString(); - return int.Parse(count, CultureInfo.InvariantCulture); - } - else - { - MySqlCommand cmd = new MySqlCommand("Select count(*) from my_aspnet_personalizationperuser as peruser, my_aspnet_users as users, " + - "my_aspnet_paths as paths " + - "where paths.applicationId = @ApplicationId and " + - "peruser.userid = users.id and " + - "peruser.pathId = paths.pathId and " + - "(@Path is null or paths.loweredpath like lower(@Path) and " + - "(@UserName is null or users.name like lower(@UserName))) and " + - "(@InactiveSinceDate is null or users.lastactivitydate <= @InactiveSinceDate) ", connection.Connection); - - cmd.Parameters.AddWithValue("@ApplicationId", applicationId); - cmd.Parameters.AddWithValue("@Path", path); - cmd.Parameters.AddWithValue("@UserName", userName); - cmd.Parameters.AddWithValue("@InactiveSinceDate", inactiveSinceDate); - cmd.Connection = connection.Connection; - var count = cmd.ExecuteScalar().ToString(); - return int.Parse(count, CultureInfo.InvariantCulture); - } - } - - - internal static Byte[] my_aspnet_PersonalizationPerUser_GetPageSettings(long applicationId, string path, string userName, DateTime currentTimeUtc, MySQLPersonalizationConnectionHelper connection) - { - if (applicationId <= 0) - return null; - - if (!connection.Opened) - throw new Exception("Error: Connection should be open"); - - //get pathid - var cmd = new MySqlCommand("select pathId from my_aspnet_paths where applicationid = @ApplicationId and loweredpath = lower(@Path)", connection.Connection); - cmd.Connection = connection.Connection; - - cmd.Parameters.AddWithValue("@ApplicationId", applicationId); - cmd.Parameters.AddWithValue("@Path", path); - - var pathId = (cmd.ExecuteScalar() ?? "").ToString(); - - if (string.IsNullOrEmpty(pathId)) - return null; - - cmd = new MySqlCommand("select Id from my_aspnet_users where applicationid = @ApplicationId and name = @UserName", connection.Connection); - cmd.Connection = connection.Connection; - cmd.Parameters.AddWithValue("@ApplicationId", applicationId); - cmd.Parameters.AddWithValue("@UserName", userName); - - - var userId = (cmd.ExecuteScalar() ?? "").ToString(); - userId = string.IsNullOrEmpty(userId) ? "0" : userId; - - if (int.Parse(userId, CultureInfo.InvariantCulture) == 0) - return null; - - UpdateUserLastActiveDate(connection.Connection, int.Parse(userId, CultureInfo.InvariantCulture), currentTimeUtc); - - cmd = new MySqlCommand("select pagesettings from my_aspnet_personalizationperuser as peruser where peruser.pathid = @PathId and peruser.userid = @UserId"); - cmd.Connection = connection.Connection; - cmd.Parameters.AddWithValue("@PathId", pathId); - cmd.Parameters.AddWithValue("@UserId", userId); - - var reader = cmd.ExecuteReader(); - - byte[] settings = null; - while (reader.Read()) - { - int size = (int)reader.GetBytes(0, 0, null, 0, 0); - settings = new byte[size]; - reader.GetBytes(0, 0, settings, 0, size); - } - reader.Close(); - return settings; - } - - - internal static byte[] my_aspnet_PersonalizationAllUsers_GetPageSettings(long applicationId, string path, MySQLPersonalizationConnectionHelper connection) - { - if (applicationId <= 0) - return null; - - if (!connection.Opened) - throw new Exception("Error: Connection should be open"); - - var cmd = new MySqlCommand("Select pathid from my_aspnet_paths as paths where paths.applicationid = @ApplicationId and paths.loweredPath = lower(@Path)", connection.Connection); - cmd.Parameters.AddWithValue("@ApplicationId", applicationId); - cmd.Parameters.AddWithValue("@Path", path); - var pathId = (string)cmd.ExecuteScalar(); - - if (!string.IsNullOrEmpty(pathId)) - { - cmd.CommandText = "Select PageSettings from my_aspnet_personalizationallusers where pathId = @PathId"; - cmd.Parameters.AddWithValue("@PathId", pathId); - cmd.Connection = connection.Connection; - var reader = cmd.ExecuteReader(); - - byte[] settings = null; - while (reader.Read()) - { - int size = (int)reader.GetBytes(0, 0, null, 0, 0); - settings = new byte[size]; - reader.GetBytes(0, 0, settings, 0, size); - } - reader.Close(); - return settings; - } - - return null; - } - - - internal static void my_aspnet_PersonalizationPerUser_ResetPageSettings(long applicationId, string userName, string path, DateTime currentTimeUtc, MySQLPersonalizationConnectionHelper connection) - { - - if (applicationId <= 0) - return; - - if (!connection.Opened) - throw new Exception("Error: Connection should be open"); - - var cmd = new MySqlCommand("Select pathid from my_aspnet_paths as paths where paths.applicationid = @ApplicationId and paths.loweredPath = lower(@Path)", connection.Connection); - cmd.Parameters.AddWithValue("@ApplicationId", applicationId); - cmd.Parameters.AddWithValue("@Path", path); - var pathId = (string)cmd.ExecuteScalar(); - - if (!string.IsNullOrEmpty(pathId)) - { - cmd = new MySqlCommand("select Id from my_aspnet_users where applicationid = @ApplicationId and name = @UserName", connection.Connection); - cmd.Connection = connection.Connection; - cmd.Parameters.AddWithValue("@ApplicationId", applicationId); - cmd.Parameters.AddWithValue("@UserName", userName); - - var userId = (int)cmd.ExecuteScalar(); - if (userId != 0) - { - var rows = UpdateUserLastActiveDate(connection.Connection, userId, currentTimeUtc); - if (rows != 0) - { - cmd = new MySqlCommand("delete from my_aspnet_personalizationperuser WHERE pathId = @PathId AND userId = @UserId"); - cmd.Connection = connection.Connection; - cmd.Parameters.AddWithValue("@PathId", pathId); - cmd.Parameters.AddWithValue("@UserId", userId); - cmd.ExecuteNonQuery(); - } - } - } - } - - internal static void my_aspnet_PersonalizationAllUsers_ResetPageSettings(long applicationId, string path, MySQLPersonalizationConnectionHelper connection) - { - - if (applicationId <= 0) - return; - - if (!connection.Opened) - throw new Exception("Error: Connection should be open"); - - var cmd = new MySqlCommand("Select pathid from my_aspnet_paths as paths where paths.applicationid = @ApplicationId and paths.loweredPath = lower(@Path)", connection.Connection); - cmd.Parameters.AddWithValue("@ApplicationId", applicationId); - cmd.Parameters.AddWithValue("@Path", path); - var pathId = (cmd.ExecuteScalar() ?? "").ToString(); - - if (!string.IsNullOrEmpty(pathId)) - { - cmd = new MySqlCommand("delete my_aspnet_personalizationallusers.* from my_aspnet_personalizationallusers WHERE pathId = @PathId"); - cmd.Connection = connection.Connection; - cmd.Parameters.AddWithValue("@PathId", pathId); - cmd.ExecuteNonQuery(); - } - - } - - - private static int UpdateUserLastActiveDate(MySqlConnection cnn, int userId, DateTime currentTimeUtc) - { - MySqlTransaction trans; - trans = cnn.BeginTransaction(); - try - { - var cmd = new MySqlCommand("update my_aspnet_users set lastactivitydate = @CurrentTimeUtc where id = @UserId"); - cmd.Connection = cnn; - cmd.Transaction = trans; - cmd.Parameters.AddWithValue("@CurrentTimeUtc", currentTimeUtc); - cmd.Parameters.AddWithValue("@UserId", userId); - var rows = cmd.ExecuteNonQuery(); - trans.Commit(); - return rows; - } - catch - { - trans.Rollback(); - throw; - } - } - - - internal static int my_aspnet_PersonalizationAdministration_ResetUserState(long applicationId, DateTime inactiveSinceDate, string[] usernames, string[] paths, MySQLPersonalizationConnectionHelper connection) - { - if (applicationId <= 0) - return 0; - - if (!connection.Opened) - throw new Exception("Error: Connection should be open"); - - var rows = 0; - var cmd = new MySqlCommand(); - if (usernames == null) usernames = new string[1] { "" }; - if (paths == null) paths = new string[1] { "" }; - - foreach (var username in usernames) - { - foreach (var path in paths) - { - var query = "DELETE peruser.* FROM (my_aspnet_personalizationperuser as peruser " + - "INNER JOIN my_aspnet_users as users ON " + - "peruser.userid = users.id) " + - "INNER JOIN my_aspnet_paths as paths ON " + - "paths.applicationId = @ApplicationId AND " + - "paths.pathid = peruser.pathid AND " + - "(@InactiveSinceDate is null OR users.lastactivitydate <= @InactiveSinceDate) "; - query = string.IsNullOrEmpty(username) ? query : query += " AND (@UserName is null OR users.name = @UserName) "; - query = string.IsNullOrEmpty(path) ? query : query += " AND (@Path is null OR paths.loweredpath = LOWER(@Path))"; - cmd.CommandText = query; - cmd.Parameters.AddWithValue("@ApplicationId", applicationId); - cmd.Parameters.AddWithValue("@InactiveSinceDate", inactiveSinceDate); - cmd.Parameters.AddWithValue("@Path", path); - cmd.Parameters.AddWithValue("@UserName", username); - cmd.Connection = connection.Connection; - rows += cmd.ExecuteNonQuery(); - } - } - - return rows; - } - - - internal static int my_aspnet_PersonalizationAdministration_DeleteAllState(long applicationId, bool allUsersScope, MySQLPersonalizationConnectionHelper connection) - { - if (applicationId <= 0) - return 0; - - if (!connection.Opened) - throw new Exception("Error: Connection should be open"); - - var cmd = new MySqlCommand(); - cmd.Connection = connection.Connection; - - if (allUsersScope) - { - cmd.CommandText = "DELETE FROM my_aspnet_personalizationallusers " + - "WHERE PathId IN (SELECT Paths.PathId FROM my_aspnet_paths as paths " + - "WHERE paths.ApplicationId = @ApplicationId)"; - cmd.Parameters.AddWithValue("@ApplicationId", applicationId); - } - else - { - cmd.CommandText = "DELETE FROM my_aspnet_personalizationperuser " + - "WHERE PathId IN (SELECT Paths.PathId FROM my_aspnet_paths as paths " + - "WHERE paths.ApplicationId = @ApplicationId)"; - cmd.Parameters.AddWithValue("@ApplicationId", applicationId); - } - - var rows = cmd.ExecuteNonQuery(); - return rows; - } - - internal static int my_aspnet_PersonalizationAdministration_ResetSharedState(long applicationId, string[] paths, MySQLPersonalizationConnectionHelper connection) - { - if (applicationId <= 0) - return 0; - - if (!connection.Opened) - throw new Exception("Error: Connection should be open"); - - if (paths == null) - return 0; - - var cmd = new MySqlCommand(); - cmd.Connection = connection.Connection; - - var rows = 0; - - foreach (var path in paths) - { - cmd.CommandText = "DELETE my_aspnet_personalizationallusers.* FROM my_aspnet_personalizationallusers " + - "INNER JOIN my_aspnet_paths as paths ON " + - "((paths.ApplicationId = @ApplicationId AND " + - "my_aspnet_personalizationallusers.PathId = paths.PathId) AND " + - "paths.loweredpath = LOWER(@Path))"; - - cmd.Parameters.AddWithValue("@ApplicationId", applicationId); - cmd.Parameters.AddWithValue("@Path", path); - rows += cmd.ExecuteNonQuery(); - } - - return rows; - } - - - internal static int my_aspnet_PersonalizationAdministration_DeleteAllState(bool allUsersScope, long applicationId, MySQLPersonalizationConnectionHelper connection) - { - if (applicationId <= 0) - return 0; - - if (!connection.Opened) - throw new Exception("Error: Connection should be open"); - - var cmd = new MySqlCommand(); - cmd.Connection = connection.Connection; - - if (allUsersScope) - { - - cmd.CommandText = "DELETE FROM my_aspnet_personalizationallusers " + - "WHERE PathId IN " + - "(SELECT paths.PathId FROM my_aspnet_paths as paths " + - "WHERE paths.ApplicationId = @ApplicationId)"; - } - else - { - cmd.CommandText = "DELETE FROM my_aspnet_personalizationperuser " + - "WHERE PathId IN " + - "(SELECT Paths.PathId FROM my_aspnet_paths Paths " + - "WHERE Paths.ApplicationId = @ApplicationId)"; - } - cmd.Parameters.AddWithValue("@ApplicationId", applicationId); - var rows = cmd.ExecuteNonQuery(); - return rows; - } - - /// - /// Saves per-user state for the specified page and the specified user in the my_aspnet_PersonalizationPerUser table. - /// - /// - internal static int my_aspnet_PersonalizationPerUser_SetPageSettings(long applicationId, string userName, string path, byte[] settings, DateTime currentTimeUtc, MySQLPersonalizationConnectionHelper connection) - { - if (applicationId <= 0) - return 0; - - if (!connection.Opened) - throw new Exception("Error: Connection should be open"); - - var cmd = new MySqlCommand(); - cmd.Connection = connection.Connection; - - cmd.CommandText = "SELECT PathId FROM my_aspnet_paths WHERE ApplicationId = @ApplicationId AND LoweredPath = LOWER(@Path)"; - cmd.Parameters.AddWithValue("@ApplicationId", applicationId); - cmd.Parameters.AddWithValue("@Path", path); - var pathId = (string)cmd.ExecuteScalar(); - - cmd.Parameters.Clear(); - - if (pathId == null) - { - // create path - MySqlTransaction trans; - trans = connection.Connection.BeginTransaction(); - - try - { - cmd.Transaction = trans; - cmd.CommandText = "INSERT INTO my_aspnet_paths (applicationId, pathId, path, loweredpath) values (@ApplicationId, @PathId, @Path, LOWER(@Path))"; - cmd.Parameters.AddWithValue("@ApplicationId", applicationId); - cmd.Parameters.AddWithValue("@PathId", pathId = Guid.NewGuid().ToString()); - cmd.Parameters.AddWithValue("@Path", path); - cmd.ExecuteNonQuery(); - trans.Commit(); - } - catch - { - trans.Rollback(); - throw; - } - } - - cmd.Parameters.Clear(); - cmd.CommandText = "SELECT id FROM my_aspnet_users WHERE ApplicationId = @ApplicationId AND name = LOWER(@UserName)"; - cmd.Parameters.AddWithValue("@ApplicationId", applicationId); - cmd.Parameters.AddWithValue("@UserName", userName); - var userId = (cmd.ExecuteScalar() ?? "").ToString(); - - userId = string.IsNullOrEmpty(userId) ? "0" : userId; - - // create user - if (int.Parse(userId, CultureInfo.InvariantCulture) == 0) - { - // create path - MySqlTransaction trans; - trans = connection.Connection.BeginTransaction(); - - try - { - cmd.Parameters.Clear(); - cmd.Transaction = trans; - cmd.CommandText = "INSERT INTO my_aspnet_users (applicationId, name, isAnonymous, lastActivityDate) values (@ApplicationId, @UserName, false, @CurrentTimeUtc)"; - cmd.Parameters.AddWithValue("@ApplicationId", applicationId); - cmd.Parameters.AddWithValue("@UserName", userName); - cmd.Parameters.AddWithValue("@CurrentTimeUtc", DateTime.UtcNow); - cmd.ExecuteNonQuery(); - trans.Commit(); - } - catch - { - trans.Rollback(); - throw; - } - - cmd.Parameters.Clear(); - cmd.CommandText = "SELECT Id from my_aspnet_users where applicationId = @ApplicationId and name = @UserName)"; - cmd.Parameters.AddWithValue("@ApplicationId", applicationId); - cmd.Parameters.AddWithValue("@UserName", userName); - userId = (string)cmd.ExecuteScalar(); - - } - var rows = UpdateUserLastActiveDate(connection.Connection, int.Parse(userId, CultureInfo.InvariantCulture), DateTime.UtcNow); - if (rows == 0) - throw new Exception("User not found"); - - cmd.Parameters.Clear(); - cmd.CommandText = "Select COUNT(*) from my_aspnet_personalizationperuser where userid = @UserId and pathId = @PathId"; - cmd.Parameters.AddWithValue("@UserId", userId); - cmd.Parameters.AddWithValue("@PathId", pathId); - if ((long)cmd.ExecuteScalar() > 0) - { - cmd.Parameters.Clear(); - cmd.CommandText = "UPDATE my_aspnet_personalizationperuser SET PageSettings = @PageSettings, LastUpdatedDate = @CurrentTimeUtc " + - "where userid = @UserId and pathId = @PathId"; - cmd.Parameters.AddWithValue("@UserId", userId); - cmd.Parameters.AddWithValue("@PathId", pathId); - cmd.Parameters.AddWithValue("@PageSettings", settings); - cmd.Parameters.AddWithValue("@CurrentTimeUtc", DateTime.UtcNow); - cmd.ExecuteNonQuery(); - } - else - { - cmd.Parameters.Clear(); - cmd.CommandText = "INSERT INTO my_aspnet_personalizationperuser(applicationId, pathId, userId, pageSettings, lastUpdatedDate) VALUES(@applicationId, @PathId, @userId, @PageSettings, @LastUpdatedDate)"; - cmd.Parameters.AddWithValue("@applicationId", applicationId); - cmd.Parameters.AddWithValue("@UserId", userId); - cmd.Parameters.AddWithValue("@PathId", pathId); - cmd.Parameters.AddWithValue("@PageSettings", settings); - cmd.Parameters.AddWithValue("@LastUpdatedDate", DateTime.UtcNow); - rows = cmd.ExecuteNonQuery(); - } - return rows; - } - - /// - /// Saves shared state for the specified page in the aspnet_PersonalizationAllUsers table - /// - /// - internal static int my_aspnet_PersonalizationAllUsers_SetPageSettings(long applicationId, string path, byte[] settings, DateTime currentTimeUtc, MySQLPersonalizationConnectionHelper connection) - { - if (applicationId <= 0) - return 0; - - if (!connection.Opened) - throw new Exception("Error: Connection should be open"); - - var cmd = new MySqlCommand(); - cmd.Connection = connection.Connection; - - cmd.CommandText = "SELECT PathId FROM my_aspnet_paths WHERE ApplicationId = @ApplicationId AND LoweredPath = LOWER(@Path)"; - cmd.Parameters.AddWithValue("@ApplicationId", applicationId); - cmd.Parameters.AddWithValue("@Path", path); - var pathId = (string)cmd.ExecuteScalar(); - cmd.Parameters.Clear(); - - if (pathId == null) - { - // create path - MySqlTransaction trans; - trans = connection.Connection.BeginTransaction(); - - try - { - cmd.Transaction = trans; - cmd.CommandText = "INSERT INTO my_aspnet_paths (applicationId, pathId, path, loweredpath) values (@ApplicationId, @PathId, @Path, LOWER(@Path))"; - cmd.Parameters.AddWithValue("@ApplicationId", applicationId); - cmd.Parameters.AddWithValue("@PathId", pathId = Guid.NewGuid().ToString()); - cmd.Parameters.AddWithValue("@Path", path); - cmd.ExecuteNonQuery(); - trans.Commit(); - } - catch - { - trans.Rollback(); - throw; - } - } - - cmd.CommandText = "INSERT INTO my_aspnet_personalizationallusers(PathId, PageSettings, LastUpdatedDate) VALUES (@PathId, @PageSettings, @CurrentTimeUtc)"; - cmd.CommandText += " ON DUPLICATE KEY UPDATE PageSettings=Values(PageSettings), LastUpdatedDate=Values(LastUpdatedDate)"; - cmd.Parameters.Clear(); - cmd.Parameters.AddWithValue("@PageSettings", settings); - cmd.Parameters.AddWithValue("@PathId", pathId); - cmd.Parameters.AddWithValue("@CurrentTimeUtc", currentTimeUtc); - var rows = cmd.ExecuteNonQuery(); - return rows; - } - } -} +// Copyright © 2014, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySql.Data.MySqlClient; +using System; +using System.Globalization; + +namespace MySql.Web.Personalization +{ + internal class PersonalizationProviderProcedures + { + + /// + /// Retrieves profile data from my_aspnet_PersonalizationAllUsers or my_aspnet_PersonalizationPerUser meeting several input criteria. + /// + internal static int myaspnet_PersonalizationAdministration_FindState(bool allUsersScope, long applicationId, string applicationName, int pageIndex, int pageSize, string path, string userName, + DateTime inactiveSinceDate, MySQLPersonalizationConnectionHelper connection, ref MySqlCommand findStateCommand) + { + // create memory table to store results + + var sql = "CREATE TEMPORARY TABLE IF NOT EXISTS pageIndexResults(" + + "IndexId int AUTO_INCREMENT NOT NULL PRIMARY KEY, " + + "ItemId int not null)"; + + if (!connection.Opened) + throw new Exception("Error: Connection should be open"); + + var cmd = new MySqlCommand(sql, connection.Connection); + cmd.ExecuteNonQuery(); + + //make sure table is empty + cmd.CommandText = "TRUNCATE TABLE pageIndexResults"; + cmd.Connection = connection.Connection; + cmd.ExecuteNonQuery(); + + int pageLowerBound = pageSize * pageIndex; + int pageUpperBound = pageSize - 1 + pageLowerBound; + + + if (allUsersScope) + { + + var query = "INSERT INTO pageIndexResults (ItemId) (" + + "SELECT myaspnet_Paths.PathId " + + "FROM myaspnet_Paths, " + + "((SELECT aspnet_Paths.PathId " + + "FROM myaspnet_PersonalizationAllUsers, aspnet_Paths " + + "WHERE myaspnet_Paths.ApplicationId = @ApplicationId " + + "AND aspnet_PersonalizationAllUsers.PathId = aspnet_Paths.PathId " + + "AND (@Path IS NULL OR aspnet_Paths.LoweredPath LIKE @Path) " + + ") AS SharedDataPerPath " + + "FULL OUTER JOIN " + + "(SELECT DISTINCT aspnet_Paths.PathId " + + "FROM my_aspnet_personalizationperuser, my_aspnet_paths " + + "WHERE my_aspnet_paths.ApplicationId = @ApplicationId " + + "AND my_aspnet_personalizationperuser.PathId = aspnet_Paths.PathId " + + "AND (@Path IS NULL OR my_aspnet_paths.LoweredPath LIKE @Path) " + + ") AS UserDataPerPath " + + "ON SharedDataPerPath.PathId = UserDataPerPath.PathId " + + ") " + + "WHERE my_aspnet_Paths.PathId = SharedDataPerPath.PathId OR my_aspnet_Paths.PathId = UserDataPerPath.PathId " + + "ORDER BY my_aspnet_Paths.Path ASC)"; + + cmd.CommandText = query; + cmd.Parameters.AddWithValue("@ApplicationId", applicationId); + cmd.Parameters.AddWithValue("@Path", path); + cmd.Connection = connection.Connection; + cmd.ExecuteNonQuery(); + + cmd.CommandText = "SELECT Count(PathId) FROM pageIndexResults"; + cmd.Connection = connection.Connection; + int totalRecords = (int)cmd.ExecuteScalar(); + + query = "SELECT my_aspnet_Paths.Path, " + + "SharedDataPerPath.LastUpdatedDate, " + + "SharedDataPerPath.SharedDataLength, " + + "UserDataPerPath.UserDataLength, " + + "UserDataPerPath.UserCount " + + "FROM aspnet_Paths, " + + "((SELECT pageIndexResults.ItemId AS PathId, " + + "aspnet_PersonalizationAllUsers.LastUpdatedDate AS LastUpdatedDate, " + + "LENGTH(aspnet_PersonalizationAllUsers.PageSettings) AS SharedDataLength " + + "FROM my_aspnet_personalizationallusers, PageIndex " + + "WHERE my_aspnet_personalizationallusers.PathId = pageIndexResults.IndexId " + + "AND pageIndexResults.IndexId >= @PageLowerBound AND pageIndexResults.IndexId <= @PageUpperBound " + + ") AS SharedDataPerPath " + + "FULL OUTER JOIN " + + "(SELECT pageIndexResults.ItemId AS PathId, " + + "SUM(LENGTH(my_aspnet_personalizationperuser.PageSettings)) AS UserDataLength, " + + "COUNT(*) AS UserCount " + + "FROM my_aspnet_personalizationperuser, pageIndexResults " + + "WHERE my_aspnet_personalizationperuser.PathId = pageIndexResults.IndexId " + + "AND pageIndexResults.IndexId >= @PageLowerBound AND pageIndexResults.IndexId <= @PageUpperBound " + + "GROUP BY pageIndexResults.IndexId " + + ") AS UserDataPerPath " + + "ON SharedDataPerPath.PathId = UserDataPerPath.PathId " + + ") " + + "WHERE aspnet_Paths.PathId = SharedDataPerPath.PathId OR aspnet_Paths.PathId = UserDataPerPath.PathId " + + "ORDER BY my_aspnet_Paths.Path ASC "; + + findStateCommand.CommandText = query; + findStateCommand.Connection = connection.Connection; + findStateCommand.Parameters.AddWithValue("@PageLowerBound", pageLowerBound); + findStateCommand.Parameters.AddWithValue("@PageUpperBound", pageUpperBound); + + return totalRecords; + } + else + { + var query = "INSERT INTO pageIndexResults (ItemId) (" + + "SELECT my_aspnet_personalizationperuser.Id " + + "FROM my_aspnet_personalizationperuser, my_aspnet_users, my_aspnet_paths " + + "WHERE my_aspnet_paths.ApplicationId = @ApplicationId " + + "AND my_aspnet_personalizationperuser.UserId = my_aspnet_Users.Id " + + "AND my_aspnet_personalizationperuser.PathId = my_aspnet_Paths.PathId " + + "AND (@Path IS NULL OR my_aspnet_paths.LoweredPath LIKE @Path) " + + "AND (@UserName IS NULL OR my_aspnet_users.name LIKE @UserName) " + + "AND (@InactiveSinceDate IS NULL OR my_aspnet_users.LastActivityDate <= @InactiveSinceDate) " + + "ORDER BY my_aspnet_paths.Path ASC, my_aspnet_users.name ASC )"; + + cmd.CommandText = query; + cmd.Parameters.AddWithValue("@ApplicationId", applicationId); + cmd.Parameters.AddWithValue("@Path", path); + cmd.Parameters.AddWithValue("@UserName", userName); + cmd.Parameters.AddWithValue("@InactiveSinceDate", inactiveSinceDate); + cmd.Connection = connection.Connection; + cmd.ExecuteNonQuery(); + + cmd.CommandText = "SELECT Count(IndexId) FROM pageIndexResults"; + cmd.Connection = connection.Connection; + var totalRecords = cmd.ExecuteScalar().ToString(); + + query = "SELECT my_aspnet_Paths.Path, my_aspnet_personalizationperuser.LastUpdatedDate, LENGTH(my_aspnet_personalizationperuser.PageSettings) as Size, my_aspnet_Users.Name, my_aspnet_Users.LastActivityDate " + + "FROM my_aspnet_personalizationperuser, my_aspnet_users, my_aspnet_paths, pageIndexResults " + + "WHERE my_aspnet_personalizationperuser.Id = PageIndexResults.IndexId " + + "AND my_aspnet_personalizationperuser.UserId = my_aspnet_users.Id " + + "AND my_aspnet_personalizationperuser.PathId = my_aspnet_paths.PathId " + + "AND pageIndexResults.ItemId >= @PageLowerBound AND PageIndexResults.ItemId <= @PageUpperBound " + + "ORDER BY my_aspnet_paths.Path ASC, my_aspnet_users.name ASC "; + + findStateCommand.CommandText = query; + findStateCommand.Parameters.AddWithValue("@PageUpperBound", pageUpperBound); + findStateCommand.Parameters.AddWithValue("@PageLowerBound", pageLowerBound); + findStateCommand.Connection = connection.Connection; + + return int.Parse(totalRecords, CultureInfo.InvariantCulture); + } + } + + + internal static int myaspnet_PersonalizationAdministration_GetCountOfState(bool allUsersScope, string applicationName, long applicationId, string path, string userName, DateTime inactiveSinceDate, MySQLPersonalizationConnectionHelper connection) + { + if (applicationId <= 0) + return 0; + + if (!connection.Opened) + throw new Exception("Error: Connection should be open"); + + if (allUsersScope) + { + + MySqlCommand cmd = new MySqlCommand("Select count(*) from my_aspnet_personalizationallusers, my_aspnet_paths " + + "where my_aspnet_paths.applicationId = @ApplicationId and " + + "my_aspnet_personalizationallusers.pathid = my_aspnet_paths.pathid and " + + "(@Path is null or my_aspnet_paths.loweredpath like lower(@Path))", connection.Connection); + + cmd.Parameters.AddWithValue("@ApplicationId", applicationId); + cmd.Parameters.AddWithValue("@Path", path); + cmd.Connection = connection.Connection; + var count = cmd.ExecuteScalar().ToString(); + return int.Parse(count, CultureInfo.InvariantCulture); + } + else + { + MySqlCommand cmd = new MySqlCommand("Select count(*) from my_aspnet_personalizationperuser as peruser, my_aspnet_users as users, " + + "my_aspnet_paths as paths " + + "where paths.applicationId = @ApplicationId and " + + "peruser.userid = users.id and " + + "peruser.pathId = paths.pathId and " + + "(@Path is null or paths.loweredpath like lower(@Path) and " + + "(@UserName is null or users.name like lower(@UserName))) and " + + "(@InactiveSinceDate is null or users.lastactivitydate <= @InactiveSinceDate) ", connection.Connection); + + cmd.Parameters.AddWithValue("@ApplicationId", applicationId); + cmd.Parameters.AddWithValue("@Path", path); + cmd.Parameters.AddWithValue("@UserName", userName); + cmd.Parameters.AddWithValue("@InactiveSinceDate", inactiveSinceDate); + cmd.Connection = connection.Connection; + var count = cmd.ExecuteScalar().ToString(); + return int.Parse(count, CultureInfo.InvariantCulture); + } + } + + + internal static Byte[] my_aspnet_PersonalizationPerUser_GetPageSettings(long applicationId, string path, string userName, DateTime currentTimeUtc, MySQLPersonalizationConnectionHelper connection) + { + if (applicationId <= 0) + return null; + + if (!connection.Opened) + throw new Exception("Error: Connection should be open"); + + //get pathid + var cmd = new MySqlCommand("select pathId from my_aspnet_paths where applicationid = @ApplicationId and loweredpath = lower(@Path)", connection.Connection); + cmd.Connection = connection.Connection; + + cmd.Parameters.AddWithValue("@ApplicationId", applicationId); + cmd.Parameters.AddWithValue("@Path", path); + + var pathId = (cmd.ExecuteScalar() ?? "").ToString(); + + if (string.IsNullOrEmpty(pathId)) + return null; + + cmd = new MySqlCommand("select Id from my_aspnet_users where applicationid = @ApplicationId and name = @UserName", connection.Connection); + cmd.Connection = connection.Connection; + cmd.Parameters.AddWithValue("@ApplicationId", applicationId); + cmd.Parameters.AddWithValue("@UserName", userName); + + + var userId = (cmd.ExecuteScalar() ?? "").ToString(); + userId = string.IsNullOrEmpty(userId) ? "0" : userId; + + if (int.Parse(userId, CultureInfo.InvariantCulture) == 0) + return null; + + UpdateUserLastActiveDate(connection.Connection, int.Parse(userId, CultureInfo.InvariantCulture), currentTimeUtc); + + cmd = new MySqlCommand("select pagesettings from my_aspnet_personalizationperuser as peruser where peruser.pathid = @PathId and peruser.userid = @UserId"); + cmd.Connection = connection.Connection; + cmd.Parameters.AddWithValue("@PathId", pathId); + cmd.Parameters.AddWithValue("@UserId", userId); + + var reader = cmd.ExecuteReader(); + + byte[] settings = null; + while (reader.Read()) + { + int size = (int)reader.GetBytes(0, 0, null, 0, 0); + settings = new byte[size]; + reader.GetBytes(0, 0, settings, 0, size); + } + reader.Close(); + return settings; + } + + + internal static byte[] my_aspnet_PersonalizationAllUsers_GetPageSettings(long applicationId, string path, MySQLPersonalizationConnectionHelper connection) + { + if (applicationId <= 0) + return null; + + if (!connection.Opened) + throw new Exception("Error: Connection should be open"); + + var cmd = new MySqlCommand("Select pathid from my_aspnet_paths as paths where paths.applicationid = @ApplicationId and paths.loweredPath = lower(@Path)", connection.Connection); + cmd.Parameters.AddWithValue("@ApplicationId", applicationId); + cmd.Parameters.AddWithValue("@Path", path); + var pathId = (string)cmd.ExecuteScalar(); + + if (!string.IsNullOrEmpty(pathId)) + { + cmd.CommandText = "Select PageSettings from my_aspnet_personalizationallusers where pathId = @PathId"; + cmd.Parameters.AddWithValue("@PathId", pathId); + cmd.Connection = connection.Connection; + var reader = cmd.ExecuteReader(); + + byte[] settings = null; + while (reader.Read()) + { + int size = (int)reader.GetBytes(0, 0, null, 0, 0); + settings = new byte[size]; + reader.GetBytes(0, 0, settings, 0, size); + } + reader.Close(); + return settings; + } + + return null; + } + + + internal static void my_aspnet_PersonalizationPerUser_ResetPageSettings(long applicationId, string userName, string path, DateTime currentTimeUtc, MySQLPersonalizationConnectionHelper connection) + { + + if (applicationId <= 0) + return; + + if (!connection.Opened) + throw new Exception("Error: Connection should be open"); + + var cmd = new MySqlCommand("Select pathid from my_aspnet_paths as paths where paths.applicationid = @ApplicationId and paths.loweredPath = lower(@Path)", connection.Connection); + cmd.Parameters.AddWithValue("@ApplicationId", applicationId); + cmd.Parameters.AddWithValue("@Path", path); + var pathId = (string)cmd.ExecuteScalar(); + + if (!string.IsNullOrEmpty(pathId)) + { + cmd = new MySqlCommand("select Id from my_aspnet_users where applicationid = @ApplicationId and name = @UserName", connection.Connection); + cmd.Connection = connection.Connection; + cmd.Parameters.AddWithValue("@ApplicationId", applicationId); + cmd.Parameters.AddWithValue("@UserName", userName); + + var userId = (int)cmd.ExecuteScalar(); + if (userId != 0) + { + var rows = UpdateUserLastActiveDate(connection.Connection, userId, currentTimeUtc); + if (rows != 0) + { + cmd = new MySqlCommand("delete from my_aspnet_personalizationperuser WHERE pathId = @PathId AND userId = @UserId"); + cmd.Connection = connection.Connection; + cmd.Parameters.AddWithValue("@PathId", pathId); + cmd.Parameters.AddWithValue("@UserId", userId); + cmd.ExecuteNonQuery(); + } + } + } + } + + internal static void my_aspnet_PersonalizationAllUsers_ResetPageSettings(long applicationId, string path, MySQLPersonalizationConnectionHelper connection) + { + + if (applicationId <= 0) + return; + + if (!connection.Opened) + throw new Exception("Error: Connection should be open"); + + var cmd = new MySqlCommand("Select pathid from my_aspnet_paths as paths where paths.applicationid = @ApplicationId and paths.loweredPath = lower(@Path)", connection.Connection); + cmd.Parameters.AddWithValue("@ApplicationId", applicationId); + cmd.Parameters.AddWithValue("@Path", path); + var pathId = (cmd.ExecuteScalar() ?? "").ToString(); + + if (!string.IsNullOrEmpty(pathId)) + { + cmd = new MySqlCommand("delete my_aspnet_personalizationallusers.* from my_aspnet_personalizationallusers WHERE pathId = @PathId"); + cmd.Connection = connection.Connection; + cmd.Parameters.AddWithValue("@PathId", pathId); + cmd.ExecuteNonQuery(); + } + + } + + + private static int UpdateUserLastActiveDate(MySqlConnection cnn, int userId, DateTime currentTimeUtc) + { + MySqlTransaction trans; + trans = cnn.BeginTransaction(); + try + { + var cmd = new MySqlCommand("update my_aspnet_users set lastactivitydate = @CurrentTimeUtc where id = @UserId"); + cmd.Connection = cnn; + cmd.Transaction = trans; + cmd.Parameters.AddWithValue("@CurrentTimeUtc", currentTimeUtc); + cmd.Parameters.AddWithValue("@UserId", userId); + var rows = cmd.ExecuteNonQuery(); + trans.Commit(); + return rows; + } + catch + { + trans.Rollback(); + throw; + } + } + + + internal static int my_aspnet_PersonalizationAdministration_ResetUserState(long applicationId, DateTime inactiveSinceDate, string[] usernames, string[] paths, MySQLPersonalizationConnectionHelper connection) + { + if (applicationId <= 0) + return 0; + + if (!connection.Opened) + throw new Exception("Error: Connection should be open"); + + var rows = 0; + var cmd = new MySqlCommand(); + if (usernames == null) usernames = new string[1] { "" }; + if (paths == null) paths = new string[1] { "" }; + + foreach (var username in usernames) + { + foreach (var path in paths) + { + var query = "DELETE peruser.* FROM (my_aspnet_personalizationperuser as peruser " + + "INNER JOIN my_aspnet_users as users ON " + + "peruser.userid = users.id) " + + "INNER JOIN my_aspnet_paths as paths ON " + + "paths.applicationId = @ApplicationId AND " + + "paths.pathid = peruser.pathid AND " + + "(@InactiveSinceDate is null OR users.lastactivitydate <= @InactiveSinceDate) "; + query = string.IsNullOrEmpty(username) ? query : query += " AND (@UserName is null OR users.name = @UserName) "; + query = string.IsNullOrEmpty(path) ? query : query += " AND (@Path is null OR paths.loweredpath = LOWER(@Path))"; + cmd.CommandText = query; + cmd.Parameters.AddWithValue("@ApplicationId", applicationId); + cmd.Parameters.AddWithValue("@InactiveSinceDate", inactiveSinceDate); + cmd.Parameters.AddWithValue("@Path", path); + cmd.Parameters.AddWithValue("@UserName", username); + cmd.Connection = connection.Connection; + rows += cmd.ExecuteNonQuery(); + } + } + + return rows; + } + + + internal static int my_aspnet_PersonalizationAdministration_DeleteAllState(long applicationId, bool allUsersScope, MySQLPersonalizationConnectionHelper connection) + { + if (applicationId <= 0) + return 0; + + if (!connection.Opened) + throw new Exception("Error: Connection should be open"); + + var cmd = new MySqlCommand(); + cmd.Connection = connection.Connection; + + if (allUsersScope) + { + cmd.CommandText = "DELETE FROM my_aspnet_personalizationallusers " + + "WHERE PathId IN (SELECT Paths.PathId FROM my_aspnet_paths as paths " + + "WHERE paths.ApplicationId = @ApplicationId)"; + cmd.Parameters.AddWithValue("@ApplicationId", applicationId); + } + else + { + cmd.CommandText = "DELETE FROM my_aspnet_personalizationperuser " + + "WHERE PathId IN (SELECT Paths.PathId FROM my_aspnet_paths as paths " + + "WHERE paths.ApplicationId = @ApplicationId)"; + cmd.Parameters.AddWithValue("@ApplicationId", applicationId); + } + + var rows = cmd.ExecuteNonQuery(); + return rows; + } + + internal static int my_aspnet_PersonalizationAdministration_ResetSharedState(long applicationId, string[] paths, MySQLPersonalizationConnectionHelper connection) + { + if (applicationId <= 0) + return 0; + + if (!connection.Opened) + throw new Exception("Error: Connection should be open"); + + if (paths == null) + return 0; + + var cmd = new MySqlCommand(); + cmd.Connection = connection.Connection; + + var rows = 0; + + foreach (var path in paths) + { + cmd.CommandText = "DELETE my_aspnet_personalizationallusers.* FROM my_aspnet_personalizationallusers " + + "INNER JOIN my_aspnet_paths as paths ON " + + "((paths.ApplicationId = @ApplicationId AND " + + "my_aspnet_personalizationallusers.PathId = paths.PathId) AND " + + "paths.loweredpath = LOWER(@Path))"; + + cmd.Parameters.AddWithValue("@ApplicationId", applicationId); + cmd.Parameters.AddWithValue("@Path", path); + rows += cmd.ExecuteNonQuery(); + } + + return rows; + } + + + internal static int my_aspnet_PersonalizationAdministration_DeleteAllState(bool allUsersScope, long applicationId, MySQLPersonalizationConnectionHelper connection) + { + if (applicationId <= 0) + return 0; + + if (!connection.Opened) + throw new Exception("Error: Connection should be open"); + + var cmd = new MySqlCommand(); + cmd.Connection = connection.Connection; + + if (allUsersScope) + { + + cmd.CommandText = "DELETE FROM my_aspnet_personalizationallusers " + + "WHERE PathId IN " + + "(SELECT paths.PathId FROM my_aspnet_paths as paths " + + "WHERE paths.ApplicationId = @ApplicationId)"; + } + else + { + cmd.CommandText = "DELETE FROM my_aspnet_personalizationperuser " + + "WHERE PathId IN " + + "(SELECT Paths.PathId FROM my_aspnet_paths Paths " + + "WHERE Paths.ApplicationId = @ApplicationId)"; + } + cmd.Parameters.AddWithValue("@ApplicationId", applicationId); + var rows = cmd.ExecuteNonQuery(); + return rows; + } + + /// + /// Saves per-user state for the specified page and the specified user in the my_aspnet_PersonalizationPerUser table. + /// + /// + internal static int my_aspnet_PersonalizationPerUser_SetPageSettings(long applicationId, string userName, string path, byte[] settings, DateTime currentTimeUtc, MySQLPersonalizationConnectionHelper connection) + { + if (applicationId <= 0) + return 0; + + if (!connection.Opened) + throw new Exception("Error: Connection should be open"); + + var cmd = new MySqlCommand(); + cmd.Connection = connection.Connection; + + cmd.CommandText = "SELECT PathId FROM my_aspnet_paths WHERE ApplicationId = @ApplicationId AND LoweredPath = LOWER(@Path)"; + cmd.Parameters.AddWithValue("@ApplicationId", applicationId); + cmd.Parameters.AddWithValue("@Path", path); + var pathId = (string)cmd.ExecuteScalar(); + + cmd.Parameters.Clear(); + + if (pathId == null) + { + // create path + MySqlTransaction trans; + trans = connection.Connection.BeginTransaction(); + + try + { + cmd.Transaction = trans; + cmd.CommandText = "INSERT INTO my_aspnet_paths (applicationId, pathId, path, loweredpath) values (@ApplicationId, @PathId, @Path, LOWER(@Path))"; + cmd.Parameters.AddWithValue("@ApplicationId", applicationId); + cmd.Parameters.AddWithValue("@PathId", pathId = Guid.NewGuid().ToString()); + cmd.Parameters.AddWithValue("@Path", path); + cmd.ExecuteNonQuery(); + trans.Commit(); + } + catch + { + trans.Rollback(); + throw; + } + } + + cmd.Parameters.Clear(); + cmd.CommandText = "SELECT id FROM my_aspnet_users WHERE ApplicationId = @ApplicationId AND name = LOWER(@UserName)"; + cmd.Parameters.AddWithValue("@ApplicationId", applicationId); + cmd.Parameters.AddWithValue("@UserName", userName); + var userId = (cmd.ExecuteScalar() ?? "").ToString(); + + userId = string.IsNullOrEmpty(userId) ? "0" : userId; + + // create user + if (int.Parse(userId, CultureInfo.InvariantCulture) == 0) + { + // create path + MySqlTransaction trans; + trans = connection.Connection.BeginTransaction(); + + try + { + cmd.Parameters.Clear(); + cmd.Transaction = trans; + cmd.CommandText = "INSERT INTO my_aspnet_users (applicationId, name, isAnonymous, lastActivityDate) values (@ApplicationId, @UserName, false, @CurrentTimeUtc)"; + cmd.Parameters.AddWithValue("@ApplicationId", applicationId); + cmd.Parameters.AddWithValue("@UserName", userName); + cmd.Parameters.AddWithValue("@CurrentTimeUtc", DateTime.UtcNow); + cmd.ExecuteNonQuery(); + trans.Commit(); + } + catch + { + trans.Rollback(); + throw; + } + + cmd.Parameters.Clear(); + cmd.CommandText = "SELECT Id from my_aspnet_users where applicationId = @ApplicationId and name = @UserName)"; + cmd.Parameters.AddWithValue("@ApplicationId", applicationId); + cmd.Parameters.AddWithValue("@UserName", userName); + userId = (string)cmd.ExecuteScalar(); + + } + var rows = UpdateUserLastActiveDate(connection.Connection, int.Parse(userId, CultureInfo.InvariantCulture), DateTime.UtcNow); + if (rows == 0) + throw new Exception("User not found"); + + cmd.Parameters.Clear(); + cmd.CommandText = "Select COUNT(*) from my_aspnet_personalizationperuser where userid = @UserId and pathId = @PathId"; + cmd.Parameters.AddWithValue("@UserId", userId); + cmd.Parameters.AddWithValue("@PathId", pathId); + if ((long)cmd.ExecuteScalar() > 0) + { + cmd.Parameters.Clear(); + cmd.CommandText = "UPDATE my_aspnet_personalizationperuser SET PageSettings = @PageSettings, LastUpdatedDate = @CurrentTimeUtc " + + "where userid = @UserId and pathId = @PathId"; + cmd.Parameters.AddWithValue("@UserId", userId); + cmd.Parameters.AddWithValue("@PathId", pathId); + cmd.Parameters.AddWithValue("@PageSettings", settings); + cmd.Parameters.AddWithValue("@CurrentTimeUtc", DateTime.UtcNow); + cmd.ExecuteNonQuery(); + } + else + { + cmd.Parameters.Clear(); + cmd.CommandText = "INSERT INTO my_aspnet_personalizationperuser(applicationId, pathId, userId, pageSettings, lastUpdatedDate) VALUES(@applicationId, @PathId, @userId, @PageSettings, @LastUpdatedDate)"; + cmd.Parameters.AddWithValue("@applicationId", applicationId); + cmd.Parameters.AddWithValue("@UserId", userId); + cmd.Parameters.AddWithValue("@PathId", pathId); + cmd.Parameters.AddWithValue("@PageSettings", settings); + cmd.Parameters.AddWithValue("@LastUpdatedDate", DateTime.UtcNow); + rows = cmd.ExecuteNonQuery(); + } + return rows; + } + + /// + /// Saves shared state for the specified page in the aspnet_PersonalizationAllUsers table + /// + /// + internal static int my_aspnet_PersonalizationAllUsers_SetPageSettings(long applicationId, string path, byte[] settings, DateTime currentTimeUtc, MySQLPersonalizationConnectionHelper connection) + { + if (applicationId <= 0) + return 0; + + if (!connection.Opened) + throw new Exception("Error: Connection should be open"); + + var cmd = new MySqlCommand(); + cmd.Connection = connection.Connection; + + cmd.CommandText = "SELECT PathId FROM my_aspnet_paths WHERE ApplicationId = @ApplicationId AND LoweredPath = LOWER(@Path)"; + cmd.Parameters.AddWithValue("@ApplicationId", applicationId); + cmd.Parameters.AddWithValue("@Path", path); + var pathId = (string)cmd.ExecuteScalar(); + cmd.Parameters.Clear(); + + if (pathId == null) + { + // create path + MySqlTransaction trans; + trans = connection.Connection.BeginTransaction(); + + try + { + cmd.Transaction = trans; + cmd.CommandText = "INSERT INTO my_aspnet_paths (applicationId, pathId, path, loweredpath) values (@ApplicationId, @PathId, @Path, LOWER(@Path))"; + cmd.Parameters.AddWithValue("@ApplicationId", applicationId); + cmd.Parameters.AddWithValue("@PathId", pathId = Guid.NewGuid().ToString()); + cmd.Parameters.AddWithValue("@Path", path); + cmd.ExecuteNonQuery(); + trans.Commit(); + } + catch + { + trans.Rollback(); + throw; + } + } + + cmd.CommandText = "INSERT INTO my_aspnet_personalizationallusers(PathId, PageSettings, LastUpdatedDate) VALUES (@PathId, @PageSettings, @CurrentTimeUtc)"; + cmd.CommandText += " ON DUPLICATE KEY UPDATE PageSettings=Values(PageSettings), LastUpdatedDate=Values(LastUpdatedDate)"; + cmd.Parameters.Clear(); + cmd.Parameters.AddWithValue("@PageSettings", settings); + cmd.Parameters.AddWithValue("@PathId", pathId); + cmd.Parameters.AddWithValue("@CurrentTimeUtc", currentTimeUtc); + var rows = cmd.ExecuteNonQuery(); + return rows; + } + } +} diff --git a/MySql.Web/src/ProfileProvider.cs b/MySql.Web/src/ProfileProvider.cs index ef472b5fb..25fad6a50 100644 --- a/MySql.Web/src/ProfileProvider.cs +++ b/MySql.Web/src/ProfileProvider.cs @@ -1,673 +1,673 @@ -// Copyright (c) 2004, 2020, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -// This code was contributed by Sean Wright (srwright@alcor.concordia.ca) on 2007-01-12 -// The copyright was assigned and transferred under the terms of -// the MySQL Contributor License Agreement (CLA) - -using MySql.Data.MySqlClient; -using MySql.Web.Common; -using MySql.Web.General; -using System; -using System.Collections.Generic; -using System.Collections.Specialized; -using System.Configuration; -using System.Configuration.Provider; -using System.Data; -using System.Globalization; -using System.IO; -using System.Text; -using System.Web.Hosting; -using System.Web.Profile; - -namespace MySql.Web.Profile -{ - /// - /// Manages storage of profile information for an ASP.NET application in a MySQL database. - /// - public class MySQLProfileProvider : ProfileProvider - { - private string connectionString; - private Application app; - - #region Abstract Members - - /// - /// Initializes the provider. - /// - /// The friendly name of the provider. - /// A collection of the name/value pairs representing the provider-specific attributes specified in the configuration for this provider. - /// The name of the provider is null. - /// The name of the provider has a length of zero. - /// An attempt is made to call on a provider after the provider has already been initialized. - public override void Initialize(string name, NameValueCollection config) - { - if (config == null) - throw new ArgumentNullException("config"); - - if (name == null || name.Length == 0) - name = "MySQLProfileProvider"; - - if (string.IsNullOrEmpty(config["description"])) - { - config.Remove("description"); - config.Add("description", "MySQL Profile provider"); - } - base.Initialize(name, config); - - try - { - string applicationName = GetConfigValue(config["applicationName"], HostingEnvironment.ApplicationVirtualPath); - - connectionString = ConfigUtility.GetConnectionString(config); - if (String.IsNullOrEmpty(connectionString)) return; - - // make sure our schema is up to date - SchemaManager.CheckSchema(connectionString, config); - - app = new Application(applicationName, base.Description); - } - catch (Exception ex) - { - throw new ProviderException(Properties.Resources.ErrorInitProfileProvider, ex); - } - } - - /// - /// When overridden in a derived class, deletes all user-profile data - /// for profiles in which the last activity date occurred before the - /// specified date. - /// - /// One of the - /// - /// values, specifying whether anonymous, authenticated, or both - /// types of profiles are deleted. - /// A - /// that identifies which user profiles are considered inactive. If the - /// - /// value of a user profile occurs on or before this date and time, the - /// profile is considered inactive. - /// - /// The number of profiles deleted from the data source. - /// - public override int DeleteInactiveProfiles( - ProfileAuthenticationOption authenticationOption, - DateTime userInactiveSinceDate) - { - using (MySqlConnection c = new MySqlConnection(connectionString)) - { - c.Open(); - - MySqlCommand queryCmd = new MySqlCommand( - @"SELECT * FROM my_aspnet_users - WHERE applicationId=@appId AND - lastActivityDate < @lastActivityDate", - c); - queryCmd.Parameters.AddWithValue("@appId", app.FetchId(c)); - queryCmd.Parameters.AddWithValue("@lastActivityDate", userInactiveSinceDate); - if (authenticationOption == ProfileAuthenticationOption.Anonymous) - queryCmd.CommandText += " AND isAnonymous = 1"; - else if (authenticationOption == ProfileAuthenticationOption.Authenticated) - queryCmd.CommandText += " AND isAnonymous = 0"; - - MySqlCommand deleteCmd = new MySqlCommand( - "DELETE FROM my_aspnet_profiles WHERE userId = @userId", c); - deleteCmd.Parameters.Add("@userId", MySqlDbType.UInt64); - - List uidList = new List(); - using (MySqlDataReader reader = queryCmd.ExecuteReader()) - { - while (reader.Read()) - uidList.Add(reader.GetUInt64("userId")); - } - - int count = 0; - foreach (ulong uid in uidList) - { - deleteCmd.Parameters[0].Value = uid; - count += deleteCmd.ExecuteNonQuery(); - } - return count; - } - } - - /// - /// When overridden in a derived class, deletes profile properties - /// and information for profiles that match the supplied list of user names. - /// - /// A string array of user names for - /// profiles to be deleted. - /// - /// The number of profiles deleted from the data source. - /// - public override int DeleteProfiles(string[] usernames) - { - using (MySqlConnection c = new MySqlConnection(connectionString)) - { - c.Open(); - - MySqlCommand queryCmd = new MySqlCommand( - @"SELECT * FROM my_aspnet_users - WHERE applicationId=@appId AND name = @name", c); - queryCmd.Parameters.AddWithValue("@appId", app.FetchId(c)); - queryCmd.Parameters.Add("@name", MySqlDbType.VarChar); - - MySqlCommand deleteCmd = new MySqlCommand( - "DELETE FROM my_aspnet_profiles WHERE userId = @userId", c); - deleteCmd.Parameters.Add("@userId", MySqlDbType.Int32); - - int count = 0; - foreach (string name in usernames) - { - queryCmd.Parameters[1].Value = name; - int uid = (int)queryCmd.ExecuteScalar(); - - deleteCmd.Parameters[0].Value = uid; - count += deleteCmd.ExecuteNonQuery(); - } - return count; - } - } - - /// - /// When overridden in a derived class, deletes profile properties - /// and information for the supplied list of profiles. - /// - /// A - /// of - /// information about profiles that are to be deleted. - /// - /// The number of profiles deleted from the data source. - /// - public override int DeleteProfiles(ProfileInfoCollection profiles) - { - string[] s = new string[profiles.Count]; - - int i = 0; - foreach (ProfileInfo p in profiles) - s[i++] = p.UserName; - return DeleteProfiles(s); - } - - /// - /// When overridden in a derived class, retrieves profile information - /// for profiles in which the last activity date occurred on or before - /// the specified date and the user name matches the specified user name. - /// - /// One of the - /// values, - /// specifying whether anonymous, authenticated, or both types of profiles - /// are returned. - /// The user name to search for. - /// A - /// that identifies which user profiles are considered inactive. If the - /// value - /// of a user profile occurs on or before this date and time, the profile - /// is considered inactive. - /// The index of the page of results to return. - /// The size of the page of results to return. - /// When this method returns, contains the total - /// number of profiles. - /// - /// A containing - /// user profile information for inactive profiles where the user name - /// matches the supplied parameter. - /// - public override ProfileInfoCollection FindInactiveProfilesByUserName( - ProfileAuthenticationOption authenticationOption, - string usernameToMatch, DateTime userInactiveSinceDate, - int pageIndex, int pageSize, out int totalRecords) - { - return GetProfiles(authenticationOption, usernameToMatch, - userInactiveSinceDate, pageIndex, pageSize, out totalRecords); - } - - /// - /// When overridden in a derived class, retrieves profile information - /// for profiles in which the user name matches the specified user names. - /// - /// One of the - /// values, - /// specifying whether anonymous, authenticated, or both types of profiles - /// are returned. - /// The user name to search for. - /// The index of the page of results to return. - /// The size of the page of results to return. - /// When this method returns, contains the total - /// number of profiles. - /// - /// A containing - /// user-profile information for profiles where the user name matches the - /// supplied parameter. - /// - public override ProfileInfoCollection FindProfilesByUserName( - ProfileAuthenticationOption authenticationOption, - string usernameToMatch, int pageIndex, int pageSize, - out int totalRecords) - { - return GetProfiles(authenticationOption, usernameToMatch, - DateTime.MinValue, pageIndex, pageSize, out totalRecords); - } - - /// - /// When overridden in a derived class, retrieves user-profile data - /// from the data source for profiles in which the last activity date - /// occurred on or before the specified date. - /// - /// One of the - /// values, - /// specifying whether anonymous, authenticated, or both types of profiles - /// are returned. - /// A - /// that identifies which user profiles are considered inactive. If the - /// of - /// a user profile occurs on or before this date and time, the profile is - /// considered inactive. - /// The index of the page of results to return. - /// The size of the page of results to return. - /// When this method returns, contains the - /// total number of profiles. - /// - /// A containing user-profile information about the inactive profiles. - /// - public override ProfileInfoCollection GetAllInactiveProfiles( - ProfileAuthenticationOption authenticationOption, - DateTime userInactiveSinceDate, int pageIndex, int pageSize, - out int totalRecords) - { - return GetProfiles(authenticationOption, null, - userInactiveSinceDate, pageIndex, pageSize, out totalRecords); - } - - /// - /// When overridden in a derived class, retrieves user profile data for - /// all profiles in the data source. - /// - /// One of the - /// values, - /// specifying whether anonymous, authenticated, or both types of profiles - /// are returned. - /// The index of the page of results to return. - /// The size of the page of results to return. - /// When this method returns, contains the - /// total number of profiles. - /// - /// A containing - /// user-profile information for all profiles in the data source. - /// - public override ProfileInfoCollection GetAllProfiles( - ProfileAuthenticationOption authenticationOption, int pageIndex, - int pageSize, out int totalRecords) - { - return GetProfiles(authenticationOption, null, - DateTime.MinValue, pageIndex, pageSize, out totalRecords); - } - - /// - /// When overridden in a derived class, returns the number of profiles - /// in which the last activity date occurred on or before the specified - /// date. - /// - /// One of the - /// values, - /// specifying whether anonymous, authenticated, or both types of profiles - /// are returned. - /// A - /// that identifies which user profiles are considered inactive. If the - /// of - /// a user profile occurs on or before this date and time, the profile - /// is considered inactive. - /// - /// The number of profiles in which the last activity date occurred on - /// or before the specified date. - /// - public override int GetNumberOfInactiveProfiles( - ProfileAuthenticationOption authenticationOption, - DateTime userInactiveSinceDate) - { - using (MySqlConnection c = new MySqlConnection(connectionString)) - { - c.Open(); - - MySqlCommand queryCmd = new MySqlCommand( - @"SELECT COUNT(*) FROM my_aspnet_users - WHERE applicationId = @appId AND - lastActivityDate < @lastActivityDate", - c); - queryCmd.Parameters.AddWithValue("@appId", app.FetchId(c)); - queryCmd.Parameters.AddWithValue("@lastActivityDate", userInactiveSinceDate); - if (authenticationOption == ProfileAuthenticationOption.Anonymous) - queryCmd.CommandText += " AND isAnonymous = 1"; - else if (authenticationOption == ProfileAuthenticationOption.Authenticated) - queryCmd.CommandText += " AND isAnonymous = 0"; - return (int)queryCmd.ExecuteScalar(); - } - } - - /// - /// Gets or sets the name of the currently running application. - /// - /// - /// A that contains the application's shortened name, which does not contain a full path or extension, for example, SimpleAppSettings. - public override string ApplicationName - { - get { return app.Name; } - set { app.Name = value; } - } - - /// - /// Returns the collection of settings property values for the specified application instance and settings property group. - /// - /// A describing the current application use. - /// A containing the settings property group whose values are to be retrieved. - /// - /// A containing the values for the specified settings property group. - /// - public override SettingsPropertyValueCollection GetPropertyValues( - SettingsContext context, SettingsPropertyCollection collection) - { - SettingsPropertyValueCollection values = new SettingsPropertyValueCollection(); - - if (collection.Count < 1) return values; - - string username = (string)context["UserName"]; - - foreach (SettingsProperty property in collection) - { - if (property.PropertyType.IsPrimitive || property.PropertyType == typeof(string)) - property.SerializeAs = SettingsSerializeAs.String; - else - property.SerializeAs = SettingsSerializeAs.Xml; - - values.Add(new SettingsPropertyValue(property)); - } - - if (String.IsNullOrEmpty(username)) - return values; - - // retrieve encoded profile data from the database - try - { - - using (MySqlConnection c = new MySqlConnection(connectionString)) - { - c.Open(); - MySqlCommand cmd = new MySqlCommand( - @"SELECT * FROM my_aspnet_profiles p - JOIN my_aspnet_users u ON u.id = p.userId - WHERE u.applicationId = @appId AND u.name = @name", c); - cmd.Parameters.AddWithValue("@appId", app.FetchId(c)); - cmd.Parameters.AddWithValue("@name", username); - MySqlDataAdapter da = new MySqlDataAdapter(cmd); - DataTable dt = new DataTable(); - da.Fill(dt); - - if (dt.Rows.Count > 0) - DecodeProfileData(dt.Rows[0], values); - return values; - } - } - catch (Exception ex) - { - throw new ProviderException(Properties.Resources.UnableToRetrieveProfileData, ex); - } - } - - /// - /// Sets the values of the specified group of property settings. - /// - /// A describing the current application usage. - /// A representing the group of property settings to set. - public override void SetPropertyValues( - SettingsContext context, SettingsPropertyValueCollection collection) - { - bool isAuthenticated = (bool)context["IsAuthenticated"]; - string username = (string)context["UserName"]; - - if (String.IsNullOrEmpty(username)) return; - if (collection.Count < 1) return; - - string index = String.Empty; - string stringData = String.Empty; - byte[] binaryData = null; - int count = EncodeProfileData(collection, isAuthenticated, ref index, ref stringData, ref binaryData); - if (count < 1) return; - - MySqlTransaction txn = null; - // save the encoded profile data to the database - using (MySqlConnection connection = new MySqlConnection(connectionString)) - { - try - { - connection.Open(); - txn = connection.BeginTransaction(); - - // either create a new user or fetch the existing user id - long userId = SchemaManager.CreateOrFetchUserId(connection, username, - app.EnsureId(connection), isAuthenticated); - - MySqlCommand cmd = new MySqlCommand( - @"INSERT INTO my_aspnet_profiles - VALUES (@userId, @index, @stringData, @binaryData, NULL) ON DUPLICATE KEY UPDATE - valueindex=VALUES(valueindex), stringdata=VALUES(stringdata), - binarydata=VALUES(binarydata)", connection); - cmd.Parameters.Clear(); - cmd.Parameters.AddWithValue("@userId", userId); - cmd.Parameters.AddWithValue("@index", index); - cmd.Parameters.AddWithValue("@stringData", stringData); - cmd.Parameters.AddWithValue("@binaryData", binaryData); - count = cmd.ExecuteNonQuery(); - if (count == 0) - throw new Exception(Properties.Resources.ProfileUpdateFailed); - txn.Commit(); - } - catch (Exception ex) - { - if (txn != null) - txn.Rollback(); - throw new ProviderException(Properties.Resources.ProfileUpdateFailed, ex); - } - } - } - - #endregion - - internal static void DeleteUserData(MySqlConnection connection, int userId) - { - MySqlCommand cmd = new MySqlCommand( - "DELETE FROM my_aspnet_profiles WHERE userId=@userId", connection); - cmd.Parameters.AddWithValue("@userId", userId); - cmd.ExecuteNonQuery(); - } - - #region Private Methods - - private void DecodeProfileData(DataRow profileRow, SettingsPropertyValueCollection values) - { - string indexData = (string)profileRow["valueindex"]; - string stringData = (string)profileRow["stringData"]; - byte[] binaryData = (byte[])profileRow["binaryData"]; - - if (indexData == null) return; - - string[] indexes = indexData.Split(':'); - - foreach (string index in indexes) - { - string[] parts = index.Split('/'); - SettingsPropertyValue value = values[parts[0]]; - if (value == null) continue; - - int pos = Int32.Parse(parts[2], CultureInfo.InvariantCulture); - int len = Int32.Parse(parts[3], CultureInfo.InvariantCulture); - if (len == -1) - { - value.PropertyValue = null; - value.IsDirty = false; - value.Deserialized = true; - } - else if (parts[1].Equals("0")) - value.SerializedValue = stringData.Substring(pos, len); - else - { - byte[] buf = new byte[len]; - Buffer.BlockCopy(binaryData, pos, buf, 0, len); - value.SerializedValue = buf; - } - } - } - - private int EncodeProfileData(SettingsPropertyValueCollection collection, bool isAuthenticated, - ref string index, ref string stringData, ref byte[] binaryData) - { - bool itemsToSave = false; - - // first we need to determine if there are any items that need saving - // this is an optimization - foreach (SettingsPropertyValue value in collection) - { - if (!value.IsDirty) continue; - if (value.Property.Attributes["AllowAnonymous"].Equals(false) && - !isAuthenticated) continue; - itemsToSave = true; - break; - } - if (!itemsToSave) return 0; - - StringBuilder indexBuilder = new StringBuilder(); - StringBuilder stringDataBuilder = new StringBuilder(); - MemoryStream binaryBuilder = new MemoryStream(); - int count = 0; - - // ok, we have some values that need to be saved so we go back through - foreach (SettingsPropertyValue value in collection) - { - // if the value has not been written to and is still using the default value - // no need to save it - if (value.UsingDefaultValue && !value.IsDirty) continue; - - // we don't save properties that require the user to be authenticated when the - // current user is not authenticated. - if (value.Property.Attributes["AllowAnonymous"].Equals(false) && - !isAuthenticated) continue; - - count++; - object propValue = value.SerializedValue; - if ((value.Deserialized && value.PropertyValue == null) || - value.SerializedValue == null) - indexBuilder.AppendFormat("{0}//0/-1:", value.Name); - else if (propValue is string) - { - indexBuilder.AppendFormat("{0}/0/{1}/{2}:", value.Name, - stringDataBuilder.Length, (propValue as string).Length); - stringDataBuilder.Append(propValue); - } - else - { - byte[] binaryValue = (byte[])propValue; - indexBuilder.AppendFormat("{0}/1/{1}/{2}:", value.Name, - binaryBuilder.Position, binaryValue.Length); - binaryBuilder.Write(binaryValue, 0, binaryValue.Length); - } - } - index = indexBuilder.ToString(); - stringData = stringDataBuilder.ToString(); - binaryData = binaryBuilder.ToArray(); - return count; - } - - - private ProfileInfoCollection GetProfiles( - ProfileAuthenticationOption authenticationOption, - string usernameToMatch, DateTime userInactiveSinceDate, - int pageIndex, int pageSize, out int totalRecords) - { - List whereClauses = new List(); - - using (MySqlConnection c = new MySqlConnection(connectionString)) - { - c.Open(); - - MySqlCommand cmd = new MySqlCommand( - @"SELECT p.*, u.name, u.isAnonymous, u.lastActivityDate, - LENGTH(p.stringdata) + LENGTH(p.binarydata) AS profilesize - FROM my_aspnet_profiles p - JOIN my_aspnet_users u ON u.id = p.userId - WHERE u.applicationId = @appId", c); - cmd.Parameters.AddWithValue("@appId", app.FetchId(c)); - - if (usernameToMatch != null) - { - cmd.CommandText += " AND u.name LIKE @userName"; - cmd.Parameters.AddWithValue("@userName", usernameToMatch); - } - if (userInactiveSinceDate != DateTime.MinValue) - { - cmd.CommandText += " AND u.lastActivityDate < @lastActivityDate"; - cmd.Parameters.AddWithValue("@lastActivityDate", userInactiveSinceDate); - } - if (authenticationOption == ProfileAuthenticationOption.Anonymous) - cmd.CommandText += " AND u.isAnonymous = 1"; - else if (authenticationOption == ProfileAuthenticationOption.Authenticated) - cmd.CommandText += " AND u.isAnonymous = 0"; - - cmd.CommandText += String.Format(" LIMIT {0},{1}", pageIndex * pageSize, pageSize); - - ProfileInfoCollection pic = new ProfileInfoCollection(); - using (MySqlDataReader reader = cmd.ExecuteReader()) - { - while (reader.Read()) - { - ProfileInfo pi = new ProfileInfo( - reader.GetString("name"), - reader.GetBoolean("isAnonymous"), - reader.GetDateTime("lastActivityDate"), - reader.GetDateTime("lastUpdatedDate"), - reader.GetInt32("profilesize")); - pic.Add(pi); - } - } - cmd.CommandText = "SELECT FOUND_ROWS()"; - totalRecords = Convert.ToInt32(cmd.ExecuteScalar()); - return pic; - } - } - - private static string GetConfigValue(string configValue, string defaultValue) - { - if (string.IsNullOrEmpty(configValue)) - { - return defaultValue; - } - return configValue; - } - - #endregion - - } -} +// Copyright © 2004, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +// This code was contributed by Sean Wright (srwright@alcor.concordia.ca) on 2007-01-12 +// The copyright was assigned and transferred under the terms of +// the MySQL Contributor License Agreement (CLA) + +using MySql.Data.MySqlClient; +using MySql.Web.Common; +using MySql.Web.General; +using System; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.Configuration; +using System.Configuration.Provider; +using System.Data; +using System.Globalization; +using System.IO; +using System.Text; +using System.Web.Hosting; +using System.Web.Profile; + +namespace MySql.Web.Profile +{ + /// + /// Manages storage of profile information for an ASP.NET application in a MySQL database. + /// + public class MySQLProfileProvider : ProfileProvider + { + private string connectionString; + private Application app; + + #region Abstract Members + + /// + /// Initializes the provider. + /// + /// The friendly name of the provider. + /// A collection of the name/value pairs representing the provider-specific attributes specified in the configuration for this provider. + /// The name of the provider is null. + /// The name of the provider has a length of zero. + /// An attempt is made to call on a provider after the provider has already been initialized. + public override void Initialize(string name, NameValueCollection config) + { + if (config == null) + throw new ArgumentNullException("config"); + + if (name == null || name.Length == 0) + name = "MySQLProfileProvider"; + + if (string.IsNullOrEmpty(config["description"])) + { + config.Remove("description"); + config.Add("description", "MySQL Profile provider"); + } + base.Initialize(name, config); + + try + { + string applicationName = GetConfigValue(config["applicationName"], HostingEnvironment.ApplicationVirtualPath); + + connectionString = ConfigUtility.GetConnectionString(config); + if (String.IsNullOrEmpty(connectionString)) return; + + // make sure our schema is up to date + SchemaManager.CheckSchema(connectionString, config); + + app = new Application(applicationName, base.Description); + } + catch (Exception ex) + { + throw new ProviderException(Properties.Resources.ErrorInitProfileProvider, ex); + } + } + + /// + /// When overridden in a derived class, deletes all user-profile data + /// for profiles in which the last activity date occurred before the + /// specified date. + /// + /// One of the + /// + /// values, specifying whether anonymous, authenticated, or both + /// types of profiles are deleted. + /// A + /// that identifies which user profiles are considered inactive. If the + /// + /// value of a user profile occurs on or before this date and time, the + /// profile is considered inactive. + /// + /// The number of profiles deleted from the data source. + /// + public override int DeleteInactiveProfiles( + ProfileAuthenticationOption authenticationOption, + DateTime userInactiveSinceDate) + { + using (MySqlConnection c = new MySqlConnection(connectionString)) + { + c.Open(); + + MySqlCommand queryCmd = new MySqlCommand( + @"SELECT * FROM my_aspnet_users + WHERE applicationId=@appId AND + lastActivityDate < @lastActivityDate", + c); + queryCmd.Parameters.AddWithValue("@appId", app.FetchId(c)); + queryCmd.Parameters.AddWithValue("@lastActivityDate", userInactiveSinceDate); + if (authenticationOption == ProfileAuthenticationOption.Anonymous) + queryCmd.CommandText += " AND isAnonymous = 1"; + else if (authenticationOption == ProfileAuthenticationOption.Authenticated) + queryCmd.CommandText += " AND isAnonymous = 0"; + + MySqlCommand deleteCmd = new MySqlCommand( + "DELETE FROM my_aspnet_profiles WHERE userId = @userId", c); + deleteCmd.Parameters.Add("@userId", MySqlDbType.UInt64); + + List uidList = new List(); + using (MySqlDataReader reader = queryCmd.ExecuteReader()) + { + while (reader.Read()) + uidList.Add(reader.GetUInt64("userId")); + } + + int count = 0; + foreach (ulong uid in uidList) + { + deleteCmd.Parameters[0].Value = uid; + count += deleteCmd.ExecuteNonQuery(); + } + return count; + } + } + + /// + /// When overridden in a derived class, deletes profile properties + /// and information for profiles that match the supplied list of user names. + /// + /// A string array of user names for + /// profiles to be deleted. + /// + /// The number of profiles deleted from the data source. + /// + public override int DeleteProfiles(string[] usernames) + { + using (MySqlConnection c = new MySqlConnection(connectionString)) + { + c.Open(); + + MySqlCommand queryCmd = new MySqlCommand( + @"SELECT * FROM my_aspnet_users + WHERE applicationId=@appId AND name = @name", c); + queryCmd.Parameters.AddWithValue("@appId", app.FetchId(c)); + queryCmd.Parameters.Add("@name", MySqlDbType.VarChar); + + MySqlCommand deleteCmd = new MySqlCommand( + "DELETE FROM my_aspnet_profiles WHERE userId = @userId", c); + deleteCmd.Parameters.Add("@userId", MySqlDbType.Int32); + + int count = 0; + foreach (string name in usernames) + { + queryCmd.Parameters[1].Value = name; + int uid = (int)queryCmd.ExecuteScalar(); + + deleteCmd.Parameters[0].Value = uid; + count += deleteCmd.ExecuteNonQuery(); + } + return count; + } + } + + /// + /// When overridden in a derived class, deletes profile properties + /// and information for the supplied list of profiles. + /// + /// A + /// of + /// information about profiles that are to be deleted. + /// + /// The number of profiles deleted from the data source. + /// + public override int DeleteProfiles(ProfileInfoCollection profiles) + { + string[] s = new string[profiles.Count]; + + int i = 0; + foreach (ProfileInfo p in profiles) + s[i++] = p.UserName; + return DeleteProfiles(s); + } + + /// + /// When overridden in a derived class, retrieves profile information + /// for profiles in which the last activity date occurred on or before + /// the specified date and the user name matches the specified user name. + /// + /// One of the + /// values, + /// specifying whether anonymous, authenticated, or both types of profiles + /// are returned. + /// The user name to search for. + /// A + /// that identifies which user profiles are considered inactive. If the + /// value + /// of a user profile occurs on or before this date and time, the profile + /// is considered inactive. + /// The index of the page of results to return. + /// The size of the page of results to return. + /// When this method returns, contains the total + /// number of profiles. + /// + /// A containing + /// user profile information for inactive profiles where the user name + /// matches the supplied parameter. + /// + public override ProfileInfoCollection FindInactiveProfilesByUserName( + ProfileAuthenticationOption authenticationOption, + string usernameToMatch, DateTime userInactiveSinceDate, + int pageIndex, int pageSize, out int totalRecords) + { + return GetProfiles(authenticationOption, usernameToMatch, + userInactiveSinceDate, pageIndex, pageSize, out totalRecords); + } + + /// + /// When overridden in a derived class, retrieves profile information + /// for profiles in which the user name matches the specified user names. + /// + /// One of the + /// values, + /// specifying whether anonymous, authenticated, or both types of profiles + /// are returned. + /// The user name to search for. + /// The index of the page of results to return. + /// The size of the page of results to return. + /// When this method returns, contains the total + /// number of profiles. + /// + /// A containing + /// user-profile information for profiles where the user name matches the + /// supplied parameter. + /// + public override ProfileInfoCollection FindProfilesByUserName( + ProfileAuthenticationOption authenticationOption, + string usernameToMatch, int pageIndex, int pageSize, + out int totalRecords) + { + return GetProfiles(authenticationOption, usernameToMatch, + DateTime.MinValue, pageIndex, pageSize, out totalRecords); + } + + /// + /// When overridden in a derived class, retrieves user-profile data + /// from the data source for profiles in which the last activity date + /// occurred on or before the specified date. + /// + /// One of the + /// values, + /// specifying whether anonymous, authenticated, or both types of profiles + /// are returned. + /// A + /// that identifies which user profiles are considered inactive. If the + /// of + /// a user profile occurs on or before this date and time, the profile is + /// considered inactive. + /// The index of the page of results to return. + /// The size of the page of results to return. + /// When this method returns, contains the + /// total number of profiles. + /// + /// A containing user-profile information about the inactive profiles. + /// + public override ProfileInfoCollection GetAllInactiveProfiles( + ProfileAuthenticationOption authenticationOption, + DateTime userInactiveSinceDate, int pageIndex, int pageSize, + out int totalRecords) + { + return GetProfiles(authenticationOption, null, + userInactiveSinceDate, pageIndex, pageSize, out totalRecords); + } + + /// + /// When overridden in a derived class, retrieves user profile data for + /// all profiles in the data source. + /// + /// One of the + /// values, + /// specifying whether anonymous, authenticated, or both types of profiles + /// are returned. + /// The index of the page of results to return. + /// The size of the page of results to return. + /// When this method returns, contains the + /// total number of profiles. + /// + /// A containing + /// user-profile information for all profiles in the data source. + /// + public override ProfileInfoCollection GetAllProfiles( + ProfileAuthenticationOption authenticationOption, int pageIndex, + int pageSize, out int totalRecords) + { + return GetProfiles(authenticationOption, null, + DateTime.MinValue, pageIndex, pageSize, out totalRecords); + } + + /// + /// When overridden in a derived class, returns the number of profiles + /// in which the last activity date occurred on or before the specified + /// date. + /// + /// One of the + /// values, + /// specifying whether anonymous, authenticated, or both types of profiles + /// are returned. + /// A + /// that identifies which user profiles are considered inactive. If the + /// of + /// a user profile occurs on or before this date and time, the profile + /// is considered inactive. + /// + /// The number of profiles in which the last activity date occurred on + /// or before the specified date. + /// + public override int GetNumberOfInactiveProfiles( + ProfileAuthenticationOption authenticationOption, + DateTime userInactiveSinceDate) + { + using (MySqlConnection c = new MySqlConnection(connectionString)) + { + c.Open(); + + MySqlCommand queryCmd = new MySqlCommand( + @"SELECT COUNT(*) FROM my_aspnet_users + WHERE applicationId = @appId AND + lastActivityDate < @lastActivityDate", + c); + queryCmd.Parameters.AddWithValue("@appId", app.FetchId(c)); + queryCmd.Parameters.AddWithValue("@lastActivityDate", userInactiveSinceDate); + if (authenticationOption == ProfileAuthenticationOption.Anonymous) + queryCmd.CommandText += " AND isAnonymous = 1"; + else if (authenticationOption == ProfileAuthenticationOption.Authenticated) + queryCmd.CommandText += " AND isAnonymous = 0"; + return (int)queryCmd.ExecuteScalar(); + } + } + + /// + /// Gets or sets the name of the currently running application. + /// + /// + /// A that contains the application's shortened name, which does not contain a full path or extension, for example, SimpleAppSettings. + public override string ApplicationName + { + get { return app.Name; } + set { app.Name = value; } + } + + /// + /// Returns the collection of settings property values for the specified application instance and settings property group. + /// + /// A describing the current application use. + /// A containing the settings property group whose values are to be retrieved. + /// + /// A containing the values for the specified settings property group. + /// + public override SettingsPropertyValueCollection GetPropertyValues( + SettingsContext context, SettingsPropertyCollection collection) + { + SettingsPropertyValueCollection values = new SettingsPropertyValueCollection(); + + if (collection.Count < 1) return values; + + string username = (string)context["UserName"]; + + foreach (SettingsProperty property in collection) + { + if (property.PropertyType.IsPrimitive || property.PropertyType == typeof(string)) + property.SerializeAs = SettingsSerializeAs.String; + else + property.SerializeAs = SettingsSerializeAs.Xml; + + values.Add(new SettingsPropertyValue(property)); + } + + if (String.IsNullOrEmpty(username)) + return values; + + // retrieve encoded profile data from the database + try + { + + using (MySqlConnection c = new MySqlConnection(connectionString)) + { + c.Open(); + MySqlCommand cmd = new MySqlCommand( + @"SELECT * FROM my_aspnet_profiles p + JOIN my_aspnet_users u ON u.id = p.userId + WHERE u.applicationId = @appId AND u.name = @name", c); + cmd.Parameters.AddWithValue("@appId", app.FetchId(c)); + cmd.Parameters.AddWithValue("@name", username); + MySqlDataAdapter da = new MySqlDataAdapter(cmd); + DataTable dt = new DataTable(); + da.Fill(dt); + + if (dt.Rows.Count > 0) + DecodeProfileData(dt.Rows[0], values); + return values; + } + } + catch (Exception ex) + { + throw new ProviderException(Properties.Resources.UnableToRetrieveProfileData, ex); + } + } + + /// + /// Sets the values of the specified group of property settings. + /// + /// A describing the current application usage. + /// A representing the group of property settings to set. + public override void SetPropertyValues( + SettingsContext context, SettingsPropertyValueCollection collection) + { + bool isAuthenticated = (bool)context["IsAuthenticated"]; + string username = (string)context["UserName"]; + + if (String.IsNullOrEmpty(username)) return; + if (collection.Count < 1) return; + + string index = String.Empty; + string stringData = String.Empty; + byte[] binaryData = null; + int count = EncodeProfileData(collection, isAuthenticated, ref index, ref stringData, ref binaryData); + if (count < 1) return; + + MySqlTransaction txn = null; + // save the encoded profile data to the database + using (MySqlConnection connection = new MySqlConnection(connectionString)) + { + try + { + connection.Open(); + txn = connection.BeginTransaction(); + + // either create a new user or fetch the existing user id + long userId = SchemaManager.CreateOrFetchUserId(connection, username, + app.EnsureId(connection), isAuthenticated); + + MySqlCommand cmd = new MySqlCommand( + @"INSERT INTO my_aspnet_profiles + VALUES (@userId, @index, @stringData, @binaryData, NULL) ON DUPLICATE KEY UPDATE + valueindex=VALUES(valueindex), stringdata=VALUES(stringdata), + binarydata=VALUES(binarydata)", connection); + cmd.Parameters.Clear(); + cmd.Parameters.AddWithValue("@userId", userId); + cmd.Parameters.AddWithValue("@index", index); + cmd.Parameters.AddWithValue("@stringData", stringData); + cmd.Parameters.AddWithValue("@binaryData", binaryData); + count = cmd.ExecuteNonQuery(); + if (count == 0) + throw new Exception(Properties.Resources.ProfileUpdateFailed); + txn.Commit(); + } + catch (Exception ex) + { + if (txn != null) + txn.Rollback(); + throw new ProviderException(Properties.Resources.ProfileUpdateFailed, ex); + } + } + } + + #endregion + + internal static void DeleteUserData(MySqlConnection connection, int userId) + { + MySqlCommand cmd = new MySqlCommand( + "DELETE FROM my_aspnet_profiles WHERE userId=@userId", connection); + cmd.Parameters.AddWithValue("@userId", userId); + cmd.ExecuteNonQuery(); + } + + #region Private Methods + + private void DecodeProfileData(DataRow profileRow, SettingsPropertyValueCollection values) + { + string indexData = (string)profileRow["valueindex"]; + string stringData = (string)profileRow["stringData"]; + byte[] binaryData = (byte[])profileRow["binaryData"]; + + if (indexData == null) return; + + string[] indexes = indexData.Split(':'); + + foreach (string index in indexes) + { + string[] parts = index.Split('/'); + SettingsPropertyValue value = values[parts[0]]; + if (value == null) continue; + + int pos = Int32.Parse(parts[2], CultureInfo.InvariantCulture); + int len = Int32.Parse(parts[3], CultureInfo.InvariantCulture); + if (len == -1) + { + value.PropertyValue = null; + value.IsDirty = false; + value.Deserialized = true; + } + else if (parts[1].Equals("0")) + value.SerializedValue = stringData.Substring(pos, len); + else + { + byte[] buf = new byte[len]; + Buffer.BlockCopy(binaryData, pos, buf, 0, len); + value.SerializedValue = buf; + } + } + } + + private int EncodeProfileData(SettingsPropertyValueCollection collection, bool isAuthenticated, + ref string index, ref string stringData, ref byte[] binaryData) + { + bool itemsToSave = false; + + // first we need to determine if there are any items that need saving + // this is an optimization + foreach (SettingsPropertyValue value in collection) + { + if (!value.IsDirty) continue; + if (value.Property.Attributes["AllowAnonymous"].Equals(false) && + !isAuthenticated) continue; + itemsToSave = true; + break; + } + if (!itemsToSave) return 0; + + StringBuilder indexBuilder = new StringBuilder(); + StringBuilder stringDataBuilder = new StringBuilder(); + MemoryStream binaryBuilder = new MemoryStream(); + int count = 0; + + // ok, we have some values that need to be saved so we go back through + foreach (SettingsPropertyValue value in collection) + { + // if the value has not been written to and is still using the default value + // no need to save it + if (value.UsingDefaultValue && !value.IsDirty) continue; + + // we don't save properties that require the user to be authenticated when the + // current user is not authenticated. + if (value.Property.Attributes["AllowAnonymous"].Equals(false) && + !isAuthenticated) continue; + + count++; + object propValue = value.SerializedValue; + if ((value.Deserialized && value.PropertyValue == null) || + value.SerializedValue == null) + indexBuilder.AppendFormat("{0}//0/-1:", value.Name); + else if (propValue is string) + { + indexBuilder.AppendFormat("{0}/0/{1}/{2}:", value.Name, + stringDataBuilder.Length, (propValue as string).Length); + stringDataBuilder.Append(propValue); + } + else + { + byte[] binaryValue = (byte[])propValue; + indexBuilder.AppendFormat("{0}/1/{1}/{2}:", value.Name, + binaryBuilder.Position, binaryValue.Length); + binaryBuilder.Write(binaryValue, 0, binaryValue.Length); + } + } + index = indexBuilder.ToString(); + stringData = stringDataBuilder.ToString(); + binaryData = binaryBuilder.ToArray(); + return count; + } + + + private ProfileInfoCollection GetProfiles( + ProfileAuthenticationOption authenticationOption, + string usernameToMatch, DateTime userInactiveSinceDate, + int pageIndex, int pageSize, out int totalRecords) + { + List whereClauses = new List(); + + using (MySqlConnection c = new MySqlConnection(connectionString)) + { + c.Open(); + + MySqlCommand cmd = new MySqlCommand( + @"SELECT p.*, u.name, u.isAnonymous, u.lastActivityDate, + LENGTH(p.stringdata) + LENGTH(p.binarydata) AS profilesize + FROM my_aspnet_profiles p + JOIN my_aspnet_users u ON u.id = p.userId + WHERE u.applicationId = @appId", c); + cmd.Parameters.AddWithValue("@appId", app.FetchId(c)); + + if (usernameToMatch != null) + { + cmd.CommandText += " AND u.name LIKE @userName"; + cmd.Parameters.AddWithValue("@userName", usernameToMatch); + } + if (userInactiveSinceDate != DateTime.MinValue) + { + cmd.CommandText += " AND u.lastActivityDate < @lastActivityDate"; + cmd.Parameters.AddWithValue("@lastActivityDate", userInactiveSinceDate); + } + if (authenticationOption == ProfileAuthenticationOption.Anonymous) + cmd.CommandText += " AND u.isAnonymous = 1"; + else if (authenticationOption == ProfileAuthenticationOption.Authenticated) + cmd.CommandText += " AND u.isAnonymous = 0"; + + cmd.CommandText += String.Format(" LIMIT {0},{1}", pageIndex * pageSize, pageSize); + + ProfileInfoCollection pic = new ProfileInfoCollection(); + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + while (reader.Read()) + { + ProfileInfo pi = new ProfileInfo( + reader.GetString("name"), + reader.GetBoolean("isAnonymous"), + reader.GetDateTime("lastActivityDate"), + reader.GetDateTime("lastUpdatedDate"), + reader.GetInt32("profilesize")); + pic.Add(pi); + } + } + cmd.CommandText = "SELECT FOUND_ROWS()"; + totalRecords = Convert.ToInt32(cmd.ExecuteScalar()); + return pic; + } + } + + private static string GetConfigValue(string configValue, string defaultValue) + { + if (string.IsNullOrEmpty(configValue)) + { + return defaultValue; + } + return configValue; + } + + #endregion + + } +} diff --git a/MySql.Web/src/Properties/AssemblyInfo.cs b/MySql.Web/src/Properties/AssemblyInfo.cs index 6751fac2a..cc06abbf3 100644 --- a/MySql.Web/src/Properties/AssemblyInfo.cs +++ b/MySql.Web/src/Properties/AssemblyInfo.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2004, 2023, Oracle and/or its affiliates. +// Copyright © 2004, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySql.Web/src/Properties/Resources.Designer.cs b/MySql.Web/src/Properties/Resources.Designer.cs index 2311964af..095ec407c 100644 --- a/MySql.Web/src/Properties/Resources.Designer.cs +++ b/MySql.Web/src/Properties/Resources.Designer.cs @@ -1,630 +1,630 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.42000 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace MySql.Web.Properties { - using System; - - - /// - /// A strongly-typed resource class, for looking up localized strings, etc. - /// - // This class was auto-generated by the StronglyTypedResourceBuilder - // class via a tool like ResGen or Visual Studio. - // To add or remove a member, edit your .ResX file then rerun ResGen - // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class Resources { - - private static global::System.Resources.ResourceManager resourceMan; - - private static global::System.Globalization.CultureInfo resourceCulture; - - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal Resources() { - } - - /// - /// Returns the cached ResourceManager instance used by this class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager { - get { - if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("MySql.Web.Properties.Resources", typeof(Resources).Assembly); - resourceMan = temp; - } - return resourceMan; - } - } - - /// - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture { - get { - return resourceCulture; - } - set { - resourceCulture = value; - } - } - - /// - /// Looks up a localized string similar to Cannot delete a populated role.. - /// - internal static string CannotDeleteAPopulatedRole { - get { - return ResourceManager.GetString("CannotDeleteAPopulatedRole", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Setting EnablePasswordRetrieval to true when PasswordFormat is Hashed is not supported.. - /// - internal static string CannotRetrieveHashedPasswords { - get { - return ResourceManager.GetString("CannotRetrieveHashedPasswords", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to You cannot specify both a connection string name and a connection string.. - /// - internal static string CannotSpecifyNameAndConnectionString { - get { - return ResourceManager.GetString("CannotSpecifyNameAndConnectionString", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Cannot unencode a hashed password.. - /// - internal static string CannotUnencodeHashedPwd { - get { - return ResourceManager.GetString("CannotUnencodeHashedPwd", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Change password operation was canceled.. - /// - internal static string ChangePasswordCanceled { - get { - return ResourceManager.GetString("ChangePasswordCanceled", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Failed to clear the token for the userid {0} in the table {1} after password update.. - /// - internal static string ClearPassTokenFailed { - get { - return ResourceManager.GetString("ClearPassTokenFailed", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to An unexpected error occurred while creating the role '{0}'.. - /// - internal static string CreateRoleFailed { - get { - return ResourceManager.GetString("CreateRoleFailed", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Failed to delete OAuth Account, combination of provider '{0}' and provider user id '{1}' not found.. - /// - internal static string DeleteOAuthAccountFailed { - get { - return ResourceManager.GetString("DeleteOAuthAccountFailed", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to There was an error during membership provider initilization.. - /// - internal static string ErrorInitOfMembershipProvider { - get { - return ResourceManager.GetString("ErrorInitOfMembershipProvider", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to There was an error during role provider initilization.. - /// - internal static string ErrorInitOfRoleProvider { - get { - return ResourceManager.GetString("ErrorInitOfRoleProvider", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to There was an error during profile provider initilization.. - /// - internal static string ErrorInitProfileProvider { - get { - return ResourceManager.GetString("ErrorInitProfileProvider", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to There was an error resetting the password.. - /// - internal static string ErrorResettingPassword { - get { - return ResourceManager.GetString("ErrorResettingPassword", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Failed to generates the PasswordVerificationToken, update not performed to Database.. - /// - internal static string GeneratePassVerificationTokenFailed { - get { - return ResourceManager.GetString("GeneratePassVerificationTokenFailed", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Role names must not be null or empty.. - /// - internal static string IllegalRoleName { - get { - return ResourceManager.GetString("IllegalRoleName", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to User names must not be null or empty.. - /// - internal static string IllegalUserName { - get { - return ResourceManager.GetString("IllegalUserName", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Incorrect password answer.. - /// - internal static string IncorrectPasswordAnswer { - get { - return ResourceManager.GetString("IncorrectPasswordAnswer", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Please provide a valid value: value provided is null or empty.. - /// - internal static string InvalidArgument { - get { - return ResourceManager.GetString("InvalidArgument", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Some of the values in the arrays received are null or empty, please verify it.. - /// - internal static string InvalidArrayValue { - get { - return ResourceManager.GetString("InvalidArrayValue", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Invalid characters in user name.. - /// - internal static string InvalidCharactersInUserName { - get { - return ResourceManager.GetString("InvalidCharactersInUserName", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to User {0} not found in the table {1}.. - /// - internal static string InvalidUser { - get { - return ResourceManager.GetString("InvalidUser", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Unable to initialize provider. Missing or incorrect schema.. - /// - internal static string MissingOrWrongSchema { - get { - return ResourceManager.GetString("MissingOrWrongSchema", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The mono runtime did not support hashed passwords. Please use clear or encrypted passwords.. - /// - internal static string MonoDoesNotSupportHash { - get { - return ResourceManager.GetString("MonoDoesNotSupportHash", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Change password canceled due to New password validation failure.. - /// - internal static string NewPasswordValidationFailed { - get { - return ResourceManager.GetString("NewPasswordValidationFailed", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to There is no connection string configured.. - /// - internal static string NoConnString { - get { - return ResourceManager.GetString("NoConnString", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Non alpha numeric characters in '{0}' needs to be greater than or equal to '{1}'.. - /// - internal static string NotEnoughNonAlphaNumericInPwd { - get { - return ResourceManager.GetString("NotEnoughNonAlphaNumericInPwd", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Password answer supplied is invalid.. - /// - internal static string PasswordAnswerInvalid { - get { - return ResourceManager.GetString("PasswordAnswerInvalid", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Password exceeds maximum length allowed.. - /// - internal static string PasswordExceedsMaxLength { - get { - return ResourceManager.GetString("PasswordExceedsMaxLength", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Password format not supported.. - /// - internal static string PasswordFormatNotSupported { - get { - return ResourceManager.GetString("PasswordFormatNotSupported", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The length of parameter '{0}' needs to be greater or equal to '{1}'.. - /// - internal static string PasswordNotLongEnough { - get { - return ResourceManager.GetString("PasswordNotLongEnough", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Password question supplied is invalid.. - /// - internal static string PasswordQuestionInvalid { - get { - return ResourceManager.GetString("PasswordQuestionInvalid", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Password answer required for password reset.. - /// - internal static string PasswordRequiredForReset { - get { - return ResourceManager.GetString("PasswordRequiredForReset", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Reset password canceled due to password validation failure.. - /// - internal static string PasswordResetCanceledNotValid { - get { - return ResourceManager.GetString("PasswordResetCanceledNotValid", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Password Reset is not enabled.. - /// - internal static string PasswordResetNotEnabled { - get { - return ResourceManager.GetString("PasswordResetNotEnabled", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Password Retrieval Not Enabled.. - /// - internal static string PasswordRetrievalNotEnabled { - get { - return ResourceManager.GetString("PasswordRetrievalNotEnabled", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to MySqlSimpleMembershipProvider is already initialized and its schema does not match the MySqlMembershipProvider schema.. - /// - internal static string PreviousProviderException { - get { - return ResourceManager.GetString("PreviousProviderException", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Profile update failed.. - /// - internal static string ProfileUpdateFailed { - get { - return ResourceManager.GetString("ProfileUpdateFailed", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The role '{0}' already exists.. - /// - internal static string RoleAlreadyExists { - get { - return ResourceManager.GetString("RoleAlreadyExists", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The role '{0}' is in use.. - /// - internal static string RoleInUse { - get { - return ResourceManager.GetString("RoleInUse", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Role name already exists.. - /// - internal static string RoleNameAlreadyExists { - get { - return ResourceManager.GetString("RoleNameAlreadyExists", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Role name not found.. - /// - internal static string RoleNameNotFound { - get { - return ResourceManager.GetString("RoleNameNotFound", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Failed to save the request token secret value '{0}'.. - /// - internal static string SaveTokenFailed { - get { - return ResourceManager.GetString("SaveTokenFailed", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The MySqlSimpleMembershipProvider is already initialized.. - /// - internal static string SimpleMembershipAlreadyInitialized { - get { - return ResourceManager.GetString("SimpleMembershipAlreadyInitialized", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The membership provider was not initialized, it must be initialized before start using it.. - /// - internal static string SimpleMembershipNotInitialized { - get { - return ResourceManager.GetString("SimpleMembershipNotInitialized", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The MySqlSimpleRoleProvider is already initialized.. - /// - internal static string SimpleRoleAlreadyInitialized { - get { - return ResourceManager.GetString("SimpleRoleAlreadyInitialized", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The connection string name is missing for the MySqlSiteMapProvider. - /// - internal static string SiteMapConnectionStringMissing { - get { - return ResourceManager.GetString("SiteMapConnectionStringMissing", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Unable to create application.. - /// - internal static string UnableToCreateApplication { - get { - return ResourceManager.GetString("UnableToCreateApplication", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Unable to create user.. - /// - internal static string UnableToCreateUser { - get { - return ResourceManager.GetString("UnableToCreateUser", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Unable to lock out user.. - /// - internal static string UnableToLockOutUser { - get { - return ResourceManager.GetString("UnableToLockOutUser", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Unable to retrieve profile data from database.. - /// - internal static string UnableToRetrieveProfileData { - get { - return ResourceManager.GetString("UnableToRetrieveProfileData", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Unable to update failure count. Membership database may be corrupt.. - /// - internal static string UnableToUpdateFailureCount { - get { - return ResourceManager.GetString("UnableToUpdateFailureCount", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Unsupported password format.. - /// - internal static string UnsupportedPasswordFormat { - get { - return ResourceManager.GetString("UnsupportedPasswordFormat", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Failed to update the request token secret value '{0}'.. - /// - internal static string UpdateTokenFailed { - get { - return ResourceManager.GetString("UpdateTokenFailed", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to User {0} already exists.. - /// - internal static string UserAlreadyExists { - get { - return ResourceManager.GetString("UserAlreadyExists", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to UserIdColumn configuration was not initialized.. - /// - internal static string UserIdColumnNotInitialized { - get { - return ResourceManager.GetString("UserIdColumnNotInitialized", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to User is already in role.. - /// - internal static string UserIsAlreadyInRole { - get { - return ResourceManager.GetString("UserIsAlreadyInRole", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The supplied user is locked out.. - /// - internal static string UserIsLockedOut { - get { - return ResourceManager.GetString("UserIsLockedOut", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to UserNameColumn configuration was not initialized.. - /// - internal static string UserNameColumnNotInitialized { - get { - return ResourceManager.GetString("UserNameColumnNotInitialized", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Username not found.. - /// - internal static string UsernameNotFound { - get { - return ResourceManager.GetString("UsernameNotFound", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to User not found int the table {0}.. - /// - internal static string UserNotFound { - get { - return ResourceManager.GetString("UserNotFound", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to User not in role.. - /// - internal static string UserNotInRole { - get { - return ResourceManager.GetString("UserNotInRole", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to UserTableName configuration was not initialized.. - /// - internal static string UserTableNameNotInitilized { - get { - return ResourceManager.GetString("UserTableNameNotInitilized", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Unable to find the table users {0}. Please create it or initialize the MySqlSimpleMembershipProvider with 'createTables=true'.. - /// - internal static string UserTableNotFound { - get { - return ResourceManager.GetString("UserTableNotFound", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The validate password operation was canceled.. - /// - internal static string ValidatePasswordCanceled { - get { - return ResourceManager.GetString("ValidatePasswordCanceled", resourceCulture); - } - } - } -} +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace MySql.Web.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("MySql.Web.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to Cannot delete a populated role.. + /// + internal static string CannotDeleteAPopulatedRole { + get { + return ResourceManager.GetString("CannotDeleteAPopulatedRole", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Setting EnablePasswordRetrieval to true when PasswordFormat is Hashed is not supported.. + /// + internal static string CannotRetrieveHashedPasswords { + get { + return ResourceManager.GetString("CannotRetrieveHashedPasswords", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You cannot specify both a connection string name and a connection string.. + /// + internal static string CannotSpecifyNameAndConnectionString { + get { + return ResourceManager.GetString("CannotSpecifyNameAndConnectionString", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Cannot unencode a hashed password.. + /// + internal static string CannotUnencodeHashedPwd { + get { + return ResourceManager.GetString("CannotUnencodeHashedPwd", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Change password operation was canceled.. + /// + internal static string ChangePasswordCanceled { + get { + return ResourceManager.GetString("ChangePasswordCanceled", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Failed to clear the token for the userid {0} in the table {1} after password update.. + /// + internal static string ClearPassTokenFailed { + get { + return ResourceManager.GetString("ClearPassTokenFailed", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to An unexpected error occurred while creating the role '{0}'.. + /// + internal static string CreateRoleFailed { + get { + return ResourceManager.GetString("CreateRoleFailed", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Failed to delete OAuth Account, combination of provider '{0}' and provider user id '{1}' not found.. + /// + internal static string DeleteOAuthAccountFailed { + get { + return ResourceManager.GetString("DeleteOAuthAccountFailed", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to There was an error during membership provider initilization.. + /// + internal static string ErrorInitOfMembershipProvider { + get { + return ResourceManager.GetString("ErrorInitOfMembershipProvider", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to There was an error during role provider initilization.. + /// + internal static string ErrorInitOfRoleProvider { + get { + return ResourceManager.GetString("ErrorInitOfRoleProvider", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to There was an error during profile provider initilization.. + /// + internal static string ErrorInitProfileProvider { + get { + return ResourceManager.GetString("ErrorInitProfileProvider", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to There was an error resetting the password.. + /// + internal static string ErrorResettingPassword { + get { + return ResourceManager.GetString("ErrorResettingPassword", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Failed to generates the PasswordVerificationToken, update not performed to Database.. + /// + internal static string GeneratePassVerificationTokenFailed { + get { + return ResourceManager.GetString("GeneratePassVerificationTokenFailed", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Role names must not be null or empty.. + /// + internal static string IllegalRoleName { + get { + return ResourceManager.GetString("IllegalRoleName", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to User names must not be null or empty.. + /// + internal static string IllegalUserName { + get { + return ResourceManager.GetString("IllegalUserName", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Incorrect password answer.. + /// + internal static string IncorrectPasswordAnswer { + get { + return ResourceManager.GetString("IncorrectPasswordAnswer", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Please provide a valid value: value provided is null or empty.. + /// + internal static string InvalidArgument { + get { + return ResourceManager.GetString("InvalidArgument", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Some of the values in the arrays received are null or empty, please verify it.. + /// + internal static string InvalidArrayValue { + get { + return ResourceManager.GetString("InvalidArrayValue", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Invalid characters in user name.. + /// + internal static string InvalidCharactersInUserName { + get { + return ResourceManager.GetString("InvalidCharactersInUserName", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to User {0} not found in the table {1}.. + /// + internal static string InvalidUser { + get { + return ResourceManager.GetString("InvalidUser", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unable to initialize provider. Missing or incorrect schema.. + /// + internal static string MissingOrWrongSchema { + get { + return ResourceManager.GetString("MissingOrWrongSchema", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The mono runtime did not support hashed passwords. Please use clear or encrypted passwords.. + /// + internal static string MonoDoesNotSupportHash { + get { + return ResourceManager.GetString("MonoDoesNotSupportHash", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Change password canceled due to New password validation failure.. + /// + internal static string NewPasswordValidationFailed { + get { + return ResourceManager.GetString("NewPasswordValidationFailed", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to There is no connection string configured.. + /// + internal static string NoConnString { + get { + return ResourceManager.GetString("NoConnString", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Non alpha numeric characters in '{0}' needs to be greater than or equal to '{1}'.. + /// + internal static string NotEnoughNonAlphaNumericInPwd { + get { + return ResourceManager.GetString("NotEnoughNonAlphaNumericInPwd", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Password answer supplied is invalid.. + /// + internal static string PasswordAnswerInvalid { + get { + return ResourceManager.GetString("PasswordAnswerInvalid", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Password exceeds maximum length allowed.. + /// + internal static string PasswordExceedsMaxLength { + get { + return ResourceManager.GetString("PasswordExceedsMaxLength", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Password format not supported.. + /// + internal static string PasswordFormatNotSupported { + get { + return ResourceManager.GetString("PasswordFormatNotSupported", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The length of parameter '{0}' needs to be greater or equal to '{1}'.. + /// + internal static string PasswordNotLongEnough { + get { + return ResourceManager.GetString("PasswordNotLongEnough", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Password question supplied is invalid.. + /// + internal static string PasswordQuestionInvalid { + get { + return ResourceManager.GetString("PasswordQuestionInvalid", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Password answer required for password reset.. + /// + internal static string PasswordRequiredForReset { + get { + return ResourceManager.GetString("PasswordRequiredForReset", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Reset password canceled due to password validation failure.. + /// + internal static string PasswordResetCanceledNotValid { + get { + return ResourceManager.GetString("PasswordResetCanceledNotValid", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Password Reset is not enabled.. + /// + internal static string PasswordResetNotEnabled { + get { + return ResourceManager.GetString("PasswordResetNotEnabled", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Password Retrieval Not Enabled.. + /// + internal static string PasswordRetrievalNotEnabled { + get { + return ResourceManager.GetString("PasswordRetrievalNotEnabled", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to MySqlSimpleMembershipProvider is already initialized and its schema does not match the MySqlMembershipProvider schema.. + /// + internal static string PreviousProviderException { + get { + return ResourceManager.GetString("PreviousProviderException", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Profile update failed.. + /// + internal static string ProfileUpdateFailed { + get { + return ResourceManager.GetString("ProfileUpdateFailed", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The role '{0}' already exists.. + /// + internal static string RoleAlreadyExists { + get { + return ResourceManager.GetString("RoleAlreadyExists", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The role '{0}' is in use.. + /// + internal static string RoleInUse { + get { + return ResourceManager.GetString("RoleInUse", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Role name already exists.. + /// + internal static string RoleNameAlreadyExists { + get { + return ResourceManager.GetString("RoleNameAlreadyExists", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Role name not found.. + /// + internal static string RoleNameNotFound { + get { + return ResourceManager.GetString("RoleNameNotFound", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Failed to save the request token secret value '{0}'.. + /// + internal static string SaveTokenFailed { + get { + return ResourceManager.GetString("SaveTokenFailed", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The MySqlSimpleMembershipProvider is already initialized.. + /// + internal static string SimpleMembershipAlreadyInitialized { + get { + return ResourceManager.GetString("SimpleMembershipAlreadyInitialized", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The membership provider was not initialized, it must be initialized before start using it.. + /// + internal static string SimpleMembershipNotInitialized { + get { + return ResourceManager.GetString("SimpleMembershipNotInitialized", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The MySqlSimpleRoleProvider is already initialized.. + /// + internal static string SimpleRoleAlreadyInitialized { + get { + return ResourceManager.GetString("SimpleRoleAlreadyInitialized", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The connection string name is missing for the MySqlSiteMapProvider. + /// + internal static string SiteMapConnectionStringMissing { + get { + return ResourceManager.GetString("SiteMapConnectionStringMissing", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unable to create application.. + /// + internal static string UnableToCreateApplication { + get { + return ResourceManager.GetString("UnableToCreateApplication", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unable to create user.. + /// + internal static string UnableToCreateUser { + get { + return ResourceManager.GetString("UnableToCreateUser", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unable to lock out user.. + /// + internal static string UnableToLockOutUser { + get { + return ResourceManager.GetString("UnableToLockOutUser", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unable to retrieve profile data from database.. + /// + internal static string UnableToRetrieveProfileData { + get { + return ResourceManager.GetString("UnableToRetrieveProfileData", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unable to update failure count. Membership database may be corrupt.. + /// + internal static string UnableToUpdateFailureCount { + get { + return ResourceManager.GetString("UnableToUpdateFailureCount", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unsupported password format.. + /// + internal static string UnsupportedPasswordFormat { + get { + return ResourceManager.GetString("UnsupportedPasswordFormat", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Failed to update the request token secret value '{0}'.. + /// + internal static string UpdateTokenFailed { + get { + return ResourceManager.GetString("UpdateTokenFailed", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to User {0} already exists.. + /// + internal static string UserAlreadyExists { + get { + return ResourceManager.GetString("UserAlreadyExists", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to UserIdColumn configuration was not initialized.. + /// + internal static string UserIdColumnNotInitialized { + get { + return ResourceManager.GetString("UserIdColumnNotInitialized", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to User is already in role.. + /// + internal static string UserIsAlreadyInRole { + get { + return ResourceManager.GetString("UserIsAlreadyInRole", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The supplied user is locked out.. + /// + internal static string UserIsLockedOut { + get { + return ResourceManager.GetString("UserIsLockedOut", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to UserNameColumn configuration was not initialized.. + /// + internal static string UserNameColumnNotInitialized { + get { + return ResourceManager.GetString("UserNameColumnNotInitialized", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Username not found.. + /// + internal static string UsernameNotFound { + get { + return ResourceManager.GetString("UsernameNotFound", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to User not found int the table {0}.. + /// + internal static string UserNotFound { + get { + return ResourceManager.GetString("UserNotFound", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to User not in role.. + /// + internal static string UserNotInRole { + get { + return ResourceManager.GetString("UserNotInRole", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to UserTableName configuration was not initialized.. + /// + internal static string UserTableNameNotInitilized { + get { + return ResourceManager.GetString("UserTableNameNotInitilized", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unable to find the table users {0}. Please create it or initialize the MySqlSimpleMembershipProvider with 'createTables=true'.. + /// + internal static string UserTableNotFound { + get { + return ResourceManager.GetString("UserTableNotFound", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The validate password operation was canceled.. + /// + internal static string ValidatePasswordCanceled { + get { + return ResourceManager.GetString("ValidatePasswordCanceled", resourceCulture); + } + } + } +} diff --git a/MySql.Web/src/Properties/schema1.sql b/MySql.Web/src/Properties/schema1.sql index 0b253cb86..ec80889ac 100644 --- a/MySql.Web/src/Properties/schema1.sql +++ b/MySql.Web/src/Properties/schema1.sql @@ -1,33 +1,33 @@ -CREATE TABLE mysql_Membership(`PKID` varchar(36) NOT NULL, - Username varchar(255) NOT NULL, - ApplicationName varchar(255) NOT NULL, - Email varchar(128) NOT NULL, - Comment varchar(255) default NULL, - Password varchar(128) NOT NULL, - PasswordQuestion varchar(255) default NULL, - PasswordAnswer varchar(255) default NULL, - IsApproved tinyint(1) default NULL, - LastActivityDate datetime default NULL, - LastLoginDate datetime default NULL, - LastPasswordChangedDate datetime default NULL, - CreationDate datetime default NULL, - IsOnline tinyint(1) default NULL, - IsLockedOut tinyint(1) default NULL, - LastLockedOutDate datetime default NULL, - FailedPasswordAttemptCount int(10) unsigned default NULL, - FailedPasswordAttemptWindowStart datetime default NULL, - FailedPasswordAnswerAttemptCount int(10) unsigned default NULL, - FailedPasswordAnswerAttemptWindowStart datetime default NULL, - PRIMARY KEY (`PKID`)) DEFAULT CHARSET=latin1 COMMENT='1'; - -CREATE TABLE mysql_UsersInRoles(`Username` varchar(255) NOT NULL, - `Rolename` varchar(255) NOT NULL, `ApplicationName` varchar(255) NOT NULL, - KEY `Username` (`Username`,`Rolename`,`ApplicationName`) - ) DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC; - -CREATE TABLE mysql_Roles(`Rolename` varchar(255) NOT NULL, - `ApplicationName` varchar(255) NOT NULL, - KEY `Rolename` (`Rolename`,`ApplicationName`) - ) DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC; - +CREATE TABLE mysql_Membership(`PKID` varchar(36) NOT NULL, + Username varchar(255) NOT NULL, + ApplicationName varchar(255) NOT NULL, + Email varchar(128) NOT NULL, + Comment varchar(255) default NULL, + Password varchar(128) NOT NULL, + PasswordQuestion varchar(255) default NULL, + PasswordAnswer varchar(255) default NULL, + IsApproved tinyint(1) default NULL, + LastActivityDate datetime default NULL, + LastLoginDate datetime default NULL, + LastPasswordChangedDate datetime default NULL, + CreationDate datetime default NULL, + IsOnline tinyint(1) default NULL, + IsLockedOut tinyint(1) default NULL, + LastLockedOutDate datetime default NULL, + FailedPasswordAttemptCount int(10) unsigned default NULL, + FailedPasswordAttemptWindowStart datetime default NULL, + FailedPasswordAnswerAttemptCount int(10) unsigned default NULL, + FailedPasswordAnswerAttemptWindowStart datetime default NULL, + PRIMARY KEY (`PKID`)) DEFAULT CHARSET=latin1 COMMENT='1'; + +CREATE TABLE mysql_UsersInRoles(`Username` varchar(255) NOT NULL, + `Rolename` varchar(255) NOT NULL, `ApplicationName` varchar(255) NOT NULL, + KEY `Username` (`Username`,`Rolename`,`ApplicationName`) + ) DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC; + +CREATE TABLE mysql_Roles(`Rolename` varchar(255) NOT NULL, + `ApplicationName` varchar(255) NOT NULL, + KEY `Rolename` (`Rolename`,`ApplicationName`) + ) DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC; + \ No newline at end of file diff --git a/MySql.Web/src/Properties/schema10.sql b/MySql.Web/src/Properties/schema10.sql index 08f758ccc..3bbc8dcde 100644 --- a/MySql.Web/src/Properties/schema10.sql +++ b/MySql.Web/src/Properties/schema10.sql @@ -1,23 +1,23 @@ -CREATE TABLE my_aspnet_personalizationperuser( -id INT PRIMARY KEY AUTO_INCREMENT, -applicationId INT NOT NULL, -pathId VARCHAR(36) DEFAULT NULL, -userId INT, -pageSettings BLOB NOT NULL, -lastUpdatedDate DATETIME NOT NULL)DEFAULT CHARSET=latin1 ; - - -CREATE TABLE my_aspnet_personalizationallusers( -pathId VARCHAR(36) PRIMARY KEY, -pageSettings BLOB NOT NULL, -lastUpdatedDate DATETIME NOT NULL)DEFAULT CHARSET=latin1 ; - -CREATE TABLE my_aspnet_paths -( -applicationId INT NOT NULL, -pathId VARCHAR(36) PRIMARY KEY, -path VARCHAR(256) NOT NULL, -loweredPath VARCHAR(256) NOT NULL -)DEFAULT CHARSET=latin1 ; - +CREATE TABLE my_aspnet_personalizationperuser( +id INT PRIMARY KEY AUTO_INCREMENT, +applicationId INT NOT NULL, +pathId VARCHAR(36) DEFAULT NULL, +userId INT, +pageSettings BLOB NOT NULL, +lastUpdatedDate DATETIME NOT NULL)DEFAULT CHARSET=latin1 ; + + +CREATE TABLE my_aspnet_personalizationallusers( +pathId VARCHAR(36) PRIMARY KEY, +pageSettings BLOB NOT NULL, +lastUpdatedDate DATETIME NOT NULL)DEFAULT CHARSET=latin1 ; + +CREATE TABLE my_aspnet_paths +( +applicationId INT NOT NULL, +pathId VARCHAR(36) PRIMARY KEY, +path VARCHAR(256) NOT NULL, +loweredPath VARCHAR(256) NOT NULL +)DEFAULT CHARSET=latin1 ; + UPDATE my_aspnet_schemaversion SET version=10; \ No newline at end of file diff --git a/MySql.Web/src/Properties/schema2.sql b/MySql.Web/src/Properties/schema2.sql index a34b8d152..69f091f8a 100644 --- a/MySql.Web/src/Properties/schema2.sql +++ b/MySql.Web/src/Properties/schema2.sql @@ -1,7 +1,7 @@ - ALTER TABLE mysql_Membership - ADD PasswordKey char(32) AFTER Password, - ADD PasswordFormat tinyint AFTER PasswordKey, - CHANGE Email Email VARCHAR(128), COMMENT='2'; - - + ALTER TABLE mysql_Membership + ADD PasswordKey char(32) AFTER Password, + ADD PasswordFormat tinyint AFTER PasswordKey, + CHANGE Email Email VARCHAR(128), COMMENT='2'; + + \ No newline at end of file diff --git a/MySql.Web/src/Properties/schema3.sql b/MySql.Web/src/Properties/schema3.sql index 8016b4b07..ee38a1017 100644 --- a/MySql.Web/src/Properties/schema3.sql +++ b/MySql.Web/src/Properties/schema3.sql @@ -1,85 +1,85 @@ -/* Provider schema block -- version 3 */ - -/* create our application and user tables */ -create table my_aspnet_applications(id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(256), description VARCHAR(256)); -create table my_aspnet_users(id INT PRIMARY KEY AUTO_INCREMENT, - applicationId INT NOT NULL, name VARCHAR(256) NOT NULL, - isAnonymous TINYINT(1) NOT NULL DEFAULT 1, lastActivityDate DATETIME); -create table my_aspnet_profiles(userId INT PRIMARY KEY, valueindex longtext, stringdata longtext, binarydata longblob, lastUpdatedDate timestamp); -create table my_aspnet_schemaversion(version INT); - -insert into my_aspnet_schemaversion VALUES (3); - -/* now we need to migrate all applications into our apps table */ -insert into my_aspnet_applications (name) select ApplicationName from mysql_Membership UNION select ApplicationName from mysql_UsersInRoles; - -/* now we make our changes to the existing tables */ -alter table mysql_Membership - rename to my_aspnet_membership, - drop primary key, - drop column pkid, - drop column IsOnline, - add column userId INT FIRST, - add column applicationId INT AFTER userId; - -alter table mysql_Roles - rename to my_aspnet_roles, - drop key Rolename, - add column id INT PRIMARY KEY AUTO_INCREMENT FIRST, - add column applicationId INT NOT NULL AFTER id; - -alter table mysql_UsersInRoles - drop key Username, - rename to my_aspnet_usersinroles, - add column userId INT FIRST, - add column roleId INT AFTER userId, - add column applicationId INT AFTER roleId; - -ALTER TABLE my_aspnet_membership CONVERT TO CHARACTER SET DEFAULT; -ALTER TABLE my_aspnet_roles CONVERT TO CHARACTER SET DEFAULT; -ALTER TABLE my_aspnet_usersinroles CONVERT TO CHARACTER SET DEFAULT; - -/* these next lines set the application Id on our tables appropriately */ -update my_aspnet_membership m, my_aspnet_applications a set m.applicationId = a.id where a.name=m.ApplicationName; -update my_aspnet_roles r, my_aspnet_applications a set r.applicationId = a.id where a.name=r.ApplicationName; -update my_aspnet_usersinroles u, my_aspnet_applications a set u.applicationId = a.id where a.name=u.ApplicationName; - -/* now merge our usernames into our users table */ -insert into my_aspnet_users (applicationId, name) - select applicationId, Username from my_aspnet_membership - UNION select applicationId, Username from my_aspnet_usersinroles; - -/* now set the user ids in our tables accordingly */ -update my_aspnet_membership m, my_aspnet_users u set m.userId = u.id where u.name=m.Username AND u.applicationId=m.applicationId; -update my_aspnet_usersinroles r, my_aspnet_users u set r.userId = u.id where u.name=r.Username AND u.applicationId=r.applicationId; - -/* now update the isanonymous and last activity date fields for the users */ -update my_aspnet_users u, my_aspnet_membership m - set u.isAnonymous=0, u.lastActivityDate=m.LastActivityDate - where u.name = m.Username; - -/* make final changes to our tables */ -alter table my_aspnet_membership - drop column Username, - drop column ApplicationName, - drop column applicationId, - add primary key (userId); - -/* next we set our role id values appropriately */ -update my_aspnet_usersinroles u, my_aspnet_roles r set u.roleId = r.id where u.Rolename = r.Rolename and r.applicationId=u.applicationId; - -/* now we make the final changes to our roles tables */ -alter table my_aspnet_roles - drop column ApplicationName, - change column Rolename name VARCHAR(255) NOT NULL; - -alter table my_aspnet_usersinroles - drop column ApplicationName, - drop column applicationId, - drop column Username, - drop column Rolename, - add primary key (userId, roleId); - - - +/* Provider schema block -- version 3 */ + +/* create our application and user tables */ +create table my_aspnet_applications(id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(256), description VARCHAR(256)); +create table my_aspnet_users(id INT PRIMARY KEY AUTO_INCREMENT, + applicationId INT NOT NULL, name VARCHAR(256) NOT NULL, + isAnonymous TINYINT(1) NOT NULL DEFAULT 1, lastActivityDate DATETIME); +create table my_aspnet_profiles(userId INT PRIMARY KEY, valueindex longtext, stringdata longtext, binarydata longblob, lastUpdatedDate timestamp); +create table my_aspnet_schemaversion(version INT); + +insert into my_aspnet_schemaversion VALUES (3); + +/* now we need to migrate all applications into our apps table */ +insert into my_aspnet_applications (name) select ApplicationName from mysql_Membership UNION select ApplicationName from mysql_UsersInRoles; + +/* now we make our changes to the existing tables */ +alter table mysql_Membership + rename to my_aspnet_membership, + drop primary key, + drop column pkid, + drop column IsOnline, + add column userId INT FIRST, + add column applicationId INT AFTER userId; + +alter table mysql_Roles + rename to my_aspnet_roles, + drop key Rolename, + add column id INT PRIMARY KEY AUTO_INCREMENT FIRST, + add column applicationId INT NOT NULL AFTER id; + +alter table mysql_UsersInRoles + drop key Username, + rename to my_aspnet_usersinroles, + add column userId INT FIRST, + add column roleId INT AFTER userId, + add column applicationId INT AFTER roleId; + +ALTER TABLE my_aspnet_membership CONVERT TO CHARACTER SET DEFAULT; +ALTER TABLE my_aspnet_roles CONVERT TO CHARACTER SET DEFAULT; +ALTER TABLE my_aspnet_usersinroles CONVERT TO CHARACTER SET DEFAULT; + +/* these next lines set the application Id on our tables appropriately */ +update my_aspnet_membership m, my_aspnet_applications a set m.applicationId = a.id where a.name=m.ApplicationName; +update my_aspnet_roles r, my_aspnet_applications a set r.applicationId = a.id where a.name=r.ApplicationName; +update my_aspnet_usersinroles u, my_aspnet_applications a set u.applicationId = a.id where a.name=u.ApplicationName; + +/* now merge our usernames into our users table */ +insert into my_aspnet_users (applicationId, name) + select applicationId, Username from my_aspnet_membership + UNION select applicationId, Username from my_aspnet_usersinroles; + +/* now set the user ids in our tables accordingly */ +update my_aspnet_membership m, my_aspnet_users u set m.userId = u.id where u.name=m.Username AND u.applicationId=m.applicationId; +update my_aspnet_usersinroles r, my_aspnet_users u set r.userId = u.id where u.name=r.Username AND u.applicationId=r.applicationId; + +/* now update the isanonymous and last activity date fields for the users */ +update my_aspnet_users u, my_aspnet_membership m + set u.isAnonymous=0, u.lastActivityDate=m.LastActivityDate + where u.name = m.Username; + +/* make final changes to our tables */ +alter table my_aspnet_membership + drop column Username, + drop column ApplicationName, + drop column applicationId, + add primary key (userId); + +/* next we set our role id values appropriately */ +update my_aspnet_usersinroles u, my_aspnet_roles r set u.roleId = r.id where u.Rolename = r.Rolename and r.applicationId=u.applicationId; + +/* now we make the final changes to our roles tables */ +alter table my_aspnet_roles + drop column ApplicationName, + change column Rolename name VARCHAR(255) NOT NULL; + +alter table my_aspnet_usersinroles + drop column ApplicationName, + drop column applicationId, + drop column Username, + drop column Rolename, + add primary key (userId, roleId); + + + \ No newline at end of file diff --git a/MySql.Web/src/Properties/schema4.sql b/MySql.Web/src/Properties/schema4.sql index 4f91e3145..1470878dd 100644 --- a/MySql.Web/src/Properties/schema4.sql +++ b/MySql.Web/src/Properties/schema4.sql @@ -1,5 +1,5 @@ -ALTER TABLE my_aspnet_membership CONVERT TO CHARACTER SET DEFAULT; -ALTER TABLE my_aspnet_roles CONVERT TO CHARACTER SET DEFAULT; -ALTER TABLE my_aspnet_usersinroles CONVERT TO CHARACTER SET DEFAULT; - -UPDATE my_aspnet_schemaversion SET version=4 WHERE version=3; +ALTER TABLE my_aspnet_membership CONVERT TO CHARACTER SET DEFAULT; +ALTER TABLE my_aspnet_roles CONVERT TO CHARACTER SET DEFAULT; +ALTER TABLE my_aspnet_usersinroles CONVERT TO CHARACTER SET DEFAULT; + +UPDATE my_aspnet_schemaversion SET version=4 WHERE version=3; diff --git a/MySql.Web/src/Properties/schema5.sql b/MySql.Web/src/Properties/schema5.sql index 39e1f6ca1..d1708c5a6 100644 --- a/MySql.Web/src/Properties/schema5.sql +++ b/MySql.Web/src/Properties/schema5.sql @@ -1,30 +1,30 @@ -CREATE TABLE my_aspnet_sessions -( - SessionId varchar(191) NOT NULL, - ApplicationId int NOT NULL, - Created datetime NOT NULL, - Expires datetime NOT NULL, - LockDate datetime NOT NULL, - LockId int NOT NULL, - Timeout int NOT NULL, - Locked tinyint(1) NOT NULL, - SessionItems BLOB, - Flags int NOT NULL, - primary key (SessionId,ApplicationId) -) DEFAULT CHARSET=latin1; - -/* - Cleaning up timed out sessions. - In 5.1 events provide a support for periodic jobs. - In older version we need a do-it-yourself event. -*/ -CREATE TABLE my_aspnet_sessioncleanup -( - LastRun datetime NOT NULL, - IntervalMinutes int NOT NULL -); - -INSERT INTO my_aspnet_sessioncleanup(LastRun,IntervalMinutes) values(NOW(), 10); - -UPDATE my_aspnet_schemaversion SET version=5; - +CREATE TABLE my_aspnet_sessions +( + SessionId varchar(191) NOT NULL, + ApplicationId int NOT NULL, + Created datetime NOT NULL, + Expires datetime NOT NULL, + LockDate datetime NOT NULL, + LockId int NOT NULL, + Timeout int NOT NULL, + Locked tinyint(1) NOT NULL, + SessionItems BLOB, + Flags int NOT NULL, + primary key (SessionId,ApplicationId) +) DEFAULT CHARSET=latin1; + +/* + Cleaning up timed out sessions. + In 5.1 events provide a support for periodic jobs. + In older version we need a do-it-yourself event. +*/ +CREATE TABLE my_aspnet_sessioncleanup +( + LastRun datetime NOT NULL, + IntervalMinutes int NOT NULL +); + +INSERT INTO my_aspnet_sessioncleanup(LastRun,IntervalMinutes) values(NOW(), 10); + +UPDATE my_aspnet_schemaversion SET version=5; + diff --git a/MySql.Web/src/Properties/schema6.sql b/MySql.Web/src/Properties/schema6.sql index 6147d16f3..58aad3cd1 100644 --- a/MySql.Web/src/Properties/schema6.sql +++ b/MySql.Web/src/Properties/schema6.sql @@ -1,4 +1,4 @@ -ALTER TABLE my_aspnet_sessions CONVERT TO CHARACTER SET DEFAULT; -ALTER TABLE my_aspnet_sessions MODIFY SessionItems LONGBLOB; - -UPDATE my_aspnet_schemaversion SET version=6; +ALTER TABLE my_aspnet_sessions CONVERT TO CHARACTER SET DEFAULT; +ALTER TABLE my_aspnet_sessions MODIFY SessionItems LONGBLOB; + +UPDATE my_aspnet_schemaversion SET version=6; diff --git a/MySql.Web/src/Properties/schema7.sql b/MySql.Web/src/Properties/schema7.sql index 0708c129e..be4a9691b 100644 --- a/MySql.Web/src/Properties/schema7.sql +++ b/MySql.Web/src/Properties/schema7.sql @@ -1,11 +1,11 @@ -RENAME TABLE my_aspnet_Applications TO my_aspnet_applications; -RENAME TABLE my_aspnet_Membership TO my_aspnet_membership; -RENAME TABLE my_aspnet_Profiles TO my_aspnet_profiles; -RENAME TABLE my_aspnet_Roles TO my_aspnet_roles; -RENAME TABLE my_aspnet_SchemaVersion TO my_aspnet_schemaversion; -RENAME TABLE my_aspnet_SessionCleanup TO my_aspnet_sessioncleanup; -RENAME TABLE my_aspnet_Sessions TO my_aspnet_sessions; -RENAME TABLE my_aspnet_Users TO my_aspnet_users; -RENAME TABLE my_aspnet_UsersInRoles TO my_aspnet_usersinroles; - +RENAME TABLE my_aspnet_Applications TO my_aspnet_applications; +RENAME TABLE my_aspnet_Membership TO my_aspnet_membership; +RENAME TABLE my_aspnet_Profiles TO my_aspnet_profiles; +RENAME TABLE my_aspnet_Roles TO my_aspnet_roles; +RENAME TABLE my_aspnet_SchemaVersion TO my_aspnet_schemaversion; +RENAME TABLE my_aspnet_SessionCleanup TO my_aspnet_sessioncleanup; +RENAME TABLE my_aspnet_Sessions TO my_aspnet_sessions; +RENAME TABLE my_aspnet_Users TO my_aspnet_users; +RENAME TABLE my_aspnet_UsersInRoles TO my_aspnet_usersinroles; + UPDATE my_aspnet_schemaversion SET version=7; \ No newline at end of file diff --git a/MySql.Web/src/Properties/schema8.sql b/MySql.Web/src/Properties/schema8.sql index 108026f76..8fcc73642 100644 --- a/MySql.Web/src/Properties/schema8.sql +++ b/MySql.Web/src/Properties/schema8.sql @@ -1,6 +1,6 @@ -DELETE FROM my_aspnet_sessioncleanup; - -ALTER TABLE my_aspnet_sessioncleanup ADD ApplicationId INT NOT NULL; -ALTER TABLE my_aspnet_sessioncleanup ADD Primary Key (ApplicationId); - +DELETE FROM my_aspnet_sessioncleanup; + +ALTER TABLE my_aspnet_sessioncleanup ADD ApplicationId INT NOT NULL; +ALTER TABLE my_aspnet_sessioncleanup ADD Primary Key (ApplicationId); + UPDATE my_aspnet_schemaversion SET version=8; \ No newline at end of file diff --git a/MySql.Web/src/RoleProvider.cs b/MySql.Web/src/RoleProvider.cs index ac441448c..2cd289d55 100644 --- a/MySql.Web/src/RoleProvider.cs +++ b/MySql.Web/src/RoleProvider.cs @@ -1,643 +1,643 @@ -// Copyright (c) 2004, 2021, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -// This code was contributed by Sean Wright (srwright@alcor.concordia.ca) on 2007-01-12 -// The copyright was assigned and transferred under the terms of -// the MySQL Contributor License Agreement (CLA) - -using MySql.Data.MySqlClient; -using MySql.Web.Common; -using MySql.Web.General; -using System; -using System.Collections.Generic; -using System.Collections.Specialized; -using System.Configuration.Provider; -using System.Diagnostics; -using System.Web.Hosting; -using System.Web.Security; - -namespace MySql.Web.Security -{ - /// - /// Manages storage of role membership information for an ASP.NET application in a MySQL database. - /// - public sealed class MySQLRoleProvider : RoleProvider - { - private string eventSource = "MySQLRoleProvider"; - private string eventLog = "Application"; - private string exceptionMessage = "An exception occurred. Please check the Event Log."; - private string connectionString; - private bool pWriteExceptionsToEventLog = false; - private Application app; - - /// - /// Initializes the provider. - /// - /// The friendly name of the provider. - /// A collection of the name/value pairs representing the provider-specific attributes specified in the configuration for this provider. - /// The name of the provider is null. - /// The name of the provider has a length of zero. - /// An attempt is made to call on a provider after the provider has already been initialized. - public override void Initialize(string name, NameValueCollection config) - { - if (config == null) - { - throw new ArgumentNullException("config"); - } - if (name == null || name.Length == 0) - { - name = "MySQLRoleProvider"; - } - if (string.IsNullOrEmpty(config["description"])) - { - config.Remove("description"); - config.Add("description", "MySQL Role provider"); - } - base.Initialize(name, config); - - string applicationName = HostingEnvironment.ApplicationVirtualPath; - if (!String.IsNullOrEmpty(config["applicationName"])) - applicationName = config["applicationName"]; - - if (!(config["writeExceptionsToEventLog"] == null)) - { - if (config["writeExceptionsToEventLog"].ToUpper() == "TRUE") - { - pWriteExceptionsToEventLog = true; - } - } - - connectionString = ConfigUtility.GetConnectionString(config); - if (String.IsNullOrEmpty(connectionString)) return; - - // make sure our schema is up to date - SchemaManager.CheckSchema(connectionString, config); - - app = new Application(applicationName, Description); - } - - #region Properties - - /// - /// Gets or sets the name of the application to store and retrieve role information for. - /// - /// The name of the application to store and retrieve role information for. - /// - /// - /// roleManager defaultProvider = "MySqlProvider" - /// enabled="true"> - /// providers> - /// add - /// name = "MySqlProvider" - /// type="MySql.Web.Security.MySQLRoleProvider" - /// connectionStringName="LocalMySqlServices" - /// writeExceptionsToEventLog="false" - /// applicationName="MyApplication" /> - /// /providers> - /// roleManager> - /// - /// - public override string ApplicationName - { - get { return app.Name; } - set { app.Name = value; } - } - - /// - /// Gets or sets a value indicating whether exceptions should be written to the event log. - /// - /// - /// true if exceptions should be written to the event log; otherwise, false. - /// - /// - /// - /// roleManager defaultProvider = "MySqlProvider" - /// enabled="true"> - /// providers> - /// add - /// name = "MySqlProvider" - /// type="MySql.Web.Security.MySQLRoleProvider" - /// connectionStringName="LocalMySqlServices" - /// writeExceptionsToEventLog="false" - /// applicationName="MyApplication" /> - /// /providers> - /// roleManager> - /// - /// - public bool WriteExceptionsToEventLog - { - get { return pWriteExceptionsToEventLog; } - set { pWriteExceptionsToEventLog = value; } - } - - #endregion - - #region Public Methods - - /// - /// Adds the users to the specified roles. - /// - /// The user names. - /// The role names. - public override void AddUsersToRoles(string[] usernames, string[] rolenames) - { - if (rolenames == null || rolenames.Length == 0) return; - if (usernames == null || usernames.Length == 0) return; - - foreach (string rolename in rolenames) - { - if (String.IsNullOrEmpty(rolename)) - throw new ArgumentException(Properties.Resources.IllegalRoleName, "rolenames"); - if (!RoleExists(rolename)) - throw new ProviderException(Properties.Resources.RoleNameNotFound); - } - - foreach (string username in usernames) - { - if (String.IsNullOrEmpty(username)) - throw new ArgumentException(Properties.Resources.IllegalUserName, "usernames"); - if (username.IndexOf(',') != -1) - throw new ArgumentException(Properties.Resources.InvalidCharactersInUserName); - - foreach (string rolename in rolenames) - { - if (IsUserInRole(username, rolename)) - throw new ProviderException(Properties.Resources.UserIsAlreadyInRole); - } - } - - using (MySqlConnection connection = new MySqlConnection(connectionString)) - { - MySqlTransaction txn = null; - try - { - connection.Open(); - txn = connection.BeginTransaction(); - MySqlCommand cmd = new MySqlCommand( - "INSERT INTO my_aspnet_usersinroles VALUES(@userId, @roleId)", connection); - cmd.Parameters.Add("@userId", MySqlDbType.Int32); - cmd.Parameters.Add("@roleId", MySqlDbType.Int32); - foreach (string username in usernames) - { - // either create a new user or fetch the existing user id - long userId = SchemaManager.CreateOrFetchUserId(connection, - username, app.FetchId(connection), true); - foreach (string rolename in rolenames) - { - int roleId = GetRoleId(connection, rolename); - cmd.Parameters[0].Value = userId; - cmd.Parameters[1].Value = roleId; - cmd.ExecuteNonQuery(); - } - } - txn.Commit(); - } - catch (Exception ex) - { - if (txn != null) - txn.Rollback(); - if (WriteExceptionsToEventLog) - WriteToEventLog(ex, "AddUsersToRoles"); - throw; - } - } - } - - /// - /// Creates the specified role. - /// - /// The role name. - public override void CreateRole(string rolename) - { - if (rolename.IndexOf(',') != -1) - throw new ArgumentException(Properties.Resources.InvalidCharactersInUserName); - if (RoleExists(rolename)) - throw new ProviderException(Properties.Resources.RoleNameAlreadyExists); - - using (MySqlConnection connection = new MySqlConnection(connectionString)) - { - try - { - connection.Open(); - - MySqlCommand cmd = new MySqlCommand( - @"INSERT INTO my_aspnet_roles Values(NULL, @appId, @name)", connection); - cmd.Parameters.AddWithValue("@appId", app.EnsureId(connection)); - cmd.Parameters.AddWithValue("@name", rolename); - cmd.ExecuteNonQuery(); - } - catch (MySqlException e) - { - if (WriteExceptionsToEventLog) - WriteToEventLog(e, "CreateRole"); - throw; - } - } - } - - /// - /// Deletes the specified role. - /// - /// The role name. - /// If set to true a will be raised if - /// there are users with the specified role. - /// true if the role was successfully deleted; otherwise, false. - /// The specified role doesn't exist or - /// is set to true and there are users with the specified role. - public override bool DeleteRole(string rolename, bool throwOnPopulatedRole) - { - using (MySqlConnection connection = new MySqlConnection(connectionString)) - { - MySqlTransaction txn = null; - try - { - if (!(RoleExists(rolename))) - throw new ProviderException(Properties.Resources.RoleNameNotFound); - if (throwOnPopulatedRole && GetUsersInRole(rolename).Length > 0) - throw new ProviderException(Properties.Resources.CannotDeleteAPopulatedRole); - - connection.Open(); - txn = connection.BeginTransaction(); - - // first delete all the user/role mappings with that roleid - MySqlCommand cmd = new MySqlCommand( - @"DELETE uir FROM my_aspnet_usersinroles uir JOIN - my_aspnet_roles r ON uir.roleId=r.id - WHERE r.name LIKE @rolename AND r.applicationId=@appId", connection); - cmd.Parameters.AddWithValue("@rolename", rolename); - cmd.Parameters.AddWithValue("@appId", app.FetchId(connection)); - cmd.ExecuteNonQuery(); - - // now delete the role itself - cmd.CommandText = @"DELETE FROM my_aspnet_roles WHERE name=@rolename - AND applicationId=@appId"; - cmd.ExecuteNonQuery(); - txn.Commit(); - } - catch (Exception ex) - { - if (txn != null) - txn.Rollback(); - if (WriteExceptionsToEventLog) - WriteToEventLog(ex, "DeleteRole"); - throw; - } - } - return true; - } - - /// - /// Gets a list of all the roles for the configured applicationName. - /// - /// - /// A string array containing the names of all the roles stored in the data source for the configured applicationName. - /// - public override string[] GetAllRoles() - { - using (MySqlConnection connection = new MySqlConnection(connectionString)) - { - connection.Open(); - return GetRolesByUserName(connection, null); - } - } - - /// - /// Gets a list of the roles that a specified user is in for the configured applicationName. - /// - /// The user to return a list of roles for. - /// - /// A string array containing the names of all the roles that the specified user is in for the configured applicationName. - /// - public override string[] GetRolesForUser(string username) - { - using (MySqlConnection connection = new MySqlConnection(connectionString)) - { - connection.Open(); - return GetRolesByUserName(connection, username); - } - } - - /// - /// Gets the users with the specified role. - /// - /// The role name. - /// A string array containing the names of all the users - /// who are members of the specified role. - public override string[] GetUsersInRole(string rolename) - { - List users = new List(); - - try - { - using (MySqlConnection connection = new MySqlConnection(connectionString)) - { - connection.Open(); - int roleId = GetRoleId(connection, rolename); - - string sql = @"SELECT u.name FROM my_aspnet_users u JOIN - my_aspnet_usersinroles uir ON uir.userId=u.id AND uir.roleId=@roleId - WHERE u.applicationId=@appId"; - MySqlCommand cmd = new MySqlCommand(sql, connection); - cmd.Parameters.AddWithValue("@roleId", roleId); - cmd.Parameters.AddWithValue("@appId", app.FetchId(connection)); - using (MySqlDataReader reader = cmd.ExecuteReader()) - { - while (reader.Read()) - users.Add(reader.GetString(0)); - } - } - return users.ToArray(); - } - catch (Exception ex) - { - if (WriteExceptionsToEventLog) - WriteToEventLog(ex, "GetUsersInRole"); - throw; - } - } - - /// - /// Determines whether [is user in role] [the specified username]. - /// - /// The username. - /// The rolename. - /// - /// true if [is user in role] [the specified username]; otherwise, false. - /// - public override bool IsUserInRole(string username, string rolename) - { - try - { - // this will refresh the app id if necessary - if (!RoleExists(rolename)) return false; - - using (MySqlConnection connection = new MySqlConnection(connectionString)) - { - connection.Open(); - - string sql = @"SELECT COUNT(*) FROM my_aspnet_usersinroles uir - JOIN my_aspnet_users u ON uir.userId=u.id - JOIN my_aspnet_roles r ON uir.roleId=r.id - WHERE u.applicationId=@appId AND - u.name = @userName AND r.name = @roleName"; - MySqlCommand cmd = new MySqlCommand(sql, connection); - cmd.Parameters.AddWithValue("@appId", app.FetchId(connection)); - cmd.Parameters.AddWithValue("@userName", username); - cmd.Parameters.AddWithValue("@roleName", rolename); - int count = Convert.ToInt32(cmd.ExecuteScalar()); - return count > 0; - } - } - catch (Exception ex) - { - if (WriteExceptionsToEventLog) - WriteToEventLog(ex, "IsUserInRole"); - throw; - } - } - - /// - /// Removes the users from the specified roles. - /// - /// The user names. - /// The role names. - public override void RemoveUsersFromRoles(string[] usernames, string[] rolenames) - { - if (rolenames == null || rolenames.Length == 0) return; - if (usernames == null || usernames.Length == 0) return; - - foreach (string rolename in rolenames) - { - if (!(RoleExists(rolename))) - throw new ProviderException(Properties.Resources.RoleNameNotFound); - } - - foreach (string username in usernames) - { - foreach (string rolename in rolenames) - { - if (!(IsUserInRole(username, rolename))) - throw new ProviderException(Properties.Resources.UserNotInRole); - } - } - - using (MySqlConnection connection = new MySqlConnection(connectionString)) - { - MySqlTransaction txn = null; - try - { - connection.Open(); - txn = connection.BeginTransaction(); - - string sql = @"DELETE uir FROM my_aspnet_usersinroles uir - JOIN my_aspnet_users u ON uir.userId=u.id - JOIN my_aspnet_roles r ON uir.roleId=r.id - WHERE u.name LIKE @username AND r.name LIKE @rolename - AND u.applicationId=@appId AND r.applicationId=@appId"; - - MySqlCommand cmd = new MySqlCommand(sql, connection); - cmd.Parameters.Add("@username", MySqlDbType.VarChar, 255); - cmd.Parameters.Add("@rolename", MySqlDbType.VarChar, 255); - cmd.Parameters.AddWithValue("@appId", app.FetchId(connection)); - - foreach (string username in usernames) - { - foreach (string rolename in rolenames) - { - cmd.Parameters[0].Value = username; - cmd.Parameters[1].Value = rolename; - cmd.ExecuteNonQuery(); - } - } - txn.Commit(); - } - catch (MySqlException e) - { - if (txn != null) - txn.Rollback(); - if (WriteExceptionsToEventLog) - WriteToEventLog(e, "RemoveUsersFromRoles"); - throw; - } - } - } - - /// - /// Determines whether the role exists. - /// - /// The rolename. - /// true if the role name already exists in the database; otherwise, false. - public override bool RoleExists(string rolename) - { - try - { - using (MySqlConnection connection = new MySqlConnection(connectionString)) - { - connection.Open(); - MySqlCommand cmd = new MySqlCommand( - @"SELECT COUNT(*) FROM my_aspnet_roles WHERE applicationId=@appId - AND name LIKE @name", connection); - cmd.Parameters.AddWithValue("@appId", app.FetchId(connection)); - cmd.Parameters.AddWithValue("@name", rolename); - int count = Convert.ToInt32(cmd.ExecuteScalar()); - return count != 0; - } - } - catch (Exception ex) - { - if (WriteExceptionsToEventLog) - WriteToEventLog(ex, "RoleExists"); - throw; - } - } - - /// - /// Finds the users with the specified role. - /// - /// The role name. - /// The user name to match. - /// A string array containing the names of all the users where the - /// user name matches usernameToMatch and the user is a member of the specified role. - public override string[] FindUsersInRole(string rolename, string usernameToMatch) - { - if (!RoleExists(rolename)) - throw new ProviderException(Properties.Resources.RoleNameNotFound); - - List users = new List(); - - try - { - using (MySqlConnection connection = new MySqlConnection(connectionString)) - { - connection.Open(); - - string sql = @"SELECT u.name FROM my_aspnet_usersinroles uir - JOIN my_aspnet_users u ON uir.userId=u.id - JOIN my_aspnet_roles r ON uir.roleId=r.id - WHERE r.name LIKE @rolename AND - u.name LIKE @username AND - u.applicationId=@appId"; - - MySqlCommand cmd = new MySqlCommand(sql, connection); - cmd.Parameters.AddWithValue("@username", usernameToMatch); - cmd.Parameters.AddWithValue("@rolename", rolename); - cmd.Parameters.AddWithValue("@appId", app.FetchId(connection)); - using (MySqlDataReader reader = cmd.ExecuteReader()) - { - while (reader.Read()) - users.Add(reader.GetString(0)); - } - } - return users.ToArray(); - } - catch (MySqlException e) - { - if (WriteExceptionsToEventLog) - WriteToEventLog(e, "FindUsersInRole"); - throw; - } - } - - #endregion - - internal static void DeleteUserData(MySqlConnection connection, int userId) - { - MySqlCommand cmd = new MySqlCommand( - "DELETE FROM my_aspnet_usersinroles WHERE userId=@userId", connection); - cmd.Parameters.AddWithValue("@userId", userId); - cmd.ExecuteNonQuery(); - } - - #region Private Methods - - private string[] GetRolesByUserName(MySqlConnection connection, string username) - { - List roleList = new List(); - - try - { - string sql = "SELECT r.name FROM my_aspnet_roles r "; - if (username != null) - sql += "JOIN my_aspnet_usersinroles uir ON uir.roleId=r.id AND uir.userId=" + - GetUserId(connection, username); - sql += " WHERE r.applicationId=@appId"; - MySqlCommand cmd = new MySqlCommand(sql, connection); - cmd.Parameters.AddWithValue("@appId", app.FetchId(connection)); - using (MySqlDataReader reader = cmd.ExecuteReader()) - { - while (reader.Read()) - roleList.Add(reader.GetString(0)); - } - return (string[])roleList.ToArray(); - } - catch (Exception ex) - { - if (WriteExceptionsToEventLog) - WriteToEventLog(ex, "GetRolesByUserName"); - throw; - } - } - - private int GetUserId(MySqlConnection connection, string username) - { - MySqlCommand cmd = new MySqlCommand( - "SELECT id FROM my_aspnet_users WHERE name=@name AND applicationId=@appId", - connection); - cmd.Parameters.AddWithValue("@name", username); - cmd.Parameters.AddWithValue("@appId", app.FetchId(connection)); - object id = cmd.ExecuteScalar(); - return Convert.ToInt32(id); - } - - private int GetRoleId(MySqlConnection connection, string rolename) - { - MySqlCommand cmd = new MySqlCommand( - "SELECT id FROM my_aspnet_roles WHERE name=@name AND applicationId=@appId", - connection); - cmd.Parameters.AddWithValue("@name", rolename); - cmd.Parameters.AddWithValue("@appId", app.FetchId(connection)); - return (int)cmd.ExecuteScalar(); - } - - private void WriteToEventLog(Exception e, string action) - { - using (EventLog log = new EventLog()) - { - log.Source = eventSource; - log.Log = eventLog; - string message = exceptionMessage + Environment.NewLine + Environment.NewLine; - message += "Action: " + action + Environment.NewLine + Environment.NewLine; - message += "Exception: " + e; - log.WriteEntry(message); - } - } - - #endregion - - } -} \ No newline at end of file +// Copyright © 2004, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +// This code was contributed by Sean Wright (srwright@alcor.concordia.ca) on 2007-01-12 +// The copyright was assigned and transferred under the terms of +// the MySQL Contributor License Agreement (CLA) + +using MySql.Data.MySqlClient; +using MySql.Web.Common; +using MySql.Web.General; +using System; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.Configuration.Provider; +using System.Diagnostics; +using System.Web.Hosting; +using System.Web.Security; + +namespace MySql.Web.Security +{ + /// + /// Manages storage of role membership information for an ASP.NET application in a MySQL database. + /// + public sealed class MySQLRoleProvider : RoleProvider + { + private string eventSource = "MySQLRoleProvider"; + private string eventLog = "Application"; + private string exceptionMessage = "An exception occurred. Please check the Event Log."; + private string connectionString; + private bool pWriteExceptionsToEventLog = false; + private Application app; + + /// + /// Initializes the provider. + /// + /// The friendly name of the provider. + /// A collection of the name/value pairs representing the provider-specific attributes specified in the configuration for this provider. + /// The name of the provider is null. + /// The name of the provider has a length of zero. + /// An attempt is made to call on a provider after the provider has already been initialized. + public override void Initialize(string name, NameValueCollection config) + { + if (config == null) + { + throw new ArgumentNullException("config"); + } + if (name == null || name.Length == 0) + { + name = "MySQLRoleProvider"; + } + if (string.IsNullOrEmpty(config["description"])) + { + config.Remove("description"); + config.Add("description", "MySQL Role provider"); + } + base.Initialize(name, config); + + string applicationName = HostingEnvironment.ApplicationVirtualPath; + if (!String.IsNullOrEmpty(config["applicationName"])) + applicationName = config["applicationName"]; + + if (!(config["writeExceptionsToEventLog"] == null)) + { + if (config["writeExceptionsToEventLog"].ToUpper() == "TRUE") + { + pWriteExceptionsToEventLog = true; + } + } + + connectionString = ConfigUtility.GetConnectionString(config); + if (String.IsNullOrEmpty(connectionString)) return; + + // make sure our schema is up to date + SchemaManager.CheckSchema(connectionString, config); + + app = new Application(applicationName, Description); + } + + #region Properties + + /// + /// Gets or sets the name of the application to store and retrieve role information for. + /// + /// The name of the application to store and retrieve role information for. + /// + /// + /// roleManager defaultProvider = "MySqlProvider" + /// enabled="true"> + /// providers> + /// add + /// name = "MySqlProvider" + /// type="MySql.Web.Security.MySQLRoleProvider" + /// connectionStringName="LocalMySqlServices" + /// writeExceptionsToEventLog="false" + /// applicationName="MyApplication" /> + /// /providers> + /// roleManager> + /// + /// + public override string ApplicationName + { + get { return app.Name; } + set { app.Name = value; } + } + + /// + /// Gets or sets a value indicating whether exceptions should be written to the event log. + /// + /// + /// true if exceptions should be written to the event log; otherwise, false. + /// + /// + /// + /// roleManager defaultProvider = "MySqlProvider" + /// enabled="true"> + /// providers> + /// add + /// name = "MySqlProvider" + /// type="MySql.Web.Security.MySQLRoleProvider" + /// connectionStringName="LocalMySqlServices" + /// writeExceptionsToEventLog="false" + /// applicationName="MyApplication" /> + /// /providers> + /// roleManager> + /// + /// + public bool WriteExceptionsToEventLog + { + get { return pWriteExceptionsToEventLog; } + set { pWriteExceptionsToEventLog = value; } + } + + #endregion + + #region Public Methods + + /// + /// Adds the users to the specified roles. + /// + /// The user names. + /// The role names. + public override void AddUsersToRoles(string[] usernames, string[] rolenames) + { + if (rolenames == null || rolenames.Length == 0) return; + if (usernames == null || usernames.Length == 0) return; + + foreach (string rolename in rolenames) + { + if (String.IsNullOrEmpty(rolename)) + throw new ArgumentException(Properties.Resources.IllegalRoleName, "rolenames"); + if (!RoleExists(rolename)) + throw new ProviderException(Properties.Resources.RoleNameNotFound); + } + + foreach (string username in usernames) + { + if (String.IsNullOrEmpty(username)) + throw new ArgumentException(Properties.Resources.IllegalUserName, "usernames"); + if (username.IndexOf(',') != -1) + throw new ArgumentException(Properties.Resources.InvalidCharactersInUserName); + + foreach (string rolename in rolenames) + { + if (IsUserInRole(username, rolename)) + throw new ProviderException(Properties.Resources.UserIsAlreadyInRole); + } + } + + using (MySqlConnection connection = new MySqlConnection(connectionString)) + { + MySqlTransaction txn = null; + try + { + connection.Open(); + txn = connection.BeginTransaction(); + MySqlCommand cmd = new MySqlCommand( + "INSERT INTO my_aspnet_usersinroles VALUES(@userId, @roleId)", connection); + cmd.Parameters.Add("@userId", MySqlDbType.Int32); + cmd.Parameters.Add("@roleId", MySqlDbType.Int32); + foreach (string username in usernames) + { + // either create a new user or fetch the existing user id + long userId = SchemaManager.CreateOrFetchUserId(connection, + username, app.FetchId(connection), true); + foreach (string rolename in rolenames) + { + int roleId = GetRoleId(connection, rolename); + cmd.Parameters[0].Value = userId; + cmd.Parameters[1].Value = roleId; + cmd.ExecuteNonQuery(); + } + } + txn.Commit(); + } + catch (Exception ex) + { + if (txn != null) + txn.Rollback(); + if (WriteExceptionsToEventLog) + WriteToEventLog(ex, "AddUsersToRoles"); + throw; + } + } + } + + /// + /// Creates the specified role. + /// + /// The role name. + public override void CreateRole(string rolename) + { + if (rolename.IndexOf(',') != -1) + throw new ArgumentException(Properties.Resources.InvalidCharactersInUserName); + if (RoleExists(rolename)) + throw new ProviderException(Properties.Resources.RoleNameAlreadyExists); + + using (MySqlConnection connection = new MySqlConnection(connectionString)) + { + try + { + connection.Open(); + + MySqlCommand cmd = new MySqlCommand( + @"INSERT INTO my_aspnet_roles Values(NULL, @appId, @name)", connection); + cmd.Parameters.AddWithValue("@appId", app.EnsureId(connection)); + cmd.Parameters.AddWithValue("@name", rolename); + cmd.ExecuteNonQuery(); + } + catch (MySqlException e) + { + if (WriteExceptionsToEventLog) + WriteToEventLog(e, "CreateRole"); + throw; + } + } + } + + /// + /// Deletes the specified role. + /// + /// The role name. + /// If set to true a will be raised if + /// there are users with the specified role. + /// true if the role was successfully deleted; otherwise, false. + /// The specified role doesn't exist or + /// is set to true and there are users with the specified role. + public override bool DeleteRole(string rolename, bool throwOnPopulatedRole) + { + using (MySqlConnection connection = new MySqlConnection(connectionString)) + { + MySqlTransaction txn = null; + try + { + if (!(RoleExists(rolename))) + throw new ProviderException(Properties.Resources.RoleNameNotFound); + if (throwOnPopulatedRole && GetUsersInRole(rolename).Length > 0) + throw new ProviderException(Properties.Resources.CannotDeleteAPopulatedRole); + + connection.Open(); + txn = connection.BeginTransaction(); + + // first delete all the user/role mappings with that roleid + MySqlCommand cmd = new MySqlCommand( + @"DELETE uir FROM my_aspnet_usersinroles uir JOIN + my_aspnet_roles r ON uir.roleId=r.id + WHERE r.name LIKE @rolename AND r.applicationId=@appId", connection); + cmd.Parameters.AddWithValue("@rolename", rolename); + cmd.Parameters.AddWithValue("@appId", app.FetchId(connection)); + cmd.ExecuteNonQuery(); + + // now delete the role itself + cmd.CommandText = @"DELETE FROM my_aspnet_roles WHERE name=@rolename + AND applicationId=@appId"; + cmd.ExecuteNonQuery(); + txn.Commit(); + } + catch (Exception ex) + { + if (txn != null) + txn.Rollback(); + if (WriteExceptionsToEventLog) + WriteToEventLog(ex, "DeleteRole"); + throw; + } + } + return true; + } + + /// + /// Gets a list of all the roles for the configured applicationName. + /// + /// + /// A string array containing the names of all the roles stored in the data source for the configured applicationName. + /// + public override string[] GetAllRoles() + { + using (MySqlConnection connection = new MySqlConnection(connectionString)) + { + connection.Open(); + return GetRolesByUserName(connection, null); + } + } + + /// + /// Gets a list of the roles that a specified user is in for the configured applicationName. + /// + /// The user to return a list of roles for. + /// + /// A string array containing the names of all the roles that the specified user is in for the configured applicationName. + /// + public override string[] GetRolesForUser(string username) + { + using (MySqlConnection connection = new MySqlConnection(connectionString)) + { + connection.Open(); + return GetRolesByUserName(connection, username); + } + } + + /// + /// Gets the users with the specified role. + /// + /// The role name. + /// A string array containing the names of all the users + /// who are members of the specified role. + public override string[] GetUsersInRole(string rolename) + { + List users = new List(); + + try + { + using (MySqlConnection connection = new MySqlConnection(connectionString)) + { + connection.Open(); + int roleId = GetRoleId(connection, rolename); + + string sql = @"SELECT u.name FROM my_aspnet_users u JOIN + my_aspnet_usersinroles uir ON uir.userId=u.id AND uir.roleId=@roleId + WHERE u.applicationId=@appId"; + MySqlCommand cmd = new MySqlCommand(sql, connection); + cmd.Parameters.AddWithValue("@roleId", roleId); + cmd.Parameters.AddWithValue("@appId", app.FetchId(connection)); + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + while (reader.Read()) + users.Add(reader.GetString(0)); + } + } + return users.ToArray(); + } + catch (Exception ex) + { + if (WriteExceptionsToEventLog) + WriteToEventLog(ex, "GetUsersInRole"); + throw; + } + } + + /// + /// Determines whether [is user in role] [the specified username]. + /// + /// The username. + /// The rolename. + /// + /// true if [is user in role] [the specified username]; otherwise, false. + /// + public override bool IsUserInRole(string username, string rolename) + { + try + { + // this will refresh the app id if necessary + if (!RoleExists(rolename)) return false; + + using (MySqlConnection connection = new MySqlConnection(connectionString)) + { + connection.Open(); + + string sql = @"SELECT COUNT(*) FROM my_aspnet_usersinroles uir + JOIN my_aspnet_users u ON uir.userId=u.id + JOIN my_aspnet_roles r ON uir.roleId=r.id + WHERE u.applicationId=@appId AND + u.name = @userName AND r.name = @roleName"; + MySqlCommand cmd = new MySqlCommand(sql, connection); + cmd.Parameters.AddWithValue("@appId", app.FetchId(connection)); + cmd.Parameters.AddWithValue("@userName", username); + cmd.Parameters.AddWithValue("@roleName", rolename); + int count = Convert.ToInt32(cmd.ExecuteScalar()); + return count > 0; + } + } + catch (Exception ex) + { + if (WriteExceptionsToEventLog) + WriteToEventLog(ex, "IsUserInRole"); + throw; + } + } + + /// + /// Removes the users from the specified roles. + /// + /// The user names. + /// The role names. + public override void RemoveUsersFromRoles(string[] usernames, string[] rolenames) + { + if (rolenames == null || rolenames.Length == 0) return; + if (usernames == null || usernames.Length == 0) return; + + foreach (string rolename in rolenames) + { + if (!(RoleExists(rolename))) + throw new ProviderException(Properties.Resources.RoleNameNotFound); + } + + foreach (string username in usernames) + { + foreach (string rolename in rolenames) + { + if (!(IsUserInRole(username, rolename))) + throw new ProviderException(Properties.Resources.UserNotInRole); + } + } + + using (MySqlConnection connection = new MySqlConnection(connectionString)) + { + MySqlTransaction txn = null; + try + { + connection.Open(); + txn = connection.BeginTransaction(); + + string sql = @"DELETE uir FROM my_aspnet_usersinroles uir + JOIN my_aspnet_users u ON uir.userId=u.id + JOIN my_aspnet_roles r ON uir.roleId=r.id + WHERE u.name LIKE @username AND r.name LIKE @rolename + AND u.applicationId=@appId AND r.applicationId=@appId"; + + MySqlCommand cmd = new MySqlCommand(sql, connection); + cmd.Parameters.Add("@username", MySqlDbType.VarChar, 255); + cmd.Parameters.Add("@rolename", MySqlDbType.VarChar, 255); + cmd.Parameters.AddWithValue("@appId", app.FetchId(connection)); + + foreach (string username in usernames) + { + foreach (string rolename in rolenames) + { + cmd.Parameters[0].Value = username; + cmd.Parameters[1].Value = rolename; + cmd.ExecuteNonQuery(); + } + } + txn.Commit(); + } + catch (MySqlException e) + { + if (txn != null) + txn.Rollback(); + if (WriteExceptionsToEventLog) + WriteToEventLog(e, "RemoveUsersFromRoles"); + throw; + } + } + } + + /// + /// Determines whether the role exists. + /// + /// The rolename. + /// true if the role name already exists in the database; otherwise, false. + public override bool RoleExists(string rolename) + { + try + { + using (MySqlConnection connection = new MySqlConnection(connectionString)) + { + connection.Open(); + MySqlCommand cmd = new MySqlCommand( + @"SELECT COUNT(*) FROM my_aspnet_roles WHERE applicationId=@appId + AND name LIKE @name", connection); + cmd.Parameters.AddWithValue("@appId", app.FetchId(connection)); + cmd.Parameters.AddWithValue("@name", rolename); + int count = Convert.ToInt32(cmd.ExecuteScalar()); + return count != 0; + } + } + catch (Exception ex) + { + if (WriteExceptionsToEventLog) + WriteToEventLog(ex, "RoleExists"); + throw; + } + } + + /// + /// Finds the users with the specified role. + /// + /// The role name. + /// The user name to match. + /// A string array containing the names of all the users where the + /// user name matches usernameToMatch and the user is a member of the specified role. + public override string[] FindUsersInRole(string rolename, string usernameToMatch) + { + if (!RoleExists(rolename)) + throw new ProviderException(Properties.Resources.RoleNameNotFound); + + List users = new List(); + + try + { + using (MySqlConnection connection = new MySqlConnection(connectionString)) + { + connection.Open(); + + string sql = @"SELECT u.name FROM my_aspnet_usersinroles uir + JOIN my_aspnet_users u ON uir.userId=u.id + JOIN my_aspnet_roles r ON uir.roleId=r.id + WHERE r.name LIKE @rolename AND + u.name LIKE @username AND + u.applicationId=@appId"; + + MySqlCommand cmd = new MySqlCommand(sql, connection); + cmd.Parameters.AddWithValue("@username", usernameToMatch); + cmd.Parameters.AddWithValue("@rolename", rolename); + cmd.Parameters.AddWithValue("@appId", app.FetchId(connection)); + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + while (reader.Read()) + users.Add(reader.GetString(0)); + } + } + return users.ToArray(); + } + catch (MySqlException e) + { + if (WriteExceptionsToEventLog) + WriteToEventLog(e, "FindUsersInRole"); + throw; + } + } + + #endregion + + internal static void DeleteUserData(MySqlConnection connection, int userId) + { + MySqlCommand cmd = new MySqlCommand( + "DELETE FROM my_aspnet_usersinroles WHERE userId=@userId", connection); + cmd.Parameters.AddWithValue("@userId", userId); + cmd.ExecuteNonQuery(); + } + + #region Private Methods + + private string[] GetRolesByUserName(MySqlConnection connection, string username) + { + List roleList = new List(); + + try + { + string sql = "SELECT r.name FROM my_aspnet_roles r "; + if (username != null) + sql += "JOIN my_aspnet_usersinroles uir ON uir.roleId=r.id AND uir.userId=" + + GetUserId(connection, username); + sql += " WHERE r.applicationId=@appId"; + MySqlCommand cmd = new MySqlCommand(sql, connection); + cmd.Parameters.AddWithValue("@appId", app.FetchId(connection)); + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + while (reader.Read()) + roleList.Add(reader.GetString(0)); + } + return (string[])roleList.ToArray(); + } + catch (Exception ex) + { + if (WriteExceptionsToEventLog) + WriteToEventLog(ex, "GetRolesByUserName"); + throw; + } + } + + private int GetUserId(MySqlConnection connection, string username) + { + MySqlCommand cmd = new MySqlCommand( + "SELECT id FROM my_aspnet_users WHERE name=@name AND applicationId=@appId", + connection); + cmd.Parameters.AddWithValue("@name", username); + cmd.Parameters.AddWithValue("@appId", app.FetchId(connection)); + object id = cmd.ExecuteScalar(); + return Convert.ToInt32(id); + } + + private int GetRoleId(MySqlConnection connection, string rolename) + { + MySqlCommand cmd = new MySqlCommand( + "SELECT id FROM my_aspnet_roles WHERE name=@name AND applicationId=@appId", + connection); + cmd.Parameters.AddWithValue("@name", rolename); + cmd.Parameters.AddWithValue("@appId", app.FetchId(connection)); + return (int)cmd.ExecuteScalar(); + } + + private void WriteToEventLog(Exception e, string action) + { + using (EventLog log = new EventLog()) + { + log.Source = eventSource; + log.Log = eventLog; + string message = exceptionMessage + Environment.NewLine + Environment.NewLine; + message += "Action: " + action + Environment.NewLine + Environment.NewLine; + message += "Exception: " + e; + log.WriteEntry(message); + } + } + + #endregion + + } +} diff --git a/MySql.Web/src/Runtime.cs b/MySql.Web/src/Runtime.cs index 8d2a2d337..162ef29cf 100644 --- a/MySql.Web/src/Runtime.cs +++ b/MySql.Web/src/Runtime.cs @@ -1,59 +1,59 @@ -// Copyright (c) 2004, 2020, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -// This code was contributed by Sean Wright (srwright@alcor.concordia.ca) on 2007-01-12 -// The copyright was assigned and transferred under the terms of -// the MySQL Contributor License Agreement (CLA) - -using System; - -namespace MySql.Web.Security -{ - internal static class Runtime - { - private static bool inited; - private static bool isMono; - - public static bool IsMono - { - get - { - if (!inited) - Init(); - return isMono; - } - } - - private static void Init() - { - inited = true; - Type t = Type.GetType("Mono.Runtime"); - isMono = t != null; - } - } -} +// Copyright © 2004, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +// This code was contributed by Sean Wright (srwright@alcor.concordia.ca) on 2007-01-12 +// The copyright was assigned and transferred under the terms of +// the MySQL Contributor License Agreement (CLA) + +using System; + +namespace MySql.Web.Security +{ + internal static class Runtime + { + private static bool inited; + private static bool isMono; + + public static bool IsMono + { + get + { + if (!inited) + Init(); + return isMono; + } + } + + private static void Init() + { + inited = true; + Type t = Type.GetType("Mono.Runtime"); + isMono = t != null; + } + } +} diff --git a/MySql.Web/src/SchemaManager.cs b/MySql.Web/src/SchemaManager.cs index ece9c2f1a..d83afbeb2 100644 --- a/MySql.Web/src/SchemaManager.cs +++ b/MySql.Web/src/SchemaManager.cs @@ -1,191 +1,191 @@ -// Copyright (c) 2004, 2020, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -// This code was contributed by Sean Wright (srwright@alcor.concordia.ca) on 2007-01-12 -// The copyright was assigned and transferred under the terms of -// the MySQL Contributor License Agreement (CLA) - -using MySql.Data.MySqlClient; -using System; -using System.Collections.Specialized; -using System.Configuration.Provider; -using System.Data; -using System.Diagnostics; -using System.IO; -using System.Reflection; -using System.Text; - -namespace MySql.Web.Common -{ - /// - /// Provided methods that allow managing a database. - /// - public static class SchemaManager - { - private const int schemaVersion = 10; - - /// - /// Gets the most recent version of the schema. - /// - /// The most recent version number of the schema. - public static int Version - { - get { return schemaVersion; } - } - - internal static void CheckSchema(string connectionString, NameValueCollection config) - { - int ver = GetSchemaVersion(connectionString); - if (ver == Version) return; - - try - { - if (String.Compare(config["autogenerateschema"], "true", true) == 0) - UpgradeToCurrent(connectionString, ver); - else - throw new ProviderException(Properties.Resources.MissingOrWrongSchema); - - } - catch (Exception ex) - { - throw new ProviderException(Properties.Resources.MissingOrWrongSchema, ex); - } - } - - internal static string GetSchema(int version) - { - var assembly = Assembly.GetExecutingAssembly(); - using (Stream stream = assembly.GetManifestResourceStream($"MySql.Web.Properties.schema{version}.sql")) - using (StreamReader reader = new StreamReader(stream)) - return reader.ReadToEnd(); - } - - private static void UpgradeToCurrent(string connectionString, int version) - { - if (version == Version) return; - - using (MySqlConnection connection = new MySqlConnection(connectionString)) - { - connection.Open(); - - for (int ver = version + 1; ver <= Version; ver++) - { - string schema = GetSchema(ver); - MySqlScript script = new MySqlScript(connection); - script.Query = schema; - - try - { - script.Execute(); - } - catch (MySqlException ex) - { - if (ex.Number == 1050 && ver == 7) - { - // Schema7 performs several renames of tables to their lowercase representation. - // If the current server OS does not support renaming to lowercase, then let's just continue. - script.Query = "UPDATE my_aspnet_schemaversion SET version=7"; - script.Execute(); - continue; - } - throw ex; - } - } - } - } - - private static int GetSchemaVersion(string connectionString) - { - // retrieve the current schema version - using (MySqlConnection conn = new MySqlConnection(connectionString)) - { - conn.Open(); - - MySqlCommand cmd = new MySqlCommand("SELECT * FROM my_aspnet_schemaversion", conn); - try - { - object ver = cmd.ExecuteScalar(); - if (ver != null) - return (int)ver; - } - catch (MySqlException ex) - { - if (ex.Number != (int)MySqlErrorCode.NoSuchTable) - throw; - string[] restrictions = new string[4]; - restrictions[2] = "mysql_membership"; - DataTable dt = conn.GetSchema("Tables", restrictions); - if (dt.Rows.Count == 1) - { - var value = dt.Rows[0]["TABLE_COMMENT"]; - if (value is Byte[]) - { - Byte[] byteArray = value as Byte[]; - return Convert.ToInt32(Encoding.UTF8.GetString(byteArray, 0, byteArray.Length)); - } - else - return Convert.ToInt32(value); - } - } - return 0; - } - } - - /// - /// Creates the or fetch user id. - /// - /// The connection. - /// The username. - /// The application id. - /// if set to true [authenticated]. - /// - internal static long CreateOrFetchUserId(MySqlConnection connection, string username, - long applicationId, bool authenticated) - { - Debug.Assert(applicationId > 0); - - // first attempt to fetch an existing user id - MySqlCommand cmd = new MySqlCommand(@"SELECT id FROM my_aspnet_users - WHERE applicationId = @appId AND name = @name", connection); - cmd.Parameters.AddWithValue("@appId", applicationId); - cmd.Parameters.AddWithValue("@name", username); - object userId = cmd.ExecuteScalar(); - if (userId != null) return (int)userId; - - cmd.CommandText = @"INSERT INTO my_aspnet_users VALUES - (NULL, @appId, @name, @isAnon, Now())"; - cmd.Parameters.AddWithValue("@isAnon", !authenticated); - int recordsAffected = cmd.ExecuteNonQuery(); - if (recordsAffected != 1) - throw new ProviderException(Properties.Resources.UnableToCreateUser); - - cmd.CommandText = "SELECT LAST_INSERT_ID()"; - return Convert.ToInt64(cmd.ExecuteScalar()); - } - } -} \ No newline at end of file +// Copyright © 2004, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +// This code was contributed by Sean Wright (srwright@alcor.concordia.ca) on 2007-01-12 +// The copyright was assigned and transferred under the terms of +// the MySQL Contributor License Agreement (CLA) + +using MySql.Data.MySqlClient; +using System; +using System.Collections.Specialized; +using System.Configuration.Provider; +using System.Data; +using System.Diagnostics; +using System.IO; +using System.Reflection; +using System.Text; + +namespace MySql.Web.Common +{ + /// + /// Provided methods that allow managing a database. + /// + public static class SchemaManager + { + private const int schemaVersion = 10; + + /// + /// Gets the most recent version of the schema. + /// + /// The most recent version number of the schema. + public static int Version + { + get { return schemaVersion; } + } + + internal static void CheckSchema(string connectionString, NameValueCollection config) + { + int ver = GetSchemaVersion(connectionString); + if (ver == Version) return; + + try + { + if (String.Compare(config["autogenerateschema"], "true", true) == 0) + UpgradeToCurrent(connectionString, ver); + else + throw new ProviderException(Properties.Resources.MissingOrWrongSchema); + + } + catch (Exception ex) + { + throw new ProviderException(Properties.Resources.MissingOrWrongSchema, ex); + } + } + + internal static string GetSchema(int version) + { + var assembly = Assembly.GetExecutingAssembly(); + using (Stream stream = assembly.GetManifestResourceStream($"MySql.Web.Properties.schema{version}.sql")) + using (StreamReader reader = new StreamReader(stream)) + return reader.ReadToEnd(); + } + + private static void UpgradeToCurrent(string connectionString, int version) + { + if (version == Version) return; + + using (MySqlConnection connection = new MySqlConnection(connectionString)) + { + connection.Open(); + + for (int ver = version + 1; ver <= Version; ver++) + { + string schema = GetSchema(ver); + MySqlScript script = new MySqlScript(connection); + script.Query = schema; + + try + { + script.Execute(); + } + catch (MySqlException ex) + { + if (ex.Number == 1050 && ver == 7) + { + // Schema7 performs several renames of tables to their lowercase representation. + // If the current server OS does not support renaming to lowercase, then let's just continue. + script.Query = "UPDATE my_aspnet_schemaversion SET version=7"; + script.Execute(); + continue; + } + throw ex; + } + } + } + } + + private static int GetSchemaVersion(string connectionString) + { + // retrieve the current schema version + using (MySqlConnection conn = new MySqlConnection(connectionString)) + { + conn.Open(); + + MySqlCommand cmd = new MySqlCommand("SELECT * FROM my_aspnet_schemaversion", conn); + try + { + object ver = cmd.ExecuteScalar(); + if (ver != null) + return (int)ver; + } + catch (MySqlException ex) + { + if (ex.Number != (int)MySqlErrorCode.NoSuchTable) + throw; + string[] restrictions = new string[4]; + restrictions[2] = "mysql_membership"; + DataTable dt = conn.GetSchema("Tables", restrictions); + if (dt.Rows.Count == 1) + { + var value = dt.Rows[0]["TABLE_COMMENT"]; + if (value is Byte[]) + { + Byte[] byteArray = value as Byte[]; + return Convert.ToInt32(Encoding.UTF8.GetString(byteArray, 0, byteArray.Length)); + } + else + return Convert.ToInt32(value); + } + } + return 0; + } + } + + /// + /// Creates the or fetch user id. + /// + /// The connection. + /// The username. + /// The application id. + /// if set to true [authenticated]. + /// + internal static long CreateOrFetchUserId(MySqlConnection connection, string username, + long applicationId, bool authenticated) + { + Debug.Assert(applicationId > 0); + + // first attempt to fetch an existing user id + MySqlCommand cmd = new MySqlCommand(@"SELECT id FROM my_aspnet_users + WHERE applicationId = @appId AND name = @name", connection); + cmd.Parameters.AddWithValue("@appId", applicationId); + cmd.Parameters.AddWithValue("@name", username); + object userId = cmd.ExecuteScalar(); + if (userId != null) return (int)userId; + + cmd.CommandText = @"INSERT INTO my_aspnet_users VALUES + (NULL, @appId, @name, @isAnon, Now())"; + cmd.Parameters.AddWithValue("@isAnon", !authenticated); + int recordsAffected = cmd.ExecuteNonQuery(); + if (recordsAffected != 1) + throw new ProviderException(Properties.Resources.UnableToCreateUser); + + cmd.CommandText = "SELECT LAST_INSERT_ID()"; + return Convert.ToInt64(cmd.ExecuteScalar()); + } + } +} diff --git a/MySql.Web/src/SessionProvider.cs b/MySql.Web/src/SessionProvider.cs index ca4499da7..68e140eee 100644 --- a/MySql.Web/src/SessionProvider.cs +++ b/MySql.Web/src/SessionProvider.cs @@ -1,909 +1,909 @@ -// Copyright (c) 2004, 2020, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySql.Data.MySqlClient; -using MySql.Web.Common; -using MySql.Web.General; -using System; -using System.Collections.Specialized; -using System.Configuration; -using System.Configuration.Provider; -using System.Diagnostics; -using System.IO; -using System.Security; -using System.Threading; -using System.Web; -using System.Web.Configuration; -using System.Web.Hosting; -using System.Web.SessionState; - -namespace MySql.Web.SessionState -{ - /// - /// This class allows ASP.NET applications to store and manage session state information in a - /// MySQL database. - /// Expired session data is periodically deleted from the database. - /// - public class MySqlSessionStateStore : SessionStateStoreProviderBase - { - string connectionString; - // ConnectionStringSettings connectionStringSettings; - string eventSource = "MySQLSessionStateStore"; - string eventLog = "Application"; - string exceptionMessage = "An exception occurred. Please check the event log."; - Application app; - - SessionStateSection sessionStateConfig; - - // cleanup old session - Timer cleanupTimer; - int cleanupInterval; - bool cleanupRunning; - - - bool writeExceptionsToEventLog = false; - - SessionStateItemExpireCallback expireCallback = null; - bool enableExpireCallback = false; - - - /// - /// Indicates whether if expire callback is on or off. - /// - public bool EnableExpireCallback - { - get { return enableExpireCallback; } - set { enableExpireCallback = value; } - } - - /// - /// Indicates whether to write exceptions to event log. - /// - public bool WriteExceptionsToEventLog - { - get { return writeExceptionsToEventLog; } - set { writeExceptionsToEventLog = value; } - } - - /// - /// The name of the ASP .NET application. - /// - public string ApplicationName - { - get { return app.Name; } - set { app.Name = value; } - } - - private long ApplicationId - { - get { return app.Id; } - } - - - /// - /// Handles a MySql type exception. - /// - /// exception - /// name of the function that throwed the exception - /// If is set it will write exception info to event log. - /// - /// is false. - private void HandleMySqlException(MySqlException e, string action) - { - if (WriteExceptionsToEventLog) - { - using (EventLog log = new EventLog()) - { - log.Source = eventSource; - log.Log = eventLog; - - string message = "An exception occurred communicating with the data source.\n\n"; - message += "Action: " + action; - message += "Exception: " + e.ToString(); - log.WriteEntry(message); - } - } - throw new ProviderException(exceptionMessage, e); - } - - - - /// - /// Initializes the provider with the property values specified in the ASP .NET application configuration file. - /// - /// The name of the provider instance to initialize. - /// Object that contains the names and values of configuration options for the provider. - /// - public override void Initialize(string name, NameValueCollection config) - { - //Initialize values from web.config. - if (config == null) - throw new ArgumentException("config"); - if (name == null || name.Length == 0) - throw new ArgumentException("name"); - if (String.IsNullOrEmpty(config["description"])) - { - config.Remove("description"); - config["description"] = "MySQL Session State Store Provider"; - } - base.Initialize(name, config); - string applicationName = HostingEnvironment.ApplicationVirtualPath; - if (!String.IsNullOrEmpty(config["applicationName"])) - applicationName = config["applicationName"]; - - // Get configuration element. - Configuration webConfig = WebConfigurationManager.OpenWebConfiguration(HostingEnvironment.ApplicationVirtualPath); - sessionStateConfig = (SessionStateSection)webConfig.SectionGroups["system.web"].Sections["sessionState"]; - - // Initialize connection. - connectionString = ConfigUtility.GetConnectionString(config); - if (string.IsNullOrEmpty(connectionString)) return; - - writeExceptionsToEventLog = false; - if (config["writeExceptionsToEventLog"] != null) - { - writeExceptionsToEventLog = (config["writeExceptionsToEventLog"].ToUpper() == "TRUE"); - } - - enableExpireCallback = false; - - if (config["enableExpireCallback"] != null) - { - enableExpireCallback = (config["enableExpireCallback"].ToUpper() == "TRUE"); - } - - // Make sure we have the correct schema. - SchemaManager.CheckSchema(connectionString, config); - app = new Application(applicationName, base.Description); - - // Get the application id. - try - { - using (MySqlConnection conn = new MySqlConnection(connectionString)) - { - conn.Open(); - app.EnsureId(conn); - CheckStorageEngine(conn); - } - } - catch (MySqlException e) - { - HandleMySqlException(e, "Initialize"); - } - - try - { - using (MySqlConnection conn = new MySqlConnection(connectionString)) - { - MySqlCommand cmd = new MySqlCommand( - "INSERT IGNORE INTO my_aspnet_sessioncleanup SET" + - " ApplicationId = @ApplicationId, " + - " LastRun = NOW(), " + - " IntervalMinutes = 10", - conn); - cmd.Parameters.AddWithValue("@ApplicationId", ApplicationId); - conn.Open(); - cmd.ExecuteNonQuery(); - cleanupInterval = GetCleanupInterval(conn, ApplicationId); - } - } - catch (MySqlException e) - { - HandleMySqlException(e, "Initialize"); - } - - // Setup the cleanup timer - if (cleanupInterval <= 0) - cleanupInterval = 1; - cleanupTimer = new Timer(new TimerCallback(CleanupOldSessions), null, 0, - cleanupInterval * 1000 * 60); - } - - /// - /// Creates a new object for the current request. - /// - /// - /// The HttpContext object for the current request. - /// - /// - /// The timeout value (in minutes) for the SessionStateStoreData object that is created. - /// - public override SessionStateStoreData CreateNewStoreData(System.Web.HttpContext context, int timeout) - { - - return new SessionStateStoreData(new SessionStateItemCollection(), - SessionStateUtility.GetSessionStaticObjects(context), timeout); - } - - /// - /// Adds a new session state item to the database. - /// - /// - /// The HttpContext object for the current request. - /// - /// - /// The session ID for the current request. - /// - /// - /// The timeout value for the current request. - /// - public override void CreateUninitializedItem(System.Web.HttpContext context, string id, int timeout) - { - try - { - using (MySqlConnection conn = new MySqlConnection(connectionString)) - { - MySqlCommand cmd = new MySqlCommand( - @"INSERT INTO my_aspnet_sessions - (SessionId, ApplicationId, Created, Expires, LockDate, - LockId, Timeout, Locked, SessionItems, Flags) - Values (@SessionId, @ApplicationId, NOW(), NOW() + INTERVAL @Timeout MINUTE, NOW(), - @LockId , @Timeout, @Locked, @SessionItems, @Flags) - on duplicate key update Created = values( Created ), Expires = values( Expires ), - LockDate = values( LockDate ), LockId = values( LockId ), Timeout = values( Timeout) , - Locked = values( Locked ), SessionItems = values( SessionItems ), Flags = values( Flags )", - conn); - - cmd.Parameters.AddWithValue("@SessionId", id); - cmd.Parameters.AddWithValue("@ApplicationId", ApplicationId); - cmd.Parameters.AddWithValue("@LockId", 0); - cmd.Parameters.AddWithValue("@Timeout", timeout); - cmd.Parameters.AddWithValue("@Locked", 0); - cmd.Parameters.AddWithValue("@SessionItems", null); - cmd.Parameters.AddWithValue("@Flags", 1); - conn.Open(); - cmd.ExecuteNonQuery(); - } - } - catch (MySqlException e) - { - HandleMySqlException(e, "CreateUninitializedItem"); - } - } - - - /// - /// Releases all the resources for this instance. - /// - public override void Dispose() - { - if (cleanupTimer != null) - cleanupTimer.Dispose(); - } - - /// - /// Allows the object to perform any cleanup that may be - /// required for the current request. - /// - /// The HttpContext object for the current request. - public override void EndRequest(System.Web.HttpContext context) - { - } - - /// - /// Returns a read-only session item from the database. - /// - public override SessionStateStoreData GetItem(System.Web.HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actions) - { - return GetSessionStoreItem(false, context, id, out locked, out lockAge, out lockId, out actions); - } - - /// - /// Locks a session item and returns it from the database. - /// - /// The HttpContext object for the current request. - /// The session ID for the current request. - /// - /// true if the session item is locked in the database; otherwise, false. - /// - /// - /// TimeSpan object that indicates the amount of time the session item has been locked in the database. - /// - /// - /// A lock identifier object. - /// - /// - /// A enumeration value that indicates whether or - /// not the session is uninitialized and cookieless. - /// - /// - public override SessionStateStoreData GetItemExclusive(System.Web.HttpContext context, string id, - out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actions) - { - return GetSessionStoreItem(true, context, id, out locked, out lockAge, out lockId, out actions); - } - - /// - /// Performs any per-request initializations that the MySqlSessionStateStore provider requires. - /// - public override void InitializeRequest(System.Web.HttpContext context) - { - } - - /// - /// Forcibly releases the lock on a session item in the database if multiple attempts to - /// retrieve the session item fail. - /// - /// The HttpContext object for the current request. - /// The session ID for the current request. - /// The lock identifier for the current request. - public override void ReleaseItemExclusive(System.Web.HttpContext context, string id, object lockId) - { - try - { - using (MySqlConnection conn = new MySqlConnection(connectionString)) - { - MySqlCommand cmd = new MySqlCommand( - "UPDATE my_aspnet_sessions SET Locked = 0, Expires = NOW() + INTERVAL @Timeout MINUTE " + - "WHERE SessionId = @SessionId AND ApplicationId = @ApplicationId AND LockId = @LockId", - conn); - - cmd.Parameters.AddWithValue("@Timeout", sessionStateConfig.Timeout.TotalMinutes); - cmd.Parameters.AddWithValue("@SessionId", id); - cmd.Parameters.AddWithValue("@ApplicationId", ApplicationId); - cmd.Parameters.AddWithValue("@LockId", lockId); - conn.Open(); - cmd.ExecuteNonQuery(); - } - } - catch (MySqlException e) - { - HandleMySqlException(e, "ReleaseItemExclusive"); - } - } - - /// - /// Removes the specified session item from the database - /// - /// The HttpContext object for the current request. - /// The session ID for the current request. - /// The lock identifier for the current request. - /// The session item to remove from the database. - public override void RemoveItem(System.Web.HttpContext context, string id, object lockId, SessionStateStoreData item) - { - bool sessionDeleted; - - try - { - using (MySqlConnection conn = new MySqlConnection(connectionString)) - { - MySqlCommand cmd = new MySqlCommand("DELETE FROM my_aspnet_sessions " + - " WHERE SessionId = @SessionId AND ApplicationId = @ApplicationId AND LockId = @LockId", - conn); - - cmd.Parameters.AddWithValue("@SessionId", id); - cmd.Parameters.AddWithValue("@ApplicationId", ApplicationId); - cmd.Parameters.AddWithValue("@LockId", lockId); - conn.Open(); - sessionDeleted = cmd.ExecuteNonQuery() > 0; - } - if (sessionDeleted && this.enableExpireCallback) - { - this.expireCallback.Invoke(id, item); - } - } - catch (MySqlException ex) - { - HandleMySqlException(ex, "RemoveItem Error: " + ex.Message); - } - } - - - /// - /// Resets the expiration date and timeout for a session item in the database. - /// - /// The HttpContext object for the current request. - /// The session ID for the current request. - public override void ResetItemTimeout(System.Web.HttpContext context, string id) - { - try - { - using (MySqlConnection conn = new MySqlConnection(connectionString)) - { - MySqlCommand cmd = new MySqlCommand( - "UPDATE my_aspnet_sessions SET Expires = NOW() + INTERVAL @Timeout MINUTE" + - " WHERE SessionId = @SessionId AND ApplicationId = @ApplicationId", conn); - - cmd.Parameters.AddWithValue("@Timeout", sessionStateConfig.Timeout.TotalMinutes); - cmd.Parameters.AddWithValue("@SessionId", id); - cmd.Parameters.AddWithValue("@ApplicationId", ApplicationId); - conn.Open(); - cmd.ExecuteNonQuery(); - } - } - catch (MySqlException e) - { - HandleMySqlException(e, "ResetItemTimeout"); - } - } - - /// - /// Updates the session time information in the database with the specified session item, - /// and releases the lock. - /// - /// The HttpContext object for the current request. - /// The session ID for the current request. - /// The session item containing new values to update the session item in the database with. - /// - /// The lock identifier for the current request. - /// A Boolean value that indicates whether or not the session item is new in the database. - /// A false value indicates an existing item. - /// - public override void SetAndReleaseItemExclusive(System.Web.HttpContext context, string id, SessionStateStoreData item, object lockId, bool newItem) - { - try - { - using (MySqlConnection conn = new MySqlConnection(connectionString)) - { - // Serialize the SessionStateItemCollection as a byte array - byte[] sessItems = Serialize((SessionStateItemCollection)item.Items); - MySqlCommand cmd; - if (newItem) - { - //Insert the new session item . If there was expired session - //with the same SessionId and Application id, it will be removed - - cmd = new MySqlCommand( - @"INSERT INTO my_aspnet_sessions - (SessionId, ApplicationId, Created, Expires, LockDate, - LockId, Timeout, Locked, SessionItems, Flags) - Values (@SessionId, @ApplicationId, NOW(), NOW() + INTERVAL @Timeout MINUTE, NOW(), - @LockId , @Timeout, @Locked, @SessionItems, @Flags) - on duplicate key update Created = values( Created ), Expires = values( Expires ), - LockDate = values( LockDate ), LockId = values( LockId ), Timeout = values( Timeout) , - Locked = values( Locked ), SessionItems = values( SessionItems ), Flags = values( Flags )", conn); - cmd.Parameters.AddWithValue("@SessionId", id); - cmd.Parameters.AddWithValue("@ApplicationId", ApplicationId); - cmd.Parameters.AddWithValue("@Timeout", item.Timeout); - cmd.Parameters.AddWithValue("@LockId", 0); - cmd.Parameters.AddWithValue("@Locked", 0); - cmd.Parameters.AddWithValue("@SessionItems", sessItems); - cmd.Parameters.AddWithValue("@Flags", 0); - } - else - { - //Update the existing session item. - cmd = new MySqlCommand( - "UPDATE my_aspnet_sessions SET Expires = NOW() + INTERVAL @Timeout MINUTE," + - " SessionItems = @SessionItems, Locked = @Locked " + - " WHERE SessionId = @SessionId AND ApplicationId = @ApplicationId AND LockId = @LockId", - conn); - - cmd.Parameters.AddWithValue("@Timeout", item.Timeout); - cmd.Parameters.AddWithValue("@SessionItems", sessItems); - cmd.Parameters.AddWithValue("@Locked", 0); - cmd.Parameters.AddWithValue("@SessionId", id); - cmd.Parameters.AddWithValue("@ApplicationId", ApplicationId); - cmd.Parameters.AddWithValue("@LockId", lockId); - } - conn.Open(); - cmd.ExecuteNonQuery(); - } - } - catch (MySqlException e) - { - HandleMySqlException(e, "SetAndReleaseItemExclusive"); - } - } - - - /// - /// GetSessionStoreItem is called by both the GetItem and GetItemExclusive methods. GetSessionStoreItem - /// retrieves the session data from the data source. If the lockRecord parameter is true (in the case of - /// GetItemExclusive), then GetSessionStoreItem locks the record and sets a New LockId and LockDate. - /// - private SessionStateStoreData GetSessionStoreItem(bool lockRecord, - HttpContext context, - string id, - out bool locked, - out TimeSpan lockAge, - out object lockId, - out SessionStateActions actionFlags) - { - - // Initial values for return value and out parameters. - SessionStateStoreData item = null; - lockAge = TimeSpan.Zero; - lockId = null; - locked = false; - actionFlags = SessionStateActions.None; - - // MySqlCommand for database commands. - MySqlCommand cmd = null; - // serialized SessionStateItemCollection. - byte[] serializedItems = null; - // True if a record is found in the database. - bool foundRecord = false; - // True if the returned session item is expired and needs to be deleted. - bool deleteData = false; - // Timeout value from the data store. - int timeout = 0; - - try - { - using (MySqlConnection conn = new MySqlConnection(connectionString)) - { - conn.Open(); - // lockRecord is True when called from GetItemExclusive and - // False when called from GetItem. - // Obtain a lock if possible. Ignore the record if it is expired. - if (lockRecord) - { - cmd = new MySqlCommand( - "UPDATE my_aspnet_sessions SET " + - " Locked = 1, LockDate = NOW()" + - " WHERE SessionId = @SessionId AND ApplicationId = @ApplicationId AND" + - " Locked = 0 AND Expires > NOW()", conn); - - cmd.Parameters.AddWithValue("@SessionId", id); - cmd.Parameters.AddWithValue("@ApplicationId", ApplicationId); - - if (cmd.ExecuteNonQuery() == 0) - { - // No record was updated because the record was locked or not found. - locked = true; - } - else - { - // The record was updated. - locked = false; - } - } - - // Retrieve the current session item information. - cmd = new MySqlCommand( - "SELECT NOW(), Expires , SessionItems, LockId, Flags, Timeout, " + - " LockDate, Locked " + - " FROM my_aspnet_sessions" + - " WHERE SessionId = @SessionId AND ApplicationId = @ApplicationId", conn); - - cmd.Parameters.AddWithValue("@SessionId", id); - cmd.Parameters.AddWithValue("@ApplicationId", ApplicationId); - - // Retrieve session item data from the data source. - using (MySqlDataReader reader = cmd.ExecuteReader()) - { - if (reader.Read()) - { - DateTime now = reader.GetDateTime(0); - DateTime expires = reader.GetDateTime(1); - if (now.CompareTo(expires) > 0) - { - //The record was expired. Mark it as not locked. - locked = false; - // The session was expired. Mark the data for deletion. - deleteData = true; - } - else - { - foundRecord = true; - } - - object items = reader.GetValue(2); - serializedItems = (items is DBNull) ? null : (byte[])items; - lockId = reader.GetValue(3); - if (lockId is DBNull) - lockId = (int)0; - - actionFlags = (SessionStateActions)(reader.GetInt32(4)); - timeout = reader.GetInt32(5); - DateTime lockDate = reader.GetDateTime(6); - lockAge = now.Subtract(lockDate); - // If it's a read-only session set locked to the current lock - // status (writable sessions have already done this) - if (!lockRecord) - locked = reader.GetBoolean(7); - } - } - - // The record was not found. Ensure that locked is false. - if (!foundRecord) - locked = false; - - // If the record was found and you obtained a lock, then set - // the lockId, clear the actionFlags, - // and create the SessionStateStoreItem to return. - if (foundRecord && !locked) - { - lockId = (int)(lockId) + 1; - - cmd = new MySqlCommand("UPDATE my_aspnet_sessions SET" + - " LockId = @LockId, Flags = 0 " + - " WHERE SessionId = @SessionId AND ApplicationId = @ApplicationId", conn); - - cmd.Parameters.AddWithValue("@LockId", lockId); - cmd.Parameters.AddWithValue("@SessionId", id); - cmd.Parameters.AddWithValue("@ApplicationId", ApplicationId); - cmd.ExecuteNonQuery(); - - - // If the actionFlags parameter is not InitializeItem, - // deserialize the stored SessionStateItemCollection. - if (actionFlags == SessionStateActions.InitializeItem) - { - item = CreateNewStoreData(context, (int)sessionStateConfig.Timeout.TotalMinutes); - } - else - { - item = Deserialize(context, serializedItems, timeout); - } - } - } - } - catch (MySqlException e) - { - HandleMySqlException(e, "GetSessionStoreItem"); - } - return item; - } - - /// - /// Sets the reference for the ExpireCallback delegate if setting is enabled. - /// - /// - /// true if is true; otherwise, false. - public override bool SetItemExpireCallback(SessionStateItemExpireCallback expireCallback) - { - if (this.enableExpireCallback) - { - this.expireCallback = expireCallback; - return true; - } - return false; - } - - /// - /// Serialize is called by the SetAndReleaseItemExclusive method to - /// convert the SessionStateItemCollection into a byte array to - /// be stored in the blob field. - /// - private byte[] Serialize(SessionStateItemCollection items) - { - MemoryStream ms = new MemoryStream(); - BinaryWriter writer = new BinaryWriter(ms); - if (items != null) - { - items.Serialize(writer); - } - writer.Close(); - return ms.ToArray(); - } - - /// - /// Deserialize is called by the GetSessionStoreItem method to - /// convert the byte array stored in the blob field to a - /// SessionStateItemCollection. - /// - private SessionStateStoreData Deserialize(HttpContext context, - byte[] serializedItems, int timeout) - { - - SessionStateItemCollection sessionItems = new SessionStateItemCollection(); - - if (serializedItems != null) - { - MemoryStream ms = new MemoryStream(serializedItems); - if (ms.Length > 0) - { - BinaryReader reader = new BinaryReader(ms); - sessionItems = SessionStateItemCollection.Deserialize(reader); - } - } - - return new SessionStateStoreData(sessionItems, SessionStateUtility.GetSessionStaticObjects(context), - timeout); - } - - - private SessionStateItemCollection DeserializeSessionItems(byte[] serializedItems) - { - SessionStateItemCollection sessionItems = new SessionStateItemCollection(); - if (serializedItems != null) - { - MemoryStream ms = new MemoryStream(serializedItems); - if (ms.Length > 0) - { - BinaryReader reader = new BinaryReader(ms); - sessionItems = SessionStateItemCollection.Deserialize(reader); - } - } - return sessionItems; - } - - - private void CleanupOldSessions(object o) - { - - lock (this) - { - if (cleanupRunning) - return; - - cleanupRunning = true; - } - try - { - using (MySqlConnection con = new MySqlConnection(connectionString)) - { - con.Open(); - MySqlCommand cmd = new MySqlCommand( - "UPDATE my_aspnet_sessioncleanup SET LastRun=NOW() WHERE" + - " LastRun + INTERVAL IntervalMinutes MINUTE < NOW() AND ApplicationId = @ApplicationId", con); - cmd.Parameters.AddWithValue("@ApplicationId", ApplicationId); - int updatedSessions = cmd.ExecuteNonQuery(); - if (updatedSessions > 0) - DeleteTimedOutSessions(); - } - } - catch (MySqlException e) - { - HandleMySqlException(e, "CleanupOldSessions"); - } - finally - { - lock (this) - { - cleanupRunning = false; - } - } - } - - int GetCleanupInterval(MySqlConnection con, long ApplicationId) - { - MySqlCommand cmd = new MySqlCommand("SELECT IntervalMinutes from my_aspnet_sessioncleanup where ApplicationId = @ApplicationId", con); - cmd.Parameters.AddWithValue("@ApplicationId", ApplicationId); - return (int)cmd.ExecuteScalar(); - } - - /// - /// Checks storage engine used by my_aspnet_sessions. - /// - /// The connection object used to check the storage engine. - /// Warn if MyISAM is used - it does not handle concurrent updates well - /// which is important for session provider, as each access to session - /// does an update to "expires" field. - private void CheckStorageEngine(MySqlConnection con) - { - - try - { - MySqlCommand cmd = new MySqlCommand( - "SELECT ENGINE FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME='my_aspnet_sessions'", - con); - using (MySqlDataReader reader = cmd.ExecuteReader()) - { - if (reader.Read()) - { - string engine = reader.GetString(0); - if (engine == "MyISAM") - { - string message = - "Storage engine for table my_aspnet_sessions is MyISAM." + - "If possible, please change it to a transactional storage engine " + - "to improve performance,e.g with 'alter table my_aspnet_sessions engine innodb'\n"; - try - { - using (EventLog log = new EventLog()) - { - log.Source = eventSource; - log.Log = eventLog; - log.WriteEntry(message); - } - } - catch (SecurityException) - { - // Can't write to event log due to security restrictions - Trace.WriteLine(message); - } - } - } - } - } - catch (MySqlException e) - { - Trace.Write("got exception while checking for engine" + e); - } - } - - private void DeleteTimedOutSessions() - { - if (this.enableExpireCallback) - { - DeleteTimedOutSessionsWithCallback(); - } - else - { - DeleteTimedOutSessionsWithoutCallback(); - } - } - - private void DeleteTimedOutSessionsWithoutCallback() - { - try - { - using (MySqlConnection con = new MySqlConnection(connectionString)) - { - con.Open(); - MySqlCommand cmd = new MySqlCommand("DELETE FROM my_aspnet_sessions WHERE Expires < NOW() AND ApplicationId = @ApplicationId", con); - cmd.Parameters.AddWithValue("@ApplicationId", ApplicationId); - cmd.ExecuteNonQuery(); - } - } - catch (Exception e) - { - Trace.Write("Got exception in Delete Timed Out Sessions With Out Callback " + e); - throw; - } - } - - private void DeleteTimedOutSessionsWithCallback() - { - using (MySqlConnection con = new MySqlConnection(connectionString)) - { - con.Open(); - MySqlCommand cmd = new MySqlCommand("SELECT SessionID, SessionItems FROM my_aspnet_sessions WHERE Expires < NOW() AND ApplicationId = @ApplicationId", con); - cmd.Parameters.AddWithValue("@ApplicationId", ApplicationId); - - using (MySqlDataReader reader = cmd.ExecuteReader()) - { - while (reader.Read()) - { - string sid = reader.GetString(0); - object items = reader.GetValue(1); - byte[] rawSessionItems = (items is DBNull) ? null : (byte[])items; - - SessionStateItemCollection sessionItems = this.DeserializeSessionItems(rawSessionItems); - SessionStateStoreData ssd = new SessionStateStoreData(sessionItems, new HttpStaticObjectsCollection(), 0); - - try - { - if (this.expireCallback != null) this.expireCallback.Invoke(sid, ssd); - - using (MySqlConnection con2 = new MySqlConnection(connectionString)) - { - MySqlCommand cmd2 = new MySqlCommand("DELETE FROM my_aspnet_sessions" + - " WHERE SessionId = @SessionId" + - " AND ApplicationId = @ApplicationId", con2); - cmd2.Parameters.AddWithValue("@SessionId", sid); - cmd2.Parameters.AddWithValue("@ApplicationId", ApplicationId); - con2.Open(); - cmd2.ExecuteNonQuery(); - } - - } - catch (Exception e) - { - Trace.Write("Got exception in Delete Timed Out Sessions With Callback " + e); - throw; - } - } - } - } - } - } -} \ No newline at end of file +// Copyright © 2004, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySql.Data.MySqlClient; +using MySql.Web.Common; +using MySql.Web.General; +using System; +using System.Collections.Specialized; +using System.Configuration; +using System.Configuration.Provider; +using System.Diagnostics; +using System.IO; +using System.Security; +using System.Threading; +using System.Web; +using System.Web.Configuration; +using System.Web.Hosting; +using System.Web.SessionState; + +namespace MySql.Web.SessionState +{ + /// + /// This class allows ASP.NET applications to store and manage session state information in a + /// MySQL database. + /// Expired session data is periodically deleted from the database. + /// + public class MySqlSessionStateStore : SessionStateStoreProviderBase + { + string connectionString; + // ConnectionStringSettings connectionStringSettings; + string eventSource = "MySQLSessionStateStore"; + string eventLog = "Application"; + string exceptionMessage = "An exception occurred. Please check the event log."; + Application app; + + SessionStateSection sessionStateConfig; + + // cleanup old session + Timer cleanupTimer; + int cleanupInterval; + bool cleanupRunning; + + + bool writeExceptionsToEventLog = false; + + SessionStateItemExpireCallback expireCallback = null; + bool enableExpireCallback = false; + + + /// + /// Indicates whether if expire callback is on or off. + /// + public bool EnableExpireCallback + { + get { return enableExpireCallback; } + set { enableExpireCallback = value; } + } + + /// + /// Indicates whether to write exceptions to event log. + /// + public bool WriteExceptionsToEventLog + { + get { return writeExceptionsToEventLog; } + set { writeExceptionsToEventLog = value; } + } + + /// + /// The name of the ASP .NET application. + /// + public string ApplicationName + { + get { return app.Name; } + set { app.Name = value; } + } + + private long ApplicationId + { + get { return app.Id; } + } + + + /// + /// Handles a MySql type exception. + /// + /// exception + /// name of the function that throwed the exception + /// If is set it will write exception info to event log. + /// + /// is false. + private void HandleMySqlException(MySqlException e, string action) + { + if (WriteExceptionsToEventLog) + { + using (EventLog log = new EventLog()) + { + log.Source = eventSource; + log.Log = eventLog; + + string message = "An exception occurred communicating with the data source.\n\n"; + message += "Action: " + action; + message += "Exception: " + e.ToString(); + log.WriteEntry(message); + } + } + throw new ProviderException(exceptionMessage, e); + } + + + + /// + /// Initializes the provider with the property values specified in the ASP .NET application configuration file. + /// + /// The name of the provider instance to initialize. + /// Object that contains the names and values of configuration options for the provider. + /// + public override void Initialize(string name, NameValueCollection config) + { + //Initialize values from web.config. + if (config == null) + throw new ArgumentException("config"); + if (name == null || name.Length == 0) + throw new ArgumentException("name"); + if (String.IsNullOrEmpty(config["description"])) + { + config.Remove("description"); + config["description"] = "MySQL Session State Store Provider"; + } + base.Initialize(name, config); + string applicationName = HostingEnvironment.ApplicationVirtualPath; + if (!String.IsNullOrEmpty(config["applicationName"])) + applicationName = config["applicationName"]; + + // Get configuration element. + Configuration webConfig = WebConfigurationManager.OpenWebConfiguration(HostingEnvironment.ApplicationVirtualPath); + sessionStateConfig = (SessionStateSection)webConfig.SectionGroups["system.web"].Sections["sessionState"]; + + // Initialize connection. + connectionString = ConfigUtility.GetConnectionString(config); + if (string.IsNullOrEmpty(connectionString)) return; + + writeExceptionsToEventLog = false; + if (config["writeExceptionsToEventLog"] != null) + { + writeExceptionsToEventLog = (config["writeExceptionsToEventLog"].ToUpper() == "TRUE"); + } + + enableExpireCallback = false; + + if (config["enableExpireCallback"] != null) + { + enableExpireCallback = (config["enableExpireCallback"].ToUpper() == "TRUE"); + } + + // Make sure we have the correct schema. + SchemaManager.CheckSchema(connectionString, config); + app = new Application(applicationName, base.Description); + + // Get the application id. + try + { + using (MySqlConnection conn = new MySqlConnection(connectionString)) + { + conn.Open(); + app.EnsureId(conn); + CheckStorageEngine(conn); + } + } + catch (MySqlException e) + { + HandleMySqlException(e, "Initialize"); + } + + try + { + using (MySqlConnection conn = new MySqlConnection(connectionString)) + { + MySqlCommand cmd = new MySqlCommand( + "INSERT IGNORE INTO my_aspnet_sessioncleanup SET" + + " ApplicationId = @ApplicationId, " + + " LastRun = NOW(), " + + " IntervalMinutes = 10", + conn); + cmd.Parameters.AddWithValue("@ApplicationId", ApplicationId); + conn.Open(); + cmd.ExecuteNonQuery(); + cleanupInterval = GetCleanupInterval(conn, ApplicationId); + } + } + catch (MySqlException e) + { + HandleMySqlException(e, "Initialize"); + } + + // Setup the cleanup timer + if (cleanupInterval <= 0) + cleanupInterval = 1; + cleanupTimer = new Timer(new TimerCallback(CleanupOldSessions), null, 0, + cleanupInterval * 1000 * 60); + } + + /// + /// Creates a new object for the current request. + /// + /// + /// The HttpContext object for the current request. + /// + /// + /// The timeout value (in minutes) for the SessionStateStoreData object that is created. + /// + public override SessionStateStoreData CreateNewStoreData(System.Web.HttpContext context, int timeout) + { + + return new SessionStateStoreData(new SessionStateItemCollection(), + SessionStateUtility.GetSessionStaticObjects(context), timeout); + } + + /// + /// Adds a new session state item to the database. + /// + /// + /// The HttpContext object for the current request. + /// + /// + /// The session ID for the current request. + /// + /// + /// The timeout value for the current request. + /// + public override void CreateUninitializedItem(System.Web.HttpContext context, string id, int timeout) + { + try + { + using (MySqlConnection conn = new MySqlConnection(connectionString)) + { + MySqlCommand cmd = new MySqlCommand( + @"INSERT INTO my_aspnet_sessions + (SessionId, ApplicationId, Created, Expires, LockDate, + LockId, Timeout, Locked, SessionItems, Flags) + Values (@SessionId, @ApplicationId, NOW(), NOW() + INTERVAL @Timeout MINUTE, NOW(), + @LockId , @Timeout, @Locked, @SessionItems, @Flags) + on duplicate key update Created = values( Created ), Expires = values( Expires ), + LockDate = values( LockDate ), LockId = values( LockId ), Timeout = values( Timeout) , + Locked = values( Locked ), SessionItems = values( SessionItems ), Flags = values( Flags )", + conn); + + cmd.Parameters.AddWithValue("@SessionId", id); + cmd.Parameters.AddWithValue("@ApplicationId", ApplicationId); + cmd.Parameters.AddWithValue("@LockId", 0); + cmd.Parameters.AddWithValue("@Timeout", timeout); + cmd.Parameters.AddWithValue("@Locked", 0); + cmd.Parameters.AddWithValue("@SessionItems", null); + cmd.Parameters.AddWithValue("@Flags", 1); + conn.Open(); + cmd.ExecuteNonQuery(); + } + } + catch (MySqlException e) + { + HandleMySqlException(e, "CreateUninitializedItem"); + } + } + + + /// + /// Releases all the resources for this instance. + /// + public override void Dispose() + { + if (cleanupTimer != null) + cleanupTimer.Dispose(); + } + + /// + /// Allows the object to perform any cleanup that may be + /// required for the current request. + /// + /// The HttpContext object for the current request. + public override void EndRequest(System.Web.HttpContext context) + { + } + + /// + /// Returns a read-only session item from the database. + /// + public override SessionStateStoreData GetItem(System.Web.HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actions) + { + return GetSessionStoreItem(false, context, id, out locked, out lockAge, out lockId, out actions); + } + + /// + /// Locks a session item and returns it from the database. + /// + /// The HttpContext object for the current request. + /// The session ID for the current request. + /// + /// true if the session item is locked in the database; otherwise, false. + /// + /// + /// TimeSpan object that indicates the amount of time the session item has been locked in the database. + /// + /// + /// A lock identifier object. + /// + /// + /// A enumeration value that indicates whether or + /// not the session is uninitialized and cookieless. + /// + /// + public override SessionStateStoreData GetItemExclusive(System.Web.HttpContext context, string id, + out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actions) + { + return GetSessionStoreItem(true, context, id, out locked, out lockAge, out lockId, out actions); + } + + /// + /// Performs any per-request initializations that the MySqlSessionStateStore provider requires. + /// + public override void InitializeRequest(System.Web.HttpContext context) + { + } + + /// + /// Forcibly releases the lock on a session item in the database if multiple attempts to + /// retrieve the session item fail. + /// + /// The HttpContext object for the current request. + /// The session ID for the current request. + /// The lock identifier for the current request. + public override void ReleaseItemExclusive(System.Web.HttpContext context, string id, object lockId) + { + try + { + using (MySqlConnection conn = new MySqlConnection(connectionString)) + { + MySqlCommand cmd = new MySqlCommand( + "UPDATE my_aspnet_sessions SET Locked = 0, Expires = NOW() + INTERVAL @Timeout MINUTE " + + "WHERE SessionId = @SessionId AND ApplicationId = @ApplicationId AND LockId = @LockId", + conn); + + cmd.Parameters.AddWithValue("@Timeout", sessionStateConfig.Timeout.TotalMinutes); + cmd.Parameters.AddWithValue("@SessionId", id); + cmd.Parameters.AddWithValue("@ApplicationId", ApplicationId); + cmd.Parameters.AddWithValue("@LockId", lockId); + conn.Open(); + cmd.ExecuteNonQuery(); + } + } + catch (MySqlException e) + { + HandleMySqlException(e, "ReleaseItemExclusive"); + } + } + + /// + /// Removes the specified session item from the database + /// + /// The HttpContext object for the current request. + /// The session ID for the current request. + /// The lock identifier for the current request. + /// The session item to remove from the database. + public override void RemoveItem(System.Web.HttpContext context, string id, object lockId, SessionStateStoreData item) + { + bool sessionDeleted; + + try + { + using (MySqlConnection conn = new MySqlConnection(connectionString)) + { + MySqlCommand cmd = new MySqlCommand("DELETE FROM my_aspnet_sessions " + + " WHERE SessionId = @SessionId AND ApplicationId = @ApplicationId AND LockId = @LockId", + conn); + + cmd.Parameters.AddWithValue("@SessionId", id); + cmd.Parameters.AddWithValue("@ApplicationId", ApplicationId); + cmd.Parameters.AddWithValue("@LockId", lockId); + conn.Open(); + sessionDeleted = cmd.ExecuteNonQuery() > 0; + } + if (sessionDeleted && this.enableExpireCallback) + { + this.expireCallback.Invoke(id, item); + } + } + catch (MySqlException ex) + { + HandleMySqlException(ex, "RemoveItem Error: " + ex.Message); + } + } + + + /// + /// Resets the expiration date and timeout for a session item in the database. + /// + /// The HttpContext object for the current request. + /// The session ID for the current request. + public override void ResetItemTimeout(System.Web.HttpContext context, string id) + { + try + { + using (MySqlConnection conn = new MySqlConnection(connectionString)) + { + MySqlCommand cmd = new MySqlCommand( + "UPDATE my_aspnet_sessions SET Expires = NOW() + INTERVAL @Timeout MINUTE" + + " WHERE SessionId = @SessionId AND ApplicationId = @ApplicationId", conn); + + cmd.Parameters.AddWithValue("@Timeout", sessionStateConfig.Timeout.TotalMinutes); + cmd.Parameters.AddWithValue("@SessionId", id); + cmd.Parameters.AddWithValue("@ApplicationId", ApplicationId); + conn.Open(); + cmd.ExecuteNonQuery(); + } + } + catch (MySqlException e) + { + HandleMySqlException(e, "ResetItemTimeout"); + } + } + + /// + /// Updates the session time information in the database with the specified session item, + /// and releases the lock. + /// + /// The HttpContext object for the current request. + /// The session ID for the current request. + /// The session item containing new values to update the session item in the database with. + /// + /// The lock identifier for the current request. + /// A Boolean value that indicates whether or not the session item is new in the database. + /// A false value indicates an existing item. + /// + public override void SetAndReleaseItemExclusive(System.Web.HttpContext context, string id, SessionStateStoreData item, object lockId, bool newItem) + { + try + { + using (MySqlConnection conn = new MySqlConnection(connectionString)) + { + // Serialize the SessionStateItemCollection as a byte array + byte[] sessItems = Serialize((SessionStateItemCollection)item.Items); + MySqlCommand cmd; + if (newItem) + { + //Insert the new session item . If there was expired session + //with the same SessionId and Application id, it will be removed + + cmd = new MySqlCommand( + @"INSERT INTO my_aspnet_sessions + (SessionId, ApplicationId, Created, Expires, LockDate, + LockId, Timeout, Locked, SessionItems, Flags) + Values (@SessionId, @ApplicationId, NOW(), NOW() + INTERVAL @Timeout MINUTE, NOW(), + @LockId , @Timeout, @Locked, @SessionItems, @Flags) + on duplicate key update Created = values( Created ), Expires = values( Expires ), + LockDate = values( LockDate ), LockId = values( LockId ), Timeout = values( Timeout) , + Locked = values( Locked ), SessionItems = values( SessionItems ), Flags = values( Flags )", conn); + cmd.Parameters.AddWithValue("@SessionId", id); + cmd.Parameters.AddWithValue("@ApplicationId", ApplicationId); + cmd.Parameters.AddWithValue("@Timeout", item.Timeout); + cmd.Parameters.AddWithValue("@LockId", 0); + cmd.Parameters.AddWithValue("@Locked", 0); + cmd.Parameters.AddWithValue("@SessionItems", sessItems); + cmd.Parameters.AddWithValue("@Flags", 0); + } + else + { + //Update the existing session item. + cmd = new MySqlCommand( + "UPDATE my_aspnet_sessions SET Expires = NOW() + INTERVAL @Timeout MINUTE," + + " SessionItems = @SessionItems, Locked = @Locked " + + " WHERE SessionId = @SessionId AND ApplicationId = @ApplicationId AND LockId = @LockId", + conn); + + cmd.Parameters.AddWithValue("@Timeout", item.Timeout); + cmd.Parameters.AddWithValue("@SessionItems", sessItems); + cmd.Parameters.AddWithValue("@Locked", 0); + cmd.Parameters.AddWithValue("@SessionId", id); + cmd.Parameters.AddWithValue("@ApplicationId", ApplicationId); + cmd.Parameters.AddWithValue("@LockId", lockId); + } + conn.Open(); + cmd.ExecuteNonQuery(); + } + } + catch (MySqlException e) + { + HandleMySqlException(e, "SetAndReleaseItemExclusive"); + } + } + + + /// + /// GetSessionStoreItem is called by both the GetItem and GetItemExclusive methods. GetSessionStoreItem + /// retrieves the session data from the data source. If the lockRecord parameter is true (in the case of + /// GetItemExclusive), then GetSessionStoreItem locks the record and sets a New LockId and LockDate. + /// + private SessionStateStoreData GetSessionStoreItem(bool lockRecord, + HttpContext context, + string id, + out bool locked, + out TimeSpan lockAge, + out object lockId, + out SessionStateActions actionFlags) + { + + // Initial values for return value and out parameters. + SessionStateStoreData item = null; + lockAge = TimeSpan.Zero; + lockId = null; + locked = false; + actionFlags = SessionStateActions.None; + + // MySqlCommand for database commands. + MySqlCommand cmd = null; + // serialized SessionStateItemCollection. + byte[] serializedItems = null; + // True if a record is found in the database. + bool foundRecord = false; + // True if the returned session item is expired and needs to be deleted. + bool deleteData = false; + // Timeout value from the data store. + int timeout = 0; + + try + { + using (MySqlConnection conn = new MySqlConnection(connectionString)) + { + conn.Open(); + // lockRecord is True when called from GetItemExclusive and + // False when called from GetItem. + // Obtain a lock if possible. Ignore the record if it is expired. + if (lockRecord) + { + cmd = new MySqlCommand( + "UPDATE my_aspnet_sessions SET " + + " Locked = 1, LockDate = NOW()" + + " WHERE SessionId = @SessionId AND ApplicationId = @ApplicationId AND" + + " Locked = 0 AND Expires > NOW()", conn); + + cmd.Parameters.AddWithValue("@SessionId", id); + cmd.Parameters.AddWithValue("@ApplicationId", ApplicationId); + + if (cmd.ExecuteNonQuery() == 0) + { + // No record was updated because the record was locked or not found. + locked = true; + } + else + { + // The record was updated. + locked = false; + } + } + + // Retrieve the current session item information. + cmd = new MySqlCommand( + "SELECT NOW(), Expires , SessionItems, LockId, Flags, Timeout, " + + " LockDate, Locked " + + " FROM my_aspnet_sessions" + + " WHERE SessionId = @SessionId AND ApplicationId = @ApplicationId", conn); + + cmd.Parameters.AddWithValue("@SessionId", id); + cmd.Parameters.AddWithValue("@ApplicationId", ApplicationId); + + // Retrieve session item data from the data source. + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + if (reader.Read()) + { + DateTime now = reader.GetDateTime(0); + DateTime expires = reader.GetDateTime(1); + if (now.CompareTo(expires) > 0) + { + //The record was expired. Mark it as not locked. + locked = false; + // The session was expired. Mark the data for deletion. + deleteData = true; + } + else + { + foundRecord = true; + } + + object items = reader.GetValue(2); + serializedItems = (items is DBNull) ? null : (byte[])items; + lockId = reader.GetValue(3); + if (lockId is DBNull) + lockId = (int)0; + + actionFlags = (SessionStateActions)(reader.GetInt32(4)); + timeout = reader.GetInt32(5); + DateTime lockDate = reader.GetDateTime(6); + lockAge = now.Subtract(lockDate); + // If it's a read-only session set locked to the current lock + // status (writable sessions have already done this) + if (!lockRecord) + locked = reader.GetBoolean(7); + } + } + + // The record was not found. Ensure that locked is false. + if (!foundRecord) + locked = false; + + // If the record was found and you obtained a lock, then set + // the lockId, clear the actionFlags, + // and create the SessionStateStoreItem to return. + if (foundRecord && !locked) + { + lockId = (int)(lockId) + 1; + + cmd = new MySqlCommand("UPDATE my_aspnet_sessions SET" + + " LockId = @LockId, Flags = 0 " + + " WHERE SessionId = @SessionId AND ApplicationId = @ApplicationId", conn); + + cmd.Parameters.AddWithValue("@LockId", lockId); + cmd.Parameters.AddWithValue("@SessionId", id); + cmd.Parameters.AddWithValue("@ApplicationId", ApplicationId); + cmd.ExecuteNonQuery(); + + + // If the actionFlags parameter is not InitializeItem, + // deserialize the stored SessionStateItemCollection. + if (actionFlags == SessionStateActions.InitializeItem) + { + item = CreateNewStoreData(context, (int)sessionStateConfig.Timeout.TotalMinutes); + } + else + { + item = Deserialize(context, serializedItems, timeout); + } + } + } + } + catch (MySqlException e) + { + HandleMySqlException(e, "GetSessionStoreItem"); + } + return item; + } + + /// + /// Sets the reference for the ExpireCallback delegate if setting is enabled. + /// + /// + /// true if is true; otherwise, false. + public override bool SetItemExpireCallback(SessionStateItemExpireCallback expireCallback) + { + if (this.enableExpireCallback) + { + this.expireCallback = expireCallback; + return true; + } + return false; + } + + /// + /// Serialize is called by the SetAndReleaseItemExclusive method to + /// convert the SessionStateItemCollection into a byte array to + /// be stored in the blob field. + /// + private byte[] Serialize(SessionStateItemCollection items) + { + MemoryStream ms = new MemoryStream(); + BinaryWriter writer = new BinaryWriter(ms); + if (items != null) + { + items.Serialize(writer); + } + writer.Close(); + return ms.ToArray(); + } + + /// + /// Deserialize is called by the GetSessionStoreItem method to + /// convert the byte array stored in the blob field to a + /// SessionStateItemCollection. + /// + private SessionStateStoreData Deserialize(HttpContext context, + byte[] serializedItems, int timeout) + { + + SessionStateItemCollection sessionItems = new SessionStateItemCollection(); + + if (serializedItems != null) + { + MemoryStream ms = new MemoryStream(serializedItems); + if (ms.Length > 0) + { + BinaryReader reader = new BinaryReader(ms); + sessionItems = SessionStateItemCollection.Deserialize(reader); + } + } + + return new SessionStateStoreData(sessionItems, SessionStateUtility.GetSessionStaticObjects(context), + timeout); + } + + + private SessionStateItemCollection DeserializeSessionItems(byte[] serializedItems) + { + SessionStateItemCollection sessionItems = new SessionStateItemCollection(); + if (serializedItems != null) + { + MemoryStream ms = new MemoryStream(serializedItems); + if (ms.Length > 0) + { + BinaryReader reader = new BinaryReader(ms); + sessionItems = SessionStateItemCollection.Deserialize(reader); + } + } + return sessionItems; + } + + + private void CleanupOldSessions(object o) + { + + lock (this) + { + if (cleanupRunning) + return; + + cleanupRunning = true; + } + try + { + using (MySqlConnection con = new MySqlConnection(connectionString)) + { + con.Open(); + MySqlCommand cmd = new MySqlCommand( + "UPDATE my_aspnet_sessioncleanup SET LastRun=NOW() WHERE" + + " LastRun + INTERVAL IntervalMinutes MINUTE < NOW() AND ApplicationId = @ApplicationId", con); + cmd.Parameters.AddWithValue("@ApplicationId", ApplicationId); + int updatedSessions = cmd.ExecuteNonQuery(); + if (updatedSessions > 0) + DeleteTimedOutSessions(); + } + } + catch (MySqlException e) + { + HandleMySqlException(e, "CleanupOldSessions"); + } + finally + { + lock (this) + { + cleanupRunning = false; + } + } + } + + int GetCleanupInterval(MySqlConnection con, long ApplicationId) + { + MySqlCommand cmd = new MySqlCommand("SELECT IntervalMinutes from my_aspnet_sessioncleanup where ApplicationId = @ApplicationId", con); + cmd.Parameters.AddWithValue("@ApplicationId", ApplicationId); + return (int)cmd.ExecuteScalar(); + } + + /// + /// Checks storage engine used by my_aspnet_sessions. + /// + /// The connection object used to check the storage engine. + /// Warn if MyISAM is used - it does not handle concurrent updates well + /// which is important for session provider, as each access to session + /// does an update to "expires" field. + private void CheckStorageEngine(MySqlConnection con) + { + + try + { + MySqlCommand cmd = new MySqlCommand( + "SELECT ENGINE FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME='my_aspnet_sessions'", + con); + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + if (reader.Read()) + { + string engine = reader.GetString(0); + if (engine == "MyISAM") + { + string message = + "Storage engine for table my_aspnet_sessions is MyISAM." + + "If possible, please change it to a transactional storage engine " + + "to improve performance,e.g with 'alter table my_aspnet_sessions engine innodb'\n"; + try + { + using (EventLog log = new EventLog()) + { + log.Source = eventSource; + log.Log = eventLog; + log.WriteEntry(message); + } + } + catch (SecurityException) + { + // Can't write to event log due to security restrictions + Trace.WriteLine(message); + } + } + } + } + } + catch (MySqlException e) + { + Trace.Write("got exception while checking for engine" + e); + } + } + + private void DeleteTimedOutSessions() + { + if (this.enableExpireCallback) + { + DeleteTimedOutSessionsWithCallback(); + } + else + { + DeleteTimedOutSessionsWithoutCallback(); + } + } + + private void DeleteTimedOutSessionsWithoutCallback() + { + try + { + using (MySqlConnection con = new MySqlConnection(connectionString)) + { + con.Open(); + MySqlCommand cmd = new MySqlCommand("DELETE FROM my_aspnet_sessions WHERE Expires < NOW() AND ApplicationId = @ApplicationId", con); + cmd.Parameters.AddWithValue("@ApplicationId", ApplicationId); + cmd.ExecuteNonQuery(); + } + } + catch (Exception e) + { + Trace.Write("Got exception in Delete Timed Out Sessions With Out Callback " + e); + throw; + } + } + + private void DeleteTimedOutSessionsWithCallback() + { + using (MySqlConnection con = new MySqlConnection(connectionString)) + { + con.Open(); + MySqlCommand cmd = new MySqlCommand("SELECT SessionID, SessionItems FROM my_aspnet_sessions WHERE Expires < NOW() AND ApplicationId = @ApplicationId", con); + cmd.Parameters.AddWithValue("@ApplicationId", ApplicationId); + + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + while (reader.Read()) + { + string sid = reader.GetString(0); + object items = reader.GetValue(1); + byte[] rawSessionItems = (items is DBNull) ? null : (byte[])items; + + SessionStateItemCollection sessionItems = this.DeserializeSessionItems(rawSessionItems); + SessionStateStoreData ssd = new SessionStateStoreData(sessionItems, new HttpStaticObjectsCollection(), 0); + + try + { + if (this.expireCallback != null) this.expireCallback.Invoke(sid, ssd); + + using (MySqlConnection con2 = new MySqlConnection(connectionString)) + { + MySqlCommand cmd2 = new MySqlCommand("DELETE FROM my_aspnet_sessions" + + " WHERE SessionId = @SessionId" + + " AND ApplicationId = @ApplicationId", con2); + cmd2.Parameters.AddWithValue("@SessionId", sid); + cmd2.Parameters.AddWithValue("@ApplicationId", ApplicationId); + con2.Open(); + cmd2.ExecuteNonQuery(); + } + + } + catch (Exception e) + { + Trace.Write("Got exception in Delete Timed Out Sessions With Callback " + e); + throw; + } + } + } + } + } + } +} diff --git a/MySql.Web/src/SimpleMembershipProvider.cs b/MySql.Web/src/SimpleMembershipProvider.cs index 4f8cede19..ff2924ec6 100644 --- a/MySql.Web/src/SimpleMembershipProvider.cs +++ b/MySql.Web/src/SimpleMembershipProvider.cs @@ -1,1138 +1,1138 @@ -// Copyright (c) 2014, 2020, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySql.Web.Common; -using MySql.Web.General; -using MySql.Web.Properties; -using System; -using System.Collections.Generic; -using System.Configuration; -using System.Configuration.Provider; -using System.Globalization; -using System.Linq; -using System.Security.Cryptography; -using System.Text; -using System.Web; -using System.Web.Hosting; -using System.Web.Security; -using WebMatrix.WebData; - -namespace MySql.Web.Security -{ - /// - /// Manages storage of simple membership information for an ASP.NET application in a MySQL database. - /// - public class MySqlSimpleMembershipProvider : ExtendedMembershipProvider - { - #region Private - private readonly MembershipProvider _prevProvider; - - Application _app; - bool _enablePwdReset; - bool _enablePwdRetrival; - int _maxPwdAttempts; - int _minReqNonAlphanumericalChars; - int _minReqPwdLength; - int _pwdAttemptWindow; - MembershipPasswordFormat _pwdFormat; - string _pwdStrenghtRegex; - bool _reqQuestionAnswer; - bool _reqUniqueEmail; - string _connString; - string _userTableName; - string _userIdColumn; - string _userNameColumn; - bool _autoGenerateTables; - private readonly string _membershipTable = "webpages_membership"; - private readonly string _oauthMembershipTable = "webpages_oauthmembership"; - private readonly string _userInRolesTable = "webpages_usersinroles"; - private readonly string _oauthTokenTable = "webpages_oauthtoken"; - - private static string GetConfigValue(string configVal, string defaultVal) - { - return !string.IsNullOrEmpty(configVal) ? configVal : defaultVal; - } - #endregion - public MySqlSimpleMembershipProvider() - : this(null) - { } - - public MySqlSimpleMembershipProvider(MembershipProvider previousProvider) - { - _prevProvider = previousProvider; - if (_prevProvider != null) - { - _prevProvider.ValidatingPassword += delegate (object sender, ValidatePasswordEventArgs args) { this.OnValidatingPassword(args); }; - } - } - - public override void Initialize(string name, System.Collections.Specialized.NameValueCollection config) - { - if (config == null) - { - NullArgumentException("config"); - } - if (string.IsNullOrEmpty(name)) - { - name = "MySqlExtendedMembershipProvider"; - } - if (string.IsNullOrEmpty(config["description"])) - { - config.Remove("description"); - config.Add("description", string.Format("MySql Default {0} Description", name)); - } - - base.Initialize(name, config); - - var appName = GetConfigValue(config["applicationName"], HostingEnvironment.SiteName); - _maxPwdAttempts = Int32.Parse(GetConfigValue(config["maxInvalidPasswordAttempts"], "5"), CultureInfo.InvariantCulture); - _pwdAttemptWindow = Int32.Parse(GetConfigValue(config["passwordAttemptWindow"], "10"), CultureInfo.InvariantCulture); - _minReqNonAlphanumericalChars = Int32.Parse(GetConfigValue(config["minRequiredNonalphanumericCharacters"], "1"), CultureInfo.InvariantCulture); - _minReqPwdLength = Int32.Parse(GetConfigValue(config["minRequiredPasswordLength"], "7"), CultureInfo.InvariantCulture); - _pwdStrenghtRegex = GetConfigValue(config["passwordStrengthRegularExpression"], ""); - _enablePwdReset = bool.Parse(GetConfigValue(config["enablePasswordReset"], "True")); - _enablePwdRetrival = bool.Parse(GetConfigValue(config["enablePasswordRetrieval"], "False")); - _reqQuestionAnswer = bool.Parse(GetConfigValue(config["requiresQuestionAndAnswer"], "False")); - _reqUniqueEmail = bool.Parse(GetConfigValue(config["requiresUniqueEmail"], "True")); - - var pwdFormat = !string.IsNullOrEmpty(config["passwordFormat"]) ? config["passwordFormat"].ToString().ToLowerInvariant() : "hashed"; - - switch (pwdFormat) - { - case "hashed": - _pwdFormat = MembershipPasswordFormat.Hashed; - break; - case "encrypted": - _pwdFormat = MembershipPasswordFormat.Encrypted; - break; - case "clear": - _pwdFormat = MembershipPasswordFormat.Clear; - break; - default: - throw new ProviderException(Resources.PasswordFormatNotSupported); - } - - if (_pwdFormat == MembershipPasswordFormat.Hashed) - { - if (_enablePwdRetrival) - throw new ProviderException(Resources.CannotRetrieveHashedPasswords); - } - - _app = new Application(appName, base.Description); - _connString = ConfigUtility.GetConnectionString(config); - if (string.IsNullOrEmpty(_connString)) return; - - UserTableName = GetConfigValue(config["userTableName"], ""); - UserIdColumn = GetConfigValue(config["userIdColumn"], ""); - UserNameColumn = GetConfigValue(config["userNameColumn"], ""); - _autoGenerateTables = bool.Parse(GetConfigValue(config["autoGenerateTables"], "True")); - if (_autoGenerateTables) - CreateTables(); - else - ValidateUserTable(); - - Initialized = true; - } - - public override bool ChangePassword(string username, string oldPassword, string newPassword) - { - if (!Initialized) - { - _prevProvider.ChangePassword(username, oldPassword, newPassword); - } - - if (string.IsNullOrEmpty(username)) - NullArgumentException("username"); - if (string.IsNullOrEmpty(oldPassword)) - NullArgumentException("oldPassword"); - if (string.IsNullOrEmpty(newPassword)) - NullArgumentException("newPassword"); - - int userid = GetUserId(username); - if (userid <= 0) - { - return false; - } - if (VerifyPassword(userid, oldPassword, GetHashedUserPassword(userid))) - { - return UpdatePassword(userid, newPassword) > 0; - } - - return false; - } - - public override bool ChangePasswordQuestionAndAnswer(string username, string password, string newPasswordQuestion, string newPasswordAnswer) - { - IsValidOperation(false); - return _prevProvider.ChangePasswordQuestionAndAnswer(username, password, newPasswordQuestion, newPasswordAnswer); - } - - public override bool ConfirmAccount(string accountConfirmationToken) - { - IsValidOperation(true); - using (MySqlDatabaseWrapper dbConn = new MySqlDatabaseWrapper(GetConnectionString())) - { - var token = dbConn.ExecuteQuerySingleRecord(string.Format("select userid, confirmationtoken from {0} where confirmationtoken=?", _membershipTable), accountConfirmationToken); - if (token == null || (token != null && string.IsNullOrEmpty(token[1].ToString()))) - { - return false; - } - return dbConn.ExecuteNonQuery(string.Format("update {0} set isconfirmed=1 where userid=?;", _membershipTable), (int)token[0]) > 0; - } - } - - public override bool ConfirmAccount(string userName, string accountConfirmationToken) - { - var userid = GetUserId(userName); - if (userid <= 0) - return false; - - using (MySqlDatabaseWrapper dbConn = new MySqlDatabaseWrapper(GetConnectionString())) - { - var token = dbConn.ExecuteQuerySingleRecord(string.Format("select userid, confirmationtoken from {0} where confirmationtoken=? and userid=?", _membershipTable), accountConfirmationToken, userid); - if (token == null || (token != null && string.IsNullOrEmpty(token[1].ToString()))) - { - return false; - } - return dbConn.ExecuteNonQuery(string.Format("update {0} set isconfirmed=1 where userid=?;", _membershipTable), userid) > 0; - } - } - - public override string CreateAccount(string userName, string password, bool requireConfirmationToken) - { - IsValidOperation(true); - if (string.IsNullOrEmpty(userName)) - NullArgumentException(userName); - if (string.IsNullOrEmpty(password)) - NullArgumentException(password); - var hashedPass = HashPassword(password); - if (hashedPass.Length > 128) - throw new ArgumentException(Resources.PasswordExceedsMaxLength, password); - - using (MySqlDatabaseWrapper dbConn = new MySqlDatabaseWrapper(GetConnectionString())) - { - var userid = GetUserId(userName); - if (userid <= 0) - { - throw new InvalidOperationException(string.Format(Resources.UserNotFound, UserTableName)); - } - if (dbConn.ExecuteQuerySingleRecord(string.Format("select userid from {0} where userid=?;", _membershipTable), userid) != null) - { - throw new InvalidOperationException(string.Format(Resources.UserAlreadyExists, userName)); - } - object token = DBNull.Value; - if (requireConfirmationToken) - token = GenerateToken(); - - string insertQuery = string.Format("insert into {0} (userid, createdate, confirmationtoken, isconfirmed, password, passwordchangeddate, passwordsalt) values(?,now(),?,?,?,now(),?)", _membershipTable); - if (dbConn.ExecuteNonQuery(insertQuery, userid, token, !requireConfirmationToken, hashedPass, string.Empty) <= 0) - { - throw new MembershipCreateUserException(MembershipCreateStatus.ProviderError); - } - return token == DBNull.Value ? null : token.ToString(); - } - } - - public override void CreateOrUpdateOAuthAccount(string provider, string providerUserId, string userName) - { - IsValidOperation(true); - if (string.IsNullOrEmpty(userName)) - NullArgumentException(userName); - var userid = GetUserId(userName); - if (userid <= 0) - { - throw new InvalidOperationException(string.Format(Resources.UserNotFound, UserTableName)); - } - var oauthUserId = GetUserIdFromOAuth(provider, providerUserId); - using (MySqlDatabaseWrapper dbConn = new MySqlDatabaseWrapper(GetConnectionString())) - { - if (oauthUserId == 0) - { - if (dbConn.ExecuteNonQuery(string.Format("insert into {0} (provider, provideruserid, userid) values(?,?,?)", _oauthMembershipTable), provider, providerUserId, userid) <= 0) - { - throw new MembershipCreateUserException(MembershipCreateStatus.ProviderError); - } - } - else - { - if (dbConn.ExecuteNonQuery(string.Format("update {0} set userid=? where upper(provider) = ? and upper(provideruserid)=?;", _oauthMembershipTable), userid, provider.ToUpper(), providerUserId.ToUpper()) <= 0) - { - throw new MembershipCreateUserException(MembershipCreateStatus.ProviderError); - } - } - } - } - - public override MembershipUser CreateUser(string username, string password, string email, string passwordQuestion, string passwordAnswer, bool isApproved, object providerUserKey, out MembershipCreateStatus status) - { - IsValidOperation(false); - return _prevProvider.CreateUser(username, password, email, passwordQuestion, passwordAnswer, isApproved, providerUserKey, out status); - } - - public override string CreateUserAndAccount(string userName, string password, bool requireConfirmation, IDictionary values) - { - IsValidOperation(true); - CreateUserInUserTable(userName, values); - return CreateAccount(userName, password, requireConfirmation); - } - - public override bool DeleteAccount(string userName) - { - IsValidOperation(true); - int userid = GetUserId(userName); - if (userid < 0) - { - return false; - } - using (MySqlDatabaseWrapper dbConn = new MySqlDatabaseWrapper(GetConnectionString())) - { - return (dbConn.ExecuteNonQuery(string.Format("delete from {0} where userid=?;", _membershipTable), userid) > 0); - } - } - - public override void DeleteOAuthAccount(string provider, string providerUserId) - { - IsValidOperation(true); - using (MySqlDatabaseWrapper dbConn = new MySqlDatabaseWrapper(GetConnectionString())) - { - if (dbConn.ExecuteNonQuery(string.Format("delete from {0} where upper(provider) = ? and upper(provideruserid)=?;", _oauthMembershipTable), provider.ToUpper(), providerUserId.ToUpper()) <= 0) - { - throw new Exception(string.Format(Resources.DeleteOAuthAccountFailed, provider, providerUserId)); - } - } - } - - public override void DeleteOAuthToken(string token) - { - IsValidOperation(true); - using (MySqlDatabaseWrapper dbConn = new MySqlDatabaseWrapper(GetConnectionString())) - { - dbConn.ExecuteNonQuery(string.Format("delete from {0} where token=?", _oauthTokenTable), token); - } - } - - public override bool DeleteUser(string username, bool deleteAllRelatedData) - { - if (!Initialized) - return _prevProvider.DeleteUser(username, deleteAllRelatedData); - - int userid = GetUserId(username); - if (userid < 0) - return false; - - using (MySqlDatabaseWrapper dbConn = new MySqlDatabaseWrapper(GetConnectionString())) - { - if (deleteAllRelatedData) - { - return dbConn.ExecuteInTransaction( - new List>() - { - new Tuple(string.Format("delete from {0} where {1}=?;", UserTableName, UserIdColumn), new object [] { userid }), - new Tuple(string.Format("delete from {0} where userid=?;", _oauthMembershipTable), new object [] { userid }), - new Tuple(string.Format("delete from {0} where userid=?;", _membershipTable), new object [] { userid }), - new Tuple(string.Format("delete from {0} where userid=?;", _userInRolesTable), new object [] { userid }) - }); - } - else - { - return (dbConn.ExecuteNonQuery(string.Format("delete from {0} where {1}=?;", UserTableName, UserIdColumn), userid) > 0); - } - } - } - - public override MembershipUserCollection FindUsersByEmail(string emailToMatch, int pageIndex, int pageSize, out int totalRecords) - { - IsValidOperation(false); - return _prevProvider.FindUsersByEmail(emailToMatch, pageIndex, pageSize, out totalRecords); - } - - public override MembershipUserCollection FindUsersByName(string usernameToMatch, int pageIndex, int pageSize, out int totalRecords) - { - IsValidOperation(false); - return _prevProvider.FindUsersByName(usernameToMatch, pageIndex, pageSize, out totalRecords); - } - - public override string GeneratePasswordResetToken(string userName, int tokenExpirationInMinutesFromNow) - { - IsValidOperation(true); - if (string.IsNullOrEmpty(userName)) - NullArgumentException("username"); - int userid = GetUserId(userName); - if (userid <= 0) - InvalidUserException(userName); - - if (UserConfirmed(userid)) - { - using (MySqlDatabaseWrapper dbConn = new MySqlDatabaseWrapper(GetConnectionString())) - { - string token = dbConn.ExecuteScalar(string.Format("select PasswordVerificationToken from {0} where userid=? and PasswordVerificationTokenExpirationDate > ?;", _membershipTable), userid, DateTime.Now) as string; - if (token != null) - { - token = GenerateToken(); - if (dbConn.ExecuteNonQuery(string.Format("update {0} set PasswordVerificationToken=?, PasswordVerificationTokenExpirationDate=? where userid=?;", _membershipTable), token, DateTime.Now.AddMinutes(tokenExpirationInMinutesFromNow), userid) <= 0) - { - throw new ProviderException(Resources.GeneratePassVerificationTokenFailed); - } - } - return token; - } - } - return null; - } - - public override ICollection GetAccountsForUser(string userName) - { - IsValidOperation(true); - int userid = GetUserId(userName); - if (userid > 0) - { - using (MySqlDatabaseWrapper dbConn = new MySqlDatabaseWrapper(GetConnectionString())) - { - var records = dbConn.ExecuteQuery(string.Format("select provider, provideruserid from {0} where userid=?", _oauthMembershipTable), userid); - if (records != null && records.Count() > 0) - { - var accounts = new List(); - records.ToList().ForEach(record => accounts.Add(new OAuthAccountData(record["provider"].ToString(), record["provideruserid"].ToString()))); - return accounts; - } - } - } - return new OAuthAccountData[0]; - } - - public override MembershipUserCollection GetAllUsers(int pageIndex, int pageSize, out int totalRecords) - { - IsValidOperation(false); - return _prevProvider.GetAllUsers(pageIndex, pageSize, out totalRecords); - } - - public override DateTime GetCreateDate(string userName) - { - int userid = GetUserId(userName); - if (userid < 0) - InvalidUserException(userName); - - using (MySqlDatabaseWrapper dbConn = new MySqlDatabaseWrapper(GetConnectionString())) - { - var createDate = dbConn.ExecuteScalar(string.Format("select CreateDate from {0} where userid=?;", _membershipTable), userid); - if (createDate != null && createDate != DBNull.Value) - return (DateTime)createDate; - - return DateTime.MinValue; - } - } - - public override DateTime GetLastPasswordFailureDate(string userName) - { - int userid = GetUserId(userName); - if (userid < 0) - InvalidUserException(userName); - - using (MySqlDatabaseWrapper dbConn = new MySqlDatabaseWrapper(GetConnectionString())) - { - var failureDate = dbConn.ExecuteScalar(string.Format("select LastPasswordFailureDate from {0} where userid=?;", _membershipTable), userid); - if (failureDate != null && failureDate != DBNull.Value) - return (DateTime)failureDate; - - return DateTime.MinValue; - } - } - - public override int GetNumberOfUsersOnline() - { - IsValidOperation(false); - return _prevProvider.GetNumberOfUsersOnline(); - } - - public override string GetPassword(string username, string answer) - { - IsValidOperation(false); - return _prevProvider.GetPassword(username, answer); - } - - public override DateTime GetPasswordChangedDate(string userName) - { - int userid = GetUserId(userName); - if (userid < 0) - InvalidUserException(userName); - - using (MySqlDatabaseWrapper dbConn = new MySqlDatabaseWrapper(GetConnectionString())) - { - var changedDate = dbConn.ExecuteScalar(string.Format("select PasswordChangedDate from {0} where userid=?;", _membershipTable), userid); - if (changedDate != null) - return (DateTime)changedDate; - - return DateTime.MinValue; - } - } - - public override int GetPasswordFailuresSinceLastSuccess(string userName) - { - int userid = GetUserId(userName); - if (userid < 0) - InvalidUserException(userName); - - return GetPasswordFailuresSinceLastSuccess(userid); - } - - private int GetPasswordFailuresSinceLastSuccess(int userId) - { - using (MySqlDatabaseWrapper dbConn = new MySqlDatabaseWrapper(GetConnectionString())) - { - var failures = dbConn.ExecuteScalar(string.Format("select PasswordFailuresSinceLastSuccess from {0} where userid=?;", _membershipTable), userId); - if (failures != null) - return (int)failures; - - return -1; - } - } - - public override MembershipUser GetUser(object providerUserKey, bool userIsOnline) - { - IsValidOperation(false); - return _prevProvider.GetUser(providerUserKey, userIsOnline); - } - - public override MembershipUser GetUser(string username, bool userIsOnline) - { - if (!Initialized) - return _prevProvider.GetUser(username, userIsOnline); - - int userid = GetUserId(username); - if (userid < 0) - { - return null; - } - return new MembershipUser(Membership.Provider.Name, username, userid, null, null, null, true, false, DateTime.MinValue, DateTime.MinValue, DateTime.MinValue, DateTime.MinValue, DateTime.MinValue); - } - - /// - /// Gets the id of the specified user. - /// - /// The name of the user. - /// An integer representing the id of the user. - public int GetUserId(string userName) - { - return GetUserId(userName, GetConnectionString(), UserTableName, UserIdColumn, UserNameColumn); - } - - internal static int GetUserId(string userName, string connectionString, string userTableName, string userIdColumn, string userNameColumn) - { - using (MySqlDatabaseWrapper dbConn = new MySqlDatabaseWrapper(connectionString)) - { - var user = dbConn.ExecuteQuerySingleRecord(string.Format("select {0} from {1} where {2} = ?;", userIdColumn, userTableName, userNameColumn), userName); - if (user != null) - return (int)user[userIdColumn]; - - return 0; - } - } - - public override int GetUserIdFromOAuth(string provider, string providerUserId) - { - IsValidOperation(true); - using (MySqlDatabaseWrapper dbConn = new MySqlDatabaseWrapper(GetConnectionString())) - { - var user = dbConn.ExecuteQuerySingleRecord(string.Format("select userid from {0} where upper(provider) = ? and upper(provideruserid)=?;", _oauthMembershipTable), provider.ToUpper(), providerUserId.ToUpper()); - if (user != null) - return (int)user["userid"]; - - return 0; - } - } - - public override int GetUserIdFromPasswordResetToken(string token) - { - IsValidOperation(true); - return GetUserIdFromPasswordResetToken(token, false); - } - - public override string GetOAuthTokenSecret(string token) - { - IsValidOperation(true); - using (MySqlDatabaseWrapper dbConn = new MySqlDatabaseWrapper(GetConnectionString())) - { - return dbConn.ExecuteScalar(string.Format("select secret from {0} where token=?;", _oauthTokenTable), token) as string; - } - } - - private int GetUserIdFromPasswordResetToken(string token, bool checkExpirationDate = false) - { - using (MySqlDatabaseWrapper dbConn = new MySqlDatabaseWrapper(GetConnectionString())) - { - var user = dbConn.ExecuteQuerySingleRecord(string.Format("select userid from {0} where PasswordVerificationToken = ? {1};", _membershipTable, (checkExpirationDate ? "and PasswordVerificationTokenExpirationDate > now()" : "")), token); - if (user != null) - return (int)user["userid"]; - - return 0; - } - } - - public override string GetUserNameByEmail(string email) - { - IsValidOperation(false); - return _prevProvider.GetUserNameByEmail(email); - } - - public override string GetUserNameFromId(int userId) - { - IsValidOperation(true); - using (MySqlDatabaseWrapper dbConn = new MySqlDatabaseWrapper(GetConnectionString())) - { - return dbConn.ExecuteScalar(string.Format("select {0} from {1} where {2}=?;", UserNameColumn, UserTableName, UserIdColumn), userId) as string; - } - } - - public override bool HasLocalAccount(int userId) - { - IsValidOperation(true); - using (MySqlDatabaseWrapper dbConn = new MySqlDatabaseWrapper(GetConnectionString())) - { - return (dbConn.ExecuteQuery(string.Format("select userid from {0} where userid=?;", _membershipTable), userId).Count() > 0); - } - } - - public override bool IsConfirmed(string userName) - { - IsValidOperation(true); - if (string.IsNullOrEmpty(userName)) - NullArgumentException("username"); - int userid = GetUserId(userName); - if (userid <= 0) - InvalidUserException(userName); - return UserConfirmed(userid); - } - - public override void ReplaceOAuthRequestTokenWithAccessToken(string requestToken, string accessToken, string accessTokenSecret) - { - IsValidOperation(true); - using (MySqlDatabaseWrapper dbConn = new MySqlDatabaseWrapper(GetConnectionString())) - { - dbConn.ExecuteNonQuery(string.Format("delete from {0} where token=?", _oauthTokenTable), requestToken); - } - StoreOAuthRequestToken(accessToken, accessTokenSecret); - } - - public override string ResetPassword(string username, string answer) - { - IsValidOperation(false); - return _prevProvider.ResetPassword(username, answer); - } - - public override bool ResetPasswordWithToken(string token, string newPassword) - { - IsValidOperation(true); - if (string.IsNullOrEmpty(token)) - { - NullArgumentException("token"); - } - if (string.IsNullOrEmpty(newPassword)) - { - NullArgumentException("newPasword"); - } - int userid = GetUserIdFromPasswordResetToken(token, true); - if (userid <= 0) - { - return false; - } - bool passUpdated = UpdatePassword(userid, newPassword) > 0; - if (passUpdated) - { - using (MySqlDatabaseWrapper dbConn = new MySqlDatabaseWrapper(GetConnectionString())) - { - if (dbConn.ExecuteNonQuery(string.Format("update {0} set PasswordVerificationToken=null, PasswordVerificationTokenExpirationDate=null where userid=?;", _membershipTable), userid) <= 0) - { - throw new ProviderException(string.Format(Resources.ClearPassTokenFailed, userid, _membershipTable)); - } - } - } - return passUpdated; - } - - public override void StoreOAuthRequestToken(string requestToken, string requestTokenSecret) - { - IsValidOperation(true); - string secret = GetOAuthTokenSecret(requestToken); - if (secret != null) - { - if (secret.Equals(requestTokenSecret, StringComparison.OrdinalIgnoreCase)) - return; - using (MySqlDatabaseWrapper dbConn = new MySqlDatabaseWrapper(GetConnectionString())) - { - if (dbConn.ExecuteNonQuery(string.Format("update {0} set secret=? where token=?;", _oauthTokenTable), requestTokenSecret, requestToken) <= 0) - throw new ProviderException(string.Format(Resources.UpdateTokenFailed, requestTokenSecret)); - } - } - else - { - using (MySqlDatabaseWrapper dbConn = new MySqlDatabaseWrapper(GetConnectionString())) - { - if (dbConn.ExecuteNonQuery(string.Format("insert into {0} (token, secret) values (?,?);", _oauthTokenTable), requestTokenSecret, requestToken) <= 0) - throw new ProviderException(string.Format(Resources.SaveTokenFailed, requestTokenSecret)); - } - } - } - - public override bool UnlockUser(string userName) - { - IsValidOperation(false); - return _prevProvider.UnlockUser(userName); - } - - public override void UpdateUser(MembershipUser user) - { - IsValidOperation(false); - _prevProvider.UpdateUser(user); - } - - public override bool ValidateUser(string username, string password) - { - if (!Initialized) - return _prevProvider.ValidateUser(username, password); - if (string.IsNullOrEmpty(username)) - NullArgumentException("userName"); - if (string.IsNullOrEmpty(password)) - NullArgumentException("password"); - int userid = GetUserId(username); - if (userid > 0) - { - if (!UserConfirmed(userid)) - return false; - else - return VerifyPassword(userid, password, GetHashedUserPassword(userid)); - } - return false; - } - - #region Properties - public override string ApplicationName - { - get - { - if (Initialized) - throw new NotSupportedException(); - else - return _prevProvider.ApplicationName; - } - set - { - if (Initialized) - throw new NotSupportedException(); - else - _prevProvider.ApplicationName = value; - } - } - - /// - /// Gets or sets the connection string. - /// - public string ConnectionString - { get; set; } - - /// - /// Gets or sets the name associated to the connection string when stored in the configuration manager. - /// - public string ConnectionStringName - { get; set; } - - public override bool EnablePasswordReset - { - get - { - return Initialized ? false : _prevProvider.EnablePasswordReset; - } - } - - public override bool EnablePasswordRetrieval - { - get - { - return Initialized ? false : _prevProvider.EnablePasswordRetrieval; - } - } - - public override int MaxInvalidPasswordAttempts - { - get - { - return Initialized ? Int32.MaxValue : _prevProvider.MaxInvalidPasswordAttempts; - } - } - - public override int MinRequiredPasswordLength - { - get - { - return Initialized ? 7 : _prevProvider.MinRequiredPasswordLength; - } - } - - public override int MinRequiredNonAlphanumericCharacters - { - get - { - return Initialized ? 1 : _prevProvider.MinRequiredNonAlphanumericCharacters; - } - } - - public override int PasswordAttemptWindow - { - get - { - return Initialized ? Int32.MaxValue : _prevProvider.PasswordAttemptWindow; - } - } - - public override MembershipPasswordFormat PasswordFormat - { - get - { - return Initialized ? MembershipPasswordFormat.Hashed : _prevProvider.PasswordFormat; - } - } - - public override string PasswordStrengthRegularExpression - { - get - { - return Initialized ? string.Empty : _prevProvider.PasswordStrengthRegularExpression; - } - } - - /// - /// Gets or sets the name of this provider. - /// - public string ProviderName - { get; set; } - - public override bool RequiresQuestionAndAnswer - { - get - { - return Initialized ? false : _prevProvider.RequiresQuestionAndAnswer; - } - } - - public override bool RequiresUniqueEmail - { - get - { - return Initialized ? false : _prevProvider.RequiresUniqueEmail; - } - } - - /// - /// Gets the name of the table storing user information. - /// - public string UserTableName - { - get - { - if (string.IsNullOrEmpty(_userTableName)) - throw new InvalidOperationException(Resources.UserTableNameNotInitilized); - - return _userTableName; - } - internal set - { - _userTableName = value; - } - } - - /// - /// Gets the name of the column storing the user ids. - /// - public string UserIdColumn - { - get - { - if (string.IsNullOrEmpty(_userIdColumn)) - throw new InvalidOperationException(Resources.UserIdColumnNotInitialized); - - return _userIdColumn; - } - internal set - { - _userIdColumn = value; - } - } - - /// - /// Gets the name of the column storing the user names. - /// - public string UserNameColumn - { - get - { - if (string.IsNullOrEmpty(_userNameColumn)) - throw new InvalidOperationException(Resources.UserNameColumnNotInitialized); - - return _userNameColumn; - } - internal set - { - _userNameColumn = value; - } - } - - #endregion - - #region Private_Internal - - internal void CreateTables() - { - string connString = GetConnectionString(); - using (MySqlDatabaseWrapper dbConn = new MySqlDatabaseWrapper(connString)) - { - if (!VerifyIfTableExists(connString, UserTableName)) - { - dbConn.ExecuteNonQuery(string.Format("create table {0} ({1} int not null primary key auto_increment, {2} varchar(250) not null unique);", UserTableName, UserIdColumn, UserNameColumn)); - } - - //create schema - string schema = SchemaManager.GetSchema(11); - dbConn.ExecuteNonQuery(schema); - } - } - - internal void ValidateUserTable() - { - if (!VerifyIfTableExists(GetConnectionString(), UserTableName)) - { - throw new InvalidOperationException(string.Format(Resources.UserTableNotFound, UserTableName)); - } - } - - internal bool Initialized - { - get; - set; - } - - private string GetConnectionString() - { - if (!string.IsNullOrEmpty(ConnectionString)) - return ConnectionString; - else - { - ConnectionStringSettings connString = ConfigurationManager.ConnectionStrings[ConnectionStringName]; - if (connString != null) - return connString.ConnectionString; - } - - if (!string.IsNullOrEmpty(_connString)) - return _connString; - throw new InvalidOperationException(Resources.NoConnString); - } - - internal static bool VerifyIfTableExists(string connectionString, string tableName) - { - using (MySqlDatabaseWrapper dbConn = new MySqlDatabaseWrapper(connectionString)) - { - var tables = dbConn.ExecuteQuery("show tables;"); - return tables.Where(record => record[0].ToString().Equals(tableName, StringComparison.OrdinalIgnoreCase)).Count() > 0; - } - } - - internal string GetHashedUserPassword(int userId) - { - using (MySqlDatabaseWrapper dbConn = new MySqlDatabaseWrapper(GetConnectionString())) - { - var userPassword = dbConn.ExecuteQuerySingleRecord(string.Format("select password from {0} where userid=?;", _membershipTable), userId); - if (userPassword != null) - return userPassword[0].ToString(); - return null; - } - } - - internal string HashPassword(string password) - { - if (string.IsNullOrEmpty(password)) - { - throw new ArgumentException(Resources.InvalidArgument, password); - } - - Rfc2898DeriveBytes rfc2898 = new Rfc2898DeriveBytes(password, 16, 1000); - byte[] salt = rfc2898.Salt; - byte[] passBytes = rfc2898.GetBytes(32); - byte[] result = new byte[48]; - Buffer.BlockCopy(salt, 0, result, 0, 16); - Buffer.BlockCopy(passBytes, 0, result, 16, 32); - return Convert.ToBase64String(result); - } - - internal bool VerifyPassword(int userid, string password, string hashedPassword) - { - if (string.IsNullOrEmpty(password)) - { - throw new ArgumentException(Resources.InvalidArgument, password); - } - if (string.IsNullOrEmpty(hashedPassword)) - { - throw new ArgumentException(Resources.InvalidArgument, hashedPassword); - } - byte[] hashed = Convert.FromBase64String(hashedPassword); - if (hashed.Length != 48) - { - return false; - } - byte[] salt = new byte[16]; - byte[] passBytes = new byte[32]; - Buffer.BlockCopy(hashed, 0, salt, 0, 16); - Buffer.BlockCopy(hashed, 16, passBytes, 0, 32); - - Rfc2898DeriveBytes rfc2898 = new Rfc2898DeriveBytes(password, salt, 1000); - bool validation = CompareBuffer(rfc2898.GetBytes(32), passBytes); - using (MySqlDatabaseWrapper dbConn = new MySqlDatabaseWrapper(GetConnectionString())) - { - if (validation) - { - dbConn.ExecuteNonQuery(string.Format("update {0} set PasswordFailuresSinceLastSuccess=0 where userid=?;", _membershipTable), userid); - } - else - { - int failures = GetPasswordFailuresSinceLastSuccess(userid); - dbConn.ExecuteNonQuery(string.Format("update {0} set PasswordFailuresSinceLastSuccess=?, LastPasswordFailureDate=now() where userid=?;", _membershipTable), (failures == -1 ? 1 : failures + 1), userid); - } - } - return validation; - } - - internal bool CompareBuffer(byte[] source, byte[] target) - { - if (source == null || target == null || (source.Length != target.Length)) - return false; - for (int ctr = 0; ctr < target.Length; ctr++) - { - if (target[ctr] != source[ctr]) - return false; - } - - return true; - } - - private int UpdatePassword(int userId, string newPassword) - { - string hashedPass = HashPassword(newPassword); - if (hashedPass.Length > 128) - throw new ArgumentException(Resources.PasswordExceedsMaxLength, newPassword); - using (MySqlDatabaseWrapper dbConn = new MySqlDatabaseWrapper(GetConnectionString())) - { - return dbConn.ExecuteNonQuery(string.Format("update {0} set password=?, PasswordChangedDate=now(), PasswordSalt='' where userid=?;", _membershipTable), hashedPass, userId); - } - } - - internal void IsValidOperation(bool currentProvider) - { - switch (currentProvider) - { - case true: - if (!Initialized) - ProviderException(); - break; - case false: - if (Initialized) - PreviousProviderException(); - break; - } - } - - private void ProviderException() - { - throw new Exception(Resources.SimpleMembershipNotInitialized); - } - - private void PreviousProviderException() - { - throw new NotSupportedException(Resources.PreviousProviderException); - } - - private void InvalidUserException(string userName) - { - throw new Exception(string.Format(Resources.InvalidUser, userName, UserTableName)); - } - - internal static void NullArgumentException(string parameterName) - { - throw new ArgumentException(Resources.InvalidArgument, parameterName); - } - - private string GenerateToken() - { - RNGCryptoServiceProvider provider = new RNGCryptoServiceProvider(); - byte[] data = new byte[16]; - provider.GetBytes(data); - return HttpServerUtility.UrlTokenEncode(data); - } - - private void CreateUserInUserTable(string userName, IDictionary values) - { - IsValidOperation(true); - var userid = GetUserId(userName); - if (userid > 0) - { - throw new MembershipCreateUserException(MembershipCreateStatus.DuplicateUserName); - } - StringBuilder columns = new StringBuilder(); - columns.Append(UserNameColumn); - StringBuilder args = new StringBuilder(); - args.Append("?"); - var argsValues = new List(); - argsValues.Add(userName); - - if (values != null) - { - foreach (var value in values) - { - if (string.Equals(UserNameColumn, value.Key, StringComparison.OrdinalIgnoreCase)) - continue; - columns.Append(string.Format(",{0}", value.Key)); - args.Append(",?"); - argsValues.Add(value.Value != null ? value.Value : DBNull.Value); - } - } - using (MySqlDatabaseWrapper dbConn = new MySqlDatabaseWrapper(GetConnectionString())) - { - string query = string.Format("insert into {0} ({1}) values({2})", UserTableName, columns.ToString(), args.ToString()); - if (dbConn.ExecuteNonQuery(query, argsValues.ToArray()) < 1) - { - throw new MembershipCreateUserException(MembershipCreateStatus.ProviderError); - } - } - } - - private bool UserConfirmed(int userId) - { - using (MySqlDatabaseWrapper dbConn = new MySqlDatabaseWrapper(GetConnectionString())) - { - return ((long)dbConn.ExecuteScalar(string.Format("select count(*) from {0} where userid=? and isconfirmed=1;", _membershipTable), userId)) > 0; - } - } - #endregion - } -} +// Copyright © 2014, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySql.Web.Common; +using MySql.Web.General; +using MySql.Web.Properties; +using System; +using System.Collections.Generic; +using System.Configuration; +using System.Configuration.Provider; +using System.Globalization; +using System.Linq; +using System.Security.Cryptography; +using System.Text; +using System.Web; +using System.Web.Hosting; +using System.Web.Security; +using WebMatrix.WebData; + +namespace MySql.Web.Security +{ + /// + /// Manages storage of simple membership information for an ASP.NET application in a MySQL database. + /// + public class MySqlSimpleMembershipProvider : ExtendedMembershipProvider + { + #region Private + private readonly MembershipProvider _prevProvider; + + Application _app; + bool _enablePwdReset; + bool _enablePwdRetrival; + int _maxPwdAttempts; + int _minReqNonAlphanumericalChars; + int _minReqPwdLength; + int _pwdAttemptWindow; + MembershipPasswordFormat _pwdFormat; + string _pwdStrenghtRegex; + bool _reqQuestionAnswer; + bool _reqUniqueEmail; + string _connString; + string _userTableName; + string _userIdColumn; + string _userNameColumn; + bool _autoGenerateTables; + private readonly string _membershipTable = "webpages_membership"; + private readonly string _oauthMembershipTable = "webpages_oauthmembership"; + private readonly string _userInRolesTable = "webpages_usersinroles"; + private readonly string _oauthTokenTable = "webpages_oauthtoken"; + + private static string GetConfigValue(string configVal, string defaultVal) + { + return !string.IsNullOrEmpty(configVal) ? configVal : defaultVal; + } + #endregion + public MySqlSimpleMembershipProvider() + : this(null) + { } + + public MySqlSimpleMembershipProvider(MembershipProvider previousProvider) + { + _prevProvider = previousProvider; + if (_prevProvider != null) + { + _prevProvider.ValidatingPassword += delegate (object sender, ValidatePasswordEventArgs args) { this.OnValidatingPassword(args); }; + } + } + + public override void Initialize(string name, System.Collections.Specialized.NameValueCollection config) + { + if (config == null) + { + NullArgumentException("config"); + } + if (string.IsNullOrEmpty(name)) + { + name = "MySqlExtendedMembershipProvider"; + } + if (string.IsNullOrEmpty(config["description"])) + { + config.Remove("description"); + config.Add("description", string.Format("MySql Default {0} Description", name)); + } + + base.Initialize(name, config); + + var appName = GetConfigValue(config["applicationName"], HostingEnvironment.SiteName); + _maxPwdAttempts = Int32.Parse(GetConfigValue(config["maxInvalidPasswordAttempts"], "5"), CultureInfo.InvariantCulture); + _pwdAttemptWindow = Int32.Parse(GetConfigValue(config["passwordAttemptWindow"], "10"), CultureInfo.InvariantCulture); + _minReqNonAlphanumericalChars = Int32.Parse(GetConfigValue(config["minRequiredNonalphanumericCharacters"], "1"), CultureInfo.InvariantCulture); + _minReqPwdLength = Int32.Parse(GetConfigValue(config["minRequiredPasswordLength"], "7"), CultureInfo.InvariantCulture); + _pwdStrenghtRegex = GetConfigValue(config["passwordStrengthRegularExpression"], ""); + _enablePwdReset = bool.Parse(GetConfigValue(config["enablePasswordReset"], "True")); + _enablePwdRetrival = bool.Parse(GetConfigValue(config["enablePasswordRetrieval"], "False")); + _reqQuestionAnswer = bool.Parse(GetConfigValue(config["requiresQuestionAndAnswer"], "False")); + _reqUniqueEmail = bool.Parse(GetConfigValue(config["requiresUniqueEmail"], "True")); + + var pwdFormat = !string.IsNullOrEmpty(config["passwordFormat"]) ? config["passwordFormat"].ToString().ToLowerInvariant() : "hashed"; + + switch (pwdFormat) + { + case "hashed": + _pwdFormat = MembershipPasswordFormat.Hashed; + break; + case "encrypted": + _pwdFormat = MembershipPasswordFormat.Encrypted; + break; + case "clear": + _pwdFormat = MembershipPasswordFormat.Clear; + break; + default: + throw new ProviderException(Resources.PasswordFormatNotSupported); + } + + if (_pwdFormat == MembershipPasswordFormat.Hashed) + { + if (_enablePwdRetrival) + throw new ProviderException(Resources.CannotRetrieveHashedPasswords); + } + + _app = new Application(appName, base.Description); + _connString = ConfigUtility.GetConnectionString(config); + if (string.IsNullOrEmpty(_connString)) return; + + UserTableName = GetConfigValue(config["userTableName"], ""); + UserIdColumn = GetConfigValue(config["userIdColumn"], ""); + UserNameColumn = GetConfigValue(config["userNameColumn"], ""); + _autoGenerateTables = bool.Parse(GetConfigValue(config["autoGenerateTables"], "True")); + if (_autoGenerateTables) + CreateTables(); + else + ValidateUserTable(); + + Initialized = true; + } + + public override bool ChangePassword(string username, string oldPassword, string newPassword) + { + if (!Initialized) + { + _prevProvider.ChangePassword(username, oldPassword, newPassword); + } + + if (string.IsNullOrEmpty(username)) + NullArgumentException("username"); + if (string.IsNullOrEmpty(oldPassword)) + NullArgumentException("oldPassword"); + if (string.IsNullOrEmpty(newPassword)) + NullArgumentException("newPassword"); + + int userid = GetUserId(username); + if (userid <= 0) + { + return false; + } + if (VerifyPassword(userid, oldPassword, GetHashedUserPassword(userid))) + { + return UpdatePassword(userid, newPassword) > 0; + } + + return false; + } + + public override bool ChangePasswordQuestionAndAnswer(string username, string password, string newPasswordQuestion, string newPasswordAnswer) + { + IsValidOperation(false); + return _prevProvider.ChangePasswordQuestionAndAnswer(username, password, newPasswordQuestion, newPasswordAnswer); + } + + public override bool ConfirmAccount(string accountConfirmationToken) + { + IsValidOperation(true); + using (MySqlDatabaseWrapper dbConn = new MySqlDatabaseWrapper(GetConnectionString())) + { + var token = dbConn.ExecuteQuerySingleRecord(string.Format("select userid, confirmationtoken from {0} where confirmationtoken=?", _membershipTable), accountConfirmationToken); + if (token == null || (token != null && string.IsNullOrEmpty(token[1].ToString()))) + { + return false; + } + return dbConn.ExecuteNonQuery(string.Format("update {0} set isconfirmed=1 where userid=?;", _membershipTable), (int)token[0]) > 0; + } + } + + public override bool ConfirmAccount(string userName, string accountConfirmationToken) + { + var userid = GetUserId(userName); + if (userid <= 0) + return false; + + using (MySqlDatabaseWrapper dbConn = new MySqlDatabaseWrapper(GetConnectionString())) + { + var token = dbConn.ExecuteQuerySingleRecord(string.Format("select userid, confirmationtoken from {0} where confirmationtoken=? and userid=?", _membershipTable), accountConfirmationToken, userid); + if (token == null || (token != null && string.IsNullOrEmpty(token[1].ToString()))) + { + return false; + } + return dbConn.ExecuteNonQuery(string.Format("update {0} set isconfirmed=1 where userid=?;", _membershipTable), userid) > 0; + } + } + + public override string CreateAccount(string userName, string password, bool requireConfirmationToken) + { + IsValidOperation(true); + if (string.IsNullOrEmpty(userName)) + NullArgumentException(userName); + if (string.IsNullOrEmpty(password)) + NullArgumentException(password); + var hashedPass = HashPassword(password); + if (hashedPass.Length > 128) + throw new ArgumentException(Resources.PasswordExceedsMaxLength, password); + + using (MySqlDatabaseWrapper dbConn = new MySqlDatabaseWrapper(GetConnectionString())) + { + var userid = GetUserId(userName); + if (userid <= 0) + { + throw new InvalidOperationException(string.Format(Resources.UserNotFound, UserTableName)); + } + if (dbConn.ExecuteQuerySingleRecord(string.Format("select userid from {0} where userid=?;", _membershipTable), userid) != null) + { + throw new InvalidOperationException(string.Format(Resources.UserAlreadyExists, userName)); + } + object token = DBNull.Value; + if (requireConfirmationToken) + token = GenerateToken(); + + string insertQuery = string.Format("insert into {0} (userid, createdate, confirmationtoken, isconfirmed, password, passwordchangeddate, passwordsalt) values(?,now(),?,?,?,now(),?)", _membershipTable); + if (dbConn.ExecuteNonQuery(insertQuery, userid, token, !requireConfirmationToken, hashedPass, string.Empty) <= 0) + { + throw new MembershipCreateUserException(MembershipCreateStatus.ProviderError); + } + return token == DBNull.Value ? null : token.ToString(); + } + } + + public override void CreateOrUpdateOAuthAccount(string provider, string providerUserId, string userName) + { + IsValidOperation(true); + if (string.IsNullOrEmpty(userName)) + NullArgumentException(userName); + var userid = GetUserId(userName); + if (userid <= 0) + { + throw new InvalidOperationException(string.Format(Resources.UserNotFound, UserTableName)); + } + var oauthUserId = GetUserIdFromOAuth(provider, providerUserId); + using (MySqlDatabaseWrapper dbConn = new MySqlDatabaseWrapper(GetConnectionString())) + { + if (oauthUserId == 0) + { + if (dbConn.ExecuteNonQuery(string.Format("insert into {0} (provider, provideruserid, userid) values(?,?,?)", _oauthMembershipTable), provider, providerUserId, userid) <= 0) + { + throw new MembershipCreateUserException(MembershipCreateStatus.ProviderError); + } + } + else + { + if (dbConn.ExecuteNonQuery(string.Format("update {0} set userid=? where upper(provider) = ? and upper(provideruserid)=?;", _oauthMembershipTable), userid, provider.ToUpper(), providerUserId.ToUpper()) <= 0) + { + throw new MembershipCreateUserException(MembershipCreateStatus.ProviderError); + } + } + } + } + + public override MembershipUser CreateUser(string username, string password, string email, string passwordQuestion, string passwordAnswer, bool isApproved, object providerUserKey, out MembershipCreateStatus status) + { + IsValidOperation(false); + return _prevProvider.CreateUser(username, password, email, passwordQuestion, passwordAnswer, isApproved, providerUserKey, out status); + } + + public override string CreateUserAndAccount(string userName, string password, bool requireConfirmation, IDictionary values) + { + IsValidOperation(true); + CreateUserInUserTable(userName, values); + return CreateAccount(userName, password, requireConfirmation); + } + + public override bool DeleteAccount(string userName) + { + IsValidOperation(true); + int userid = GetUserId(userName); + if (userid < 0) + { + return false; + } + using (MySqlDatabaseWrapper dbConn = new MySqlDatabaseWrapper(GetConnectionString())) + { + return (dbConn.ExecuteNonQuery(string.Format("delete from {0} where userid=?;", _membershipTable), userid) > 0); + } + } + + public override void DeleteOAuthAccount(string provider, string providerUserId) + { + IsValidOperation(true); + using (MySqlDatabaseWrapper dbConn = new MySqlDatabaseWrapper(GetConnectionString())) + { + if (dbConn.ExecuteNonQuery(string.Format("delete from {0} where upper(provider) = ? and upper(provideruserid)=?;", _oauthMembershipTable), provider.ToUpper(), providerUserId.ToUpper()) <= 0) + { + throw new Exception(string.Format(Resources.DeleteOAuthAccountFailed, provider, providerUserId)); + } + } + } + + public override void DeleteOAuthToken(string token) + { + IsValidOperation(true); + using (MySqlDatabaseWrapper dbConn = new MySqlDatabaseWrapper(GetConnectionString())) + { + dbConn.ExecuteNonQuery(string.Format("delete from {0} where token=?", _oauthTokenTable), token); + } + } + + public override bool DeleteUser(string username, bool deleteAllRelatedData) + { + if (!Initialized) + return _prevProvider.DeleteUser(username, deleteAllRelatedData); + + int userid = GetUserId(username); + if (userid < 0) + return false; + + using (MySqlDatabaseWrapper dbConn = new MySqlDatabaseWrapper(GetConnectionString())) + { + if (deleteAllRelatedData) + { + return dbConn.ExecuteInTransaction( + new List>() + { + new Tuple(string.Format("delete from {0} where {1}=?;", UserTableName, UserIdColumn), new object [] { userid }), + new Tuple(string.Format("delete from {0} where userid=?;", _oauthMembershipTable), new object [] { userid }), + new Tuple(string.Format("delete from {0} where userid=?;", _membershipTable), new object [] { userid }), + new Tuple(string.Format("delete from {0} where userid=?;", _userInRolesTable), new object [] { userid }) + }); + } + else + { + return (dbConn.ExecuteNonQuery(string.Format("delete from {0} where {1}=?;", UserTableName, UserIdColumn), userid) > 0); + } + } + } + + public override MembershipUserCollection FindUsersByEmail(string emailToMatch, int pageIndex, int pageSize, out int totalRecords) + { + IsValidOperation(false); + return _prevProvider.FindUsersByEmail(emailToMatch, pageIndex, pageSize, out totalRecords); + } + + public override MembershipUserCollection FindUsersByName(string usernameToMatch, int pageIndex, int pageSize, out int totalRecords) + { + IsValidOperation(false); + return _prevProvider.FindUsersByName(usernameToMatch, pageIndex, pageSize, out totalRecords); + } + + public override string GeneratePasswordResetToken(string userName, int tokenExpirationInMinutesFromNow) + { + IsValidOperation(true); + if (string.IsNullOrEmpty(userName)) + NullArgumentException("username"); + int userid = GetUserId(userName); + if (userid <= 0) + InvalidUserException(userName); + + if (UserConfirmed(userid)) + { + using (MySqlDatabaseWrapper dbConn = new MySqlDatabaseWrapper(GetConnectionString())) + { + string token = dbConn.ExecuteScalar(string.Format("select PasswordVerificationToken from {0} where userid=? and PasswordVerificationTokenExpirationDate > ?;", _membershipTable), userid, DateTime.Now) as string; + if (token != null) + { + token = GenerateToken(); + if (dbConn.ExecuteNonQuery(string.Format("update {0} set PasswordVerificationToken=?, PasswordVerificationTokenExpirationDate=? where userid=?;", _membershipTable), token, DateTime.Now.AddMinutes(tokenExpirationInMinutesFromNow), userid) <= 0) + { + throw new ProviderException(Resources.GeneratePassVerificationTokenFailed); + } + } + return token; + } + } + return null; + } + + public override ICollection GetAccountsForUser(string userName) + { + IsValidOperation(true); + int userid = GetUserId(userName); + if (userid > 0) + { + using (MySqlDatabaseWrapper dbConn = new MySqlDatabaseWrapper(GetConnectionString())) + { + var records = dbConn.ExecuteQuery(string.Format("select provider, provideruserid from {0} where userid=?", _oauthMembershipTable), userid); + if (records != null && records.Count() > 0) + { + var accounts = new List(); + records.ToList().ForEach(record => accounts.Add(new OAuthAccountData(record["provider"].ToString(), record["provideruserid"].ToString()))); + return accounts; + } + } + } + return new OAuthAccountData[0]; + } + + public override MembershipUserCollection GetAllUsers(int pageIndex, int pageSize, out int totalRecords) + { + IsValidOperation(false); + return _prevProvider.GetAllUsers(pageIndex, pageSize, out totalRecords); + } + + public override DateTime GetCreateDate(string userName) + { + int userid = GetUserId(userName); + if (userid < 0) + InvalidUserException(userName); + + using (MySqlDatabaseWrapper dbConn = new MySqlDatabaseWrapper(GetConnectionString())) + { + var createDate = dbConn.ExecuteScalar(string.Format("select CreateDate from {0} where userid=?;", _membershipTable), userid); + if (createDate != null && createDate != DBNull.Value) + return (DateTime)createDate; + + return DateTime.MinValue; + } + } + + public override DateTime GetLastPasswordFailureDate(string userName) + { + int userid = GetUserId(userName); + if (userid < 0) + InvalidUserException(userName); + + using (MySqlDatabaseWrapper dbConn = new MySqlDatabaseWrapper(GetConnectionString())) + { + var failureDate = dbConn.ExecuteScalar(string.Format("select LastPasswordFailureDate from {0} where userid=?;", _membershipTable), userid); + if (failureDate != null && failureDate != DBNull.Value) + return (DateTime)failureDate; + + return DateTime.MinValue; + } + } + + public override int GetNumberOfUsersOnline() + { + IsValidOperation(false); + return _prevProvider.GetNumberOfUsersOnline(); + } + + public override string GetPassword(string username, string answer) + { + IsValidOperation(false); + return _prevProvider.GetPassword(username, answer); + } + + public override DateTime GetPasswordChangedDate(string userName) + { + int userid = GetUserId(userName); + if (userid < 0) + InvalidUserException(userName); + + using (MySqlDatabaseWrapper dbConn = new MySqlDatabaseWrapper(GetConnectionString())) + { + var changedDate = dbConn.ExecuteScalar(string.Format("select PasswordChangedDate from {0} where userid=?;", _membershipTable), userid); + if (changedDate != null) + return (DateTime)changedDate; + + return DateTime.MinValue; + } + } + + public override int GetPasswordFailuresSinceLastSuccess(string userName) + { + int userid = GetUserId(userName); + if (userid < 0) + InvalidUserException(userName); + + return GetPasswordFailuresSinceLastSuccess(userid); + } + + private int GetPasswordFailuresSinceLastSuccess(int userId) + { + using (MySqlDatabaseWrapper dbConn = new MySqlDatabaseWrapper(GetConnectionString())) + { + var failures = dbConn.ExecuteScalar(string.Format("select PasswordFailuresSinceLastSuccess from {0} where userid=?;", _membershipTable), userId); + if (failures != null) + return (int)failures; + + return -1; + } + } + + public override MembershipUser GetUser(object providerUserKey, bool userIsOnline) + { + IsValidOperation(false); + return _prevProvider.GetUser(providerUserKey, userIsOnline); + } + + public override MembershipUser GetUser(string username, bool userIsOnline) + { + if (!Initialized) + return _prevProvider.GetUser(username, userIsOnline); + + int userid = GetUserId(username); + if (userid < 0) + { + return null; + } + return new MembershipUser(Membership.Provider.Name, username, userid, null, null, null, true, false, DateTime.MinValue, DateTime.MinValue, DateTime.MinValue, DateTime.MinValue, DateTime.MinValue); + } + + /// + /// Gets the id of the specified user. + /// + /// The name of the user. + /// An integer representing the id of the user. + public int GetUserId(string userName) + { + return GetUserId(userName, GetConnectionString(), UserTableName, UserIdColumn, UserNameColumn); + } + + internal static int GetUserId(string userName, string connectionString, string userTableName, string userIdColumn, string userNameColumn) + { + using (MySqlDatabaseWrapper dbConn = new MySqlDatabaseWrapper(connectionString)) + { + var user = dbConn.ExecuteQuerySingleRecord(string.Format("select {0} from {1} where {2} = ?;", userIdColumn, userTableName, userNameColumn), userName); + if (user != null) + return (int)user[userIdColumn]; + + return 0; + } + } + + public override int GetUserIdFromOAuth(string provider, string providerUserId) + { + IsValidOperation(true); + using (MySqlDatabaseWrapper dbConn = new MySqlDatabaseWrapper(GetConnectionString())) + { + var user = dbConn.ExecuteQuerySingleRecord(string.Format("select userid from {0} where upper(provider) = ? and upper(provideruserid)=?;", _oauthMembershipTable), provider.ToUpper(), providerUserId.ToUpper()); + if (user != null) + return (int)user["userid"]; + + return 0; + } + } + + public override int GetUserIdFromPasswordResetToken(string token) + { + IsValidOperation(true); + return GetUserIdFromPasswordResetToken(token, false); + } + + public override string GetOAuthTokenSecret(string token) + { + IsValidOperation(true); + using (MySqlDatabaseWrapper dbConn = new MySqlDatabaseWrapper(GetConnectionString())) + { + return dbConn.ExecuteScalar(string.Format("select secret from {0} where token=?;", _oauthTokenTable), token) as string; + } + } + + private int GetUserIdFromPasswordResetToken(string token, bool checkExpirationDate = false) + { + using (MySqlDatabaseWrapper dbConn = new MySqlDatabaseWrapper(GetConnectionString())) + { + var user = dbConn.ExecuteQuerySingleRecord(string.Format("select userid from {0} where PasswordVerificationToken = ? {1};", _membershipTable, (checkExpirationDate ? "and PasswordVerificationTokenExpirationDate > now()" : "")), token); + if (user != null) + return (int)user["userid"]; + + return 0; + } + } + + public override string GetUserNameByEmail(string email) + { + IsValidOperation(false); + return _prevProvider.GetUserNameByEmail(email); + } + + public override string GetUserNameFromId(int userId) + { + IsValidOperation(true); + using (MySqlDatabaseWrapper dbConn = new MySqlDatabaseWrapper(GetConnectionString())) + { + return dbConn.ExecuteScalar(string.Format("select {0} from {1} where {2}=?;", UserNameColumn, UserTableName, UserIdColumn), userId) as string; + } + } + + public override bool HasLocalAccount(int userId) + { + IsValidOperation(true); + using (MySqlDatabaseWrapper dbConn = new MySqlDatabaseWrapper(GetConnectionString())) + { + return (dbConn.ExecuteQuery(string.Format("select userid from {0} where userid=?;", _membershipTable), userId).Count() > 0); + } + } + + public override bool IsConfirmed(string userName) + { + IsValidOperation(true); + if (string.IsNullOrEmpty(userName)) + NullArgumentException("username"); + int userid = GetUserId(userName); + if (userid <= 0) + InvalidUserException(userName); + return UserConfirmed(userid); + } + + public override void ReplaceOAuthRequestTokenWithAccessToken(string requestToken, string accessToken, string accessTokenSecret) + { + IsValidOperation(true); + using (MySqlDatabaseWrapper dbConn = new MySqlDatabaseWrapper(GetConnectionString())) + { + dbConn.ExecuteNonQuery(string.Format("delete from {0} where token=?", _oauthTokenTable), requestToken); + } + StoreOAuthRequestToken(accessToken, accessTokenSecret); + } + + public override string ResetPassword(string username, string answer) + { + IsValidOperation(false); + return _prevProvider.ResetPassword(username, answer); + } + + public override bool ResetPasswordWithToken(string token, string newPassword) + { + IsValidOperation(true); + if (string.IsNullOrEmpty(token)) + { + NullArgumentException("token"); + } + if (string.IsNullOrEmpty(newPassword)) + { + NullArgumentException("newPasword"); + } + int userid = GetUserIdFromPasswordResetToken(token, true); + if (userid <= 0) + { + return false; + } + bool passUpdated = UpdatePassword(userid, newPassword) > 0; + if (passUpdated) + { + using (MySqlDatabaseWrapper dbConn = new MySqlDatabaseWrapper(GetConnectionString())) + { + if (dbConn.ExecuteNonQuery(string.Format("update {0} set PasswordVerificationToken=null, PasswordVerificationTokenExpirationDate=null where userid=?;", _membershipTable), userid) <= 0) + { + throw new ProviderException(string.Format(Resources.ClearPassTokenFailed, userid, _membershipTable)); + } + } + } + return passUpdated; + } + + public override void StoreOAuthRequestToken(string requestToken, string requestTokenSecret) + { + IsValidOperation(true); + string secret = GetOAuthTokenSecret(requestToken); + if (secret != null) + { + if (secret.Equals(requestTokenSecret, StringComparison.OrdinalIgnoreCase)) + return; + using (MySqlDatabaseWrapper dbConn = new MySqlDatabaseWrapper(GetConnectionString())) + { + if (dbConn.ExecuteNonQuery(string.Format("update {0} set secret=? where token=?;", _oauthTokenTable), requestTokenSecret, requestToken) <= 0) + throw new ProviderException(string.Format(Resources.UpdateTokenFailed, requestTokenSecret)); + } + } + else + { + using (MySqlDatabaseWrapper dbConn = new MySqlDatabaseWrapper(GetConnectionString())) + { + if (dbConn.ExecuteNonQuery(string.Format("insert into {0} (token, secret) values (?,?);", _oauthTokenTable), requestTokenSecret, requestToken) <= 0) + throw new ProviderException(string.Format(Resources.SaveTokenFailed, requestTokenSecret)); + } + } + } + + public override bool UnlockUser(string userName) + { + IsValidOperation(false); + return _prevProvider.UnlockUser(userName); + } + + public override void UpdateUser(MembershipUser user) + { + IsValidOperation(false); + _prevProvider.UpdateUser(user); + } + + public override bool ValidateUser(string username, string password) + { + if (!Initialized) + return _prevProvider.ValidateUser(username, password); + if (string.IsNullOrEmpty(username)) + NullArgumentException("userName"); + if (string.IsNullOrEmpty(password)) + NullArgumentException("password"); + int userid = GetUserId(username); + if (userid > 0) + { + if (!UserConfirmed(userid)) + return false; + else + return VerifyPassword(userid, password, GetHashedUserPassword(userid)); + } + return false; + } + + #region Properties + public override string ApplicationName + { + get + { + if (Initialized) + throw new NotSupportedException(); + else + return _prevProvider.ApplicationName; + } + set + { + if (Initialized) + throw new NotSupportedException(); + else + _prevProvider.ApplicationName = value; + } + } + + /// + /// Gets or sets the connection string. + /// + public string ConnectionString + { get; set; } + + /// + /// Gets or sets the name associated to the connection string when stored in the configuration manager. + /// + public string ConnectionStringName + { get; set; } + + public override bool EnablePasswordReset + { + get + { + return Initialized ? false : _prevProvider.EnablePasswordReset; + } + } + + public override bool EnablePasswordRetrieval + { + get + { + return Initialized ? false : _prevProvider.EnablePasswordRetrieval; + } + } + + public override int MaxInvalidPasswordAttempts + { + get + { + return Initialized ? Int32.MaxValue : _prevProvider.MaxInvalidPasswordAttempts; + } + } + + public override int MinRequiredPasswordLength + { + get + { + return Initialized ? 7 : _prevProvider.MinRequiredPasswordLength; + } + } + + public override int MinRequiredNonAlphanumericCharacters + { + get + { + return Initialized ? 1 : _prevProvider.MinRequiredNonAlphanumericCharacters; + } + } + + public override int PasswordAttemptWindow + { + get + { + return Initialized ? Int32.MaxValue : _prevProvider.PasswordAttemptWindow; + } + } + + public override MembershipPasswordFormat PasswordFormat + { + get + { + return Initialized ? MembershipPasswordFormat.Hashed : _prevProvider.PasswordFormat; + } + } + + public override string PasswordStrengthRegularExpression + { + get + { + return Initialized ? string.Empty : _prevProvider.PasswordStrengthRegularExpression; + } + } + + /// + /// Gets or sets the name of this provider. + /// + public string ProviderName + { get; set; } + + public override bool RequiresQuestionAndAnswer + { + get + { + return Initialized ? false : _prevProvider.RequiresQuestionAndAnswer; + } + } + + public override bool RequiresUniqueEmail + { + get + { + return Initialized ? false : _prevProvider.RequiresUniqueEmail; + } + } + + /// + /// Gets the name of the table storing user information. + /// + public string UserTableName + { + get + { + if (string.IsNullOrEmpty(_userTableName)) + throw new InvalidOperationException(Resources.UserTableNameNotInitilized); + + return _userTableName; + } + internal set + { + _userTableName = value; + } + } + + /// + /// Gets the name of the column storing the user ids. + /// + public string UserIdColumn + { + get + { + if (string.IsNullOrEmpty(_userIdColumn)) + throw new InvalidOperationException(Resources.UserIdColumnNotInitialized); + + return _userIdColumn; + } + internal set + { + _userIdColumn = value; + } + } + + /// + /// Gets the name of the column storing the user names. + /// + public string UserNameColumn + { + get + { + if (string.IsNullOrEmpty(_userNameColumn)) + throw new InvalidOperationException(Resources.UserNameColumnNotInitialized); + + return _userNameColumn; + } + internal set + { + _userNameColumn = value; + } + } + + #endregion + + #region Private_Internal + + internal void CreateTables() + { + string connString = GetConnectionString(); + using (MySqlDatabaseWrapper dbConn = new MySqlDatabaseWrapper(connString)) + { + if (!VerifyIfTableExists(connString, UserTableName)) + { + dbConn.ExecuteNonQuery(string.Format("create table {0} ({1} int not null primary key auto_increment, {2} varchar(250) not null unique);", UserTableName, UserIdColumn, UserNameColumn)); + } + + //create schema + string schema = SchemaManager.GetSchema(11); + dbConn.ExecuteNonQuery(schema); + } + } + + internal void ValidateUserTable() + { + if (!VerifyIfTableExists(GetConnectionString(), UserTableName)) + { + throw new InvalidOperationException(string.Format(Resources.UserTableNotFound, UserTableName)); + } + } + + internal bool Initialized + { + get; + set; + } + + private string GetConnectionString() + { + if (!string.IsNullOrEmpty(ConnectionString)) + return ConnectionString; + else + { + ConnectionStringSettings connString = ConfigurationManager.ConnectionStrings[ConnectionStringName]; + if (connString != null) + return connString.ConnectionString; + } + + if (!string.IsNullOrEmpty(_connString)) + return _connString; + throw new InvalidOperationException(Resources.NoConnString); + } + + internal static bool VerifyIfTableExists(string connectionString, string tableName) + { + using (MySqlDatabaseWrapper dbConn = new MySqlDatabaseWrapper(connectionString)) + { + var tables = dbConn.ExecuteQuery("show tables;"); + return tables.Where(record => record[0].ToString().Equals(tableName, StringComparison.OrdinalIgnoreCase)).Count() > 0; + } + } + + internal string GetHashedUserPassword(int userId) + { + using (MySqlDatabaseWrapper dbConn = new MySqlDatabaseWrapper(GetConnectionString())) + { + var userPassword = dbConn.ExecuteQuerySingleRecord(string.Format("select password from {0} where userid=?;", _membershipTable), userId); + if (userPassword != null) + return userPassword[0].ToString(); + return null; + } + } + + internal string HashPassword(string password) + { + if (string.IsNullOrEmpty(password)) + { + throw new ArgumentException(Resources.InvalidArgument, password); + } + + Rfc2898DeriveBytes rfc2898 = new Rfc2898DeriveBytes(password, 16, 1000); + byte[] salt = rfc2898.Salt; + byte[] passBytes = rfc2898.GetBytes(32); + byte[] result = new byte[48]; + Buffer.BlockCopy(salt, 0, result, 0, 16); + Buffer.BlockCopy(passBytes, 0, result, 16, 32); + return Convert.ToBase64String(result); + } + + internal bool VerifyPassword(int userid, string password, string hashedPassword) + { + if (string.IsNullOrEmpty(password)) + { + throw new ArgumentException(Resources.InvalidArgument, password); + } + if (string.IsNullOrEmpty(hashedPassword)) + { + throw new ArgumentException(Resources.InvalidArgument, hashedPassword); + } + byte[] hashed = Convert.FromBase64String(hashedPassword); + if (hashed.Length != 48) + { + return false; + } + byte[] salt = new byte[16]; + byte[] passBytes = new byte[32]; + Buffer.BlockCopy(hashed, 0, salt, 0, 16); + Buffer.BlockCopy(hashed, 16, passBytes, 0, 32); + + Rfc2898DeriveBytes rfc2898 = new Rfc2898DeriveBytes(password, salt, 1000); + bool validation = CompareBuffer(rfc2898.GetBytes(32), passBytes); + using (MySqlDatabaseWrapper dbConn = new MySqlDatabaseWrapper(GetConnectionString())) + { + if (validation) + { + dbConn.ExecuteNonQuery(string.Format("update {0} set PasswordFailuresSinceLastSuccess=0 where userid=?;", _membershipTable), userid); + } + else + { + int failures = GetPasswordFailuresSinceLastSuccess(userid); + dbConn.ExecuteNonQuery(string.Format("update {0} set PasswordFailuresSinceLastSuccess=?, LastPasswordFailureDate=now() where userid=?;", _membershipTable), (failures == -1 ? 1 : failures + 1), userid); + } + } + return validation; + } + + internal bool CompareBuffer(byte[] source, byte[] target) + { + if (source == null || target == null || (source.Length != target.Length)) + return false; + for (int ctr = 0; ctr < target.Length; ctr++) + { + if (target[ctr] != source[ctr]) + return false; + } + + return true; + } + + private int UpdatePassword(int userId, string newPassword) + { + string hashedPass = HashPassword(newPassword); + if (hashedPass.Length > 128) + throw new ArgumentException(Resources.PasswordExceedsMaxLength, newPassword); + using (MySqlDatabaseWrapper dbConn = new MySqlDatabaseWrapper(GetConnectionString())) + { + return dbConn.ExecuteNonQuery(string.Format("update {0} set password=?, PasswordChangedDate=now(), PasswordSalt='' where userid=?;", _membershipTable), hashedPass, userId); + } + } + + internal void IsValidOperation(bool currentProvider) + { + switch (currentProvider) + { + case true: + if (!Initialized) + ProviderException(); + break; + case false: + if (Initialized) + PreviousProviderException(); + break; + } + } + + private void ProviderException() + { + throw new Exception(Resources.SimpleMembershipNotInitialized); + } + + private void PreviousProviderException() + { + throw new NotSupportedException(Resources.PreviousProviderException); + } + + private void InvalidUserException(string userName) + { + throw new Exception(string.Format(Resources.InvalidUser, userName, UserTableName)); + } + + internal static void NullArgumentException(string parameterName) + { + throw new ArgumentException(Resources.InvalidArgument, parameterName); + } + + private string GenerateToken() + { + RNGCryptoServiceProvider provider = new RNGCryptoServiceProvider(); + byte[] data = new byte[16]; + provider.GetBytes(data); + return HttpServerUtility.UrlTokenEncode(data); + } + + private void CreateUserInUserTable(string userName, IDictionary values) + { + IsValidOperation(true); + var userid = GetUserId(userName); + if (userid > 0) + { + throw new MembershipCreateUserException(MembershipCreateStatus.DuplicateUserName); + } + StringBuilder columns = new StringBuilder(); + columns.Append(UserNameColumn); + StringBuilder args = new StringBuilder(); + args.Append("?"); + var argsValues = new List(); + argsValues.Add(userName); + + if (values != null) + { + foreach (var value in values) + { + if (string.Equals(UserNameColumn, value.Key, StringComparison.OrdinalIgnoreCase)) + continue; + columns.Append(string.Format(",{0}", value.Key)); + args.Append(",?"); + argsValues.Add(value.Value != null ? value.Value : DBNull.Value); + } + } + using (MySqlDatabaseWrapper dbConn = new MySqlDatabaseWrapper(GetConnectionString())) + { + string query = string.Format("insert into {0} ({1}) values({2})", UserTableName, columns.ToString(), args.ToString()); + if (dbConn.ExecuteNonQuery(query, argsValues.ToArray()) < 1) + { + throw new MembershipCreateUserException(MembershipCreateStatus.ProviderError); + } + } + } + + private bool UserConfirmed(int userId) + { + using (MySqlDatabaseWrapper dbConn = new MySqlDatabaseWrapper(GetConnectionString())) + { + return ((long)dbConn.ExecuteScalar(string.Format("select count(*) from {0} where userid=? and isconfirmed=1;", _membershipTable), userId)) > 0; + } + } + #endregion + } +} diff --git a/MySql.Web/src/SimpleRoleProvider.cs b/MySql.Web/src/SimpleRoleProvider.cs index 3cdde662a..649402452 100644 --- a/MySql.Web/src/SimpleRoleProvider.cs +++ b/MySql.Web/src/SimpleRoleProvider.cs @@ -1,534 +1,534 @@ -// Copyright (c) 2014, 2020, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySql.Web.Common; -using MySql.Web.General; -using MySql.Web.Properties; -using System; -using System.Collections.Generic; -using System.Configuration.Provider; -using System.Globalization; -using System.Linq; -using System.Web.Hosting; -using System.Web.Security; -using WebMatrix.WebData; - -namespace MySql.Web.Security -{ - /// - /// Manages storage of simple role membership information for an ASP.NET application in a MySQL database. - /// - public class MySqlSimpleRoleProvider : SimpleRoleProvider - { - #region Private - private readonly RoleProvider _prevProvider; - - Application _app; - bool _enablePwdReset; - bool _enablePwdRetrival; - int _maxPwdAttempts; - int _minReqNonAlphanumericalChars; - int _minReqPwdLength; - int _pwdAttemptWindow; - MembershipPasswordFormat _pwdFormat; - string _pwdStrenghtRegex; - bool _reqQuestionAnswer; - bool _reqUniqueEmail; - string _userTableName; - string _userIdColumn; - string _userNameColumn; - bool _autoGenerateTables; - private readonly string _rolesTable = "webpages_Roles"; - private readonly string _userInRolesTable = "webpages_UsersInRoles"; - private static string GetConfigValue(string configVal, string defaultVal) - { - return !string.IsNullOrEmpty(configVal) ? configVal : defaultVal; - } - - private void NotInitializedException() - { - throw new Exception(Resources.SimpleMembershipNotInitialized); - } - - #endregion - public MySqlSimpleRoleProvider() - : this(null) - { } - - public MySqlSimpleRoleProvider(RoleProvider previousProvider) - { - _prevProvider = previousProvider; - } - - public override void Initialize(string name, System.Collections.Specialized.NameValueCollection config) - { - if (config == null) - { - throw new ArgumentNullException("config"); - } - if (string.IsNullOrEmpty(name)) - { - name = "MySqlExtendedMembershipProvider"; - } - if (string.IsNullOrEmpty(config["description"])) - { - config.Remove("description"); - config.Add("description", string.Format("MySql Default {0} Description", name)); - } - - base.Initialize(name, config); - - var appName = GetConfigValue(config["applicationName"], HostingEnvironment.SiteName); - _maxPwdAttempts = Int32.Parse(GetConfigValue(config["maxInvalidPasswordAttempts"], "5"), CultureInfo.InvariantCulture); - _pwdAttemptWindow = Int32.Parse(GetConfigValue(config["passwordAttemptWindow"], "10"), CultureInfo.InvariantCulture); - _minReqNonAlphanumericalChars = Int32.Parse(GetConfigValue(config["minRequiredNonalphanumericCharacters"], "1"), CultureInfo.InvariantCulture); - _minReqPwdLength = Int32.Parse(GetConfigValue(config["minRequiredPasswordLength"], "7"), CultureInfo.InvariantCulture); - _pwdStrenghtRegex = GetConfigValue(config["passwordStrengthRegularExpression"], ""); - _enablePwdReset = bool.Parse(GetConfigValue(config["enablePasswordReset"], "True")); - _enablePwdRetrival = bool.Parse(GetConfigValue(config["enablePasswordRetrieval"], "False")); - _reqQuestionAnswer = bool.Parse(GetConfigValue(config["requiresQuestionAndAnswer"], "False")); - _reqUniqueEmail = bool.Parse(GetConfigValue(config["requiresUniqueEmail"], "True")); - - var pwdFormat = !string.IsNullOrEmpty(config["passwordFormat"]) ? config["passwordFormat"].ToString().ToLowerInvariant() : "hashed"; - - switch (pwdFormat) - { - case "hashed": - _pwdFormat = MembershipPasswordFormat.Hashed; - break; - case "encrypted": - _pwdFormat = MembershipPasswordFormat.Encrypted; - break; - case "clear": - _pwdFormat = MembershipPasswordFormat.Clear; - break; - default: - throw new ProviderException(Resources.PasswordFormatNotSupported); - } - - if (_pwdFormat == MembershipPasswordFormat.Hashed) - { - if (_enablePwdRetrival) - throw new ProviderException(Resources.CannotRetrieveHashedPasswords); - } - - _app = new Application(appName, base.Description); - ConnectionString = ConfigUtility.GetConnectionString(config); - if (string.IsNullOrEmpty(ConnectionString)) return; - - UserTableName = GetConfigValue(config["userTableName"], ""); - UserIdColumn = GetConfigValue(config["userIdColumn"], ""); - UserNameColumn = GetConfigValue(config["userNameColumn"], ""); - _autoGenerateTables = bool.Parse(GetConfigValue(config["autoGenerateTables"], "True")); - if (_autoGenerateTables) - CreateTables(); - - Initialized = true; - } - - public override void AddUsersToRoles(string[] usernames, string[] roleNames) - { - if (!Initialized) - { - _prevProvider.AddUsersToRoles(usernames, roleNames); - } - else - { - if (usernames.Where(username => string.IsNullOrEmpty(username)).Count() > 0 || usernames.Where(username => string.IsNullOrEmpty(username)).Count() > 0) - throw new ArgumentException(Resources.InvalidArrayValue); - - using (MySqlDatabaseWrapper dbConn = new MySqlDatabaseWrapper(ConnectionString)) - { - foreach (var userid in GetUsersId(usernames)) - { - foreach (var roleid in GetRolesId(roleNames)) - { - if (userid > 0 && roleid > 0) - { - dbConn.ExecuteNonQuery(string.Format("insert into {0} (userid, roleid) values(?,?);", _userInRolesTable), userid, roleid); - } - } - } - } - } - } - - public override void CreateRole(string roleName) - { - if (!Initialized) - { - _prevProvider.CreateRole(roleName); - } - else - { - if (string.IsNullOrEmpty(roleName)) - MySqlSimpleMembershipProvider.NullArgumentException("roleName"); - - using (MySqlDatabaseWrapper dbConn = new MySqlDatabaseWrapper(ConnectionString)) - { - int roleid = GetRoleId(roleName); - if (roleid != 0) - { - throw new InvalidOperationException(string.Format(Resources.RoleAlreadyExists, roleName)); - } - if (dbConn.ExecuteNonQuery(string.Format("insert into {0} (rolename) values(?);", _rolesTable), roleName) <= 0) - { - throw new ProviderException(string.Format(Resources.CreateRoleFailed, roleName)); - } - } - } - } - - public override bool DeleteRole(string roleName, bool throwOnPopulatedRole) - { - if (!Initialized) - { - return _prevProvider.DeleteRole(roleName, throwOnPopulatedRole); - } - if (string.IsNullOrEmpty(roleName)) - MySqlSimpleMembershipProvider.NullArgumentException("roleName"); - - int roleid = GetRoleId(roleName); - if (roleid <= 0) - { - return false; - } - using (MySqlDatabaseWrapper dbConn = new MySqlDatabaseWrapper(ConnectionString)) - { - if (throwOnPopulatedRole) - { - if (IsRoleInUse(roleid)) - throw new InvalidOperationException(string.Format(Resources.RoleInUse, roleName)); - } - else - { - dbConn.ExecuteNonQuery(string.Format("delete from {0} where roleid=?;", _userInRolesTable), roleid); - } - return dbConn.ExecuteNonQuery(string.Format("delete from {0} where roleid=?;", _rolesTable), roleid) > 0; - } - } - - public override string[] FindUsersInRole(string roleName, string usernameToMatch) - { - if (!Initialized) - { - return _prevProvider.FindUsersInRole(roleName, usernameToMatch); - } - if (string.IsNullOrEmpty(roleName)) - MySqlSimpleMembershipProvider.NullArgumentException("roleName"); - if (string.IsNullOrEmpty(usernameToMatch)) - return GetUsersInRole(roleName); - - using (MySqlDatabaseWrapper dbConn = new MySqlDatabaseWrapper(ConnectionString)) - { - var usersName = dbConn.ExecuteQuery(string.Format("select ut.{0} from {1} as rt join {2} as urt on rt.roleid=urt.roleid join {3} as ut on rt.userid=ut.{4} where rt.rolename=? and ut.name like '%?%'", UserNameColumn, _rolesTable, _userInRolesTable, UserTableName, UserIdColumn), roleName, usernameToMatch); - if (usersName.Count() > 0) - return usersName.Select(username => username[0].ToString()).ToArray(); - } - return null; - } - - public override string[] GetAllRoles() - { - if (!Initialized) - return _prevProvider.GetAllRoles(); - - using (MySqlDatabaseWrapper dbConn = new MySqlDatabaseWrapper(ConnectionString)) - { - var roles = dbConn.ExecuteQuery(string.Format("select rolename from {0};", _rolesTable)); - if (roles.Count() > 0) - return roles.Select(role => role[0].ToString()).ToArray(); - } - return null; - } - - public override string[] GetRolesForUser(string username) - { - if (!Initialized) - return _prevProvider.GetRolesForUser(username); - if (string.IsNullOrEmpty(username)) - MySqlSimpleMembershipProvider.NullArgumentException("username"); - - string connString = ConnectionString; - int userid = MySqlSimpleMembershipProvider.GetUserId(username, connString, UserTableName, UserIdColumn, UserNameColumn); - if (userid > 0) - { - using (MySqlDatabaseWrapper dbConn = new MySqlDatabaseWrapper(connString)) - { - var roles = dbConn.ExecuteQuery(string.Format("select rt.rolename from {0} as urt join {1} as rt on urt.roleid = rt.roleid where urt.userid=?;", _userInRolesTable, _rolesTable), userid); - if (roles.Count() > 0) - return roles.Select(role => role[0].ToString()).ToArray(); - } - } - return null; - } - - public override string[] GetUsersInRole(string roleName) - { - if (!Initialized) - return _prevProvider.GetUsersInRole(roleName); - if (string.IsNullOrEmpty(roleName)) - MySqlSimpleMembershipProvider.NullArgumentException("roleName"); - - int roleid = GetRoleId(roleName); - if (roleid > 0) - { - using (MySqlDatabaseWrapper dbConn = new MySqlDatabaseWrapper(ConnectionString)) - { - var users = dbConn.ExecuteQuery(string.Format("select ut.{0} from {1} as urt join {2} as ut on urt.userid = ut.{3} where urt.roleid=?;", UserNameColumn, _userInRolesTable, UserTableName, UserIdColumn), roleid); - if (users.Count() > 0) - return users.Select(role => role[0].ToString()).ToArray(); - } - } - return null; - } - - public override bool IsUserInRole(string username, string roleName) - { - if (!Initialized) - return _prevProvider.IsUserInRole(username, roleName); - string connString = ConnectionString; - if (string.IsNullOrEmpty(username)) - MySqlSimpleMembershipProvider.NullArgumentException("username"); - if (string.IsNullOrEmpty(roleName)) - MySqlSimpleMembershipProvider.NullArgumentException("roleName"); - int userid = MySqlSimpleMembershipProvider.GetUserId(username, connString, UserTableName, UserIdColumn, UserNameColumn); - int roleid = GetRoleId(roleName); - if (userid <= 0 || roleid <= 0) - return false; - using (MySqlDatabaseWrapper dbConn = new MySqlDatabaseWrapper(connString)) - { - return (dbConn.ExecuteQuery(string.Format("select count(userid) from {0} where userid=? and roleid=?;", _userInRolesTable), userid, roleid)).Count() > 0; - } - } - - public override void RemoveUsersFromRoles(string[] usernames, string[] roleNames) - { - if (!Initialized) - _prevProvider.RemoveUsersFromRoles(usernames, roleNames); - else - { - if (usernames.Where(username => string.IsNullOrEmpty(username)).Count() > 0 || usernames.Where(username => string.IsNullOrEmpty(username)).Count() > 0) - throw new ArgumentException(Resources.InvalidArrayValue); - using (MySqlDatabaseWrapper dbConn = new MySqlDatabaseWrapper(ConnectionString)) - { - foreach (var userid in GetUsersId(usernames)) - { - foreach (var roleid in GetRolesId(roleNames)) - { - if (userid > 0 && roleid > 0) - { - dbConn.ExecuteNonQuery(string.Format("delete from {0} where userid=? and roleid=?;", _userInRolesTable), userid, roleid); - } - } - } - } - } - } - - public override bool RoleExists(string roleName) - { - if (!Initialized) - return _prevProvider.RoleExists(roleName); - return (GetRoleId(roleName) > 0); - } - - #region Properties - - public override string ApplicationName - { - get - { - if (Initialized) - { - throw new NotSupportedException(); - } - else - { - return _prevProvider.ApplicationName; - } - } - set - { - if (Initialized) - { - throw new NotSupportedException(); - } - else - { - _prevProvider.ApplicationName = value; - } - } - } - - /// - /// Gets or sets the connection string. - /// - public string ConnectionString { get; set; } - - /// - /// Gets or sets the name associated to the connection string when stored in the configuration manager. - /// - public string ConnectionStringName { get; set; } - - /// - /// Gets the name of the table storing user information. - /// - public string UserTableName - { - get - { - if (string.IsNullOrEmpty(_userTableName)) - throw new InvalidOperationException(Resources.UserTableNameNotInitilized); - - return _userTableName; - } - internal set - { - _userTableName = value; - } - } - - /// - /// Gets the name of the column storing the user ids. - /// - public string UserIdColumn - { - get - { - if (string.IsNullOrEmpty(_userIdColumn)) - throw new InvalidOperationException(Resources.UserIdColumnNotInitialized); - - return _userIdColumn; - } - internal set - { - _userIdColumn = value; - } - } - - /// - /// Gets the name of the column storing the user names. - /// - public string UserNameColumn - { - get - { - if (string.IsNullOrEmpty(_userNameColumn)) - throw new InvalidOperationException(Resources.UserNameColumnNotInitialized); - - return _userNameColumn; - } - internal set - { - _userNameColumn = value; - } - } - - #endregion - - #region Private_Internal - internal bool Initialized - { - get; - set; - } - - internal void CreateTables() - { - var connString = ConnectionString; - using (MySqlDatabaseWrapper dbConn = new MySqlDatabaseWrapper(connString)) - { - //create schema - string schema = SchemaManager.GetSchema(11); - dbConn.ExecuteNonQuery(schema); - } - } - - //private string GetConnectionString() - //{ - // if (!string.IsNullOrEmpty(ConnectionString)) - // return ConnectionString; - // else - // { - // ConnectionStringSettings connString = ConfigurationManager.ConnectionStrings[ConnectionStringName]; - // if (connString != null) - // return connString.ConnectionString; - // } - - // if (!string.IsNullOrEmpty(_connString)) - // return _connString; - // throw new InvalidOperationException(Resources.NoConnString); - //} - - private IEnumerable GetUsersId(string[] usersName) - { - foreach (string userName in usersName) - { - yield return MySqlSimpleMembershipProvider.GetUserId(userName, ConnectionString, UserTableName, UserIdColumn, UserNameColumn); - } - } - - private IEnumerable GetRolesId(string[] roles) - { - foreach (string role in roles) - { - yield return GetRoleId(role); - } - } - - internal int GetRoleId(string role) - { - using (MySqlDatabaseWrapper dbConn = new MySqlDatabaseWrapper(ConnectionString)) - { - var roleid = dbConn.ExecuteQuerySingleRecord(string.Format("select roleid from {0} where rolename=?;", _rolesTable), role); - if (roleid != null) - return (int)roleid[0]; - - return 0; - } - } - - private bool UserHasRole(int userid, int roleid) - { - using (MySqlDatabaseWrapper dbConn = new MySqlDatabaseWrapper(ConnectionString)) - { - return (dbConn.ExecuteQuery(string.Format("select count(*) from {0} where userid=? and roleid=?;", _userInRolesTable), userid, roleid).Count() > 0); - } - } - - private bool IsRoleInUse(int roleid) - { - using (MySqlDatabaseWrapper dbConn = new MySqlDatabaseWrapper(ConnectionString)) - { - return (dbConn.ExecuteQuery(string.Format("select count(*) from {0} where roleid=?;", _userInRolesTable), roleid).Count() > 0); - } - } - #endregion - } -} +// Copyright © 2014, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySql.Web.Common; +using MySql.Web.General; +using MySql.Web.Properties; +using System; +using System.Collections.Generic; +using System.Configuration.Provider; +using System.Globalization; +using System.Linq; +using System.Web.Hosting; +using System.Web.Security; +using WebMatrix.WebData; + +namespace MySql.Web.Security +{ + /// + /// Manages storage of simple role membership information for an ASP.NET application in a MySQL database. + /// + public class MySqlSimpleRoleProvider : SimpleRoleProvider + { + #region Private + private readonly RoleProvider _prevProvider; + + Application _app; + bool _enablePwdReset; + bool _enablePwdRetrival; + int _maxPwdAttempts; + int _minReqNonAlphanumericalChars; + int _minReqPwdLength; + int _pwdAttemptWindow; + MembershipPasswordFormat _pwdFormat; + string _pwdStrenghtRegex; + bool _reqQuestionAnswer; + bool _reqUniqueEmail; + string _userTableName; + string _userIdColumn; + string _userNameColumn; + bool _autoGenerateTables; + private readonly string _rolesTable = "webpages_Roles"; + private readonly string _userInRolesTable = "webpages_UsersInRoles"; + private static string GetConfigValue(string configVal, string defaultVal) + { + return !string.IsNullOrEmpty(configVal) ? configVal : defaultVal; + } + + private void NotInitializedException() + { + throw new Exception(Resources.SimpleMembershipNotInitialized); + } + + #endregion + public MySqlSimpleRoleProvider() + : this(null) + { } + + public MySqlSimpleRoleProvider(RoleProvider previousProvider) + { + _prevProvider = previousProvider; + } + + public override void Initialize(string name, System.Collections.Specialized.NameValueCollection config) + { + if (config == null) + { + throw new ArgumentNullException("config"); + } + if (string.IsNullOrEmpty(name)) + { + name = "MySqlExtendedMembershipProvider"; + } + if (string.IsNullOrEmpty(config["description"])) + { + config.Remove("description"); + config.Add("description", string.Format("MySql Default {0} Description", name)); + } + + base.Initialize(name, config); + + var appName = GetConfigValue(config["applicationName"], HostingEnvironment.SiteName); + _maxPwdAttempts = Int32.Parse(GetConfigValue(config["maxInvalidPasswordAttempts"], "5"), CultureInfo.InvariantCulture); + _pwdAttemptWindow = Int32.Parse(GetConfigValue(config["passwordAttemptWindow"], "10"), CultureInfo.InvariantCulture); + _minReqNonAlphanumericalChars = Int32.Parse(GetConfigValue(config["minRequiredNonalphanumericCharacters"], "1"), CultureInfo.InvariantCulture); + _minReqPwdLength = Int32.Parse(GetConfigValue(config["minRequiredPasswordLength"], "7"), CultureInfo.InvariantCulture); + _pwdStrenghtRegex = GetConfigValue(config["passwordStrengthRegularExpression"], ""); + _enablePwdReset = bool.Parse(GetConfigValue(config["enablePasswordReset"], "True")); + _enablePwdRetrival = bool.Parse(GetConfigValue(config["enablePasswordRetrieval"], "False")); + _reqQuestionAnswer = bool.Parse(GetConfigValue(config["requiresQuestionAndAnswer"], "False")); + _reqUniqueEmail = bool.Parse(GetConfigValue(config["requiresUniqueEmail"], "True")); + + var pwdFormat = !string.IsNullOrEmpty(config["passwordFormat"]) ? config["passwordFormat"].ToString().ToLowerInvariant() : "hashed"; + + switch (pwdFormat) + { + case "hashed": + _pwdFormat = MembershipPasswordFormat.Hashed; + break; + case "encrypted": + _pwdFormat = MembershipPasswordFormat.Encrypted; + break; + case "clear": + _pwdFormat = MembershipPasswordFormat.Clear; + break; + default: + throw new ProviderException(Resources.PasswordFormatNotSupported); + } + + if (_pwdFormat == MembershipPasswordFormat.Hashed) + { + if (_enablePwdRetrival) + throw new ProviderException(Resources.CannotRetrieveHashedPasswords); + } + + _app = new Application(appName, base.Description); + ConnectionString = ConfigUtility.GetConnectionString(config); + if (string.IsNullOrEmpty(ConnectionString)) return; + + UserTableName = GetConfigValue(config["userTableName"], ""); + UserIdColumn = GetConfigValue(config["userIdColumn"], ""); + UserNameColumn = GetConfigValue(config["userNameColumn"], ""); + _autoGenerateTables = bool.Parse(GetConfigValue(config["autoGenerateTables"], "True")); + if (_autoGenerateTables) + CreateTables(); + + Initialized = true; + } + + public override void AddUsersToRoles(string[] usernames, string[] roleNames) + { + if (!Initialized) + { + _prevProvider.AddUsersToRoles(usernames, roleNames); + } + else + { + if (usernames.Where(username => string.IsNullOrEmpty(username)).Count() > 0 || usernames.Where(username => string.IsNullOrEmpty(username)).Count() > 0) + throw new ArgumentException(Resources.InvalidArrayValue); + + using (MySqlDatabaseWrapper dbConn = new MySqlDatabaseWrapper(ConnectionString)) + { + foreach (var userid in GetUsersId(usernames)) + { + foreach (var roleid in GetRolesId(roleNames)) + { + if (userid > 0 && roleid > 0) + { + dbConn.ExecuteNonQuery(string.Format("insert into {0} (userid, roleid) values(?,?);", _userInRolesTable), userid, roleid); + } + } + } + } + } + } + + public override void CreateRole(string roleName) + { + if (!Initialized) + { + _prevProvider.CreateRole(roleName); + } + else + { + if (string.IsNullOrEmpty(roleName)) + MySqlSimpleMembershipProvider.NullArgumentException("roleName"); + + using (MySqlDatabaseWrapper dbConn = new MySqlDatabaseWrapper(ConnectionString)) + { + int roleid = GetRoleId(roleName); + if (roleid != 0) + { + throw new InvalidOperationException(string.Format(Resources.RoleAlreadyExists, roleName)); + } + if (dbConn.ExecuteNonQuery(string.Format("insert into {0} (rolename) values(?);", _rolesTable), roleName) <= 0) + { + throw new ProviderException(string.Format(Resources.CreateRoleFailed, roleName)); + } + } + } + } + + public override bool DeleteRole(string roleName, bool throwOnPopulatedRole) + { + if (!Initialized) + { + return _prevProvider.DeleteRole(roleName, throwOnPopulatedRole); + } + if (string.IsNullOrEmpty(roleName)) + MySqlSimpleMembershipProvider.NullArgumentException("roleName"); + + int roleid = GetRoleId(roleName); + if (roleid <= 0) + { + return false; + } + using (MySqlDatabaseWrapper dbConn = new MySqlDatabaseWrapper(ConnectionString)) + { + if (throwOnPopulatedRole) + { + if (IsRoleInUse(roleid)) + throw new InvalidOperationException(string.Format(Resources.RoleInUse, roleName)); + } + else + { + dbConn.ExecuteNonQuery(string.Format("delete from {0} where roleid=?;", _userInRolesTable), roleid); + } + return dbConn.ExecuteNonQuery(string.Format("delete from {0} where roleid=?;", _rolesTable), roleid) > 0; + } + } + + public override string[] FindUsersInRole(string roleName, string usernameToMatch) + { + if (!Initialized) + { + return _prevProvider.FindUsersInRole(roleName, usernameToMatch); + } + if (string.IsNullOrEmpty(roleName)) + MySqlSimpleMembershipProvider.NullArgumentException("roleName"); + if (string.IsNullOrEmpty(usernameToMatch)) + return GetUsersInRole(roleName); + + using (MySqlDatabaseWrapper dbConn = new MySqlDatabaseWrapper(ConnectionString)) + { + var usersName = dbConn.ExecuteQuery(string.Format("select ut.{0} from {1} as rt join {2} as urt on rt.roleid=urt.roleid join {3} as ut on rt.userid=ut.{4} where rt.rolename=? and ut.name like '%?%'", UserNameColumn, _rolesTable, _userInRolesTable, UserTableName, UserIdColumn), roleName, usernameToMatch); + if (usersName.Count() > 0) + return usersName.Select(username => username[0].ToString()).ToArray(); + } + return null; + } + + public override string[] GetAllRoles() + { + if (!Initialized) + return _prevProvider.GetAllRoles(); + + using (MySqlDatabaseWrapper dbConn = new MySqlDatabaseWrapper(ConnectionString)) + { + var roles = dbConn.ExecuteQuery(string.Format("select rolename from {0};", _rolesTable)); + if (roles.Count() > 0) + return roles.Select(role => role[0].ToString()).ToArray(); + } + return null; + } + + public override string[] GetRolesForUser(string username) + { + if (!Initialized) + return _prevProvider.GetRolesForUser(username); + if (string.IsNullOrEmpty(username)) + MySqlSimpleMembershipProvider.NullArgumentException("username"); + + string connString = ConnectionString; + int userid = MySqlSimpleMembershipProvider.GetUserId(username, connString, UserTableName, UserIdColumn, UserNameColumn); + if (userid > 0) + { + using (MySqlDatabaseWrapper dbConn = new MySqlDatabaseWrapper(connString)) + { + var roles = dbConn.ExecuteQuery(string.Format("select rt.rolename from {0} as urt join {1} as rt on urt.roleid = rt.roleid where urt.userid=?;", _userInRolesTable, _rolesTable), userid); + if (roles.Count() > 0) + return roles.Select(role => role[0].ToString()).ToArray(); + } + } + return null; + } + + public override string[] GetUsersInRole(string roleName) + { + if (!Initialized) + return _prevProvider.GetUsersInRole(roleName); + if (string.IsNullOrEmpty(roleName)) + MySqlSimpleMembershipProvider.NullArgumentException("roleName"); + + int roleid = GetRoleId(roleName); + if (roleid > 0) + { + using (MySqlDatabaseWrapper dbConn = new MySqlDatabaseWrapper(ConnectionString)) + { + var users = dbConn.ExecuteQuery(string.Format("select ut.{0} from {1} as urt join {2} as ut on urt.userid = ut.{3} where urt.roleid=?;", UserNameColumn, _userInRolesTable, UserTableName, UserIdColumn), roleid); + if (users.Count() > 0) + return users.Select(role => role[0].ToString()).ToArray(); + } + } + return null; + } + + public override bool IsUserInRole(string username, string roleName) + { + if (!Initialized) + return _prevProvider.IsUserInRole(username, roleName); + string connString = ConnectionString; + if (string.IsNullOrEmpty(username)) + MySqlSimpleMembershipProvider.NullArgumentException("username"); + if (string.IsNullOrEmpty(roleName)) + MySqlSimpleMembershipProvider.NullArgumentException("roleName"); + int userid = MySqlSimpleMembershipProvider.GetUserId(username, connString, UserTableName, UserIdColumn, UserNameColumn); + int roleid = GetRoleId(roleName); + if (userid <= 0 || roleid <= 0) + return false; + using (MySqlDatabaseWrapper dbConn = new MySqlDatabaseWrapper(connString)) + { + return (dbConn.ExecuteQuery(string.Format("select count(userid) from {0} where userid=? and roleid=?;", _userInRolesTable), userid, roleid)).Count() > 0; + } + } + + public override void RemoveUsersFromRoles(string[] usernames, string[] roleNames) + { + if (!Initialized) + _prevProvider.RemoveUsersFromRoles(usernames, roleNames); + else + { + if (usernames.Where(username => string.IsNullOrEmpty(username)).Count() > 0 || usernames.Where(username => string.IsNullOrEmpty(username)).Count() > 0) + throw new ArgumentException(Resources.InvalidArrayValue); + using (MySqlDatabaseWrapper dbConn = new MySqlDatabaseWrapper(ConnectionString)) + { + foreach (var userid in GetUsersId(usernames)) + { + foreach (var roleid in GetRolesId(roleNames)) + { + if (userid > 0 && roleid > 0) + { + dbConn.ExecuteNonQuery(string.Format("delete from {0} where userid=? and roleid=?;", _userInRolesTable), userid, roleid); + } + } + } + } + } + } + + public override bool RoleExists(string roleName) + { + if (!Initialized) + return _prevProvider.RoleExists(roleName); + return (GetRoleId(roleName) > 0); + } + + #region Properties + + public override string ApplicationName + { + get + { + if (Initialized) + { + throw new NotSupportedException(); + } + else + { + return _prevProvider.ApplicationName; + } + } + set + { + if (Initialized) + { + throw new NotSupportedException(); + } + else + { + _prevProvider.ApplicationName = value; + } + } + } + + /// + /// Gets or sets the connection string. + /// + public string ConnectionString { get; set; } + + /// + /// Gets or sets the name associated to the connection string when stored in the configuration manager. + /// + public string ConnectionStringName { get; set; } + + /// + /// Gets the name of the table storing user information. + /// + public string UserTableName + { + get + { + if (string.IsNullOrEmpty(_userTableName)) + throw new InvalidOperationException(Resources.UserTableNameNotInitilized); + + return _userTableName; + } + internal set + { + _userTableName = value; + } + } + + /// + /// Gets the name of the column storing the user ids. + /// + public string UserIdColumn + { + get + { + if (string.IsNullOrEmpty(_userIdColumn)) + throw new InvalidOperationException(Resources.UserIdColumnNotInitialized); + + return _userIdColumn; + } + internal set + { + _userIdColumn = value; + } + } + + /// + /// Gets the name of the column storing the user names. + /// + public string UserNameColumn + { + get + { + if (string.IsNullOrEmpty(_userNameColumn)) + throw new InvalidOperationException(Resources.UserNameColumnNotInitialized); + + return _userNameColumn; + } + internal set + { + _userNameColumn = value; + } + } + + #endregion + + #region Private_Internal + internal bool Initialized + { + get; + set; + } + + internal void CreateTables() + { + var connString = ConnectionString; + using (MySqlDatabaseWrapper dbConn = new MySqlDatabaseWrapper(connString)) + { + //create schema + string schema = SchemaManager.GetSchema(11); + dbConn.ExecuteNonQuery(schema); + } + } + + //private string GetConnectionString() + //{ + // if (!string.IsNullOrEmpty(ConnectionString)) + // return ConnectionString; + // else + // { + // ConnectionStringSettings connString = ConfigurationManager.ConnectionStrings[ConnectionStringName]; + // if (connString != null) + // return connString.ConnectionString; + // } + + // if (!string.IsNullOrEmpty(_connString)) + // return _connString; + // throw new InvalidOperationException(Resources.NoConnString); + //} + + private IEnumerable GetUsersId(string[] usersName) + { + foreach (string userName in usersName) + { + yield return MySqlSimpleMembershipProvider.GetUserId(userName, ConnectionString, UserTableName, UserIdColumn, UserNameColumn); + } + } + + private IEnumerable GetRolesId(string[] roles) + { + foreach (string role in roles) + { + yield return GetRoleId(role); + } + } + + internal int GetRoleId(string role) + { + using (MySqlDatabaseWrapper dbConn = new MySqlDatabaseWrapper(ConnectionString)) + { + var roleid = dbConn.ExecuteQuerySingleRecord(string.Format("select roleid from {0} where rolename=?;", _rolesTable), role); + if (roleid != null) + return (int)roleid[0]; + + return 0; + } + } + + private bool UserHasRole(int userid, int roleid) + { + using (MySqlDatabaseWrapper dbConn = new MySqlDatabaseWrapper(ConnectionString)) + { + return (dbConn.ExecuteQuery(string.Format("select count(*) from {0} where userid=? and roleid=?;", _userInRolesTable), userid, roleid).Count() > 0); + } + } + + private bool IsRoleInUse(int roleid) + { + using (MySqlDatabaseWrapper dbConn = new MySqlDatabaseWrapper(ConnectionString)) + { + return (dbConn.ExecuteQuery(string.Format("select count(*) from {0} where roleid=?;", _userInRolesTable), roleid).Count() > 0); + } + } + #endregion + } +} diff --git a/MySql.Web/src/SiteMapProvider.cs b/MySql.Web/src/SiteMapProvider.cs index 6ff4c1d1f..3fdd5a90b 100644 --- a/MySql.Web/src/SiteMapProvider.cs +++ b/MySql.Web/src/SiteMapProvider.cs @@ -1,199 +1,199 @@ -// Copyright (c) 2004, 2020, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySql.Data.MySqlClient; -using MySql.Web.Common; -using MySql.Web.Properties; -using System; -using System.Collections.Generic; -using System.Configuration.Provider; -using System.Data; -using System.Diagnostics; -using System.Web; - -namespace MySql.Web.SiteMap -{ - /// - /// SiteMap provider backed by MySql database. - /// - public class MySqlSiteMapProvider : StaticSiteMapProvider - { - private readonly object _lockObject = new object(); - private string _connStr; - private SiteMapNode _rootNode; - private Dictionary _nodes = new Dictionary(); - private bool writeExceptionsToEventLog; - string eventSource = "MySQLSiteMap"; - string eventLog = "Application"; - string exceptionMessage = "An exception occurred. Please check the event log."; - - internal bool WriteExceptionsToEventLog { get { return writeExceptionsToEventLog; } } - - public override void Initialize(string name, System.Collections.Specialized.NameValueCollection config) - { - base.Initialize(name, config); - - if (config == null) - throw new ArgumentException(Resources.SiteMapConnectionStringMissing); - - _connStr = ConfigUtility.GetConnectionString(config); - if (string.IsNullOrEmpty(_connStr)) - throw new ArgumentException(Resources.SiteMapConnectionStringMissing); - - writeExceptionsToEventLog = false; - if (config["writeExceptionsToEventLog"] != null) - { - writeExceptionsToEventLog = (config["writeExceptionsToEventLog"].ToUpper() == "TRUE"); - } - - SchemaManager.CheckSchema(_connStr, config); - } - - public override SiteMapNode BuildSiteMap() - { - lock (_lockObject) - { - if (_rootNode != null) return _rootNode; - string sql = "select Id, Title, Description, Url, Roles, ParentId from my_aspnet_sitemap"; - MySqlConnection conn = new MySqlConnection(_connStr); - try - { - conn.Open(); - MySqlCommand cmd = new MySqlCommand(sql, conn); - using (MySqlDataReader r = cmd.ExecuteReader()) - { - int IdFld = r.GetOrdinal("Id"); - int TitleFld = r.GetOrdinal("Title"); - int DescFld = r.GetOrdinal("Description"); - int UrlFld = r.GetOrdinal("Url"); - int RolesFld = r.GetOrdinal("Roles"); - int ParentIdFld = r.GetOrdinal("ParentId"); - - while (r.Read()) - { - int IdVal; - string TitleVal; - string DescVal; - string UrlVal; - string RolesVal; - int ParentIdVal; - - LoadValue(r, IdFld, out IdVal); - LoadValue(r, TitleFld, out TitleVal); - LoadValue(r, DescFld, out DescVal); - LoadValue(r, UrlFld, out UrlVal); - LoadValue(r, RolesFld, out RolesVal); - LoadValue(r, ParentIdFld, out ParentIdVal); - - SiteMapNode node = new SiteMapNode(this, IdVal.ToString(), UrlVal, TitleVal, DescVal); - _nodes.Add(IdVal, node); - if (ParentIdVal != 0) - { - SiteMapNode parentNode = _nodes[ParentIdVal]; - AddNode(node, parentNode); - } - else - { - AddNode(node); - } - if (ParentIdVal == 0) - { - _rootNode = node; - } - } - } - } - catch (MySqlException ex) - { - HandleMySqlException(ex, "BuildSiteMap"); - } - finally - { - if ((conn.State & ConnectionState.Open) != 0) conn.Close(); - } - return _rootNode; - } - } - - private void LoadValue(MySqlDataReader r, int fldNum, out T val) - { - if (r.IsDBNull(fldNum)) - val = default(T); - else - { - val = (T)r.GetValue(fldNum); - } - } - - public override SiteMapNode FindSiteMapNodeFromKey(string key) - { - if (string.IsNullOrEmpty(key)) return null; - else - { - int idKey = Convert.ToInt32(key); - SiteMapNode node; - _nodes.TryGetValue(idKey, out node); - return node; - } - } - - /// - /// Handles MySql exception. - /// If WriteExceptionsToEventLog is set, will write exception info - /// to event log. - /// It throws provider exception (original exception is stored as inner exception) - /// - /// exception - /// name of the function that throwed the exception - private void HandleMySqlException(MySqlException e, string action) - { - if (WriteExceptionsToEventLog) - { - using (EventLog log = new EventLog()) - { - log.Source = eventSource; - log.Log = eventLog; - - string message = "An exception occurred communicating with the data source.\n\n"; - message += "Action: " + action; - message += "Exception: " + e.ToString(); - log.WriteEntry(message); - } - } - throw new ProviderException(exceptionMessage, e); - } - - protected override SiteMapNode GetRootNodeCore() - { - if (_rootNode == null) - BuildSiteMap(); - - return _rootNode; - } - } -} +// Copyright © 2004, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySql.Data.MySqlClient; +using MySql.Web.Common; +using MySql.Web.Properties; +using System; +using System.Collections.Generic; +using System.Configuration.Provider; +using System.Data; +using System.Diagnostics; +using System.Web; + +namespace MySql.Web.SiteMap +{ + /// + /// SiteMap provider backed by MySql database. + /// + public class MySqlSiteMapProvider : StaticSiteMapProvider + { + private readonly object _lockObject = new object(); + private string _connStr; + private SiteMapNode _rootNode; + private Dictionary _nodes = new Dictionary(); + private bool writeExceptionsToEventLog; + string eventSource = "MySQLSiteMap"; + string eventLog = "Application"; + string exceptionMessage = "An exception occurred. Please check the event log."; + + internal bool WriteExceptionsToEventLog { get { return writeExceptionsToEventLog; } } + + public override void Initialize(string name, System.Collections.Specialized.NameValueCollection config) + { + base.Initialize(name, config); + + if (config == null) + throw new ArgumentException(Resources.SiteMapConnectionStringMissing); + + _connStr = ConfigUtility.GetConnectionString(config); + if (string.IsNullOrEmpty(_connStr)) + throw new ArgumentException(Resources.SiteMapConnectionStringMissing); + + writeExceptionsToEventLog = false; + if (config["writeExceptionsToEventLog"] != null) + { + writeExceptionsToEventLog = (config["writeExceptionsToEventLog"].ToUpper() == "TRUE"); + } + + SchemaManager.CheckSchema(_connStr, config); + } + + public override SiteMapNode BuildSiteMap() + { + lock (_lockObject) + { + if (_rootNode != null) return _rootNode; + string sql = "select Id, Title, Description, Url, Roles, ParentId from my_aspnet_sitemap"; + MySqlConnection conn = new MySqlConnection(_connStr); + try + { + conn.Open(); + MySqlCommand cmd = new MySqlCommand(sql, conn); + using (MySqlDataReader r = cmd.ExecuteReader()) + { + int IdFld = r.GetOrdinal("Id"); + int TitleFld = r.GetOrdinal("Title"); + int DescFld = r.GetOrdinal("Description"); + int UrlFld = r.GetOrdinal("Url"); + int RolesFld = r.GetOrdinal("Roles"); + int ParentIdFld = r.GetOrdinal("ParentId"); + + while (r.Read()) + { + int IdVal; + string TitleVal; + string DescVal; + string UrlVal; + string RolesVal; + int ParentIdVal; + + LoadValue(r, IdFld, out IdVal); + LoadValue(r, TitleFld, out TitleVal); + LoadValue(r, DescFld, out DescVal); + LoadValue(r, UrlFld, out UrlVal); + LoadValue(r, RolesFld, out RolesVal); + LoadValue(r, ParentIdFld, out ParentIdVal); + + SiteMapNode node = new SiteMapNode(this, IdVal.ToString(), UrlVal, TitleVal, DescVal); + _nodes.Add(IdVal, node); + if (ParentIdVal != 0) + { + SiteMapNode parentNode = _nodes[ParentIdVal]; + AddNode(node, parentNode); + } + else + { + AddNode(node); + } + if (ParentIdVal == 0) + { + _rootNode = node; + } + } + } + } + catch (MySqlException ex) + { + HandleMySqlException(ex, "BuildSiteMap"); + } + finally + { + if ((conn.State & ConnectionState.Open) != 0) conn.Close(); + } + return _rootNode; + } + } + + private void LoadValue(MySqlDataReader r, int fldNum, out T val) + { + if (r.IsDBNull(fldNum)) + val = default(T); + else + { + val = (T)r.GetValue(fldNum); + } + } + + public override SiteMapNode FindSiteMapNodeFromKey(string key) + { + if (string.IsNullOrEmpty(key)) return null; + else + { + int idKey = Convert.ToInt32(key); + SiteMapNode node; + _nodes.TryGetValue(idKey, out node); + return node; + } + } + + /// + /// Handles MySql exception. + /// If WriteExceptionsToEventLog is set, will write exception info + /// to event log. + /// It throws provider exception (original exception is stored as inner exception) + /// + /// exception + /// name of the function that throwed the exception + private void HandleMySqlException(MySqlException e, string action) + { + if (WriteExceptionsToEventLog) + { + using (EventLog log = new EventLog()) + { + log.Source = eventSource; + log.Log = eventLog; + + string message = "An exception occurred communicating with the data source.\n\n"; + message += "Action: " + action; + message += "Exception: " + e.ToString(); + log.WriteEntry(message); + } + } + throw new ProviderException(exceptionMessage, e); + } + + protected override SiteMapNode GetRootNodeCore() + { + if (_rootNode == null) + BuildSiteMap(); + + return _rootNode; + } + } +} diff --git a/MySql.Web/tests/PersonalizationTests.cs b/MySql.Web/tests/PersonalizationTests.cs index 480d55de1..3d306323d 100644 --- a/MySql.Web/tests/PersonalizationTests.cs +++ b/MySql.Web/tests/PersonalizationTests.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2014, 2020, Oracle and/or its affiliates. +// Copyright © 2014, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySql.Web/tests/ProfileTests.cs b/MySql.Web/tests/ProfileTests.cs index 986fe4ee1..fa0d2157d 100644 --- a/MySql.Web/tests/ProfileTests.cs +++ b/MySql.Web/tests/ProfileTests.cs @@ -1,287 +1,287 @@ -// Copyright (c) 2013, 2020, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySql.Web.Profile; -using NUnit.Framework; -using System; -using System.Collections.Specialized; -using System.Configuration; -using System.Data; -using System.Reflection; -using System.Web.Profile; - -namespace MySql.Web.Tests -{ - public class ProfileTests : WebTestBase - { - private MySQLProfileProvider InitProfileProvider() - { - MySQLProfileProvider p = new MySQLProfileProvider(); - NameValueCollection config = new NameValueCollection(); - config.Add("connectionStringName", "LocalMySqlServer"); - config.Add("applicationName", "/"); - p.Initialize(null, config); - return p; - } - [TearDown] - public void Cleanup() - { - execSQL(@"delete from my_aspnet_applications; - delete from my_aspnet_paths; - delete from my_aspnet_users; - delete from my_aspnet_profiles; - delete from my_aspnet_personalizationallusers;"); - } - - [Test] - public void SettingValuesCreatesAnAppAndUserId() - { - - MySQLProfileProvider provider = InitProfileProvider(); - SettingsContext ctx = new SettingsContext(); - ctx.Add("IsAuthenticated", false); - ctx.Add("UserName", "user1"); - - SettingsPropertyValueCollection values = new SettingsPropertyValueCollection(); - SettingsProperty property1 = new SettingsProperty("color"); - property1.PropertyType = typeof(string); - property1.Attributes["AllowAnonymous"] = true; - SettingsPropertyValue value = new SettingsPropertyValue(property1); - value.PropertyValue = "blue"; - values.Add(value); - - provider.SetPropertyValues(ctx, values); - - DataTable dt = FillTable("SELECT * FROM my_aspnet_applications"); - Assert.True(1 == dt.Rows.Count, "Rows count on table my_aspnet_applications is not 1"); - - dt = FillTable("SELECT * FROM my_aspnet_users"); - Assert.True(1 == dt.Rows.Count, "Rows count on table my_aspnet_users is not 1"); - - - dt = FillTable("SELECT * FROM my_aspnet_profiles"); - Assert.True(1 == dt.Rows.Count, "Rows count on table my_aspnet_profiles is not 1"); - - values["color"].PropertyValue = "green"; - provider.SetPropertyValues(ctx, values); - - dt = FillTable("SELECT * FROM my_aspnet_applications"); - Assert.True(1 == dt.Rows.Count, "Rows count on table my_aspnet_applications is not 1 after setting property"); - - dt = FillTable("SELECT * FROM my_aspnet_users"); - Assert.True(1 == dt.Rows.Count, "Rows count on table my_aspnet_users is not 1 after setting property"); - - dt = FillTable("SELECT * FROM my_aspnet_profiles"); - Assert.True(1 == dt.Rows.Count, "Rows count on table my_aspnet_profiles is not 1 after setting property"); - } - - [Test] - public void AnonymousUserSettingNonAnonymousProperties() - { - MySQLProfileProvider provider = InitProfileProvider(); - SettingsContext ctx = new SettingsContext(); - ctx.Add("IsAuthenticated", false); - ctx.Add("UserName", "user1"); - - SettingsPropertyValueCollection values = new SettingsPropertyValueCollection(); - SettingsProperty property1 = new SettingsProperty("color"); - property1.PropertyType = typeof(string); - property1.Attributes["AllowAnonymous"] = false; - SettingsPropertyValue value = new SettingsPropertyValue(property1); - value.PropertyValue = "blue"; - values.Add(value); - - provider.SetPropertyValues(ctx, values); - - DataTable dt = FillTable("SELECT * FROM my_aspnet_applications"); - Assert.True(0 == dt.Rows.Count, "Table my_aspnet_applications Rows is not 0"); - - dt = FillTable("SELECT * FROM my_aspnet_users"); - Assert.True(0 == dt.Rows.Count, "Table my_aspnet_users Rows is not 0"); - - dt = FillTable("SELECT * FROM my_aspnet_profiles"); - Assert.True(0 == dt.Rows.Count, "Table my_aspnet_profiles Rows is not 0"); - - } - - [Test] - public void StringCollectionAsProperty() - { - ProfileBase profile = ProfileBase.Create("foo", true); - ResetAppId(profile.Providers["MySqlProfileProvider"] as MySQLProfileProvider); - StringCollection colors = new StringCollection(); - colors.Add("red"); - colors.Add("green"); - colors.Add("blue"); - profile["FavoriteColors"] = colors; - profile.Save(); - - DataTable dt = FillTable("SELECT * FROM my_aspnet_applications"); - Assert.AreEqual(1, dt.Rows.Count); - dt = FillTable("SELECT * FROM my_aspnet_users"); - Assert.AreEqual(1, dt.Rows.Count); - dt = FillTable("SELECT * FROM my_aspnet_profiles"); - Assert.AreEqual(1, dt.Rows.Count); - - // now retrieve them - SettingsPropertyCollection getProps = new SettingsPropertyCollection(); - SettingsProperty getProp1 = new SettingsProperty("FavoriteColors"); - getProp1.PropertyType = typeof(StringCollection); - getProp1.SerializeAs = SettingsSerializeAs.Xml; - getProps.Add(getProp1); - - MySQLProfileProvider provider = InitProfileProvider(); - SettingsContext ctx = new SettingsContext(); - ctx.Add("IsAuthenticated", true); - ctx.Add("UserName", "foo"); - SettingsPropertyValueCollection getValues = provider.GetPropertyValues(ctx, getProps); - Assert.AreEqual(1, getValues.Count); - SettingsPropertyValue getValue1 = getValues["FavoriteColors"]; - StringCollection outValue = (StringCollection)getValue1.PropertyValue; - Assert.AreEqual(3, outValue.Count); - Assert.AreEqual("red", outValue[0]); - Assert.AreEqual("green", outValue[1]); - Assert.AreEqual("blue", outValue[2]); - } - - [Test] - public void AuthenticatedDateTime() - { - ProfileBase profile = ProfileBase.Create("foo", true); - ResetAppId(profile.Providers["MySqlProfileProvider"] as MySQLProfileProvider); - DateTime date = DateTime.Now; - profile["BirthDate"] = date; - profile.Save(); - - SettingsPropertyCollection getProps = new SettingsPropertyCollection(); - SettingsProperty getProp1 = new SettingsProperty("BirthDate"); - getProp1.PropertyType = typeof(DateTime); - getProp1.SerializeAs = SettingsSerializeAs.Xml; - getProps.Add(getProp1); - - MySQLProfileProvider provider = InitProfileProvider(); - SettingsContext ctx = new SettingsContext(); - ctx.Add("IsAuthenticated", true); - ctx.Add("UserName", "foo"); - - SettingsPropertyValueCollection getValues = provider.GetPropertyValues(ctx, getProps); - Assert.AreEqual(1, getValues.Count); - SettingsPropertyValue getValue1 = getValues["BirthDate"]; - Assert.AreEqual(date, getValue1.PropertyValue); - } - - /// - /// We have to manually reset the app id because our profile provider is loaded from - /// previous tests but we are destroying our database between tests. This means that - /// our provider thinks we have an application in our database when we really don't. - /// Doing this will force the provider to generate a new app id. - /// Note that this is not really a problem in a normal app that is not destroying - /// the database behind the back of the provider. - /// - /// - private void ResetAppId(MySQLProfileProvider p) - { - Type t = p.GetType(); - FieldInfo fi = t.GetField("app", - BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly | BindingFlags.GetField); - object appObject = fi.GetValue(p); - Type appType = appObject.GetType(); - PropertyInfo pi = appType.GetProperty("Id"); - pi.SetValue(appObject, -1, null); - } - - [Test, Order(4)] - public void AuthenticatedStringProperty() - { - ProfileBase profile = ProfileBase.Create("foo", true); - ResetAppId(profile.Providers["MySqlProfileProvider"] as MySQLProfileProvider); - profile["Name"] = "Fred Flintstone"; - profile.Save(); - - SettingsPropertyCollection getProps = new SettingsPropertyCollection(); - SettingsProperty getProp1 = new SettingsProperty("Name"); - getProp1.PropertyType = typeof(String); - getProps.Add(getProp1); - - MySQLProfileProvider provider = InitProfileProvider(); - SettingsContext ctx = new SettingsContext(); - ctx.Add("IsAuthenticated", true); - ctx.Add("UserName", "foo"); - - SettingsPropertyValueCollection getValues = provider.GetPropertyValues(ctx, getProps); - Assert.AreEqual(1, getValues.Count); - SettingsPropertyValue getValue1 = getValues["Name"]; - Assert.AreEqual("Fred Flintstone", getValue1.PropertyValue); - } - - /// - /// Bug #41654 FindProfilesByUserName error into Connector .NET - /// - [Test] - public void GetAllProfiles() - { - ProfileBase profile = ProfileBase.Create("foo", true); - ResetAppId(profile.Providers["MySqlProfileProvider"] as MySQLProfileProvider); - profile["Name"] = "Fred Flintstone"; - profile.Save(); - - SettingsPropertyCollection getProps = new SettingsPropertyCollection(); - SettingsProperty getProp1 = new SettingsProperty("Name"); - getProp1.PropertyType = typeof(String); - getProps.Add(getProp1); - - MySQLProfileProvider provider = InitProfileProvider(); - SettingsContext ctx = new SettingsContext(); - ctx.Add("IsAuthenticated", true); - ctx.Add("UserName", "foo"); - - int total; - ProfileInfoCollection profiles = provider.GetAllProfiles( - ProfileAuthenticationOption.All, 0, 10, out total); - Assert.AreEqual(1, total); - } - - /// - /// Tests deleting a user profile - /// - [Test] - public void DeleteProfiles() - { - ProfileBase profile = ProfileBase.Create("foo", true); - profile.SetPropertyValue("Name", "this is my name"); - profile.Save(); - profile = ProfileBase.Create("foo", true); // refresh profile from database - Assert.AreEqual("this is my name", profile.GetPropertyValue("Name")); - - Assert.AreEqual(1, ProfileManager.DeleteProfiles(new string[] { "foo" })); - profile = ProfileBase.Create("foo", true); // refresh profile from database - Assert.AreEqual(string.Empty, profile.GetPropertyValue("Name")); - } - - } -} +// Copyright © 2013, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySql.Web.Profile; +using NUnit.Framework; +using System; +using System.Collections.Specialized; +using System.Configuration; +using System.Data; +using System.Reflection; +using System.Web.Profile; + +namespace MySql.Web.Tests +{ + public class ProfileTests : WebTestBase + { + private MySQLProfileProvider InitProfileProvider() + { + MySQLProfileProvider p = new MySQLProfileProvider(); + NameValueCollection config = new NameValueCollection(); + config.Add("connectionStringName", "LocalMySqlServer"); + config.Add("applicationName", "/"); + p.Initialize(null, config); + return p; + } + [TearDown] + public void Cleanup() + { + execSQL(@"delete from my_aspnet_applications; + delete from my_aspnet_paths; + delete from my_aspnet_users; + delete from my_aspnet_profiles; + delete from my_aspnet_personalizationallusers;"); + } + + [Test] + public void SettingValuesCreatesAnAppAndUserId() + { + + MySQLProfileProvider provider = InitProfileProvider(); + SettingsContext ctx = new SettingsContext(); + ctx.Add("IsAuthenticated", false); + ctx.Add("UserName", "user1"); + + SettingsPropertyValueCollection values = new SettingsPropertyValueCollection(); + SettingsProperty property1 = new SettingsProperty("color"); + property1.PropertyType = typeof(string); + property1.Attributes["AllowAnonymous"] = true; + SettingsPropertyValue value = new SettingsPropertyValue(property1); + value.PropertyValue = "blue"; + values.Add(value); + + provider.SetPropertyValues(ctx, values); + + DataTable dt = FillTable("SELECT * FROM my_aspnet_applications"); + Assert.True(1 == dt.Rows.Count, "Rows count on table my_aspnet_applications is not 1"); + + dt = FillTable("SELECT * FROM my_aspnet_users"); + Assert.True(1 == dt.Rows.Count, "Rows count on table my_aspnet_users is not 1"); + + + dt = FillTable("SELECT * FROM my_aspnet_profiles"); + Assert.True(1 == dt.Rows.Count, "Rows count on table my_aspnet_profiles is not 1"); + + values["color"].PropertyValue = "green"; + provider.SetPropertyValues(ctx, values); + + dt = FillTable("SELECT * FROM my_aspnet_applications"); + Assert.True(1 == dt.Rows.Count, "Rows count on table my_aspnet_applications is not 1 after setting property"); + + dt = FillTable("SELECT * FROM my_aspnet_users"); + Assert.True(1 == dt.Rows.Count, "Rows count on table my_aspnet_users is not 1 after setting property"); + + dt = FillTable("SELECT * FROM my_aspnet_profiles"); + Assert.True(1 == dt.Rows.Count, "Rows count on table my_aspnet_profiles is not 1 after setting property"); + } + + [Test] + public void AnonymousUserSettingNonAnonymousProperties() + { + MySQLProfileProvider provider = InitProfileProvider(); + SettingsContext ctx = new SettingsContext(); + ctx.Add("IsAuthenticated", false); + ctx.Add("UserName", "user1"); + + SettingsPropertyValueCollection values = new SettingsPropertyValueCollection(); + SettingsProperty property1 = new SettingsProperty("color"); + property1.PropertyType = typeof(string); + property1.Attributes["AllowAnonymous"] = false; + SettingsPropertyValue value = new SettingsPropertyValue(property1); + value.PropertyValue = "blue"; + values.Add(value); + + provider.SetPropertyValues(ctx, values); + + DataTable dt = FillTable("SELECT * FROM my_aspnet_applications"); + Assert.True(0 == dt.Rows.Count, "Table my_aspnet_applications Rows is not 0"); + + dt = FillTable("SELECT * FROM my_aspnet_users"); + Assert.True(0 == dt.Rows.Count, "Table my_aspnet_users Rows is not 0"); + + dt = FillTable("SELECT * FROM my_aspnet_profiles"); + Assert.True(0 == dt.Rows.Count, "Table my_aspnet_profiles Rows is not 0"); + + } + + [Test] + public void StringCollectionAsProperty() + { + ProfileBase profile = ProfileBase.Create("foo", true); + ResetAppId(profile.Providers["MySqlProfileProvider"] as MySQLProfileProvider); + StringCollection colors = new StringCollection(); + colors.Add("red"); + colors.Add("green"); + colors.Add("blue"); + profile["FavoriteColors"] = colors; + profile.Save(); + + DataTable dt = FillTable("SELECT * FROM my_aspnet_applications"); + Assert.AreEqual(1, dt.Rows.Count); + dt = FillTable("SELECT * FROM my_aspnet_users"); + Assert.AreEqual(1, dt.Rows.Count); + dt = FillTable("SELECT * FROM my_aspnet_profiles"); + Assert.AreEqual(1, dt.Rows.Count); + + // now retrieve them + SettingsPropertyCollection getProps = new SettingsPropertyCollection(); + SettingsProperty getProp1 = new SettingsProperty("FavoriteColors"); + getProp1.PropertyType = typeof(StringCollection); + getProp1.SerializeAs = SettingsSerializeAs.Xml; + getProps.Add(getProp1); + + MySQLProfileProvider provider = InitProfileProvider(); + SettingsContext ctx = new SettingsContext(); + ctx.Add("IsAuthenticated", true); + ctx.Add("UserName", "foo"); + SettingsPropertyValueCollection getValues = provider.GetPropertyValues(ctx, getProps); + Assert.AreEqual(1, getValues.Count); + SettingsPropertyValue getValue1 = getValues["FavoriteColors"]; + StringCollection outValue = (StringCollection)getValue1.PropertyValue; + Assert.AreEqual(3, outValue.Count); + Assert.AreEqual("red", outValue[0]); + Assert.AreEqual("green", outValue[1]); + Assert.AreEqual("blue", outValue[2]); + } + + [Test] + public void AuthenticatedDateTime() + { + ProfileBase profile = ProfileBase.Create("foo", true); + ResetAppId(profile.Providers["MySqlProfileProvider"] as MySQLProfileProvider); + DateTime date = DateTime.Now; + profile["BirthDate"] = date; + profile.Save(); + + SettingsPropertyCollection getProps = new SettingsPropertyCollection(); + SettingsProperty getProp1 = new SettingsProperty("BirthDate"); + getProp1.PropertyType = typeof(DateTime); + getProp1.SerializeAs = SettingsSerializeAs.Xml; + getProps.Add(getProp1); + + MySQLProfileProvider provider = InitProfileProvider(); + SettingsContext ctx = new SettingsContext(); + ctx.Add("IsAuthenticated", true); + ctx.Add("UserName", "foo"); + + SettingsPropertyValueCollection getValues = provider.GetPropertyValues(ctx, getProps); + Assert.AreEqual(1, getValues.Count); + SettingsPropertyValue getValue1 = getValues["BirthDate"]; + Assert.AreEqual(date, getValue1.PropertyValue); + } + + /// + /// We have to manually reset the app id because our profile provider is loaded from + /// previous tests but we are destroying our database between tests. This means that + /// our provider thinks we have an application in our database when we really don't. + /// Doing this will force the provider to generate a new app id. + /// Note that this is not really a problem in a normal app that is not destroying + /// the database behind the back of the provider. + /// + /// + private void ResetAppId(MySQLProfileProvider p) + { + Type t = p.GetType(); + FieldInfo fi = t.GetField("app", + BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly | BindingFlags.GetField); + object appObject = fi.GetValue(p); + Type appType = appObject.GetType(); + PropertyInfo pi = appType.GetProperty("Id"); + pi.SetValue(appObject, -1, null); + } + + [Test, Order(4)] + public void AuthenticatedStringProperty() + { + ProfileBase profile = ProfileBase.Create("foo", true); + ResetAppId(profile.Providers["MySqlProfileProvider"] as MySQLProfileProvider); + profile["Name"] = "Fred Flintstone"; + profile.Save(); + + SettingsPropertyCollection getProps = new SettingsPropertyCollection(); + SettingsProperty getProp1 = new SettingsProperty("Name"); + getProp1.PropertyType = typeof(String); + getProps.Add(getProp1); + + MySQLProfileProvider provider = InitProfileProvider(); + SettingsContext ctx = new SettingsContext(); + ctx.Add("IsAuthenticated", true); + ctx.Add("UserName", "foo"); + + SettingsPropertyValueCollection getValues = provider.GetPropertyValues(ctx, getProps); + Assert.AreEqual(1, getValues.Count); + SettingsPropertyValue getValue1 = getValues["Name"]; + Assert.AreEqual("Fred Flintstone", getValue1.PropertyValue); + } + + /// + /// Bug #41654 FindProfilesByUserName error into Connector .NET + /// + [Test] + public void GetAllProfiles() + { + ProfileBase profile = ProfileBase.Create("foo", true); + ResetAppId(profile.Providers["MySqlProfileProvider"] as MySQLProfileProvider); + profile["Name"] = "Fred Flintstone"; + profile.Save(); + + SettingsPropertyCollection getProps = new SettingsPropertyCollection(); + SettingsProperty getProp1 = new SettingsProperty("Name"); + getProp1.PropertyType = typeof(String); + getProps.Add(getProp1); + + MySQLProfileProvider provider = InitProfileProvider(); + SettingsContext ctx = new SettingsContext(); + ctx.Add("IsAuthenticated", true); + ctx.Add("UserName", "foo"); + + int total; + ProfileInfoCollection profiles = provider.GetAllProfiles( + ProfileAuthenticationOption.All, 0, 10, out total); + Assert.AreEqual(1, total); + } + + /// + /// Tests deleting a user profile + /// + [Test] + public void DeleteProfiles() + { + ProfileBase profile = ProfileBase.Create("foo", true); + profile.SetPropertyValue("Name", "this is my name"); + profile.Save(); + profile = ProfileBase.Create("foo", true); // refresh profile from database + Assert.AreEqual("this is my name", profile.GetPropertyValue("Name")); + + Assert.AreEqual(1, ProfileManager.DeleteProfiles(new string[] { "foo" })); + profile = ProfileBase.Create("foo", true); // refresh profile from database + Assert.AreEqual(string.Empty, profile.GetPropertyValue("Name")); + } + + } +} diff --git a/MySql.Web/tests/Properties/AssemblyInfo.cs b/MySql.Web/tests/Properties/AssemblyInfo.cs index 9a023faaf..1564b2a2c 100644 --- a/MySql.Web/tests/Properties/AssemblyInfo.cs +++ b/MySql.Web/tests/Properties/AssemblyInfo.cs @@ -1,49 +1,49 @@ -// Copyright (c) 2004, 2020, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using NUnit.Framework; -using System.Reflection; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("MySql.Web.Tests")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("Oracle")] -[assembly: AssemblyProduct("MySql.Web.Tests")] -[assembly: AssemblyCopyright("Copyright © 2004, 2019, Oracle and/or its affiliates. All rights reserved.")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] -[assembly: NonParallelizable] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] \ No newline at end of file +// Copyright © 2004, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using NUnit.Framework; +using System.Reflection; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("MySql.Web.Tests")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Oracle")] +[assembly: AssemblyProduct("MySql.Web.Tests")] +[assembly: AssemblyCopyright("Copyright © 2004, 2019, Oracle and/or its affiliates. All rights reserved.")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] +[assembly: NonParallelizable] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] diff --git a/MySql.Web/tests/RoleManagement.cs b/MySql.Web/tests/RoleManagement.cs index 17b39f2c9..3990e7634 100644 --- a/MySql.Web/tests/RoleManagement.cs +++ b/MySql.Web/tests/RoleManagement.cs @@ -1,234 +1,234 @@ -// Copyright (c) 2013, 2020, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySql.Web.Security; -using NUnit.Framework; -using System; -using System.Collections.Specialized; -using System.Web.Security; - -namespace MySql.Web.Tests -{ - public class RoleManagement : WebTestBase - { - private MySQLMembershipProvider membershipProvider; - private MySQLRoleProvider roleProvider; - - public RoleManagement() - { - membershipProvider = new MySQLMembershipProvider(); - NameValueCollection config = new NameValueCollection(); - config.Add("connectionStringName", "LocalMySqlServer"); - config.Add("applicationName", "/"); - membershipProvider.Initialize(null, config); - - roleProvider = new MySQLRoleProvider(); - roleProvider.Initialize(null, config); - } - - private void AddUser(string username, string password) - { - MembershipCreateStatus status; - membershipProvider.CreateUser(username, password, "foo@bar.com", null, - null, true, null, out status); - Assert.False(status != MembershipCreateStatus.Success, "User creation failed"); - } - - private void AttemptToAddUserToRole(string username, string role) - { - try - { - roleProvider.AddUsersToRoles(new string[] { username }, - new string[] { role }); - } - catch (ArgumentException) - { - } - } - - - [Test] - public void CreateAndDeleteRoles() - { - // Add the role - roleProvider.CreateRole("Administrator"); - string[] roles = roleProvider.GetAllRoles(); - Assert.AreEqual(1, roles.Length); - Assert.AreEqual("Administrator", roles[0]); - roleProvider.DeleteRole("Administrator", false); - } - - [Test] - public void AddUserToRole() - { - AddUser("eve", "eveeve!"); - roleProvider.CreateRole("Administrator"); - - roleProvider.AddUsersToRoles(new string[] { "eve" }, - new string[] { "Administrator" }); - Assert.True(roleProvider.IsUserInRole("eve", "Administrator")); - - roleProvider.RemoveUsersFromRoles(new string[] { "eve" }, new string[] { "Administrator" }); - Assert.False(roleProvider.IsUserInRole("eve", "Administrator")); - - roleProvider.DeleteRole("Administrator", false); - Assert.AreEqual(0, roleProvider.GetAllRoles().Length); - - //clean up - membershipProvider.DeleteUser("eve", true); - - } - - /// - /// Bug #38243 Not Handling non existing user when calling AddUsersToRoles method - /// - [Test] - public void AddNonExistingUserToRole() - { - roleProvider.CreateRole("Administrator"); - roleProvider.AddUsersToRoles(new string[] { "eve" }, - new string[] { "Administrator" }); - Assert.True(roleProvider.IsUserInRole("eve", "Administrator")); - - //Cleanup - roleProvider.RemoveUsersFromRoles(new string[] { "eve" }, new string[] { "Administrator" }); - roleProvider.DeleteRole("Administrator", false); - - } - - - [Test] - public void IllegalRoleAndUserNames() - { - AttemptToAddUserToRole("test", null); - AttemptToAddUserToRole("test", ""); - roleProvider.CreateRole("Administrator"); - AttemptToAddUserToRole(null, "Administrator"); - AttemptToAddUserToRole("", "Administrator"); - - //Cleanup - roleProvider.DeleteRole("Administrator", false); - } - - [Test] - public void AddUserToRoleWithRoleClass() - { - roleProvider.CreateRole("Administrator"); - - MembershipCreateStatus status; - membershipProvider.CreateUser("eve", "eve1@eve", "eve@boo.com", - "question", "answer", true, null, out status); - Assert.AreEqual(MembershipCreateStatus.Success, status); - - roleProvider.AddUsersToRoles(new string[] { "eve" }, new string[] { "Administrator" }); - Assert.True(roleProvider.IsUserInRole("eve", "Administrator")); - - //Cleanup - membershipProvider.DeleteUser("eve", true); - roleProvider.DeleteRole("Administrator", true); - - } - - [Test] - public void IsUserInRoleCrossDomain() - { - MySQLMembershipProvider provider = new MySQLMembershipProvider(); - NameValueCollection config1 = new NameValueCollection(); - config1.Add("connectionStringName", "LocalMySqlServer"); - config1.Add("applicationName", "/"); - config1.Add("passwordStrengthRegularExpression", "bar.*"); - config1.Add("passwordFormat", "Clear"); - provider.Initialize(null, config1); - MembershipCreateStatus status; - provider.CreateUser("foo", "bar!bar", null, null, null, true, null, out status); - - MySQLMembershipProvider provider2 = new MySQLMembershipProvider(); - NameValueCollection config2 = new NameValueCollection(); - config2.Add("connectionStringName", "LocalMySqlServer"); - config2.Add("applicationName", "/myapp"); - config2.Add("passwordStrengthRegularExpression", ".*"); - config2.Add("passwordFormat", "Clear"); - provider2.Initialize(null, config2); - - roleProvider = new MySQLRoleProvider(); - NameValueCollection config = new NameValueCollection(); - config.Add("connectionStringName", "LocalMySqlServer"); - config.Add("applicationName", "/"); - roleProvider.Initialize(null, config); - - MySQLRoleProvider r2 = new MySQLRoleProvider(); - NameValueCollection configr2 = new NameValueCollection(); - configr2.Add("connectionStringName", "LocalMySqlServer"); - configr2.Add("applicationName", "/myapp"); - r2.Initialize(null, configr2); - - roleProvider.CreateRole("Administrator"); - roleProvider.AddUsersToRoles(new string[] { "foo" }, - new string[] { "Administrator" }); - Assert.False(r2.IsUserInRole("foo", "Administrator")); - - roleProvider.DeleteRole("Administrator", false); - Assert.AreEqual(0, roleProvider.GetAllRoles().Length); - - //Cleanup - provider.DeleteUser("foo", true); - - } - - /// - /// Testing fix for Calling RoleProvider.RemoveUserFromRole() causes an exception due to a wrong table being used. - /// http://clustra.no.oracle.com/orabugs/bug.php?id=14405338 / http://bugs.mysql.com/bug.php?id=65805. - /// - [Test] - public void TestUserRemoveFindFromRole() - { - roleProvider = new MySQLRoleProvider(); - NameValueCollection config = new NameValueCollection(); - config.Add("connectionStringName", "LocalMySqlServer"); - config.Add("applicationName", "/"); - roleProvider.Initialize(null, config); - - AddUser("eve", "eveeve!"); - roleProvider.CreateRole("Administrator"); - roleProvider.AddUsersToRoles(new string[] { "eve" }, - new string[] { "Administrator" }); - Assert.True(roleProvider.IsUserInRole("eve", "Administrator")); - string[] users = roleProvider.FindUsersInRole("Administrator", "eve"); - Assert.AreEqual(1, users.Length); - Assert.AreEqual("eve", users[0]); - roleProvider.RemoveUsersFromRoles(new string[] { "eve" }, new string[] { "Administrator" }); - Assert.False(roleProvider.IsUserInRole("eve", "Administrator")); - - //Cleanup - membershipProvider.DeleteUser("eve", true); - roleProvider.DeleteRole("Administrator", false); - - } - - } -} +// Copyright © 2013, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySql.Web.Security; +using NUnit.Framework; +using System; +using System.Collections.Specialized; +using System.Web.Security; + +namespace MySql.Web.Tests +{ + public class RoleManagement : WebTestBase + { + private MySQLMembershipProvider membershipProvider; + private MySQLRoleProvider roleProvider; + + public RoleManagement() + { + membershipProvider = new MySQLMembershipProvider(); + NameValueCollection config = new NameValueCollection(); + config.Add("connectionStringName", "LocalMySqlServer"); + config.Add("applicationName", "/"); + membershipProvider.Initialize(null, config); + + roleProvider = new MySQLRoleProvider(); + roleProvider.Initialize(null, config); + } + + private void AddUser(string username, string password) + { + MembershipCreateStatus status; + membershipProvider.CreateUser(username, password, "foo@bar.com", null, + null, true, null, out status); + Assert.False(status != MembershipCreateStatus.Success, "User creation failed"); + } + + private void AttemptToAddUserToRole(string username, string role) + { + try + { + roleProvider.AddUsersToRoles(new string[] { username }, + new string[] { role }); + } + catch (ArgumentException) + { + } + } + + + [Test] + public void CreateAndDeleteRoles() + { + // Add the role + roleProvider.CreateRole("Administrator"); + string[] roles = roleProvider.GetAllRoles(); + Assert.AreEqual(1, roles.Length); + Assert.AreEqual("Administrator", roles[0]); + roleProvider.DeleteRole("Administrator", false); + } + + [Test] + public void AddUserToRole() + { + AddUser("eve", "eveeve!"); + roleProvider.CreateRole("Administrator"); + + roleProvider.AddUsersToRoles(new string[] { "eve" }, + new string[] { "Administrator" }); + Assert.True(roleProvider.IsUserInRole("eve", "Administrator")); + + roleProvider.RemoveUsersFromRoles(new string[] { "eve" }, new string[] { "Administrator" }); + Assert.False(roleProvider.IsUserInRole("eve", "Administrator")); + + roleProvider.DeleteRole("Administrator", false); + Assert.AreEqual(0, roleProvider.GetAllRoles().Length); + + //clean up + membershipProvider.DeleteUser("eve", true); + + } + + /// + /// Bug #38243 Not Handling non existing user when calling AddUsersToRoles method + /// + [Test] + public void AddNonExistingUserToRole() + { + roleProvider.CreateRole("Administrator"); + roleProvider.AddUsersToRoles(new string[] { "eve" }, + new string[] { "Administrator" }); + Assert.True(roleProvider.IsUserInRole("eve", "Administrator")); + + //Cleanup + roleProvider.RemoveUsersFromRoles(new string[] { "eve" }, new string[] { "Administrator" }); + roleProvider.DeleteRole("Administrator", false); + + } + + + [Test] + public void IllegalRoleAndUserNames() + { + AttemptToAddUserToRole("test", null); + AttemptToAddUserToRole("test", ""); + roleProvider.CreateRole("Administrator"); + AttemptToAddUserToRole(null, "Administrator"); + AttemptToAddUserToRole("", "Administrator"); + + //Cleanup + roleProvider.DeleteRole("Administrator", false); + } + + [Test] + public void AddUserToRoleWithRoleClass() + { + roleProvider.CreateRole("Administrator"); + + MembershipCreateStatus status; + membershipProvider.CreateUser("eve", "eve1@eve", "eve@boo.com", + "question", "answer", true, null, out status); + Assert.AreEqual(MembershipCreateStatus.Success, status); + + roleProvider.AddUsersToRoles(new string[] { "eve" }, new string[] { "Administrator" }); + Assert.True(roleProvider.IsUserInRole("eve", "Administrator")); + + //Cleanup + membershipProvider.DeleteUser("eve", true); + roleProvider.DeleteRole("Administrator", true); + + } + + [Test] + public void IsUserInRoleCrossDomain() + { + MySQLMembershipProvider provider = new MySQLMembershipProvider(); + NameValueCollection config1 = new NameValueCollection(); + config1.Add("connectionStringName", "LocalMySqlServer"); + config1.Add("applicationName", "/"); + config1.Add("passwordStrengthRegularExpression", "bar.*"); + config1.Add("passwordFormat", "Clear"); + provider.Initialize(null, config1); + MembershipCreateStatus status; + provider.CreateUser("foo", "bar!bar", null, null, null, true, null, out status); + + MySQLMembershipProvider provider2 = new MySQLMembershipProvider(); + NameValueCollection config2 = new NameValueCollection(); + config2.Add("connectionStringName", "LocalMySqlServer"); + config2.Add("applicationName", "/myapp"); + config2.Add("passwordStrengthRegularExpression", ".*"); + config2.Add("passwordFormat", "Clear"); + provider2.Initialize(null, config2); + + roleProvider = new MySQLRoleProvider(); + NameValueCollection config = new NameValueCollection(); + config.Add("connectionStringName", "LocalMySqlServer"); + config.Add("applicationName", "/"); + roleProvider.Initialize(null, config); + + MySQLRoleProvider r2 = new MySQLRoleProvider(); + NameValueCollection configr2 = new NameValueCollection(); + configr2.Add("connectionStringName", "LocalMySqlServer"); + configr2.Add("applicationName", "/myapp"); + r2.Initialize(null, configr2); + + roleProvider.CreateRole("Administrator"); + roleProvider.AddUsersToRoles(new string[] { "foo" }, + new string[] { "Administrator" }); + Assert.False(r2.IsUserInRole("foo", "Administrator")); + + roleProvider.DeleteRole("Administrator", false); + Assert.AreEqual(0, roleProvider.GetAllRoles().Length); + + //Cleanup + provider.DeleteUser("foo", true); + + } + + /// + /// Testing fix for Calling RoleProvider.RemoveUserFromRole() causes an exception due to a wrong table being used. + /// http://clustra.no.oracle.com/orabugs/bug.php?id=14405338 / http://bugs.mysql.com/bug.php?id=65805. + /// + [Test] + public void TestUserRemoveFindFromRole() + { + roleProvider = new MySQLRoleProvider(); + NameValueCollection config = new NameValueCollection(); + config.Add("connectionStringName", "LocalMySqlServer"); + config.Add("applicationName", "/"); + roleProvider.Initialize(null, config); + + AddUser("eve", "eveeve!"); + roleProvider.CreateRole("Administrator"); + roleProvider.AddUsersToRoles(new string[] { "eve" }, + new string[] { "Administrator" }); + Assert.True(roleProvider.IsUserInRole("eve", "Administrator")); + string[] users = roleProvider.FindUsersInRole("Administrator", "eve"); + Assert.AreEqual(1, users.Length); + Assert.AreEqual("eve", users[0]); + roleProvider.RemoveUsersFromRoles(new string[] { "eve" }, new string[] { "Administrator" }); + Assert.False(roleProvider.IsUserInRole("eve", "Administrator")); + + //Cleanup + membershipProvider.DeleteUser("eve", true); + roleProvider.DeleteRole("Administrator", false); + + } + + } +} diff --git a/MySql.Web/tests/SchemaManagerTests.cs b/MySql.Web/tests/SchemaManagerTests.cs index d2c38baf6..4aedebf96 100644 --- a/MySql.Web/tests/SchemaManagerTests.cs +++ b/MySql.Web/tests/SchemaManagerTests.cs @@ -1,319 +1,319 @@ -// Copyright (c) 2013, 2020, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySql.Data.MySqlClient; -using MySql.Web.Common; -using MySql.Web.Security; -using NUnit.Framework; -using System; -using System.Collections.Specialized; -using System.Configuration.Provider; -using System.Data; -using System.Web.Security; - -namespace MySql.Web.Tests -{ - public class SchemaManagerTests : WebTestBase - { - protected override void InitSchema() - { - // we override this and leave it empty because we don't want - // to init the schema for this test. - } - - [OneTimeSetUp] - public void Setup() - { - LoadData(); - } - - - /// - /// Bug #37469 autogenerateschema optimizing - /// - [Test] - public void SchemaCheck() - { - for (int i = 0; i <= SchemaManager.Version; i++) - { - MySQLMembershipProvider provider = new MySQLMembershipProvider(); - NameValueCollection config = new NameValueCollection(); - config.Add("connectionStringName", "LocalMySqlServer"); - config.Add("applicationName", "/"); - config.Add("passwordFormat", "Clear"); - - if (i > 0) - for (int x = 1; x <= i; x++) - LoadSchema(x); - - try - { - provider.Initialize(null, config); - if (i < SchemaManager.Version) - Assert.False(false, "Should have failed"); - } - catch (ProviderException) - { - if (i == SchemaManager.Version) - Assert.False(false, "This should not have failed"); - } - } - } - - /// - /// Bug #36444 'autogenerateschema' produces tables with 'random' collations - /// - [Test] - public void CurrentSchema() - { - execSQL(@"set character_set_database=utf8; - ALTER TABLE my_aspnet_membership CONVERT TO CHARACTER SET DEFAULT; - UPDATE my_aspnet_schemaversion SET version=4;"); - - MySqlCommand cmd = new MySqlCommand("SELECT * FROM my_aspnet_schemaversion", Connection); - object ver = cmd.ExecuteScalar(); - Assert.AreEqual(4, ver); - - cmd.CommandText = "SHOW CREATE TABLE my_aspnet_membership"; - using (MySqlDataReader reader = cmd.ExecuteReader()) - { - reader.Read(); - string createSql = reader.GetString(1); - Assert.True(createSql.IndexOf("CHARSET=utf8") != -1); - } - } - - [Test] - public void UpgradeV1ToV2() - { - execSQL(@"CREATE TABLE if not exists mysql_Membership(`PKID` varchar(36) NOT NULL, - Username varchar(255) NOT NULL, - ApplicationName varchar(255) NOT NULL, - Email varchar(128) NOT NULL, - Comment varchar(255) default NULL, - Password varchar(128) NOT NULL, - PasswordQuestion varchar(255) default NULL, - PasswordAnswer varchar(255) default NULL, - IsApproved tinyint(1) default NULL, - LastActivityDate datetime default NULL, - LastLoginDate datetime default NULL, - LastPasswordChangedDate datetime default NULL, - CreationDate datetime default NULL, - IsOnline tinyint(1) default NULL, - IsLockedOut tinyint(1) default NULL, - LastLockedOutDate datetime default NULL, - FailedPasswordAttemptCount int(10) unsigned default NULL, - FailedPasswordAttemptWindowStart datetime default NULL, - FailedPasswordAnswerAttemptCount int(10) unsigned default NULL, - FailedPasswordAnswerAttemptWindowStart datetime default NULL, - PRIMARY KEY (`PKID`)) DEFAULT CHARSET=latin1 COMMENT='1'; - ALTER TABLE mysql_Membership CHANGE Email Email VARCHAR(128), COMMENT='1';"); - - - MySqlCommand cmd = new MySqlCommand("SHOW CREATE TABLE mysql_membership", Connection); - using (MySqlDataReader reader = cmd.ExecuteReader()) - { - reader.Read(); - string createTable = reader.GetString(1); - int index = createTable.IndexOf("COMMENT='1'"); - Assert.AreNotEqual(-1, index); - } - - execSQL(@" ALTER TABLE mysql_Membership - CHANGE Email Email VARCHAR(128), COMMENT='2';"); - cmd = new MySqlCommand("SHOW CREATE TABLE mysql_membership", Connection); - using (MySqlDataReader reader = cmd.ExecuteReader()) - { - reader.Read(); - string createTable = reader.GetString(1); - int index = createTable.IndexOf("COMMENT='2'"); - Assert.AreNotEqual(-1, index); - } - } - - private void LoadData() - { - LoadSchema(1); - LoadSchema(2); - execSQL(@"INSERT INTO mysql_membership (pkid, username, password, applicationname, lastactivitydate) - VALUES('1', 'user1', '', 'app1', '2007-01-01')"); - execSQL(@"INSERT INTO mysql_membership (pkid, username, password, applicationname, lastactivitydate) - VALUES('2', 'user2', '', 'app1', '2007-01-01')"); - execSQL(@"INSERT INTO mysql_membership (pkid, username, password, applicationname, lastactivitydate) - VALUES('3', 'user1', '', 'app2', '2007-01-01')"); - execSQL(@"INSERT INTO mysql_membership (pkid, username, password, applicationname, lastactivitydate) - VALUES('4', 'user2', '', 'app2', '2007-01-01')"); - execSQL(@"INSERT INTO mysql_roles VALUES ('role1', 'app1')"); - execSQL(@"INSERT INTO mysql_roles VALUES ('role2', 'app1')"); - execSQL(@"INSERT INTO mysql_roles VALUES ('role1', 'app2')"); - execSQL(@"INSERT INTO mysql_roles VALUES ('role2', 'app2')"); - execSQL(@"INSERT INTO mysql_UsersInRoles VALUES ('user1', 'role1', 'app1')"); - execSQL(@"INSERT INTO mysql_UsersInRoles VALUES ('user2', 'role2', 'app1')"); - execSQL(@"INSERT INTO mysql_UsersInRoles VALUES ('user1', 'role1', 'app2')"); - execSQL(@"INSERT INTO mysql_UsersInRoles VALUES ('user2', 'role2', 'app2')"); - LoadSchema(3); - Assert.False(TableExists("mysql_membership")); - Assert.False(TableExists("mysql_roles")); - Assert.False(TableExists("mysql_usersinroles")); - } - - [Test] - public void CheckAppsUpgrade() - { - DataTable apps = FillTable("SELECT * FROM my_aspnet_applications"); - Assert.AreEqual(2, apps.Rows.Count); - Assert.AreEqual(1, apps.Rows[0]["id"]); - Assert.AreEqual("app1", apps.Rows[0]["name"]); - Assert.AreEqual(2, apps.Rows[1]["id"]); - Assert.AreEqual("app2", apps.Rows[1]["name"]); - } - - [Test] - public void CheckUsersUpgrade() - { - DataTable dt = FillTable("SELECT * FROM my_aspnet_users"); - Assert.AreEqual(4, dt.Rows.Count); - Assert.AreEqual(1, dt.Rows[0]["id"]); - Assert.AreEqual(1, dt.Rows[0]["applicationId"]); - Assert.AreEqual("user1", dt.Rows[0]["name"]); - Assert.AreEqual(2, dt.Rows[1]["id"]); - Assert.AreEqual(1, dt.Rows[1]["applicationId"]); - Assert.AreEqual("user2", dt.Rows[1]["name"]); - Assert.AreEqual(3, dt.Rows[2]["id"]); - Assert.AreEqual(2, dt.Rows[2]["applicationId"]); - Assert.AreEqual("user1", dt.Rows[2]["name"]); - Assert.AreEqual(4, dt.Rows[3]["id"]); - Assert.AreEqual(2, dt.Rows[3]["applicationId"]); - Assert.AreEqual("user2", dt.Rows[3]["name"]); - } - - [Test] - public void CheckRolesUpgrade() - { - DataTable dt = FillTable("SELECT * FROM my_aspnet_roles"); - Assert.AreEqual(4, dt.Rows.Count); - Assert.AreEqual(1, dt.Rows[0]["id"]); - Assert.AreEqual(1, dt.Rows[0]["applicationId"]); - Assert.AreEqual("role1", dt.Rows[0]["name"]); - Assert.AreEqual(2, dt.Rows[1]["id"]); - Assert.AreEqual(1, dt.Rows[1]["applicationId"]); - Assert.AreEqual("role2", dt.Rows[1]["name"]); - Assert.AreEqual(3, dt.Rows[2]["id"]); - Assert.AreEqual(2, dt.Rows[2]["applicationId"]); - Assert.AreEqual("role1", dt.Rows[2]["name"]); - Assert.AreEqual(4, dt.Rows[3]["id"]); - Assert.AreEqual(2, dt.Rows[3]["applicationId"]); - Assert.AreEqual("role2", dt.Rows[3]["name"]); - } - - [Test] - public void CheckMembershipUpgrade() - { - DataTable dt = FillTable("SELECT * FROM my_aspnet_membership"); - Assert.AreEqual(4, dt.Rows.Count); - Assert.AreEqual(1, dt.Rows[0]["userid"]); - Assert.AreEqual(2, dt.Rows[1]["userid"]); - Assert.AreEqual(3, dt.Rows[2]["userid"]); - Assert.AreEqual(4, dt.Rows[3]["userid"]); - } - - [Test] - public void CheckUsersInRolesUpgrade() - { - DataTable dt = FillTable("SELECT * FROM my_aspnet_usersinroles"); - Assert.AreEqual(4, dt.Rows.Count); - Assert.AreEqual(1, dt.Rows[0]["userid"]); - Assert.AreEqual(1, dt.Rows[0]["roleid"]); - Assert.AreEqual(2, dt.Rows[1]["userid"]); - Assert.AreEqual(2, dt.Rows[1]["roleid"]); - Assert.AreEqual(3, dt.Rows[2]["userid"]); - Assert.AreEqual(3, dt.Rows[2]["roleid"]); - Assert.AreEqual(4, dt.Rows[3]["userid"]); - Assert.AreEqual(4, dt.Rows[3]["roleid"]); - } - - /// - /// Bug #39072 Web provider does not work - /// - [Test] - public void AutoGenerateSchema() - { - MySQLMembershipProvider provider = new MySQLMembershipProvider(); - NameValueCollection config = new NameValueCollection(); - config.Add("connectionStringName", "LocalMySqlServer"); - config.Add("autogenerateschema", "true"); - config.Add("applicationName", "/"); - config.Add("passwordFormat", "Clear"); - - provider.Initialize(null, config); - - MembershipCreateStatus status; - MembershipUser user = provider.CreateUser("boo", "password", "email@email.com", - "question", "answer", true, null, out status); - } - - [Test] - public void SchemaTablesUseSameEngine() - { - for (int x = 1; x <= SchemaManager.Version; x++) - LoadSchema(x); - - string query = string.Format("SELECT TABLE_NAME, ENGINE FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = '{0}'", Connection.Database); - MySqlCommand cmd = new MySqlCommand(query, Connection); - string lastEngine = null; - string currentEngine; - - using (MySqlDataReader reader = cmd.ExecuteReader()) - { - while (reader.Read()) - { - currentEngine = reader.GetString("ENGINE"); - - if (string.IsNullOrEmpty(lastEngine)) - { - lastEngine = currentEngine; - } - - Assert.AreEqual(lastEngine, currentEngine); - } - } - } - - [Test] - public void InitializeInvalidConnStringThrowsArgumentException() - { - MySQLMembershipProvider provider = new MySQLMembershipProvider(); - NameValueCollection config = new NameValueCollection(); - var badConnectionString = ConnectionString + ";fookey=boo"; - config.Add("connectionString", badConnectionString); - - Exception ex = Assert.Throws(() => provider.Initialize(null, config)); - Assert.AreEqual("Option not supported.\r\nParameter name: fookey", ex.Message); - } - } -} +// Copyright © 2013, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySql.Data.MySqlClient; +using MySql.Web.Common; +using MySql.Web.Security; +using NUnit.Framework; +using System; +using System.Collections.Specialized; +using System.Configuration.Provider; +using System.Data; +using System.Web.Security; + +namespace MySql.Web.Tests +{ + public class SchemaManagerTests : WebTestBase + { + protected override void InitSchema() + { + // we override this and leave it empty because we don't want + // to init the schema for this test. + } + + [OneTimeSetUp] + public void Setup() + { + LoadData(); + } + + + /// + /// Bug #37469 autogenerateschema optimizing + /// + [Test] + public void SchemaCheck() + { + for (int i = 0; i <= SchemaManager.Version; i++) + { + MySQLMembershipProvider provider = new MySQLMembershipProvider(); + NameValueCollection config = new NameValueCollection(); + config.Add("connectionStringName", "LocalMySqlServer"); + config.Add("applicationName", "/"); + config.Add("passwordFormat", "Clear"); + + if (i > 0) + for (int x = 1; x <= i; x++) + LoadSchema(x); + + try + { + provider.Initialize(null, config); + if (i < SchemaManager.Version) + Assert.False(false, "Should have failed"); + } + catch (ProviderException) + { + if (i == SchemaManager.Version) + Assert.False(false, "This should not have failed"); + } + } + } + + /// + /// Bug #36444 'autogenerateschema' produces tables with 'random' collations + /// + [Test] + public void CurrentSchema() + { + execSQL(@"set character_set_database=utf8; + ALTER TABLE my_aspnet_membership CONVERT TO CHARACTER SET DEFAULT; + UPDATE my_aspnet_schemaversion SET version=4;"); + + MySqlCommand cmd = new MySqlCommand("SELECT * FROM my_aspnet_schemaversion", Connection); + object ver = cmd.ExecuteScalar(); + Assert.AreEqual(4, ver); + + cmd.CommandText = "SHOW CREATE TABLE my_aspnet_membership"; + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + reader.Read(); + string createSql = reader.GetString(1); + Assert.True(createSql.IndexOf("CHARSET=utf8") != -1); + } + } + + [Test] + public void UpgradeV1ToV2() + { + execSQL(@"CREATE TABLE if not exists mysql_Membership(`PKID` varchar(36) NOT NULL, + Username varchar(255) NOT NULL, + ApplicationName varchar(255) NOT NULL, + Email varchar(128) NOT NULL, + Comment varchar(255) default NULL, + Password varchar(128) NOT NULL, + PasswordQuestion varchar(255) default NULL, + PasswordAnswer varchar(255) default NULL, + IsApproved tinyint(1) default NULL, + LastActivityDate datetime default NULL, + LastLoginDate datetime default NULL, + LastPasswordChangedDate datetime default NULL, + CreationDate datetime default NULL, + IsOnline tinyint(1) default NULL, + IsLockedOut tinyint(1) default NULL, + LastLockedOutDate datetime default NULL, + FailedPasswordAttemptCount int(10) unsigned default NULL, + FailedPasswordAttemptWindowStart datetime default NULL, + FailedPasswordAnswerAttemptCount int(10) unsigned default NULL, + FailedPasswordAnswerAttemptWindowStart datetime default NULL, + PRIMARY KEY (`PKID`)) DEFAULT CHARSET=latin1 COMMENT='1'; + ALTER TABLE mysql_Membership CHANGE Email Email VARCHAR(128), COMMENT='1';"); + + + MySqlCommand cmd = new MySqlCommand("SHOW CREATE TABLE mysql_membership", Connection); + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + reader.Read(); + string createTable = reader.GetString(1); + int index = createTable.IndexOf("COMMENT='1'"); + Assert.AreNotEqual(-1, index); + } + + execSQL(@" ALTER TABLE mysql_Membership + CHANGE Email Email VARCHAR(128), COMMENT='2';"); + cmd = new MySqlCommand("SHOW CREATE TABLE mysql_membership", Connection); + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + reader.Read(); + string createTable = reader.GetString(1); + int index = createTable.IndexOf("COMMENT='2'"); + Assert.AreNotEqual(-1, index); + } + } + + private void LoadData() + { + LoadSchema(1); + LoadSchema(2); + execSQL(@"INSERT INTO mysql_membership (pkid, username, password, applicationname, lastactivitydate) + VALUES('1', 'user1', '', 'app1', '2007-01-01')"); + execSQL(@"INSERT INTO mysql_membership (pkid, username, password, applicationname, lastactivitydate) + VALUES('2', 'user2', '', 'app1', '2007-01-01')"); + execSQL(@"INSERT INTO mysql_membership (pkid, username, password, applicationname, lastactivitydate) + VALUES('3', 'user1', '', 'app2', '2007-01-01')"); + execSQL(@"INSERT INTO mysql_membership (pkid, username, password, applicationname, lastactivitydate) + VALUES('4', 'user2', '', 'app2', '2007-01-01')"); + execSQL(@"INSERT INTO mysql_roles VALUES ('role1', 'app1')"); + execSQL(@"INSERT INTO mysql_roles VALUES ('role2', 'app1')"); + execSQL(@"INSERT INTO mysql_roles VALUES ('role1', 'app2')"); + execSQL(@"INSERT INTO mysql_roles VALUES ('role2', 'app2')"); + execSQL(@"INSERT INTO mysql_UsersInRoles VALUES ('user1', 'role1', 'app1')"); + execSQL(@"INSERT INTO mysql_UsersInRoles VALUES ('user2', 'role2', 'app1')"); + execSQL(@"INSERT INTO mysql_UsersInRoles VALUES ('user1', 'role1', 'app2')"); + execSQL(@"INSERT INTO mysql_UsersInRoles VALUES ('user2', 'role2', 'app2')"); + LoadSchema(3); + Assert.False(TableExists("mysql_membership")); + Assert.False(TableExists("mysql_roles")); + Assert.False(TableExists("mysql_usersinroles")); + } + + [Test] + public void CheckAppsUpgrade() + { + DataTable apps = FillTable("SELECT * FROM my_aspnet_applications"); + Assert.AreEqual(2, apps.Rows.Count); + Assert.AreEqual(1, apps.Rows[0]["id"]); + Assert.AreEqual("app1", apps.Rows[0]["name"]); + Assert.AreEqual(2, apps.Rows[1]["id"]); + Assert.AreEqual("app2", apps.Rows[1]["name"]); + } + + [Test] + public void CheckUsersUpgrade() + { + DataTable dt = FillTable("SELECT * FROM my_aspnet_users"); + Assert.AreEqual(4, dt.Rows.Count); + Assert.AreEqual(1, dt.Rows[0]["id"]); + Assert.AreEqual(1, dt.Rows[0]["applicationId"]); + Assert.AreEqual("user1", dt.Rows[0]["name"]); + Assert.AreEqual(2, dt.Rows[1]["id"]); + Assert.AreEqual(1, dt.Rows[1]["applicationId"]); + Assert.AreEqual("user2", dt.Rows[1]["name"]); + Assert.AreEqual(3, dt.Rows[2]["id"]); + Assert.AreEqual(2, dt.Rows[2]["applicationId"]); + Assert.AreEqual("user1", dt.Rows[2]["name"]); + Assert.AreEqual(4, dt.Rows[3]["id"]); + Assert.AreEqual(2, dt.Rows[3]["applicationId"]); + Assert.AreEqual("user2", dt.Rows[3]["name"]); + } + + [Test] + public void CheckRolesUpgrade() + { + DataTable dt = FillTable("SELECT * FROM my_aspnet_roles"); + Assert.AreEqual(4, dt.Rows.Count); + Assert.AreEqual(1, dt.Rows[0]["id"]); + Assert.AreEqual(1, dt.Rows[0]["applicationId"]); + Assert.AreEqual("role1", dt.Rows[0]["name"]); + Assert.AreEqual(2, dt.Rows[1]["id"]); + Assert.AreEqual(1, dt.Rows[1]["applicationId"]); + Assert.AreEqual("role2", dt.Rows[1]["name"]); + Assert.AreEqual(3, dt.Rows[2]["id"]); + Assert.AreEqual(2, dt.Rows[2]["applicationId"]); + Assert.AreEqual("role1", dt.Rows[2]["name"]); + Assert.AreEqual(4, dt.Rows[3]["id"]); + Assert.AreEqual(2, dt.Rows[3]["applicationId"]); + Assert.AreEqual("role2", dt.Rows[3]["name"]); + } + + [Test] + public void CheckMembershipUpgrade() + { + DataTable dt = FillTable("SELECT * FROM my_aspnet_membership"); + Assert.AreEqual(4, dt.Rows.Count); + Assert.AreEqual(1, dt.Rows[0]["userid"]); + Assert.AreEqual(2, dt.Rows[1]["userid"]); + Assert.AreEqual(3, dt.Rows[2]["userid"]); + Assert.AreEqual(4, dt.Rows[3]["userid"]); + } + + [Test] + public void CheckUsersInRolesUpgrade() + { + DataTable dt = FillTable("SELECT * FROM my_aspnet_usersinroles"); + Assert.AreEqual(4, dt.Rows.Count); + Assert.AreEqual(1, dt.Rows[0]["userid"]); + Assert.AreEqual(1, dt.Rows[0]["roleid"]); + Assert.AreEqual(2, dt.Rows[1]["userid"]); + Assert.AreEqual(2, dt.Rows[1]["roleid"]); + Assert.AreEqual(3, dt.Rows[2]["userid"]); + Assert.AreEqual(3, dt.Rows[2]["roleid"]); + Assert.AreEqual(4, dt.Rows[3]["userid"]); + Assert.AreEqual(4, dt.Rows[3]["roleid"]); + } + + /// + /// Bug #39072 Web provider does not work + /// + [Test] + public void AutoGenerateSchema() + { + MySQLMembershipProvider provider = new MySQLMembershipProvider(); + NameValueCollection config = new NameValueCollection(); + config.Add("connectionStringName", "LocalMySqlServer"); + config.Add("autogenerateschema", "true"); + config.Add("applicationName", "/"); + config.Add("passwordFormat", "Clear"); + + provider.Initialize(null, config); + + MembershipCreateStatus status; + MembershipUser user = provider.CreateUser("boo", "password", "email@email.com", + "question", "answer", true, null, out status); + } + + [Test] + public void SchemaTablesUseSameEngine() + { + for (int x = 1; x <= SchemaManager.Version; x++) + LoadSchema(x); + + string query = string.Format("SELECT TABLE_NAME, ENGINE FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = '{0}'", Connection.Database); + MySqlCommand cmd = new MySqlCommand(query, Connection); + string lastEngine = null; + string currentEngine; + + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + while (reader.Read()) + { + currentEngine = reader.GetString("ENGINE"); + + if (string.IsNullOrEmpty(lastEngine)) + { + lastEngine = currentEngine; + } + + Assert.AreEqual(lastEngine, currentEngine); + } + } + } + + [Test] + public void InitializeInvalidConnStringThrowsArgumentException() + { + MySQLMembershipProvider provider = new MySQLMembershipProvider(); + NameValueCollection config = new NameValueCollection(); + var badConnectionString = ConnectionString + ";fookey=boo"; + config.Add("connectionString", badConnectionString); + + Exception ex = Assert.Throws(() => provider.Initialize(null, config)); + Assert.AreEqual("Option not supported.\r\nParameter name: fookey", ex.Message); + } + } +} diff --git a/MySql.Web/tests/SchemaTests.cs b/MySql.Web/tests/SchemaTests.cs index 600f19c63..5ff9c8f65 100644 --- a/MySql.Web/tests/SchemaTests.cs +++ b/MySql.Web/tests/SchemaTests.cs @@ -1,357 +1,357 @@ -// Copyright (c) 2013, 2020, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySql.Data.MySqlClient; -using MySql.Web.Common; -using MySql.Web.Security; -using NUnit.Framework; -using System.Collections.Specialized; -using System.Configuration.Provider; -using System.Data; -using System.Web.Security; - -namespace MySql.Web.Tests -{ - public class SchemaTests : WebTestBase - { - protected override void InitSchema() - { - // we override this and leave it empty because we don't want - // to init the schema for this test. - } - - [OneTimeSetUp] - public void Setup() - { - LoadData(); - } - /// - /// Bug #37469 autogenerateschema optimizing - /// - [Test] - public void SchemaCheck() - { - for (int i = 0; i <= SchemaManager.Version; i++) - { - MySQLMembershipProvider provider = new MySQLMembershipProvider(); - NameValueCollection config = new NameValueCollection(); - config.Add("connectionStringName", "LocalMySqlServer"); - config.Add("applicationName", "/"); - config.Add("passwordFormat", "Clear"); - - if (i > 0) - for (int x = 1; x <= i; x++) - LoadSchema(x); - - try - { - provider.Initialize(null, config); - if (i < SchemaManager.Version) - Assert.False(false, "Should have failed"); - } - catch (ProviderException) - { - if (i == SchemaManager.Version) - Assert.False(false, "This should not have failed"); - } - } - } - - /// - /// Bug #36444 'autogenerateschema' produces tables with 'random' collations - /// - [Test] - public void CurrentSchema() - { - execSQL(@"set character_set_database=utf8; - ALTER TABLE my_aspnet_membership CONVERT TO CHARACTER SET DEFAULT; - UPDATE my_aspnet_schemaversion SET version=4;"); - - MySqlCommand cmd = new MySqlCommand("SELECT * FROM my_aspnet_schemaversion", Connection); - object ver = cmd.ExecuteScalar(); - Assert.AreEqual(4, ver); - - cmd.CommandText = "SHOW CREATE TABLE my_aspnet_membership"; - using (MySqlDataReader reader = cmd.ExecuteReader()) - { - reader.Read(); - string createSql = reader.GetString(1); - Assert.True(createSql.IndexOf("CHARSET=utf8") != -1); - } - } - - [Test] - public void UpgradeV1ToV2() - { - execSQL(@"CREATE TABLE if not exists mysql_Membership(`PKID` varchar(36) NOT NULL, - Username varchar(255) NOT NULL, - ApplicationName varchar(255) NOT NULL, - Email varchar(128) NOT NULL, - Comment varchar(255) default NULL, - Password varchar(128) NOT NULL, - PasswordQuestion varchar(255) default NULL, - PasswordAnswer varchar(255) default NULL, - IsApproved tinyint(1) default NULL, - LastActivityDate datetime default NULL, - LastLoginDate datetime default NULL, - LastPasswordChangedDate datetime default NULL, - CreationDate datetime default NULL, - IsOnline tinyint(1) default NULL, - IsLockedOut tinyint(1) default NULL, - LastLockedOutDate datetime default NULL, - FailedPasswordAttemptCount int(10) unsigned default NULL, - FailedPasswordAttemptWindowStart datetime default NULL, - FailedPasswordAnswerAttemptCount int(10) unsigned default NULL, - FailedPasswordAnswerAttemptWindowStart datetime default NULL, - PRIMARY KEY (`PKID`)) DEFAULT CHARSET=latin1 COMMENT='1'; - ALTER TABLE mysql_Membership CHANGE Email Email VARCHAR(128), COMMENT='1';"); - - - MySqlCommand cmd = new MySqlCommand("SHOW CREATE TABLE mysql_membership", Connection); - using (MySqlDataReader reader = cmd.ExecuteReader()) - { - reader.Read(); - string createTable = reader.GetString(1); - int index = createTable.IndexOf("COMMENT='1'"); - Assert.AreNotEqual(-1, index); - } - - execSQL(@" ALTER TABLE mysql_Membership - CHANGE Email Email VARCHAR(128), COMMENT='2';"); - cmd = new MySqlCommand("SHOW CREATE TABLE mysql_membership", Connection); - using (MySqlDataReader reader = cmd.ExecuteReader()) - { - reader.Read(); - string createTable = reader.GetString(1); - int index = createTable.IndexOf("COMMENT='2'"); - Assert.AreNotEqual(-1, index); - } - } - - private void LoadData() - { - LoadSchema(1); - LoadSchema(2); - execSQL(@"INSERT INTO mysql_membership (pkid, username, password, applicationname, lastactivitydate) - VALUES('1', 'user1', '', 'app1', '2007-01-01')"); - execSQL(@"INSERT INTO mysql_membership (pkid, username, password, applicationname, lastactivitydate) - VALUES('2', 'user2', '', 'app1', '2007-01-01')"); - execSQL(@"INSERT INTO mysql_membership (pkid, username, password, applicationname, lastactivitydate) - VALUES('3', 'user1', '', 'app2', '2007-01-01')"); - execSQL(@"INSERT INTO mysql_membership (pkid, username, password, applicationname, lastactivitydate) - VALUES('4', 'user2', '', 'app2', '2007-01-01')"); - execSQL(@"INSERT INTO mysql_roles VALUES ('role1', 'app1')"); - execSQL(@"INSERT INTO mysql_roles VALUES ('role2', 'app1')"); - execSQL(@"INSERT INTO mysql_roles VALUES ('role1', 'app2')"); - execSQL(@"INSERT INTO mysql_roles VALUES ('role2', 'app2')"); - execSQL(@"INSERT INTO mysql_UsersInRoles VALUES ('user1', 'role1', 'app1')"); - execSQL(@"INSERT INTO mysql_UsersInRoles VALUES ('user2', 'role2', 'app1')"); - execSQL(@"INSERT INTO mysql_UsersInRoles VALUES ('user1', 'role1', 'app2')"); - execSQL(@"INSERT INTO mysql_UsersInRoles VALUES ('user2', 'role2', 'app2')"); - LoadSchema(3); - Assert.False(TableExists("mysql_membership")); - Assert.False(TableExists("mysql_roles")); - Assert.False(TableExists("mysql_usersinroles")); - } - - [Test] - public void CheckAppsUpgrade() - { - DataTable apps = FillTable("SELECT * FROM my_aspnet_applications"); - Assert.AreEqual(2, apps.Rows.Count); - Assert.AreEqual(1, apps.Rows[0]["id"]); - Assert.AreEqual("app1", apps.Rows[0]["name"]); - Assert.AreEqual(2, apps.Rows[1]["id"]); - Assert.AreEqual("app2", apps.Rows[1]["name"]); - } - - //[Test] - //public void CheckUsersUpgrade() - //{ - // LoadData(); - - // DataTable dt = FillTable("SELECT * FROM my_aspnet_users"); - // Assert.AreEqual(4, dt.Rows.Count); - // Assert.AreEqual(1, dt.Rows[0]["id"]); - // Assert.AreEqual(1, dt.Rows[0]["applicationId"]); - // Assert.AreEqual("user1", dt.Rows[0]["name"]); - // Assert.AreEqual(2, dt.Rows[1]["id"]); - // Assert.AreEqual(1, dt.Rows[1]["applicationId"]); - // Assert.AreEqual("user2", dt.Rows[1]["name"]); - // Assert.AreEqual(3, dt.Rows[2]["id"]); - // Assert.AreEqual(2, dt.Rows[2]["applicationId"]); - // Assert.AreEqual("user1", dt.Rows[2]["name"]); - // Assert.AreEqual(4, dt.Rows[3]["id"]); - // Assert.AreEqual(2, dt.Rows[3]["applicationId"]); - // Assert.AreEqual("user2", dt.Rows[3]["name"]); - //} - - // [Test] - // public void CheckRolesUpgrade() - // { - // LoadData(); - - // DataTable dt = FillTable("SELECT * FROM my_aspnet_roles"); - // Assert.AreEqual(4, dt.Rows.Count); - // Assert.AreEqual(1, dt.Rows[0]["id"]); - // Assert.AreEqual(1, dt.Rows[0]["applicationId"]); - // Assert.AreEqual("role1", dt.Rows[0]["name"]); - // Assert.AreEqual(2, dt.Rows[1]["id"]); - // Assert.AreEqual(1, dt.Rows[1]["applicationId"]); - // Assert.AreEqual("role2", dt.Rows[1]["name"]); - // Assert.AreEqual(3, dt.Rows[2]["id"]); - // Assert.AreEqual(2, dt.Rows[2]["applicationId"]); - // Assert.AreEqual("role1", dt.Rows[2]["name"]); - // Assert.AreEqual(4, dt.Rows[3]["id"]); - // Assert.AreEqual(2, dt.Rows[3]["applicationId"]); - // Assert.AreEqual("role2", dt.Rows[3]["name"]); - // } - - // [Test] - // public void CheckMembershipUpgrade() - // { - // LoadData(); - - // DataTable dt = FillTable("SELECT * FROM my_aspnet_membership"); - // Assert.AreEqual(4, dt.Rows.Count); - // Assert.AreEqual(1, dt.Rows[0]["userid"]); - // Assert.AreEqual(2, dt.Rows[1]["userid"]); - // Assert.AreEqual(3, dt.Rows[2]["userid"]); - // Assert.AreEqual(4, dt.Rows[3]["userid"]); - // } - - // [Test] - // public void CheckUsersInRolesUpgrade() - // { - // LoadData(); - - // DataTable dt = FillTable("SELECT * FROM my_aspnet_usersinroles"); - // Assert.AreEqual(4, dt.Rows.Count); - // Assert.AreEqual(1, dt.Rows[0]["userid"]); - // Assert.AreEqual(1, dt.Rows[0]["roleid"]); - // Assert.AreEqual(2, dt.Rows[1]["userid"]); - // Assert.AreEqual(2, dt.Rows[1]["roleid"]); - // Assert.AreEqual(3, dt.Rows[2]["userid"]); - // Assert.AreEqual(3, dt.Rows[2]["roleid"]); - // Assert.AreEqual(4, dt.Rows[3]["userid"]); - // Assert.AreEqual(4, dt.Rows[3]["roleid"]); - // } - - /// - /// Bug #39072 Web provider does not work - /// - [Test] - public void AutoGenerateSchema() - { - MySQLMembershipProvider provider = new MySQLMembershipProvider(); - NameValueCollection config = new NameValueCollection(); - config.Add("ConnectionStringName", "LocalMySqlServer"); - config.Add("autogenerateschema", "true"); - config.Add("applicationName", "/"); - config.Add("passwordFormat", "Clear"); - - provider.Initialize(null, config); - - MembershipCreateStatus status; - MembershipUser user = provider.CreateUser("boo", "password", "email@email.com", - "question", "answer", true, null, out status); - } - - // [Test] - // public void SchemaTablesUseSameEngine() - // { - // DropAllTables(); - - // for (int x = 1; x <= SchemaManager.Version; x++) - // LoadSchema(x); - - // string query = string.Format("SELECT TABLE_NAME, ENGINE FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = '{0}'", st.conn.Database); - // MySqlCommand cmd = new MySqlCommand(query, st.conn); - // string lastEngine = null; - // string currentEngine; - - // using (MySqlDataReader reader = cmd.ExecuteReader()) - // { - // while (reader.Read()) - // { - // currentEngine = reader.GetString("ENGINE"); - - // if (string.IsNullOrEmpty(lastEngine)) - // { - // lastEngine = currentEngine; - // } - - // Assert.AreEqual(lastEngine, currentEngine); - // } - // } - // } - - // [Test] - // public void InitializeInvalidConnStringThrowsArgumentException() - // { - // Configuration configFile = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None); - // string connStr = configFile.ConnectionStrings.ConnectionStrings["LocalMySqlServer"].ConnectionString; - // string fakeConnectionString = connStr.Replace("database", "fooKey"); - // configFile.ConnectionStrings.ConnectionStrings["LocalMySqlServer"].ConnectionString = fakeConnectionString; - // configFile.Save(); - // ConfigurationManager.RefreshSection("connectionStrings"); - - // MySQLMembershipProvider provider = new MySQLMembershipProvider(); - // NameValueCollection config = new NameValueCollection(); - // config.Add("connectionStringName", "LocalMySqlServer"); - - // Exception ex = Assert.Throws(() => provider.Initialize(null, config)); - // Assert.AreEqual(ex.Message, "Keyword not supported.\r\nParameter name: fookey"); - - // configFile.ConnectionStrings.ConnectionStrings["LocalMySqlServer"].ConnectionString = connStr; - // configFile.Save(); - // ConfigurationManager.RefreshSection("connectionStrings"); - - // } - - /// - /// Checking fix for http://bugs.mysql.com/bug.php?id=65144 / http://clustra.no.oracle.com/orabugs/14495292 - /// (Net Connector 6.4.4 Asp.Net Membership Database fails on MySql Db of UTF32). - /// - [Test] - public void AttemptLatestSchemaVersion() - { - execSQL(string.Format("alter database `{0}` character set = 'utf32' collate = 'utf32_general_ci'", Connection.Database)); - for (int i = 1; i <= 4; i++) - { - LoadSchema(i); - } - MySQLRoleProvider roleProvider = new MySQLRoleProvider(); - NameValueCollection config = new NameValueCollection(); - config.Add("connectionStringName", "LocalMySqlServer"); - config.Add("applicationName", "/"); - config.Add("autogenerateschema", "true"); - roleProvider.Initialize(null, config); - } - } -} +// Copyright © 2013, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySql.Data.MySqlClient; +using MySql.Web.Common; +using MySql.Web.Security; +using NUnit.Framework; +using System.Collections.Specialized; +using System.Configuration.Provider; +using System.Data; +using System.Web.Security; + +namespace MySql.Web.Tests +{ + public class SchemaTests : WebTestBase + { + protected override void InitSchema() + { + // we override this and leave it empty because we don't want + // to init the schema for this test. + } + + [OneTimeSetUp] + public void Setup() + { + LoadData(); + } + /// + /// Bug #37469 autogenerateschema optimizing + /// + [Test] + public void SchemaCheck() + { + for (int i = 0; i <= SchemaManager.Version; i++) + { + MySQLMembershipProvider provider = new MySQLMembershipProvider(); + NameValueCollection config = new NameValueCollection(); + config.Add("connectionStringName", "LocalMySqlServer"); + config.Add("applicationName", "/"); + config.Add("passwordFormat", "Clear"); + + if (i > 0) + for (int x = 1; x <= i; x++) + LoadSchema(x); + + try + { + provider.Initialize(null, config); + if (i < SchemaManager.Version) + Assert.False(false, "Should have failed"); + } + catch (ProviderException) + { + if (i == SchemaManager.Version) + Assert.False(false, "This should not have failed"); + } + } + } + + /// + /// Bug #36444 'autogenerateschema' produces tables with 'random' collations + /// + [Test] + public void CurrentSchema() + { + execSQL(@"set character_set_database=utf8; + ALTER TABLE my_aspnet_membership CONVERT TO CHARACTER SET DEFAULT; + UPDATE my_aspnet_schemaversion SET version=4;"); + + MySqlCommand cmd = new MySqlCommand("SELECT * FROM my_aspnet_schemaversion", Connection); + object ver = cmd.ExecuteScalar(); + Assert.AreEqual(4, ver); + + cmd.CommandText = "SHOW CREATE TABLE my_aspnet_membership"; + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + reader.Read(); + string createSql = reader.GetString(1); + Assert.True(createSql.IndexOf("CHARSET=utf8") != -1); + } + } + + [Test] + public void UpgradeV1ToV2() + { + execSQL(@"CREATE TABLE if not exists mysql_Membership(`PKID` varchar(36) NOT NULL, + Username varchar(255) NOT NULL, + ApplicationName varchar(255) NOT NULL, + Email varchar(128) NOT NULL, + Comment varchar(255) default NULL, + Password varchar(128) NOT NULL, + PasswordQuestion varchar(255) default NULL, + PasswordAnswer varchar(255) default NULL, + IsApproved tinyint(1) default NULL, + LastActivityDate datetime default NULL, + LastLoginDate datetime default NULL, + LastPasswordChangedDate datetime default NULL, + CreationDate datetime default NULL, + IsOnline tinyint(1) default NULL, + IsLockedOut tinyint(1) default NULL, + LastLockedOutDate datetime default NULL, + FailedPasswordAttemptCount int(10) unsigned default NULL, + FailedPasswordAttemptWindowStart datetime default NULL, + FailedPasswordAnswerAttemptCount int(10) unsigned default NULL, + FailedPasswordAnswerAttemptWindowStart datetime default NULL, + PRIMARY KEY (`PKID`)) DEFAULT CHARSET=latin1 COMMENT='1'; + ALTER TABLE mysql_Membership CHANGE Email Email VARCHAR(128), COMMENT='1';"); + + + MySqlCommand cmd = new MySqlCommand("SHOW CREATE TABLE mysql_membership", Connection); + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + reader.Read(); + string createTable = reader.GetString(1); + int index = createTable.IndexOf("COMMENT='1'"); + Assert.AreNotEqual(-1, index); + } + + execSQL(@" ALTER TABLE mysql_Membership + CHANGE Email Email VARCHAR(128), COMMENT='2';"); + cmd = new MySqlCommand("SHOW CREATE TABLE mysql_membership", Connection); + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + reader.Read(); + string createTable = reader.GetString(1); + int index = createTable.IndexOf("COMMENT='2'"); + Assert.AreNotEqual(-1, index); + } + } + + private void LoadData() + { + LoadSchema(1); + LoadSchema(2); + execSQL(@"INSERT INTO mysql_membership (pkid, username, password, applicationname, lastactivitydate) + VALUES('1', 'user1', '', 'app1', '2007-01-01')"); + execSQL(@"INSERT INTO mysql_membership (pkid, username, password, applicationname, lastactivitydate) + VALUES('2', 'user2', '', 'app1', '2007-01-01')"); + execSQL(@"INSERT INTO mysql_membership (pkid, username, password, applicationname, lastactivitydate) + VALUES('3', 'user1', '', 'app2', '2007-01-01')"); + execSQL(@"INSERT INTO mysql_membership (pkid, username, password, applicationname, lastactivitydate) + VALUES('4', 'user2', '', 'app2', '2007-01-01')"); + execSQL(@"INSERT INTO mysql_roles VALUES ('role1', 'app1')"); + execSQL(@"INSERT INTO mysql_roles VALUES ('role2', 'app1')"); + execSQL(@"INSERT INTO mysql_roles VALUES ('role1', 'app2')"); + execSQL(@"INSERT INTO mysql_roles VALUES ('role2', 'app2')"); + execSQL(@"INSERT INTO mysql_UsersInRoles VALUES ('user1', 'role1', 'app1')"); + execSQL(@"INSERT INTO mysql_UsersInRoles VALUES ('user2', 'role2', 'app1')"); + execSQL(@"INSERT INTO mysql_UsersInRoles VALUES ('user1', 'role1', 'app2')"); + execSQL(@"INSERT INTO mysql_UsersInRoles VALUES ('user2', 'role2', 'app2')"); + LoadSchema(3); + Assert.False(TableExists("mysql_membership")); + Assert.False(TableExists("mysql_roles")); + Assert.False(TableExists("mysql_usersinroles")); + } + + [Test] + public void CheckAppsUpgrade() + { + DataTable apps = FillTable("SELECT * FROM my_aspnet_applications"); + Assert.AreEqual(2, apps.Rows.Count); + Assert.AreEqual(1, apps.Rows[0]["id"]); + Assert.AreEqual("app1", apps.Rows[0]["name"]); + Assert.AreEqual(2, apps.Rows[1]["id"]); + Assert.AreEqual("app2", apps.Rows[1]["name"]); + } + + //[Test] + //public void CheckUsersUpgrade() + //{ + // LoadData(); + + // DataTable dt = FillTable("SELECT * FROM my_aspnet_users"); + // Assert.AreEqual(4, dt.Rows.Count); + // Assert.AreEqual(1, dt.Rows[0]["id"]); + // Assert.AreEqual(1, dt.Rows[0]["applicationId"]); + // Assert.AreEqual("user1", dt.Rows[0]["name"]); + // Assert.AreEqual(2, dt.Rows[1]["id"]); + // Assert.AreEqual(1, dt.Rows[1]["applicationId"]); + // Assert.AreEqual("user2", dt.Rows[1]["name"]); + // Assert.AreEqual(3, dt.Rows[2]["id"]); + // Assert.AreEqual(2, dt.Rows[2]["applicationId"]); + // Assert.AreEqual("user1", dt.Rows[2]["name"]); + // Assert.AreEqual(4, dt.Rows[3]["id"]); + // Assert.AreEqual(2, dt.Rows[3]["applicationId"]); + // Assert.AreEqual("user2", dt.Rows[3]["name"]); + //} + + // [Test] + // public void CheckRolesUpgrade() + // { + // LoadData(); + + // DataTable dt = FillTable("SELECT * FROM my_aspnet_roles"); + // Assert.AreEqual(4, dt.Rows.Count); + // Assert.AreEqual(1, dt.Rows[0]["id"]); + // Assert.AreEqual(1, dt.Rows[0]["applicationId"]); + // Assert.AreEqual("role1", dt.Rows[0]["name"]); + // Assert.AreEqual(2, dt.Rows[1]["id"]); + // Assert.AreEqual(1, dt.Rows[1]["applicationId"]); + // Assert.AreEqual("role2", dt.Rows[1]["name"]); + // Assert.AreEqual(3, dt.Rows[2]["id"]); + // Assert.AreEqual(2, dt.Rows[2]["applicationId"]); + // Assert.AreEqual("role1", dt.Rows[2]["name"]); + // Assert.AreEqual(4, dt.Rows[3]["id"]); + // Assert.AreEqual(2, dt.Rows[3]["applicationId"]); + // Assert.AreEqual("role2", dt.Rows[3]["name"]); + // } + + // [Test] + // public void CheckMembershipUpgrade() + // { + // LoadData(); + + // DataTable dt = FillTable("SELECT * FROM my_aspnet_membership"); + // Assert.AreEqual(4, dt.Rows.Count); + // Assert.AreEqual(1, dt.Rows[0]["userid"]); + // Assert.AreEqual(2, dt.Rows[1]["userid"]); + // Assert.AreEqual(3, dt.Rows[2]["userid"]); + // Assert.AreEqual(4, dt.Rows[3]["userid"]); + // } + + // [Test] + // public void CheckUsersInRolesUpgrade() + // { + // LoadData(); + + // DataTable dt = FillTable("SELECT * FROM my_aspnet_usersinroles"); + // Assert.AreEqual(4, dt.Rows.Count); + // Assert.AreEqual(1, dt.Rows[0]["userid"]); + // Assert.AreEqual(1, dt.Rows[0]["roleid"]); + // Assert.AreEqual(2, dt.Rows[1]["userid"]); + // Assert.AreEqual(2, dt.Rows[1]["roleid"]); + // Assert.AreEqual(3, dt.Rows[2]["userid"]); + // Assert.AreEqual(3, dt.Rows[2]["roleid"]); + // Assert.AreEqual(4, dt.Rows[3]["userid"]); + // Assert.AreEqual(4, dt.Rows[3]["roleid"]); + // } + + /// + /// Bug #39072 Web provider does not work + /// + [Test] + public void AutoGenerateSchema() + { + MySQLMembershipProvider provider = new MySQLMembershipProvider(); + NameValueCollection config = new NameValueCollection(); + config.Add("ConnectionStringName", "LocalMySqlServer"); + config.Add("autogenerateschema", "true"); + config.Add("applicationName", "/"); + config.Add("passwordFormat", "Clear"); + + provider.Initialize(null, config); + + MembershipCreateStatus status; + MembershipUser user = provider.CreateUser("boo", "password", "email@email.com", + "question", "answer", true, null, out status); + } + + // [Test] + // public void SchemaTablesUseSameEngine() + // { + // DropAllTables(); + + // for (int x = 1; x <= SchemaManager.Version; x++) + // LoadSchema(x); + + // string query = string.Format("SELECT TABLE_NAME, ENGINE FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = '{0}'", st.conn.Database); + // MySqlCommand cmd = new MySqlCommand(query, st.conn); + // string lastEngine = null; + // string currentEngine; + + // using (MySqlDataReader reader = cmd.ExecuteReader()) + // { + // while (reader.Read()) + // { + // currentEngine = reader.GetString("ENGINE"); + + // if (string.IsNullOrEmpty(lastEngine)) + // { + // lastEngine = currentEngine; + // } + + // Assert.AreEqual(lastEngine, currentEngine); + // } + // } + // } + + // [Test] + // public void InitializeInvalidConnStringThrowsArgumentException() + // { + // Configuration configFile = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None); + // string connStr = configFile.ConnectionStrings.ConnectionStrings["LocalMySqlServer"].ConnectionString; + // string fakeConnectionString = connStr.Replace("database", "fooKey"); + // configFile.ConnectionStrings.ConnectionStrings["LocalMySqlServer"].ConnectionString = fakeConnectionString; + // configFile.Save(); + // ConfigurationManager.RefreshSection("connectionStrings"); + + // MySQLMembershipProvider provider = new MySQLMembershipProvider(); + // NameValueCollection config = new NameValueCollection(); + // config.Add("connectionStringName", "LocalMySqlServer"); + + // Exception ex = Assert.Throws(() => provider.Initialize(null, config)); + // Assert.AreEqual(ex.Message, "Keyword not supported.\r\nParameter name: fookey"); + + // configFile.ConnectionStrings.ConnectionStrings["LocalMySqlServer"].ConnectionString = connStr; + // configFile.Save(); + // ConfigurationManager.RefreshSection("connectionStrings"); + + // } + + /// + /// Checking fix for http://bugs.mysql.com/bug.php?id=65144 / http://clustra.no.oracle.com/orabugs/14495292 + /// (Net Connector 6.4.4 Asp.Net Membership Database fails on MySql Db of UTF32). + /// + [Test] + public void AttemptLatestSchemaVersion() + { + execSQL(string.Format("alter database `{0}` character set = 'utf32' collate = 'utf32_general_ci'", Connection.Database)); + for (int i = 1; i <= 4; i++) + { + LoadSchema(i); + } + MySQLRoleProvider roleProvider = new MySQLRoleProvider(); + NameValueCollection config = new NameValueCollection(); + config.Add("connectionStringName", "LocalMySqlServer"); + config.Add("applicationName", "/"); + config.Add("autogenerateschema", "true"); + roleProvider.Initialize(null, config); + } + } +} diff --git a/MySql.Web/tests/SessionLocking/Global.asax.cs b/MySql.Web/tests/SessionLocking/Global.asax.cs index ea62fe855..270c7b09a 100644 --- a/MySql.Web/tests/SessionLocking/Global.asax.cs +++ b/MySql.Web/tests/SessionLocking/Global.asax.cs @@ -1,16 +1,16 @@ -// Copyright © 2004,2010, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2004, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySql.Web/tests/SessionLocking/InitSessionLocking.aspx.cs b/MySql.Web/tests/SessionLocking/InitSessionLocking.aspx.cs index 25a6c40ce..7760aa845 100644 --- a/MySql.Web/tests/SessionLocking/InitSessionLocking.aspx.cs +++ b/MySql.Web/tests/SessionLocking/InitSessionLocking.aspx.cs @@ -1,48 +1,48 @@ -// Copyright © 2004, 2013, Oracle and/or its affiliates. All rights reserved. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -// This code was contributed by Sean Wright (srwright@alcor.concordia.ca) on 2007-01-12 -// The copyright was assigned and transferred under the terms of -// the MySQL Contributor License Agreement (CLA) - -using System; -using System.Collections.Generic; -using System.Web; -using System.Web.UI; -using System.Web.UI.WebControls; - -namespace MySql.Web.Tests.SessionLocking -{ - public partial class InitSessionLocking : System.Web.UI.Page - { - protected void Page_Load(object sender, EventArgs e) - { - - } - } -} \ No newline at end of file +// Copyright © 2004, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +// This code was contributed by Sean Wright (srwright@alcor.concordia.ca) on 2007-01-12 +// The copyright was assigned and transferred under the terms of +// the MySQL Contributor License Agreement (CLA) + +using System; +using System.Collections.Generic; +using System.Web; +using System.Web.UI; +using System.Web.UI.WebControls; + +namespace MySql.Web.Tests.SessionLocking +{ + public partial class InitSessionLocking : System.Web.UI.Page + { + protected void Page_Load(object sender, EventArgs e) + { + + } + } +} diff --git a/MySql.Web/tests/SessionLocking/InitSessionLocking.aspx.designer.cs b/MySql.Web/tests/SessionLocking/InitSessionLocking.aspx.designer.cs index 5bb831374..c15fda308 100644 --- a/MySql.Web/tests/SessionLocking/InitSessionLocking.aspx.designer.cs +++ b/MySql.Web/tests/SessionLocking/InitSessionLocking.aspx.designer.cs @@ -1,26 +1,26 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace MySql.Web.Tests.SessionLocking -{ - - - public partial class InitSessionLocking - { - - /// - /// form1 control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.HtmlControls.HtmlForm form1; - } -} +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace MySql.Web.Tests.SessionLocking +{ + + + public partial class InitSessionLocking + { + + /// + /// form1 control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.HtmlControls.HtmlForm form1; + } +} diff --git a/MySql.Web/tests/SessionLocking/read.aspx.cs b/MySql.Web/tests/SessionLocking/read.aspx.cs index 5e83e2fa4..890444b96 100644 --- a/MySql.Web/tests/SessionLocking/read.aspx.cs +++ b/MySql.Web/tests/SessionLocking/read.aspx.cs @@ -1,52 +1,52 @@ -// Copyright © 2004, 2013, Oracle and/or its affiliates. All rights reserved. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -// This code was contributed by Sean Wright (srwright@alcor.concordia.ca) on 2007-01-12 -// The copyright was assigned and transferred under the terms of -// the MySQL Contributor License Agreement (CLA) - -using System; -using System.Collections.Generic; -using System.Web; -using System.Web.UI; -using System.Web.UI.WebControls; -using System.Threading; -using MySql.Web.Tests; - -namespace MySql.Web.Tests -{ - public partial class read : System.Web.UI.Page - { - protected void Page_Load(object sender, EventArgs e) - { - object o = Session["x"]; - // Signaler -// SessionTests.mtxReader.Set(); - } - } -} \ No newline at end of file +// Copyright © 2004, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +// This code was contributed by Sean Wright (srwright@alcor.concordia.ca) on 2007-01-12 +// The copyright was assigned and transferred under the terms of +// the MySQL Contributor License Agreement (CLA) + +using System; +using System.Collections.Generic; +using System.Web; +using System.Web.UI; +using System.Web.UI.WebControls; +using System.Threading; +using MySql.Web.Tests; + +namespace MySql.Web.Tests +{ + public partial class read : System.Web.UI.Page + { + protected void Page_Load(object sender, EventArgs e) + { + object o = Session["x"]; + // Signaler +// SessionTests.mtxReader.Set(); + } + } +} diff --git a/MySql.Web/tests/SessionLocking/read.aspx.designer.cs b/MySql.Web/tests/SessionLocking/read.aspx.designer.cs index fe385e6b1..44778047d 100644 --- a/MySql.Web/tests/SessionLocking/read.aspx.designer.cs +++ b/MySql.Web/tests/SessionLocking/read.aspx.designer.cs @@ -1,24 +1,24 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace MySql.Web.Tests { - - - public partial class read { - - /// - /// form1 control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.HtmlControls.HtmlForm form1; - } -} +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace MySql.Web.Tests { + + + public partial class read { + + /// + /// form1 control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.HtmlControls.HtmlForm form1; + } +} diff --git a/MySql.Web/tests/SessionLocking/write.aspx.cs b/MySql.Web/tests/SessionLocking/write.aspx.cs index 660832260..1ef9fe54d 100644 --- a/MySql.Web/tests/SessionLocking/write.aspx.cs +++ b/MySql.Web/tests/SessionLocking/write.aspx.cs @@ -1,54 +1,54 @@ -// Copyright © 2004, 2013, Oracle and/or its affiliates. All rights reserved. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -// This code was contributed by Sean Wright (srwright@alcor.concordia.ca) on 2007-01-12 -// The copyright was assigned and transferred under the terms of -// the MySQL Contributor License Agreement (CLA) - -using System; -using System.Collections.Generic; -using System.Web; -using System.Web.UI; -using System.Web.UI.WebControls; -using System.Threading; -using MySql.Web.Tests; - -namespace MySql.Web.Tests -{ - public partial class write : System.Web.UI.Page - { - protected void Page_Load(object sender, EventArgs e) - { - // Make session dirty -// Session["x"] = "x"; - - // SessionTests.mtxWriter.Set(); - // SessionTests.WaitSyncCreation( false ); - } - } -} \ No newline at end of file +// Copyright © 2004, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +// This code was contributed by Sean Wright (srwright@alcor.concordia.ca) on 2007-01-12 +// The copyright was assigned and transferred under the terms of +// the MySQL Contributor License Agreement (CLA) + +using System; +using System.Collections.Generic; +using System.Web; +using System.Web.UI; +using System.Web.UI.WebControls; +using System.Threading; +using MySql.Web.Tests; + +namespace MySql.Web.Tests +{ + public partial class write : System.Web.UI.Page + { + protected void Page_Load(object sender, EventArgs e) + { + // Make session dirty +// Session["x"] = "x"; + + // SessionTests.mtxWriter.Set(); + // SessionTests.WaitSyncCreation( false ); + } + } +} diff --git a/MySql.Web/tests/SessionLocking/write.aspx.designer.cs b/MySql.Web/tests/SessionLocking/write.aspx.designer.cs index b73b0eea1..1035ebd07 100644 --- a/MySql.Web/tests/SessionLocking/write.aspx.designer.cs +++ b/MySql.Web/tests/SessionLocking/write.aspx.designer.cs @@ -1,24 +1,24 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace MySql.Web.Tests { - - - public partial class write { - - /// - /// form1 control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.HtmlControls.HtmlForm form1; - } -} +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace MySql.Web.Tests { + + + public partial class write { + + /// + /// form1 control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.HtmlControls.HtmlForm form1; + } +} diff --git a/MySql.Web/tests/SessionLocking/write2.aspx.cs b/MySql.Web/tests/SessionLocking/write2.aspx.cs index 82c01275b..9098345f1 100644 --- a/MySql.Web/tests/SessionLocking/write2.aspx.cs +++ b/MySql.Web/tests/SessionLocking/write2.aspx.cs @@ -1,51 +1,51 @@ -// Copyright © 2004, 2013, Oracle and/or its affiliates. All rights reserved. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -// This code was contributed by Sean Wright (srwright@alcor.concordia.ca) on 2007-01-12 -// The copyright was assigned and transferred under the terms of -// the MySQL Contributor License Agreement (CLA) - -using System; -using System.Collections.Generic; -#if CLR4 - -#endif -using System.Web; -using System.Web.UI; -using System.Web.UI.WebControls; - -namespace MySql.Web.Tests -{ - public partial class write2 : System.Web.UI.Page - { - protected void Page_Load(object sender, EventArgs e) - { - Session["x"] = "x2"; - } - } -} \ No newline at end of file +// Copyright © 2004, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +// This code was contributed by Sean Wright (srwright@alcor.concordia.ca) on 2007-01-12 +// The copyright was assigned and transferred under the terms of +// the MySQL Contributor License Agreement (CLA) + +using System; +using System.Collections.Generic; +#if CLR4 + +#endif +using System.Web; +using System.Web.UI; +using System.Web.UI.WebControls; + +namespace MySql.Web.Tests +{ + public partial class write2 : System.Web.UI.Page + { + protected void Page_Load(object sender, EventArgs e) + { + Session["x"] = "x2"; + } + } +} diff --git a/MySql.Web/tests/SessionLocking/write2.aspx.designer.cs b/MySql.Web/tests/SessionLocking/write2.aspx.designer.cs index 5c0052461..b545ee60b 100644 --- a/MySql.Web/tests/SessionLocking/write2.aspx.designer.cs +++ b/MySql.Web/tests/SessionLocking/write2.aspx.designer.cs @@ -1,24 +1,24 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace MySql.Web.Tests { - - - public partial class write2 { - - /// - /// form1 control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.HtmlControls.HtmlForm form1; - } -} +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace MySql.Web.Tests { + + + public partial class write2 { + + /// + /// form1 control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.HtmlControls.HtmlForm form1; + } +} diff --git a/MySql.Web/tests/SessionTests.cs b/MySql.Web/tests/SessionTests.cs index 25cdeea83..efdf692cc 100644 --- a/MySql.Web/tests/SessionTests.cs +++ b/MySql.Web/tests/SessionTests.cs @@ -1,381 +1,381 @@ -// Copyright (c) 2013, 2020, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySql.Data.MySqlClient; -using MySql.Web.SessionState; -using NUnit.Framework; -using System; -using System.Collections.Specialized; -using System.Configuration; -using System.Diagnostics; -using System.IO; -using System.Net; -using System.Threading; -using System.Web.SessionState; - -namespace MySql.Web.Tests -{ - public class SessionTests : WebTestBase - { - private string strSessionID { get; set; } - private string calledId { get; set; } - private AutoResetEvent _evt { get; set; } - - private byte[] Serialize(SessionStateItemCollection items) - { - MemoryStream ms = new MemoryStream(); - BinaryWriter writer = new BinaryWriter(ms); - if (items != null) - { - items.Serialize(writer); - } - writer.Close(); - return ms.ToArray(); - } - - - private void CreateSessionData(int AppId, DateTime timeCreated) - { - MySqlCommand cmd = new MySqlCommand(); - strSessionID = System.Guid.NewGuid().ToString(); - - //DateTime now = DateTime.Now; - //DateTime lastHour = now.Subtract(new TimeSpan(1, 0, 0)); - - SessionStateItemCollection collection = new SessionStateItemCollection(); - collection["FirstName"] = "Some"; - collection["LastName"] = "Name"; - byte[] items = Serialize(collection); - - string sql = @"INSERT INTO my_aspnet_sessions VALUES ( - @sessionId, @appId, @created, @expires, @lockdate, @lockid, @timeout, - @locked, @items, @flags)"; - - cmd = new MySqlCommand(sql, Connection); - cmd.Parameters.AddWithValue("@sessionId", strSessionID); - cmd.Parameters.AddWithValue("@appId", AppId); - cmd.Parameters.AddWithValue("@created", timeCreated); - cmd.Parameters.AddWithValue("@expires", timeCreated); - cmd.Parameters.AddWithValue("@lockdate", timeCreated); - cmd.Parameters.AddWithValue("@lockid", 1); - cmd.Parameters.AddWithValue("@timeout", 1); - cmd.Parameters.AddWithValue("@locked", 0); - cmd.Parameters.AddWithValue("@items", items); - cmd.Parameters.AddWithValue("@flags", 0); - cmd.ExecuteNonQuery(); - - //create new row on sessioncleanup table - cmd.CommandText = "INSERT IGNORE INTO my_aspnet_sessioncleanup SET" + - " ApplicationId = @ApplicationId, " + - " LastRun = NOW(), " + - " IntervalMinutes = 10"; - cmd.Parameters.Clear(); - cmd.Parameters.AddWithValue("@ApplicationId", AppId); - cmd.ExecuteNonQuery(); - - // set our last run table to 1 hour ago - cmd.CommandText = "UPDATE my_aspnet_sessioncleanup SET LastRun=@lastHour WHERE ApplicationId = @ApplicationId"; - cmd.Parameters.Clear(); - cmd.Parameters.AddWithValue("@lastHour", DateTime.Now.Subtract(new TimeSpan(1, 0, 0))); - cmd.Parameters.AddWithValue("@ApplicationId", AppId); - cmd.ExecuteNonQuery(); - } - - - private void SetSessionItemExpiredCallback(bool includeCallback) - { - _evt = new AutoResetEvent(false); - calledId = null; - - CreateSessionData(1, DateTime.Now.Subtract(new TimeSpan(1, 0, 0))); - - MySqlSessionStateStore session = new MySqlSessionStateStore(); - - NameValueCollection config = new NameValueCollection(); - config.Add("connectionStringName", "LocalMySqlServer"); - config.Add("applicationName", "/"); - config.Add("enableExpireCallback", includeCallback ? "true" : "false"); - session.Initialize("SessionProvTest", config); - if (includeCallback) session.SetItemExpireCallback(expireCallback); - Thread.Sleep(1000); - session.Dispose(); - } - - private long CountSessions() - { - return (long)MySqlHelper.ExecuteScalar(Connection, "SELECT COUNT(*) FROM my_aspnet_sessions"); - } - - public void expireCallback(string id, SessionStateStoreData item) - { - calledId = id; - _evt.Set(); - } - - - [Test] - public void SessionItemWithExpireCallback() - { - execSQL(@"delete from my_aspnet_sessions; - delete from my_aspnet_sessioncleanup;"); - SetSessionItemExpiredCallback(true); - _evt.WaitOne(); - - Assert.AreEqual(strSessionID, calledId); - - int i = 0; - while (((long)CountSessions() != 0) && (i < 10)) - { - Thread.Sleep(500); - i++; - } - - Assert.AreEqual(0, CountSessions()); - } - - - [Test] - public void SessionItemWithoutExpireCallback() - { - execSQL(@"delete from my_aspnet_sessions; - delete from my_aspnet_sessioncleanup;"); - SetSessionItemExpiredCallback(false); - Assert.AreNotEqual(strSessionID, calledId); - - int i = 0; - while (((long)MySqlHelper.ExecuteScalar(Connection, "SELECT Count(*) FROM my_aspnet_sessions;") != 0) && (i < 10)) - { - Thread.Sleep(500); - i++; - } - - Assert.AreEqual(0, CountSessions()); - } - - [Test] - public void DeleteSessionAppSpecific() - { - // create two sessions of different appId - // it should delete only 1 - CreateSessionData(1, DateTime.Now.Subtract(new TimeSpan(1, 10, 0))); - CreateSessionData(2, DateTime.Now.Subtract(new TimeSpan(1, 0, 0))); - - MySqlSessionStateStore session = new MySqlSessionStateStore(); - - NameValueCollection config = new NameValueCollection(); - config.Add("connectionStringName", "LocalMySqlServer"); - config.Add("applicationName", "/"); - config.Add("enableExpireCallback", "false"); - session.Initialize("SessionTests", config); - - int i = 0; - while (CountSessions() == 2 && (i < 10)) - { - Thread.Sleep(500); - i++; - } - - session.Dispose(); - Assert.AreEqual(1, CountSessions()); - session.Dispose(); - } - - public class ThreadRequestData - { - public string pageName; - public ManualResetEvent signal; - public bool FirstDateToUpdate; - } - - delegate WebResponse GetResponse(); - delegate void ThreadRequest(ThreadRequestData data); - - [Ignore("Fix Me")] - public void SessionLocking() - { - // Copy updated configuration file for web server process - Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None); - ConnectionStringSettings css = config.ConnectionStrings.ConnectionStrings["LocalMySqlServer"]; - string curDir = Directory.GetCurrentDirectory(); - string webconfigPath = string.Format(@"{0}\SessionLocking\{1}", Directory.GetCurrentDirectory(), @"web.config"); - string webconfigPathSrc = string.Format(@"{0}\SessionLocking\{1}", Directory.GetCurrentDirectory(), @"web_config_src.txt"); - - string text = File.ReadAllText(webconfigPathSrc); - text = text.Replace("connection_string_here", css.ConnectionString); - Version ver = System.Environment.Version; - if (ver.Major != 4) - { - text = text.Replace("", ""); - } - - File.WriteAllText(webconfigPath, text); - - int port = 12224; - - string webserverPath; - if (ver.Major == 4) - { - webserverPath = @"C:\Program Files (x86)\Common Files\microsoft shared\DevServer\10.0\WebDev.WebServer40.exe"; - } - else - { - webserverPath = @"C:\Program Files (x86)\Common Files\microsoft shared\DevServer\9.0\WebDev.WebServer.exe"; - } - string webserverArgs = string.Format(" /port:{0} /path:{1}\\SessionLocking", port, - Path.GetFullPath(@".")); - - DirectoryInfo di = new DirectoryInfo(Path.GetFullPath(curDir)); - Directory.CreateDirectory(Path.GetFullPath(@".\SessionLocking\bin")); - foreach (FileInfo fi in di.GetFiles("*.dll")) - { - File.Copy(fi.FullName, Path.Combine(Path.GetFullPath(@".\SessionLocking\bin\"), fi.Name), true); - } - - Process webserver = Process.Start(webserverPath, webserverArgs); - System.Threading.Thread.Sleep(2000); - - // This dummy request is just to get the ASP.NET sessionid to reuse. - HttpWebRequest req = (HttpWebRequest)WebRequest.Create("http://localhost:12224/InitSessionLocking.aspx"); - HttpWebResponse res = (HttpWebResponse)req.GetResponse(); - WebHeaderCollection headers = new WebHeaderCollection(); - - string url = res.ResponseUri.ToString().Replace("InitSessionLocking.aspx", ""); - Debug.Write(url); - - try - { - DateTime? firstDt = null; - DateTime? secondDt = null; - - ManualResetEvent[] re = new ManualResetEvent[2]; - re[0] = new ManualResetEvent(false); - re[1] = new ManualResetEvent(false); - ParameterizedThreadStart ts = - (object data1) => - { - ThreadRequestData data = (ThreadRequestData)data1; - Debug.WriteLine(string.Format("Requesting {0}", data.pageName)); - try - { - HttpWebRequest req1 = - (HttpWebRequest)WebRequest.Create(string.Format(@"{0}{1}", url, data.pageName)); - req1.Timeout = 2000000; - WebResponse res1 = req1.GetResponse(); - Debug.WriteLine(string.Format("Response from {0}", data.pageName)); - Stream s = res1.GetResponseStream(); - while (s.ReadByte() != -1) - ; - res1.Close(); - if (data.FirstDateToUpdate) - { - firstDt = DateTime.Now; - } - else - { - secondDt = DateTime.Now; - } - } - catch (Exception e) - { - Debug.WriteLine(string.Format("Server error: {0}", e.ToString())); - throw; - } - finally - { - data.signal.Set(); - } - }; - - Thread t = new Thread(ts); - Thread t2 = new Thread(ts); - t.Start(new ThreadRequestData() - { - pageName = "write.aspx", - FirstDateToUpdate = true, - signal = re[0] - }); - t2.Start(new ThreadRequestData() - { - pageName = "read.aspx", - FirstDateToUpdate = false, - signal = re[1] - }); - WaitHandle.WaitAll(re); - re[0].Reset(); - Thread t3 = new Thread(ts); - t3.Start(new ThreadRequestData() - { - pageName = "write2.aspx", - FirstDateToUpdate = false, - signal = re[0] - }); - WaitHandle.WaitAll(re); - double totalMillisecs = Math.Abs((secondDt.Value - firstDt.Value).TotalMilliseconds); - // OK if wait is less than session timeout - Debug.WriteLine(string.Empty); - Debug.WriteLine(totalMillisecs); - Assert.True(totalMillisecs < 30000); - } - finally - { - webserver.Kill(); - } - } - - public volatile static ManualResetEvent mtxReader = null; - public volatile static ManualResetEvent mtxWriter = null; - - public static void WaitSyncCreation(bool writer) - { - if (writer) - { - while (true) - { - if (mtxWriter == null) - Thread.Sleep(100); - else - break; - } - mtxWriter.WaitOne(); - } - else - { - while (true) - { - if (mtxReader == null) - Thread.Sleep(100); - else - break; - } - mtxReader.WaitOne(); - } - } - - - } -} +// Copyright © 2013, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySql.Data.MySqlClient; +using MySql.Web.SessionState; +using NUnit.Framework; +using System; +using System.Collections.Specialized; +using System.Configuration; +using System.Diagnostics; +using System.IO; +using System.Net; +using System.Threading; +using System.Web.SessionState; + +namespace MySql.Web.Tests +{ + public class SessionTests : WebTestBase + { + private string strSessionID { get; set; } + private string calledId { get; set; } + private AutoResetEvent _evt { get; set; } + + private byte[] Serialize(SessionStateItemCollection items) + { + MemoryStream ms = new MemoryStream(); + BinaryWriter writer = new BinaryWriter(ms); + if (items != null) + { + items.Serialize(writer); + } + writer.Close(); + return ms.ToArray(); + } + + + private void CreateSessionData(int AppId, DateTime timeCreated) + { + MySqlCommand cmd = new MySqlCommand(); + strSessionID = System.Guid.NewGuid().ToString(); + + //DateTime now = DateTime.Now; + //DateTime lastHour = now.Subtract(new TimeSpan(1, 0, 0)); + + SessionStateItemCollection collection = new SessionStateItemCollection(); + collection["FirstName"] = "Some"; + collection["LastName"] = "Name"; + byte[] items = Serialize(collection); + + string sql = @"INSERT INTO my_aspnet_sessions VALUES ( + @sessionId, @appId, @created, @expires, @lockdate, @lockid, @timeout, + @locked, @items, @flags)"; + + cmd = new MySqlCommand(sql, Connection); + cmd.Parameters.AddWithValue("@sessionId", strSessionID); + cmd.Parameters.AddWithValue("@appId", AppId); + cmd.Parameters.AddWithValue("@created", timeCreated); + cmd.Parameters.AddWithValue("@expires", timeCreated); + cmd.Parameters.AddWithValue("@lockdate", timeCreated); + cmd.Parameters.AddWithValue("@lockid", 1); + cmd.Parameters.AddWithValue("@timeout", 1); + cmd.Parameters.AddWithValue("@locked", 0); + cmd.Parameters.AddWithValue("@items", items); + cmd.Parameters.AddWithValue("@flags", 0); + cmd.ExecuteNonQuery(); + + //create new row on sessioncleanup table + cmd.CommandText = "INSERT IGNORE INTO my_aspnet_sessioncleanup SET" + + " ApplicationId = @ApplicationId, " + + " LastRun = NOW(), " + + " IntervalMinutes = 10"; + cmd.Parameters.Clear(); + cmd.Parameters.AddWithValue("@ApplicationId", AppId); + cmd.ExecuteNonQuery(); + + // set our last run table to 1 hour ago + cmd.CommandText = "UPDATE my_aspnet_sessioncleanup SET LastRun=@lastHour WHERE ApplicationId = @ApplicationId"; + cmd.Parameters.Clear(); + cmd.Parameters.AddWithValue("@lastHour", DateTime.Now.Subtract(new TimeSpan(1, 0, 0))); + cmd.Parameters.AddWithValue("@ApplicationId", AppId); + cmd.ExecuteNonQuery(); + } + + + private void SetSessionItemExpiredCallback(bool includeCallback) + { + _evt = new AutoResetEvent(false); + calledId = null; + + CreateSessionData(1, DateTime.Now.Subtract(new TimeSpan(1, 0, 0))); + + MySqlSessionStateStore session = new MySqlSessionStateStore(); + + NameValueCollection config = new NameValueCollection(); + config.Add("connectionStringName", "LocalMySqlServer"); + config.Add("applicationName", "/"); + config.Add("enableExpireCallback", includeCallback ? "true" : "false"); + session.Initialize("SessionProvTest", config); + if (includeCallback) session.SetItemExpireCallback(expireCallback); + Thread.Sleep(1000); + session.Dispose(); + } + + private long CountSessions() + { + return (long)MySqlHelper.ExecuteScalar(Connection, "SELECT COUNT(*) FROM my_aspnet_sessions"); + } + + public void expireCallback(string id, SessionStateStoreData item) + { + calledId = id; + _evt.Set(); + } + + + [Test] + public void SessionItemWithExpireCallback() + { + execSQL(@"delete from my_aspnet_sessions; + delete from my_aspnet_sessioncleanup;"); + SetSessionItemExpiredCallback(true); + _evt.WaitOne(); + + Assert.AreEqual(strSessionID, calledId); + + int i = 0; + while (((long)CountSessions() != 0) && (i < 10)) + { + Thread.Sleep(500); + i++; + } + + Assert.AreEqual(0, CountSessions()); + } + + + [Test] + public void SessionItemWithoutExpireCallback() + { + execSQL(@"delete from my_aspnet_sessions; + delete from my_aspnet_sessioncleanup;"); + SetSessionItemExpiredCallback(false); + Assert.AreNotEqual(strSessionID, calledId); + + int i = 0; + while (((long)MySqlHelper.ExecuteScalar(Connection, "SELECT Count(*) FROM my_aspnet_sessions;") != 0) && (i < 10)) + { + Thread.Sleep(500); + i++; + } + + Assert.AreEqual(0, CountSessions()); + } + + [Test] + public void DeleteSessionAppSpecific() + { + // create two sessions of different appId + // it should delete only 1 + CreateSessionData(1, DateTime.Now.Subtract(new TimeSpan(1, 10, 0))); + CreateSessionData(2, DateTime.Now.Subtract(new TimeSpan(1, 0, 0))); + + MySqlSessionStateStore session = new MySqlSessionStateStore(); + + NameValueCollection config = new NameValueCollection(); + config.Add("connectionStringName", "LocalMySqlServer"); + config.Add("applicationName", "/"); + config.Add("enableExpireCallback", "false"); + session.Initialize("SessionTests", config); + + int i = 0; + while (CountSessions() == 2 && (i < 10)) + { + Thread.Sleep(500); + i++; + } + + session.Dispose(); + Assert.AreEqual(1, CountSessions()); + session.Dispose(); + } + + public class ThreadRequestData + { + public string pageName; + public ManualResetEvent signal; + public bool FirstDateToUpdate; + } + + delegate WebResponse GetResponse(); + delegate void ThreadRequest(ThreadRequestData data); + + [Ignore("Fix Me")] + public void SessionLocking() + { + // Copy updated configuration file for web server process + Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None); + ConnectionStringSettings css = config.ConnectionStrings.ConnectionStrings["LocalMySqlServer"]; + string curDir = Directory.GetCurrentDirectory(); + string webconfigPath = string.Format(@"{0}\SessionLocking\{1}", Directory.GetCurrentDirectory(), @"web.config"); + string webconfigPathSrc = string.Format(@"{0}\SessionLocking\{1}", Directory.GetCurrentDirectory(), @"web_config_src.txt"); + + string text = File.ReadAllText(webconfigPathSrc); + text = text.Replace("connection_string_here", css.ConnectionString); + Version ver = System.Environment.Version; + if (ver.Major != 4) + { + text = text.Replace("", ""); + } + + File.WriteAllText(webconfigPath, text); + + int port = 12224; + + string webserverPath; + if (ver.Major == 4) + { + webserverPath = @"C:\Program Files (x86)\Common Files\microsoft shared\DevServer\10.0\WebDev.WebServer40.exe"; + } + else + { + webserverPath = @"C:\Program Files (x86)\Common Files\microsoft shared\DevServer\9.0\WebDev.WebServer.exe"; + } + string webserverArgs = string.Format(" /port:{0} /path:{1}\\SessionLocking", port, + Path.GetFullPath(@".")); + + DirectoryInfo di = new DirectoryInfo(Path.GetFullPath(curDir)); + Directory.CreateDirectory(Path.GetFullPath(@".\SessionLocking\bin")); + foreach (FileInfo fi in di.GetFiles("*.dll")) + { + File.Copy(fi.FullName, Path.Combine(Path.GetFullPath(@".\SessionLocking\bin\"), fi.Name), true); + } + + Process webserver = Process.Start(webserverPath, webserverArgs); + System.Threading.Thread.Sleep(2000); + + // This dummy request is just to get the ASP.NET sessionid to reuse. + HttpWebRequest req = (HttpWebRequest)WebRequest.Create("http://localhost:12224/InitSessionLocking.aspx"); + HttpWebResponse res = (HttpWebResponse)req.GetResponse(); + WebHeaderCollection headers = new WebHeaderCollection(); + + string url = res.ResponseUri.ToString().Replace("InitSessionLocking.aspx", ""); + Debug.Write(url); + + try + { + DateTime? firstDt = null; + DateTime? secondDt = null; + + ManualResetEvent[] re = new ManualResetEvent[2]; + re[0] = new ManualResetEvent(false); + re[1] = new ManualResetEvent(false); + ParameterizedThreadStart ts = + (object data1) => + { + ThreadRequestData data = (ThreadRequestData)data1; + Debug.WriteLine(string.Format("Requesting {0}", data.pageName)); + try + { + HttpWebRequest req1 = + (HttpWebRequest)WebRequest.Create(string.Format(@"{0}{1}", url, data.pageName)); + req1.Timeout = 2000000; + WebResponse res1 = req1.GetResponse(); + Debug.WriteLine(string.Format("Response from {0}", data.pageName)); + Stream s = res1.GetResponseStream(); + while (s.ReadByte() != -1) + ; + res1.Close(); + if (data.FirstDateToUpdate) + { + firstDt = DateTime.Now; + } + else + { + secondDt = DateTime.Now; + } + } + catch (Exception e) + { + Debug.WriteLine(string.Format("Server error: {0}", e.ToString())); + throw; + } + finally + { + data.signal.Set(); + } + }; + + Thread t = new Thread(ts); + Thread t2 = new Thread(ts); + t.Start(new ThreadRequestData() + { + pageName = "write.aspx", + FirstDateToUpdate = true, + signal = re[0] + }); + t2.Start(new ThreadRequestData() + { + pageName = "read.aspx", + FirstDateToUpdate = false, + signal = re[1] + }); + WaitHandle.WaitAll(re); + re[0].Reset(); + Thread t3 = new Thread(ts); + t3.Start(new ThreadRequestData() + { + pageName = "write2.aspx", + FirstDateToUpdate = false, + signal = re[0] + }); + WaitHandle.WaitAll(re); + double totalMillisecs = Math.Abs((secondDt.Value - firstDt.Value).TotalMilliseconds); + // OK if wait is less than session timeout + Debug.WriteLine(string.Empty); + Debug.WriteLine(totalMillisecs); + Assert.True(totalMillisecs < 30000); + } + finally + { + webserver.Kill(); + } + } + + public volatile static ManualResetEvent mtxReader = null; + public volatile static ManualResetEvent mtxWriter = null; + + public static void WaitSyncCreation(bool writer) + { + if (writer) + { + while (true) + { + if (mtxWriter == null) + Thread.Sleep(100); + else + break; + } + mtxWriter.WaitOne(); + } + else + { + while (true) + { + if (mtxReader == null) + Thread.Sleep(100); + else + break; + } + mtxReader.WaitOne(); + } + } + + + } +} diff --git a/MySql.Web/tests/SimpleMembership.cs b/MySql.Web/tests/SimpleMembership.cs index 4a7caf8f7..12e785d3e 100644 --- a/MySql.Web/tests/SimpleMembership.cs +++ b/MySql.Web/tests/SimpleMembership.cs @@ -1,228 +1,228 @@ -// Copyright (c) 2014, 2021, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySql.Data.MySqlClient; -using MySql.Web.Security; -using NUnit.Framework; -using System; -using System.Collections.Specialized; -using System.Web.Security; - -namespace MySql.Web.Tests -{ - public class SimpleMembership : WebTestBase - { - private readonly string _userTable = "UserProfile"; - private readonly string _userIdColumn = "UserId"; - private readonly string _userNameColumn = "UserName"; - private readonly string _userName = "New User"; - private readonly string _pass = "password"; - private MySqlSimpleMembershipProvider _simpleProvider; - private MySqlSimpleRoleProvider _simpleRoleProvider; - - public SimpleMembership() - { - _simpleProvider = new MySqlSimpleMembershipProvider(); - _simpleRoleProvider = new MySqlSimpleRoleProvider(); - - var _config = new NameValueCollection(); - _config.Add("connectionStringName", "LocalMySqlServer"); - _config.Add("userTableName", "UserProfile"); - _config.Add("userIdColumn", "UserId"); - _config.Add("userNameColumn", "UserName"); - - _simpleProvider.Initialize("Test", _config); - _simpleRoleProvider.Initialize("TestRoleProvider", _config); - - MySqlWebSecurity.InitializeDatabaseConnection(ConnectionString, "MySqlSimpleMembership", _userTable, _userIdColumn, _userNameColumn, true, true); - } - - [TearDown] - public void Cleanup() - { - execSQL(@"delete from userprofile; - delete from webpages_membership;"); - } - - [Test] - public void CheckIfRoleNotExists() - { - var roleExists = _simpleRoleProvider.RoleExists("roleName"); - Assert.False(roleExists); - } - - [Test] - public void CheckIfRoleExists() - { - if (!Roles.RoleExists("Administrator")) - { - _simpleRoleProvider.CreateRole("Administrator"); - var roleExists = _simpleRoleProvider.RoleExists("Administrator"); - Assert.True(roleExists); - } - } - - [Test] - public void CreateUserAndAccountTest() - { - MySqlWebSecurity.CreateUserAndAccount(_userName, _pass); - Assert.True(MySqlWebSecurity.UserExists(_userName)); - var user = MySqlHelper.ExecuteDataRow(ConnectionString, string.Format("select * from {0} where {1} = '{2}'", _userTable, _userNameColumn, _userName)); - Assert.IsNotNull(user); - Assert.AreEqual(_userName, user[_userNameColumn]); - - Assert.True(_simpleProvider.ValidateUser(_userName, _pass)); - //We need to mock the login because in that method there is a call to "FormsAuthentication.SetAuthCookie" which causes an "Object reference not set to an instance of an object" exception, because the test doesn't run on web application context - //Assert.True(MySqlWebSecurity.Login(_userName, _pass)); - } - - //We need to mock this test because there is no data on Membership object, there is no user available because login doesn't add it to the context - //[Test] - public void ChangePasswordTest() - { - string newPass = "newpassword"; - MySqlWebSecurity.CreateUserAndAccount(_userName, _pass); - Assert.True(MySqlWebSecurity.UserExists(_userName)); - - //We need to mock the login because in that method there is a call to "FormsAuthentication.SetAuthCookie" which causes an "Object reference not set to an instance of an object" exception, because the test doesn't run on web application context - - Assert.True(_simpleProvider.ValidateUser(_userName, _pass)); - //Assert.True(MySqlWebSecurity.Login(_userName, _pass)); - - Assert.True(MySqlWebSecurity.ChangePassword(_userName, _pass, newPass)); - - Assert.True(_simpleProvider.ValidateUser(_userName, newPass)); - //Assert.True(MySqlWebSecurity.Login(_userName, newPass)); - } - - [Test] - public void ConfirmAccountWithTokenTest() - { - var token = MySqlWebSecurity.CreateUserAndAccount(_userName, _pass, null, true); - Assert.True(MySqlWebSecurity.UserExists(_userName)); - Assert.True(MySqlWebSecurity.ConfirmAccount(token)); - } - - [Test] - public void ConfirmAccountWithUserAndTokenTest() - { - var token = MySqlWebSecurity.CreateUserAndAccount(_userName, _pass, null, true); - Assert.True(MySqlWebSecurity.UserExists(_userName)); - Assert.True(MySqlWebSecurity.ConfirmAccount(_userName, token)); - } - - [Test] - public void ConfirmAccountWithoutTokenTest() - { - var token = "falsetoken"; - MySqlWebSecurity.CreateUserAndAccount(_userName, _pass); - Assert.True(MySqlWebSecurity.UserExists(_userName)); - Assert.False(MySqlWebSecurity.ConfirmAccount(token)); - } - - [Test] - public void CreatedDateTest() - { - execSQL(@"delete from userprofile; - delete from webpages_membership;"); - MySqlWebSecurity.CreateUserAndAccount(_userName, _pass); - Assert.AreNotEqual(DateTime.MinValue, MySqlWebSecurity.GetCreateDate(_userName)); - } - - [Test] - public void DeleteTest() - { - _simpleProvider.CreateUserAndAccount(_userName, _pass, false, null); - Assert.True(_simpleProvider.DeleteAccount(_userName)); - _simpleProvider.CreateAccount(_userName, _pass, false); - Assert.True(_simpleProvider.DeleteUser(_userName, true)); - } - - [Test] - public void UserIsConfirmedTest() - { - MySqlWebSecurity.CreateUserAndAccount(_userName, _pass, null, true); - Assert.False(MySqlWebSecurity.IsConfirmed(_userName)); - } - - [Test] - public void UserIsLockedOutTest() - { - MySqlWebSecurity.CreateUserAndAccount(_userName, _pass, null, true); - Assert.False(MySqlWebSecurity.IsAccountLockedOut(_userName, 5, 60)); - } - - [Test] - public void PasswordTest() - { - MySqlWebSecurity.CreateUserAndAccount(_userName, _pass); - Assert.AreEqual(DateTime.MinValue, MySqlWebSecurity.GetLastPasswordFailureDate(_userName)); - Assert.AreNotEqual(DateTime.MinValue, MySqlWebSecurity.GetPasswordChangedDate(_userName)); - Assert.AreEqual(0, MySqlWebSecurity.GetPasswordFailuresSinceLastSuccess(_userName)); - } - - //Password reset token must be assigned to the user but that field is not added in any part of the code, so maybe that field must be handled manually by the user - // should we handle this functionality? WebMatrix.WebData.SimpleMembershipProvider doesn't handle it - [Ignore("Fix Me")] - public void PasswordResetTokenTest() - { - var token = MySqlWebSecurity.CreateUserAndAccount(_userName, _pass, null, true); - int userID = MySqlWebSecurity.GetUserId(_userName); - Assert.True(MySqlWebSecurity.ConfirmAccount(token)); - var newToken = MySqlWebSecurity.GeneratePasswordResetToken(_userName, 1440); - Assert.AreNotEqual(null, newToken); - Assert.AreEqual(MySqlWebSecurity.GetUserIdFromPasswordResetToken(newToken), userID); - } - - #region WL14389 - [TestCase(1, "Waren", null)] - [TestCase(2, "Bill", false)] - [TestCase(3, "Steve", true)] - public void CreateUserAccountWithAttributes(int id, string userN, bool? token) - { - //Bug25046364 - switch (token) - { - case null: - MySqlWebSecurity.CreateUserAndAccount(userN, _pass, new {UserId = id, UserName = userN}); - break; - - default: - MySqlWebSecurity.CreateUserAndAccount(userN, _pass, new { UserId = id, UserName = userN }, (bool)token); - break; - } - - Assert.True(MySqlWebSecurity.UserExists(userN)); - var user = MySqlHelper.ExecuteDataRow(ConnectionString, string.Format("select * from {0} where {1} = '{2}'", _userTable, _userNameColumn, userN)); - Assert.IsNotNull(user); - Assert.AreEqual(userN, user[_userNameColumn]); - } - #endregion - - } -} +// Copyright © 2014, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySql.Data.MySqlClient; +using MySql.Web.Security; +using NUnit.Framework; +using System; +using System.Collections.Specialized; +using System.Web.Security; + +namespace MySql.Web.Tests +{ + public class SimpleMembership : WebTestBase + { + private readonly string _userTable = "UserProfile"; + private readonly string _userIdColumn = "UserId"; + private readonly string _userNameColumn = "UserName"; + private readonly string _userName = "New User"; + private readonly string _pass = "password"; + private MySqlSimpleMembershipProvider _simpleProvider; + private MySqlSimpleRoleProvider _simpleRoleProvider; + + public SimpleMembership() + { + _simpleProvider = new MySqlSimpleMembershipProvider(); + _simpleRoleProvider = new MySqlSimpleRoleProvider(); + + var _config = new NameValueCollection(); + _config.Add("connectionStringName", "LocalMySqlServer"); + _config.Add("userTableName", "UserProfile"); + _config.Add("userIdColumn", "UserId"); + _config.Add("userNameColumn", "UserName"); + + _simpleProvider.Initialize("Test", _config); + _simpleRoleProvider.Initialize("TestRoleProvider", _config); + + MySqlWebSecurity.InitializeDatabaseConnection(ConnectionString, "MySqlSimpleMembership", _userTable, _userIdColumn, _userNameColumn, true, true); + } + + [TearDown] + public void Cleanup() + { + execSQL(@"delete from userprofile; + delete from webpages_membership;"); + } + + [Test] + public void CheckIfRoleNotExists() + { + var roleExists = _simpleRoleProvider.RoleExists("roleName"); + Assert.False(roleExists); + } + + [Test] + public void CheckIfRoleExists() + { + if (!Roles.RoleExists("Administrator")) + { + _simpleRoleProvider.CreateRole("Administrator"); + var roleExists = _simpleRoleProvider.RoleExists("Administrator"); + Assert.True(roleExists); + } + } + + [Test] + public void CreateUserAndAccountTest() + { + MySqlWebSecurity.CreateUserAndAccount(_userName, _pass); + Assert.True(MySqlWebSecurity.UserExists(_userName)); + var user = MySqlHelper.ExecuteDataRow(ConnectionString, string.Format("select * from {0} where {1} = '{2}'", _userTable, _userNameColumn, _userName)); + Assert.IsNotNull(user); + Assert.AreEqual(_userName, user[_userNameColumn]); + + Assert.True(_simpleProvider.ValidateUser(_userName, _pass)); + //We need to mock the login because in that method there is a call to "FormsAuthentication.SetAuthCookie" which causes an "Object reference not set to an instance of an object" exception, because the test doesn't run on web application context + //Assert.True(MySqlWebSecurity.Login(_userName, _pass)); + } + + //We need to mock this test because there is no data on Membership object, there is no user available because login doesn't add it to the context + //[Test] + public void ChangePasswordTest() + { + string newPass = "newpassword"; + MySqlWebSecurity.CreateUserAndAccount(_userName, _pass); + Assert.True(MySqlWebSecurity.UserExists(_userName)); + + //We need to mock the login because in that method there is a call to "FormsAuthentication.SetAuthCookie" which causes an "Object reference not set to an instance of an object" exception, because the test doesn't run on web application context + + Assert.True(_simpleProvider.ValidateUser(_userName, _pass)); + //Assert.True(MySqlWebSecurity.Login(_userName, _pass)); + + Assert.True(MySqlWebSecurity.ChangePassword(_userName, _pass, newPass)); + + Assert.True(_simpleProvider.ValidateUser(_userName, newPass)); + //Assert.True(MySqlWebSecurity.Login(_userName, newPass)); + } + + [Test] + public void ConfirmAccountWithTokenTest() + { + var token = MySqlWebSecurity.CreateUserAndAccount(_userName, _pass, null, true); + Assert.True(MySqlWebSecurity.UserExists(_userName)); + Assert.True(MySqlWebSecurity.ConfirmAccount(token)); + } + + [Test] + public void ConfirmAccountWithUserAndTokenTest() + { + var token = MySqlWebSecurity.CreateUserAndAccount(_userName, _pass, null, true); + Assert.True(MySqlWebSecurity.UserExists(_userName)); + Assert.True(MySqlWebSecurity.ConfirmAccount(_userName, token)); + } + + [Test] + public void ConfirmAccountWithoutTokenTest() + { + var token = "falsetoken"; + MySqlWebSecurity.CreateUserAndAccount(_userName, _pass); + Assert.True(MySqlWebSecurity.UserExists(_userName)); + Assert.False(MySqlWebSecurity.ConfirmAccount(token)); + } + + [Test] + public void CreatedDateTest() + { + execSQL(@"delete from userprofile; + delete from webpages_membership;"); + MySqlWebSecurity.CreateUserAndAccount(_userName, _pass); + Assert.AreNotEqual(DateTime.MinValue, MySqlWebSecurity.GetCreateDate(_userName)); + } + + [Test] + public void DeleteTest() + { + _simpleProvider.CreateUserAndAccount(_userName, _pass, false, null); + Assert.True(_simpleProvider.DeleteAccount(_userName)); + _simpleProvider.CreateAccount(_userName, _pass, false); + Assert.True(_simpleProvider.DeleteUser(_userName, true)); + } + + [Test] + public void UserIsConfirmedTest() + { + MySqlWebSecurity.CreateUserAndAccount(_userName, _pass, null, true); + Assert.False(MySqlWebSecurity.IsConfirmed(_userName)); + } + + [Test] + public void UserIsLockedOutTest() + { + MySqlWebSecurity.CreateUserAndAccount(_userName, _pass, null, true); + Assert.False(MySqlWebSecurity.IsAccountLockedOut(_userName, 5, 60)); + } + + [Test] + public void PasswordTest() + { + MySqlWebSecurity.CreateUserAndAccount(_userName, _pass); + Assert.AreEqual(DateTime.MinValue, MySqlWebSecurity.GetLastPasswordFailureDate(_userName)); + Assert.AreNotEqual(DateTime.MinValue, MySqlWebSecurity.GetPasswordChangedDate(_userName)); + Assert.AreEqual(0, MySqlWebSecurity.GetPasswordFailuresSinceLastSuccess(_userName)); + } + + //Password reset token must be assigned to the user but that field is not added in any part of the code, so maybe that field must be handled manually by the user + // should we handle this functionality? WebMatrix.WebData.SimpleMembershipProvider doesn't handle it + [Ignore("Fix Me")] + public void PasswordResetTokenTest() + { + var token = MySqlWebSecurity.CreateUserAndAccount(_userName, _pass, null, true); + int userID = MySqlWebSecurity.GetUserId(_userName); + Assert.True(MySqlWebSecurity.ConfirmAccount(token)); + var newToken = MySqlWebSecurity.GeneratePasswordResetToken(_userName, 1440); + Assert.AreNotEqual(null, newToken); + Assert.AreEqual(MySqlWebSecurity.GetUserIdFromPasswordResetToken(newToken), userID); + } + + #region WL14389 + [TestCase(1, "Waren", null)] + [TestCase(2, "Bill", false)] + [TestCase(3, "Steve", true)] + public void CreateUserAccountWithAttributes(int id, string userN, bool? token) + { + //Bug25046364 + switch (token) + { + case null: + MySqlWebSecurity.CreateUserAndAccount(userN, _pass, new {UserId = id, UserName = userN}); + break; + + default: + MySqlWebSecurity.CreateUserAndAccount(userN, _pass, new { UserId = id, UserName = userN }, (bool)token); + break; + } + + Assert.True(MySqlWebSecurity.UserExists(userN)); + var user = MySqlHelper.ExecuteDataRow(ConnectionString, string.Format("select * from {0} where {1} = '{2}'", _userTable, _userNameColumn, userN)); + Assert.IsNotNull(user); + Assert.AreEqual(userN, user[_userNameColumn]); + } + #endregion + + } +} diff --git a/MySql.Web/tests/SiteMapTests.cs b/MySql.Web/tests/SiteMapTests.cs index 9946dd271..c288f9458 100644 --- a/MySql.Web/tests/SiteMapTests.cs +++ b/MySql.Web/tests/SiteMapTests.cs @@ -1,118 +1,118 @@ -// Copyright (c) 2014, 2020, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySql.Data.MySqlClient; -using MySql.Web.SiteMap; -using NUnit.Framework; -using System; -using System.Collections.Specialized; -using System.IO; -using System.Web; -using System.Web.Hosting; - -namespace MySql.Web.Tests -{ - public class SiteMapTests : WebTestBase - { - private void PopulateSiteMapTable() - { - string sql = @" - insert into my_aspnet_sitemap( Id, Title, Description, Url, Roles, ParentId ) values ( 1, 'Index', 'The Index page', '~/Index.aspx', null, null ); - insert into my_aspnet_sitemap( Id, Title, Description, Url, Roles, ParentId ) values ( 2, 'Chess Openings', 'Collection of Chess openings articles', '~/Openings.aspx', null, 1 ); - insert into my_aspnet_sitemap( Id, Title, Description, Url, Roles, ParentId ) values ( 3, 'King''s Gambit', 'The hyper sharp King''s Gambit', '~/Openings/KingsGambit.aspx', null, 2 ); - insert into my_aspnet_sitemap( Id, Title, Description, Url, Roles, ParentId ) values ( 4, 'Ruy Lopez', 'The spanish opening', '~/RuyLopez.aspx', null, 2 ); - insert into my_aspnet_sitemap( Id, Title, Description, Url, Roles, ParentId ) values ( 5, 'Evan''s Gambit', 'The Funny Italian Game', '~/EvansGambit.aspx', null, 2 ); - insert into my_aspnet_sitemap( Id, Title, Description, Url, Roles, ParentId ) values ( 6, 'Sicilian Defense', 'Sharp Double Edge Defense', '~/Sicilian.aspx', null, 2 ); - insert into my_aspnet_sitemap( Id, Title, Description, Url, Roles, ParentId ) values ( 7, 'Middle Game', 'Middle Game Topics', '~/MiddleGame.aspx', null, 1 ); - insert into my_aspnet_sitemap( Id, Title, Description, Url, Roles, ParentId ) values ( 8, 'Isolated Queen Pawn', 'Isolani Typical Positions', '~/Isolani.aspx', null, 7 ); - insert into my_aspnet_sitemap( Id, Title, Description, Url, Roles, ParentId ) values ( 9, 'Rook vs Two Minor pieces', 'Rook vs Two Minor Pieces', '~/RookVsTwoMinor.aspx', null, 7 ); - insert into my_aspnet_sitemap( Id, Title, Description, Url, Roles, ParentID ) values (10, 'Exchange Sacrifice', 'Sacrifice of Rook per Bishop or Knight', '~/ExchangeSacrifice.aspx', null, 7 ); - insert into my_aspnet_sitemap( Id, Title, Description, Url, Roles, ParentID ) values (11, 'Nd5 Sacrifice in Sicilian', 'Sacrifice Nc3-Nd5 against Schevening like structures', '~/Nd5SacSicilian.aspx', null, 7 ); - insert into my_aspnet_sitemap( Id, Title, Description, Url, Roles, ParentID ) values (12, 'Endings', 'Theory of chess endings & practical endings', '~/Endings.aspx', null, 1 ); - insert into my_aspnet_sitemap( Id, Title, Description, Url, Roles, ParentID ) values (13, 'Rook Endings', 'Rook Endings', '~/RookEndigs.aspx', null, 12 ); - insert into my_aspnet_sitemap( Id, Title, Description, Url, Roles, ParentID ) values (14, 'Queen vs Rook', 'Queen vs Rook, pawnless endings', '~/QueenVsRook.aspx ', null, 12 ); - insert into my_aspnet_sitemap( Id, Title, Description, Url, Roles, ParentID ) values (15, 'Isolated Queen Pawn Ending', 'Endings with queen pawn isolated', '~/IQPending.aspx', null, 12 ); - "; - MySqlScript script = new MySqlScript(Connection, sql); - script.Execute(); - } - - [Test] - public void TestBuildSiteMap() - { - PopulateSiteMapTable(); - - MySqlSiteMapProvider prov = new MySqlSiteMapProvider(); - NameValueCollection config = new NameValueCollection(); - config.Add("connectionStringName", "LocalMySqlServer"); - config.Add("applicationName", "/"); - config.Add("enableExpireCallback", "false"); - - prov.Initialize("SiteMapTests", config); - prov.BuildSiteMap(); - SiteMapNode node = prov.FindSiteMapNodeFromKey("5"); - SimpleWorkerRequest req = new SimpleWorkerRequest("/dummy", Environment.CurrentDirectory, "default.aspx", null, new StringWriter()); - HttpContext.Current = new HttpContext(req); - - Assert.AreEqual(node.Title, "Evan's Gambit"); - SiteMapNode nodep = prov.GetParentNode(node); - Assert.AreEqual(node.Description, "The Funny Italian Game"); - Assert.False(node.HasChildNodes); - SiteMapNode node2 = node.NextSibling; - Assert.IsNotNull(node2); - Assert.AreEqual(node2.Title, "Sicilian Defense"); - Assert.AreEqual(node2.Description, "Sharp Double Edge Defense"); - - node = node.PreviousSibling; - Assert.IsNotNull(node); - Assert.AreEqual(node.Title, "Ruy Lopez"); - Assert.AreEqual(node.Description, "The spanish opening"); - Assert.False(node.HasChildNodes); - Assert.IsNotNull(node.NextSibling); - - node = node.ParentNode; - Assert.AreEqual(node.Title, "Chess Openings"); - - node = node.ParentNode; - Assert.AreEqual(node.Title, "Index"); - - node = node.ParentNode; - Assert.IsNull(node); - - node = prov.RootNode; - Assert.AreEqual(node.Title, "Index"); - string[] childData = new string[] { "Chess Openings", "Middle Game", "Endings" }; - - for (int i = 0; i < node.ChildNodes.Count; i++) - { - SiteMapNode child = node.ChildNodes[i]; - Assert.AreEqual(child.Title, childData[i]); - } - } - } -} +// Copyright © 2014, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySql.Data.MySqlClient; +using MySql.Web.SiteMap; +using NUnit.Framework; +using System; +using System.Collections.Specialized; +using System.IO; +using System.Web; +using System.Web.Hosting; + +namespace MySql.Web.Tests +{ + public class SiteMapTests : WebTestBase + { + private void PopulateSiteMapTable() + { + string sql = @" + insert into my_aspnet_sitemap( Id, Title, Description, Url, Roles, ParentId ) values ( 1, 'Index', 'The Index page', '~/Index.aspx', null, null ); + insert into my_aspnet_sitemap( Id, Title, Description, Url, Roles, ParentId ) values ( 2, 'Chess Openings', 'Collection of Chess openings articles', '~/Openings.aspx', null, 1 ); + insert into my_aspnet_sitemap( Id, Title, Description, Url, Roles, ParentId ) values ( 3, 'King''s Gambit', 'The hyper sharp King''s Gambit', '~/Openings/KingsGambit.aspx', null, 2 ); + insert into my_aspnet_sitemap( Id, Title, Description, Url, Roles, ParentId ) values ( 4, 'Ruy Lopez', 'The spanish opening', '~/RuyLopez.aspx', null, 2 ); + insert into my_aspnet_sitemap( Id, Title, Description, Url, Roles, ParentId ) values ( 5, 'Evan''s Gambit', 'The Funny Italian Game', '~/EvansGambit.aspx', null, 2 ); + insert into my_aspnet_sitemap( Id, Title, Description, Url, Roles, ParentId ) values ( 6, 'Sicilian Defense', 'Sharp Double Edge Defense', '~/Sicilian.aspx', null, 2 ); + insert into my_aspnet_sitemap( Id, Title, Description, Url, Roles, ParentId ) values ( 7, 'Middle Game', 'Middle Game Topics', '~/MiddleGame.aspx', null, 1 ); + insert into my_aspnet_sitemap( Id, Title, Description, Url, Roles, ParentId ) values ( 8, 'Isolated Queen Pawn', 'Isolani Typical Positions', '~/Isolani.aspx', null, 7 ); + insert into my_aspnet_sitemap( Id, Title, Description, Url, Roles, ParentId ) values ( 9, 'Rook vs Two Minor pieces', 'Rook vs Two Minor Pieces', '~/RookVsTwoMinor.aspx', null, 7 ); + insert into my_aspnet_sitemap( Id, Title, Description, Url, Roles, ParentID ) values (10, 'Exchange Sacrifice', 'Sacrifice of Rook per Bishop or Knight', '~/ExchangeSacrifice.aspx', null, 7 ); + insert into my_aspnet_sitemap( Id, Title, Description, Url, Roles, ParentID ) values (11, 'Nd5 Sacrifice in Sicilian', 'Sacrifice Nc3-Nd5 against Schevening like structures', '~/Nd5SacSicilian.aspx', null, 7 ); + insert into my_aspnet_sitemap( Id, Title, Description, Url, Roles, ParentID ) values (12, 'Endings', 'Theory of chess endings & practical endings', '~/Endings.aspx', null, 1 ); + insert into my_aspnet_sitemap( Id, Title, Description, Url, Roles, ParentID ) values (13, 'Rook Endings', 'Rook Endings', '~/RookEndigs.aspx', null, 12 ); + insert into my_aspnet_sitemap( Id, Title, Description, Url, Roles, ParentID ) values (14, 'Queen vs Rook', 'Queen vs Rook, pawnless endings', '~/QueenVsRook.aspx ', null, 12 ); + insert into my_aspnet_sitemap( Id, Title, Description, Url, Roles, ParentID ) values (15, 'Isolated Queen Pawn Ending', 'Endings with queen pawn isolated', '~/IQPending.aspx', null, 12 ); + "; + MySqlScript script = new MySqlScript(Connection, sql); + script.Execute(); + } + + [Test] + public void TestBuildSiteMap() + { + PopulateSiteMapTable(); + + MySqlSiteMapProvider prov = new MySqlSiteMapProvider(); + NameValueCollection config = new NameValueCollection(); + config.Add("connectionStringName", "LocalMySqlServer"); + config.Add("applicationName", "/"); + config.Add("enableExpireCallback", "false"); + + prov.Initialize("SiteMapTests", config); + prov.BuildSiteMap(); + SiteMapNode node = prov.FindSiteMapNodeFromKey("5"); + SimpleWorkerRequest req = new SimpleWorkerRequest("/dummy", Environment.CurrentDirectory, "default.aspx", null, new StringWriter()); + HttpContext.Current = new HttpContext(req); + + Assert.AreEqual(node.Title, "Evan's Gambit"); + SiteMapNode nodep = prov.GetParentNode(node); + Assert.AreEqual(node.Description, "The Funny Italian Game"); + Assert.False(node.HasChildNodes); + SiteMapNode node2 = node.NextSibling; + Assert.IsNotNull(node2); + Assert.AreEqual(node2.Title, "Sicilian Defense"); + Assert.AreEqual(node2.Description, "Sharp Double Edge Defense"); + + node = node.PreviousSibling; + Assert.IsNotNull(node); + Assert.AreEqual(node.Title, "Ruy Lopez"); + Assert.AreEqual(node.Description, "The spanish opening"); + Assert.False(node.HasChildNodes); + Assert.IsNotNull(node.NextSibling); + + node = node.ParentNode; + Assert.AreEqual(node.Title, "Chess Openings"); + + node = node.ParentNode; + Assert.AreEqual(node.Title, "Index"); + + node = node.ParentNode; + Assert.IsNull(node); + + node = prov.RootNode; + Assert.AreEqual(node.Title, "Index"); + string[] childData = new string[] { "Chess Openings", "Middle Game", "Endings" }; + + for (int i = 0; i < node.ChildNodes.Count; i++) + { + SiteMapNode child = node.ChildNodes[i]; + Assert.AreEqual(child.Title, childData[i]); + } + } + } +} diff --git a/MySql.Web/tests/TestProfile.cs b/MySql.Web/tests/TestProfile.cs index 54b8bfafb..1b2a54a2e 100644 --- a/MySql.Web/tests/TestProfile.cs +++ b/MySql.Web/tests/TestProfile.cs @@ -1,67 +1,67 @@ -// Copyright (c) 2013, 2020, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using System.Web.Profile; -using System.Web.Security; - -namespace MySql.Web.Tests -{ - public class TestProfile : ProfileBase - { - public static TestProfile GetUserProfile(string username, bool auth) - { - return Create(username, auth) as TestProfile; - } - - public static TestProfile GetUserProfile(bool auth) - { - return Create(Membership.GetUser().UserName, auth) as TestProfile; - } - - [SettingsAllowAnonymous(false)] - public string Description - { - get { return base["Description"] as string; } - set { base["Description"] = value; } - } - - [SettingsAllowAnonymous(false)] - public string Location - { - get { return base["Location"] as string; } - set { base["Location"] = value; } - } - - [SettingsAllowAnonymous(false)] - public string FavoriteMovie - { - get { return base["FavoriteMovie"] as string; } - set { base["FavoriteMovie"] = value; } - } - } -} +// Copyright © 2013, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using System.Web.Profile; +using System.Web.Security; + +namespace MySql.Web.Tests +{ + public class TestProfile : ProfileBase + { + public static TestProfile GetUserProfile(string username, bool auth) + { + return Create(username, auth) as TestProfile; + } + + public static TestProfile GetUserProfile(bool auth) + { + return Create(Membership.GetUser().UserName, auth) as TestProfile; + } + + [SettingsAllowAnonymous(false)] + public string Description + { + get { return base["Description"] as string; } + set { base["Description"] = value; } + } + + [SettingsAllowAnonymous(false)] + public string Location + { + get { return base["Location"] as string; } + set { base["Location"] = value; } + } + + [SettingsAllowAnonymous(false)] + public string FavoriteMovie + { + get { return base["FavoriteMovie"] as string; } + set { base["FavoriteMovie"] = value; } + } + } +} diff --git a/MySql.Web/tests/UserManagement.cs b/MySql.Web/tests/UserManagement.cs index df82bfab5..5bbffb3f9 100644 --- a/MySql.Web/tests/UserManagement.cs +++ b/MySql.Web/tests/UserManagement.cs @@ -1,825 +1,825 @@ -// Copyright (c) 2013, 2020, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySql.Data.MySqlClient; -using MySql.Web.Security; -using NUnit.Framework; -using System; -using System.Collections.Specialized; -using System.Configuration.Provider; -using System.Data; -using System.Web.Security; - -namespace MySql.Web.Tests -{ - public class UserManagement : WebTestBase - { - private MySQLMembershipProvider provider { get; set; } - - private void CreateUserWithFormat(MembershipPasswordFormat format) - { - provider = new MySQLMembershipProvider(); - NameValueCollection config = new NameValueCollection(); - config.Add("connectionStringName", "LocalMySqlServer"); - config.Add("applicationName", "/"); - config.Add("passwordStrengthRegularExpression", "bar.*"); - config.Add("passwordFormat", format.ToString()); - provider.Initialize(null, config); - - // create the user - MembershipCreateStatus status; - provider.CreateUser("foo", "barbar!", "foo@bar.com", null, null, true, null, out status); - Assert.AreEqual(MembershipCreateStatus.Success, status); - - // verify that the password format is hashed. - DataTable table = FillTable("SELECT * FROM my_aspnet_membership"); - MembershipPasswordFormat rowFormat = - (MembershipPasswordFormat)Convert.ToInt32(table.Rows[0]["PasswordFormat"]); - Assert.AreEqual(format, rowFormat); - - // then attempt to verify the user - Assert.True(provider.ValidateUser("foo", "barbar!")); - - } - - [Test] - public void CreateUserWithHashedPassword() - { - CreateUserWithFormat(MembershipPasswordFormat.Hashed); - //Cleanup - provider.DeleteUser("foo", true); - } - - [Test] - public void CreateUserWithEncryptedPasswordWithAutoGenKeys() - { - //TODO check this test logic - try - { - CreateUserWithFormat(MembershipPasswordFormat.Encrypted); - } - catch (ProviderException) - { - } - //Cleanup - provider.DeleteUser("foo", true); - } - - [Test] - public void CreateUserWithClearPassword() - { - CreateUserWithFormat(MembershipPasswordFormat.Clear); - //Cleanup - provider.DeleteUser("foo", true); - } - - /// - /// Bug #34792 New User/Changing Password Validation Not working. - /// - [Test] - public void ChangePassword() - { - CreateUserWithFormat(MembershipPasswordFormat.Hashed); - ArgumentException ex = Assert.Throws(() => provider.ChangePassword("foo", "barbar!", "bar2")); - - Assert.AreEqual("newPassword", ex.ParamName); - Assert.True(ex.Message.Contains("length of parameter")); - ArgumentException ex1 = Assert.Throws(() => provider.ChangePassword("foo", "barbar!", "barbar2")); - Assert.AreEqual("newPassword", ex1.ParamName); - Assert.True(ex1.Message.Contains("alpha numeric")); - - // now test regex strength testing - bool result = provider.ChangePassword("foo", "barbar!", "zzzxxx!"); - Assert.False(result); - - // now do one that should work - result = provider.ChangePassword("foo", "barbar!", "barfoo!"); - Assert.True(result); - - provider.ValidateUser("foo", "barfoo!"); - - //Cleanup - provider.DeleteUser("foo", true); - } - - /// - /// Bug #34792 New User/Changing Password Validation Not working. - /// - [Test] - public void CreateUserWithErrors() - { - provider = new MySQLMembershipProvider(); - NameValueCollection config = new NameValueCollection(); - config.Add("connectionStringName", "LocalMySqlServer"); - config.Add("applicationName", "/"); - config.Add("passwordStrengthRegularExpression", "bar.*"); - config.Add("passwordFormat", "Hashed"); - provider.Initialize(null, config); - - // first try to create a user with a password not long enough - MembershipCreateStatus status; - MembershipUser user = provider.CreateUser("foo", "xyz", - "foo@bar.com", null, null, true, null, out status); - Assert.IsNull(user); - Assert.AreEqual(MembershipCreateStatus.InvalidPassword, status); - - // now with not enough non-alphas - user = provider.CreateUser("foo", "xyz1234", - "foo@bar.com", null, null, true, null, out status); - Assert.IsNull(user); - Assert.AreEqual(MembershipCreateStatus.InvalidPassword, status); - - // now one that doesn't pass the regex test - user = provider.CreateUser("foo", "xyzxyz!", - "foo@bar.com", null, null, true, null, out status); - Assert.IsNull(user); - Assert.AreEqual(MembershipCreateStatus.InvalidPassword, status); - - // now one that works - user = provider.CreateUser("foo", "barbar!", - "foo@bar.com", null, null, true, null, out status); - Assert.IsNotNull(user); - Assert.AreEqual(MembershipCreateStatus.Success, status); - - //Cleanup - provider.DeleteUser("foo", true); - - } - - [Test] - public void DeleteUser() - { - execSQL(@"delete from my_aspnet_membership; - delete from my_aspnet_users;"); - CreateUserWithFormat(MembershipPasswordFormat.Hashed); - Assert.True(provider.DeleteUser("foo", true)); - DataTable table = FillTable("SELECT * FROM my_aspnet_membership"); - Assert.AreEqual(0, table.Rows.Count); - table = FillTable("SELECT * FROM my_aspnet_users"); - Assert.AreEqual(0, table.Rows.Count); - - CreateUserWithFormat(MembershipPasswordFormat.Hashed); - provider = new MySQLMembershipProvider(); - NameValueCollection config = new NameValueCollection(); - config.Add("connectionStringName", "LocalMySqlServer"); - config.Add("applicationName", "/"); - provider.Initialize(null, config); - Assert.True(Membership.DeleteUser("foo", false)); - table = FillTable("SELECT * FROM my_aspnet_membership"); - Assert.AreEqual(0, table.Rows.Count); - table = FillTable("SELECT * FROM my_aspnet_users"); - Assert.AreEqual(1, table.Rows.Count); - } - - [Test] - public void FindUsersByName() - { - CreateUserWithFormat(MembershipPasswordFormat.Hashed); - int records; - MembershipUserCollection users = provider.FindUsersByName("F%", 0, 10, out records); - Assert.AreEqual(1, records); - Assert.AreEqual("foo", users["foo"].UserName); - - //Cleanup - provider.DeleteUser("foo", true); - } - - [Test] - public void FindUsersByEmail() - { - CreateUserWithFormat(MembershipPasswordFormat.Hashed); - - int records; - MembershipUserCollection users = provider.FindUsersByEmail("foo@bar.com", 0, 10, out records); - Assert.AreEqual(1, records); - Assert.AreEqual("foo", users["foo"].UserName); - - //Cleanup - provider.DeleteUser("foo", true); - } - - [Test] - public void TestCreateUserOverrides() - { - try - { - MembershipCreateStatus status; - Membership.CreateUser("foo", "barbar!", null, "question", "answer", true, out status); - int records; - MembershipUserCollection users = Membership.FindUsersByName("F%", 0, 10, out records); - Assert.AreEqual(1, records); - Assert.AreEqual("foo", users["foo"].UserName); - - Membership.CreateUser("test", "barbar!", "myemail@host.com", - "question", "answer", true, out status); - users = Membership.FindUsersByName("T%", 0, 10, out records); - Assert.AreEqual(1, records); - Assert.AreEqual("test", users["test"].UserName); - } - catch (Exception ex) - { - Assert.True(ex.Message != String.Empty, ex.Message); - } - - //Cleanup - Membership.DeleteUser("test", true); - Membership.DeleteUser("foo", true); - } - - [Test] - public void NumberOfUsersOnline() - { - int numOnline = Membership.GetNumberOfUsersOnline(); - Assert.AreEqual(0, numOnline); - - MembershipCreateStatus status; - Membership.CreateUser("foo", "barbar!", null, "question", "answer", true, out status); - Membership.CreateUser("foo2", "barbar!", null, "question", "answer", true, out status); - - numOnline = Membership.GetNumberOfUsersOnline(); - Assert.AreEqual(2, numOnline); - - //Cleanup - Membership.DeleteUser("foo"); - Membership.DeleteUser("foo2"); - } - - [Test] - public void UnlockUser() - { - MembershipCreateStatus status; - Membership.CreateUser("foo", "barbar!", null, "question", "answer", true, out status); - Assert.False(Membership.ValidateUser("foo", "bar2")); - Assert.False(Membership.ValidateUser("foo", "bar3")); - Assert.False(Membership.ValidateUser("foo", "bar3")); - Assert.False(Membership.ValidateUser("foo", "bar3")); - Assert.False(Membership.ValidateUser("foo", "bar3")); - - // the user should be locked now so the right password should fail - Assert.False(Membership.ValidateUser("foo", "barbar!")); - - MembershipUser user = Membership.GetUser("foo"); - Assert.True(user.IsLockedOut); - - Assert.True(user.UnlockUser()); - user = Membership.GetUser("foo"); - Assert.False(user.IsLockedOut); - - Assert.True(Membership.ValidateUser("foo", "barbar!")); - - //Cleanup - Membership.DeleteUser("foo"); - } - - [Test] - public void GetUsernameByEmail() - { - MembershipCreateStatus status; - Membership.CreateUser("foo", "barbar!", "foo@bar.com", "question", "answer", true, out status); - string username = Membership.GetUserNameByEmail("foo@bar.com"); - Assert.AreEqual("foo", username); - - username = Membership.GetUserNameByEmail("foo@b.com"); - Assert.IsNull(username); - - username = Membership.GetUserNameByEmail(" foo@bar.com "); - Assert.AreEqual("foo", username); - - //Cleanup - Membership.DeleteUser("foo"); - } - - [Test] - public void UpdateUser() - { - MembershipCreateStatus status; - Membership.CreateUser("foo", "barbar!", "foo@bar.com", "color", "blue", true, out status); - Assert.AreEqual(MembershipCreateStatus.Success, status); - - MembershipUser user = Membership.GetUser("foo"); - - user.Comment = "my comment"; - user.Email = "my email"; - user.IsApproved = false; - user.LastActivityDate = new DateTime(2008, 1, 1); - user.LastLoginDate = new DateTime(2008, 2, 1); - Membership.UpdateUser(user); - - MembershipUser newUser = Membership.GetUser("foo"); - Assert.AreEqual(user.Comment, newUser.Comment); - Assert.AreEqual(user.Email, newUser.Email); - Assert.AreEqual(user.IsApproved, newUser.IsApproved); - Assert.AreEqual(user.LastActivityDate, newUser.LastActivityDate); - Assert.AreEqual(user.LastLoginDate, newUser.LastLoginDate); - - //Cleanup - Membership.DeleteUser("foo"); - } - - private void ChangePasswordQAHelper(MembershipUser user, string pw, string newQ, string newA) - { - try - { - user.ChangePasswordQuestionAndAnswer(pw, newQ, newA); - } - catch (ArgumentNullException ane) - { - Assert.AreEqual("password", ane.ParamName); - } - catch (ArgumentException) - { - Assert.IsNotNull(pw); - } - } - - [Test] - public void ChangePasswordQuestionAndAnswer() - { - MembershipCreateStatus status; - Membership.CreateUser("foo", "barbar!", "foo@bar.com", "color", "blue", true, out status); - Assert.AreEqual(MembershipCreateStatus.Success, status); - - MembershipUser user = Membership.GetUser("foo"); - ChangePasswordQAHelper(user, "", "newQ", "newA"); - ChangePasswordQAHelper(user, "barbar!", "", "newA"); - ChangePasswordQAHelper(user, "barbar!", "newQ", ""); - ChangePasswordQAHelper(user, null, "newQ", "newA"); - - bool result = user.ChangePasswordQuestionAndAnswer("barbar!", "newQ", "newA"); - Assert.True(result); - - user = Membership.GetUser("foo"); - Assert.AreEqual("newQ", user.PasswordQuestion); - - //Cleanup - Membership.DeleteUser("foo"); - - } - - [Test] - public void GetAllUsers() - { - MembershipCreateStatus status; - // first create a bunch of users - for (int i = 0; i < 100; i++) - Membership.CreateUser(String.Format("foo{0}", i), "barbar!", null, - "question", "answer", true, out status); - - MembershipUserCollection users = Membership.GetAllUsers(); - Assert.AreEqual(100, users.Count); - int index = 0; - foreach (MembershipUser user in users) - Assert.AreEqual(String.Format("foo{0}", index++), user.UserName); - - int total; - users = Membership.GetAllUsers(2, 10, out total); - Assert.AreEqual(10, users.Count); - Assert.AreEqual(100, total); - index = 0; - foreach (MembershipUser user in users) - Assert.AreEqual(String.Format("foo2{0}", index++), user.UserName); - - //Cleanup - MySqlHelper.ExecuteScalar(Connection, "DELETE FROM my_aspnet_users"); - MySqlHelper.ExecuteScalar(Connection, "DELETE FROM my_aspnet_membership"); - } - - private void GetPasswordHelper(bool requireQA, bool enablePasswordRetrieval, string answer) - { - MembershipCreateStatus status; - provider = new MySQLMembershipProvider(); - NameValueCollection config = new NameValueCollection(); - config.Add("connectionStringName", "LocalMySqlServer"); - config.Add("requiresQuestionAndAnswer", requireQA ? "true" : "false"); - config.Add("enablePasswordRetrieval", enablePasswordRetrieval ? "true" : "false"); - config.Add("passwordFormat", "clear"); - config.Add("applicationName", "/"); - config.Add("writeExceptionsToEventLog", "false"); - provider.Initialize(null, config); - - provider.CreateUser("foo", "barbar!", "foo@bar.com", "color", "blue", true, null, out status); - - string password = string.Empty; - if (!enablePasswordRetrieval) - { - if (requireQA && answer != null) - { - Exception ex = Assert.Throws(() => provider.GetPassword("foo", answer)); - } - else - { - Exception ex = Assert.Throws(() => provider.GetPassword("foo", answer)); - Assert.AreEqual(ex.Message, "Password Retrieval Not Enabled."); - } - } - else - { - if (requireQA && answer != null) - { - provider.GetPassword("foo", answer); - } - else if (requireQA && answer == null) - { - //Incorrect password answer. - Assert.Throws(() => provider.GetPassword("foo", answer)); - } - else - { - password = provider.GetPassword("foo", answer); - Assert.AreEqual("barbar!", password); - } - } - - //Cleanup - provider.DeleteUser("foo", true); - } - - [Test] - public void GetPassword() - { - GetPasswordHelper(false, false, null); - GetPasswordHelper(false, true, null); - GetPasswordHelper(true, true, null); - GetPasswordHelper(true, true, "blue"); - } - - /// - /// Bug #38939 MembershipUser.GetPassword(string answer) fails when incorrect answer is passed. - /// - [Test] - public void GetPasswordWithWrongAnswer() - { - MembershipCreateStatus status; - provider = new MySQLMembershipProvider(); - NameValueCollection config = new NameValueCollection(); - config.Add("connectionStringName", "LocalMySqlServer"); - config.Add("requiresQuestionAndAnswer", "true"); - config.Add("enablePasswordRetrieval", "true"); - config.Add("passwordFormat", "Encrypted"); - config.Add("applicationName", "/"); - provider.Initialize(null, config); - provider.CreateUser("foo", "barbar!", "foo@bar.com", "color", "blue", true, null, out status); - - MySQLMembershipProvider provider2 = new MySQLMembershipProvider(); - NameValueCollection config2 = new NameValueCollection(); - config2.Add("connectionStringName", "LocalMySqlServer"); - config2.Add("requiresQuestionAndAnswer", "true"); - config2.Add("enablePasswordRetrieval", "true"); - config2.Add("passwordFormat", "Encrypted"); - config2.Add("applicationName", "/"); - provider2.Initialize(null, config2); - Assert.Throws(() => provider2.GetPassword("foo", "wrong")); - - //Cleanup - provider.DeleteUser("foo", true); - } - - [Test] - public void GetUser() - { - //Resetting PK - MySqlHelper.ExecuteScalar(Connection, "ALTER TABLE my_aspnet_users AUTO_INCREMENT = 1;"); - - MembershipCreateStatus status; - Membership.CreateUser("foo", "barbar!", null, "question", "answer", true, out status); - MembershipUser user = Membership.GetUser(1); - Assert.AreEqual("foo", user.UserName); - - // now move the activity date back outside the login - // window - user.LastActivityDate = new DateTime(2008, 1, 1); - Membership.UpdateUser(user); - - user = Membership.GetUser("foo"); - Assert.False(user.IsOnline); - - user = Membership.GetUser("foo", true); - Assert.True(user.IsOnline); - - // now move the activity date back outside the login - // window again - user.LastActivityDate = new DateTime(2008, 1, 1); - Membership.UpdateUser(user); - - user = Membership.GetUser(1); - Assert.False(user.IsOnline); - - user = Membership.GetUser(1, true); - Assert.True(user.IsOnline); - - //Cleanup - Membership.DeleteUser("foo"); - } - - [Ignore("Fix Me")] - public void FindUsers() - { - MembershipCreateStatus status; - for (int i = 0; i < 100; i++) - Membership.CreateUser(String.Format("boo{0}", i), "barbar!", null, - "question", "answer", true, out status); - for (int i = 0; i < 100; i++) - Membership.CreateUser(String.Format("foo{0}", i), "barbar!", null, - "question", "answer", true, out status); - for (int i = 0; i < 100; i++) - Membership.CreateUser(String.Format("schmoo{0}", i), "barbar!", null, - "question", "answer", true, out status); - - - MembershipUserCollection users = Membership.FindUsersByName("fo%"); - Assert.AreEqual(100, users.Count); - - int total; - users = Membership.FindUsersByName("fo%", 2, 10, out total); - Assert.AreEqual(10, users.Count); - Assert.AreEqual(100, total); - int index = 0; - foreach (MembershipUser user in users) - Assert.AreEqual(String.Format("foo2{0}", index++), user.UserName); - - //Cleanup - MySqlHelper.ExecuteScalar(Connection, "DELETE FROM my_aspnet_users"); - MySqlHelper.ExecuteScalar(Connection, "DELETE FROM my_aspnet_membership"); - - } - - [Test] - public void CreateUserWithNoQA() - { - MembershipCreateStatus status; - provider = new MySQLMembershipProvider(); - NameValueCollection config = new NameValueCollection(); - config.Add("connectionStringName", "LocalMySqlServer"); - config.Add("requiresQuestionAndAnswer", "true"); - config.Add("passwordFormat", "clear"); - config.Add("applicationName", "/"); - provider.Initialize(null, config); - - Exception ex = Assert.Throws(() => provider.CreateUser("foo", "barbar!", "foo@bar.com", "color", null, true, null, out status)); - Assert.True(ex.Message.StartsWith("Password answer supplied is invalid", StringComparison.OrdinalIgnoreCase)); - - ex = Assert.Throws(() => provider.CreateUser("foo", "barbar!", "foo@bar.com", "", "blue", true, null, out status)); - Assert.True(ex.Message.StartsWith("Password question supplied is invalid", StringComparison.OrdinalIgnoreCase)); - - } - - [Test] - public void MinRequiredAlpha() - { - provider = new MySQLMembershipProvider(); - NameValueCollection config = new NameValueCollection(); - config.Add("connectionStringName", "LocalMySqlServer"); - config.Add("applicationName", "/"); - config.Add("minRequiredNonalphanumericCharacters", "3"); - provider.Initialize(null, config); - - MembershipCreateStatus status; - MembershipUser user = provider.CreateUser("foo", "pw!pass", "email", null, null, true, null, out status); - Assert.IsNull(user); - - user = provider.CreateUser("foo", "pw!pa!!", "email", null, null, true, null, out status); - Assert.IsNotNull(user); - - //Cleanup - Membership.DeleteUser("foo"); - - } - - /// - /// Bug #35332 GetPassword() don't working (when PasswordAnswer is NULL) - /// - [Test] - public void GetPasswordWithNullValues() - { - MembershipCreateStatus status; - provider = new MySQLMembershipProvider(); - NameValueCollection config = new NameValueCollection(); - config.Add("connectionStringName", "LocalMySqlServer"); - config.Add("requiresQuestionAndAnswer", "false"); - config.Add("enablePasswordRetrieval", "true"); - config.Add("passwordFormat", "clear"); - config.Add("applicationName", "/"); - provider.Initialize(null, config); - - MembershipUser user = provider.CreateUser("foo", "barbar!", "foo@bar.com", null, null, true, null, out status); - Assert.IsNotNull(user); - - string pw = provider.GetPassword("foo", null); - Assert.AreEqual("barbar!", pw); - - //Cleanup - Membership.DeleteUser("foo"); - } - - /// - /// Bug #35336 GetPassword() return wrong password (when format is encrypted) - /// - [Test] - public void GetEncryptedPassword() - { - MembershipCreateStatus status; - provider = new MySQLMembershipProvider(); - NameValueCollection config = new NameValueCollection(); - config.Add("connectionStringName", "LocalMySqlServer"); - config.Add("requiresQuestionAndAnswer", "false"); - config.Add("enablePasswordRetrieval", "true"); - config.Add("passwordFormat", "encrypted"); - config.Add("applicationName", "/"); - provider.Initialize(null, config); - - MembershipUser user = provider.CreateUser("foo", "barbar!", "foo@bar.com", null, null, true, null, out status); - Assert.IsNotNull(user); - - string pw = provider.GetPassword("foo", null); - Assert.AreEqual("barbar!", pw); - - //Cleanup - provider.DeleteUser("foo", true); - } - - /// - /// Bug #42574 ValidateUser does not use the application id, allowing cross application login - /// - [Test] - public void CrossAppLogin() - { - provider = new MySQLMembershipProvider(); - NameValueCollection config = new NameValueCollection(); - config.Add("connectionStringName", "LocalMySqlServer"); - config.Add("applicationName", "/"); - config.Add("passwordStrengthRegularExpression", "bar.*"); - config.Add("passwordFormat", "Clear"); - provider.Initialize(null, config); - MembershipCreateStatus status; - provider.CreateUser("foo", "bar!bar", null, null, null, true, null, out status); - - MySQLMembershipProvider provider2 = new MySQLMembershipProvider(); - NameValueCollection config2 = new NameValueCollection(); - config2.Add("connectionStringName", "LocalMySqlServer"); - config2.Add("applicationName", "/myapp"); - config2.Add("passwordStrengthRegularExpression", ".*"); - config2.Add("passwordFormat", "Clear"); - provider2.Initialize(null, config2); - - bool worked = provider2.ValidateUser("foo", "bar!bar"); - Assert.AreEqual(false, worked); - - //Cleanup - provider.DeleteUser("foo", true); - } - - /// - /// Bug #41408 PasswordReset not possible when requiresQuestionAndAnswer="false" - /// - [Test] - public void ResetPassword() - { - provider = new MySQLMembershipProvider(); - NameValueCollection config = new NameValueCollection(); - config.Add("connectionStringName", "LocalMySqlServer"); - config.Add("applicationName", "/"); - config.Add("passwordStrengthRegularExpression", "bar.*"); - config.Add("passwordFormat", "Clear"); - config.Add("requiresQuestionAndAnswer", "false"); - provider.Initialize(null, config); - - MembershipCreateStatus status; - provider.CreateUser("foo", "bar!bar", null, null, null, true, null, out status); - - MembershipUser u = provider.GetUser("foo", false); - string newpw = provider.ResetPassword("foo", null); - - //Cleanup - provider.DeleteUser("foo", true); - } - - /// - /// Bug #59438 setting Membership.ApplicationName has no effect - /// - [Test] - public void ChangeAppName() - { - provider = new MySQLMembershipProvider(); - NameValueCollection config = new NameValueCollection(); - config.Add("connectionStringName", "LocalMySqlServer"); - config.Add("applicationName", "/"); - config.Add("passwordStrengthRegularExpression", "bar.*"); - config.Add("passwordFormat", "Clear"); - provider.Initialize(null, config); - MembershipCreateStatus status; - provider.CreateUser("foo", "bar!bar", null, null, null, true, null, out status); - Assert.True(status == MembershipCreateStatus.Success); - - MySQLMembershipProvider provider2 = new MySQLMembershipProvider(); - NameValueCollection config2 = new NameValueCollection(); - config2.Add("connectionStringName", "LocalMySqlServer"); - config2.Add("applicationName", "/myapp"); - config2.Add("passwordStrengthRegularExpression", "foo.*"); - config2.Add("passwordFormat", "Clear"); - provider2.Initialize(null, config2); - provider2.CreateUser("foo2", "foo!foo", null, null, null, true, null, out status); - Assert.True(status == MembershipCreateStatus.Success); - - provider.ApplicationName = "/myapp"; - Assert.False(provider.ValidateUser("foo", "bar!bar")); - Assert.True(provider.ValidateUser("foo2", "foo!foo")); - - //Cleanup - //provider.DeleteUser("foo2", true); - //provider.DeleteUser("foo", true); - - //Cleanup - MySqlHelper.ExecuteScalar(Connection, "DELETE FROM my_aspnet_users"); - MySqlHelper.ExecuteScalar(Connection, "DELETE FROM my_aspnet_membership"); - - } - - [Test] - public void GetUserLooksForExactUsername() - { - MembershipCreateStatus status; - Membership.CreateUser("code", "thecode!", null, "question", "answer", true, out status); - - MembershipUser user = Membership.GetUser("code"); - Assert.AreEqual("code", user.UserName); - - user = Membership.GetUser("co_e"); - Assert.IsNull(user); - - //Cleanup - Membership.DeleteUser("code"); - } - - [Test] - public void GetUserNameByEmailLooksForExactEmail() - { - MembershipCreateStatus status; - Membership.CreateUser("code", "thecode!", "code@mysql.com", "question", "answer", true, out status); - - string username = Membership.GetUserNameByEmail("code@mysql.com"); - Assert.AreEqual("code", username); - - username = Membership.GetUserNameByEmail("co_e@mysql.com"); - Assert.IsNull(username); - - //Cleanup - Membership.DeleteUser("code"); - } - - /// - /// MySqlBug 73411, Oracle Bug: 19453313 - /// - [Test] - public void CreateUserWithLeadingAndTrailingSpaces() - { - provider = new MySQLMembershipProvider(); - NameValueCollection config = new NameValueCollection(); - config.Add("connectionStringName", "LocalMySqlServer"); - config.Add("autogenerateschema", "true"); - config.Add("applicationName", "/"); - provider.Initialize(null, config); - - MembershipCreateStatus status; - MembershipUser muser1 = provider.CreateUser(" with trailing space ", "dummypassword1!", "w@w1.w", "yes", "yes", true, null, out status); - Assert.AreNotEqual(null, muser1); - MembershipUser muser2 = provider.GetUser("with trailing space", false); - Assert.AreNotEqual(null, muser1); - - Roles.CreateRole("SomeRole"); - Assert.True(Roles.GetAllRoles().Length > 0); - - bool isInRole = Roles.IsUserInRole(muser2.UserName, "SomeRole"); - Assert.False(isInRole); - - Roles.AddUserToRole(muser2.UserName, "SomeRole"); - - isInRole = Roles.IsUserInRole(muser2.UserName, "SomeRole"); - Assert.True(isInRole); - } - } -} +// Copyright © 2013, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySql.Data.MySqlClient; +using MySql.Web.Security; +using NUnit.Framework; +using System; +using System.Collections.Specialized; +using System.Configuration.Provider; +using System.Data; +using System.Web.Security; + +namespace MySql.Web.Tests +{ + public class UserManagement : WebTestBase + { + private MySQLMembershipProvider provider { get; set; } + + private void CreateUserWithFormat(MembershipPasswordFormat format) + { + provider = new MySQLMembershipProvider(); + NameValueCollection config = new NameValueCollection(); + config.Add("connectionStringName", "LocalMySqlServer"); + config.Add("applicationName", "/"); + config.Add("passwordStrengthRegularExpression", "bar.*"); + config.Add("passwordFormat", format.ToString()); + provider.Initialize(null, config); + + // create the user + MembershipCreateStatus status; + provider.CreateUser("foo", "barbar!", "foo@bar.com", null, null, true, null, out status); + Assert.AreEqual(MembershipCreateStatus.Success, status); + + // verify that the password format is hashed. + DataTable table = FillTable("SELECT * FROM my_aspnet_membership"); + MembershipPasswordFormat rowFormat = + (MembershipPasswordFormat)Convert.ToInt32(table.Rows[0]["PasswordFormat"]); + Assert.AreEqual(format, rowFormat); + + // then attempt to verify the user + Assert.True(provider.ValidateUser("foo", "barbar!")); + + } + + [Test] + public void CreateUserWithHashedPassword() + { + CreateUserWithFormat(MembershipPasswordFormat.Hashed); + //Cleanup + provider.DeleteUser("foo", true); + } + + [Test] + public void CreateUserWithEncryptedPasswordWithAutoGenKeys() + { + //TODO check this test logic + try + { + CreateUserWithFormat(MembershipPasswordFormat.Encrypted); + } + catch (ProviderException) + { + } + //Cleanup + provider.DeleteUser("foo", true); + } + + [Test] + public void CreateUserWithClearPassword() + { + CreateUserWithFormat(MembershipPasswordFormat.Clear); + //Cleanup + provider.DeleteUser("foo", true); + } + + /// + /// Bug #34792 New User/Changing Password Validation Not working. + /// + [Test] + public void ChangePassword() + { + CreateUserWithFormat(MembershipPasswordFormat.Hashed); + ArgumentException ex = Assert.Throws(() => provider.ChangePassword("foo", "barbar!", "bar2")); + + Assert.AreEqual("newPassword", ex.ParamName); + Assert.True(ex.Message.Contains("length of parameter")); + ArgumentException ex1 = Assert.Throws(() => provider.ChangePassword("foo", "barbar!", "barbar2")); + Assert.AreEqual("newPassword", ex1.ParamName); + Assert.True(ex1.Message.Contains("alpha numeric")); + + // now test regex strength testing + bool result = provider.ChangePassword("foo", "barbar!", "zzzxxx!"); + Assert.False(result); + + // now do one that should work + result = provider.ChangePassword("foo", "barbar!", "barfoo!"); + Assert.True(result); + + provider.ValidateUser("foo", "barfoo!"); + + //Cleanup + provider.DeleteUser("foo", true); + } + + /// + /// Bug #34792 New User/Changing Password Validation Not working. + /// + [Test] + public void CreateUserWithErrors() + { + provider = new MySQLMembershipProvider(); + NameValueCollection config = new NameValueCollection(); + config.Add("connectionStringName", "LocalMySqlServer"); + config.Add("applicationName", "/"); + config.Add("passwordStrengthRegularExpression", "bar.*"); + config.Add("passwordFormat", "Hashed"); + provider.Initialize(null, config); + + // first try to create a user with a password not long enough + MembershipCreateStatus status; + MembershipUser user = provider.CreateUser("foo", "xyz", + "foo@bar.com", null, null, true, null, out status); + Assert.IsNull(user); + Assert.AreEqual(MembershipCreateStatus.InvalidPassword, status); + + // now with not enough non-alphas + user = provider.CreateUser("foo", "xyz1234", + "foo@bar.com", null, null, true, null, out status); + Assert.IsNull(user); + Assert.AreEqual(MembershipCreateStatus.InvalidPassword, status); + + // now one that doesn't pass the regex test + user = provider.CreateUser("foo", "xyzxyz!", + "foo@bar.com", null, null, true, null, out status); + Assert.IsNull(user); + Assert.AreEqual(MembershipCreateStatus.InvalidPassword, status); + + // now one that works + user = provider.CreateUser("foo", "barbar!", + "foo@bar.com", null, null, true, null, out status); + Assert.IsNotNull(user); + Assert.AreEqual(MembershipCreateStatus.Success, status); + + //Cleanup + provider.DeleteUser("foo", true); + + } + + [Test] + public void DeleteUser() + { + execSQL(@"delete from my_aspnet_membership; + delete from my_aspnet_users;"); + CreateUserWithFormat(MembershipPasswordFormat.Hashed); + Assert.True(provider.DeleteUser("foo", true)); + DataTable table = FillTable("SELECT * FROM my_aspnet_membership"); + Assert.AreEqual(0, table.Rows.Count); + table = FillTable("SELECT * FROM my_aspnet_users"); + Assert.AreEqual(0, table.Rows.Count); + + CreateUserWithFormat(MembershipPasswordFormat.Hashed); + provider = new MySQLMembershipProvider(); + NameValueCollection config = new NameValueCollection(); + config.Add("connectionStringName", "LocalMySqlServer"); + config.Add("applicationName", "/"); + provider.Initialize(null, config); + Assert.True(Membership.DeleteUser("foo", false)); + table = FillTable("SELECT * FROM my_aspnet_membership"); + Assert.AreEqual(0, table.Rows.Count); + table = FillTable("SELECT * FROM my_aspnet_users"); + Assert.AreEqual(1, table.Rows.Count); + } + + [Test] + public void FindUsersByName() + { + CreateUserWithFormat(MembershipPasswordFormat.Hashed); + int records; + MembershipUserCollection users = provider.FindUsersByName("F%", 0, 10, out records); + Assert.AreEqual(1, records); + Assert.AreEqual("foo", users["foo"].UserName); + + //Cleanup + provider.DeleteUser("foo", true); + } + + [Test] + public void FindUsersByEmail() + { + CreateUserWithFormat(MembershipPasswordFormat.Hashed); + + int records; + MembershipUserCollection users = provider.FindUsersByEmail("foo@bar.com", 0, 10, out records); + Assert.AreEqual(1, records); + Assert.AreEqual("foo", users["foo"].UserName); + + //Cleanup + provider.DeleteUser("foo", true); + } + + [Test] + public void TestCreateUserOverrides() + { + try + { + MembershipCreateStatus status; + Membership.CreateUser("foo", "barbar!", null, "question", "answer", true, out status); + int records; + MembershipUserCollection users = Membership.FindUsersByName("F%", 0, 10, out records); + Assert.AreEqual(1, records); + Assert.AreEqual("foo", users["foo"].UserName); + + Membership.CreateUser("test", "barbar!", "myemail@host.com", + "question", "answer", true, out status); + users = Membership.FindUsersByName("T%", 0, 10, out records); + Assert.AreEqual(1, records); + Assert.AreEqual("test", users["test"].UserName); + } + catch (Exception ex) + { + Assert.True(ex.Message != String.Empty, ex.Message); + } + + //Cleanup + Membership.DeleteUser("test", true); + Membership.DeleteUser("foo", true); + } + + [Test] + public void NumberOfUsersOnline() + { + int numOnline = Membership.GetNumberOfUsersOnline(); + Assert.AreEqual(0, numOnline); + + MembershipCreateStatus status; + Membership.CreateUser("foo", "barbar!", null, "question", "answer", true, out status); + Membership.CreateUser("foo2", "barbar!", null, "question", "answer", true, out status); + + numOnline = Membership.GetNumberOfUsersOnline(); + Assert.AreEqual(2, numOnline); + + //Cleanup + Membership.DeleteUser("foo"); + Membership.DeleteUser("foo2"); + } + + [Test] + public void UnlockUser() + { + MembershipCreateStatus status; + Membership.CreateUser("foo", "barbar!", null, "question", "answer", true, out status); + Assert.False(Membership.ValidateUser("foo", "bar2")); + Assert.False(Membership.ValidateUser("foo", "bar3")); + Assert.False(Membership.ValidateUser("foo", "bar3")); + Assert.False(Membership.ValidateUser("foo", "bar3")); + Assert.False(Membership.ValidateUser("foo", "bar3")); + + // the user should be locked now so the right password should fail + Assert.False(Membership.ValidateUser("foo", "barbar!")); + + MembershipUser user = Membership.GetUser("foo"); + Assert.True(user.IsLockedOut); + + Assert.True(user.UnlockUser()); + user = Membership.GetUser("foo"); + Assert.False(user.IsLockedOut); + + Assert.True(Membership.ValidateUser("foo", "barbar!")); + + //Cleanup + Membership.DeleteUser("foo"); + } + + [Test] + public void GetUsernameByEmail() + { + MembershipCreateStatus status; + Membership.CreateUser("foo", "barbar!", "foo@bar.com", "question", "answer", true, out status); + string username = Membership.GetUserNameByEmail("foo@bar.com"); + Assert.AreEqual("foo", username); + + username = Membership.GetUserNameByEmail("foo@b.com"); + Assert.IsNull(username); + + username = Membership.GetUserNameByEmail(" foo@bar.com "); + Assert.AreEqual("foo", username); + + //Cleanup + Membership.DeleteUser("foo"); + } + + [Test] + public void UpdateUser() + { + MembershipCreateStatus status; + Membership.CreateUser("foo", "barbar!", "foo@bar.com", "color", "blue", true, out status); + Assert.AreEqual(MembershipCreateStatus.Success, status); + + MembershipUser user = Membership.GetUser("foo"); + + user.Comment = "my comment"; + user.Email = "my email"; + user.IsApproved = false; + user.LastActivityDate = new DateTime(2008, 1, 1); + user.LastLoginDate = new DateTime(2008, 2, 1); + Membership.UpdateUser(user); + + MembershipUser newUser = Membership.GetUser("foo"); + Assert.AreEqual(user.Comment, newUser.Comment); + Assert.AreEqual(user.Email, newUser.Email); + Assert.AreEqual(user.IsApproved, newUser.IsApproved); + Assert.AreEqual(user.LastActivityDate, newUser.LastActivityDate); + Assert.AreEqual(user.LastLoginDate, newUser.LastLoginDate); + + //Cleanup + Membership.DeleteUser("foo"); + } + + private void ChangePasswordQAHelper(MembershipUser user, string pw, string newQ, string newA) + { + try + { + user.ChangePasswordQuestionAndAnswer(pw, newQ, newA); + } + catch (ArgumentNullException ane) + { + Assert.AreEqual("password", ane.ParamName); + } + catch (ArgumentException) + { + Assert.IsNotNull(pw); + } + } + + [Test] + public void ChangePasswordQuestionAndAnswer() + { + MembershipCreateStatus status; + Membership.CreateUser("foo", "barbar!", "foo@bar.com", "color", "blue", true, out status); + Assert.AreEqual(MembershipCreateStatus.Success, status); + + MembershipUser user = Membership.GetUser("foo"); + ChangePasswordQAHelper(user, "", "newQ", "newA"); + ChangePasswordQAHelper(user, "barbar!", "", "newA"); + ChangePasswordQAHelper(user, "barbar!", "newQ", ""); + ChangePasswordQAHelper(user, null, "newQ", "newA"); + + bool result = user.ChangePasswordQuestionAndAnswer("barbar!", "newQ", "newA"); + Assert.True(result); + + user = Membership.GetUser("foo"); + Assert.AreEqual("newQ", user.PasswordQuestion); + + //Cleanup + Membership.DeleteUser("foo"); + + } + + [Test] + public void GetAllUsers() + { + MembershipCreateStatus status; + // first create a bunch of users + for (int i = 0; i < 100; i++) + Membership.CreateUser(String.Format("foo{0}", i), "barbar!", null, + "question", "answer", true, out status); + + MembershipUserCollection users = Membership.GetAllUsers(); + Assert.AreEqual(100, users.Count); + int index = 0; + foreach (MembershipUser user in users) + Assert.AreEqual(String.Format("foo{0}", index++), user.UserName); + + int total; + users = Membership.GetAllUsers(2, 10, out total); + Assert.AreEqual(10, users.Count); + Assert.AreEqual(100, total); + index = 0; + foreach (MembershipUser user in users) + Assert.AreEqual(String.Format("foo2{0}", index++), user.UserName); + + //Cleanup + MySqlHelper.ExecuteScalar(Connection, "DELETE FROM my_aspnet_users"); + MySqlHelper.ExecuteScalar(Connection, "DELETE FROM my_aspnet_membership"); + } + + private void GetPasswordHelper(bool requireQA, bool enablePasswordRetrieval, string answer) + { + MembershipCreateStatus status; + provider = new MySQLMembershipProvider(); + NameValueCollection config = new NameValueCollection(); + config.Add("connectionStringName", "LocalMySqlServer"); + config.Add("requiresQuestionAndAnswer", requireQA ? "true" : "false"); + config.Add("enablePasswordRetrieval", enablePasswordRetrieval ? "true" : "false"); + config.Add("passwordFormat", "clear"); + config.Add("applicationName", "/"); + config.Add("writeExceptionsToEventLog", "false"); + provider.Initialize(null, config); + + provider.CreateUser("foo", "barbar!", "foo@bar.com", "color", "blue", true, null, out status); + + string password = string.Empty; + if (!enablePasswordRetrieval) + { + if (requireQA && answer != null) + { + Exception ex = Assert.Throws(() => provider.GetPassword("foo", answer)); + } + else + { + Exception ex = Assert.Throws(() => provider.GetPassword("foo", answer)); + Assert.AreEqual(ex.Message, "Password Retrieval Not Enabled."); + } + } + else + { + if (requireQA && answer != null) + { + provider.GetPassword("foo", answer); + } + else if (requireQA && answer == null) + { + //Incorrect password answer. + Assert.Throws(() => provider.GetPassword("foo", answer)); + } + else + { + password = provider.GetPassword("foo", answer); + Assert.AreEqual("barbar!", password); + } + } + + //Cleanup + provider.DeleteUser("foo", true); + } + + [Test] + public void GetPassword() + { + GetPasswordHelper(false, false, null); + GetPasswordHelper(false, true, null); + GetPasswordHelper(true, true, null); + GetPasswordHelper(true, true, "blue"); + } + + /// + /// Bug #38939 MembershipUser.GetPassword(string answer) fails when incorrect answer is passed. + /// + [Test] + public void GetPasswordWithWrongAnswer() + { + MembershipCreateStatus status; + provider = new MySQLMembershipProvider(); + NameValueCollection config = new NameValueCollection(); + config.Add("connectionStringName", "LocalMySqlServer"); + config.Add("requiresQuestionAndAnswer", "true"); + config.Add("enablePasswordRetrieval", "true"); + config.Add("passwordFormat", "Encrypted"); + config.Add("applicationName", "/"); + provider.Initialize(null, config); + provider.CreateUser("foo", "barbar!", "foo@bar.com", "color", "blue", true, null, out status); + + MySQLMembershipProvider provider2 = new MySQLMembershipProvider(); + NameValueCollection config2 = new NameValueCollection(); + config2.Add("connectionStringName", "LocalMySqlServer"); + config2.Add("requiresQuestionAndAnswer", "true"); + config2.Add("enablePasswordRetrieval", "true"); + config2.Add("passwordFormat", "Encrypted"); + config2.Add("applicationName", "/"); + provider2.Initialize(null, config2); + Assert.Throws(() => provider2.GetPassword("foo", "wrong")); + + //Cleanup + provider.DeleteUser("foo", true); + } + + [Test] + public void GetUser() + { + //Resetting PK + MySqlHelper.ExecuteScalar(Connection, "ALTER TABLE my_aspnet_users AUTO_INCREMENT = 1;"); + + MembershipCreateStatus status; + Membership.CreateUser("foo", "barbar!", null, "question", "answer", true, out status); + MembershipUser user = Membership.GetUser(1); + Assert.AreEqual("foo", user.UserName); + + // now move the activity date back outside the login + // window + user.LastActivityDate = new DateTime(2008, 1, 1); + Membership.UpdateUser(user); + + user = Membership.GetUser("foo"); + Assert.False(user.IsOnline); + + user = Membership.GetUser("foo", true); + Assert.True(user.IsOnline); + + // now move the activity date back outside the login + // window again + user.LastActivityDate = new DateTime(2008, 1, 1); + Membership.UpdateUser(user); + + user = Membership.GetUser(1); + Assert.False(user.IsOnline); + + user = Membership.GetUser(1, true); + Assert.True(user.IsOnline); + + //Cleanup + Membership.DeleteUser("foo"); + } + + [Ignore("Fix Me")] + public void FindUsers() + { + MembershipCreateStatus status; + for (int i = 0; i < 100; i++) + Membership.CreateUser(String.Format("boo{0}", i), "barbar!", null, + "question", "answer", true, out status); + for (int i = 0; i < 100; i++) + Membership.CreateUser(String.Format("foo{0}", i), "barbar!", null, + "question", "answer", true, out status); + for (int i = 0; i < 100; i++) + Membership.CreateUser(String.Format("schmoo{0}", i), "barbar!", null, + "question", "answer", true, out status); + + + MembershipUserCollection users = Membership.FindUsersByName("fo%"); + Assert.AreEqual(100, users.Count); + + int total; + users = Membership.FindUsersByName("fo%", 2, 10, out total); + Assert.AreEqual(10, users.Count); + Assert.AreEqual(100, total); + int index = 0; + foreach (MembershipUser user in users) + Assert.AreEqual(String.Format("foo2{0}", index++), user.UserName); + + //Cleanup + MySqlHelper.ExecuteScalar(Connection, "DELETE FROM my_aspnet_users"); + MySqlHelper.ExecuteScalar(Connection, "DELETE FROM my_aspnet_membership"); + + } + + [Test] + public void CreateUserWithNoQA() + { + MembershipCreateStatus status; + provider = new MySQLMembershipProvider(); + NameValueCollection config = new NameValueCollection(); + config.Add("connectionStringName", "LocalMySqlServer"); + config.Add("requiresQuestionAndAnswer", "true"); + config.Add("passwordFormat", "clear"); + config.Add("applicationName", "/"); + provider.Initialize(null, config); + + Exception ex = Assert.Throws(() => provider.CreateUser("foo", "barbar!", "foo@bar.com", "color", null, true, null, out status)); + Assert.True(ex.Message.StartsWith("Password answer supplied is invalid", StringComparison.OrdinalIgnoreCase)); + + ex = Assert.Throws(() => provider.CreateUser("foo", "barbar!", "foo@bar.com", "", "blue", true, null, out status)); + Assert.True(ex.Message.StartsWith("Password question supplied is invalid", StringComparison.OrdinalIgnoreCase)); + + } + + [Test] + public void MinRequiredAlpha() + { + provider = new MySQLMembershipProvider(); + NameValueCollection config = new NameValueCollection(); + config.Add("connectionStringName", "LocalMySqlServer"); + config.Add("applicationName", "/"); + config.Add("minRequiredNonalphanumericCharacters", "3"); + provider.Initialize(null, config); + + MembershipCreateStatus status; + MembershipUser user = provider.CreateUser("foo", "pw!pass", "email", null, null, true, null, out status); + Assert.IsNull(user); + + user = provider.CreateUser("foo", "pw!pa!!", "email", null, null, true, null, out status); + Assert.IsNotNull(user); + + //Cleanup + Membership.DeleteUser("foo"); + + } + + /// + /// Bug #35332 GetPassword() don't working (when PasswordAnswer is NULL) + /// + [Test] + public void GetPasswordWithNullValues() + { + MembershipCreateStatus status; + provider = new MySQLMembershipProvider(); + NameValueCollection config = new NameValueCollection(); + config.Add("connectionStringName", "LocalMySqlServer"); + config.Add("requiresQuestionAndAnswer", "false"); + config.Add("enablePasswordRetrieval", "true"); + config.Add("passwordFormat", "clear"); + config.Add("applicationName", "/"); + provider.Initialize(null, config); + + MembershipUser user = provider.CreateUser("foo", "barbar!", "foo@bar.com", null, null, true, null, out status); + Assert.IsNotNull(user); + + string pw = provider.GetPassword("foo", null); + Assert.AreEqual("barbar!", pw); + + //Cleanup + Membership.DeleteUser("foo"); + } + + /// + /// Bug #35336 GetPassword() return wrong password (when format is encrypted) + /// + [Test] + public void GetEncryptedPassword() + { + MembershipCreateStatus status; + provider = new MySQLMembershipProvider(); + NameValueCollection config = new NameValueCollection(); + config.Add("connectionStringName", "LocalMySqlServer"); + config.Add("requiresQuestionAndAnswer", "false"); + config.Add("enablePasswordRetrieval", "true"); + config.Add("passwordFormat", "encrypted"); + config.Add("applicationName", "/"); + provider.Initialize(null, config); + + MembershipUser user = provider.CreateUser("foo", "barbar!", "foo@bar.com", null, null, true, null, out status); + Assert.IsNotNull(user); + + string pw = provider.GetPassword("foo", null); + Assert.AreEqual("barbar!", pw); + + //Cleanup + provider.DeleteUser("foo", true); + } + + /// + /// Bug #42574 ValidateUser does not use the application id, allowing cross application login + /// + [Test] + public void CrossAppLogin() + { + provider = new MySQLMembershipProvider(); + NameValueCollection config = new NameValueCollection(); + config.Add("connectionStringName", "LocalMySqlServer"); + config.Add("applicationName", "/"); + config.Add("passwordStrengthRegularExpression", "bar.*"); + config.Add("passwordFormat", "Clear"); + provider.Initialize(null, config); + MembershipCreateStatus status; + provider.CreateUser("foo", "bar!bar", null, null, null, true, null, out status); + + MySQLMembershipProvider provider2 = new MySQLMembershipProvider(); + NameValueCollection config2 = new NameValueCollection(); + config2.Add("connectionStringName", "LocalMySqlServer"); + config2.Add("applicationName", "/myapp"); + config2.Add("passwordStrengthRegularExpression", ".*"); + config2.Add("passwordFormat", "Clear"); + provider2.Initialize(null, config2); + + bool worked = provider2.ValidateUser("foo", "bar!bar"); + Assert.AreEqual(false, worked); + + //Cleanup + provider.DeleteUser("foo", true); + } + + /// + /// Bug #41408 PasswordReset not possible when requiresQuestionAndAnswer="false" + /// + [Test] + public void ResetPassword() + { + provider = new MySQLMembershipProvider(); + NameValueCollection config = new NameValueCollection(); + config.Add("connectionStringName", "LocalMySqlServer"); + config.Add("applicationName", "/"); + config.Add("passwordStrengthRegularExpression", "bar.*"); + config.Add("passwordFormat", "Clear"); + config.Add("requiresQuestionAndAnswer", "false"); + provider.Initialize(null, config); + + MembershipCreateStatus status; + provider.CreateUser("foo", "bar!bar", null, null, null, true, null, out status); + + MembershipUser u = provider.GetUser("foo", false); + string newpw = provider.ResetPassword("foo", null); + + //Cleanup + provider.DeleteUser("foo", true); + } + + /// + /// Bug #59438 setting Membership.ApplicationName has no effect + /// + [Test] + public void ChangeAppName() + { + provider = new MySQLMembershipProvider(); + NameValueCollection config = new NameValueCollection(); + config.Add("connectionStringName", "LocalMySqlServer"); + config.Add("applicationName", "/"); + config.Add("passwordStrengthRegularExpression", "bar.*"); + config.Add("passwordFormat", "Clear"); + provider.Initialize(null, config); + MembershipCreateStatus status; + provider.CreateUser("foo", "bar!bar", null, null, null, true, null, out status); + Assert.True(status == MembershipCreateStatus.Success); + + MySQLMembershipProvider provider2 = new MySQLMembershipProvider(); + NameValueCollection config2 = new NameValueCollection(); + config2.Add("connectionStringName", "LocalMySqlServer"); + config2.Add("applicationName", "/myapp"); + config2.Add("passwordStrengthRegularExpression", "foo.*"); + config2.Add("passwordFormat", "Clear"); + provider2.Initialize(null, config2); + provider2.CreateUser("foo2", "foo!foo", null, null, null, true, null, out status); + Assert.True(status == MembershipCreateStatus.Success); + + provider.ApplicationName = "/myapp"; + Assert.False(provider.ValidateUser("foo", "bar!bar")); + Assert.True(provider.ValidateUser("foo2", "foo!foo")); + + //Cleanup + //provider.DeleteUser("foo2", true); + //provider.DeleteUser("foo", true); + + //Cleanup + MySqlHelper.ExecuteScalar(Connection, "DELETE FROM my_aspnet_users"); + MySqlHelper.ExecuteScalar(Connection, "DELETE FROM my_aspnet_membership"); + + } + + [Test] + public void GetUserLooksForExactUsername() + { + MembershipCreateStatus status; + Membership.CreateUser("code", "thecode!", null, "question", "answer", true, out status); + + MembershipUser user = Membership.GetUser("code"); + Assert.AreEqual("code", user.UserName); + + user = Membership.GetUser("co_e"); + Assert.IsNull(user); + + //Cleanup + Membership.DeleteUser("code"); + } + + [Test] + public void GetUserNameByEmailLooksForExactEmail() + { + MembershipCreateStatus status; + Membership.CreateUser("code", "thecode!", "code@mysql.com", "question", "answer", true, out status); + + string username = Membership.GetUserNameByEmail("code@mysql.com"); + Assert.AreEqual("code", username); + + username = Membership.GetUserNameByEmail("co_e@mysql.com"); + Assert.IsNull(username); + + //Cleanup + Membership.DeleteUser("code"); + } + + /// + /// MySqlBug 73411, Oracle Bug: 19453313 + /// + [Test] + public void CreateUserWithLeadingAndTrailingSpaces() + { + provider = new MySQLMembershipProvider(); + NameValueCollection config = new NameValueCollection(); + config.Add("connectionStringName", "LocalMySqlServer"); + config.Add("autogenerateschema", "true"); + config.Add("applicationName", "/"); + provider.Initialize(null, config); + + MembershipCreateStatus status; + MembershipUser muser1 = provider.CreateUser(" with trailing space ", "dummypassword1!", "w@w1.w", "yes", "yes", true, null, out status); + Assert.AreNotEqual(null, muser1); + MembershipUser muser2 = provider.GetUser("with trailing space", false); + Assert.AreNotEqual(null, muser1); + + Roles.CreateRole("SomeRole"); + Assert.True(Roles.GetAllRoles().Length > 0); + + bool isInRole = Roles.IsUserInRole(muser2.UserName, "SomeRole"); + Assert.False(isInRole); + + Roles.AddUserToRole(muser2.UserName, "SomeRole"); + + isInRole = Roles.IsUserInRole(muser2.UserName, "SomeRole"); + Assert.True(isInRole); + } + } +} diff --git a/MySql.Web/tests/WebTestBase.cs b/MySql.Web/tests/WebTestBase.cs index c3ba03d5f..8e3153569 100644 --- a/MySql.Web/tests/WebTestBase.cs +++ b/MySql.Web/tests/WebTestBase.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2013, 2020, Oracle and/or its affiliates. +// Copyright © 2013, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the From 4edbaff3fdeb85df2c3d99917272f40aecc2c695 Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Sun, 28 Jan 2024 17:54:55 -0700 Subject: [PATCH 021/125] Bug#36208932 [Shared memory connection doesn't work in multithread environment] Change-Id: I243f0b10a5e837d12bfb3df6262a5da098a40143 --- CHANGES | 4 +- .../netstandard2_0/SharedMemoryStream.cs | 62 ++++++++++++------- .../tests/MySql.Data.Tests/ConnectionTests.cs | 48 ++++++++++++++ 3 files changed, 91 insertions(+), 23 deletions(-) diff --git a/CHANGES b/CHANGES index b54054960..a156a9ac8 100644 --- a/CHANGES +++ b/CHANGES @@ -1,5 +1,7 @@ 8.4.0 -- Updated FOSS license text in all source files (WL16197) +- Updated FOSS license text in all source files (WL16197). +- Fixed bug Shared memory connection doesn't work in multithread environment (Oracle Bug #36208932). + 8.3.0 - Added support for build traversal (WL15798). diff --git a/MySQL.Data/src/common/netstandard2_0/SharedMemoryStream.cs b/MySQL.Data/src/common/netstandard2_0/SharedMemoryStream.cs index f9b092d53..4c4ad2e78 100644 --- a/MySQL.Data/src/common/netstandard2_0/SharedMemoryStream.cs +++ b/MySQL.Data/src/common/netstandard2_0/SharedMemoryStream.cs @@ -160,34 +160,52 @@ public override void Close() private void GetConnectNumber(uint timeOut) { - EventWaitHandle connectRequest; + Mutex connectNamedMutex = null; try { - connectRequest = - EventWaitHandle.OpenExisting(memoryName + "_CONNECT_REQUEST"); - + connectNamedMutex = Mutex.OpenExisting(memoryName + "_CONNECT_NAMED_MUTEX"); } - catch (Exception) + catch { - // If server runs as service, its shared memory is global - // And if connector runs in user session, it needs to prefix - // shared memory name with "Global\" - string prefixedMemoryName = @"Global\" + memoryName; - connectRequest = - EventWaitHandle.OpenExisting(prefixedMemoryName + "_CONNECT_REQUEST"); - memoryName = prefixedMemoryName; + throw new MySqlException("Failed to open shared memory connection mutex"); + } + if (!connectNamedMutex.WaitOne(checked((int)timeOut) * 1000, false)) + throw new MySqlException("Mutex timeout during connection"); + try + { + EventWaitHandle connectRequest; + try + { + connectRequest = + EventWaitHandle.OpenExisting(memoryName + "_CONNECT_REQUEST"); + } + catch (Exception) + { + // If server runs as service, its shared memory is global + // And if connector runs in user session, it needs to prefix + // shared memory name with "Global\" + string prefixedMemoryName = @"Global\" + memoryName; + connectRequest = + EventWaitHandle.OpenExisting(prefixedMemoryName + "_CONNECT_REQUEST"); + memoryName = prefixedMemoryName; + } + EventWaitHandle connectAnswer = + EventWaitHandle.OpenExisting(memoryName + "_CONNECT_ANSWER"); + using (SharedMemory connectData = + new SharedMemory(memoryName + "_CONNECT_DATA", (IntPtr)4)) + { + // now start the connection + if (!connectRequest.Set()) + throw new MySqlException("Failed to open shared memory connection"); + if (!connectAnswer.WaitOne((int)(timeOut * 1000), false)) + throw new MySqlException("Timeout during connection"); + connectNumber = Marshal.ReadInt32(connectData.View); + } } - EventWaitHandle connectAnswer = - EventWaitHandle.OpenExisting(memoryName + "_CONNECT_ANSWER"); - using (SharedMemory connectData = - new SharedMemory(memoryName + "_CONNECT_DATA", (IntPtr)4)) + finally { - // now start the connection - if (!connectRequest.Set()) - throw new MySqlException("Failed to open shared memory connection"); - if (!connectAnswer.WaitOne((int)(timeOut * 1000), false)) - throw new MySqlException("Timeout during connection"); - connectNumber = Marshal.ReadInt32(connectData.View); + connectNamedMutex.ReleaseMutex(); + connectNamedMutex.Dispose(); } } diff --git a/MySQL.Data/tests/MySql.Data.Tests/ConnectionTests.cs b/MySQL.Data/tests/MySql.Data.Tests/ConnectionTests.cs index f4a4fdf8c..e2d6a364d 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/ConnectionTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/ConnectionTests.cs @@ -880,6 +880,54 @@ public void ConnectUsingSharedMemory() } } + /// + /// Bug#36208932 - Shared memory connection doesn't work in multithread environment + /// To be able to connect using Shared Memory, it requires to start the server supporting the protocol + /// mysqld --standalone --console --shared-memory=on + /// + [Test] + [Ignore("To be able to connect using Shared Memory, it requires to start the server supporting the protocol")] + public void SharedMemoryMultithreadConnection() + { + if (!Platform.IsWindows()) Assert.Ignore("Shared Memory is only supported on Windows."); + + var sb = new MySqlConnectionStringBuilder() + { + Server = Host, + UserID = RootUser, + ConnectionProtocol = MySqlConnectionProtocol.SharedMemory, + }; + + List threads = new List(); + for (int i = 0; i < 2; i++) + { + threads.Add(new Thread(() => + { + MySqlConnection connection = new MySqlConnection(sb.ConnectionString); + + Assert.DoesNotThrow(() => connection.Open()); + + for (int i = 0; i < 200; i++) + { + MySqlCommand cmd = connection.CreateCommand(); + cmd.CommandText = "Select CURRENT_USER();"; + cmd.CommandType = CommandType.Text; + Assert.DoesNotThrow(() => cmd.ExecuteNonQuery()); + } + })); + } + + foreach (Thread thread in threads) + { + thread.Start(); + } + + foreach (Thread thread in threads) + { + thread.Join(); + } + } + #if NET452 /// /// Fix for aborted connections MySQL bug 80997 OraBug 23346197 From fdaedf5939ac68c6dc4fbe4fdcb8bc472d863341 Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Sun, 28 Jan 2024 18:29:44 -0700 Subject: [PATCH 022/125] Bug#36208929 [Named pipe connection doesn't work in multithread environment] Change-Id: Ic646b56b1795ba08bf3f51b4b521e17daded294d --- CHANGES | 1 + MySQL.Data/src/common/NativeMethods.cs | 2 +- .../common/netstandard2_0/NamedPipeStream.cs | 4 +- .../tests/MySql.Data.Tests/ConnectionTests.cs | 51 +++++++++++++++++++ 4 files changed, 55 insertions(+), 3 deletions(-) diff --git a/CHANGES b/CHANGES index a156a9ac8..020b833d8 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,7 @@ 8.4.0 - Updated FOSS license text in all source files (WL16197). - Fixed bug Shared memory connection doesn't work in multithread environment (Oracle Bug #36208932). +- Fixed bug Named pipe connection doesn't work in multithread environment (Oracle Bug #36208929). 8.3.0 diff --git a/MySQL.Data/src/common/NativeMethods.cs b/MySQL.Data/src/common/NativeMethods.cs index 79a601a65..b6fa9fae8 100644 --- a/MySQL.Data/src/common/NativeMethods.cs +++ b/MySQL.Data/src/common/NativeMethods.cs @@ -68,7 +68,7 @@ public SecurityAttributes() public bool inheritHandle; } - [DllImport("Kernel32", CharSet = CharSet.Unicode)] + [DllImport("Kernel32", CharSet = CharSet.Unicode, SetLastError = true)] static extern public IntPtr CreateFile( String fileName, uint desiredAccess, diff --git a/MySQL.Data/src/common/netstandard2_0/NamedPipeStream.cs b/MySQL.Data/src/common/netstandard2_0/NamedPipeStream.cs index 47cf4d06c..57302c11a 100644 --- a/MySQL.Data/src/common/netstandard2_0/NamedPipeStream.cs +++ b/MySQL.Data/src/common/netstandard2_0/NamedPipeStream.cs @@ -76,7 +76,8 @@ public void Open(string path, FileAccess mode, uint timeout) NativeMethods.FILE_WRITE_ATTRIBUTES | NativeMethods.FILE_WRITE_DATA, 0, security, NativeMethods.OPEN_EXISTING, NativeMethods.FILE_FLAG_OVERLAPPED, 0); - if (nativeHandle != IntPtr.Zero) + handle = new SafeFileHandle(nativeHandle, true); + if (!handle.IsInvalid) break; if (Marshal.GetLastWin32Error() != ERROR_PIPE_BUSY) @@ -102,7 +103,6 @@ public void Open(string path, FileAccess mode, uint timeout) } timeout -= (uint)sw.ElapsedMilliseconds; } - handle = new SafeFileHandle(nativeHandle, true); fileStream = new FileStream(handle, mode, 4096, true); } diff --git a/MySQL.Data/tests/MySql.Data.Tests/ConnectionTests.cs b/MySQL.Data/tests/MySql.Data.Tests/ConnectionTests.cs index e2d6a364d..10d85106f 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/ConnectionTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/ConnectionTests.cs @@ -31,6 +31,7 @@ using System; using System.Collections.Generic; using System.Data; +using System.Diagnostics; using System.Text; using System.Threading; using System.Threading.Tasks; @@ -832,6 +833,8 @@ public void ExpiredPwdWithOldPassword() [Ignore("To be able to connect using Named Pipes, it requires to start the server supporting the protocol")] public void ConnectUsingNamedPipes() { + if (!Platform.IsWindows()) Assert.Ignore("Shared Memory is only supported on Windows."); + var sb = new MySqlConnectionStringBuilder() { Server = Host, @@ -847,6 +850,54 @@ public void ConnectUsingNamedPipes() StringAssert.AreEqualIgnoringCase(string.Format(Resources.SslNotAllowedForConnectionProtocol, sb.ConnectionProtocol), ex.Message); } + /// + /// Bug#36208929 - Named pipe connection doesn't work in multithread environment + /// To be able to connect using Named Pipes, it requires to start the server supporting the protocol + /// mysqld --standalone --console --named-pipe=on + /// + [Test] + [Ignore("To be able to connect using Named Pipes, it requires to start the server supporting the protocol")] + public void NamedPipesMultithreadConnection() + { + if (!Platform.IsWindows()) Assert.Ignore("Named Pipes is only supported on Windows."); + + var sb = new MySqlConnectionStringBuilder() + { + Server = Host, + UserID = RootUser, + ConnectionProtocol = MySqlConnectionProtocol.NamedPipe, + }; + + List threads = new List(); + for (int i = 0; i < 2; i++) + { + threads.Add(new Thread(() => + { + MySqlConnection connection = new MySqlConnection(sb.ConnectionString); + + Assert.DoesNotThrow(() => connection.Open()); + + for (int i = 0; i < 200; i++) + { + MySqlCommand cmd = connection.CreateCommand(); + cmd.CommandText = "Select CURRENT_USER();"; + cmd.CommandType = CommandType.Text; + Assert.DoesNotThrow(() => cmd.ExecuteNonQuery()); + } + })); + } + + foreach (Thread thread in threads) + { + thread.Start(); + } + + foreach (Thread thread in threads) + { + thread.Join(); + } + } + /// /// Bug#32853205 - UNABLE TO CONNECT USING NAMED PIPES AND SHARED MEMORY /// From 399669bec2015f5141e0f77ed57bd222f3931c21 Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Fri, 16 Feb 2024 12:53:33 -0700 Subject: [PATCH 023/125] Reverting changes in Resources file Change-Id: If7df2774161acd8d25059e471b31a23b28715145 --- MySQL.Data/src/Resources.Designer.cs | 2 +- MySQL.Data/src/Resources.resx | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/MySQL.Data/src/Resources.Designer.cs b/MySQL.Data/src/Resources.Designer.cs index 8b7f60be2..8df5d75fd 100644 --- a/MySQL.Data/src/Resources.Designer.cs +++ b/MySQL.Data/src/Resources.Designer.cs @@ -889,7 +889,7 @@ internal static string OciSDKNotFound { } /// - /// Looks up a localized string similar to Security token file could not be found at location given by OCI configuration entry 'security_token_file'.. + /// Looks up a localized string similar to Secutiry token file could not be found at location given by OCI configuration entry 'security_token_file'.. /// internal static string OciSecurityTokenDoesNotExists { get { diff --git a/MySQL.Data/src/Resources.resx b/MySQL.Data/src/Resources.resx index 728f43d23..b9618f3be 100644 --- a/MySQL.Data/src/Resources.resx +++ b/MySQL.Data/src/Resources.resx @@ -669,6 +669,15 @@ Private key could not be found at location given by OCI configuration entry 'key_file'. + + The size of the OCI security token file exceeds the maximum value of 10KB allowed. + + + OCI configuration profile not found. + + + Secutiry token file could not be found at location given by OCI configuration entry 'security_token_file'. + TLS protocols TLSv1 and TLSv1.1 are no longer supported. Accepted values are TLSv1.2 and TLSv1.3 From 62239e80d14c4280f43c7d7fcca6c1a46f783de3 Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Sat, 10 Feb 2024 20:14:28 -0700 Subject: [PATCH 024/125] Bug#36208913 [Byte array type mapping has a fixed limit of 8000 in EFCore] Removed data limitation in EFCore. Change-Id: Ie9482330d5f005c7f2409ce49ea7bdfe33c6d233 --- CHANGES | 1 + .../Internal/MySQLByteArrayTypeMapping.cs | 2 +- .../DbContextClasses/EntitiesClasses.cs | 9 ++++ .../DbContextClasses/TestsContexts.cs | 30 +++++++++++++ .../MySQLTypeMapperTests.cs | 44 +++++++++++++++++++ 5 files changed, 85 insertions(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index 020b833d8..365271cc4 100644 --- a/CHANGES +++ b/CHANGES @@ -2,6 +2,7 @@ - Updated FOSS license text in all source files (WL16197). - Fixed bug Shared memory connection doesn't work in multithread environment (Oracle Bug #36208932). - Fixed bug Named pipe connection doesn't work in multithread environment (Oracle Bug #36208929). +_ Fixed bug Byte array type mapping has a fixed limit of 8000 in EFCore (Oracle Bug #36208913). 8.3.0 diff --git a/EFCore/src/Storage/Internal/MySQLByteArrayTypeMapping.cs b/EFCore/src/Storage/Internal/MySQLByteArrayTypeMapping.cs index 9cdc33da4..d9ecd53dd 100644 --- a/EFCore/src/Storage/Internal/MySQLByteArrayTypeMapping.cs +++ b/EFCore/src/Storage/Internal/MySQLByteArrayTypeMapping.cs @@ -36,7 +36,7 @@ namespace MySql.EntityFrameworkCore.Storage.Internal { internal class MySQLByteArrayTypeMapping : ByteArrayTypeMapping { - private const int MaxSize = 8000; + private const int MaxSize = System.Int32.MaxValue; private readonly int _maxSpecificSize; diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/DbContextClasses/EntitiesClasses.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/DbContextClasses/EntitiesClasses.cs index 78151cb87..2d3214dba 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/DbContextClasses/EntitiesClasses.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/DbContextClasses/EntitiesClasses.cs @@ -225,6 +225,15 @@ public class JsonData public string? jsoncol { get; set; } } + public partial class AllBlobTypes + { + public byte Id { get; set; } + public byte[]? Example1 { get; set; } + public byte[]? Example2 { get; set; } + public byte[]? Example3 { get; set; } + + } + public partial class AllDataTypes { public byte AddressNumber1 { get; set; } diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/DbContextClasses/TestsContexts.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/DbContextClasses/TestsContexts.cs index 8f5036906..2cc62d404 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/DbContextClasses/TestsContexts.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/DbContextClasses/TestsContexts.cs @@ -362,6 +362,36 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) } } + public partial class AllBlobTypesContext : MyTestContext + { + public virtual DbSet AllBlobTypes { get; set; } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + modelBuilder.Entity(entity => + { + entity.HasKey(e => e.Id) + .HasName("PRIMARY"); + + entity.ToTable("all_blob_types"); + + entity.Property(e => e.Example1) + .HasColumnName("blob_column") + .HasColumnType("blob"); + + entity.Property(e => e.Example2) + .HasColumnName("mediumblob_column") + .HasColumnType("mediumblob") + .HasMaxLength(65535); + + entity.Property(e => e.Example3) + .HasColumnName("longblob_column") + .HasColumnType("longblob") + .HasMaxLength(16777215); + }); + } + } + public class WorldContext : MyTestContext { public virtual DbSet Countries { get; set; } diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/MySQLTypeMapperTests.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/MySQLTypeMapperTests.cs index 194600c28..adf585fd0 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/MySQLTypeMapperTests.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/MySQLTypeMapperTests.cs @@ -47,6 +47,8 @@ public void OneTimeTearDown() context.Database.EnsureDeleted(); using (var context = new StringTypesContext()) context.Database.EnsureDeleted(); + using (var context = new AllBlobTypesContext()) + context.Database.EnsureDeleted(); } [Test] @@ -130,6 +132,48 @@ public void InsertAllDataTypes() } } + /// + /// Bug#36208913 Byte array type mapping has a fixed limit of 8000 in EFCore + /// + [Test] + public void LongBlobMapping() + { + using (var context = new AllBlobTypesContext()) + { + context.Database.EnsureDeleted(); + context.Database.EnsureCreated(); + + + var data1 = new byte[7000]; + var data2 = new byte[60000]; + var data3 = new byte[90000]; + + + context.AllBlobTypes.Add(new AllBlobTypes() + { + Id = 1, + Example1 = data1, + Example2 = data2, + Example3 = data3, + }); + context.SaveChanges(); + } + + using (var context = new AllBlobTypesContext()) + { + + var data1 = new byte[7000]; + var data2 = new byte[60000]; + var data3 = new byte[90000]; + + var data = context.AllBlobTypes.First(); + + Assert.AreEqual(data1.Length, data.Example1.Length); + Assert.AreEqual(data2.Length, data.Example2.Length); + Assert.AreEqual(data3.Length, data.Example3.Length); + } + } + [Test] public void ValidateStringLength() { From 944adfc24da7570eba21118e20e92d42277c031c Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Fri, 16 Feb 2024 13:49:59 -0700 Subject: [PATCH 025/125] WL#16150 [Remove support for FIDO authentication] Change-Id: I2f5e130a1510762e6602ec6f9f4114edeeb5f840 --- CHANGES | 3 +- .../Authentication/AuthenticationManager.cs | 1 - .../FidoAuthenticationPlugin.cs | 145 ------------------ MySQL.Data/src/MySqlConnection.cs | 14 -- .../src/MySqlConnectionStringBuilder.cs | 5 - MySQL.Data/src/Resources.Designer.cs | 9 -- MySQL.Data/src/Resources.resx | 3 - .../tests/MySql.Data.Tests/AuthTests.cs | 145 +----------------- 8 files changed, 3 insertions(+), 322 deletions(-) delete mode 100644 MySQL.Data/src/Authentication/FidoAuthenticationPlugin.cs diff --git a/CHANGES b/CHANGES index 365271cc4..89f643609 100644 --- a/CHANGES +++ b/CHANGES @@ -2,7 +2,8 @@ - Updated FOSS license text in all source files (WL16197). - Fixed bug Shared memory connection doesn't work in multithread environment (Oracle Bug #36208932). - Fixed bug Named pipe connection doesn't work in multithread environment (Oracle Bug #36208929). -_ Fixed bug Byte array type mapping has a fixed limit of 8000 in EFCore (Oracle Bug #36208913). +- Fixed bug Byte array type mapping has a fixed limit of 8000 in EFCore (Oracle Bug #36208913). +- Removed support for FIDO authentication (WL16150). 8.3.0 diff --git a/MySQL.Data/src/Authentication/AuthenticationManager.cs b/MySQL.Data/src/Authentication/AuthenticationManager.cs index 3dfe08708..78e78000d 100644 --- a/MySQL.Data/src/Authentication/AuthenticationManager.cs +++ b/MySQL.Data/src/Authentication/AuthenticationManager.cs @@ -48,7 +48,6 @@ static AuthenticationPluginManager() Plugins["mysql_clear_password"] = new PluginInfo("MySql.Data.MySqlClient.Authentication.MySqlClearPasswordPlugin"); Plugins["authentication_kerberos_client"] = new PluginInfo("MySql.Data.MySqlClient.Authentication.KerberosAuthenticationPlugin"); Plugins["authentication_oci_client"] = new PluginInfo("MySql.Data.MySqlClient.Authentication.OciAuthenticationPlugin"); - Plugins["authentication_fido_client"] = new PluginInfo("MySql.Data.MySqlClient.Authentication.FidoAuthenticationPlugin"); Plugins["authentication_webauthn_client"] = new PluginInfo("MySql.Data.MySqlClient.Authentication.WebAuthnAuthenticationPlugin"); AuthenticationManagerCtorConfiguration(); diff --git a/MySQL.Data/src/Authentication/FidoAuthenticationPlugin.cs b/MySQL.Data/src/Authentication/FidoAuthenticationPlugin.cs deleted file mode 100644 index 9976a137a..000000000 --- a/MySQL.Data/src/Authentication/FidoAuthenticationPlugin.cs +++ /dev/null @@ -1,145 +0,0 @@ -// Copyright © 2022, 2024, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is designed to work with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, as -// designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an additional -// permission to link the program and your derivative works with the -// separately licensed software that they have either included with -// the program or referenced in the documentation. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using MySql.Data.Authentication.FIDO; -using System; -using System.IO; -using System.Text; -using System.Threading.Tasks; - -namespace MySql.Data.MySqlClient.Authentication -{ - [Obsolete("FIDO authentication client-side plugin is now deprecated.")] - internal class FidoAuthenticationPlugin : MySqlAuthenticationPlugin - { - public override string PluginName => "authentication_fido_client"; - - // Constants - private const int CLIENT_DATA_LENGTH = 32; - private const int RELYING_PARTY_ID_MAX_LENGTH = 255; - - // Fields - private byte[] _clientDataHash; - private byte[] _credentialId; - private string _relyingPartyId; - - protected override void SetAuthData(byte[] data) - { - if (data.Length > 0) - ParseChallenge(data); - else - throw new MySqlException(Resources.FidoRegistrationMissing); - } - - protected override async Task MoreDataAsync(byte[] data, bool execAsync) - { - Tuple response = BuildFidoAssertionStatement(); - return await SignChallengeAsync(response, execAsync).ConfigureAwait(false); - } - - /// - /// Method that parse the challenge received from server during authentication process. - /// This method extracts salt, relying party name and set it in the object. - /// - /// Buffer holding the server challenge. - /// Thrown if an error occurs while parsing the challenge. - private void ParseChallenge(byte[] challenge) - { - // client_data_hash length should be 32 bytes - int clientDataLength = challenge[0]; - if (clientDataLength != CLIENT_DATA_LENGTH) throw new MySqlException(Resources.FidoChallengeCorrupt); - // client_data_hash - _clientDataHash = new byte[clientDataLength]; - Array.Copy(challenge, 1, _clientDataHash, 0, clientDataLength); - - // relyting_party_id length cannot be more than 255 - int relyingPartyIdLength = challenge[clientDataLength + 1]; - if (relyingPartyIdLength > RELYING_PARTY_ID_MAX_LENGTH) throw new MySqlException(Resources.FidoChallengeCorrupt); - // relying_party_id - _relyingPartyId = Encoding.GetString(challenge, clientDataLength + 2, relyingPartyIdLength); - - // credential_id length - int credentialIdLength = challenge[clientDataLength + relyingPartyIdLength + 2]; - // credential_id - _credentialId = new byte[credentialIdLength]; - Array.Copy(challenge, clientDataLength + relyingPartyIdLength + 3, _credentialId, 0, credentialIdLength); - } - - /// - /// Signs the challenge obtained from the FIDO device and returns it to the server. - /// - private async Task SignChallengeAsync(Tuple response, bool execAsync) - { - var challenge = new MySqlPacket(new MemoryStream(response.Item1)); - await challenge.WriteLengthAsync(response.Item2, execAsync).ConfigureAwait(false); - await challenge.WriteAsync(response.Item3, execAsync).ConfigureAwait(false); - await challenge.WriteLengthAsync(response.Item4, execAsync).ConfigureAwait(false); - await challenge.WriteAsync(response.Item5, execAsync).ConfigureAwait(false); - - return challenge.Buffer; - } - - /// - /// Method to obtain an assertion from a FIDO device. - /// - private Tuple BuildFidoAssertionStatement() - { - string devicePath; - - using (var fidoDeviceInfo = new FidoDeviceInfo()) - devicePath = fidoDeviceInfo.Path; - - using (var fidoAssertion = new FidoAssertion()) - { - using (var fidoDevice = new FidoDevice()) - { - fidoAssertion.ClientDataHash = _clientDataHash; - fidoAssertion.Rp = _relyingPartyId; - fidoAssertion.AllowCredential(_credentialId); - - fidoDevice.Open(devicePath); - - if (_driver.Settings.FidoActionRequested != null) - _driver.Settings.FidoActionRequested?.Invoke(); - else - throw new MySqlException(Resources.FidoMissingHandler); - - fidoDevice.GetAssert(fidoAssertion); - - var fidoAssertionStatement = fidoAssertion.GetFidoAssertionStatement(); - int responseLength = fidoAssertionStatement.SignatureLen + fidoAssertionStatement.AuthDataLen + - Utils.GetLengthSize((ulong)fidoAssertionStatement.SignatureLen) + Utils.GetLengthSize((ulong)fidoAssertionStatement.AuthDataLen); - - return new Tuple(responseLength, - fidoAssertionStatement.AuthDataLen, fidoAssertionStatement.AuthData.ToArray(), - fidoAssertionStatement.SignatureLen, fidoAssertionStatement.Signature.ToArray()); - } - } - } - } -} diff --git a/MySQL.Data/src/MySqlConnection.cs b/MySQL.Data/src/MySqlConnection.cs index 23376a4c9..7aa18e908 100644 --- a/MySQL.Data/src/MySqlConnection.cs +++ b/MySQL.Data/src/MySqlConnection.cs @@ -86,12 +86,6 @@ public sealed class MySqlConnection : DbConnection, ICloneable #nullable disable #endif - /// - /// Occurs when FIDO authentication requests to perform gesture action on a device. - /// - [Obsolete("FIDO authentication client-side plugin is now deprecated. Use WebAuthn authentication client-side plugin instead.")] - public event FidoActionCallback FidoActionRequested; - /// /// Occurs when WebAuthn authentication makes a request to perform the gesture action on a device. /// @@ -618,7 +612,6 @@ internal async Task OpenAsync(bool execAsync, CancellationToken cancellationToke SetState(ConnectionState.Connecting, true); AssertPermissions(); - Settings.FidoActionRequested = FidoActionRequested; Settings.WebAuthnActionRequested = WebAuthnActionRequested; //TODO: SUPPORT FOR 452 AND 46X @@ -1271,13 +1264,6 @@ private static async Task ClearAllPoolsAsync(bool execAsync) #endregion } - /// - /// Represents the method to handle the event of a - /// - /// - [Obsolete("FIDO authentication client-side plugin is now deprecated. Use WebAuthn authentication client-side plugin instead.")] - public delegate void FidoActionCallback(); - /// /// Represents the method to handle the event of a /// . diff --git a/MySQL.Data/src/MySqlConnectionStringBuilder.cs b/MySQL.Data/src/MySqlConnectionStringBuilder.cs index e12a4ab22..200615948 100644 --- a/MySQL.Data/src/MySqlConnectionStringBuilder.cs +++ b/MySQL.Data/src/MySqlConnectionStringBuilder.cs @@ -852,11 +852,6 @@ public string CommandInterceptors set { SetValue("commandinterceptors", value); } } - /// - /// Gets or sets the event for the Fido callback. - /// - internal FidoActionCallback FidoActionRequested { get; set; } - /// /// Gets or sets the event for the WebauthN callback. /// diff --git a/MySQL.Data/src/Resources.Designer.cs b/MySQL.Data/src/Resources.Designer.cs index 8df5d75fd..e7d8bf967 100644 --- a/MySQL.Data/src/Resources.Designer.cs +++ b/MySQL.Data/src/Resources.Designer.cs @@ -429,15 +429,6 @@ internal static string FidoChallengeCorrupt { } } - /// - /// Looks up a localized string similar to An event handler for FidoActionRequested was not specified.. - /// - internal static string FidoMissingHandler { - get { - return ResourceManager.GetString("FidoMissingHandler", resourceCulture); - } - } - /// /// Looks up a localized string similar to FIDO registration is missing.. /// diff --git a/MySQL.Data/src/Resources.resx b/MySQL.Data/src/Resources.resx index b9618f3be..95effbdd4 100644 --- a/MySQL.Data/src/Resources.resx +++ b/MySQL.Data/src/Resources.resx @@ -684,9 +684,6 @@ Challenge received is corrupt. - - An event handler for FidoActionRequested was not specified. - FIDO registration is missing. diff --git a/MySQL.Data/tests/MySql.Data.Tests/AuthTests.cs b/MySQL.Data/tests/MySql.Data.Tests/AuthTests.cs index 8be4eeca9..115ed476c 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/AuthTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/AuthTests.cs @@ -26,15 +26,13 @@ // along with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -using Microsoft.Win32; -using MySql.Data.Authentication.FIDO.Utility; + using MySql.Data.Common; using MySql.Data.MySqlClient.Authentication; using NUnit.Framework; using System; using System.Collections.Generic; using System.Data; -using System.Numerics; using System.Reflection; using System.Text; @@ -1680,147 +1678,6 @@ public void ConnectUsing3FAuth(string user, string pwd, string pwd2, string pwd3 } #endregion - #region FIDO Authentication - /// - /// WL14871 - Support FIDO authentication [classic] - /// - [Test] - [Ignore("This should be executed manually since it depends on libfido2 library")] - [Property("Category", "Security")] - public void FidoAuthentication1F() - { - // Install FIDO plugin - ExecuteSQL("INSTALL PLUGIN authentication_fido SONAME 'authentication_fido.so';", true); - // Create user - // The INITIAL AUTHENTICATION IDENTIFIED clause must be specified to set a random or a static password. - ExecuteSQL("CREATE USER 'user_f1'@'localhost' IDENTIFIED WITH authentication_fido INITIAL AUTHENTICATION IDENTIFIED BY 'bar';", true); - - // Register the authenticator - // $ mysql --user=user_f1 --fido-register-factor=1 - - var connStringBuilder = new MySqlConnectionStringBuilder() - { - UserID = "user_f1", - Server = Settings.Server, - Port = Settings.Port - }; - - using var conn = new MySqlConnection(connStringBuilder.ConnectionString); - conn.FidoActionRequested += Conn_FidoActionRequested; - conn.Open(); - Assert.AreEqual(ConnectionState.Open, conn.State); - } - - [Test] - [Ignore("This should be executed manually since it depends on libfido2 library")] - [Property("Category", "Security")] - public void FidoAuthentication2F() - { - // Install FIDO plugin - ExecuteSQL("INSTALL PLUGIN authentication_fido SONAME 'authentication_fido.so';", true); - // Create user - ExecuteSQL("CREATE USER 'user_f2'@'localhost' IDENTIFIED BY 'bar' AND IDENTIFIED WITH authentication_fido;", true); - - // Register the authenticator - // $ mysql --user=user_f2 --fido-register-factor=2 - - var connStringBuilder = new MySqlConnectionStringBuilder() - { - UserID = "user_f2", - Password = "bar", - Server = Settings.Server, - Port = Settings.Port - }; - - using var conn = new MySqlConnection(connStringBuilder.ConnectionString); - conn.FidoActionRequested += Conn_FidoActionRequested; - conn.Open(); - Assert.AreEqual(ConnectionState.Open, conn.State); - } - - [Test] - [Ignore("This should be executed manually since it depends on libfido2 library")] - [Property("Category", "Security")] - public void FidoAuthentication3F() - { - // Install FIDO plugin - ExecuteSQL("INSTALL PLUGIN authentication_fido SONAME 'authentication_fido.so';", true); - // Create user - ExecuteSQL("CREATE USER 'user_f3'@'localhost' IDENTIFIED BY 'bar' AND IDENTIFIED BY 'baz' AND IDENTIFIED WITH authentication_fido;", true); - - // Register the authenticator - // $ mysql --user=user_f3 --fido-register-factor=3 - - var connStringBuilder = new MySqlConnectionStringBuilder() - { - UserID = "user_f3", - Password = "bar", - Password2 = "baz", - Server = Settings.Server, - Port = Settings.Port - }; - - using var conn = new MySqlConnection(connStringBuilder.ConnectionString); - conn.FidoActionRequested += Conn_FidoActionRequested; - conn.Open(); - Assert.AreEqual(ConnectionState.Open, conn.State); - } - - [Test] - [Ignore("This should be executed manually since it depends on libfido2 library")] - [Property("Category", "Security")] - public void FidoAuthenticationNoUserGestureException() - { - // Install FIDO plugin - ExecuteSQL("INSTALL PLUGIN authentication_fido SONAME 'authentication_fido.so';", true); - // Create user - ExecuteSQL("CREATE USER 'user_f2'@'localhost' IDENTIFIED BY 'bar' AND IDENTIFIED WITH authentication_fido;", true); - - // Register the authenticator - // $ mysql --user=user_f2 --fido-register-factor=2 - - var connStringBuilder = new MySqlConnectionStringBuilder() - { - UserID = "user_f2", - Password = "bar", - Server = Settings.Server, - Port = Settings.Port - }; - - using var conn = new MySqlConnection(connStringBuilder.ConnectionString); - conn.FidoActionRequested += Conn_FidoActionRequested; - Assert.Throws(() => conn.Open()); - } - - [Test] - [Ignore("This should be executed manually since it depends on libfido2 library")] - [Property("Category", "Security")] - public void FidoAuthenticationUnregisteredUserException() - { - // Install FIDO plugin - ExecuteSQL("INSTALL PLUGIN authentication_fido SONAME 'authentication_fido.so';", true); - // Create user - ExecuteSQL("CREATE USER 'user_f2'@'localhost' IDENTIFIED BY 'bar' AND IDENTIFIED WITH authentication_fido;", true); - - var connStringBuilder = new MySqlConnectionStringBuilder() - { - UserID = "user_f2", - Password = "bar", - Server = Settings.Server, - Port = Settings.Port - }; - - using var conn = new MySqlConnection(connStringBuilder.ConnectionString); - conn.FidoActionRequested += Conn_FidoActionRequested; - Assert.Throws(() => conn.Open()); - } - - private static void Conn_FidoActionRequested() - { - Console.WriteLine("Please insert FIDO device and perform gesture action for authentication to complete."); - } - #endregion - #region WebAuthn Authentication /// /// WL15193 - Support WebauthN in fido authentication plugin [Classic] From 877c0cb144d9ad1dae316de2747312bd5a7842ce Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Sun, 11 Feb 2024 16:21:05 -0700 Subject: [PATCH 026/125] WL#16176 [Add suport for TLS 1.3] Change-Id: I2af396507c205f7ef626f0d88d6dd48366bfc4c5 --- CHANGES | 1 + MySQL.Data/src/Resources.Designer.cs | 9 -------- MySQL.Data/src/Resources.resx | 3 --- MySQL.Data/src/common/Ssl.cs | 17 +++++++------- MySQL.Data/tests/MySql.Data.Tests/SslTests.cs | 23 ++++++++----------- 5 files changed, 18 insertions(+), 35 deletions(-) diff --git a/CHANGES b/CHANGES index 89f643609..2fea5f559 100644 --- a/CHANGES +++ b/CHANGES @@ -4,6 +4,7 @@ - Fixed bug Named pipe connection doesn't work in multithread environment (Oracle Bug #36208929). - Fixed bug Byte array type mapping has a fixed limit of 8000 in EFCore (Oracle Bug #36208913). - Removed support for FIDO authentication (WL16150). +- Add support for TLS 1.3 (WL16176). 8.3.0 diff --git a/MySQL.Data/src/Resources.Designer.cs b/MySQL.Data/src/Resources.Designer.cs index e7d8bf967..c937bc965 100644 --- a/MySQL.Data/src/Resources.Designer.cs +++ b/MySQL.Data/src/Resources.Designer.cs @@ -1374,15 +1374,6 @@ internal static string TlsUnsupportedVersions { } } - /// - /// Looks up a localized string similar to TLSv1.3 is not supported by this framework.. - /// - internal static string Tlsv13NotSupported { - get { - return ResourceManager.GetString("Tlsv13NotSupported", resourceCulture); - } - } - /// /// Looks up a localized string similar to Specified list of TLS versions is empty. Accepted values are TLSv1.2 and TLSv1.3. /// diff --git a/MySQL.Data/src/Resources.resx b/MySQL.Data/src/Resources.resx index 95effbdd4..732ef98b1 100644 --- a/MySQL.Data/src/Resources.resx +++ b/MySQL.Data/src/Resources.resx @@ -618,9 +618,6 @@ Specified list of TLS versions only contains non valid TLS protocols. Accepted values are TLSv1.2 and TLSv1.3 - - TLSv1.3 is not supported by this framework. - Specified list of TLS versions is empty. Accepted values are TLSv1.2 and TLSv1.3 diff --git a/MySQL.Data/src/common/Ssl.cs b/MySQL.Data/src/common/Ssl.cs index f201878d9..7e16343e5 100644 --- a/MySQL.Data/src/common/Ssl.cs +++ b/MySQL.Data/src/common/Ssl.cs @@ -66,7 +66,7 @@ internal class Ssl /// /// Defines the supported TLS protocols. /// - private static SslProtocols[] tlsProtocols = new SslProtocols[] { SslProtocols.Tls12 }; + private static SslProtocols[] tlsProtocols = new SslProtocols[] { SslProtocols.Tls12}; private static Dictionary tlsConnectionRef = new Dictionary(); private static Dictionary tlsRetry = new Dictionary(); private static Object thisLock = new Object(); @@ -108,9 +108,9 @@ private X509Certificate2 GetCertificateFromPEM(string certificatePath, string ce { var certParser = new Org.BouncyCastle.X509.X509CertificateParser(); var cert = certParser.ReadCertificate(File.ReadAllBytes(certificatePath)); - return new X509Certificate2(cert.GetEncoded(),certificatePassword); + return new X509Certificate2(cert.GetEncoded(), certificatePassword); } - + /// /// Retrieves a collection containing the client SSL PFX certificates. @@ -214,15 +214,14 @@ public async Task> StartSSLAsync(Stream baseStream, E if (_settings.TlsVersion != null) { -#if NET452 || NETSTANDARD2_0 - if (_settings.TlsVersion.Equals("Tls13", StringComparison.OrdinalIgnoreCase)) - throw new NotSupportedException(Resources.Tlsv13NotSupported); -#endif - SslProtocols sslProtocolsToUse = (SslProtocols)Enum.Parse(typeof(SslProtocols), _settings.TlsVersion); List listProtocols = new List(); -#if NET48 || NETSTANDARD2_1 || NET5_0_OR_GREATER +#if NET5_0_OR_GREATER + if (sslProtocolsToUse.HasFlag(SslProtocols.Tls13)) + listProtocols.Add(SslProtocols.Tls13); +#else + // 12288 represents the numerical value of SslProtocols.Tls13 enum option. if (sslProtocolsToUse.HasFlag((SslProtocols)12288)) listProtocols.Add((SslProtocols)12288); #endif diff --git a/MySQL.Data/tests/MySql.Data.Tests/SslTests.cs b/MySQL.Data/tests/MySql.Data.Tests/SslTests.cs index 1e4037cbb..96f60ded2 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/SslTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/SslTests.cs @@ -199,6 +199,7 @@ public void SslOverrided() /// /// WL14811 - Remove support for TLS 1.0 and 1.1 + /// WL16176 - Add support for TLS 1.3 /// [TestCase("[]", 1)] [TestCase("Tlsv1, Tlsv1.1", 2)] @@ -208,21 +209,17 @@ public void SslOverrided() [TestCase("foo, bar", 3)] [TestCase("Tlsv1.0, Tlsv1.2", 0)] [TestCase("foo, Tlsv1.2", 0)] - //#if NET48 || NETCOREAPP3_1 || NET5_0 || NET6_0 - // [TestCase("Tlsv1.3", "Tlsv1.3")] - // [TestCase("Tlsv1.0, Tlsv1.1, Tlsv1.2, Tlsv1.3", "Tlsv1.3")] - //#endif -#if NET452 [TestCase("Tlsv1.3", 4)] - [TestCase("Tlsv1.0, Tlsv1.1, Tlsv1.2, Tlsv1.3", 0)] -#endif [Property("Category", "Security")] public void TlsVersionTest(string tlsVersion, int error) { + if (error == 4 && Platform.IsMacOSX()) + Assert.Ignore(); + var builder = new MySqlConnectionStringBuilder(Connection.ConnectionString); void SetTlsVersion() { builder.TlsVersion = tlsVersion; } string ex; - string tls = "TLSv1.2"; + string tlsdefault = "TLSv1.2"; switch (error) { @@ -238,10 +235,6 @@ public void TlsVersionTest(string tlsVersion, int error) ex = Assert.Throws(SetTlsVersion).Message; StringAssert.AreEqualIgnoringCase(Resources.TlsNonValidProtocols, ex); break; - case 4: - SetTlsVersion(); - Assert.Throws(() => new MySqlConnection(builder.ConnectionString).Open()); - break; default: SetTlsVersion(); var conn = new MySqlConnection(builder.ConnectionString); @@ -256,9 +249,11 @@ public void TlsVersionTest(string tlsVersion, int error) using MySqlDataReader dr = cmd.ExecuteReader(); Assert.True(dr.Read()); - StringAssert.AreEqualIgnoringCase(tls, dr[1].ToString()); + if (error==4) + StringAssert.AreEqualIgnoringCase(tlsVersion, dr[1].ToString()); + else + StringAssert.AreEqualIgnoringCase(tlsdefault, dr[1].ToString()); } - break; } } From df8bb452ea346f5385e553460ddac0dec113f64d Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Sat, 10 Feb 2024 17:16:42 -0700 Subject: [PATCH 027/125] WL#16204 [Update installer and binary metadata] Change-Id: I4d36607f55fe3ec313598ec8cde07190b1887b19 --- CHANGES | 1 + EFCore/src/MySql.EntityFrameworkCore.csproj | 9 +++ EFCore/src/Properties/AssemblyInfo.cs | 23 ++++++++ .../src/Properties/AssemblyInfo.cs | 18 +++--- .../src/Properties/AssemblyInfo.cs | 55 +++++++++++++++++++ MySQL.Data/src/Properties/AssemblyInfo.cs | 10 ++-- MySQL.Data/src/Properties/VersionInfo.cs | 1 + MySql.Web/src/Properties/AssemblyInfo.cs | 14 +++-- 8 files changed, 112 insertions(+), 19 deletions(-) create mode 100644 MySQL.Data.OpenTelemetry/src/Properties/AssemblyInfo.cs diff --git a/CHANGES b/CHANGES index 2fea5f559..bd72fce8f 100644 --- a/CHANGES +++ b/CHANGES @@ -5,6 +5,7 @@ - Fixed bug Byte array type mapping has a fixed limit of 8000 in EFCore (Oracle Bug #36208913). - Removed support for FIDO authentication (WL16150). - Add support for TLS 1.3 (WL16176). +- Updated installer and binary metadata (WL16204). 8.3.0 diff --git a/EFCore/src/MySql.EntityFrameworkCore.csproj b/EFCore/src/MySql.EntityFrameworkCore.csproj index f0d8c2a31..7f07fda00 100644 --- a/EFCore/src/MySql.EntityFrameworkCore.csproj +++ b/EFCore/src/MySql.EntityFrameworkCore.csproj @@ -19,6 +19,15 @@ ..\..\ConnectorNetPublicKey.snk true $(NoWarn);CS1591;EF1001 + false + false + false + false + false + false + false + false + false diff --git a/EFCore/src/Properties/AssemblyInfo.cs b/EFCore/src/Properties/AssemblyInfo.cs index 5315d16f7..e18a3ad26 100644 --- a/EFCore/src/Properties/AssemblyInfo.cs +++ b/EFCore/src/Properties/AssemblyInfo.cs @@ -27,8 +27,31 @@ // 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA using Microsoft.EntityFrameworkCore.Design; +using System.Reflection; +using System; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +using System.Security; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("MySql.EntityFrameworkCore")] +[assembly: AssemblyDescription("MySql.EntityFrameworkCore adds support for Microsoft Entity Framework Core (EF Core) 6, 7, and 8.")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Oracle Corporation")] +[assembly: AssemblyProduct("MySQL Connector/NET")] +#if NET6_0 +[assembly: AssemblyCopyright("Copyright © 2021, 2024, Oracle and/or its affiliates.")] +#elif NET7_0 +[assembly: AssemblyCopyright("Copyright © 2022, 2024, Oracle and/or its affiliates.")] +#elif NET8_0 +[assembly: AssemblyCopyright("Copyright © 2024, Oracle and/or its affiliates.")] +#endif +[assembly: AssemblyTrademark("Oracle®, Java, MySQL, and NetSuite are registered trademarks of Oracle and/or its affiliates.")] +[assembly: AssemblyCulture("")] +[assembly: SecurityRules(SecurityRuleSet.Level1)] +[assembly: CLSCompliant(false)] // Setting ComVisible to false makes the types in this assembly not visible to COM // components. If you need to access a type in this assembly from COM, set the ComVisible diff --git a/EntityFramework/src/Properties/AssemblyInfo.cs b/EntityFramework/src/Properties/AssemblyInfo.cs index fa254f8c9..795f53733 100644 --- a/EntityFramework/src/Properties/AssemblyInfo.cs +++ b/EntityFramework/src/Properties/AssemblyInfo.cs @@ -30,19 +30,21 @@ using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +using System; -// General Information about an assembly is controlled through the following +// General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. -[assembly: AssemblyTitle("MySql.Data.EntityFramework for EF6")] -[assembly: AssemblyDescription("Entity Framework 6.0 supported")] - +[assembly: AssemblyTitle("MySql.Data.EntityFramework")] +[assembly: AssemblyDescription("MySql.Data.EntityFramework adds support for cross-platform application deployment with the Entity Framework 6.4 version.")] [assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("Oracle")] -[assembly: AssemblyProduct("MySql.Data.EntityFramework")] -[assembly: AssemblyCopyright("Copyright © 2008, 2023, Oracle and/or its affiliates.")] -[assembly: AssemblyTrademark("")] +[assembly: AssemblyCompany("Oracle Corporation")] +[assembly: AssemblyProduct("MySQL Connector/NET")] +[assembly: AssemblyCopyright("Copyright © 2008, 2024, Oracle and/or its affiliates.")] +[assembly: AssemblyTrademark("Oracle®, Java, MySQL, and NetSuite are registered trademarks of Oracle and/or its affiliates.")] [assembly: AssemblyCulture("")] +[assembly: SecurityRules(SecurityRuleSet.Level1)] +[assembly: CLSCompliant(false)] // Setting ComVisible to false makes the types in this assembly not visible // to COM components. If you need to access a type in this assembly from diff --git a/MySQL.Data.OpenTelemetry/src/Properties/AssemblyInfo.cs b/MySQL.Data.OpenTelemetry/src/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..eec58f246 --- /dev/null +++ b/MySQL.Data.OpenTelemetry/src/Properties/AssemblyInfo.cs @@ -0,0 +1,55 @@ +// Copyright � 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using System; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Security; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("MySql.Data.OpenTelemetry")] +[assembly: AssemblyDescription("MySql.Data.OpenTelemetry activates telemetry capabilities when the target MySQL server is configured to support telemetry.")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Oracle Corporation")] +[assembly: AssemblyProduct("MySQL Connector/NET")] +[assembly: AssemblyCopyright("Copyright � 2023, 2024, Oracle and/or its affiliates.")] +[assembly: AssemblyTrademark("Oracle�, Java, MySQL, and NetSuite are registered trademarks of Oracle and/or its affiliates.")] +[assembly: AssemblyCulture("")] +[assembly: SecurityRules(SecurityRuleSet.Level1)] +[assembly: CLSCompliant(false)] + +// Setting ComVisible to false makes the types in this assembly not visible to COM +// components. If you need to access a type in this assembly from COM, set the ComVisible +// attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM. + +[assembly: Guid("e33f787c-329b-410a-ab72-37126450cd7b")] diff --git a/MySQL.Data/src/Properties/AssemblyInfo.cs b/MySQL.Data/src/Properties/AssemblyInfo.cs index 96592b0c2..1a1f691c3 100644 --- a/MySQL.Data/src/Properties/AssemblyInfo.cs +++ b/MySQL.Data/src/Properties/AssemblyInfo.cs @@ -36,12 +36,12 @@ // set of attributes. Change these attribute values to modify the information // associated with an assembly. [assembly: AssemblyTitle("MySql.Data")] -[assembly: AssemblyDescription("ADO.Net driver for MySQL for .Net Framework and .Net Core")] +[assembly: AssemblyDescription("MySql.Data.EntityFramework adds support for cross-platform application deployment with the Entity Framework 6.4 version.")] [assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("Oracle")] -[assembly: AssemblyProduct("MySql.Data.Core")] -[assembly: AssemblyCopyright("Copyright (c) 2016, 2023, Oracle and/or its affiliates.")] -[assembly: AssemblyTrademark("")] +[assembly: AssemblyCompany("Oracle Corporation")] +[assembly: AssemblyProduct("MySQL Connector/NET")] +[assembly: AssemblyCopyright("Copyright © 2016, 2024, Oracle and/or its affiliates.")] +[assembly: AssemblyTrademark("Oracle®, Java, MySQL, and NetSuite are registered trademarks of Oracle and/or its affiliates.")] [assembly: AssemblyCulture("")] [assembly: SecurityRules(SecurityRuleSet.Level1)] [assembly: CLSCompliant(false)] diff --git a/MySQL.Data/src/Properties/VersionInfo.cs b/MySQL.Data/src/Properties/VersionInfo.cs index ee702c60b..a9d5ff8f8 100644 --- a/MySQL.Data/src/Properties/VersionInfo.cs +++ b/MySQL.Data/src/Properties/VersionInfo.cs @@ -42,4 +42,5 @@ [assembly: AssemblyVersion("8.4.0")] [assembly: AssemblyInformationalVersion("8.4.0")] +[assembly: AssemblyFileVersion("8.4.0")] [assembly: NeutralResourcesLanguage("en-US")] diff --git a/MySql.Web/src/Properties/AssemblyInfo.cs b/MySql.Web/src/Properties/AssemblyInfo.cs index cc06abbf3..9f1e50067 100644 --- a/MySql.Web/src/Properties/AssemblyInfo.cs +++ b/MySql.Web/src/Properties/AssemblyInfo.cs @@ -26,6 +26,7 @@ // along with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +using System; using System.Reflection; using System.Runtime.InteropServices; using System.Security; @@ -34,20 +35,21 @@ // set of attributes. Change these attribute values to modify the information // associated with an assembly. [assembly: AssemblyTitle("MySql.Web")] -[assembly: AssemblyDescription("ADO.Net driver for MySQL")] +[assembly: AssemblyDescription("MySql.Web includes a provider model for use with ASP.NET applications.")] [assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("Oracle")] -[assembly: AssemblyProduct("MySql.Web")] -[assembly: AssemblyCopyright("Copyright © 2004, 2023, Oracle and/or its affiliates.")] -[assembly: AssemblyTrademark("")] +[assembly: AssemblyCompany("Oracle Corporation")] +[assembly: AssemblyProduct("MySQL Connector/NET")] +[assembly: AssemblyCopyright("Copyright © 2004, 2024, Oracle and/or its affiliates.")] +[assembly: AssemblyTrademark("Oracle®, Java, MySQL, and NetSuite are registered trademarks of Oracle and/or its affiliates.")] [assembly: AssemblyCulture("")] +[assembly: SecurityRules(SecurityRuleSet.Level1)] +[assembly: CLSCompliant(false)] [assembly: AllowPartiallyTrustedCallers()] // Setting ComVisible to false makes the types in this assembly not visible // to COM components. If you need to access a type in this assembly from // COM, set the ComVisible attribute to true on that type. [assembly: ComVisible(false)] -[assembly: SecurityRules(SecurityRuleSet.Level1)] From 8e82d56d5fa7daa974ffba372c24bb3020ca7d1d Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Sun, 3 Mar 2024 18:00:07 -0700 Subject: [PATCH 028/125] WL#16204 [Update installer and binary metadata] - Fixed AssemblyFileVersionAttribute Change-Id: I8faad8ec096a5beb24685e3e7d621f361e5d4feb --- MySQL.Data/src/MySql.Data.csproj | 1 + 1 file changed, 1 insertion(+) diff --git a/MySQL.Data/src/MySql.Data.csproj b/MySQL.Data/src/MySql.Data.csproj index 1f435c3fc..a857625ee 100644 --- a/MySQL.Data/src/MySql.Data.csproj +++ b/MySQL.Data/src/MySql.Data.csproj @@ -24,6 +24,7 @@ false false false + false false false True From 53a1a7a995a819fb7d1a7175954e2f10c077a378 Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Sun, 3 Mar 2024 17:52:06 -0700 Subject: [PATCH 029/125] Bug#36319784 [Minpoolsize different than 0 causes connector to hang after first connection] Change-Id: I7f4c3e788f3c9f43ff293ad35c738730c85a20e2 --- CHANGES | 1 + MySQL.Data/src/MySqlPoolManager.cs | 22 ++++++++++++++----- .../tests/MySql.Data.Tests/ConnectionTests.cs | 21 ++++++++++++++++++ 3 files changed, 38 insertions(+), 6 deletions(-) diff --git a/CHANGES b/CHANGES index bd72fce8f..38d29f624 100644 --- a/CHANGES +++ b/CHANGES @@ -6,6 +6,7 @@ - Removed support for FIDO authentication (WL16150). - Add support for TLS 1.3 (WL16176). - Updated installer and binary metadata (WL16204). +- Fixed bug Minpoolsize different than 0 causes connector to hang after first connection (Oracle Bug #36319784). 8.3.0 diff --git a/MySQL.Data/src/MySqlPoolManager.cs b/MySQL.Data/src/MySqlPoolManager.cs index 0ad123d06..f8396952e 100644 --- a/MySQL.Data/src/MySqlPoolManager.cs +++ b/MySQL.Data/src/MySqlPoolManager.cs @@ -143,15 +143,25 @@ public static async Task GetPoolAsync(MySqlConnectionStringBuilder se MySqlPool pool; Pools.TryGetValue(text, out pool); - if (pool == null) + try { - pool = await MySqlPool.CreateMySqlPoolAsync(settings, execAsync, cancellationToken).ConfigureAwait(false); - Pools.Add(text, pool); + if (pool == null) + { + pool = await MySqlPool.CreateMySqlPoolAsync(settings, execAsync, cancellationToken).ConfigureAwait(false); + Pools.Add(text, pool); + } + else + pool.Settings = settings; + } + catch (Exception ex) + { + throw; + } + finally + { + waitHandle.Release(); } - else - pool.Settings = settings; - waitHandle.Release(); return pool; } diff --git a/MySQL.Data/tests/MySql.Data.Tests/ConnectionTests.cs b/MySQL.Data/tests/MySql.Data.Tests/ConnectionTests.cs index 10d85106f..1f8461d32 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/ConnectionTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/ConnectionTests.cs @@ -133,6 +133,27 @@ private void CreateCommandTimeoutException() } } + /// + /// Bug#36319784 Minpoolsize different than 0 causes connector to hang after first connection + /// + [Test] + public void PoolingMultipleConnections() + { + Connection.Settings.Pooling = true; + Connection.Settings.MaximumPoolSize = 100; + Connection.Settings.MinimumPoolSize = 1; + MySqlConnection conn =new MySqlConnection(Connection.ConnectionString); + Assert.DoesNotThrow(() => conn.Open()); + + Connection.Settings.PersistSecurityInfo = false; + conn = conn = new MySqlConnection(Connection.ConnectionString); + Assert.Throws(() => conn.Open()); + + Connection.Settings.PersistSecurityInfo = true; + conn = conn = new MySqlConnection(Connection.ConnectionString ); + Assert.DoesNotThrow(() => conn.Open()); + } + /// /// Bug#35827809 Connector/Net allows a connection that has been disposed to be reopened. /// From 68b0ea7adaf0724dbea9ced4c0bac033791dfaee Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Wed, 6 Mar 2024 13:44:28 -0700 Subject: [PATCH 030/125] Bug#36374702 [Tests failing due to removal of 'HAVE_SSL' variable from server] Change-Id: I3ed71e5d807e38f1634a67b9a7195fa0233d7353 --- CHANGES | 1 + MySQL.Data/tests/MySql.Data.Tests/SslTests.cs | 11 ++--------- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/CHANGES b/CHANGES index 38d29f624..6486d07ba 100644 --- a/CHANGES +++ b/CHANGES @@ -7,6 +7,7 @@ - Add support for TLS 1.3 (WL16176). - Updated installer and binary metadata (WL16204). - Fixed bug Minpoolsize different than 0 causes connector to hang after first connection (Oracle Bug #36319784). +- Fixed bug Tests failing due to removal of 'HAVE_SSL' variable from server (Oracle Bug #36374702). 8.3.0 diff --git a/MySQL.Data/tests/MySql.Data.Tests/SslTests.cs b/MySQL.Data/tests/MySql.Data.Tests/SslTests.cs index 96f60ded2..f91031fa1 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/SslTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/SslTests.cs @@ -332,13 +332,6 @@ public void ConnectUsingPFXCertificates() StringAssert.StartsWith("TLSv1", reader.GetString(1)); } - command = new MySqlCommand("show variables like 'have_ssl';", c); - using (MySqlDataReader reader = command.ExecuteReader()) - { - Assert.True(reader.Read()); - StringAssert.AreEqualIgnoringCase("YES", reader.GetString(1)); - } - command = new MySqlCommand("show variables like 'tls_version'", c); using (MySqlDataReader reader = command.ExecuteReader()) { @@ -1208,7 +1201,7 @@ public bool ServerHaveSsl() { Dictionary strValues = new(); - var commandList = new string[] { "show variables like 'have_ssl'", "show status like '%Ssl_version'", "show variables like 'tls_version'" }; + var commandList = new string[] { "show status like '%Ssl_version'", "show variables like 'tls_version'" }; foreach (var item in commandList) { var cmd = Connection.CreateCommand(); @@ -1221,7 +1214,7 @@ public bool ServerHaveSsl() } } } - return (strValues["have_ssl"] == "YES" && strValues["Ssl_version"].StartsWith("TLS") && !string.IsNullOrEmpty(strValues["tls_version"])) ? true : false; + return (strValues["Ssl_version"].StartsWith("TLS") && !string.IsNullOrEmpty(strValues["tls_version"])) ? true : false; } #endregion Methods } From 7266863cafac97383af327751407c644d5a49bee Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Fri, 8 Mar 2024 14:52:59 -0700 Subject: [PATCH 031/125] Bug#36374702 [Tests failing due to removal of 'HAVE_SSL' variable from server] - continuation Change-Id: I13d515efee7005a9e3be2ea46bea6b676490479f --- MySQL.Data/tests/MySqlX.Data.Tests/SslTests.cs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/SslTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/SslTests.cs index f52be59cc..f410728eb 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/SslTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/SslTests.cs @@ -682,8 +682,6 @@ public void AttemptConnectionWitSwitchedPemCertificates() public void PfxCertificateWithUri() { if (!session.Version.isAtLeast(8, 0, 0)) Assert.Ignore("This test is for MySql 8.0 or higher."); - var result = session.SQL("show variables like '%ave_ssl%'").Execute().FetchOne(); - if (result[1].ToString() != "YES") return; var connStr = ConnectionStringUri + $"?ssl-mode=VerifyCA&ssl-ca={clientPfxIncorrect}&ssl-ca-pwd={sslCertificatePassword}"; Assert.That(() => MySQLX.GetSession(connStr), Throws.Exception); @@ -704,8 +702,6 @@ public void PfxCertificateWithUri() public void PfxCertificateWithConnectionString() { if (!session.Version.isAtLeast(8, 0, 0)) Assert.Ignore("This test is for MySql 8.0 or higher."); - var result = session.SQL("show variables like '%ave_ssl%'").Execute().FetchOne(); - if (result[1].ToString() != "YES") return; var connStr = ConnectionString + $";ssl-mode=Required;ssl-ca={clientPfx};ssl-ca-pwd={sslCertificatePassword};"; using (Session c = MySQLX.GetSession(connStr)) @@ -751,8 +747,6 @@ public void TlsVersionInConnectionStringXplugin(string tlsVersion) { if (!Platform.IsWindows()) Assert.Ignore("This test is for Windows OS only"); if (!session.Version.isAtLeast(8, 0, 16)) Assert.Ignore("This test is for MySql 8.0.16 or higher."); - var result = session.SQL("show variables like '%ave_ssl%'").Execute().FetchOne(); - if (result[1].ToString() != "YES") return; var connStr = ConnectionString + $";sslmode=Required;tls-version={tlsVersion}"; using (var c = MySQLX.GetSession(connStr)) From 14bc3195e6972f7391c4149c68193fd92417d93c Mon Sep 17 00:00:00 2001 From: Reggie Burnett Date: Wed, 21 Feb 2024 17:45:22 -0600 Subject: [PATCH 032/125] WL#16175 [Add support for Vector data type] Change-Id: I904a94d7a06dd1782d70e2c02e82e647cdc7bb8f --- CHANGES | 1 + MySQL.Data/src/Field.cs | 1 + MySQL.Data/src/MysqlDefs.cs | 6 ++ MySQL.Data/src/Types/MySqlBinary.cs | 12 ++- .../tests/MySql.Data.Tests/DataTypeTests.cs | 95 +++++++++++++++++++ .../netstandard2_0/GetSchemaTests.cs | 3 + 6 files changed, 113 insertions(+), 5 deletions(-) diff --git a/CHANGES b/CHANGES index 6486d07ba..24e007bd8 100644 --- a/CHANGES +++ b/CHANGES @@ -8,6 +8,7 @@ - Updated installer and binary metadata (WL16204). - Fixed bug Minpoolsize different than 0 causes connector to hang after first connection (Oracle Bug #36319784). - Fixed bug Tests failing due to removal of 'HAVE_SSL' variable from server (Oracle Bug #36374702). +- Added support for Vector data type (WL16175). 8.3.0 diff --git a/MySQL.Data/src/Field.cs b/MySQL.Data/src/Field.cs index 7715ef83a..6f2e92a1c 100644 --- a/MySQL.Data/src/Field.cs +++ b/MySQL.Data/src/Field.cs @@ -345,6 +345,7 @@ public static IMySqlValue GetIMySqlValue(MySqlDbType type) case MySqlDbType.TinyBlob: case MySqlDbType.Binary: case MySqlDbType.VarBinary: + case MySqlDbType.Vector: return new MySqlBinary(type, true); case MySqlDbType.Guid: return new MySqlGuid(); diff --git a/MySQL.Data/src/MysqlDefs.cs b/MySQL.Data/src/MysqlDefs.cs index a81c20711..82e54f2aa 100644 --- a/MySQL.Data/src/MysqlDefs.cs +++ b/MySQL.Data/src/MysqlDefs.cs @@ -223,6 +223,12 @@ public enum MySqlDbType /// Bit-field data type /// Bit = 16, + + /// + /// Vector type + /// + Vector=242, + /// /// JSON /// diff --git a/MySQL.Data/src/Types/MySqlBinary.cs b/MySQL.Data/src/Types/MySqlBinary.cs index 7704b7671..21d398eba 100644 --- a/MySQL.Data/src/Types/MySqlBinary.cs +++ b/MySQL.Data/src/Types/MySqlBinary.cs @@ -73,6 +73,7 @@ string IMySqlValue.MySqlTypeName case MySqlDbType.TinyBlob: return "TINY_BLOB"; case MySqlDbType.MediumBlob: return "MEDIUM_BLOB"; case MySqlDbType.LongBlob: return "LONG_BLOB"; + case MySqlDbType.Vector: return "VECTOR"; default: return "BLOB"; } @@ -167,12 +168,13 @@ void IMySqlValue.SkipValue(MySqlPacket packet) public static void SetDSInfo(MySqlSchemaCollection sc) { - string[] types = new string[] { "BLOB", "TINYBLOB", "MEDIUMBLOB", "LONGBLOB", "BINARY", "VARBINARY" }; + string[] types = new string[] { "BLOB", "TINYBLOB", "MEDIUMBLOB", "LONGBLOB", "BINARY", "VARBINARY", "VECTOR" }; MySqlDbType[] dbtype = new MySqlDbType[] { MySqlDbType.Blob, - MySqlDbType.TinyBlob, MySqlDbType.MediumBlob, MySqlDbType.LongBlob, MySqlDbType.Binary, MySqlDbType.VarBinary }; - long[] sizes = new long[] { 65535L, 255L, 16777215L, 4294967295L, 255L, 65535L }; - string[] format = new string[] { null, null, null, null, "binary({0})", "varbinary({0})" }; - string[] parms = new string[] { null, null, null, null, "length", "length" }; + MySqlDbType.TinyBlob, MySqlDbType.MediumBlob, MySqlDbType.LongBlob, MySqlDbType.Binary, MySqlDbType.VarBinary, + MySqlDbType.Vector}; + long[] sizes = new long[] { 65535L, 255L, 16777215L, 4294967295L, 255L, 65535L, 16777215L }; + string[] format = new string[] { null, null, null, null, "binary({0})", "varbinary({0})", null }; + string[] parms = new string[] { null, null, null, null, "length", "length", null }; // we use name indexing because this method will only be called // when GetSchema is called for the DataSourceInformation diff --git a/MySQL.Data/tests/MySql.Data.Tests/DataTypeTests.cs b/MySQL.Data/tests/MySql.Data.Tests/DataTypeTests.cs index 428716362..8d8ab43a0 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/DataTypeTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/DataTypeTests.cs @@ -1692,5 +1692,100 @@ public void OldGetStringBehaviorOn() Assert.AreEqual("20.40", reader.GetString(1)); } + [Test] + public void BadVectorDataThrowsException() + { + if (Version < new Version(9, 0, 0)) + Assert.Ignore(); + + ExecuteSQL(@"CREATE TABLE Test (vector1 VECTOR)"); + using var cmd = new MySqlCommand(); + cmd.Connection = Connection; + + // insert a value + cmd.CommandText = "INSERT INTO Test VALUES(@v1)"; + cmd.Parameters.Add("v1", MySqlDbType.Vector); + cmd.Parameters[0].Value = "not a vector value"; + Assert.Throws(() => cmd.ExecuteNonQuery()); + } + + [TestCase(false)] + [TestCase(true)] + public void InsertAndSelectVector(bool prepared) + { + if (Version < new Version(9, 0, 0)) + Assert.Ignore(); + + ExecuteSQL(@"CREATE TABLE Test (vector1 VECTOR)"); + using var cmd = new MySqlCommand(); + cmd.Connection = Connection; + + // insert a value + cmd.CommandText = "INSERT INTO Test VALUES(@v1)"; + cmd.Parameters.Add("v1", MySqlDbType.Vector); + float[] floatArray = [1.2f, 2.3f, 3.4f]; + + // copy floats into byteArray + byte[] byteArray = new byte[floatArray.Length * 4]; + Buffer.BlockCopy(floatArray, 0, byteArray, 0, byteArray.Length); + + cmd.Parameters[0].Value = byteArray; + if (prepared) cmd.Prepare(); + cmd.ExecuteNonQuery(); + + // now select that value back out and compare + cmd.CommandText = "SELECT vector1 from Test"; + if (prepared) cmd.Prepare(); + using var reader = cmd.ExecuteReader(); + reader.Read(); + var value = reader.GetValue(0); + Assert.IsInstanceOf(typeof(byte[]), value); + byteArray = (byte[])value; + + float[] floatArray2 = new float[byteArray.Length / 4]; + Buffer.BlockCopy(byteArray, 0, floatArray2, 0, byteArray.Length); + + Assert.AreEqual(3, floatArray2.Length); + Assert.AreEqual(1.2f, floatArray2[0]); + Assert.AreEqual(2.3f, floatArray2[1]); + Assert.AreEqual(3.4f, floatArray2[2]); + } + + [TestCase(false)] + [TestCase(true)] + public void VectorReturnedFromSproc(bool prepared) + { + if (Version < new Version(9, 0, 0)) + Assert.Ignore(); + + ExecuteSQL("DROP PROCEDURE IF EXISTS spTest"); + ExecuteSQL(@"CREATE PROCEDURE spTest (OUT v1 VECTOR) BEGIN + SELECT STRING_TO_VECTOR('[1.2, 2.3, 3.4]') INTO v1; END"); + using var cmd = new MySqlCommand(); + cmd.Connection = Connection; + + // prepare and execute the command + cmd.CommandText = "spTest"; + cmd.Parameters.Add("v1", MySqlDbType.Vector); + cmd.Parameters[0].Direction = ParameterDirection.Output; + cmd.CommandType = CommandType.StoredProcedure; + if (prepared) cmd.Prepare(); + cmd.ExecuteNonQuery(); + + // now the parameter should contain the output value + Assert.IsInstanceOf(typeof(byte[]), cmd.Parameters[0].Value); + byte[] byteArray = (byte[])cmd.Parameters[0].Value; + + // now check to see if it has the correct values + float[] floatArray = new float[byteArray.Length / 4]; + Buffer.BlockCopy(byteArray, 0, floatArray, 0, byteArray.Length); + + Assert.AreEqual(3, floatArray.Length); + Assert.AreEqual(1.2f, floatArray[0]); + Assert.AreEqual(2.3f, floatArray[1]); + Assert.AreEqual(3.4f, floatArray[2]); + } } + + } diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/GetSchemaTests.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/GetSchemaTests.cs index f0abd1339..628c199a5 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/GetSchemaTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/GetSchemaTests.cs @@ -75,6 +75,9 @@ public void Collections() [Test] public void DataTypes() { + if (Version < new Version(9, 0, 0)) + Assert.Ignore(); + DataTable dt = Connection.GetSchema("DataTypes", new string[] { }); foreach (DataRow row in dt.Rows) From eda445bbe7c800101fcb77a6b29f3419f519242a Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Wed, 6 Mar 2024 16:26:06 -0700 Subject: [PATCH 033/125] WL#16197 [GPL License Exception Update] continuation of (a19b71f8dd032ed435d850f8ddea146582a82b7e) Change-Id: Ie7aeec4a2e9e5a9aa77749a8847e519e56c1d4fa --- .../src/Generators/FunctionProcessor.cs | 2 +- EntityFramework/src/Metadata.cs | 2 +- .../src/MySql.Data.EntityFramework.csproj | 2 +- .../MySql.EntityFramework.Basic.Tests.csproj | 2 +- .../Properties/AssemblyInfo.cs | 2 +- .../MySql.EntityFramework.CodeFirst.Tests.csproj | 2 +- .../Properties/AssemblyInfo.cs | 2 +- .../Properties/sakila-data.sql | 3 +-- .../Properties/sakila-schema.sql | 3 +-- ...MySql.EntityFramework.Migrations.Tests.csproj | 2 +- .../Properties/AssemblyInfo.cs | 2 +- .../src/MySQL.Data.OpenTelemetry.csproj | 2 +- .../Properties/AssemblyInfo.cs | 2 +- MySQL.Data/src/MySql.Data.csproj | 2 +- MySQL.Data/src/MySqlCommand.cs | 2 +- MySQL.Data/src/MySqlConnection.cs | 2 +- MySQL.Data/src/MySqlHelper.cs | 2 +- .../src/X/Protocol/X/Protobuf/MysqlxSql.cs | 16 ++++++++-------- .../Framework/netstandard2_0/NETCore20Tests.cs | 2 +- .../MySql.Data.Tests/MySql.Data.Tests.csproj | 2 +- .../MySql.Data.Tests/Properties/AssemblyInfo.cs | 2 +- .../Properties/AssemblyInfo.cs | 2 +- .../MySqlX.Data.Tests/MySqlX.Data.Tests.csproj | 2 +- .../MySqlX.Data.Tests/Properties/AssemblyInfo.cs | 2 +- MySql.Web/src/MySql.Web.csproj | 2 +- MySql.Web/tests/MySql.Web.Tests.csproj | 2 +- MySql.Web/tests/Properties/AssemblyInfo.cs | 2 +- README | 2 +- 28 files changed, 35 insertions(+), 37 deletions(-) diff --git a/EntityFramework/src/Generators/FunctionProcessor.cs b/EntityFramework/src/Generators/FunctionProcessor.cs index d8f44727f..1eaa1eb87 100644 --- a/EntityFramework/src/Generators/FunctionProcessor.cs +++ b/EntityFramework/src/Generators/FunctionProcessor.cs @@ -1,4 +1,4 @@ -// Copyright © 2008, 2024, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2008, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/src/Metadata.cs b/EntityFramework/src/Metadata.cs index 38b4709b2..f4da5682a 100644 --- a/EntityFramework/src/Metadata.cs +++ b/EntityFramework/src/Metadata.cs @@ -1,4 +1,4 @@ -// Copyright © 2008, 2024, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2008, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/src/MySql.Data.EntityFramework.csproj b/EntityFramework/src/MySql.Data.EntityFramework.csproj index 42ba730d8..9aeeed0a7 100644 --- a/EntityFramework/src/MySql.Data.EntityFramework.csproj +++ b/EntityFramework/src/MySql.Data.EntityFramework.csproj @@ -2,7 +2,7 @@ MySql.Data.EntityFramework - Copyright (c) 2016, 2023, Oracle and/or its affiliates. + Copyright © 2016, 2024, Oracle and/or its affiliates. en-US 8.4.0 Oracle diff --git a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/MySql.EntityFramework.Basic.Tests.csproj b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/MySql.EntityFramework.Basic.Tests.csproj index 548d2bb0c..582784520 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/MySql.EntityFramework.Basic.Tests.csproj +++ b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/MySql.EntityFramework.Basic.Tests.csproj @@ -2,7 +2,7 @@ MySql.Data.EntityFramework.CodeFirTests - Copyright (c) 2016, 2023, Oracle and/or its affiliates. + Copyright © 2016, 2024, Oracle and/or its affiliates. en-US 8.4.0 Oracle diff --git a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/Properties/AssemblyInfo.cs b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/Properties/AssemblyInfo.cs index 95de9a1c9..0c52fccc9 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/Properties/AssemblyInfo.cs +++ b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/Properties/AssemblyInfo.cs @@ -38,7 +38,7 @@ [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Oracle")] [assembly: AssemblyProduct("MySql.Data.EntityFramework.Tests")] -[assembly: AssemblyCopyright("Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved.")] +[assembly: AssemblyCopyright("Copyright © 2008, 2024, Oracle and/or its affiliates.")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/MySql.EntityFramework.CodeFirst.Tests.csproj b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/MySql.EntityFramework.CodeFirst.Tests.csproj index 5e91bd5af..ab33be29a 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/MySql.EntityFramework.CodeFirst.Tests.csproj +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/MySql.EntityFramework.CodeFirst.Tests.csproj @@ -2,7 +2,7 @@ MySql.Data.EntityFramework.CodeFirst.Tests - Copyright (c) 2016, 2023, Oracle and/or its affiliates. + Copyright © 2016, 2024, Oracle and/or its affiliates. en-US 8.4.0 Oracle diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/Properties/AssemblyInfo.cs b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/Properties/AssemblyInfo.cs index 6f4cc1fb9..04f490d66 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/Properties/AssemblyInfo.cs +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/Properties/AssemblyInfo.cs @@ -38,7 +38,7 @@ [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Oracle")] [assembly: AssemblyProduct("MySql.EntityFramework.CodeFirst.Tests")] -[assembly: AssemblyCopyright("Copyright © 2011, 2019, Oracle and/or its affiliates. All rights reserved.")] +[assembly: AssemblyCopyright("Copyright © 2011, 2024, Oracle and/or its affiliates.")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/Properties/sakila-data.sql b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/Properties/sakila-data.sql index 644fc65fe..fcb99f2f6 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/Properties/sakila-data.sql +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/Properties/sakila-data.sql @@ -1,8 +1,7 @@ -- Sakila Sample Database Data -- Version 1.0 --- Copyright (c) 2006, 2015, Oracle and/or its affiliates. --- All rights reserved. +-- Copyright � 2006, 2024, Oracle and/or its affiliates. -- Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/Properties/sakila-schema.sql b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/Properties/sakila-schema.sql index 8754868a1..f25502e95 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/Properties/sakila-schema.sql +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/Properties/sakila-schema.sql @@ -1,8 +1,7 @@ -- Sakila Sample Database Schema -- Version 1.0 --- Copyright (c) 2006, 2015, Oracle and/or its affiliates. --- All rights reserved. +-- Copyright � 2006, 2024, Oracle and/or its affiliates. -- Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: diff --git a/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/MySql.EntityFramework.Migrations.Tests.csproj b/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/MySql.EntityFramework.Migrations.Tests.csproj index a7ad7c9a2..4e0e6901e 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/MySql.EntityFramework.Migrations.Tests.csproj +++ b/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/MySql.EntityFramework.Migrations.Tests.csproj @@ -2,7 +2,7 @@ MySql.Data.EntityFramework.Migrations.Tests - Copyright (c) 2016, 2023, Oracle and/or its affiliates. + Copyright © 2016, 2024, Oracle and/or its affiliates. en-US 8.4.0 Oracle diff --git a/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/Properties/AssemblyInfo.cs b/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/Properties/AssemblyInfo.cs index 4c56279e1..17dbf24a2 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/Properties/AssemblyInfo.cs +++ b/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/Properties/AssemblyInfo.cs @@ -39,7 +39,7 @@ [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Oracle")] [assembly: AssemblyProduct("MySql.Data.EntityFramework.Migrations.Tests")] -[assembly: AssemblyCopyright("Copyright © 2013, 2019, Oracle and/or its affiliates. All rights reserved.")] +[assembly: AssemblyCopyright("Copyright © 2013, 2024, Oracle and/or its affiliates.")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] diff --git a/MySQL.Data.OpenTelemetry/src/MySQL.Data.OpenTelemetry.csproj b/MySQL.Data.OpenTelemetry/src/MySQL.Data.OpenTelemetry.csproj index c9f9cf24d..abfbca424 100644 --- a/MySQL.Data.OpenTelemetry/src/MySQL.Data.OpenTelemetry.csproj +++ b/MySQL.Data.OpenTelemetry/src/MySQL.Data.OpenTelemetry.csproj @@ -2,7 +2,7 @@ MySql.Data.OpenTelemetry - Copyright (c) 2023, Oracle and/or its affiliates. + Copyright © 2023, 2024, Oracle and/or its affiliates. en-US 8.4.0 Oracle diff --git a/MySQL.Data/MySql.Replication.Tests/Properties/AssemblyInfo.cs b/MySQL.Data/MySql.Replication.Tests/Properties/AssemblyInfo.cs index 1fed11efd..0e3b4168c 100644 --- a/MySQL.Data/MySql.Replication.Tests/Properties/AssemblyInfo.cs +++ b/MySQL.Data/MySql.Replication.Tests/Properties/AssemblyInfo.cs @@ -39,7 +39,7 @@ [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Oracle Corporation")] [assembly: AssemblyProduct("MySql.LoadBalancing.Tests")] -[assembly: AssemblyCopyright("Copyright © 2013, 2019, Oracle and/or its affiliates. All rights reserved.")] +[assembly: AssemblyCopyright("Copyright © 2013, 2024, Oracle and/or its affiliates.")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] diff --git a/MySQL.Data/src/MySql.Data.csproj b/MySQL.Data/src/MySql.Data.csproj index a857625ee..4728aa496 100644 --- a/MySQL.Data/src/MySql.Data.csproj +++ b/MySQL.Data/src/MySql.Data.csproj @@ -3,7 +3,7 @@ MySql.Data.MySqlClient .Net Core Class Library - Copyright (c) 2016, 2023, Oracle and/or its affiliates. + Copyright © 2016, 2024, Oracle and/or its affiliates. en-US 8.4.0 Oracle diff --git a/MySQL.Data/src/MySqlCommand.cs b/MySQL.Data/src/MySqlCommand.cs index bf0ea1633..925229172 100644 --- a/MySQL.Data/src/MySqlCommand.cs +++ b/MySQL.Data/src/MySqlCommand.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2004, 2024, Oracle and/or its affiliates. +// Copyright � 2004, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/MySqlConnection.cs b/MySQL.Data/src/MySqlConnection.cs index 7aa18e908..8deb192e8 100644 --- a/MySQL.Data/src/MySqlConnection.cs +++ b/MySQL.Data/src/MySqlConnection.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2004, 2024, Oracle and/or its affiliates. +// Copyright � 2004, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/MySqlHelper.cs b/MySQL.Data/src/MySqlHelper.cs index 9545a44f4..9bf4518a6 100644 --- a/MySQL.Data/src/MySqlHelper.cs +++ b/MySQL.Data/src/MySqlHelper.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2004, 2024, Oracle and/or its affiliates. +// Copyright � 2004, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxSql.cs b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxSql.cs index 52856d584..62320a573 100644 --- a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxSql.cs +++ b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxSql.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2022, 2023, Oracle and/or its affiliates. +// Copyright � 2022, 2023, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // -// This program is also distributed with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, -// as designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an -// additional permission to link the program and your derivative works -// with the separately licensed software that they have included with -// MySQL. +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/NETCore20Tests.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/NETCore20Tests.cs index 86aced015..b37707e76 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/NETCore20Tests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/NETCore20Tests.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved. +// Copyright © 2018, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySql.Data.Tests/MySql.Data.Tests.csproj b/MySQL.Data/tests/MySql.Data.Tests/MySql.Data.Tests.csproj index 68baf743f..91faa3dcc 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/MySql.Data.Tests.csproj +++ b/MySQL.Data/tests/MySql.Data.Tests/MySql.Data.Tests.csproj @@ -3,7 +3,7 @@ MySql.Data.Tests MySql.Data.Tests Class Library - Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved. + Copyright © 2016, 2024, Oracle and/or its affiliates. 8.4.0 Oracle Oracle diff --git a/MySQL.Data/tests/MySql.Data.Tests/Properties/AssemblyInfo.cs b/MySQL.Data/tests/MySql.Data.Tests/Properties/AssemblyInfo.cs index 311cedc69..24d6ecb8c 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Properties/AssemblyInfo.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Properties/AssemblyInfo.cs @@ -40,7 +40,7 @@ [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Oracle")] [assembly: AssemblyProduct("MySql.Data.Tests")] -[assembly: AssemblyCopyright("Copyright © 2004, 2019, Oracle and/or its affiliates. All rights reserved.")] +[assembly: AssemblyCopyright("Copyright © 2004, 2024, Oracle and/or its affiliates.")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] diff --git a/MySQL.Data/tests/MySqlX.Data.Performance.Console.Tests/Properties/AssemblyInfo.cs b/MySQL.Data/tests/MySqlX.Data.Performance.Console.Tests/Properties/AssemblyInfo.cs index 53a3ec6a6..32dd847ad 100644 --- a/MySQL.Data/tests/MySqlX.Data.Performance.Console.Tests/Properties/AssemblyInfo.cs +++ b/MySQL.Data/tests/MySqlX.Data.Performance.Console.Tests/Properties/AssemblyInfo.cs @@ -10,7 +10,7 @@ [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Oracle")] [assembly: AssemblyProduct("MySqlX.Data.Performance.Console.Tests")] -[assembly: AssemblyCopyright("Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.")] +[assembly: AssemblyCopyright("Copyright © 2019, 2024, Oracle and/or its affiliates.")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/MySqlX.Data.Tests.csproj b/MySQL.Data/tests/MySqlX.Data.Tests/MySqlX.Data.Tests.csproj index 3e23abe90..d253a03dc 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/MySqlX.Data.Tests.csproj +++ b/MySQL.Data/tests/MySqlX.Data.Tests/MySqlX.Data.Tests.csproj @@ -3,7 +3,7 @@ MySql.Data.Tests MySql.Data.Tests Class Library - Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved. + Copyright © 2016, 2024, Oracle and/or its affiliates. 8.4.0 Oracle Oracle diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/Properties/AssemblyInfo.cs b/MySQL.Data/tests/MySqlX.Data.Tests/Properties/AssemblyInfo.cs index 97675c386..7503c029b 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/Properties/AssemblyInfo.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/Properties/AssemblyInfo.cs @@ -38,7 +38,7 @@ [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("MySQL Connector/NET")] -[assembly: AssemblyCopyright("Copyright © 2016, 2020, Oracle and/or its affiliates. All rights reserved.")] +[assembly: AssemblyCopyright("Copyright © 2016, 2024, Oracle and/or its affiliates.")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] diff --git a/MySql.Web/src/MySql.Web.csproj b/MySql.Web/src/MySql.Web.csproj index 12aa57b06..04741c8ea 100644 --- a/MySql.Web/src/MySql.Web.csproj +++ b/MySql.Web/src/MySql.Web.csproj @@ -2,7 +2,7 @@ MySql.Web - Copyright (c) 2016, 2023, Oracle and/or its affiliates. + Copyright © 2016, 2024, Oracle and/or its affiliates. en-US 8.4.0 Oracle diff --git a/MySql.Web/tests/MySql.Web.Tests.csproj b/MySql.Web/tests/MySql.Web.Tests.csproj index 535a6939f..5d43bf263 100644 --- a/MySql.Web/tests/MySql.Web.Tests.csproj +++ b/MySql.Web/tests/MySql.Web.Tests.csproj @@ -2,7 +2,7 @@ MySql.Web.Tests - Copyright (c) 2016, 2023, Oracle and/or its affiliates. + Copyright © 2016, 2024, Oracle and/or its affiliates. en-US 8.4.0 Oracle diff --git a/MySql.Web/tests/Properties/AssemblyInfo.cs b/MySql.Web/tests/Properties/AssemblyInfo.cs index 1564b2a2c..f492e56f2 100644 --- a/MySql.Web/tests/Properties/AssemblyInfo.cs +++ b/MySql.Web/tests/Properties/AssemblyInfo.cs @@ -38,7 +38,7 @@ [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Oracle")] [assembly: AssemblyProduct("MySql.Web.Tests")] -[assembly: AssemblyCopyright("Copyright © 2004, 2019, Oracle and/or its affiliates. All rights reserved.")] +[assembly: AssemblyCopyright("Copyright © 2004, 2024, Oracle and/or its affiliates.")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] [assembly: NonParallelizable] diff --git a/README b/README index 4448edd0b..6e6fc8689 100644 --- a/README +++ b/README @@ -1,4 +1,4 @@ -Copyright (c) 2004, 2024, Oracle and/or its affiliates. +Copyright © 2004, 2024, Oracle and/or its affiliates. This is a release of MySQL Connector/NET, Oracle's fully managed ADO .NET Driver for MySQL. From 89468faa220f087ae34a8a493fc2daf03ad2db23 Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Fri, 8 Mar 2024 15:39:40 -0700 Subject: [PATCH 034/125] Updated version number references in documentation. Change-Id: I79b68b9ae1b0a11689969f1cc02a2ed5f6b92550 --- Documentation/index.md | 4 ++-- README.md | 2 ++ Release Notes.txt | 6 +++--- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/Documentation/index.md b/Documentation/index.md index 00ffbfdfc..4965d6ca3 100644 --- a/Documentation/index.md +++ b/Documentation/index.md @@ -1,6 +1,6 @@ ## MySQL Connector/NET and X DevAPI -MySQL Connector/NET 8.3 supports X Protocol, which enables you to use X DevAPI with the .NET language of choice to develop applications that communicate with a MySQL server functioning as a document store, relational database, or both. +MySQL Connector/NET 8.4 supports X Protocol, which enables you to use X DevAPI with the .NET language of choice to develop applications that communicate with a MySQL server functioning as a document store, relational database, or both. To get started, review the following main classes: @@ -16,7 +16,7 @@ For an introduction to X DevAPI concepts, see the [X DevAPI User Guide](https:// ## MySQL Connector/NET -MySQL Connector/NET 8.3 also supports the development of .NET, .NET Core and .NET Framework applications that require secure, high-performance data connectivity with MySQL through the classic protocol. It supports ADO.NET, Entity Framework and various web providers. +MySQL Connector/NET 8.4 also supports the development of .NET, .NET Core and .NET Framework applications that require secure, high-performance data connectivity with MySQL through the classic protocol. It supports ADO.NET, Entity Framework and various web providers. To get started, review the following main classes: diff --git a/README.md b/README.md index a9bdb7f44..4f91301bd 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,8 @@ From MySQL Connector/NET 8.2, the driver adds support for [WebAuthn authenticati From MySQL Connector/NET 8.3, the driver also adds support for [.NET 8](https://learn.microsoft.com/en-us/dotnet/core/whats-new/dotnet-8) and [EFCore 8](https://learn.microsoft.com/en-us/ef/core/what-is-new/ef-core-8.0/whatsnew) GA versions. +From MySQL Connector/NET 8.4, the driver adds support for TLS1.3 and removes support for FIDO authentication plugin. + For detailed information please visit the official [MySQL Connector/NET documentation.](https://dev.mysql.com/doc/connector-net/en/) ## Licensing diff --git a/Release Notes.txt b/Release Notes.txt index 8d0350ec8..6f1e6dde2 100644 --- a/Release Notes.txt +++ b/Release Notes.txt @@ -1,8 +1,8 @@ -Connector/NET 8.3 Release Notes +Connector/NET 8.4 Release Notes ------------------------------------ Welcome to the release notes for Connector/NET 8.3 -What's new in 8.3 +What's new in 8.4 -------------------- -Connector/NET added support for the GA version of .NET 8 and EF Core 8, if you want know more about .NET 8 see (https://learn.microsoft.com/en-us/dotnet/core/whats-new/dotnet-8). \ No newline at end of file +Connector/NET added support for TLS1.3 and removed support for FIDO authentication plugin. \ No newline at end of file From 583795c821e475fc43b54f3ea90820a520487222 Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Fri, 8 Mar 2024 15:49:23 -0700 Subject: [PATCH 035/125] Updated EF Core project versions. Change-Id: I0dfc7e1628eb1a0b38d759f629938d32e1b07bb1 --- EFCore/src/MySql.EntityFrameworkCore.csproj | 12 ++++++------ .../MySql.EntityFrameworkCore.Basic.Tests.csproj | 6 +++--- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/EFCore/src/MySql.EntityFrameworkCore.csproj b/EFCore/src/MySql.EntityFrameworkCore.csproj index 7f07fda00..a42ec8b92 100644 --- a/EFCore/src/MySql.EntityFrameworkCore.csproj +++ b/EFCore/src/MySql.EntityFrameworkCore.csproj @@ -31,18 +31,18 @@ - - + + - - + + - - + + diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/MySql.EntityFrameworkCore.Basic.Tests.csproj b/EFCore/tests/MySql.EFCore.Basic.Tests/MySql.EntityFrameworkCore.Basic.Tests.csproj index 895966926..cbfe194b8 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/MySql.EntityFrameworkCore.Basic.Tests.csproj +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/MySql.EntityFrameworkCore.Basic.Tests.csproj @@ -14,15 +14,15 @@ - + - + - + From 1b5d61b61808ff0a47123e3274adcfa147416206 Mon Sep 17 00:00:00 2001 From: Reggie Burnett Date: Fri, 8 Mar 2024 13:13:31 -0600 Subject: [PATCH 036/125] Bug#36380976 [Fix deadlock in mysql poolmanager attempt] Change-Id: Ibc99c9fb04df45ee4848be04ee041c61b32d3245 --- CHANGES | 2 +- MySQL.Data/src/MySqlPoolManager.cs | 4 +- .../tests/MySql.Data.Tests/ConnectionTests.cs | 49 +++++++++++++++++++ 3 files changed, 52 insertions(+), 3 deletions(-) diff --git a/CHANGES b/CHANGES index 24e007bd8..9a4bf6ce1 100644 --- a/CHANGES +++ b/CHANGES @@ -9,7 +9,7 @@ - Fixed bug Minpoolsize different than 0 causes connector to hang after first connection (Oracle Bug #36319784). - Fixed bug Tests failing due to removal of 'HAVE_SSL' variable from server (Oracle Bug #36374702). - Added support for Vector data type (WL16175). - +- Fixed bug Fix deadlock in mysql poolmanager attempt (Oracle Bug #36380976) 8.3.0 - Added support for build traversal (WL15798). diff --git a/MySQL.Data/src/MySqlPoolManager.cs b/MySQL.Data/src/MySqlPoolManager.cs index f8396952e..a052dcdf2 100644 --- a/MySQL.Data/src/MySqlPoolManager.cs +++ b/MySQL.Data/src/MySqlPoolManager.cs @@ -139,7 +139,7 @@ public static async Task GetPoolAsync(MySqlConnectionStringBuilder se { string text = GetKey(settings); - await waitHandle.WaitAsync(CancellationToken.None); + await waitHandle.WaitAsync(CancellationToken.None).ConfigureAwait(false); MySqlPool pool; Pools.TryGetValue(text, out pool); @@ -219,7 +219,7 @@ private static async Task ClearPoolByTextAsync(string key, bool execAsync) public static async Task ClearAllPoolsAsync(bool execAsync) { - await waitHandle.WaitAsync(); + await waitHandle.WaitAsync().ConfigureAwait(false); // Create separate keys list. List keys = new List(Pools.Count); diff --git a/MySQL.Data/tests/MySql.Data.Tests/ConnectionTests.cs b/MySQL.Data/tests/MySql.Data.Tests/ConnectionTests.cs index 1f8461d32..40d791b4c 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/ConnectionTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/ConnectionTests.cs @@ -1666,6 +1666,55 @@ public void OpenMultipleConnectionsOnMultipleThreads() Task.WaitAll(tasks.ToArray()); } + #if NET462 || NET48 + /// + /// Deadlock bug on application with Synchronization context (Net full framework Asp.NET app, Windows Forms App, WPF app. + /// Any App with - WindowsFormsSynchronizationContext, DispatcherSynchronizationContext and AspNetSynchronizationContext + /// will deadlock if missing ConfigureAwait(false) inside the MySql library. + /// + //[Test] + //public void OpenMultipleConnectionsOnMultipleThreadsInAppWithSynchronizationContext() + //{ + // var sb = new MySqlConnectionStringBuilder(Connection.ConnectionString); + // sb.Pooling = true; + + // var tasks = new List(); + // for (int i = 0; i < 5; i++) + // { + // tasks.Add(Task.Run(() => + // { + // SynchronizationContext.SetSynchronizationContext(new System.Windows.Forms.WindowsFormsSynchronizationContext()); + // using (var connection = new MySqlConnection(sb.ConnectionString)) + // { + // connection.Open(); + // } + // })); + // } + // Assert.IsTrue(Task.WaitAll(tasks.ToArray(),5000),"Deadlock when connecting - cancelled waiting after 5 seconds."); + //} + + //[Test] + //public void OpenAsyncMultipleConnectionsOnMultipleThreadsInAppWithSynchronizationContext() + //{ + // var sb = new MySqlConnectionStringBuilder(Connection.ConnectionString); + // sb.Pooling = true; + + // var tasks = new List(); + // for (int i = 0; i < 5; i++) + // { + // tasks.Add(Task.Run(() => + // { + // SynchronizationContext.SetSynchronizationContext(new System.Windows.Forms.WindowsFormsSynchronizationContext()); + // using (var connection = new MySqlConnection(sb.ConnectionString)) + // { + // connection.OpenAsync().ConfigureAwait(false).GetAwaiter().GetResult(); + // } + // })); + // } + // Assert.IsTrue(Task.WaitAll(tasks.ToArray(),5000),"Deadlock when connecting - cancelled waiting after 5 seconds."); + //} + #endif + #region Methods private void ExecuteQueriesSuccess(string sql, string password) From 535ec6b57292300af74a5b6bf9cd700470c31808 Mon Sep 17 00:00:00 2001 From: Sreedhar Sreedhargadda Date: Mon, 4 Mar 2024 10:58:19 +0100 Subject: [PATCH 037/125] Updated the LICENSE files --- LICENSE | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/LICENSE b/LICENSE index 8e4d63098..25cfdd21e 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ Licensing Information User Manual -MySQL Connector/NET 8.3.0 Community +MySQL Connector/NET 8.4.0 Community __________________________________________________________________ Introduction @@ -8,25 +8,25 @@ Introduction This License Information User Manual contains Oracle's product license and other licensing information, including licensing information for third-party software which may be included in this distribution of - MySQL Connector/NET 8.3.0 Community. + MySQL Connector/NET 8.4.0 Community. - Last updated: November 2023 + Last updated: February 2024 Licensing Information - This release of MySQL Connector/NET 8.3.0 Community is brought to you + This release of MySQL Connector/NET 8.4.0 Community is brought to you by the MySQL team at Oracle. This software is released under version 2 of the GNU General Public License (GPLv2), as set forth below, with the following additional permissions: - This distribution of MySQL Connector/Net is designed to work with certain - software (including but not limited to OpenSSL) that is licensed under - separate terms, as designated in a particular file or component or in the - license documentation. Without limiting your rights under the GPLv2, the - authors of MySQL hereby grant you an additional permission to link the - program and your derivative works with the separately licensed software - that they have either included with the program or referenced in the - documenation. + This distribution of MySQL Connector/NET 8.4.0 Community is designed to + work with certain software (including but not limited to OpenSSL) that + is licensed under separate terms, as designated in a particular file or + component or in the license documentation. Without limiting your rights + under the GPLv2, the authors of MySQL hereby grant you an additional + permission to link the program and your derivative works with the + separately licensed software that they have either included with the + program or referenced in the documentation. Without limiting the foregoing grant of rights under the GPLv2 and additional permission as to separately licensed software, this @@ -34,7 +34,7 @@ Licensing Information a copy of which is reproduced below and can also be found along with its FAQ at http://oss.oracle.com/licenses/universal-foss-exception. - Copyright (c) 2004, 2023, Oracle and/or its affiliates. + Copyright (c) 2004, 2024, Oracle and/or its affiliates. Election of GPLv2 @@ -1017,4 +1017,4 @@ Written Offer for Source Code that included the binary that is the subject of your request, or b. in the case of code licensed under the GPL v3 for as long as Oracle - offers spare parts or customer support for that product model. \ No newline at end of file + offers spare parts or customer support for that product model. From a2bf2c44fcd60ab6c27dacc0ab5ff6189a7296b8 Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Fri, 15 Mar 2024 15:56:08 -0600 Subject: [PATCH 038/125] Bug#36405198 [Test failing due to removal of 'default_authentication_plugin' server variable] Change-Id: I384e332705a6f3327db18e18bafb4a8cd10e339c --- CHANGES | 2 ++ MySQL.Data/tests/MySqlX.Data.Tests/XAuth.cs | 8 ++++---- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/CHANGES b/CHANGES index 9a4bf6ce1..bc4b31cc0 100644 --- a/CHANGES +++ b/CHANGES @@ -10,6 +10,8 @@ - Fixed bug Tests failing due to removal of 'HAVE_SSL' variable from server (Oracle Bug #36374702). - Added support for Vector data type (WL16175). - Fixed bug Fix deadlock in mysql poolmanager attempt (Oracle Bug #36380976) +- Fixed bug Test failing due to removal of 'default_authentication_plugin' server variable (Oracle Bug #36405198). + 8.3.0 - Added support for build traversal (WL15798). diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/XAuth.cs b/MySQL.Data/tests/MySqlX.Data.Tests/XAuth.cs index 49d70e524..fa1dff39e 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/XAuth.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/XAuth.cs @@ -42,15 +42,15 @@ public class XAuth : BaseTest public void DefaultAuthNullPlugin() { if (!Platform.IsWindows()) Assert.Ignore("Check for Linux OS"); - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("Test available only to MySQL Server +8.0.11"); + if (!session.Version.isAtLeast(8, 4, 0)) Assert.Ignore("Test available only to MySQL Server +8.4.0"); - string pluginName = null;//default plugin + string pluginName = "caching_sha2_password";//default plugin MySqlConnectionStringBuilder builder = new MySqlConnectionStringBuilder(ConnectionString); builder.UserID = "testDefaultPlugin"; builder.Password = "test"; CreateUser(builder.UserID, builder.Password, pluginName); string connectionString = null, connectionStringUri = null; - string defaultAuthPlugin = session.SQL("SHOW VARIABLES LIKE 'default_authentication_plugin'").Execute().FetchAll()[0][1].ToString(); + string defaultAuthPlugin = session.SQL("SHOW VARIABLES LIKE 'authentication_policy'").Execute().FetchAll()[0][1].ToString().Split(',')[0] == "*" ? "caching_sha2_password" : ""; //Connection String connectionString = $"server={Host};user={builder.UserID};port={XPort};password={builder.Password}"; @@ -61,7 +61,7 @@ public void DefaultAuthNullPlugin() Assert.True(result[0][1].ToString().Contains("TLSv1")); } - connectionString = connectionString + ";ssl-mode=none"; + connectionString = connectionString + ";sslmode=none;"; using (var session1 = MySQLX.GetSession(connectionString)) Assert.AreEqual(defaultAuthPlugin == "mysql_native_password" ? MySqlAuthenticationMode.MYSQL41 : MySqlAuthenticationMode.SHA256_MEMORY, session1.Settings.Auth); From 87939c99fdad68b30803e9f4bb115e17cfabb8ce Mon Sep 17 00:00:00 2001 From: Sreedhar Sreedhargadda Date: Mon, 18 Mar 2024 08:26:10 +0100 Subject: [PATCH 039/125] Updated the LICENSE files --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index 25cfdd21e..9ca7460c7 100644 --- a/LICENSE +++ b/LICENSE @@ -10,7 +10,7 @@ Introduction third-party software which may be included in this distribution of MySQL Connector/NET 8.4.0 Community. - Last updated: February 2024 + Last updated: March 2024 Licensing Information From 4d3d329cb99cec2eefe587c6fe386bd9aa695375 Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Thu, 21 Mar 2024 11:34:20 -0600 Subject: [PATCH 040/125] Bump up version to 9.0.0 Change-Id: Idb5c4beccdab130858d7b05deb6309da98d2e43c --- CHANGES | 3 +++ .../templates/custom/partials/class.header.tmpl.partial | 2 +- EntityFramework/src/MySql.Data.EntityFramework.csproj | 2 +- .../MySql.EntityFramework.Basic.Tests.csproj | 2 +- .../MySql.EntityFramework.CodeFirst.Tests.csproj | 2 +- .../MySql.EntityFramework.Migrations.Tests.csproj | 2 +- .../src/MySQL.Data.OpenTelemetry.csproj | 2 +- MySQL.Data/src/MySql.Data.csproj | 2 +- MySQL.Data/src/Properties/VersionInfo.cs | 6 +++--- MySQL.Data/tests/MySql.Data.Tests/MySql.Data.Tests.csproj | 2 +- MySQL.Data/tests/MySqlX.Data.Tests/MySqlX.Data.Tests.csproj | 2 +- MySql.Web/src/MySql.Web.csproj | 2 +- MySql.Web/tests/MySql.Web.Tests.csproj | 2 +- 13 files changed, 17 insertions(+), 14 deletions(-) diff --git a/CHANGES b/CHANGES index bc4b31cc0..c0021045c 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,6 @@ +9.0.0 + + 8.4.0 - Updated FOSS license text in all source files (WL16197). - Fixed bug Shared memory connection doesn't work in multithread environment (Oracle Bug #36208932). diff --git a/Documentation/templates/custom/partials/class.header.tmpl.partial b/Documentation/templates/custom/partials/class.header.tmpl.partial index a5e724eed..9df19ebdd 100644 --- a/Documentation/templates/custom/partials/class.header.tmpl.partial +++ b/Documentation/templates/custom/partials/class.header.tmpl.partial @@ -25,7 +25,7 @@ {{/implements.0}}
{{__global.namespace}}: {{{namespace.specName.0.value}}}
{{__global.assembly}}: {{assemblies.0}}.dll
-
Version: 8.4.0
+
Version: 9.0.0
{{__global.syntax}}
{{syntax.content.0.value}}
diff --git a/EntityFramework/src/MySql.Data.EntityFramework.csproj b/EntityFramework/src/MySql.Data.EntityFramework.csproj index 9aeeed0a7..21d144a18 100644 --- a/EntityFramework/src/MySql.Data.EntityFramework.csproj +++ b/EntityFramework/src/MySql.Data.EntityFramework.csproj @@ -4,7 +4,7 @@ MySql.Data.EntityFramework Copyright © 2016, 2024, Oracle and/or its affiliates. en-US - 8.4.0 + 9.0.0 Oracle net462;netstandard2.1; $(NoWarn);CS1591 diff --git a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/MySql.EntityFramework.Basic.Tests.csproj b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/MySql.EntityFramework.Basic.Tests.csproj index 582784520..40ab28073 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/MySql.EntityFramework.Basic.Tests.csproj +++ b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/MySql.EntityFramework.Basic.Tests.csproj @@ -4,7 +4,7 @@ MySql.Data.EntityFramework.CodeFirTests Copyright © 2016, 2024, Oracle and/or its affiliates. en-US - 8.4.0 + 9.0.0 Oracle net7.0 MySql.EntityFramework.Basic.Tests diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/MySql.EntityFramework.CodeFirst.Tests.csproj b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/MySql.EntityFramework.CodeFirst.Tests.csproj index ab33be29a..8466175cc 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/MySql.EntityFramework.CodeFirst.Tests.csproj +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/MySql.EntityFramework.CodeFirst.Tests.csproj @@ -4,7 +4,7 @@ MySql.Data.EntityFramework.CodeFirst.Tests Copyright © 2016, 2024, Oracle and/or its affiliates. en-US - 8.4.0 + 9.0.0 Oracle net7.0 MySql.EntityFramework.CodeFirst.Tests diff --git a/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/MySql.EntityFramework.Migrations.Tests.csproj b/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/MySql.EntityFramework.Migrations.Tests.csproj index 4e0e6901e..a45dcd0d6 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/MySql.EntityFramework.Migrations.Tests.csproj +++ b/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/MySql.EntityFramework.Migrations.Tests.csproj @@ -4,7 +4,7 @@ MySql.Data.EntityFramework.Migrations.Tests Copyright © 2016, 2024, Oracle and/or its affiliates. en-US - 8.4.0 + 9.0.0 Oracle net7.0 MySql.EntityFramework.Migrations.Tests diff --git a/MySQL.Data.OpenTelemetry/src/MySQL.Data.OpenTelemetry.csproj b/MySQL.Data.OpenTelemetry/src/MySQL.Data.OpenTelemetry.csproj index abfbca424..70d0f257f 100644 --- a/MySQL.Data.OpenTelemetry/src/MySQL.Data.OpenTelemetry.csproj +++ b/MySQL.Data.OpenTelemetry/src/MySQL.Data.OpenTelemetry.csproj @@ -4,7 +4,7 @@ MySql.Data.OpenTelemetry Copyright © 2023, 2024, Oracle and/or its affiliates. en-US - 8.4.0 + 9.0.0 Oracle netstandard2.0 MySql.Data.OpenTelemetry diff --git a/MySQL.Data/src/MySql.Data.csproj b/MySQL.Data/src/MySql.Data.csproj index 4728aa496..cf2092cfc 100644 --- a/MySQL.Data/src/MySql.Data.csproj +++ b/MySQL.Data/src/MySql.Data.csproj @@ -5,7 +5,7 @@ MySql.Data.MySqlClient .Net Core Class Library Copyright © 2016, 2024, Oracle and/or its affiliates. en-US - 8.4.0 + 9.0.0 Oracle MySql.Data net462;net48;netstandard2.0;netstandard2.1;net6.0;net7.0;net8.0; diff --git a/MySQL.Data/src/Properties/VersionInfo.cs b/MySQL.Data/src/Properties/VersionInfo.cs index a9d5ff8f8..545a5808b 100644 --- a/MySQL.Data/src/Properties/VersionInfo.cs +++ b/MySQL.Data/src/Properties/VersionInfo.cs @@ -40,7 +40,7 @@ // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("8.4.0")] -[assembly: AssemblyInformationalVersion("8.4.0")] -[assembly: AssemblyFileVersion("8.4.0")] +[assembly: AssemblyVersion("9.0.0")] +[assembly: AssemblyInformationalVersion("9.0.0")] +[assembly: AssemblyFileVersion("9.0.0")] [assembly: NeutralResourcesLanguage("en-US")] diff --git a/MySQL.Data/tests/MySql.Data.Tests/MySql.Data.Tests.csproj b/MySQL.Data/tests/MySql.Data.Tests/MySql.Data.Tests.csproj index 91faa3dcc..ab9a2c1ee 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/MySql.Data.Tests.csproj +++ b/MySQL.Data/tests/MySql.Data.Tests/MySql.Data.Tests.csproj @@ -4,7 +4,7 @@ MySql.Data.Tests MySql.Data.Tests Class Library Copyright © 2016, 2024, Oracle and/or its affiliates. - 8.4.0 + 9.0.0 Oracle Oracle MySql.Data.Tests diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/MySqlX.Data.Tests.csproj b/MySQL.Data/tests/MySqlX.Data.Tests/MySqlX.Data.Tests.csproj index d253a03dc..76a1d4a15 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/MySqlX.Data.Tests.csproj +++ b/MySQL.Data/tests/MySqlX.Data.Tests/MySqlX.Data.Tests.csproj @@ -4,7 +4,7 @@ MySql.Data.Tests MySql.Data.Tests Class Library Copyright © 2016, 2024, Oracle and/or its affiliates. - 8.4.0 + 9.0.0 Oracle Oracle MySql.Data.Tests diff --git a/MySql.Web/src/MySql.Web.csproj b/MySql.Web/src/MySql.Web.csproj index 04741c8ea..9bf197b3e 100644 --- a/MySql.Web/src/MySql.Web.csproj +++ b/MySql.Web/src/MySql.Web.csproj @@ -4,7 +4,7 @@ MySql.Web Copyright © 2016, 2024, Oracle and/or its affiliates. en-US - 8.4.0 + 9.0.0 Oracle net462;net48; $(NoWarn);CS1591 diff --git a/MySql.Web/tests/MySql.Web.Tests.csproj b/MySql.Web/tests/MySql.Web.Tests.csproj index 5d43bf263..6c7042484 100644 --- a/MySql.Web/tests/MySql.Web.Tests.csproj +++ b/MySql.Web/tests/MySql.Web.Tests.csproj @@ -4,7 +4,7 @@ MySql.Web.Tests Copyright © 2016, 2024, Oracle and/or its affiliates. en-US - 8.4.0 + 9.0.0 Oracle net462;net48; MySql.Web.Tests From a6c99c18ad0597a4d66c955e67250a87ca33d7f2 Mon Sep 17 00:00:00 2001 From: Reggie Burnett Date: Fri, 15 Mar 2024 13:31:51 -0500 Subject: [PATCH 041/125] WL#16279 [Migrate to NUnit 4.x] Change-Id: I02c391bb4150b2f2da6e78fd8ec424feaea87221 --- CHANGES | 2 +- EFCore/tests/Directory.build.props | 12 ++++++++++++ .../tests/MySql.EFCore.Basic.Tests/BasicGuidTests.cs | 1 + .../MySql.EFCore.Basic.Tests/ConcurrencyTests.cs | 1 + .../MySql.EFCore.Basic.Tests/ConnectionTests.cs | 1 + EFCore/tests/MySql.EFCore.Basic.Tests/DataTests.cs | 1 + .../MySql.EFCore.Basic.Tests/DbFunctionsMySQLTest.cs | 1 + EFCore/tests/MySql.EFCore.Basic.Tests/EFCoreTests.cs | 1 + .../tests/MySql.EFCore.Basic.Tests/FluentAPITests.cs | 1 + .../MySql.EFCore.Basic.Tests/FunctionalTests.cs | 1 + .../LoadingRelatedDataTests.cs | 1 + .../tests/MySql.EFCore.Basic.Tests/ModelingTests.cs | 1 + .../MySql.EFCore.Basic.Tests/MultiSchemaTests.cs | 1 + .../MySQLDatabaseFacadeTest.cs | 1 + .../MySql.EFCore.Basic.Tests/MySQLTypeMapperTests.cs | 1 + .../MySql.EntityFrameworkCore.Basic.Tests.csproj | 5 ++--- .../ShadowPropertiesTests.cs | 1 + .../Utils/EntityTestsFixtureClass.cs | 1 + .../MySQLAnnotationCodeGeneratorTest.cs | 1 + .../MySQLCodeGeneratorTest.cs | 1 + .../MySQLDatabaseModelFactoryTest.cs | 1 + .../MySQLDesignTimeProviderServicesTest.cs | 1 + .../MySql.EntityFrameworkCore.Design.Tests.csproj | 5 ++--- .../MySQLHistoryRepositoryTests.cs | 1 + .../MySQLMigrationsTests.cs | 1 + ...MySql.EntityFrameworkCore.Migrations.Tests.csproj | 5 ++--- .../MySqlMigrationsGeneratorTest.cs | 1 + .../MySqlMigrationsGeneratorTestBase.cs | 1 + MySQL.Data/tests/Directory.build.props | 12 ++++++++++++ MySQL.Data/tests/MySql.Data.Tests/AttributeTests.cs | 1 + MySQL.Data/tests/MySql.Data.Tests/AuthTests.cs | 1 + MySQL.Data/tests/MySql.Data.Tests/BlobTests.cs | 1 + .../tests/MySql.Data.Tests/BlobTestsCompressed.cs | 1 + MySQL.Data/tests/MySql.Data.Tests/CharSetTests.cs | 1 + .../tests/MySql.Data.Tests/CharSetUTF8Tests.cs | 1 + .../MySql.Data.Tests/ClientSideFailoverTests.cs | 1 + MySQL.Data/tests/MySql.Data.Tests/CmdTests.cs | 1 + .../tests/MySql.Data.Tests/CmdTestsCompressed.cs | 1 + .../MySql.Data.Tests/ConnectionStringBuilderTests.cs | 1 + MySQL.Data/tests/MySql.Data.Tests/ConnectionTests.cs | 1 + MySQL.Data/tests/MySql.Data.Tests/DataTypeTests.cs | 1 + MySQL.Data/tests/MySql.Data.Tests/DateTimeTests.cs | 1 + MySQL.Data/tests/MySql.Data.Tests/DnsSrvTests.cs | 1 + MySQL.Data/tests/MySql.Data.Tests/EventTests.cs | 1 + MySQL.Data/tests/MySql.Data.Tests/ExceptionTests.cs | 1 + .../Framework/netstandard2_0/CultureTests.cs | 1 + .../Framework/netstandard2_0/DataTypeTests.cs | 1 + .../Framework/netstandard2_0/DateTimeTests.cs | 1 + .../Framework/netstandard2_0/GetSchemaTests.cs | 1 + .../Framework/netstandard2_0/MySQLHelperTests.cs | 1 + .../netstandard2_0/MySqlCommandBuilderTests.cs | 1 + .../netstandard2_0/MySqlDataAdapterTests.cs | 1 + .../Framework/netstandard2_0/MySqlDataReaderTests.cs | 1 + .../Framework/netstandard2_0/NETCore20Tests.cs | 1 + .../Framework/netstandard2_0/PerfMonTests.cs | 1 + .../netstandard2_0/ProcedureParameterTests.cs | 1 + .../Framework/netstandard2_0/ReplicationTests.cs | 1 + .../Framework/netstandard2_0/ThreadingTests.cs | 1 + .../Framework/netstandard2_0/TimeoutAndCancel.cs | 1 + .../Framework/netstandard2_0/TypeTests.cs | 1 + .../Framework/netstandard2_0/UsageAdvisorTests.cs | 1 + MySQL.Data/tests/MySql.Data.Tests/LoggingTests.cs | 1 + .../tests/MySql.Data.Tests/MySql.Data.Tests.csproj | 7 +++---- .../tests/MySql.Data.Tests/MySqlBulkLoaderTests.cs | 1 + .../tests/MySql.Data.Tests/MySqlDataReaderTests.cs | 1 + .../tests/MySql.Data.Tests/OutputParametersBatch.cs | 1 + MySQL.Data/tests/MySql.Data.Tests/ParameterTests.cs | 1 + MySQL.Data/tests/MySql.Data.Tests/PoolingTests.cs | 1 + .../tests/MySql.Data.Tests/PreparedStatements.cs | 1 + MySQL.Data/tests/MySql.Data.Tests/ScriptExecution.cs | 1 + .../tests/MySql.Data.Tests/SimpleTransactions.cs | 1 + MySQL.Data/tests/MySql.Data.Tests/SqlServerMode.cs | 1 + MySQL.Data/tests/MySql.Data.Tests/SslTests.cs | 1 + MySQL.Data/tests/MySql.Data.Tests/StoredProcedure.cs | 1 + .../MySql.Data.Tests/StoredProcedureWithAccess.cs | 1 + MySQL.Data/tests/MySql.Data.Tests/StressTests.cs | 1 + MySQL.Data/tests/MySql.Data.Tests/Syntax.cs | 1 + MySQL.Data/tests/MySql.Data.Tests/Syntax2.cs | 1 + MySQL.Data/tests/MySql.Data.Tests/TableCaching.cs | 1 + MySQL.Data/tests/MySql.Data.Tests/TestBase.cs | 1 + MySQL.Data/tests/MySql.Data.Tests/Tokenizer.cs | 1 + MySQL.Data/tests/MySql.Data.Tests/Transactions.cs | 1 + MySQL.Data/tests/MySql.Data.Tests/UnixSockets.cs | 1 + MySQL.Data/tests/MySqlX.Data.Tests/BaseTest.cs | 1 + MySQL.Data/tests/MySqlX.Data.Tests/BasicFindTests.cs | 1 + .../tests/MySqlX.Data.Tests/BasicSelectTests.cs | 1 + .../MySqlX.Data.Tests/CharsetAndCollationTests.cs | 1 + .../MySqlX.Data.Tests/ClientSideFailoverTests.cs | 1 + MySQL.Data/tests/MySqlX.Data.Tests/ClientTests.cs | 1 + .../tests/MySqlX.Data.Tests/CloseConnectionTests.cs | 1 + .../tests/MySqlX.Data.Tests/CollectionAsyncTests.cs | 1 + .../tests/MySqlX.Data.Tests/CollectionIndexTests.cs | 1 + .../tests/MySqlX.Data.Tests/CollectionTests.cs | 1 + .../tests/MySqlX.Data.Tests/CompressionTests.cs | 1 + .../tests/MySqlX.Data.Tests/CrudInsertTests.cs | 1 + .../tests/MySqlX.Data.Tests/CrudRemoveTests.cs | 1 + .../tests/MySqlX.Data.Tests/CrudTests/CrudGCTests.cs | 1 + .../MySqlX.Data.Tests/CrudTests/DocBufferingTests.cs | 1 + .../tests/MySqlX.Data.Tests/CrudUpdateTests.cs | 1 + .../tests/MySqlX.Data.Tests/CustomTypeTests.cs | 1 + MySQL.Data/tests/MySqlX.Data.Tests/DbDocTests.cs | 1 + MySQL.Data/tests/MySqlX.Data.Tests/DnsSrvTests.cs | 1 + .../tests/MySqlX.Data.Tests/ExprParserTests.cs | 1 + .../tests/MySqlX.Data.Tests/JsonParserTests.cs | 1 + MySQL.Data/tests/MySqlX.Data.Tests/MergePatch.cs | 1 + .../tests/MySqlX.Data.Tests/MySqlX.Data.Tests.csproj | 7 +++---- .../MySqlX.Data.Tests/PreparedStatementsTests.cs | 1 + .../RelationalTests/ColumnMetadataTests.cs | 1 + .../RelationalTests/DataTypeTests.cs | 1 + .../RelationalTests/DateTimeTests.cs | 1 + .../RelationalTests/RelationalGCTests.cs | 1 + .../RelationalTests/RowBufferingTests.cs | 1 + .../MySqlX.Data.Tests/RelationalTests/SqlTests.cs | 1 + .../RelationalTests/TableAsyncTests.cs | 1 + .../RelationalTests/TableDeleteTests.cs | 1 + .../RelationalTests/TableInsertTests.cs | 1 + .../RelationalTests/TableSelectTests.cs | 1 + .../RelationalTests/TableUpdateTests.cs | 1 + .../MySqlX.Data.Tests/RelationalTests/ViewTests.cs | 1 + MySQL.Data/tests/MySqlX.Data.Tests/SchemaTests.cs | 1 + MySQL.Data/tests/MySqlX.Data.Tests/SessionTests.cs | 1 + MySQL.Data/tests/MySqlX.Data.Tests/SslTests.cs | 1 + .../tests/MySqlX.Data.Tests/TransactionTests.cs | 1 + .../tests/MySqlX.Data.Tests/UnixSocketsTests.cs | 1 + MySQL.Data/tests/MySqlX.Data.Tests/XAuth.cs | 1 + .../XConnectionStringBuilderTests.cs | 1 + MySql.Web/tests/Directory.build.props | 12 ++++++++++++ MySql.Web/tests/MySql.Web.Tests.csproj | 6 +++--- MySql.Web/tests/PersonalizationTests.cs | 1 + MySql.Web/tests/ProfileTests.cs | 1 + MySql.Web/tests/RoleManagement.cs | 1 + MySql.Web/tests/SchemaManagerTests.cs | 1 + MySql.Web/tests/SchemaTests.cs | 1 + MySql.Web/tests/SessionTests.cs | 1 + MySql.Web/tests/SimpleMembership.cs | 1 + MySql.Web/tests/SiteMapTests.cs | 1 + MySql.Web/tests/UserManagement.cs | 1 + MySql.Web/tests/WebTestBase.cs | 1 + 138 files changed, 180 insertions(+), 21 deletions(-) create mode 100644 EFCore/tests/Directory.build.props create mode 100644 MySQL.Data/tests/Directory.build.props create mode 100644 MySql.Web/tests/Directory.build.props diff --git a/CHANGES b/CHANGES index c0021045c..d29099ec1 100644 --- a/CHANGES +++ b/CHANGES @@ -1,5 +1,5 @@ 9.0.0 - +- Updated NUnit to 4.x (WL16279) 8.4.0 - Updated FOSS license text in all source files (WL16197). diff --git a/EFCore/tests/Directory.build.props b/EFCore/tests/Directory.build.props new file mode 100644 index 000000000..03b886514 --- /dev/null +++ b/EFCore/tests/Directory.build.props @@ -0,0 +1,12 @@ + + + true + + + + + + + + + diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/BasicGuidTests.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/BasicGuidTests.cs index 5888e6e48..69bdcc775 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/BasicGuidTests.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/BasicGuidTests.cs @@ -30,6 +30,7 @@ using MySql.EntityFrameworkCore.Basic.Tests.Utils; using MySql.EntityFrameworkCore.Infrastructure.Internal; using NUnit.Framework; +using NUnit.Framework.Legacy; using System; using System.Linq; diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/ConcurrencyTests.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/ConcurrencyTests.cs index 7591baea0..4a2572b8a 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/ConcurrencyTests.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/ConcurrencyTests.cs @@ -31,6 +31,7 @@ using MySql.EntityFrameworkCore.Basic.Tests.DbContextClasses; using MySql.EntityFrameworkCore.Extensions; using NUnit.Framework; +using NUnit.Framework.Legacy; using System; using System.Linq; diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/ConnectionTests.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/ConnectionTests.cs index 1e88d0e76..08673d39a 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/ConnectionTests.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/ConnectionTests.cs @@ -40,6 +40,7 @@ using MySql.EntityFrameworkCore.Internal; using MySql.EntityFrameworkCore.Storage.Internal; using NUnit.Framework; +using NUnit.Framework.Legacy; using System.Diagnostics; namespace MySql.EntityFrameworkCore.Basic.Tests diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/DataTests.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/DataTests.cs index 8cf95c170..a542c2e30 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/DataTests.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/DataTests.cs @@ -30,6 +30,7 @@ using MySql.Data.MySqlClient; using MySql.EntityFrameworkCore.Basic.Tests.DbContextClasses; using NUnit.Framework; +using NUnit.Framework.Legacy; using System; using System.Linq; using System.Threading.Tasks; diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/DbFunctionsMySQLTest.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/DbFunctionsMySQLTest.cs index c24d54de8..1085dba0f 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/DbFunctionsMySQLTest.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/DbFunctionsMySQLTest.cs @@ -30,6 +30,7 @@ using MySql.EntityFrameworkCore.Basic.Tests.DbContextClasses; using MySql.EntityFrameworkCore.Extensions; using NUnit.Framework; +using NUnit.Framework.Legacy; using System; using System.Linq; diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/EFCoreTests.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/EFCoreTests.cs index c105145cd..fd84eb897 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/EFCoreTests.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/EFCoreTests.cs @@ -31,6 +31,7 @@ using MySql.EntityFrameworkCore.Basic.Tests.DbContextClasses; using MySql.EntityFrameworkCore.Basic.Tests.Utils; using NUnit.Framework; +using NUnit.Framework.Legacy; using System; using System.Linq; using System.Transactions; diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/FluentAPITests.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/FluentAPITests.cs index 16851d3fc..c34dd7f03 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/FluentAPITests.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/FluentAPITests.cs @@ -33,6 +33,7 @@ using MySql.EntityFrameworkCore.Basic.Tests.Utils; using MySql.EntityFrameworkCore.Extensions; using NUnit.Framework; +using NUnit.Framework.Legacy; using System; using System.Linq; using System.Text.RegularExpressions; diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/FunctionalTests.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/FunctionalTests.cs index 1c7a6336a..6c0d235c2 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/FunctionalTests.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/FunctionalTests.cs @@ -34,6 +34,7 @@ using MySql.EntityFrameworkCore.Basic.Tests.Utils; using MySql.EntityFrameworkCore.Extensions; using NUnit.Framework; +using NUnit.Framework.Legacy; using System; using System.Linq; diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/LoadingRelatedDataTests.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/LoadingRelatedDataTests.cs index 955c5432b..cec6177a3 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/LoadingRelatedDataTests.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/LoadingRelatedDataTests.cs @@ -31,6 +31,7 @@ using MySql.EntityFrameworkCore.Basic.Tests.DbContextClasses; using MySql.EntityFrameworkCore.Basic.Tests.Utils; using NUnit.Framework; +using NUnit.Framework.Legacy; using System.Linq; namespace MySql.EntityFrameworkCore.Basic.Tests diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/ModelingTests.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/ModelingTests.cs index 6424d0277..cf1746d64 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/ModelingTests.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/ModelingTests.cs @@ -30,6 +30,7 @@ using MySql.EntityFrameworkCore.Basic.Tests.DbContextClasses; using MySql.EntityFrameworkCore.Basic.Tests.Utils; using NUnit.Framework; +using NUnit.Framework.Legacy; using System; using System.Collections.Generic; using System.Linq; diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/MultiSchemaTests.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/MultiSchemaTests.cs index 503c32699..c40e6a61f 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/MultiSchemaTests.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/MultiSchemaTests.cs @@ -31,6 +31,7 @@ using MySql.EntityFrameworkCore.Basic.Tests.DbContextClasses; using MySql.EntityFrameworkCore.Basic.Tests.Utils; using NUnit.Framework; +using NUnit.Framework.Legacy; using System; using System.Collections.Generic; using System.Linq; diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/MySQLDatabaseFacadeTest.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/MySQLDatabaseFacadeTest.cs index 72cfe80e9..6fb864f2b 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/MySQLDatabaseFacadeTest.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/MySQLDatabaseFacadeTest.cs @@ -34,6 +34,7 @@ using MySql.EntityFrameworkCore.Basic.Tests.Utils; using MySql.EntityFrameworkCore.Extensions; using NUnit.Framework; +using NUnit.Framework.Legacy; using System; namespace MySql.EntityFrameworkCore.Basic.Tests diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/MySQLTypeMapperTests.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/MySQLTypeMapperTests.cs index adf585fd0..b4aedf779 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/MySQLTypeMapperTests.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/MySQLTypeMapperTests.cs @@ -31,6 +31,7 @@ using MySql.EntityFrameworkCore.Basic.Tests.DbContextClasses; using MySql.EntityFrameworkCore.Basic.Tests.Utils; using NUnit.Framework; +using NUnit.Framework.Legacy; using System; using System.Collections.Generic; using System.Linq; diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/MySql.EntityFrameworkCore.Basic.Tests.csproj b/EFCore/tests/MySql.EFCore.Basic.Tests/MySql.EntityFrameworkCore.Basic.Tests.csproj index cbfe194b8..4df134a7a 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/MySql.EntityFrameworkCore.Basic.Tests.csproj +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/MySql.EntityFrameworkCore.Basic.Tests.csproj @@ -26,9 +26,8 @@ - - - + + diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/ShadowPropertiesTests.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/ShadowPropertiesTests.cs index acfe975f5..bd957825b 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/ShadowPropertiesTests.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/ShadowPropertiesTests.cs @@ -32,6 +32,7 @@ using MySql.EntityFrameworkCore.Basic.Tests.DbContextClasses; using MySql.EntityFrameworkCore.Extensions; using NUnit.Framework; +using NUnit.Framework.Legacy; using System; using System.Data; using System.Linq; diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/Utils/EntityTestsFixtureClass.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/Utils/EntityTestsFixtureClass.cs index 670bc5778..4da09804f 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/Utils/EntityTestsFixtureClass.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/Utils/EntityTestsFixtureClass.cs @@ -30,6 +30,7 @@ using MySql.Data.MySqlClient; using MySql.EntityFrameworkCore.Basic.Tests.DbContextClasses; using NUnit.Framework; +using NUnit.Framework.Legacy; using System; using System.Diagnostics; using System.Text; diff --git a/EFCore/tests/MySql.EFCore.Design.Tests/MySQLAnnotationCodeGeneratorTest.cs b/EFCore/tests/MySql.EFCore.Design.Tests/MySQLAnnotationCodeGeneratorTest.cs index b913c72ac..61ff8b711 100644 --- a/EFCore/tests/MySql.EFCore.Design.Tests/MySQLAnnotationCodeGeneratorTest.cs +++ b/EFCore/tests/MySql.EFCore.Design.Tests/MySQLAnnotationCodeGeneratorTest.cs @@ -36,6 +36,7 @@ using MySql.EntityFrameworkCore.Metadata.Internal; using MySql.EntityFrameworkCore.Storage.Internal; using NUnit.Framework; +using NUnit.Framework.Legacy; using System.Linq; namespace MySql.EntityFrameworkCore.Design.Tests diff --git a/EFCore/tests/MySql.EFCore.Design.Tests/MySQLCodeGeneratorTest.cs b/EFCore/tests/MySql.EFCore.Design.Tests/MySQLCodeGeneratorTest.cs index c0b65a21a..c1549b537 100644 --- a/EFCore/tests/MySql.EFCore.Design.Tests/MySQLCodeGeneratorTest.cs +++ b/EFCore/tests/MySql.EFCore.Design.Tests/MySQLCodeGeneratorTest.cs @@ -32,6 +32,7 @@ using MySql.EntityFrameworkCore.Infrastructure; using MySql.EntityFrameworkCore.Scaffolding.Internal; using NUnit.Framework; +using NUnit.Framework.Legacy; using System; using System.Linq; using System.Reflection; diff --git a/EFCore/tests/MySql.EFCore.Design.Tests/MySQLDatabaseModelFactoryTest.cs b/EFCore/tests/MySql.EFCore.Design.Tests/MySQLDatabaseModelFactoryTest.cs index b416915a6..d264c8c4d 100644 --- a/EFCore/tests/MySql.EFCore.Design.Tests/MySQLDatabaseModelFactoryTest.cs +++ b/EFCore/tests/MySql.EFCore.Design.Tests/MySQLDatabaseModelFactoryTest.cs @@ -35,6 +35,7 @@ using MySql.EntityFrameworkCore.Diagnostics.Internal; using MySql.EntityFrameworkCore.Scaffolding.Internal; using NUnit.Framework; +using NUnit.Framework.Legacy; using System; using System.Collections.Generic; using System.Diagnostics; diff --git a/EFCore/tests/MySql.EFCore.Design.Tests/MySQLDesignTimeProviderServicesTest.cs b/EFCore/tests/MySql.EFCore.Design.Tests/MySQLDesignTimeProviderServicesTest.cs index 3a37ccf82..ca39de4c1 100644 --- a/EFCore/tests/MySql.EFCore.Design.Tests/MySQLDesignTimeProviderServicesTest.cs +++ b/EFCore/tests/MySql.EFCore.Design.Tests/MySQLDesignTimeProviderServicesTest.cs @@ -30,6 +30,7 @@ using MySql.EntityFrameworkCore.Design.Internal; using MySql.EntityFrameworkCore.Storage.Internal; using NUnit.Framework; +using NUnit.Framework.Legacy; using System; using System.Reflection; diff --git a/EFCore/tests/MySql.EFCore.Design.Tests/MySql.EntityFrameworkCore.Design.Tests.csproj b/EFCore/tests/MySql.EFCore.Design.Tests/MySql.EntityFrameworkCore.Design.Tests.csproj index 86eaa62e7..e95a51ffc 100644 --- a/EFCore/tests/MySql.EFCore.Design.Tests/MySql.EntityFrameworkCore.Design.Tests.csproj +++ b/EFCore/tests/MySql.EFCore.Design.Tests/MySql.EntityFrameworkCore.Design.Tests.csproj @@ -25,9 +25,8 @@ - - - + + diff --git a/EFCore/tests/MySql.EFCore.Migrations.Tests/MySQLHistoryRepositoryTests.cs b/EFCore/tests/MySql.EFCore.Migrations.Tests/MySQLHistoryRepositoryTests.cs index 35a1611d5..70085710b 100644 --- a/EFCore/tests/MySql.EFCore.Migrations.Tests/MySQLHistoryRepositoryTests.cs +++ b/EFCore/tests/MySql.EFCore.Migrations.Tests/MySQLHistoryRepositoryTests.cs @@ -34,6 +34,7 @@ using MySql.EntityFrameworkCore.Basic.Tests.Utils; using MySql.EntityFrameworkCore.Extensions; using NUnit.Framework; +using NUnit.Framework.Legacy; namespace MySql.EntityFrameworkCore.Migrations.Tests { diff --git a/EFCore/tests/MySql.EFCore.Migrations.Tests/MySQLMigrationsTests.cs b/EFCore/tests/MySql.EFCore.Migrations.Tests/MySQLMigrationsTests.cs index 30e97a470..a91f32c00 100644 --- a/EFCore/tests/MySql.EFCore.Migrations.Tests/MySQLMigrationsTests.cs +++ b/EFCore/tests/MySql.EFCore.Migrations.Tests/MySQLMigrationsTests.cs @@ -32,6 +32,7 @@ using Microsoft.Extensions.DependencyInjection; using MySql.EntityFrameworkCore.Basic.Tests.Utils; using NUnit.Framework; +using NUnit.Framework.Legacy; namespace MySql.EntityFrameworkCore.Migrations.Tests { diff --git a/EFCore/tests/MySql.EFCore.Migrations.Tests/MySql.EntityFrameworkCore.Migrations.Tests.csproj b/EFCore/tests/MySql.EFCore.Migrations.Tests/MySql.EntityFrameworkCore.Migrations.Tests.csproj index fd2e0ef96..e82a9bb8c 100644 --- a/EFCore/tests/MySql.EFCore.Migrations.Tests/MySql.EntityFrameworkCore.Migrations.Tests.csproj +++ b/EFCore/tests/MySql.EFCore.Migrations.Tests/MySql.EntityFrameworkCore.Migrations.Tests.csproj @@ -14,9 +14,8 @@ - - - + + diff --git a/EFCore/tests/MySql.EFCore.Migrations.Tests/MySqlMigrationsGeneratorTest.cs b/EFCore/tests/MySql.EFCore.Migrations.Tests/MySqlMigrationsGeneratorTest.cs index f36545f30..bcb5c3ee2 100644 --- a/EFCore/tests/MySql.EFCore.Migrations.Tests/MySqlMigrationsGeneratorTest.cs +++ b/EFCore/tests/MySql.EFCore.Migrations.Tests/MySqlMigrationsGeneratorTest.cs @@ -33,6 +33,7 @@ using MySql.EntityFrameworkCore.Basic.Tests.Utils; using MySql.EntityFrameworkCore.Extensions; using NUnit.Framework; +using NUnit.Framework.Legacy; namespace MySql.EntityFrameworkCore.Migrations.Tests { diff --git a/EFCore/tests/MySql.EFCore.Migrations.Tests/MySqlMigrationsGeneratorTestBase.cs b/EFCore/tests/MySql.EFCore.Migrations.Tests/MySqlMigrationsGeneratorTestBase.cs index 8e15deaad..e597dfcee 100644 --- a/EFCore/tests/MySql.EFCore.Migrations.Tests/MySqlMigrationsGeneratorTestBase.cs +++ b/EFCore/tests/MySql.EFCore.Migrations.Tests/MySqlMigrationsGeneratorTestBase.cs @@ -33,6 +33,7 @@ using MySql.EntityFrameworkCore.Metadata.Internal; using MySql.EntityFrameworkCore.Migrations.Tests.Utilities; using NUnit.Framework; +using NUnit.Framework.Legacy; using System; using System.Linq; diff --git a/MySQL.Data/tests/Directory.build.props b/MySQL.Data/tests/Directory.build.props new file mode 100644 index 000000000..03b886514 --- /dev/null +++ b/MySQL.Data/tests/Directory.build.props @@ -0,0 +1,12 @@ + + + true + + + + + + + + + diff --git a/MySQL.Data/tests/MySql.Data.Tests/AttributeTests.cs b/MySQL.Data/tests/MySql.Data.Tests/AttributeTests.cs index 269a21b5f..e52a7279b 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/AttributeTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/AttributeTests.cs @@ -27,6 +27,7 @@ // 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA using NUnit.Framework; +using NUnit.Framework.Legacy; using System; namespace MySql.Data.MySqlClient.Tests diff --git a/MySQL.Data/tests/MySql.Data.Tests/AuthTests.cs b/MySQL.Data/tests/MySql.Data.Tests/AuthTests.cs index 115ed476c..5c7cfdcf6 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/AuthTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/AuthTests.cs @@ -30,6 +30,7 @@ using MySql.Data.Common; using MySql.Data.MySqlClient.Authentication; using NUnit.Framework; +using NUnit.Framework.Legacy; using System; using System.Collections.Generic; using System.Data; diff --git a/MySQL.Data/tests/MySql.Data.Tests/BlobTests.cs b/MySQL.Data/tests/MySql.Data.Tests/BlobTests.cs index a49c7bb41..14f7e05be 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/BlobTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/BlobTests.cs @@ -29,6 +29,7 @@ using System; using System.Data; using NUnit.Framework; +using NUnit.Framework.Legacy; namespace MySql.Data.MySqlClient.Tests { diff --git a/MySQL.Data/tests/MySql.Data.Tests/BlobTestsCompressed.cs b/MySQL.Data/tests/MySql.Data.Tests/BlobTestsCompressed.cs index 2dc442e06..fcb85a1f4 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/BlobTestsCompressed.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/BlobTestsCompressed.cs @@ -27,6 +27,7 @@ // 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA using NUnit.Framework; +using NUnit.Framework.Legacy; namespace MySql.Data.MySqlClient.Tests { diff --git a/MySQL.Data/tests/MySql.Data.Tests/CharSetTests.cs b/MySQL.Data/tests/MySql.Data.Tests/CharSetTests.cs index 2e461ab60..e527c3e01 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/CharSetTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/CharSetTests.cs @@ -28,6 +28,7 @@ using MySql.Data.Common; using NUnit.Framework; +using NUnit.Framework.Legacy; using System; using System.Data; diff --git a/MySQL.Data/tests/MySql.Data.Tests/CharSetUTF8Tests.cs b/MySQL.Data/tests/MySql.Data.Tests/CharSetUTF8Tests.cs index 53878b95c..4760e06d7 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/CharSetUTF8Tests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/CharSetUTF8Tests.cs @@ -28,6 +28,7 @@ using MySql.Data.Common; using NUnit.Framework; +using NUnit.Framework.Legacy; using System; using System.Data; using System.Text; diff --git a/MySQL.Data/tests/MySql.Data.Tests/ClientSideFailoverTests.cs b/MySQL.Data/tests/MySql.Data.Tests/ClientSideFailoverTests.cs index ca9ec8aad..cfd078190 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/ClientSideFailoverTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/ClientSideFailoverTests.cs @@ -28,6 +28,7 @@ using MySql.Data.Failover; using NUnit.Framework; +using NUnit.Framework.Legacy; using System; using System.Data; diff --git a/MySQL.Data/tests/MySql.Data.Tests/CmdTests.cs b/MySQL.Data/tests/MySql.Data.Tests/CmdTests.cs index 8cc409197..c2454add3 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/CmdTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/CmdTests.cs @@ -27,6 +27,7 @@ // 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA using NUnit.Framework; +using NUnit.Framework.Legacy; using System; using System.Data; using System.Diagnostics; diff --git a/MySQL.Data/tests/MySql.Data.Tests/CmdTestsCompressed.cs b/MySQL.Data/tests/MySql.Data.Tests/CmdTestsCompressed.cs index e259383f9..d18aecbcb 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/CmdTestsCompressed.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/CmdTestsCompressed.cs @@ -27,6 +27,7 @@ // 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA using NUnit.Framework; +using NUnit.Framework.Legacy; namespace MySql.Data.MySqlClient.Tests { diff --git a/MySQL.Data/tests/MySql.Data.Tests/ConnectionStringBuilderTests.cs b/MySQL.Data/tests/MySql.Data.Tests/ConnectionStringBuilderTests.cs index e6e01b814..3d50fa738 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/ConnectionStringBuilderTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/ConnectionStringBuilderTests.cs @@ -28,6 +28,7 @@ using MySql.Data.Common; using NUnit.Framework; +using NUnit.Framework.Legacy; using System; using System.Collections.Generic; using System.Data; diff --git a/MySQL.Data/tests/MySql.Data.Tests/ConnectionTests.cs b/MySQL.Data/tests/MySql.Data.Tests/ConnectionTests.cs index 40d791b4c..2e7f989fa 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/ConnectionTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/ConnectionTests.cs @@ -28,6 +28,7 @@ using MySql.Data.Common; using NUnit.Framework; +using NUnit.Framework.Legacy; using System; using System.Collections.Generic; using System.Data; diff --git a/MySQL.Data/tests/MySql.Data.Tests/DataTypeTests.cs b/MySQL.Data/tests/MySql.Data.Tests/DataTypeTests.cs index 8d8ab43a0..4f2c02e76 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/DataTypeTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/DataTypeTests.cs @@ -28,6 +28,7 @@ using MySql.Data.Types; using NUnit.Framework; +using NUnit.Framework.Legacy; using System; using System.Data; using System.Text; diff --git a/MySQL.Data/tests/MySql.Data.Tests/DateTimeTests.cs b/MySQL.Data/tests/MySql.Data.Tests/DateTimeTests.cs index 398f4c58a..8ccb87cf9 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/DateTimeTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/DateTimeTests.cs @@ -28,6 +28,7 @@ using MySql.Data.Types; using NUnit.Framework; +using NUnit.Framework.Legacy; using System; using System.Globalization; using System.Text; diff --git a/MySQL.Data/tests/MySql.Data.Tests/DnsSrvTests.cs b/MySQL.Data/tests/MySql.Data.Tests/DnsSrvTests.cs index b51b16dd9..59a074e65 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/DnsSrvTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/DnsSrvTests.cs @@ -29,6 +29,7 @@ using MySql.Data.Common; using MySql.Data.Common.DnsClient; using NUnit.Framework; +using NUnit.Framework.Legacy; using System; using System.Collections.Generic; using System.Linq; diff --git a/MySQL.Data/tests/MySql.Data.Tests/EventTests.cs b/MySQL.Data/tests/MySql.Data.Tests/EventTests.cs index 836c62f65..78d6e0df9 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/EventTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/EventTests.cs @@ -28,6 +28,7 @@ using System.Data; using NUnit.Framework; +using NUnit.Framework.Legacy; namespace MySql.Data.MySqlClient.Tests { diff --git a/MySQL.Data/tests/MySql.Data.Tests/ExceptionTests.cs b/MySQL.Data/tests/MySql.Data.Tests/ExceptionTests.cs index f5d43f9da..51ecf2d76 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/ExceptionTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/ExceptionTests.cs @@ -27,6 +27,7 @@ // 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA using NUnit.Framework; +using NUnit.Framework.Legacy; using System; using System.Data; using System.Reflection; diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/CultureTests.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/CultureTests.cs index ccb2a1f4b..52f2c24ed 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/CultureTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/CultureTests.cs @@ -28,6 +28,7 @@ using System; using NUnit.Framework; +using NUnit.Framework.Legacy; using System.Threading; using System.Globalization; using System.Data; diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/DataTypeTests.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/DataTypeTests.cs index 4ae5238ef..dedd778f2 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/DataTypeTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/DataTypeTests.cs @@ -28,6 +28,7 @@ using System; using NUnit.Framework; +using NUnit.Framework.Legacy; using System.Data; using System.Data.Common; diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/DateTimeTests.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/DateTimeTests.cs index ba43bb143..07be3e8a5 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/DateTimeTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/DateTimeTests.cs @@ -28,6 +28,7 @@ using System; using NUnit.Framework; +using NUnit.Framework.Legacy; using MySql.Data.Types; using System.Data; using System.Globalization; diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/GetSchemaTests.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/GetSchemaTests.cs index 628c199a5..71214f36b 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/GetSchemaTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/GetSchemaTests.cs @@ -28,6 +28,7 @@ using MySql.Data.Common; using NUnit.Framework; +using NUnit.Framework.Legacy; using System; using System.Data; using System.Linq; diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MySQLHelperTests.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MySQLHelperTests.cs index a2bdd79c3..bdeff2071 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MySQLHelperTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MySQLHelperTests.cs @@ -28,6 +28,7 @@ using System; using NUnit.Framework; +using NUnit.Framework.Legacy; using System.Data; using System.Threading.Tasks; using System.Threading; diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MySqlCommandBuilderTests.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MySqlCommandBuilderTests.cs index 309184a2e..542c70aa8 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MySqlCommandBuilderTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MySqlCommandBuilderTests.cs @@ -27,6 +27,7 @@ // 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA using NUnit.Framework; +using NUnit.Framework.Legacy; using System; using System.Data; diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MySqlDataAdapterTests.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MySqlDataAdapterTests.cs index 2c8651fd9..27effd8f6 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MySqlDataAdapterTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MySqlDataAdapterTests.cs @@ -27,6 +27,7 @@ // 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA using NUnit.Framework; +using NUnit.Framework.Legacy; using System; using System.Data; using System.Data.Common; diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MySqlDataReaderTests.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MySqlDataReaderTests.cs index 12e0315d1..542ea6f54 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MySqlDataReaderTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MySqlDataReaderTests.cs @@ -27,6 +27,7 @@ // 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA using NUnit.Framework; +using NUnit.Framework.Legacy; using System.Data; namespace MySql.Data.MySqlClient.Tests diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/NETCore20Tests.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/NETCore20Tests.cs index b37707e76..2d984200c 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/NETCore20Tests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/NETCore20Tests.cs @@ -29,6 +29,7 @@ using System; using System.Data; using NUnit.Framework; +using NUnit.Framework.Legacy; namespace MySql.Data.MySqlClient.Tests { diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/PerfMonTests.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/PerfMonTests.cs index 0e69f2da6..cdb6c0230 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/PerfMonTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/PerfMonTests.cs @@ -27,6 +27,7 @@ // 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA using NUnit.Framework; +using NUnit.Framework.Legacy; namespace MySql.Data.MySqlClient.Tests { diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/ProcedureParameterTests.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/ProcedureParameterTests.cs index 0b4894594..c84deb683 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/ProcedureParameterTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/ProcedureParameterTests.cs @@ -27,6 +27,7 @@ // 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA using NUnit.Framework; +using NUnit.Framework.Legacy; using System; using System.Data; diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/ReplicationTests.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/ReplicationTests.cs index c25ee2aca..7f9f37d80 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/ReplicationTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/ReplicationTests.cs @@ -27,6 +27,7 @@ // 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA using NUnit.Framework; +using NUnit.Framework.Legacy; namespace MySql.Data.MySqlClient.Tests { diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/ThreadingTests.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/ThreadingTests.cs index 2c297992b..865d0c484 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/ThreadingTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/ThreadingTests.cs @@ -28,6 +28,7 @@ using System; using NUnit.Framework; +using NUnit.Framework.Legacy; using System.Threading; using System.Collections; diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/TimeoutAndCancel.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/TimeoutAndCancel.cs index 48a894fc5..be448303a 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/TimeoutAndCancel.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/TimeoutAndCancel.cs @@ -28,6 +28,7 @@ using System; using NUnit.Framework; +using NUnit.Framework.Legacy; using System.Threading; using System.Data; using System.Globalization; diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/TypeTests.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/TypeTests.cs index b2271bed1..b64e74f6f 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/TypeTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/TypeTests.cs @@ -27,6 +27,7 @@ // 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA using NUnit.Framework; +using NUnit.Framework.Legacy; using MySql.Data.Types; using System.IO; diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/UsageAdvisorTests.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/UsageAdvisorTests.cs index 06cf54f96..5ac06fdc8 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/UsageAdvisorTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/UsageAdvisorTests.cs @@ -27,6 +27,7 @@ // 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA using NUnit.Framework; +using NUnit.Framework.Legacy; using System.Diagnostics; using System; diff --git a/MySQL.Data/tests/MySql.Data.Tests/LoggingTests.cs b/MySQL.Data/tests/MySql.Data.Tests/LoggingTests.cs index 7fe068944..f5b437ce5 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/LoggingTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/LoggingTests.cs @@ -29,6 +29,7 @@ using System; using System.Text; using NUnit.Framework; +using NUnit.Framework.Legacy; using System.Diagnostics; namespace MySql.Data.MySqlClient.Tests diff --git a/MySQL.Data/tests/MySql.Data.Tests/MySql.Data.Tests.csproj b/MySQL.Data/tests/MySql.Data.Tests/MySql.Data.Tests.csproj index ab9a2c1ee..0de26db87 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/MySql.Data.Tests.csproj +++ b/MySQL.Data/tests/MySql.Data.Tests/MySql.Data.Tests.csproj @@ -60,10 +60,9 @@ - - - - + + + diff --git a/MySQL.Data/tests/MySql.Data.Tests/MySqlBulkLoaderTests.cs b/MySQL.Data/tests/MySql.Data.Tests/MySqlBulkLoaderTests.cs index 5e0c8bb56..869f11e03 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/MySqlBulkLoaderTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/MySqlBulkLoaderTests.cs @@ -27,6 +27,7 @@ // 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA using NUnit.Framework; +using NUnit.Framework.Legacy; using System; using System.Data; using System.IO; diff --git a/MySQL.Data/tests/MySql.Data.Tests/MySqlDataReaderTests.cs b/MySQL.Data/tests/MySql.Data.Tests/MySqlDataReaderTests.cs index 530c91c6e..9ebad9a27 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/MySqlDataReaderTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/MySqlDataReaderTests.cs @@ -28,6 +28,7 @@ using MySql.Data.Common; using NUnit.Framework; +using NUnit.Framework.Legacy; using System; using System.Data; using System.Data.SqlTypes; diff --git a/MySQL.Data/tests/MySql.Data.Tests/OutputParametersBatch.cs b/MySQL.Data/tests/MySql.Data.Tests/OutputParametersBatch.cs index 82a1997b9..2f1ddbbee 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/OutputParametersBatch.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/OutputParametersBatch.cs @@ -27,6 +27,7 @@ // 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA using NUnit.Framework; +using NUnit.Framework.Legacy; using System; using System.Data; diff --git a/MySQL.Data/tests/MySql.Data.Tests/ParameterTests.cs b/MySQL.Data/tests/MySql.Data.Tests/ParameterTests.cs index 75229f3fc..41448db0a 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/ParameterTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/ParameterTests.cs @@ -27,6 +27,7 @@ // 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA using NUnit.Framework; +using NUnit.Framework.Legacy; using System; using System.Data; using System.Diagnostics; diff --git a/MySQL.Data/tests/MySql.Data.Tests/PoolingTests.cs b/MySQL.Data/tests/MySql.Data.Tests/PoolingTests.cs index 910f73016..5ad5212e1 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/PoolingTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/PoolingTests.cs @@ -28,6 +28,7 @@ using MySql.Data.Common; using NUnit.Framework; +using NUnit.Framework.Legacy; using System; using System.Collections.Generic; using System.Data; diff --git a/MySQL.Data/tests/MySql.Data.Tests/PreparedStatements.cs b/MySQL.Data/tests/MySql.Data.Tests/PreparedStatements.cs index c7370fbad..9c0e94a3f 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/PreparedStatements.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/PreparedStatements.cs @@ -27,6 +27,7 @@ // 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA using NUnit.Framework; +using NUnit.Framework.Legacy; using System; using System.Data; using System.Linq; diff --git a/MySQL.Data/tests/MySql.Data.Tests/ScriptExecution.cs b/MySQL.Data/tests/MySql.Data.Tests/ScriptExecution.cs index 585edd440..b6d5b6f42 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/ScriptExecution.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/ScriptExecution.cs @@ -30,6 +30,7 @@ using System.Text; using System.Threading.Tasks; using NUnit.Framework; +using NUnit.Framework.Legacy; namespace MySql.Data.MySqlClient.Tests { diff --git a/MySQL.Data/tests/MySql.Data.Tests/SimpleTransactions.cs b/MySQL.Data/tests/MySql.Data.Tests/SimpleTransactions.cs index 01254868e..bea676d27 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/SimpleTransactions.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/SimpleTransactions.cs @@ -28,6 +28,7 @@ using System; using NUnit.Framework; +using NUnit.Framework.Legacy; using System.Data; using System.Reflection; diff --git a/MySQL.Data/tests/MySql.Data.Tests/SqlServerMode.cs b/MySQL.Data/tests/MySql.Data.Tests/SqlServerMode.cs index e81985b5d..c3129f6bd 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/SqlServerMode.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/SqlServerMode.cs @@ -27,6 +27,7 @@ // 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA using NUnit.Framework; +using NUnit.Framework.Legacy; namespace MySql.Data.MySqlClient.Tests { diff --git a/MySQL.Data/tests/MySql.Data.Tests/SslTests.cs b/MySQL.Data/tests/MySql.Data.Tests/SslTests.cs index f91031fa1..5dce64220 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/SslTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/SslTests.cs @@ -29,6 +29,7 @@ using MySql.Data.Common; using MySqlX.XDevAPI; using NUnit.Framework; +using NUnit.Framework.Legacy; using System; using System.Collections.Generic; using System.Data; diff --git a/MySQL.Data/tests/MySql.Data.Tests/StoredProcedure.cs b/MySQL.Data/tests/MySql.Data.Tests/StoredProcedure.cs index ab47cc78b..1a053144b 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/StoredProcedure.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/StoredProcedure.cs @@ -27,6 +27,7 @@ // 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA using NUnit.Framework; +using NUnit.Framework.Legacy; using System; using System.Data; using System.Data.Common; diff --git a/MySQL.Data/tests/MySql.Data.Tests/StoredProcedureWithAccess.cs b/MySQL.Data/tests/MySql.Data.Tests/StoredProcedureWithAccess.cs index ba50c3390..e0d2b4fa2 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/StoredProcedureWithAccess.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/StoredProcedureWithAccess.cs @@ -30,6 +30,7 @@ using System.Collections.Generic; using System.Text; using NUnit.Framework; +using NUnit.Framework.Legacy; using System.Data; using System.Globalization; diff --git a/MySQL.Data/tests/MySql.Data.Tests/StressTests.cs b/MySQL.Data/tests/MySql.Data.Tests/StressTests.cs index 6e65b4852..66a4334ff 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/StressTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/StressTests.cs @@ -29,6 +29,7 @@ using System; using System.Threading.Tasks; using NUnit.Framework; +using NUnit.Framework.Legacy; namespace MySql.Data.MySqlClient.Tests { diff --git a/MySQL.Data/tests/MySql.Data.Tests/Syntax.cs b/MySQL.Data/tests/MySql.Data.Tests/Syntax.cs index 5a59e9bba..23b31e307 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Syntax.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Syntax.cs @@ -27,6 +27,7 @@ // 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA using NUnit.Framework; +using NUnit.Framework.Legacy; using System; using System.Data; using System.IO; diff --git a/MySQL.Data/tests/MySql.Data.Tests/Syntax2.cs b/MySQL.Data/tests/MySql.Data.Tests/Syntax2.cs index 253a68a9a..15a090262 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Syntax2.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Syntax2.cs @@ -27,6 +27,7 @@ // 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA using NUnit.Framework; +using NUnit.Framework.Legacy; using System; using System.Data; diff --git a/MySQL.Data/tests/MySql.Data.Tests/TableCaching.cs b/MySQL.Data/tests/MySql.Data.Tests/TableCaching.cs index 32bebd7b8..68eefe76b 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/TableCaching.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/TableCaching.cs @@ -27,6 +27,7 @@ // 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA using NUnit.Framework; +using NUnit.Framework.Legacy; using System.Data; using System.Threading; using System.Diagnostics; diff --git a/MySQL.Data/tests/MySql.Data.Tests/TestBase.cs b/MySQL.Data/tests/MySql.Data.Tests/TestBase.cs index 35e44a965..ecd20ef18 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/TestBase.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/TestBase.cs @@ -28,6 +28,7 @@ using MySql.Data.Common; using NUnit.Framework; +using NUnit.Framework.Legacy; using System; using System.Data; using System.Diagnostics; diff --git a/MySQL.Data/tests/MySql.Data.Tests/Tokenizer.cs b/MySQL.Data/tests/MySql.Data.Tests/Tokenizer.cs index 54cf1dc71..a8a0b83f5 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Tokenizer.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Tokenizer.cs @@ -28,6 +28,7 @@ using System; using NUnit.Framework; +using NUnit.Framework.Legacy; namespace MySql.Data.MySqlClient.Tests { diff --git a/MySQL.Data/tests/MySql.Data.Tests/Transactions.cs b/MySQL.Data/tests/MySql.Data.Tests/Transactions.cs index 7f79e875a..665f677ed 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Transactions.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Transactions.cs @@ -27,6 +27,7 @@ // 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA using NUnit.Framework; +using NUnit.Framework.Legacy; using System; using System.Data; using System.Data.Common; diff --git a/MySQL.Data/tests/MySql.Data.Tests/UnixSockets.cs b/MySQL.Data/tests/MySql.Data.Tests/UnixSockets.cs index ce5b4ff3d..ce79a457a 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/UnixSockets.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/UnixSockets.cs @@ -28,6 +28,7 @@ using MySql.Data.Common; using NUnit.Framework; +using NUnit.Framework.Legacy; using System; using System.Data; diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/BaseTest.cs b/MySQL.Data/tests/MySqlX.Data.Tests/BaseTest.cs index ac30710f4..cec0bfdd2 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/BaseTest.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/BaseTest.cs @@ -32,6 +32,7 @@ using MySqlX.XDevAPI.CRUD; using MySqlX.XDevAPI.Relational; using NUnit.Framework; +using NUnit.Framework.Legacy; using System; using System.Data; using System.IO; diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/BasicFindTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/BasicFindTests.cs index 6c0f85bb9..6bb3b881b 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/BasicFindTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/BasicFindTests.cs @@ -32,6 +32,7 @@ using MySqlX.XDevAPI.Common; using MySqlX.XDevAPI.CRUD; using NUnit.Framework; +using NUnit.Framework.Legacy; using System; namespace MySqlX.Data.Tests diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/BasicSelectTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/BasicSelectTests.cs index 4f5c64bf3..0037b7cb0 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/BasicSelectTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/BasicSelectTests.cs @@ -31,6 +31,7 @@ using MySqlX.XDevAPI.Relational; using System; using NUnit.Framework; +using NUnit.Framework.Legacy; namespace MySqlX.Data.Tests { diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/CharsetAndCollationTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/CharsetAndCollationTests.cs index a32cf7065..d0d1090cf 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/CharsetAndCollationTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/CharsetAndCollationTests.cs @@ -31,6 +31,7 @@ using MySqlX.XDevAPI; using MySqlX.XDevAPI.Relational; using NUnit.Framework; +using NUnit.Framework.Legacy; using System; using System.Collections.Generic; using System.Linq; diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/ClientSideFailoverTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/ClientSideFailoverTests.cs index f6f525b95..1a8ac5077 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/ClientSideFailoverTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/ClientSideFailoverTests.cs @@ -31,6 +31,7 @@ using MySql.Data.MySqlClient; using MySqlX.XDevAPI; using NUnit.Framework; +using NUnit.Framework.Legacy; using System; using System.Collections.Generic; diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/ClientTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/ClientTests.cs index 522035522..3b981419d 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/ClientTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/ClientTests.cs @@ -33,6 +33,7 @@ using MySqlX.XDevAPI.Common; using MySqlX.XDevAPI.Relational; using NUnit.Framework; +using NUnit.Framework.Legacy; using System; using System.Collections.Generic; using System.Diagnostics; diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/CloseConnectionTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/CloseConnectionTests.cs index e1ccd486f..46afde1da 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/CloseConnectionTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/CloseConnectionTests.cs @@ -30,6 +30,7 @@ using MySql.Data.MySqlClient; using MySqlX.XDevAPI; using NUnit.Framework; +using NUnit.Framework.Legacy; using System; using System.Diagnostics; using System.Threading; diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/CollectionAsyncTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/CollectionAsyncTests.cs index 3a9d9f8c0..6c9c393df 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/CollectionAsyncTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/CollectionAsyncTests.cs @@ -30,6 +30,7 @@ using MySqlX.XDevAPI.Common; using MySqlX.XDevAPI.CRUD; using NUnit.Framework; +using NUnit.Framework.Legacy; using System; using System.Collections.Generic; using System.Threading; diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/CollectionIndexTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/CollectionIndexTests.cs index 4a2a6f264..df880847c 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/CollectionIndexTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/CollectionIndexTests.cs @@ -31,6 +31,7 @@ using MySqlX.XDevAPI.Common; using MySqlX.XDevAPI.CRUD; using NUnit.Framework; +using NUnit.Framework.Legacy; using System; using System.Threading; using System.Threading.Tasks; diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/CollectionTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/CollectionTests.cs index 80d9f73aa..00d73b3d8 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/CollectionTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/CollectionTests.cs @@ -32,6 +32,7 @@ using MySqlX.XDevAPI.Common; using MySqlX.XDevAPI.Relational; using NUnit.Framework; +using NUnit.Framework.Legacy; using System; using System.Collections.Generic; using System.Linq; diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/CompressionTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/CompressionTests.cs index edec20eb6..16a94cfd2 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/CompressionTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/CompressionTests.cs @@ -31,6 +31,7 @@ using MySqlX.Common; using MySqlX.XDevAPI; using NUnit.Framework; +using NUnit.Framework.Legacy; using System; using System.Collections.Generic; using System.Diagnostics; diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/CrudInsertTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/CrudInsertTests.cs index 7532e8be4..aa5bcd253 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/CrudInsertTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/CrudInsertTests.cs @@ -35,6 +35,7 @@ using MySqlX.XDevAPI.CRUD; using MySqlX.XDevAPI.Relational; using NUnit.Framework; +using NUnit.Framework.Legacy; using System; using System.Collections.Generic; using System.Linq; diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/CrudRemoveTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/CrudRemoveTests.cs index b2736ef38..d6dc7081e 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/CrudRemoveTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/CrudRemoveTests.cs @@ -29,6 +29,7 @@ using MySqlX.XDevAPI; using MySqlX.XDevAPI.Common; using NUnit.Framework; +using NUnit.Framework.Legacy; using System; using System.Collections.Generic; diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/CrudTests/CrudGCTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/CrudTests/CrudGCTests.cs index c44326e07..5b181c9bb 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/CrudTests/CrudGCTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/CrudTests/CrudGCTests.cs @@ -30,6 +30,7 @@ using MySqlX.XDevAPI.Common; using System; using NUnit.Framework; +using NUnit.Framework.Legacy; namespace MySqlX.Data.Tests.ResultTests { diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/CrudTests/DocBufferingTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/CrudTests/DocBufferingTests.cs index 43eb2665f..968fb8b8b 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/CrudTests/DocBufferingTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/CrudTests/DocBufferingTests.cs @@ -29,6 +29,7 @@ using MySqlX.XDevAPI; using MySqlX.XDevAPI.Common; using NUnit.Framework; +using NUnit.Framework.Legacy; namespace MySqlX.Data.Tests.CrudTests { diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/CrudUpdateTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/CrudUpdateTests.cs index ba5ed2dd5..b5abd79a6 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/CrudUpdateTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/CrudUpdateTests.cs @@ -30,6 +30,7 @@ using MySqlX.XDevAPI; using MySqlX.XDevAPI.Common; using NUnit.Framework; +using NUnit.Framework.Legacy; using System; using System.Collections.Generic; diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/CustomTypeTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/CustomTypeTests.cs index 33c98ecc6..ba9a17c37 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/CustomTypeTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/CustomTypeTests.cs @@ -29,6 +29,7 @@ using MySqlX.XDevAPI; using MySqlX.XDevAPI.Common; using NUnit.Framework; +using NUnit.Framework.Legacy; using System; using System.Collections.Generic; using System.Threading.Tasks; diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/DbDocTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/DbDocTests.cs index 36c5e8902..e2acbd9fa 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/DbDocTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/DbDocTests.cs @@ -29,6 +29,7 @@ using MySqlX.XDevAPI; using System; using NUnit.Framework; +using NUnit.Framework.Legacy; namespace MySqlX.Data.Tests { diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/DnsSrvTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/DnsSrvTests.cs index ae65cc357..301471910 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/DnsSrvTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/DnsSrvTests.cs @@ -29,6 +29,7 @@ using MySql.Data.MySqlClient; using MySqlX.XDevAPI; using NUnit.Framework; +using NUnit.Framework.Legacy; using System; namespace MySqlX.Data.Tests diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/ExprParserTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/ExprParserTests.cs index a251cc660..89426bba8 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/ExprParserTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/ExprParserTests.cs @@ -34,6 +34,7 @@ using System.Collections.Generic; using System.Linq; using NUnit.Framework; +using NUnit.Framework.Legacy; namespace MySqlX.Data.Tests { diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/JsonParserTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/JsonParserTests.cs index e7a1b9482..e12dee9f7 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/JsonParserTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/JsonParserTests.cs @@ -31,6 +31,7 @@ using System; using System.Collections.Generic; using NUnit.Framework; +using NUnit.Framework.Legacy; namespace MySqlX.Data.Tests { diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/MergePatch.cs b/MySQL.Data/tests/MySqlX.Data.Tests/MergePatch.cs index 6caeeeadd..c0097e85b 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/MergePatch.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/MergePatch.cs @@ -32,6 +32,7 @@ using System; using System.Collections.Generic; using NUnit.Framework; +using NUnit.Framework.Legacy; namespace MySqlX.Data.Tests { diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/MySqlX.Data.Tests.csproj b/MySQL.Data/tests/MySqlX.Data.Tests/MySqlX.Data.Tests.csproj index 76a1d4a15..16fa0020c 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/MySqlX.Data.Tests.csproj +++ b/MySQL.Data/tests/MySqlX.Data.Tests/MySqlX.Data.Tests.csproj @@ -62,10 +62,9 @@ - - - - + + + diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/PreparedStatementsTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/PreparedStatementsTests.cs index 4da250cef..e2af9b591 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/PreparedStatementsTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/PreparedStatementsTests.cs @@ -33,6 +33,7 @@ using MySqlX.XDevAPI.CRUD; using MySqlX.XDevAPI.Relational; using NUnit.Framework; +using NUnit.Framework.Legacy; using System; using System.Collections.Generic; using System.Threading.Tasks; diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/ColumnMetadataTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/ColumnMetadataTests.cs index 5efb99a58..fa37af35e 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/ColumnMetadataTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/ColumnMetadataTests.cs @@ -30,6 +30,7 @@ using MySql.Data.MySqlClient.X.XDevAPI.Common; using MySqlX.XDevAPI.Relational; using NUnit.Framework; +using NUnit.Framework.Legacy; namespace MySqlX.Data.Tests.RelationalTests { diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/DataTypeTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/DataTypeTests.cs index 62245811d..4e76036a7 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/DataTypeTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/DataTypeTests.cs @@ -30,6 +30,7 @@ using MySql.Data.MySqlClient.X.XDevAPI.Common; using MySqlX.XDevAPI.Relational; using NUnit.Framework; +using NUnit.Framework.Legacy; using System; namespace MySqlX.Data.Tests.RelationalTests diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/DateTimeTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/DateTimeTests.cs index 1894b9040..8ae4ee483 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/DateTimeTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/DateTimeTests.cs @@ -29,6 +29,7 @@ using MySql.Data.MySqlClient.X.XDevAPI.Common; using MySqlX.XDevAPI.Relational; using NUnit.Framework; +using NUnit.Framework.Legacy; using System; namespace MySqlX.Data.Tests.RelationalTests diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/RelationalGCTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/RelationalGCTests.cs index 40dac96ae..34d1aaa12 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/RelationalGCTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/RelationalGCTests.cs @@ -29,6 +29,7 @@ using MySqlX.XDevAPI.Relational; using System; using NUnit.Framework; +using NUnit.Framework.Legacy; namespace MySqlX.Data.Tests.ResultTests { diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/RowBufferingTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/RowBufferingTests.cs index 0f4e02f1e..3809bb29b 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/RowBufferingTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/RowBufferingTests.cs @@ -28,6 +28,7 @@ using MySqlX.XDevAPI.Relational; using NUnit.Framework; +using NUnit.Framework.Legacy; namespace MySqlX.Data.Tests.RelationalTests { diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/SqlTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/SqlTests.cs index c6bdb2cbd..4ffb01a71 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/SqlTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/SqlTests.cs @@ -32,6 +32,7 @@ using MySqlX.XDevAPI; using MySqlX.XDevAPI.Relational; using NUnit.Framework; +using NUnit.Framework.Legacy; using System.Collections.Generic; namespace MySqlX.Data.Tests.RelationalTests diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/TableAsyncTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/TableAsyncTests.cs index 29cfb61b3..c071fecbb 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/TableAsyncTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/TableAsyncTests.cs @@ -31,6 +31,7 @@ using MySqlX.XDevAPI.Common; using MySqlX.XDevAPI.Relational; using NUnit.Framework; +using NUnit.Framework.Legacy; using System; using System.Collections.Generic; using System.Threading; diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/TableDeleteTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/TableDeleteTests.cs index 7f0564253..508eefec0 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/TableDeleteTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/TableDeleteTests.cs @@ -30,6 +30,7 @@ using MySqlX.XDevAPI.Common; using MySqlX.XDevAPI.Relational; using NUnit.Framework; +using NUnit.Framework.Legacy; namespace MySqlX.Data.Tests.RelationalTests { diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/TableInsertTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/TableInsertTests.cs index 5d1ad8320..d831154fd 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/TableInsertTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/TableInsertTests.cs @@ -29,6 +29,7 @@ using MySql.Data.MySqlClient; using MySqlX.XDevAPI.Relational; using NUnit.Framework; +using NUnit.Framework.Legacy; using System.Linq; namespace MySqlX.Data.Tests.RelationalTests diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/TableSelectTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/TableSelectTests.cs index f16f24d4c..693435fc1 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/TableSelectTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/TableSelectTests.cs @@ -32,6 +32,7 @@ using MySqlX.XDevAPI.Common; using MySqlX.XDevAPI.Relational; using NUnit.Framework; +using NUnit.Framework.Legacy; using System; using System.Linq; using System.Text; diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/TableUpdateTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/TableUpdateTests.cs index ab9946777..5ea8882b3 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/TableUpdateTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/TableUpdateTests.cs @@ -30,6 +30,7 @@ using MySqlX.XDevAPI.Common; using MySqlX.XDevAPI.Relational; using NUnit.Framework; +using NUnit.Framework.Legacy; using System; using System.Collections.Generic; using MySqlX.XDevAPI; diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/ViewTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/ViewTests.cs index 859193436..3d046bc76 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/ViewTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/ViewTests.cs @@ -29,6 +29,7 @@ using MySql.Data.MySqlClient; using MySqlX.XDevAPI.Relational; using NUnit.Framework; +using NUnit.Framework.Legacy; using System.Collections.Generic; using System.Linq; using MySqlX.XDevAPI; diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/SchemaTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/SchemaTests.cs index 517bcac3e..95e68b92d 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/SchemaTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/SchemaTests.cs @@ -31,6 +31,7 @@ using MySqlX.XDevAPI.Common; using MySqlX.XDevAPI.Relational; using NUnit.Framework; +using NUnit.Framework.Legacy; using System; using System.Collections.Generic; using System.Linq; diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/SessionTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/SessionTests.cs index 9d497395e..5d37e3c23 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/SessionTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/SessionTests.cs @@ -32,6 +32,7 @@ using MySqlX.XDevAPI; using MySqlX.XDevAPI.Relational; using NUnit.Framework; +using NUnit.Framework.Legacy; using System; using System.Collections.Generic; using System.Data; diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/SslTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/SslTests.cs index f410728eb..771f58f95 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/SslTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/SslTests.cs @@ -30,6 +30,7 @@ using MySql.Data.MySqlClient; using MySqlX.XDevAPI; using NUnit.Framework; +using NUnit.Framework.Legacy; using System; using System.Collections.Generic; diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/TransactionTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/TransactionTests.cs index bcd4d6266..092aa057e 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/TransactionTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/TransactionTests.cs @@ -32,6 +32,7 @@ using MySqlX.XDevAPI.CRUD; using MySqlX.XDevAPI.Relational; using NUnit.Framework; +using NUnit.Framework.Legacy; using System; using System.Linq; diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/UnixSocketsTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/UnixSocketsTests.cs index 89e41fa4e..680642278 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/UnixSocketsTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/UnixSocketsTests.cs @@ -30,6 +30,7 @@ using MySql.Data.MySqlClient; using MySqlX.XDevAPI; using NUnit.Framework; +using NUnit.Framework.Legacy; using System; namespace MySqlX.Data.Tests diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/XAuth.cs b/MySQL.Data/tests/MySqlX.Data.Tests/XAuth.cs index fa1dff39e..a5b9d3de9 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/XAuth.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/XAuth.cs @@ -30,6 +30,7 @@ using MySql.Data.MySqlClient; using MySqlX.XDevAPI; using NUnit.Framework; +using NUnit.Framework.Legacy; using System; namespace MySqlX.Data.Tests diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/XConnectionStringBuilderTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/XConnectionStringBuilderTests.cs index bc535e2f0..2df0497af 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/XConnectionStringBuilderTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/XConnectionStringBuilderTests.cs @@ -30,6 +30,7 @@ using MySql.Data.MySqlClient; using MySqlX.XDevAPI; using NUnit.Framework; +using NUnit.Framework.Legacy; using System; using System.Data; diff --git a/MySql.Web/tests/Directory.build.props b/MySql.Web/tests/Directory.build.props new file mode 100644 index 000000000..03b886514 --- /dev/null +++ b/MySql.Web/tests/Directory.build.props @@ -0,0 +1,12 @@ + + + true + + + + + + + + + diff --git a/MySql.Web/tests/MySql.Web.Tests.csproj b/MySql.Web/tests/MySql.Web.Tests.csproj index 6c7042484..4faa9ab0c 100644 --- a/MySql.Web/tests/MySql.Web.Tests.csproj +++ b/MySql.Web/tests/MySql.Web.Tests.csproj @@ -23,6 +23,7 @@ True True ..\..\ConnectorNetPublicKey.snk + latest @@ -30,9 +31,8 @@ - - - + + diff --git a/MySql.Web/tests/PersonalizationTests.cs b/MySql.Web/tests/PersonalizationTests.cs index 3d306323d..23ef47655 100644 --- a/MySql.Web/tests/PersonalizationTests.cs +++ b/MySql.Web/tests/PersonalizationTests.cs @@ -29,6 +29,7 @@ using MySql.Data.MySqlClient; using MySql.Web.Personalization; using NUnit.Framework; +using NUnit.Framework.Legacy; using System; using System.Collections.Specialized; using System.Web.UI.WebControls.WebParts; diff --git a/MySql.Web/tests/ProfileTests.cs b/MySql.Web/tests/ProfileTests.cs index fa0d2157d..f1ac081ba 100644 --- a/MySql.Web/tests/ProfileTests.cs +++ b/MySql.Web/tests/ProfileTests.cs @@ -28,6 +28,7 @@ using MySql.Web.Profile; using NUnit.Framework; +using NUnit.Framework.Legacy; using System; using System.Collections.Specialized; using System.Configuration; diff --git a/MySql.Web/tests/RoleManagement.cs b/MySql.Web/tests/RoleManagement.cs index 3990e7634..764b43da1 100644 --- a/MySql.Web/tests/RoleManagement.cs +++ b/MySql.Web/tests/RoleManagement.cs @@ -28,6 +28,7 @@ using MySql.Web.Security; using NUnit.Framework; +using NUnit.Framework.Legacy; using System; using System.Collections.Specialized; using System.Web.Security; diff --git a/MySql.Web/tests/SchemaManagerTests.cs b/MySql.Web/tests/SchemaManagerTests.cs index 4aedebf96..a8304eb16 100644 --- a/MySql.Web/tests/SchemaManagerTests.cs +++ b/MySql.Web/tests/SchemaManagerTests.cs @@ -30,6 +30,7 @@ using MySql.Web.Common; using MySql.Web.Security; using NUnit.Framework; +using NUnit.Framework.Legacy; using System; using System.Collections.Specialized; using System.Configuration.Provider; diff --git a/MySql.Web/tests/SchemaTests.cs b/MySql.Web/tests/SchemaTests.cs index 5ff9c8f65..71f8bf050 100644 --- a/MySql.Web/tests/SchemaTests.cs +++ b/MySql.Web/tests/SchemaTests.cs @@ -30,6 +30,7 @@ using MySql.Web.Common; using MySql.Web.Security; using NUnit.Framework; +using NUnit.Framework.Legacy; using System.Collections.Specialized; using System.Configuration.Provider; using System.Data; diff --git a/MySql.Web/tests/SessionTests.cs b/MySql.Web/tests/SessionTests.cs index efdf692cc..51418899c 100644 --- a/MySql.Web/tests/SessionTests.cs +++ b/MySql.Web/tests/SessionTests.cs @@ -29,6 +29,7 @@ using MySql.Data.MySqlClient; using MySql.Web.SessionState; using NUnit.Framework; +using NUnit.Framework.Legacy; using System; using System.Collections.Specialized; using System.Configuration; diff --git a/MySql.Web/tests/SimpleMembership.cs b/MySql.Web/tests/SimpleMembership.cs index 12e785d3e..d76ba9cfe 100644 --- a/MySql.Web/tests/SimpleMembership.cs +++ b/MySql.Web/tests/SimpleMembership.cs @@ -29,6 +29,7 @@ using MySql.Data.MySqlClient; using MySql.Web.Security; using NUnit.Framework; +using NUnit.Framework.Legacy; using System; using System.Collections.Specialized; using System.Web.Security; diff --git a/MySql.Web/tests/SiteMapTests.cs b/MySql.Web/tests/SiteMapTests.cs index c288f9458..1e66800c6 100644 --- a/MySql.Web/tests/SiteMapTests.cs +++ b/MySql.Web/tests/SiteMapTests.cs @@ -29,6 +29,7 @@ using MySql.Data.MySqlClient; using MySql.Web.SiteMap; using NUnit.Framework; +using NUnit.Framework.Legacy; using System; using System.Collections.Specialized; using System.IO; diff --git a/MySql.Web/tests/UserManagement.cs b/MySql.Web/tests/UserManagement.cs index 5bbffb3f9..0c312bbbf 100644 --- a/MySql.Web/tests/UserManagement.cs +++ b/MySql.Web/tests/UserManagement.cs @@ -29,6 +29,7 @@ using MySql.Data.MySqlClient; using MySql.Web.Security; using NUnit.Framework; +using NUnit.Framework.Legacy; using System; using System.Collections.Specialized; using System.Configuration.Provider; diff --git a/MySql.Web/tests/WebTestBase.cs b/MySql.Web/tests/WebTestBase.cs index 8e3153569..9b8d09355 100644 --- a/MySql.Web/tests/WebTestBase.cs +++ b/MySql.Web/tests/WebTestBase.cs @@ -31,6 +31,7 @@ using MySql.Web.Common; using MySql.Web.Security; using NUnit.Framework; +using NUnit.Framework.Legacy; using System; using System.Configuration; using System.Data; From dd51a525b6c097cdf81ede81ba176d7177c97d4e Mon Sep 17 00:00:00 2001 From: Reggie Burnett Date: Thu, 14 Mar 2024 11:44:26 -0500 Subject: [PATCH 042/125] WL#16280 [Remove OldGetStringBehavior workaround] Change-Id: Id33222f0e00411a98575a7fff0a556fd29bed9b1 --- CHANGES | 3 +- .../src/MySqlConnectionStringBuilder.cs | 14 -------- MySQL.Data/src/MySqlDataReader.cs | 12 +------ .../tests/MySql.Data.Tests/DataTypeTests.cs | 32 ------------------- 4 files changed, 3 insertions(+), 58 deletions(-) diff --git a/CHANGES b/CHANGES index d29099ec1..9f75566a0 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,7 @@ 9.0.0 - Updated NUnit to 4.x (WL16279) - +- Removed deprecated OldGetStringBehavior option (WL16280) + 8.4.0 - Updated FOSS license text in all source files (WL16197). - Fixed bug Shared memory connection doesn't work in multithread environment (Oracle Bug #36208932). diff --git a/MySQL.Data/src/MySqlConnectionStringBuilder.cs b/MySQL.Data/src/MySqlConnectionStringBuilder.cs index 200615948..0a5d60e11 100644 --- a/MySQL.Data/src/MySqlConnectionStringBuilder.cs +++ b/MySQL.Data/src/MySqlConnectionStringBuilder.cs @@ -241,9 +241,6 @@ static MySqlConnectionStringBuilder() (msb, sender, value) => { msb.SetValue("blobasutf8excludepattern", value); }, (msb, sender) => msb.BlobAsUTF8ExcludePattern)); #endregion - - Options.Add(new MySqlConnectionStringOption("oldgetstringbehavior", null, typeof(bool), false, true, - (msb, sender, value) => { msb.SetValue("oldgetstringbehavior", value); }, (msb, sender) => msb.OldGetStringBehavior)); } /// @@ -1012,17 +1009,6 @@ public bool UseDefaultCommandTimeoutForEF } #endregion - [DisplayName("Use the old GetString behavior for readers")] - [Category("Backwards Compatibility")] - [Description("When true, MySqlDataReader.GetString will return a string version of every possible data type")] - [DefaultValue(false)] - [Obsolete("This property is only used to provide old behavior. This option and the old behavior will be removed in 9.0")] - public bool OldGetStringBehavior - { - get { return (bool)values["oldgetstringbehavior"]; } - set { SetValue("oldgetstringbehavior", value); } - } - /// /// Gets or sets a connection option. /// diff --git a/MySQL.Data/src/MySqlDataReader.cs b/MySQL.Data/src/MySqlDataReader.cs index b878c56d8..32a441b48 100644 --- a/MySQL.Data/src/MySqlDataReader.cs +++ b/MySQL.Data/src/MySqlDataReader.cs @@ -919,17 +919,7 @@ public override String GetString(int i) { IMySqlValue val = GetFieldValue(i, true); - if (!_connection.Settings.OldGetStringBehavior) - return (string)val.Value; - - - if (val is MySqlBinary) - { - byte[] v = ((MySqlBinary)val).Value; - return ResultSet.Fields[i].Encoding.GetString(v, 0, v.Length); - } - - return val.Value.ToString(); + return (string)val.Value; } /// diff --git a/MySQL.Data/tests/MySql.Data.Tests/DataTypeTests.cs b/MySQL.Data/tests/MySql.Data.Tests/DataTypeTests.cs index 4f2c02e76..25b9e198c 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/DataTypeTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/DataTypeTests.cs @@ -1661,38 +1661,6 @@ public void GetIntForTinyInt(bool treatAsBool, bool isPrepared) Assert.AreEqual(treatAsBool ? 1 : -2, reader.GetFieldValue(0)); } - [Test] - public void OldGetStringBehaviorOff() - { - ExecuteSQL(@"CREATE TABLE Test (value1 int, value2 DATETIME); INSERT INTO Test VALUES (1, '2023-10-30');"); - - using var cmd = new MySqlCommand(); - cmd.Connection = Connection; - cmd.CommandText = "SELECT * FROM Test"; - using var reader = cmd.ExecuteReader(); - reader.Read(); - Assert.Throws(() => reader.GetString(0)); - Assert.Throws(() => reader.GetString(1)); - } - - [Test] - public void OldGetStringBehaviorOn() - { - ExecuteSQL(@"CREATE TABLE Test (value1 int, value2 DECIMAL(10,2)); INSERT INTO Test VALUES (1, 20.4);"); - - string connString = Connection.ConnectionString + $";oldgetstringbehavior=true;"; - using var conn = new MySqlConnection(connString); - conn.Open(); - - using var cmd = new MySqlCommand(); - cmd.Connection = conn; - cmd.CommandText = "SELECT * FROM Test"; - using var reader = cmd.ExecuteReader(); - reader.Read(); - Assert.AreEqual("1", reader.GetString(0)); - Assert.AreEqual("20.40", reader.GetString(1)); - } - [Test] public void BadVectorDataThrowsException() { From fd5b1f44b3641fdeef08fab240ac946896552739 Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Wed, 1 May 2024 18:30:45 -0600 Subject: [PATCH 043/125] WL#16279 [Migrate to NUnit 4.x] - Added NUnit test adapter package Change-Id: I72b0eb5b4982e1f0e4c7c98264865d3e57d1bebe --- .../MySql.EntityFrameworkCore.Basic.Tests.csproj | 1 + .../MySql.EntityFrameworkCore.Design.Tests.csproj | 1 + .../MySql.EntityFrameworkCore.Migrations.Tests.csproj | 1 + MySQL.Data/tests/MySql.Data.Tests/MySql.Data.Tests.csproj | 1 + MySQL.Data/tests/MySqlX.Data.Tests/MySqlX.Data.Tests.csproj | 1 + MySql.Web/tests/MySql.Web.Tests.csproj | 1 + 6 files changed, 6 insertions(+) diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/MySql.EntityFrameworkCore.Basic.Tests.csproj b/EFCore/tests/MySql.EFCore.Basic.Tests/MySql.EntityFrameworkCore.Basic.Tests.csproj index 4df134a7a..ad5d720ab 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/MySql.EntityFrameworkCore.Basic.Tests.csproj +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/MySql.EntityFrameworkCore.Basic.Tests.csproj @@ -28,6 +28,7 @@ + diff --git a/EFCore/tests/MySql.EFCore.Design.Tests/MySql.EntityFrameworkCore.Design.Tests.csproj b/EFCore/tests/MySql.EFCore.Design.Tests/MySql.EntityFrameworkCore.Design.Tests.csproj index e95a51ffc..e46a6a2bc 100644 --- a/EFCore/tests/MySql.EFCore.Design.Tests/MySql.EntityFrameworkCore.Design.Tests.csproj +++ b/EFCore/tests/MySql.EFCore.Design.Tests/MySql.EntityFrameworkCore.Design.Tests.csproj @@ -27,6 +27,7 @@ + diff --git a/EFCore/tests/MySql.EFCore.Migrations.Tests/MySql.EntityFrameworkCore.Migrations.Tests.csproj b/EFCore/tests/MySql.EFCore.Migrations.Tests/MySql.EntityFrameworkCore.Migrations.Tests.csproj index e82a9bb8c..fcf790362 100644 --- a/EFCore/tests/MySql.EFCore.Migrations.Tests/MySql.EntityFrameworkCore.Migrations.Tests.csproj +++ b/EFCore/tests/MySql.EFCore.Migrations.Tests/MySql.EntityFrameworkCore.Migrations.Tests.csproj @@ -16,6 +16,7 @@ + diff --git a/MySQL.Data/tests/MySql.Data.Tests/MySql.Data.Tests.csproj b/MySQL.Data/tests/MySql.Data.Tests/MySql.Data.Tests.csproj index 0de26db87..7fc50c885 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/MySql.Data.Tests.csproj +++ b/MySQL.Data/tests/MySql.Data.Tests/MySql.Data.Tests.csproj @@ -62,6 +62,7 @@ + diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/MySqlX.Data.Tests.csproj b/MySQL.Data/tests/MySqlX.Data.Tests/MySqlX.Data.Tests.csproj index 16fa0020c..16e8ca52c 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/MySqlX.Data.Tests.csproj +++ b/MySQL.Data/tests/MySqlX.Data.Tests/MySqlX.Data.Tests.csproj @@ -64,6 +64,7 @@ + diff --git a/MySql.Web/tests/MySql.Web.Tests.csproj b/MySql.Web/tests/MySql.Web.Tests.csproj index 4faa9ab0c..4459f0cf9 100644 --- a/MySql.Web/tests/MySql.Web.Tests.csproj +++ b/MySql.Web/tests/MySql.Web.Tests.csproj @@ -33,6 +33,7 @@ + From 864af89eaebd2f460ac6c941a836275dd9529090 Mon Sep 17 00:00:00 2001 From: Reggie Burnett Date: Wed, 15 May 2024 15:24:43 -0500 Subject: [PATCH 044/125] WL#16387 [Remove MySqlX.Data.Performance.Console.Tests project] Change-Id: I91018c2cc333e8055009cd8d4dcae5077b9e1819 --- CHANGES | 1 + MySQL.Data/MySql.Data.sln | 2 - .../App.config | 6 - .../InstrumentationSession.psess | 122 ------------- ...SqlX.Data.Performance.Console.Tests.csproj | 88 ---------- .../Program.cs | 165 ------------------ .../Properties/AssemblyInfo.cs | 23 --- 7 files changed, 1 insertion(+), 406 deletions(-) delete mode 100644 MySQL.Data/tests/MySqlX.Data.Performance.Console.Tests/App.config delete mode 100644 MySQL.Data/tests/MySqlX.Data.Performance.Console.Tests/InstrumentationSession.psess delete mode 100644 MySQL.Data/tests/MySqlX.Data.Performance.Console.Tests/MySqlX.Data.Performance.Console.Tests.csproj delete mode 100644 MySQL.Data/tests/MySqlX.Data.Performance.Console.Tests/Program.cs delete mode 100644 MySQL.Data/tests/MySqlX.Data.Performance.Console.Tests/Properties/AssemblyInfo.cs diff --git a/CHANGES b/CHANGES index 9f75566a0..1f8e5f379 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,7 @@ 9.0.0 - Updated NUnit to 4.x (WL16279) - Removed deprecated OldGetStringBehavior option (WL16280) +- Remove MySqlX.Data.Performance.Console.Tests project (WL16387) 8.4.0 - Updated FOSS license text in all source files (WL16197). diff --git a/MySQL.Data/MySql.Data.sln b/MySQL.Data/MySql.Data.sln index 5bd527a5a..3d178e566 100644 --- a/MySQL.Data/MySql.Data.sln +++ b/MySQL.Data/MySql.Data.sln @@ -9,8 +9,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MySqlX.Data.Tests", "tests\ EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MySql.Data.Tests", "tests\MySql.Data.Tests\MySql.Data.Tests.csproj", "{951A6C18-E97C-4F6A-A52C-B6FC4DECABAE}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MySqlX.Data.Performance.Console.Tests", "tests\MySqlX.Data.Performance.Console.Tests\MySqlX.Data.Performance.Console.Tests.csproj", "{9D5EDC76-5A1C-46C9-A4F2-CF57F276E537}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU diff --git a/MySQL.Data/tests/MySqlX.Data.Performance.Console.Tests/App.config b/MySQL.Data/tests/MySqlX.Data.Performance.Console.Tests/App.config deleted file mode 100644 index 4bfa00561..000000000 --- a/MySQL.Data/tests/MySqlX.Data.Performance.Console.Tests/App.config +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/MySQL.Data/tests/MySqlX.Data.Performance.Console.Tests/InstrumentationSession.psess b/MySQL.Data/tests/MySqlX.Data.Performance.Console.Tests/InstrumentationSession.psess deleted file mode 100644 index 2937c6df6..000000000 --- a/MySQL.Data/tests/MySqlX.Data.Performance.Console.Tests/InstrumentationSession.psess +++ /dev/null @@ -1,122 +0,0 @@ - - - - ..\..\MySql.Data.sln - Instrumentation - None - Reports\InstrumentationReport.vsp - true - true - Timestamp - Cycles - 10000000 - 10 - 10 - - false - /include:MySqlX.Data.Tests.BaseTest::*;MySqlX.Data.Tests.BasicFindTests::*;MySqlX.Data.Tests.BasicSelectTests::*;MySqlX.Data.Tests.CharsetAndCollationTests::*;MySqlX.Data.Tests.CollectionIndexTests::*;MySqlX.Data.Tests.CollectionTests::*;MySqlX.Data.Tests.CollectionAsyncTests::*;MySqlX.Data.Tests.CrudInsertTests::*;MySqlX.Data.Tests.CrudRemoveTests::*;MySqlX.Data.Tests.CrudUpdateTests::*;MySqlX.Data.Tests.MergePatch::*;MySqlX.Data.Tests.SchemaTests::*;MySqlX.Data.Tests.SessionTests::*;MySqlX.Data.Tests.TransactionTests::*;MySqlX.Data.Tests.ExprParserTests::*;MySqlX.Data.Tests.DbDocTests::*;MySqlX.Data.Tests.JsonParserTests::*;MySqlX.Data.Tests.RelationalTests.ColumnMetadataTests::*;MySqlX.Data.Tests.RelationalTests.DataTypeTests::*;MySqlX.Data.Tests.RelationalTests.RowBufferingTests::*;MySqlX.Data.Tests.RelationalTests.DateTimeTests::*;MySqlX.Data.Tests.RelationalTests.SqlTests::*;MySqlX.Data.Tests.RelationalTests.TableAsyncTests::*;MySqlX.Data.Tests.RelationalTests.TableDeleteTests::*;MySqlX.Data.Tests.RelationalTests.TableInsertTests::*;MySqlX.Data.Tests.RelationalTests.TableSelectTests::*;MySqlX.Data.Tests.RelationalTests.TableUpdateTests::*;MySqlX.Data.Tests.RelationalTests.ViewTests::*;MySqlX.Data.Tests.ResultTests.RelationalGCTests::*;MySqlX.Data.Tests.ResultTests.CrudGCTests::*;MySqlX.Data.Tests.CrudTests.DocBufferingTests::*;MySqlX.Data.Tests.PerformanceTests::*; - - - - false - 500 - - \Memory\Pages/sec - \PhysicalDisk(_Total)\Avg. Disk Queue Length - \Processor(_Total)\% Processor Time - - - - true - false - false - - false - - - false - - - - bin\Release\MySql.Data.dll - 08/17/2018 18:41:24 - true - true - false - false - false - false - false - true - false - Executable - IIS - InternetExplorer - true - false - - false - - - false - - - - bin\Release\MySqlX.Data.Performance.Console.Tests.exe - 08/17/2018 18:41:24 - true - true - false - false - false - false - false - false - true - Executable - bin\Release\MySqlX.Data.Performance.Console.Tests.exe - - - 2 - IIS - InternetExplorer - true - false - - false - - - false - - - - bin\Release\MySqlX.Data.Tests.dll - 08/17/2018 18:41:24 - true - true - false - false - false - false - false - true - false - Executable - IIS - InternetExplorer - true - false - - false - - - false - - - - - - bin\Release\MySqlX.Data.Performance.Console.Tests.exe - - - \ No newline at end of file diff --git a/MySQL.Data/tests/MySqlX.Data.Performance.Console.Tests/MySqlX.Data.Performance.Console.Tests.csproj b/MySQL.Data/tests/MySqlX.Data.Performance.Console.Tests/MySqlX.Data.Performance.Console.Tests.csproj deleted file mode 100644 index 07faa6cef..000000000 --- a/MySQL.Data/tests/MySqlX.Data.Performance.Console.Tests/MySqlX.Data.Performance.Console.Tests.csproj +++ /dev/null @@ -1,88 +0,0 @@ - - - - - Debug - AnyCPU - {9D5EDC76-5A1C-46C9-A4F2-CF57F276E537} - Exe - MySqlX.Data.Performance.Console.Tests - MySqlX.Data.Performance.Console.Tests - v4.8 - 512 - true - publish\ - true - Disk - false - Foreground - 7 - Days - false - false - true - 0 - 1.0.0.%2a - false - false - true - - - AnyCPU - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - AnyCPU - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - - - - - - - - - - - - Properties\VersionInfo.cs - - - - - - - - - - {c411c777-fbe2-4f27-bde1-2b69001320bc} - MySqlX.Data.Tests - - - - - False - Microsoft .NET Framework 4.8 %28x86 and x64%29 - true - - - False - .NET Framework 3.5 SP1 - false - - - - \ No newline at end of file diff --git a/MySQL.Data/tests/MySqlX.Data.Performance.Console.Tests/Program.cs b/MySQL.Data/tests/MySqlX.Data.Performance.Console.Tests/Program.cs deleted file mode 100644 index 74052df56..000000000 --- a/MySQL.Data/tests/MySqlX.Data.Performance.Console.Tests/Program.cs +++ /dev/null @@ -1,165 +0,0 @@ -// Copyright © 2018, 2024, Oracle and/or its affiliates. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License, version 2.0, as -// published by the Free Software Foundation. -// -// This program is designed to work with certain software (including -// but not limited to OpenSSL) that is licensed under separate terms, as -// designated in a particular file or component or in included license -// documentation. The authors of MySQL hereby grant you an additional -// permission to link the program and your derivative works with the -// separately licensed software that they have either included with -// the program or referenced in the documentation. -// -// Without limiting anything contained in the foregoing, this file, -// which is part of MySQL Connector/NET, is also subject to the -// Universal FOSS Exception, version 1.0, a copy of which can be found at -// http://oss.oracle.com/licenses/universal-foss-exception. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License, version 2.0, for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -using System; -using System.Reflection; - -namespace MySqlX.Data.Performance.Console.Tests -{ - public class Program - { - /// - /// Number of times to execute the operation. - /// - private const int EXECUTION_COUNT = 1; - - /// - /// Namespaces. - /// - private const string X_DEVAPI_TESTS_MAIN_NAMESPACE = "MySqlX.Data.Tests"; - private const string X_DEVAPI_RELATIONAL_TESTS_NAMESPACE = "MySqlX.Data.Tests.RelationalTests"; - private const string X_DEVAPI_CRUD_TESTS_NAMESPACE = "MySqlX.Data.Tests.CrudTests"; - private const string X_DEVAPI_RESULT_TESTS_NAMESPACE = "MySqlX.Data.Tests.ResultTests"; - - static void Main(string[] args) - { - if (args.Length > 0) - { - switch (args.Length) - { - case 1: - Program.ExecuteCase(Convert.ToInt32(args[0])); - break; - case 2: - case 3: - Program.ExecuteCase(1, args); - break; - default: - break; - } - } - else - { - System.Console.WriteLine("No arguments were found."); - Program.ExecuteCase(2); - } - - System.Console.WriteLine("Execution completed."); - System.Console.ReadKey(); - } - - static void ExecuteCase(int caseToExecute, string[] args = null) - { - switch (caseToExecute) - { - case 0: - System.Console.WriteLine("Run tests from the PerformanceTests class."); - ExecuteAllClassTests("PerformanceTests", X_DEVAPI_TESTS_MAIN_NAMESPACE, EXECUTION_COUNT); - break; - case 1: - System.Console.WriteLine("Run tests from a specific class."); - ExecuteAllClassTests( - args[0], args.Length == 3 ? - args[1] : X_DEVAPI_TESTS_MAIN_NAMESPACE, - args.Length == 2 ? - Convert.ToInt32(args[1]) : args.Length == 3 ? - Convert.ToInt32(args[2]) : EXECUTION_COUNT); - break; - case 2: - System.Console.WriteLine("Run all unit tests."); - ExecuteAllClassTests("BasicFindTests", X_DEVAPI_TESTS_MAIN_NAMESPACE, EXECUTION_COUNT); - ExecuteAllClassTests("BasicSelectTests", X_DEVAPI_TESTS_MAIN_NAMESPACE, EXECUTION_COUNT); - ExecuteAllClassTests("CharsetAndCollationTests", X_DEVAPI_TESTS_MAIN_NAMESPACE, EXECUTION_COUNT); - ExecuteAllClassTests("CollectionIndexTests", X_DEVAPI_TESTS_MAIN_NAMESPACE, EXECUTION_COUNT); - ExecuteAllClassTests("CollectionTests", X_DEVAPI_TESTS_MAIN_NAMESPACE, EXECUTION_COUNT); - ExecuteAllClassTests("CollectionAsyncTests", X_DEVAPI_TESTS_MAIN_NAMESPACE, EXECUTION_COUNT); - ExecuteAllClassTests("CrudInsertTests", X_DEVAPI_TESTS_MAIN_NAMESPACE, EXECUTION_COUNT); - ExecuteAllClassTests("CrudRemoveTests", X_DEVAPI_TESTS_MAIN_NAMESPACE, EXECUTION_COUNT); - ExecuteAllClassTests("CrudUpdateTests", X_DEVAPI_TESTS_MAIN_NAMESPACE, EXECUTION_COUNT); - ExecuteAllClassTests("MergePatch", X_DEVAPI_TESTS_MAIN_NAMESPACE, EXECUTION_COUNT); - ExecuteAllClassTests("SchemaTests", X_DEVAPI_TESTS_MAIN_NAMESPACE, EXECUTION_COUNT); - ExecuteAllClassTests("SessionTests", X_DEVAPI_TESTS_MAIN_NAMESPACE, EXECUTION_COUNT); - ExecuteAllClassTests("TransactionTests", X_DEVAPI_TESTS_MAIN_NAMESPACE, EXECUTION_COUNT); - ExecuteAllClassTests("ExprParserTests", X_DEVAPI_TESTS_MAIN_NAMESPACE, EXECUTION_COUNT); - ExecuteAllClassTests("DbDocTests", X_DEVAPI_TESTS_MAIN_NAMESPACE, EXECUTION_COUNT); - ExecuteAllClassTests("JsonParserTests", X_DEVAPI_TESTS_MAIN_NAMESPACE, EXECUTION_COUNT); - ExecuteAllClassTests("ColumnMetadataTests", X_DEVAPI_RELATIONAL_TESTS_NAMESPACE, EXECUTION_COUNT); - ExecuteAllClassTests("DataTypeTests", X_DEVAPI_RELATIONAL_TESTS_NAMESPACE, EXECUTION_COUNT); - ExecuteAllClassTests("RowBufferingTests", X_DEVAPI_RELATIONAL_TESTS_NAMESPACE, EXECUTION_COUNT); - ExecuteAllClassTests("DateTimeTests", X_DEVAPI_RELATIONAL_TESTS_NAMESPACE, EXECUTION_COUNT); - ExecuteAllClassTests("SqlTests", X_DEVAPI_RELATIONAL_TESTS_NAMESPACE, EXECUTION_COUNT); - ExecuteAllClassTests("TableAsyncTests", X_DEVAPI_RELATIONAL_TESTS_NAMESPACE, EXECUTION_COUNT); - ExecuteAllClassTests("TableDeleteTests", X_DEVAPI_RELATIONAL_TESTS_NAMESPACE, EXECUTION_COUNT); - ExecuteAllClassTests("TableInsertTests", X_DEVAPI_RELATIONAL_TESTS_NAMESPACE, EXECUTION_COUNT); - ExecuteAllClassTests("TableSelectTests", X_DEVAPI_RELATIONAL_TESTS_NAMESPACE, EXECUTION_COUNT); - ExecuteAllClassTests("TableUpdateTests", X_DEVAPI_RELATIONAL_TESTS_NAMESPACE, EXECUTION_COUNT); - ExecuteAllClassTests("ViewTests", X_DEVAPI_RELATIONAL_TESTS_NAMESPACE, EXECUTION_COUNT); - ExecuteAllClassTests("RelationalGCTests", X_DEVAPI_RESULT_TESTS_NAMESPACE, EXECUTION_COUNT); - ExecuteAllClassTests("CrudGCTests", X_DEVAPI_RESULT_TESTS_NAMESPACE, EXECUTION_COUNT); - ExecuteAllClassTests("DocBufferingTests", X_DEVAPI_CRUD_TESTS_NAMESPACE, EXECUTION_COUNT); - ExecuteAllClassTests("PerformanceTests", X_DEVAPI_TESTS_MAIN_NAMESPACE, EXECUTION_COUNT); - ExecuteAllClassTests("UnixSocketsTests", X_DEVAPI_TESTS_MAIN_NAMESPACE, EXECUTION_COUNT); - ExecuteAllClassTests("ClientSideFailoverTests", X_DEVAPI_TESTS_MAIN_NAMESPACE, EXECUTION_COUNT); - break; - default: - System.Console.WriteLine("Invalid value. Use 0 to execute PerformanceTests tests," + - "1 to execute tests from a specific class or 2 to execute all tests."); - break; - } - } - - static void ExecuteAllClassTests(string className, string nameSpace, int executionCount) - { - System.Console.WriteLine(string.Format("{0} -------------------------- ", className)); - var type = Type.GetType(string.Format("{0}.{1},{2}", nameSpace, className, X_DEVAPI_TESTS_MAIN_NAMESPACE)); - var methodInfos = type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly); - foreach (var methodInfo in methodInfos) - { - int i = 0; - try - { - for (; i < executionCount; i++) - { - methodInfo.Invoke(Activator.CreateInstance(type), null); - } - System.Console.WriteLine(string.Format("\t{0} <-- Success({1})", methodInfo.Name, i)); - } - catch (Exception ex) - { - System.Console.WriteLine(string.Format("\t{0} <-- Not executed({1}): Exception: {2}, Inner exception: {3}", - methodInfo.Name, - i, - ex.Message, - ex.InnerException != null ? - ex.InnerException.Message : - "N/A")); - } - } - } - } -} diff --git a/MySQL.Data/tests/MySqlX.Data.Performance.Console.Tests/Properties/AssemblyInfo.cs b/MySQL.Data/tests/MySqlX.Data.Performance.Console.Tests/Properties/AssemblyInfo.cs deleted file mode 100644 index 32dd847ad..000000000 --- a/MySQL.Data/tests/MySqlX.Data.Performance.Console.Tests/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("MySqlX.Data.Performance.Console.Tests")] -[assembly: AssemblyDescription("Console application to run Performance Profiling tests for MySQL Connector/NET")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("Oracle")] -[assembly: AssemblyProduct("MySqlX.Data.Performance.Console.Tests")] -[assembly: AssemblyCopyright("Copyright © 2019, 2024, Oracle and/or its affiliates.")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("9d5edc76-5a1c-46c9-a4f2-cf57f276e537")] From 40eba919858df78f4a3d8ca72958e861449aa5fa Mon Sep 17 00:00:00 2001 From: Reggie Burnett Date: Tue, 14 May 2024 16:28:28 -0500 Subject: [PATCH 045/125] WL#16291 [Update dependencies] Change-Id: I4070c42b9984d48c9c09359be005935bcfbccb13 --- CHANGES | 3 ++- EFCore/src/MySql.EntityFrameworkCore.csproj | 16 +++++++------- ...Sql.EntityFrameworkCore.Basic.Tests.csproj | 6 ++--- ...ql.EntityFrameworkCore.Design.Tests.csproj | 2 +- MySQL.Data/src/MySql.Data.csproj | 22 +++++++++---------- .../MySql.Data.Tests/MySql.Data.Tests.csproj | 1 - .../MySqlX.Data.Tests.csproj | 1 - MySql.Web/src/MySql.Web.csproj | 4 ++-- 8 files changed, 27 insertions(+), 28 deletions(-) diff --git a/CHANGES b/CHANGES index 1f8e5f379..f9df32857 100644 --- a/CHANGES +++ b/CHANGES @@ -2,7 +2,8 @@ - Updated NUnit to 4.x (WL16279) - Removed deprecated OldGetStringBehavior option (WL16280) - Remove MySqlX.Data.Performance.Console.Tests project (WL16387) - +- Updated third party dependencies (WL16291) + 8.4.0 - Updated FOSS license text in all source files (WL16197). - Fixed bug Shared memory connection doesn't work in multithread environment (Oracle Bug #36208932). diff --git a/EFCore/src/MySql.EntityFrameworkCore.csproj b/EFCore/src/MySql.EntityFrameworkCore.csproj index a42ec8b92..6ce2419a7 100644 --- a/EFCore/src/MySql.EntityFrameworkCore.csproj +++ b/EFCore/src/MySql.EntityFrameworkCore.csproj @@ -29,20 +29,20 @@ false false - + - - + + - + - - + + - - + + diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/MySql.EntityFrameworkCore.Basic.Tests.csproj b/EFCore/tests/MySql.EFCore.Basic.Tests/MySql.EntityFrameworkCore.Basic.Tests.csproj index ad5d720ab..6ff70fb78 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/MySql.EntityFrameworkCore.Basic.Tests.csproj +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/MySql.EntityFrameworkCore.Basic.Tests.csproj @@ -14,15 +14,15 @@ - + - + - + diff --git a/EFCore/tests/MySql.EFCore.Design.Tests/MySql.EntityFrameworkCore.Design.Tests.csproj b/EFCore/tests/MySql.EFCore.Design.Tests/MySql.EntityFrameworkCore.Design.Tests.csproj index e46a6a2bc..4e5ba881d 100644 --- a/EFCore/tests/MySql.EFCore.Design.Tests/MySql.EntityFrameworkCore.Design.Tests.csproj +++ b/EFCore/tests/MySql.EFCore.Design.Tests/MySql.EntityFrameworkCore.Design.Tests.csproj @@ -24,7 +24,7 @@ - + diff --git a/MySQL.Data/src/MySql.Data.csproj b/MySQL.Data/src/MySql.Data.csproj index cf2092cfc..2d4dc7a03 100644 --- a/MySQL.Data/src/MySql.Data.csproj +++ b/MySQL.Data/src/MySql.Data.csproj @@ -42,21 +42,21 @@ - + - - - + + + - - - + + + @@ -79,12 +79,12 @@ - - + + - + - + diff --git a/MySQL.Data/tests/MySql.Data.Tests/MySql.Data.Tests.csproj b/MySQL.Data/tests/MySql.Data.Tests/MySql.Data.Tests.csproj index 7fc50c885..e1789b63c 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/MySql.Data.Tests.csproj +++ b/MySQL.Data/tests/MySql.Data.Tests/MySql.Data.Tests.csproj @@ -63,7 +63,6 @@ - diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/MySqlX.Data.Tests.csproj b/MySQL.Data/tests/MySqlX.Data.Tests/MySqlX.Data.Tests.csproj index 16e8ca52c..2bcd44d75 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/MySqlX.Data.Tests.csproj +++ b/MySQL.Data/tests/MySqlX.Data.Tests/MySqlX.Data.Tests.csproj @@ -65,7 +65,6 @@ - diff --git a/MySql.Web/src/MySql.Web.csproj b/MySql.Web/src/MySql.Web.csproj index 9bf197b3e..c35ac7721 100644 --- a/MySql.Web/src/MySql.Web.csproj +++ b/MySql.Web/src/MySql.Web.csproj @@ -53,8 +53,8 @@ - - + + From 49807f697c0db24b186be7854a378b3232033652 Mon Sep 17 00:00:00 2001 From: Reggie Burnett Date: Wed, 15 May 2024 14:16:56 -0500 Subject: [PATCH 046/125] WL#16386 [Remove .NET Core 7 and EF Core 7] Change-Id: Idc2709d5204532587a39cc6e014203120d174d0f --- CHANGES | 2 ++ EFCore/src/MySql.EntityFrameworkCore.csproj | 9 ++---- ...Sql.EntityFrameworkCore.Basic.Tests.csproj | 6 +--- ...ql.EntityFrameworkCore.Design.Tests.csproj | 2 +- ...ntityFrameworkCore.Migrations.Tests.csproj | 2 +- .../MySql.EntityFramework.Basic.Tests.csproj | 29 +++++++++---------- ...Sql.EntityFramework.CodeFirst.Tests.csproj | 27 ++++++++--------- ...ql.EntityFramework.Migrations.Tests.csproj | 2 +- MySQL.Data/src/MySql.Data.csproj | 8 +++-- .../MySql.Data.Tests/MySql.Data.Tests.csproj | 8 +++-- .../MySqlX.Data.Tests.csproj | 6 +++- 11 files changed, 50 insertions(+), 51 deletions(-) diff --git a/CHANGES b/CHANGES index f9df32857..87155fbae 100644 --- a/CHANGES +++ b/CHANGES @@ -3,6 +3,8 @@ - Removed deprecated OldGetStringBehavior option (WL16280) - Remove MySqlX.Data.Performance.Console.Tests project (WL16387) - Updated third party dependencies (WL16291) +- Remove .NET 7 and EF Core 7 (WL16386) + 8.4.0 - Updated FOSS license text in all source files (WL16197). diff --git a/EFCore/src/MySql.EntityFrameworkCore.csproj b/EFCore/src/MySql.EntityFrameworkCore.csproj index 6ce2419a7..d3230975c 100644 --- a/EFCore/src/MySql.EntityFrameworkCore.csproj +++ b/EFCore/src/MySql.EntityFrameworkCore.csproj @@ -10,7 +10,7 @@ GPL-2.0-only true 10.0 - net6.0;net7.0;net8.0; + net6.0;net8.0; MySql.EntityFrameworkCore MySql.EntityFrameworkCore enable @@ -34,12 +34,7 @@ - - - - - - + diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/MySql.EntityFrameworkCore.Basic.Tests.csproj b/EFCore/tests/MySql.EFCore.Basic.Tests/MySql.EntityFrameworkCore.Basic.Tests.csproj index 6ff70fb78..c29cff6d4 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/MySql.EntityFrameworkCore.Basic.Tests.csproj +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/MySql.EntityFrameworkCore.Basic.Tests.csproj @@ -2,7 +2,7 @@ MySql.EntityFrameworkCore.Basic.Tests Class Library - net6.0;net7.0;net8.0; + net6.0;net8.0; MySql.EntityFrameworkCore.Basic.Tests MySql.EntityFrameworkCore.Basic.Tests true @@ -17,10 +17,6 @@ - - - - diff --git a/EFCore/tests/MySql.EFCore.Design.Tests/MySql.EntityFrameworkCore.Design.Tests.csproj b/EFCore/tests/MySql.EFCore.Design.Tests/MySql.EntityFrameworkCore.Design.Tests.csproj index 4e5ba881d..939de4597 100644 --- a/EFCore/tests/MySql.EFCore.Design.Tests/MySql.EntityFrameworkCore.Design.Tests.csproj +++ b/EFCore/tests/MySql.EFCore.Design.Tests/MySql.EntityFrameworkCore.Design.Tests.csproj @@ -2,7 +2,7 @@ MySql.EntityFrameworkCore.Design.Tests Class Library - net6.0;net7.0;net8.0; + net6.0;net8.0; MySql.EntityFrameworkCore.Design.Tests MySql.EntityFrameworkCore.Design.Tests true diff --git a/EFCore/tests/MySql.EFCore.Migrations.Tests/MySql.EntityFrameworkCore.Migrations.Tests.csproj b/EFCore/tests/MySql.EFCore.Migrations.Tests/MySql.EntityFrameworkCore.Migrations.Tests.csproj index fcf790362..a0c036a21 100644 --- a/EFCore/tests/MySql.EFCore.Migrations.Tests/MySql.EntityFrameworkCore.Migrations.Tests.csproj +++ b/EFCore/tests/MySql.EFCore.Migrations.Tests/MySql.EntityFrameworkCore.Migrations.Tests.csproj @@ -2,7 +2,7 @@ MySql.EntityFrameworkCore.Migrations.Tests Class Library - net6.0;net7.0;net8.0; + net6.0;net8.0; MySql.EntityFrameworkCore.Migrations.Tests MySql.EntityFrameworkCore.Migrations.Tests true diff --git a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/MySql.EntityFramework.Basic.Tests.csproj b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/MySql.EntityFramework.Basic.Tests.csproj index 40ab28073..5ca853e1d 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/MySql.EntityFramework.Basic.Tests.csproj +++ b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/MySql.EntityFramework.Basic.Tests.csproj @@ -6,7 +6,7 @@ en-US 9.0.0 Oracle - net7.0 + net462;netstandard2.1; MySql.EntityFramework.Basic.Tests MySql.EntityFramework.Basic.Tests MySql;.NET Connector;MySql Connector/NET @@ -33,21 +33,6 @@ - - - - - - - - TRACE;DEBUG;NET452; - - - - TRACE;RELEASE;NET452; - - - @@ -58,8 +43,20 @@ + + + + + + TRACE;DEBUG;NET462; + + + + TRACE;RELEASE;NET462; + + diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/MySql.EntityFramework.CodeFirst.Tests.csproj b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/MySql.EntityFramework.CodeFirst.Tests.csproj index 8466175cc..cef87a71c 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/MySql.EntityFramework.CodeFirst.Tests.csproj +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/MySql.EntityFramework.CodeFirst.Tests.csproj @@ -6,7 +6,7 @@ en-US 9.0.0 Oracle - net7.0 + net462;netstandard2.1; MySql.EntityFramework.CodeFirst.Tests MySql.EntityFramework.CodeFirst.Tests MySql;.NET Connector;MySql Connector/NET @@ -48,6 +48,17 @@ + + + + + + + + + + + @@ -62,20 +73,6 @@ true - - - - - - - - - - - - - - True diff --git a/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/MySql.EntityFramework.Migrations.Tests.csproj b/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/MySql.EntityFramework.Migrations.Tests.csproj index a45dcd0d6..a21af629e 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/MySql.EntityFramework.Migrations.Tests.csproj +++ b/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/MySql.EntityFramework.Migrations.Tests.csproj @@ -6,7 +6,7 @@ en-US 9.0.0 Oracle - net7.0 + net462;netstandard2.1; MySql.EntityFramework.Migrations.Tests MySql.EntityFramework.Migrations.Tests MySql;.NET Connector;MySql Connector/NET diff --git a/MySQL.Data/src/MySql.Data.csproj b/MySQL.Data/src/MySql.Data.csproj index 2d4dc7a03..8d18d61c7 100644 --- a/MySQL.Data/src/MySql.Data.csproj +++ b/MySQL.Data/src/MySql.Data.csproj @@ -8,7 +8,7 @@ 9.0.0 Oracle MySql.Data - net462;net48;netstandard2.0;netstandard2.1;net6.0;net7.0;net8.0; + netstandard2.0;netstandard2.1;net6.0;net8.0; MySql.Data MySql;.NET Connector;MySql Connector/NET;netcore;.Net Core;MySql Conector/Net Core;coreclr;C/NET;C/Net Core Review ReleaseNotes.txt for details. @@ -35,6 +35,10 @@ true + + net462;net48;$(TargetFrameworks) + + @@ -77,7 +81,7 @@ - + diff --git a/MySQL.Data/tests/MySql.Data.Tests/MySql.Data.Tests.csproj b/MySQL.Data/tests/MySql.Data.Tests/MySql.Data.Tests.csproj index e1789b63c..b7ed1a817 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/MySql.Data.Tests.csproj +++ b/MySQL.Data/tests/MySql.Data.Tests/MySql.Data.Tests.csproj @@ -8,7 +8,7 @@ Oracle Oracle MySql.Data.Tests - net8.0;net7.0;net6.0;net462;net48; + net8.0;net6.0 MySql.Data.Tests MySql;.NET Connector;MySql Connector/NET;netcore;.Net Core;MySql Conector/Net Core;coreclr;C/NET;C/Net Core http://www.mysql.com/common/logos/logo-mysql-170x115.png @@ -28,7 +28,11 @@ CS1591,CS1587,CS1701,CS1702,CS1570,CA2100 - + + net462;net48;$(TargetFrameworks) + + + diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/MySqlX.Data.Tests.csproj b/MySQL.Data/tests/MySqlX.Data.Tests/MySqlX.Data.Tests.csproj index 2bcd44d75..e404eda36 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/MySqlX.Data.Tests.csproj +++ b/MySQL.Data/tests/MySqlX.Data.Tests/MySqlX.Data.Tests.csproj @@ -8,7 +8,7 @@ Oracle Oracle MySql.Data.Tests - net8.0;net7.0;net6.0;net462;net48; + net8.0;net6.0 MySqlx.Data.Tests MySql;.NET Connector;MySql Connector/NET;netcore;.Net Core;MySql Conector/Net Core;coreclr;C/NET;C/Net Core http://www.mysql.com/common/logos/logo-mysql-170x115.png @@ -28,6 +28,10 @@ latest + + net462;net48;$(TargetFrameworks) + + From c4ddf988a1faa6a6d8f7e0afdf8054fe96a933ef Mon Sep 17 00:00:00 2001 From: Reggie Burnett Date: Thu, 16 May 2024 12:49:07 -0500 Subject: [PATCH 047/125] Bug#36116171 [Fixed bug SQL Keyword "RETURNING" not handled properly when updating data] Change-Id: If09ce296bd7ef41aba5dfb97765854f49e289921 --- CHANGES | 2 +- EFCore/src/Update/MySQLUpdateSqlGenerator.cs | 13 +++ .../MySql.EFCore.Basic.Tests/UpdateTests.cs | 87 +++++++++++++++++++ 3 files changed, 101 insertions(+), 1 deletion(-) create mode 100644 EFCore/tests/MySql.EFCore.Basic.Tests/UpdateTests.cs diff --git a/CHANGES b/CHANGES index 87155fbae..b6e2349bb 100644 --- a/CHANGES +++ b/CHANGES @@ -4,7 +4,7 @@ - Remove MySqlX.Data.Performance.Console.Tests project (WL16387) - Updated third party dependencies (WL16291) - Remove .NET 7 and EF Core 7 (WL16386) - +- Fixed bug SQL Keyword "RETURNING" not handled properly when updating data (Oracle Bug #36116171) 8.4.0 - Updated FOSS license text in all source files (WL16197). diff --git a/EFCore/src/Update/MySQLUpdateSqlGenerator.cs b/EFCore/src/Update/MySQLUpdateSqlGenerator.cs index 7350729a8..83ed2ea7b 100644 --- a/EFCore/src/Update/MySQLUpdateSqlGenerator.cs +++ b/EFCore/src/Update/MySQLUpdateSqlGenerator.cs @@ -551,6 +551,19 @@ protected virtual void AppendWhereAffectedClause( } } + protected override void AppendReturningClause(StringBuilder commandStringBuilder, IReadOnlyList operations, string? additionalValues = null) + { + if (additionalValues is not null) + { + if (operations.Count > 0) + { + commandStringBuilder.Append(", "); + } + + commandStringBuilder.Append('1'); + } + } + private void AppendRowsAffectedWhereCondition(StringBuilder commandStringBuilder, int expectedRowsAffected) { Check.NotNull(commandStringBuilder, "commandStringBuilder"); diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/UpdateTests.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/UpdateTests.cs new file mode 100644 index 000000000..baa1ec466 --- /dev/null +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/UpdateTests.cs @@ -0,0 +1,87 @@ +// Copyright © 2021, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using Microsoft.EntityFrameworkCore; +using MySql.EntityFrameworkCore.Basic.Tests.Utils; +using NUnit.Framework; +using System; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; + +namespace MySql.EntityFrameworkCore.Basic.Tests +{ + +#region Bug113443 + + [Table("Bug113443Table")] + public record Bug113443Record + { + [Key] + [Column("id")] + [DatabaseGenerated(DatabaseGeneratedOption.Identity)] + public int Id { get; init; } + [Column("name")] + public string? Name { get; set;} + + [Column("time_created", TypeName = "TIMESTAMP(6)")] + [DatabaseGenerated(DatabaseGeneratedOption.Computed)] + public DateTime TimeCreated { get; init; } + + [Column("time_updated", TypeName = "TIMESTAMP(6)")] + [DatabaseGenerated(DatabaseGeneratedOption.Computed)] + public DateTime TimeUpdated { get; init; } + } + + public class Bug113443Context : MyTestContext + { + public DbSet Bug113443 { get; set; } + } + +#endregion + + public class UpdateTests + { + [Test] + public void Bug113443() { + using var ctx = new Bug113443Context(); + ctx.Database.EnsureCreated(); + try + { + Bug113443Record data = new() { Name = "Sample1"}; + ctx.Bug113443.Add(data); + ctx.SaveChanges(); + data.Name = "Changed!"; + ctx.SaveChanges(); + } + finally + { + ctx.Database.EnsureDeleted(); + } + } + } +} From b82bdc95dbc6d9efffd6a749ced680b71dd4fad8 Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Thu, 18 Apr 2024 19:15:11 -0600 Subject: [PATCH 048/125] Bug#36483069 [IIS Website is crashing after upgrading MySQL.Data package to 8.3.0] Change-Id: I11ae533a54093b249f110a44c94772e088ad53cf --- CHANGES | 14 +++--- MySQL.Data/src/MySqlPoolManager.cs | 72 ++++++++++++++++++++---------- 2 files changed, 56 insertions(+), 30 deletions(-) diff --git a/CHANGES b/CHANGES index b6e2349bb..064ece117 100644 --- a/CHANGES +++ b/CHANGES @@ -1,10 +1,12 @@ 9.0.0 -- Updated NUnit to 4.x (WL16279) -- Removed deprecated OldGetStringBehavior option (WL16280) -- Remove MySqlX.Data.Performance.Console.Tests project (WL16387) -- Updated third party dependencies (WL16291) -- Remove .NET 7 and EF Core 7 (WL16386) -- Fixed bug SQL Keyword "RETURNING" not handled properly when updating data (Oracle Bug #36116171) +- Updated NUnit to 4.x (WL16279). +- Removed deprecated OldGetStringBehavior option (WL16280). + - Remove MySqlX.Data.Performance.Console.Tests project (WL16387). +- Updated third party dependencies (WL16291). +- Remove .NET 7 and EF Core 7 (WL16386). +- Fixed bug SQL Keyword "RETURNING" not handled properly when updating data (Oracle Bug #36116171). +- Fixed bug IIS Website is crashing after upgrading MySQL.Data package to 8.3.0 (Oracle Bug #36483069). + 8.4.0 - Updated FOSS license text in all source files (WL16197). diff --git a/MySQL.Data/src/MySqlPoolManager.cs b/MySQL.Data/src/MySqlPoolManager.cs index a052dcdf2..72f89caea 100644 --- a/MySQL.Data/src/MySqlPoolManager.cs +++ b/MySQL.Data/src/MySqlPoolManager.cs @@ -139,12 +139,15 @@ public static async Task GetPoolAsync(MySqlConnectionStringBuilder se { string text = GetKey(settings); - await waitHandle.WaitAsync(CancellationToken.None).ConfigureAwait(false); - MySqlPool pool; - Pools.TryGetValue(text, out pool); + if (execAsync) + await waitHandle.WaitAsync(CancellationToken.None).ConfigureAwait(false); + else + waitHandle.Wait(cancellationToken); try { + MySqlPool pool; + Pools.TryGetValue(text, out pool); if (pool == null) { pool = await MySqlPool.CreateMySqlPoolAsync(settings, execAsync, cancellationToken).ConfigureAwait(false); @@ -152,6 +155,8 @@ public static async Task GetPoolAsync(MySqlConnectionStringBuilder se } else pool.Settings = settings; + + return pool; } catch (Exception ex) { @@ -161,8 +166,6 @@ public static async Task GetPoolAsync(MySqlConnectionStringBuilder se { waitHandle.Release(); } - - return pool; } public static void RemoveConnection(Driver driver) @@ -180,7 +183,8 @@ public static async Task ReleaseConnectionAsync(Driver driver, bool execAsync) MySqlPool pool = driver.Pool; - await pool?.ReleaseConnectionAsync(driver, execAsync); + if (pool != null) + await pool.ReleaseConnectionAsync(driver, execAsync).ConfigureAwait(false); } public static async Task ClearPoolAsync(MySqlConnectionStringBuilder settings, bool execAsync) @@ -203,33 +207,53 @@ public static async Task ClearPoolAsync(MySqlConnectionStringBuilder settings, b private static async Task ClearPoolByTextAsync(string key, bool execAsync) { - // if pools doesn't have it, then this pool must already have been cleared - if (!Pools.ContainsKey(key)) return; + if (execAsync) + await waitHandle.WaitAsync().ConfigureAwait(false); + else + waitHandle.Wait(); + + try + { + // if pools doesn't have it, then this pool must already have been cleared + if (!Pools.ContainsKey(key)) return; - // add the pool to our list of pools being cleared - MySqlPool pool = (Pools[key] as MySqlPool); - ClearingPools.Add(pool); + // add the pool to our list of pools being cleared + MySqlPool pool = (Pools[key] as MySqlPool); + ClearingPools.Add(pool); - // now tell the pool to clear itself - await pool.ClearAsync(execAsync).ConfigureAwait(false); + // now tell the pool to clear itself + await pool.ClearAsync(execAsync).ConfigureAwait(false); - // and then remove the pool from the active pools list - Pools.Remove(key); + // and then remove the pool from the active pools list + Pools.Remove(key); + } + finally + { + waitHandle.Release(); + } } public static async Task ClearAllPoolsAsync(bool execAsync) { - await waitHandle.WaitAsync().ConfigureAwait(false); - - // Create separate keys list. - List keys = new List(Pools.Count); - keys.AddRange(Pools.Keys); + if (execAsync) + await waitHandle.WaitAsync().ConfigureAwait(false); + else + waitHandle.Wait(); - // Remove all pools by key. - foreach (string key in keys) - await ClearPoolByTextAsync(key, execAsync).ConfigureAwait(false); + try + { + // Create separate keys list. + List keys = new List(Pools.Count); + keys.AddRange(Pools.Keys); - waitHandle.Release(); + // Remove all pools by key. + foreach (string key in keys) + await ClearPoolByTextAsync(key, execAsync).ConfigureAwait(false); + } + finally + { + waitHandle.Release(); + } if (DemotedServersTimer != null) { From 96e6d948ab335fe9253192de3cef83053008797d Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Fri, 17 May 2024 11:42:09 -0600 Subject: [PATCH 049/125] Bug#36627858 [Use WiX Toolset 4.0.5] Change-Id: Ied69354a52e3c2012ff4c7f342cfdc10350d83e1 --- CHANGES | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/CHANGES b/CHANGES index 064ece117..2011d0666 100644 --- a/CHANGES +++ b/CHANGES @@ -1,11 +1,12 @@ 9.0.0 -- Updated NUnit to 4.x (WL16279). -- Removed deprecated OldGetStringBehavior option (WL16280). - - Remove MySqlX.Data.Performance.Console.Tests project (WL16387). -- Updated third party dependencies (WL16291). -- Remove .NET 7 and EF Core 7 (WL16386). -- Fixed bug SQL Keyword "RETURNING" not handled properly when updating data (Oracle Bug #36116171). +- Updated NUnit to 4.x (WL16279) +- Removed deprecated OldGetStringBehavior option (WL16280) +- Remove MySqlX.Data.Performance.Console.Tests project (WL16387) +- Updated third party dependencies (WL16291) +- Remove .NET 7 and EF Core 7 (WL16386) +- Fixed bug SQL Keyword "RETURNING" not handled properly when updating data (Oracle Bug #36116171) - Fixed bug IIS Website is crashing after upgrading MySQL.Data package to 8.3.0 (Oracle Bug #36483069). +- Updated Wix Toolset to 4.0.5 (Oracle Bug #36627858). 8.4.0 From ea0e78b74f936eee087a4885d4448ac27178da24 Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Wed, 22 May 2024 18:24:54 -0600 Subject: [PATCH 050/125] Bug#36483069 [IIS Website is crashing after upgrading MySQL.Data package to 8.3.0] - complement Change-Id: I1d08d5778d184a56efb83d57bb8b36953126090e --- MySQL.Data/src/MySqlPoolManager.cs | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/MySQL.Data/src/MySqlPoolManager.cs b/MySQL.Data/src/MySqlPoolManager.cs index 72f89caea..cc16792d0 100644 --- a/MySQL.Data/src/MySqlPoolManager.cs +++ b/MySQL.Data/src/MySqlPoolManager.cs @@ -235,10 +235,7 @@ private static async Task ClearPoolByTextAsync(string key, bool execAsync) public static async Task ClearAllPoolsAsync(bool execAsync) { - if (execAsync) - await waitHandle.WaitAsync().ConfigureAwait(false); - else - waitHandle.Wait(); + try { @@ -250,9 +247,9 @@ public static async Task ClearAllPoolsAsync(bool execAsync) foreach (string key in keys) await ClearPoolByTextAsync(key, execAsync).ConfigureAwait(false); } - finally - { - waitHandle.Release(); + catch + { + throw; } if (DemotedServersTimer != null) From 9f38bdfd9912ae169e3d7c87afe15cebed7d9f80 Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Wed, 29 May 2024 14:46:23 -0600 Subject: [PATCH 051/125] global.json test Change-Id: I80a4f252149e206c3a8b87615f880b4f224009dd --- global.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/global.json b/global.json index f17298ca8..f6386c452 100644 --- a/global.json +++ b/global.json @@ -2,4 +2,7 @@ "msbuild-sdks": { "Microsoft.Build.Traversal": "4.1.0" } + "sdk": { + "version": "8.0.22" + } } \ No newline at end of file From 83af47f797022f23e76060236f236adb9d25487e Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Thu, 23 May 2024 16:17:52 -0600 Subject: [PATCH 052/125] Bug#36529814 [The disabling of mysql_native_password in server causes errors in testsuite] Change-Id: I59408a3bd92bb67e208825b75e8997b8375baad0 --- CHANGES | 13 +++++++------ MySQL.Data/tests/MySql.Data.Tests/AuthTests.cs | 15 +++++++++------ .../tests/MySql.Data.Tests/ExceptionTests.cs | 2 +- MySQL.Data/tests/MySql.Data.Tests/TestBase.cs | 10 +++++++++- MySQL.Data/tests/MySqlX.Data.Tests/BaseTest.cs | 6 ++++++ .../Properties/CreateUsers.sql | 2 -- MySQL.Data/tests/MySqlX.Data.Tests/XAuth.cs | 18 ++++++++++++++---- 7 files changed, 46 insertions(+), 20 deletions(-) diff --git a/CHANGES b/CHANGES index 2011d0666..c4b67410d 100644 --- a/CHANGES +++ b/CHANGES @@ -1,12 +1,13 @@ 9.0.0 -- Updated NUnit to 4.x (WL16279) -- Removed deprecated OldGetStringBehavior option (WL16280) -- Remove MySqlX.Data.Performance.Console.Tests project (WL16387) -- Updated third party dependencies (WL16291) -- Remove .NET 7 and EF Core 7 (WL16386) -- Fixed bug SQL Keyword "RETURNING" not handled properly when updating data (Oracle Bug #36116171) +- Updated NUnit to 4.x (WL16279). +- Removed deprecated OldGetStringBehavior option (WL16280). +- Remove MySqlX.Data.Performance.Console.Tests project (WL16387). +- Updated third party dependencies (WL16291). +- Remove .NET 7 and EF Core 7 (WL16386). +- Fixed bug SQL Keyword "RETURNING" not handled properly when updating data (Oracle Bug #36116171). - Fixed bug IIS Website is crashing after upgrading MySQL.Data package to 8.3.0 (Oracle Bug #36483069). - Updated Wix Toolset to 4.0.5 (Oracle Bug #36627858). +- Fixed bug disabling of mysql_native_password in server causes errors in testsuite (Oracle Bug #36529814). 8.4.0 diff --git a/MySQL.Data/tests/MySql.Data.Tests/AuthTests.cs b/MySQL.Data/tests/MySql.Data.Tests/AuthTests.cs index 5c7cfdcf6..afd6beba9 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/AuthTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/AuthTests.cs @@ -358,6 +358,9 @@ private void TestIntegratedSecurityWithUser(string user, bool pooling) [Property("Category", "Security")] public void ConnectUsingMySqlNativePasswordPlugin() { + if (!Check_Plugin_Enabled("mysql_native_password")) + Assert.Ignore("mysql_native_password plugin must be enabled on the server to run this test"); + string userName = "testNtvPass"; string password = "mysql"; string pluginName = "mysql_native_password"; @@ -1832,12 +1835,12 @@ public void AuthPlainAndMySql41() "with secure connections(classic connection).Server started with mysql native password plugin")] public void Sha256AndNativeWithCertificates() { - if (Version <= new Version("8.0.4")) Assert.Ignore("This test is for MySql 8.0.4 or higher"); - - using (var rdr = ExecuteReader("SELECT * FROM INFORMATION_SCHEMA.PLUGINS WHERE PLUGIN_NAME = 'caching_sha2_password'")) - { - if (!rdr.HasRows) Assert.Ignore("This test needs plugin caching_sha2_password"); - } + if (Version < new Version("8.0.4")) + Assert.Ignore("This test is for MySql 8.0.4 or higher"); + if (!Check_Plugin_Enabled("mysql_native_password")) + Assert.Ignore("mysql_native_password plugin must be enabled on the server to run this test"); + if (!Check_Plugin_Enabled("caching_sha2_password")) + Assert.Ignore("This test needs plugin caching_sha2_password"); // Test connection for VALID user in LDAP server with different SSLMode values, expected result pass string assemblyPath = Assembly.GetExecutingAssembly().Location.Replace(String.Format("{0}.dll", diff --git a/MySQL.Data/tests/MySql.Data.Tests/ExceptionTests.cs b/MySQL.Data/tests/MySql.Data.Tests/ExceptionTests.cs index 51ecf2d76..ecb0e9a82 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/ExceptionTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/ExceptionTests.cs @@ -139,7 +139,7 @@ public void UngrantedAccessException() /// [TestCase("Port", 1455, 1042)] [TestCase("Database", "nonExistingDB", 1049)] - [TestCase("UserID", "nonExistingUser", 1045)] + [TestCase("UserID", "nonExistingUser", 1045)] // Check server bug Bug#36527984 in case of failure [TestCase("Server", "nonExistingServer", 1042)] [TestCase("MaxConnections", "", 1040)] public void AuthenticationExceptionNumber(string propertyName, object propertyValue, int exNumber) diff --git a/MySQL.Data/tests/MySql.Data.Tests/TestBase.cs b/MySQL.Data/tests/MySql.Data.Tests/TestBase.cs index ecd20ef18..80de1b551 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/TestBase.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/TestBase.cs @@ -209,7 +209,7 @@ public string CreateUser(string postfix, string password) { string userName = String.Format("{0}{1}", BaseUserName, postfix); - ExecuteSQL($"CREATE USER '{userName}'@'{host}' IDENTIFIED WITH mysql_native_password BY '{password}'", connection); + ExecuteSQL($"CREATE USER '{userName}'@'{host}' IDENTIFIED BY '{password}'", connection); ExecuteSQL($"GRANT ALL ON *.* TO '{userName}'@'{host}'", connection); ExecuteSQL("FLUSH PRIVILEGES", connection); return userName; @@ -334,6 +334,14 @@ public string GetMySqlServerIp(bool isIpV6 = false) return isIpV6 ? ipv6 : ipv4; } + + public bool Check_Plugin_Enabled(string pluginname) + { + using (var rdr = ExecuteReader($"SELECT PLUGIN_STATUS FROM INFORMATION_SCHEMA.PLUGINS WHERE PLUGIN_NAME = '{pluginname}' AND plugin_status = 'ACTIVE';")) + { + return rdr.HasRows; + } + } #endregion } } diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/BaseTest.cs b/MySQL.Data/tests/MySqlX.Data.Tests/BaseTest.cs index cec0bfdd2..764700cf3 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/BaseTest.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/BaseTest.cs @@ -278,6 +278,12 @@ public string GetMySqlServerIp(bool isIpV6 = false) return isIpV6 ? ipv6 : ipv4; } + public bool Check_Plugin_Enabled(string pluginname) + { + var checkplugin = session.SQL($"SELECT * FROM INFORMATION_SCHEMA.PLUGINS WHERE PLUGIN_NAME = '{pluginname}' AND PLUGIN_STATUS='ACTIVE';").Execute().FetchOne(); + return checkplugin != null; + } + #endregion } } diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/Properties/CreateUsers.sql b/MySQL.Data/tests/MySqlX.Data.Tests/Properties/CreateUsers.sql index 4edcb388b..8c0ea0906 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/Properties/CreateUsers.sql +++ b/MySQL.Data/tests/MySqlX.Data.Tests/Properties/CreateUsers.sql @@ -1,14 +1,12 @@ DROP USER IF EXISTS 'test'; DROP USER IF EXISTS 'testNoPass'; DROP USER IF EXISTS 'testSha2'; -DROP USER IF EXISTS 'testNative'; DROP USER IF EXISTS 'testAnyhost'; CREATE USER 'test'@'%' identified by 'test'; GRANT ALL PRIVILEGES ON *.* TO 'test'@'%'; CREATE USER 'testNoPass'@'%'; CREATE USER 'testSha2'@'%' identified with caching_sha2_password by 'mysql'; GRANT ALL PRIVILEGES ON *.* TO 'testSha2'@'%'; -CREATE USER 'testNative'@'%' identified with mysql_native_password by 'test'; CREATE USER 'testAnyhost'@'%' identified by 'test'; GRANT ALL PRIVILEGES ON *.* TO 'testAnyhost'@'%'; FLUSH PRIVILEGES; \ No newline at end of file diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/XAuth.cs b/MySQL.Data/tests/MySqlX.Data.Tests/XAuth.cs index a5b9d3de9..4cd927b21 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/XAuth.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/XAuth.cs @@ -199,10 +199,8 @@ public void DefaultAuthPublicKeyRetrieval() public void MySqlNativePlugin() { if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("Test available only to MySQL Server +8.0.11"); - - var counter = session.SQL("SELECT count(*) FROM INFORMATION_SCHEMA.PLUGINS WHERE PLUGIN_NAME = 'caching_sha2_password'").Execute().FetchOne(); - if (Convert.ToInt32(counter[0]) <= 0) - Assert.Ignore("The caching_sha2_password plugin isn't available."); + if (!Check_Plugin_Enabled("mysql_native_password")) + Assert.Ignore("mysql_native_password plugin must be enabled on the server to run this test"); string pluginName = "mysql_native_password";//mysql_native_password plugin MySqlConnectionStringBuilder builder = new MySqlConnectionStringBuilder(ConnectionString); @@ -263,6 +261,10 @@ public void MySqlNativePlugin() [Property("Category", "Security")] public void ConnectUsingMySQL41Auth() { + if (!Check_Plugin_Enabled("mysql_native_password")) + Assert.Ignore("mysql_native_password plugin must be enabled on the server to run this test"); + ExecuteSqlAsRoot("CREATE USER IF NOT EXISTS 'testNative'@'%' identified with mysql_native_password by 'test';"); + var connectionStringUri = ConnectionStringUri; if (session.InternalSession.GetServerVersion().isAtLeast(8, 0, 4)) { @@ -371,6 +373,11 @@ public void Sha256MemoryAuthWithDifferentPlugin(string pluginName) { if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("Test available only to MySQL Server +8.0.11"); + if (pluginName == "mysql_native_password") + { + if (!Check_Plugin_Enabled("mysql_native_password")) + Assert.Ignore("mysql_native_password plugin must be enabled on the server to run this test"); + } MySqlConnectionStringBuilder builder = new MySqlConnectionStringBuilder(ConnectionString); builder.UserID = "testDefaultPlugin"; builder.Password = "test"; @@ -417,6 +424,9 @@ public void NativeAuthValidAndInvalidConnection() { if (!Platform.IsWindows()) Assert.Ignore("Check for Linux OS"); if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("Test available only to MySQL Server +8.0.11"); + if (!Check_Plugin_Enabled("mysql_native_password")) + Assert.Ignore("mysql_native_password plugin must be enabled on the server to run this test"); + ExecuteSqlAsRoot("CREATE USER IF NOT EXISTS 'testNative'@'%' identified with mysql_native_password by 'test';"); var user = "testNative"; var pwd = "test"; From d8beb16d39a525639f45eac22b00c4992374ef49 Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Sun, 26 May 2024 14:44:45 -0600 Subject: [PATCH 053/125] WL#16386 [Remove .NET Core 7 and EF Core 7] - Update Change-Id: Iaf30c0883631f0bcde438b28b9cb58cb6bd4c390 --- .../Internal/MySQLAnnotationProvider.cs | 25 ------------------- .../Internal/MySQLMigrationsModelDiffer.cs | 2 +- EFCore/src/Properties/AssemblyInfo.cs | 2 -- .../MySQLParameterBasedSqlProcessor.cs | 2 +- EFCore/src/Update/IMySQLUpdateSqlGenerator.cs | 2 +- .../Update/MySQLModificationCommandBatch.cs | 4 +-- EFCore/src/Update/MySQLUpdateSqlGenerator.cs | 2 +- .../ConnectionTests.cs | 2 +- .../Framework/netstandard2_0/TypeTests.cs | 2 +- .../tests/MySqlX.Data.Tests/SessionTests.cs | 2 +- .../tests/MySqlX.Data.Tests/SslTests.cs | 2 +- 11 files changed, 10 insertions(+), 37 deletions(-) diff --git a/EFCore/src/Metadata/Internal/MySQLAnnotationProvider.cs b/EFCore/src/Metadata/Internal/MySQLAnnotationProvider.cs index 50d43a214..dc22f8f4d 100644 --- a/EFCore/src/Metadata/Internal/MySQLAnnotationProvider.cs +++ b/EFCore/src/Metadata/Internal/MySQLAnnotationProvider.cs @@ -155,31 +155,6 @@ public override IEnumerable For(IColumn column, bool designTime) yield return new Annotation(MySQLAnnotationNames.ValueGenerationStrategy, valueGenerationStrategy); } } -#elif NET7_0 - public override IEnumerable For(IColumn column, bool designTime) - { - if (!designTime) - yield break; - - var table = StoreObjectIdentifier.Table(column.Table.Name, column.Table.Schema); - var properties = column.PropertyMappings.Select(m => m.Property).ToArray(); - - if (column.PropertyMappings.Where(m => m.TableMapping.IsSharedTablePrincipal ?? true - && m.TableMapping.EntityType == m.Property.DeclaringEntityType) - .Select(m => m.Property) - .FirstOrDefault(p => p.GetValueGenerationStrategy(table) == MySQLValueGenerationStrategy.IdentityColumn) is IProperty identityProperty) - { - var valueGenerationStrategy = identityProperty.GetValueGenerationStrategy(table); - yield return new Annotation(MySQLAnnotationNames.ValueGenerationStrategy, valueGenerationStrategy); - } - else if (properties.FirstOrDefault - (p => p.GetValueGenerationStrategy(table) == MySQLValueGenerationStrategy.ComputedColumn) is IProperty computedProperty) - { - var valueGenerationStrategy = computedProperty.GetValueGenerationStrategy(table); - yield return new Annotation(MySQLAnnotationNames.ValueGenerationStrategy, valueGenerationStrategy); - } - } - #elif NET8_0 public override IEnumerable For(IColumn column, bool designTime) diff --git a/EFCore/src/Migrations/Internal/MySQLMigrationsModelDiffer.cs b/EFCore/src/Migrations/Internal/MySQLMigrationsModelDiffer.cs index 12ad45c71..22ffaa57a 100644 --- a/EFCore/src/Migrations/Internal/MySQLMigrationsModelDiffer.cs +++ b/EFCore/src/Migrations/Internal/MySQLMigrationsModelDiffer.cs @@ -81,7 +81,7 @@ protected override IEnumerable Add(IColumn target, DiffConte return base.Add(target, diffContext, inline); } -#elif NET7_0 || NET8_0 +#elif NET8_0 public MySQLMigrationsModelDiffer( [NotNull] IRelationalTypeMappingSource typeMappingSource, [NotNull] IMigrationsAnnotationProvider migrationsAnnotations, diff --git a/EFCore/src/Properties/AssemblyInfo.cs b/EFCore/src/Properties/AssemblyInfo.cs index e18a3ad26..66005293d 100644 --- a/EFCore/src/Properties/AssemblyInfo.cs +++ b/EFCore/src/Properties/AssemblyInfo.cs @@ -43,8 +43,6 @@ [assembly: AssemblyProduct("MySQL Connector/NET")] #if NET6_0 [assembly: AssemblyCopyright("Copyright © 2021, 2024, Oracle and/or its affiliates.")] -#elif NET7_0 -[assembly: AssemblyCopyright("Copyright © 2022, 2024, Oracle and/or its affiliates.")] #elif NET8_0 [assembly: AssemblyCopyright("Copyright © 2024, Oracle and/or its affiliates.")] #endif diff --git a/EFCore/src/Query/Internal/MySQLParameterBasedSqlProcessor.cs b/EFCore/src/Query/Internal/MySQLParameterBasedSqlProcessor.cs index c23e34dd2..c73a1f77f 100644 --- a/EFCore/src/Query/Internal/MySQLParameterBasedSqlProcessor.cs +++ b/EFCore/src/Query/Internal/MySQLParameterBasedSqlProcessor.cs @@ -62,7 +62,7 @@ protected override SelectExpression ProcessSqlNullability( return selectExpression; } -#elif NET7_0 || NET8_0 +#elif NET8_0 protected override Expression ProcessSqlNullability( Expression selectExpression, IReadOnlyDictionary parametersValues, out bool canCache) { diff --git a/EFCore/src/Update/IMySQLUpdateSqlGenerator.cs b/EFCore/src/Update/IMySQLUpdateSqlGenerator.cs index 4c6c7d3b7..5e94a0019 100644 --- a/EFCore/src/Update/IMySQLUpdateSqlGenerator.cs +++ b/EFCore/src/Update/IMySQLUpdateSqlGenerator.cs @@ -42,7 +42,7 @@ ResultSetMapping AppendBulkInsertOperation( [NotNull] IReadOnlyList modificationCommands, int commandPosition); } -#elif NET7_0 || NET8_0 +#elif NET8_0 /// /// /// The service lifetime is . This means a single instance diff --git a/EFCore/src/Update/MySQLModificationCommandBatch.cs b/EFCore/src/Update/MySQLModificationCommandBatch.cs index 9ea4cf0aa..965390c17 100644 --- a/EFCore/src/Update/MySQLModificationCommandBatch.cs +++ b/EFCore/src/Update/MySQLModificationCommandBatch.cs @@ -55,7 +55,7 @@ internal class MySQLModificationCommandBatch : AffectedCountModificationCommandB private readonly int _maxBatchSize; private readonly List _bulkInsertCommands = new List(); private int _commandsLeftToLengthCheck = 50; -#elif NET7_0 || NET8_0 +#elif NET8_0 private readonly List _pendingBulkInsertCommands = new(); #endif @@ -200,7 +200,7 @@ protected override void UpdateCachedCommandText(int commandPosition) } } -#elif NET7_0 || NET8_0 +#elif NET8_0 /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to /// the same compatibility standards as public APIs. It may be changed or removed without notice in diff --git a/EFCore/src/Update/MySQLUpdateSqlGenerator.cs b/EFCore/src/Update/MySQLUpdateSqlGenerator.cs index 83ed2ea7b..b94d96dba 100644 --- a/EFCore/src/Update/MySQLUpdateSqlGenerator.cs +++ b/EFCore/src/Update/MySQLUpdateSqlGenerator.cs @@ -233,7 +233,7 @@ internal enum ResultsGrouping OneResultSet, OneCommandPerResultSet } -#elif NET7_0 || NET8_0 +#elif NET8_0 public virtual ResultSetMapping AppendBulkInsertOperation( StringBuilder commandStringBuilder, IReadOnlyList modificationCommands, diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/ConnectionTests.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/ConnectionTests.cs index 08673d39a..c54c09f04 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/ConnectionTests.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/ConnectionTests.cs @@ -85,7 +85,7 @@ public static RelationalConnectionDependencies CreateDependencies(DbContextOptio TestServiceFactory.Instance.Create(), new MySQLOptions())))); } -#elif NET7_0 || NET8_0 +#elif NET8_0 public static RelationalConnectionDependencies CreateDependencies(DbContextOptions? options = null) { options ??= new DbContextOptionsBuilder() diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/TypeTests.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/TypeTests.cs index b64e74f6f..62ccf2c49 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/TypeTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/TypeTests.cs @@ -35,7 +35,7 @@ namespace MySql.Data.MySqlClient.Tests { public class TypeTests : TestBase { -#if !NET7_0_OR_GREATER +#if !NET8_0_OR_GREATER /// /// Test fix for http://bugs.mysql.com/bug.php?id=40555 /// Make MySql.Data.Types.MySqlDateTime serializable. diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/SessionTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/SessionTests.cs index 5d37e3c23..13f0ff70c 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/SessionTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/SessionTests.cs @@ -255,7 +255,7 @@ public void CheckConnectionUri() CheckConnectionData("mysqlx://myuser:password@[(address=[fe80::bd41:e449:45ee:2e1a%17]:3305,priority=100)]", "myuser", "password", "[fe80::bd41:e449:45ee:2e1a]", 3305); Assert.Throws(() => CheckConnectionData("mysqlx://myuser:password@[(address=fe80::bd41:e449:45ee:2e1a%17,priority=100)]", "myuser", "password", "[fe80::bd41:e449:45ee:2e1a]", 33060)); CheckConnectionData("mysqlx://myuser@localhost/test", "myuser", "", "localhost", 33060, "database", schemaName); -#if NET7_0 +#if NET8_0 CheckConnectionData("mysqlx://myuser@localhost/test?ssl%20mode=disabled&connecttimeout=10", "myuser", "", "localhost", 33060, "database", schemaName, "ssl mode", "None", "connecttimeout", "10"); #else CheckConnectionData("mysqlx://myuser@localhost/test?ssl%20mode=disabled&connecttimeout=10", "myuser", "", "localhost", 33060, "database", schemaName, "ssl mode", "Disabled", "connecttimeout", "10"); diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/SslTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/SslTests.cs index 771f58f95..6e399c635 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/SslTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/SslTests.cs @@ -123,7 +123,7 @@ public void SslRequiredByDefault() public void SslPreferredIsInvalid() { string prefered = "Prefered"; -#if NET7_0 +#if NET8_0 prefered = "Preferred"; #endif var expectedErrorMessage = "Value '{0}' is not of the correct type."; From c84ab782237fc06c881c3c2cb866cb32bcbefc2a Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Sun, 2 Jun 2024 19:11:25 -0600 Subject: [PATCH 054/125] Updated LIUMS. Change-Id: Ia1970c5a1e4eac466e8dc864db752110e202f6c4 --- LICENSE | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/LICENSE b/LICENSE index 9ca7460c7..b6c7a6e7e 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ Licensing Information User Manual -MySQL Connector/NET 8.4.0 Community +MySQL Connector/NET 9.0.0 Community __________________________________________________________________ Introduction @@ -8,18 +8,18 @@ Introduction This License Information User Manual contains Oracle's product license and other licensing information, including licensing information for third-party software which may be included in this distribution of - MySQL Connector/NET 8.4.0 Community. + MySQL Connector/NET 9.0.0 Community. - Last updated: March 2024 + Last updated: May 2024 Licensing Information - This release of MySQL Connector/NET 8.4.0 Community is brought to you + This release of MySQL Connector/NET 9.0.0 Community is brought to you by the MySQL team at Oracle. This software is released under version 2 of the GNU General Public License (GPLv2), as set forth below, with the following additional permissions: - This distribution of MySQL Connector/NET 8.4.0 Community is designed to + This distribution of MySQL Connector/NET 9.0.0 Community is designed to work with certain software (including but not limited to OpenSSL) that is licensed under separate terms, as designated in a particular file or component or in the license documentation. Without limiting your rights @@ -1017,4 +1017,4 @@ Written Offer for Source Code that included the binary that is the subject of your request, or b. in the case of code licensed under the GPL v3 for as long as Oracle - offers spare parts or customer support for that product model. + offers spare parts or customer support for that product model. \ No newline at end of file From 370c081c6c1e43f65f5bda419fe23748ad9b2246 Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Sun, 2 Jun 2024 19:31:57 -0600 Subject: [PATCH 055/125] Updated Documentation Change-Id: I760c43767e2d4b63da58792ae727b022b0ea4c7a --- Documentation/index.md | 4 ++-- README.md | 2 ++ Release Notes.txt | 10 ++++++---- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/Documentation/index.md b/Documentation/index.md index 4965d6ca3..ffb271d5f 100644 --- a/Documentation/index.md +++ b/Documentation/index.md @@ -1,6 +1,6 @@ ## MySQL Connector/NET and X DevAPI -MySQL Connector/NET 8.4 supports X Protocol, which enables you to use X DevAPI with the .NET language of choice to develop applications that communicate with a MySQL server functioning as a document store, relational database, or both. +MySQL Connector/NET 9.0 supports X Protocol, which enables you to use X DevAPI with the .NET language of choice to develop applications that communicate with a MySQL server functioning as a document store, relational database, or both. To get started, review the following main classes: @@ -16,7 +16,7 @@ For an introduction to X DevAPI concepts, see the [X DevAPI User Guide](https:// ## MySQL Connector/NET -MySQL Connector/NET 8.4 also supports the development of .NET, .NET Core and .NET Framework applications that require secure, high-performance data connectivity with MySQL through the classic protocol. It supports ADO.NET, Entity Framework and various web providers. +MySQL Connector/NET 9.0 also supports the development of .NET, .NET Core and .NET Framework applications that require secure, high-performance data connectivity with MySQL through the classic protocol. It supports ADO.NET, Entity Framework and various web providers. To get started, review the following main classes: diff --git a/README.md b/README.md index 4f91301bd..0a25e8138 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,8 @@ From MySQL Connector/NET 8.3, the driver also adds support for [.NET 8](https:// From MySQL Connector/NET 8.4, the driver adds support for TLS1.3 and removes support for FIDO authentication plugin. +From MySQL Connector/NET 9.0, the driver removes support for .NET 7 and EF Core 7. + For detailed information please visit the official [MySQL Connector/NET documentation.](https://dev.mysql.com/doc/connector-net/en/) ## Licensing diff --git a/Release Notes.txt b/Release Notes.txt index 6f1e6dde2..b6cf83c91 100644 --- a/Release Notes.txt +++ b/Release Notes.txt @@ -1,8 +1,10 @@ -Connector/NET 8.4 Release Notes +Connector/NET 9.0 Release Notes ------------------------------------ -Welcome to the release notes for Connector/NET 8.3 +Welcome to the release notes for Connector/NET 9.0 -What's new in 8.4 +What's new in 9.0 -------------------- -Connector/NET added support for TLS1.3 and removed support for FIDO authentication plugin. \ No newline at end of file +Connector/NET now uses NUnit 4.1 in the testsuite. +Connector/NET updated 3rd party dependencies. +Connector/NET removes support for .NET 7 and EF Core 7. \ No newline at end of file From b96a8e68f8b77e6cd0bd114cef33697150916a1a Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Sun, 2 Jun 2024 15:34:30 -0600 Subject: [PATCH 056/125] Permit only SDK GA versions to be used in build process. Change-Id: I2040c7cb92df20d3dfa0ddd186666fa1c20d73e0 --- EFCore/src/global.json | 5 +++++ EFCore/tests/MySql.EFCore.Basic.Tests/global.json | 5 +++++ EFCore/tests/MySql.EFCore.Design.Tests/global.json | 5 +++++ EFCore/tests/MySql.EFCore.Migrations.Tests/global.json | 5 +++++ EntityFramework/src/global.json | 5 +++++ .../tests/MySql.EntityFramework.Basic.Tests/global.json | 5 +++++ .../tests/MySql.EntityFramework.CodeFirst.Tests/global.json | 5 +++++ .../tests/MySql.EntityFramework.Migrations.Tests/global.json | 5 +++++ MySQL.Data.OpenTelemetry/src/global.json | 5 +++++ MySQL.Data/src/global.json | 5 +++++ MySQL.Data/tests/MySql.Data.Tests/global.json | 5 +++++ MySQL.Data/tests/MySqlX.Data.Tests/global.json | 5 +++++ MySql.Web/src/global.json | 5 +++++ MySql.Web/tests/global.json | 5 +++++ global.json | 4 ++-- 15 files changed, 72 insertions(+), 2 deletions(-) create mode 100644 EFCore/src/global.json create mode 100644 EFCore/tests/MySql.EFCore.Basic.Tests/global.json create mode 100644 EFCore/tests/MySql.EFCore.Design.Tests/global.json create mode 100644 EFCore/tests/MySql.EFCore.Migrations.Tests/global.json create mode 100644 EntityFramework/src/global.json create mode 100644 EntityFramework/tests/MySql.EntityFramework.Basic.Tests/global.json create mode 100644 EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/global.json create mode 100644 EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/global.json create mode 100644 MySQL.Data.OpenTelemetry/src/global.json create mode 100644 MySQL.Data/src/global.json create mode 100644 MySQL.Data/tests/MySql.Data.Tests/global.json create mode 100644 MySQL.Data/tests/MySqlX.Data.Tests/global.json create mode 100644 MySql.Web/src/global.json create mode 100644 MySql.Web/tests/global.json diff --git a/EFCore/src/global.json b/EFCore/src/global.json new file mode 100644 index 000000000..a8ab760dd --- /dev/null +++ b/EFCore/src/global.json @@ -0,0 +1,5 @@ +{ + "sdk": { + "allowPrerelease": false + } +} \ No newline at end of file diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/global.json b/EFCore/tests/MySql.EFCore.Basic.Tests/global.json new file mode 100644 index 000000000..a8ab760dd --- /dev/null +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/global.json @@ -0,0 +1,5 @@ +{ + "sdk": { + "allowPrerelease": false + } +} \ No newline at end of file diff --git a/EFCore/tests/MySql.EFCore.Design.Tests/global.json b/EFCore/tests/MySql.EFCore.Design.Tests/global.json new file mode 100644 index 000000000..a8ab760dd --- /dev/null +++ b/EFCore/tests/MySql.EFCore.Design.Tests/global.json @@ -0,0 +1,5 @@ +{ + "sdk": { + "allowPrerelease": false + } +} \ No newline at end of file diff --git a/EFCore/tests/MySql.EFCore.Migrations.Tests/global.json b/EFCore/tests/MySql.EFCore.Migrations.Tests/global.json new file mode 100644 index 000000000..a8ab760dd --- /dev/null +++ b/EFCore/tests/MySql.EFCore.Migrations.Tests/global.json @@ -0,0 +1,5 @@ +{ + "sdk": { + "allowPrerelease": false + } +} \ No newline at end of file diff --git a/EntityFramework/src/global.json b/EntityFramework/src/global.json new file mode 100644 index 000000000..a8ab760dd --- /dev/null +++ b/EntityFramework/src/global.json @@ -0,0 +1,5 @@ +{ + "sdk": { + "allowPrerelease": false + } +} \ No newline at end of file diff --git a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/global.json b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/global.json new file mode 100644 index 000000000..a8ab760dd --- /dev/null +++ b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/global.json @@ -0,0 +1,5 @@ +{ + "sdk": { + "allowPrerelease": false + } +} \ No newline at end of file diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/global.json b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/global.json new file mode 100644 index 000000000..a8ab760dd --- /dev/null +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/global.json @@ -0,0 +1,5 @@ +{ + "sdk": { + "allowPrerelease": false + } +} \ No newline at end of file diff --git a/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/global.json b/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/global.json new file mode 100644 index 000000000..a8ab760dd --- /dev/null +++ b/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/global.json @@ -0,0 +1,5 @@ +{ + "sdk": { + "allowPrerelease": false + } +} \ No newline at end of file diff --git a/MySQL.Data.OpenTelemetry/src/global.json b/MySQL.Data.OpenTelemetry/src/global.json new file mode 100644 index 000000000..a8ab760dd --- /dev/null +++ b/MySQL.Data.OpenTelemetry/src/global.json @@ -0,0 +1,5 @@ +{ + "sdk": { + "allowPrerelease": false + } +} \ No newline at end of file diff --git a/MySQL.Data/src/global.json b/MySQL.Data/src/global.json new file mode 100644 index 000000000..a8ab760dd --- /dev/null +++ b/MySQL.Data/src/global.json @@ -0,0 +1,5 @@ +{ + "sdk": { + "allowPrerelease": false + } +} \ No newline at end of file diff --git a/MySQL.Data/tests/MySql.Data.Tests/global.json b/MySQL.Data/tests/MySql.Data.Tests/global.json new file mode 100644 index 000000000..a8ab760dd --- /dev/null +++ b/MySQL.Data/tests/MySql.Data.Tests/global.json @@ -0,0 +1,5 @@ +{ + "sdk": { + "allowPrerelease": false + } +} \ No newline at end of file diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/global.json b/MySQL.Data/tests/MySqlX.Data.Tests/global.json new file mode 100644 index 000000000..a8ab760dd --- /dev/null +++ b/MySQL.Data/tests/MySqlX.Data.Tests/global.json @@ -0,0 +1,5 @@ +{ + "sdk": { + "allowPrerelease": false + } +} \ No newline at end of file diff --git a/MySql.Web/src/global.json b/MySql.Web/src/global.json new file mode 100644 index 000000000..a8ab760dd --- /dev/null +++ b/MySql.Web/src/global.json @@ -0,0 +1,5 @@ +{ + "sdk": { + "allowPrerelease": false + } +} \ No newline at end of file diff --git a/MySql.Web/tests/global.json b/MySql.Web/tests/global.json new file mode 100644 index 000000000..a8ab760dd --- /dev/null +++ b/MySql.Web/tests/global.json @@ -0,0 +1,5 @@ +{ + "sdk": { + "allowPrerelease": false + } +} \ No newline at end of file diff --git a/global.json b/global.json index f6386c452..4978943db 100644 --- a/global.json +++ b/global.json @@ -1,8 +1,8 @@ { "msbuild-sdks": { "Microsoft.Build.Traversal": "4.1.0" - } + }, "sdk": { - "version": "8.0.22" + "allowPrerelease": false } } \ No newline at end of file From baf1ce9e4709d87bf25af5380ecd80ac97c63803 Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Sun, 26 May 2024 14:14:32 -0600 Subject: [PATCH 057/125] WL#16279 [Migrate to NUnit 4.x] - Update Change-Id: I4323bed71ea1dbc07cd6f5542ae3f9b1ba3aadf6 --- EFCore/tests/Directory.build.props | 12 ------------ .../tests/MySql.EFCore.Basic.Tests/GlobalUsings.cs | 5 +++++ .../tests/MySql.EFCore.Design.Tests/GlobalUsings.cs | 5 +++++ .../MySql.EFCore.Migrations.Tests/GlobalUsings.cs | 5 +++++ .../src/MySql.Data.EntityFramework.csproj | 2 +- .../GlobalUsings.cs | 5 +++++ .../MySql.EntityFramework.Basic.Tests.csproj | 7 ++++--- .../GlobalUsings.cs | 5 +++++ .../MySql.EntityFramework.CodeFirst.Tests.csproj | 7 ++++--- .../GlobalUsings.cs | 5 +++++ .../MySql.EntityFramework.Migrations.Tests.csproj | 7 ++++--- .../SetUpMigrationsTests.cs | 3 ++- MySQL.Data/tests/Directory.build.props | 12 ------------ MySQL.Data/tests/MySql.Data.Tests/GlobalUsings.cs | 5 +++++ MySQL.Data/tests/MySqlX.Data.Tests/GlobalUsings.cs | 5 +++++ MySql.Web/tests/Directory.build.props | 12 ------------ MySql.Web/tests/GlobalUsings.cs | 5 +++++ 17 files changed, 60 insertions(+), 47 deletions(-) delete mode 100644 EFCore/tests/Directory.build.props create mode 100644 EFCore/tests/MySql.EFCore.Basic.Tests/GlobalUsings.cs create mode 100644 EFCore/tests/MySql.EFCore.Design.Tests/GlobalUsings.cs create mode 100644 EFCore/tests/MySql.EFCore.Migrations.Tests/GlobalUsings.cs create mode 100644 EntityFramework/tests/MySql.EntityFramework.Basic.Tests/GlobalUsings.cs create mode 100644 EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/GlobalUsings.cs create mode 100644 EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/GlobalUsings.cs delete mode 100644 MySQL.Data/tests/Directory.build.props create mode 100644 MySQL.Data/tests/MySql.Data.Tests/GlobalUsings.cs create mode 100644 MySQL.Data/tests/MySqlX.Data.Tests/GlobalUsings.cs delete mode 100644 MySql.Web/tests/Directory.build.props create mode 100644 MySql.Web/tests/GlobalUsings.cs diff --git a/EFCore/tests/Directory.build.props b/EFCore/tests/Directory.build.props deleted file mode 100644 index 03b886514..000000000 --- a/EFCore/tests/Directory.build.props +++ /dev/null @@ -1,12 +0,0 @@ - - - true - - - - - - - - - diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/GlobalUsings.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/GlobalUsings.cs new file mode 100644 index 000000000..575c7cfd0 --- /dev/null +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/GlobalUsings.cs @@ -0,0 +1,5 @@ +global using Assert = NUnit.Framework.Legacy.ClassicAssert; +global using CollectionAssert = NUnit.Framework.Legacy.CollectionAssert; +global using StringAssert = NUnit.Framework.Legacy.StringAssert; +global using DirectoryAssert = NUnit.Framework.Legacy.DirectoryAssert; +global using FileAssert = NUnit.Framework.Legacy.FileAssert; diff --git a/EFCore/tests/MySql.EFCore.Design.Tests/GlobalUsings.cs b/EFCore/tests/MySql.EFCore.Design.Tests/GlobalUsings.cs new file mode 100644 index 000000000..575c7cfd0 --- /dev/null +++ b/EFCore/tests/MySql.EFCore.Design.Tests/GlobalUsings.cs @@ -0,0 +1,5 @@ +global using Assert = NUnit.Framework.Legacy.ClassicAssert; +global using CollectionAssert = NUnit.Framework.Legacy.CollectionAssert; +global using StringAssert = NUnit.Framework.Legacy.StringAssert; +global using DirectoryAssert = NUnit.Framework.Legacy.DirectoryAssert; +global using FileAssert = NUnit.Framework.Legacy.FileAssert; diff --git a/EFCore/tests/MySql.EFCore.Migrations.Tests/GlobalUsings.cs b/EFCore/tests/MySql.EFCore.Migrations.Tests/GlobalUsings.cs new file mode 100644 index 000000000..575c7cfd0 --- /dev/null +++ b/EFCore/tests/MySql.EFCore.Migrations.Tests/GlobalUsings.cs @@ -0,0 +1,5 @@ +global using Assert = NUnit.Framework.Legacy.ClassicAssert; +global using CollectionAssert = NUnit.Framework.Legacy.CollectionAssert; +global using StringAssert = NUnit.Framework.Legacy.StringAssert; +global using DirectoryAssert = NUnit.Framework.Legacy.DirectoryAssert; +global using FileAssert = NUnit.Framework.Legacy.FileAssert; diff --git a/EntityFramework/src/MySql.Data.EntityFramework.csproj b/EntityFramework/src/MySql.Data.EntityFramework.csproj index 21d144a18..eb256a715 100644 --- a/EntityFramework/src/MySql.Data.EntityFramework.csproj +++ b/EntityFramework/src/MySql.Data.EntityFramework.csproj @@ -6,7 +6,7 @@ en-US 9.0.0 Oracle - net462;netstandard2.1; + net462;net48; $(NoWarn);CS1591 MySql.Data.EntityFramework MySql.Data.EntityFramework diff --git a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/GlobalUsings.cs b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/GlobalUsings.cs new file mode 100644 index 000000000..575c7cfd0 --- /dev/null +++ b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/GlobalUsings.cs @@ -0,0 +1,5 @@ +global using Assert = NUnit.Framework.Legacy.ClassicAssert; +global using CollectionAssert = NUnit.Framework.Legacy.CollectionAssert; +global using StringAssert = NUnit.Framework.Legacy.StringAssert; +global using DirectoryAssert = NUnit.Framework.Legacy.DirectoryAssert; +global using FileAssert = NUnit.Framework.Legacy.FileAssert; diff --git a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/MySql.EntityFramework.Basic.Tests.csproj b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/MySql.EntityFramework.Basic.Tests.csproj index 5ca853e1d..3b3b43b7c 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/MySql.EntityFramework.Basic.Tests.csproj +++ b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/MySql.EntityFramework.Basic.Tests.csproj @@ -6,7 +6,7 @@ en-US 9.0.0 Oracle - net462;netstandard2.1; + net462;net48; MySql.EntityFramework.Basic.Tests MySql.EntityFramework.Basic.Tests MySql;.NET Connector;MySql Connector/NET @@ -25,6 +25,7 @@ ..\..\..\ConnectorNetPublicKey.snk MySql.EntityFramework.Basic.Tests CA2100 + latest @@ -45,8 +46,8 @@ - - + + diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/GlobalUsings.cs b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/GlobalUsings.cs new file mode 100644 index 000000000..575c7cfd0 --- /dev/null +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/GlobalUsings.cs @@ -0,0 +1,5 @@ +global using Assert = NUnit.Framework.Legacy.ClassicAssert; +global using CollectionAssert = NUnit.Framework.Legacy.CollectionAssert; +global using StringAssert = NUnit.Framework.Legacy.StringAssert; +global using DirectoryAssert = NUnit.Framework.Legacy.DirectoryAssert; +global using FileAssert = NUnit.Framework.Legacy.FileAssert; diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/MySql.EntityFramework.CodeFirst.Tests.csproj b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/MySql.EntityFramework.CodeFirst.Tests.csproj index cef87a71c..ef07197bf 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/MySql.EntityFramework.CodeFirst.Tests.csproj +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/MySql.EntityFramework.CodeFirst.Tests.csproj @@ -6,7 +6,7 @@ en-US 9.0.0 Oracle - net462;netstandard2.1; + net462;net48; MySql.EntityFramework.CodeFirst.Tests MySql.EntityFramework.CodeFirst.Tests MySql;.NET Connector;MySql Connector/NET @@ -25,6 +25,7 @@ True ..\..\..\ConnectorNetPublicKey.snk CA2100 + latest @@ -61,8 +62,8 @@ - - + + diff --git a/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/GlobalUsings.cs b/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/GlobalUsings.cs new file mode 100644 index 000000000..575c7cfd0 --- /dev/null +++ b/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/GlobalUsings.cs @@ -0,0 +1,5 @@ +global using Assert = NUnit.Framework.Legacy.ClassicAssert; +global using CollectionAssert = NUnit.Framework.Legacy.CollectionAssert; +global using StringAssert = NUnit.Framework.Legacy.StringAssert; +global using DirectoryAssert = NUnit.Framework.Legacy.DirectoryAssert; +global using FileAssert = NUnit.Framework.Legacy.FileAssert; diff --git a/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/MySql.EntityFramework.Migrations.Tests.csproj b/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/MySql.EntityFramework.Migrations.Tests.csproj index a21af629e..323ac00d4 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/MySql.EntityFramework.Migrations.Tests.csproj +++ b/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/MySql.EntityFramework.Migrations.Tests.csproj @@ -6,7 +6,7 @@ en-US 9.0.0 Oracle - net462;netstandard2.1; + net462;net48; MySql.EntityFramework.Migrations.Tests MySql.EntityFramework.Migrations.Tests MySql;.NET Connector;MySql Connector/NET @@ -24,6 +24,7 @@ ..\..\..\ConnectorNetPublicKey.snk true CA2100 + latest @@ -35,8 +36,8 @@ - - + + diff --git a/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/SetUpMigrationsTests.cs b/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/SetUpMigrationsTests.cs index 62d31c7d6..1b5599a5f 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/SetUpMigrationsTests.cs +++ b/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/SetUpMigrationsTests.cs @@ -29,6 +29,7 @@ using MySql.Data.EntityFramework.Properties; using MySql.Data.EntityFramework.Tests; using NUnit.Framework; +using NUnit.Framework.Internal; using System; using System.Configuration; using System.Data; @@ -49,7 +50,7 @@ public class SetUpMigrationsTests : DefaultFixture [OneTimeSetUp] public new void OneTimeSetup() { - ConnectionStringBlogContext = RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? MySql.EntityFramework.Migrations.Tests.Properties.Resources.ConnStringMacOS : MySql.EntityFramework.Migrations.Tests.Properties.Resources.ConnString; + ConnectionStringBlogContext = System.Environment.OSVersion.Platform == PlatformID.MacOSX ? MySql.EntityFramework.Migrations.Tests.Properties.Resources.ConnStringMacOS : MySql.EntityFramework.Migrations.Tests.Properties.Resources.ConnString; configuration = new Configuration(); DataSet dataSet = ConfigurationManager.GetSection("system.data") as System.Data.DataSet; diff --git a/MySQL.Data/tests/Directory.build.props b/MySQL.Data/tests/Directory.build.props deleted file mode 100644 index 03b886514..000000000 --- a/MySQL.Data/tests/Directory.build.props +++ /dev/null @@ -1,12 +0,0 @@ - - - true - - - - - - - - - diff --git a/MySQL.Data/tests/MySql.Data.Tests/GlobalUsings.cs b/MySQL.Data/tests/MySql.Data.Tests/GlobalUsings.cs new file mode 100644 index 000000000..575c7cfd0 --- /dev/null +++ b/MySQL.Data/tests/MySql.Data.Tests/GlobalUsings.cs @@ -0,0 +1,5 @@ +global using Assert = NUnit.Framework.Legacy.ClassicAssert; +global using CollectionAssert = NUnit.Framework.Legacy.CollectionAssert; +global using StringAssert = NUnit.Framework.Legacy.StringAssert; +global using DirectoryAssert = NUnit.Framework.Legacy.DirectoryAssert; +global using FileAssert = NUnit.Framework.Legacy.FileAssert; diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/GlobalUsings.cs b/MySQL.Data/tests/MySqlX.Data.Tests/GlobalUsings.cs new file mode 100644 index 000000000..575c7cfd0 --- /dev/null +++ b/MySQL.Data/tests/MySqlX.Data.Tests/GlobalUsings.cs @@ -0,0 +1,5 @@ +global using Assert = NUnit.Framework.Legacy.ClassicAssert; +global using CollectionAssert = NUnit.Framework.Legacy.CollectionAssert; +global using StringAssert = NUnit.Framework.Legacy.StringAssert; +global using DirectoryAssert = NUnit.Framework.Legacy.DirectoryAssert; +global using FileAssert = NUnit.Framework.Legacy.FileAssert; diff --git a/MySql.Web/tests/Directory.build.props b/MySql.Web/tests/Directory.build.props deleted file mode 100644 index 03b886514..000000000 --- a/MySql.Web/tests/Directory.build.props +++ /dev/null @@ -1,12 +0,0 @@ - - - true - - - - - - - - - diff --git a/MySql.Web/tests/GlobalUsings.cs b/MySql.Web/tests/GlobalUsings.cs new file mode 100644 index 000000000..575c7cfd0 --- /dev/null +++ b/MySql.Web/tests/GlobalUsings.cs @@ -0,0 +1,5 @@ +global using Assert = NUnit.Framework.Legacy.ClassicAssert; +global using CollectionAssert = NUnit.Framework.Legacy.CollectionAssert; +global using StringAssert = NUnit.Framework.Legacy.StringAssert; +global using DirectoryAssert = NUnit.Framework.Legacy.DirectoryAssert; +global using FileAssert = NUnit.Framework.Legacy.FileAssert; From 7456bd102cc4193d61b12f82312b3db063aacea1 Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Wed, 5 Jun 2024 12:58:26 -0600 Subject: [PATCH 058/125] Bug#36701652 [EFCore test failing due to misconfiguration] Change-Id: I91b60bf0aea34a8ee368532b5827e337b219c4e1 --- CHANGES | 1 + .../Conventions/MySQLConventionSetBuilder.cs | 3 +- .../Internal/MySQLAnnotationProvider.cs | 199 +++++++----------- 3 files changed, 81 insertions(+), 122 deletions(-) diff --git a/CHANGES b/CHANGES index c4b67410d..5b11b2590 100644 --- a/CHANGES +++ b/CHANGES @@ -8,6 +8,7 @@ - Fixed bug IIS Website is crashing after upgrading MySQL.Data package to 8.3.0 (Oracle Bug #36483069). - Updated Wix Toolset to 4.0.5 (Oracle Bug #36627858). - Fixed bug disabling of mysql_native_password in server causes errors in testsuite (Oracle Bug #36529814). +- Fixed bug EFCore test failing due to misconfiguration (Oracle Bug #36701652). 8.4.0 diff --git a/EFCore/src/Metadata/Conventions/MySQLConventionSetBuilder.cs b/EFCore/src/Metadata/Conventions/MySQLConventionSetBuilder.cs index f80db87e8..51691531a 100644 --- a/EFCore/src/Metadata/Conventions/MySQLConventionSetBuilder.cs +++ b/EFCore/src/Metadata/Conventions/MySQLConventionSetBuilder.cs @@ -67,10 +67,9 @@ public override ConventionSet CreateConventionSet() conventionSet.PropertyAddedConventions.Add(new MySqlCharsetAttributeConvention(Dependencies)); conventionSet.PropertyAddedConventions.Add(new MySqlCollationAttributeConvention(Dependencies)); - #if !NET8_0 conventionSet.EntityTypeAddedConventions.Add(new MySqlEntityCharsetAttributeConvention(Dependencies)); conventionSet.EntityTypeAddedConventions.Add(new MySqlEntityCollationAttributeConvention(Dependencies)); - #endif + ValueGenerationConvention valueGeneratorConvention = new MySQLValueGenerationConvention(Dependencies, RelationalDependencies); ReplaceConvention(conventionSet.EntityTypeBaseTypeChangedConventions, valueGeneratorConvention); ReplaceConvention(conventionSet.EntityTypePrimaryKeyChangedConventions, valueGeneratorConvention); diff --git a/EFCore/src/Metadata/Internal/MySQLAnnotationProvider.cs b/EFCore/src/Metadata/Internal/MySQLAnnotationProvider.cs index dc22f8f4d..74a77b683 100644 --- a/EFCore/src/Metadata/Internal/MySQLAnnotationProvider.cs +++ b/EFCore/src/Metadata/Internal/MySQLAnnotationProvider.cs @@ -70,29 +70,23 @@ public override IEnumerable For(ITable table, bool designTime) { yield break; } -#if !NET8_0 - var entityType = table.EntityTypeMappings.First().EntityType; - - if (GetActualEntityTypeCharSet(entityType) is string charSet) +#if NET8_0 + var entityType = table.EntityTypeMappings.First().TypeBase; + if (GetActualTypeBaseCharSet(entityType) is string charSet) yield return new Annotation(MySQLAnnotationNames.Charset, charSet); - if (GetActualEntityTypeCollation(entityType) is string collation) + if (GetActualTypeBaseCollation(entityType) is string collation) yield return new Annotation(RelationalAnnotationNames.Collation, collation); - - foreach (var annotation in entityType.GetAnnotations().Where(a => a.Name is MySQLAnnotationNames.StoreOptions)) - yield return annotation; #else - var typeBase = table.EntityTypeMappings.First().TypeBase; - - if (GetActualTypeBaseCharSet(typeBase) is string charSet) + var entityType = table.EntityTypeMappings.First().EntityType; + if (GetActualEntityTypeCharSet(entityType) is string charSet) yield return new Annotation(MySQLAnnotationNames.Charset, charSet); - if (GetActualTypeBaseCollation(typeBase) is string collation) + if (GetActualEntityTypeCollation(entityType) is string collation) yield return new Annotation(RelationalAnnotationNames.Collation, collation); - - foreach (var annotation in typeBase.GetAnnotations().Where(a => a.Name is MySQLAnnotationNames.StoreOptions)) - yield return annotation; #endif + foreach (var annotation in entityType.GetAnnotations().Where(a => a.Name is MySQLAnnotationNames.StoreOptions)) + yield return annotation; } public override IEnumerable For(IUniqueConstraint constraint, bool designTime) @@ -131,7 +125,6 @@ public override IEnumerable For(ITableIndex index, bool designTime) yield return new Annotation(MySQLAnnotationNames.SpatialIndex, isSpatial.Value); } -#if NET6_0 public override IEnumerable For(IColumn column, bool designTime) { if (!designTime) @@ -139,49 +132,25 @@ public override IEnumerable For(IColumn column, bool designTime) var table = StoreObjectIdentifier.Table(column.Table.Name, column.Table.Schema); var properties = column.PropertyMappings.Select(m => m.Property).ToArray(); - - if (column.PropertyMappings.Where( - m => m.TableMapping.IsSharedTablePrincipal && m.TableMapping.EntityType == m.Property.DeclaringEntityType) - .Select(m => m.Property) - .FirstOrDefault(p => p.GetValueGenerationStrategy(table) == MySQLValueGenerationStrategy.IdentityColumn) is IProperty identityProperty) - { - var valueGenerationStrategy = identityProperty.GetValueGenerationStrategy(table); - yield return new Annotation(MySQLAnnotationNames.ValueGenerationStrategy, valueGenerationStrategy); - } - else if (properties.FirstOrDefault - (p => p.GetValueGenerationStrategy(table) == MySQLValueGenerationStrategy.ComputedColumn) is IProperty computedProperty) - { - var valueGenerationStrategy = computedProperty.GetValueGenerationStrategy(table); - yield return new Annotation(MySQLAnnotationNames.ValueGenerationStrategy, valueGenerationStrategy); - } - } -#elif NET8_0 - -public override IEnumerable For(IColumn column, bool designTime) - { - if (!designTime) - yield break; - - var table = StoreObjectIdentifier.Table(column.Table.Name, column.Table.Schema); - var properties = column.PropertyMappings.Select(m => m.Property).ToArray(); - - if (column.PropertyMappings.Where(m => m.TableMapping.IsSharedTablePrincipal ?? true - && m.TableMapping.TypeBase == m.Property.DeclaringEntityType) - .Select(m => m.Property) - .FirstOrDefault(p => p.GetValueGenerationStrategy(table) == MySQLValueGenerationStrategy.IdentityColumn) is IProperty identityProperty) +#if NET8_0 + if (column.PropertyMappings.Where(m => m.TableMapping.IsSharedTablePrincipal ?? true && m.TableMapping.TypeBase == m.Property.DeclaringType) + .Select(m => m.Property) + .FirstOrDefault(p => p.GetValueGenerationStrategy(table) == MySQLValueGenerationStrategy.IdentityColumn) is IProperty identityProperty) +#else + if (column.PropertyMappings.Where(m => m.TableMapping.IsSharedTablePrincipal && m.TableMapping.EntityType == m.Property.DeclaringEntityType) + .Select(m => m.Property) + .FirstOrDefault(p => p.GetValueGenerationStrategy(table) == MySQLValueGenerationStrategy.IdentityColumn) is IProperty identityProperty) +#endif { var valueGenerationStrategy = identityProperty.GetValueGenerationStrategy(table); yield return new Annotation(MySQLAnnotationNames.ValueGenerationStrategy, valueGenerationStrategy); } - else if (properties.FirstOrDefault - (p => p.GetValueGenerationStrategy(table) == MySQLValueGenerationStrategy.ComputedColumn) is IProperty computedProperty) + else if (properties.FirstOrDefault(p => p.GetValueGenerationStrategy(table) == MySQLValueGenerationStrategy.ComputedColumn) is IProperty computedProperty) { var valueGenerationStrategy = computedProperty.GetValueGenerationStrategy(table); yield return new Annotation(MySQLAnnotationNames.ValueGenerationStrategy, valueGenerationStrategy); } } -#endif - protected virtual string GetActualModelCharSet(IModel model) { @@ -193,148 +162,138 @@ protected virtual string GetActualModelCollation(IModel model) return model.GetCollation()!; } - -#if !NET8_0 - protected virtual string? GetActualEntityTypeCharSet(IEntityType entityType) +#if NET8_0 + protected virtual string? GetActualTypeBaseCharSet(ITypeBase typeBase) { - var entityTypeCharSet = entityType.GetCharSet(); + var typeBaseCharSet = typeBase.GetCharSet(); - if (entityTypeCharSet is not null) - return entityTypeCharSet; + if (typeBaseCharSet is not null) + return typeBaseCharSet; - if (entityTypeCharSet is null) + if (typeBaseCharSet is null) { - var entityTypeCollation = entityType.GetCollation(); - var actualModelCharSet = GetActualModelCharSet(entityType.Model); + var typeBaseCollation = typeBase.GetCollation(); + var actualModelCharSet = GetActualModelCharSet(typeBase.Model); - if (entityTypeCollation is not null) + if (typeBaseCollation is not null) { - return actualModelCharSet is not null && entityTypeCollation.StartsWith(actualModelCharSet, StringComparison.OrdinalIgnoreCase) + return actualModelCharSet is not null && typeBaseCollation.StartsWith(actualModelCharSet, StringComparison.OrdinalIgnoreCase) ? actualModelCharSet : null; } - var actualModelCollation = GetActualModelCollation(entityType.Model); + var actualModelCollation = GetActualModelCollation(typeBase.Model); if (actualModelCollation is not null) { return actualModelCharSet is not null && actualModelCollation.StartsWith(actualModelCharSet, StringComparison.OrdinalIgnoreCase) ? actualModelCharSet : null; } - return actualModelCharSet; } - return null; } - protected virtual string? GetActualEntityTypeCollation(IEntityType entityType) + protected virtual string? GetActualTypeBaseCollation(ITypeBase typeBase) { - var entityTypeCollation = entityType.GetCollation(); + var typeBaseCollation = typeBase.GetCollation(); - if (entityTypeCollation is not null) - return entityTypeCollation; + if (typeBaseCollation is not null) + return typeBaseCollation; - if (entityTypeCollation is null) + if (typeBaseCollation is null) { - var entityTypeCharSet = entityType.GetCharSet(); - var actualModelCollation = GetActualModelCollation(entityType.Model); + var typeBaseCharSet = typeBase.GetCharSet(); + var actualModelCollation = GetActualModelCollation(typeBase.Model); - if (entityTypeCharSet is not null) + if (typeBaseCharSet is not null) { - return actualModelCollation is not null && actualModelCollation.StartsWith(entityTypeCharSet, StringComparison.OrdinalIgnoreCase) + return actualModelCollation is not null && actualModelCollation.StartsWith(typeBaseCharSet, StringComparison.OrdinalIgnoreCase) ? actualModelCollation : null; } - return actualModelCollation; } - return null; } - - protected virtual string? GetActualPropertyCharSet(IProperty[] properties) - { - return properties.Select(p => p.GetCharSet()).FirstOrDefault(s => s is not null) ?? - properties.Select( - p => p.FindTypeMapping() is MySQLStringTypeMapping - ? GetActualEntityTypeCharSet(p.DeclaringEntityType) is string charSet && - (p.GetCollation() is not string collation || - collation.StartsWith(charSet, StringComparison.OrdinalIgnoreCase)) - ? charSet - : null - : null) - .FirstOrDefault(s => s is not null); - } #else - protected virtual string? GetActualTypeBaseCharSet(ITypeBase typeBase) + protected virtual string? GetActualEntityTypeCharSet(IEntityType entityType) { - var typeBaseCharSet = typeBase.GetCharSet(); + var entityTypeCharSet = entityType.GetCharSet(); - if (typeBaseCharSet is not null) - return typeBaseCharSet; + if (entityTypeCharSet is not null) + return entityTypeCharSet; - if (typeBaseCharSet is null) + if (entityTypeCharSet is null) { - var typeBaseCollation = typeBase.GetCollation(); - var actualModelCharSet = GetActualModelCharSet(typeBase.Model); + var entityTypeCollation = entityType.GetCollation(); + var actualModelCharSet = GetActualModelCharSet(entityType.Model); - if (typeBaseCollation is not null) + if (entityTypeCollation is not null) { - return actualModelCharSet is not null && typeBaseCollation.StartsWith(actualModelCharSet, StringComparison.OrdinalIgnoreCase) + return actualModelCharSet is not null && entityTypeCollation.StartsWith(actualModelCharSet, StringComparison.OrdinalIgnoreCase) ? actualModelCharSet : null; } - var actualModelCollation = GetActualModelCollation(typeBase.Model); + var actualModelCollation = GetActualModelCollation(entityType.Model); if (actualModelCollation is not null) { return actualModelCharSet is not null && actualModelCollation.StartsWith(actualModelCharSet, StringComparison.OrdinalIgnoreCase) ? actualModelCharSet : null; } - return actualModelCharSet; } - return null; } - protected virtual string? GetActualTypeBaseCollation(ITypeBase typeBase) + protected virtual string? GetActualEntityTypeCollation(IEntityType entityType) { - var typeBaseCollation = typeBase.GetCollation(); + var entityTypeCollation = entityType.GetCollation(); - if (typeBaseCollation is not null) - return typeBaseCollation; + if (entityTypeCollation is not null) + return entityTypeCollation; - if (typeBaseCollation is null) + if (entityTypeCollation is null) { - var typeBaseCharSet = typeBase.GetCharSet(); - var actualModelCollation = GetActualModelCollation(typeBase.Model); + var entityTypeCharSet = entityType.GetCharSet(); + var actualModelCollation = GetActualModelCollation(entityType.Model); - if (typeBaseCharSet is not null) + if (entityTypeCharSet is not null) { - return actualModelCollation is not null && actualModelCollation.StartsWith(typeBaseCharSet, StringComparison.OrdinalIgnoreCase) + return actualModelCollation is not null && actualModelCollation.StartsWith(entityTypeCharSet, StringComparison.OrdinalIgnoreCase) ? actualModelCollation : null; } - return actualModelCollation; } - return null; } +#endif protected virtual string? GetActualPropertyCharSet(IProperty[] properties) { +#if NET8_0 + return properties.Select(p => p.GetCharSet()).FirstOrDefault(s => s is not null) ?? + properties.Select( + p => p.FindTypeMapping() is MySQLStringTypeMapping + ? GetActualTypeBaseCharSet(p.DeclaringType) is string charSet && + (p.GetCollation() is not string collation || + collation.StartsWith(charSet, StringComparison.OrdinalIgnoreCase)) + ? charSet + : null + : null) + .FirstOrDefault(s => s is not null); + } +#else return properties.Select(p => p.GetCharSet()).FirstOrDefault(s => s is not null) ?? properties.Select( - p => p.FindTypeMapping() is MySQLStringTypeMapping - ? GetActualTypeBaseCharSet(p.DeclaringType) is string charSet && - (p.GetCollation() is not string collation || - collation.StartsWith(charSet, StringComparison.OrdinalIgnoreCase)) - ? charSet - : null - : null) + p => p.FindTypeMapping() is MySQLStringTypeMapping + ? GetActualEntityTypeCharSet(p.DeclaringEntityType) is string charSet && + (p.GetCollation() is not string collation || + collation.StartsWith(charSet, StringComparison.OrdinalIgnoreCase)) + ? charSet + : null + : null) .FirstOrDefault(s => s is not null); } #endif - } } From b5945b636087f11a871fd52a711296748b77a7b3 Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Tue, 11 Jun 2024 14:54:29 -0600 Subject: [PATCH 059/125] Bump up version to 9.1.0 Change-Id: Ic417825f9d8fad6dc04e289baf7abc3367654bb9 --- CHANGES | 3 +++ .../templates/custom/partials/class.header.tmpl.partial | 2 +- EntityFramework/src/MySql.Data.EntityFramework.csproj | 2 +- .../MySql.EntityFramework.Basic.Tests.csproj | 2 +- .../MySql.EntityFramework.CodeFirst.Tests.csproj | 2 +- .../MySql.EntityFramework.Migrations.Tests.csproj | 2 +- .../src/MySQL.Data.OpenTelemetry.csproj | 2 +- MySQL.Data/src/MySql.Data.csproj | 2 +- MySQL.Data/src/Properties/VersionInfo.cs | 6 +++--- MySQL.Data/tests/MySql.Data.Tests/MySql.Data.Tests.csproj | 2 +- MySQL.Data/tests/MySqlX.Data.Tests/MySqlX.Data.Tests.csproj | 2 +- MySql.Web/src/MySql.Web.csproj | 2 +- MySql.Web/tests/MySql.Web.Tests.csproj | 2 +- 13 files changed, 17 insertions(+), 14 deletions(-) diff --git a/CHANGES b/CHANGES index 5b11b2590..c80c87130 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,6 @@ +9.1.0 + + 9.0.0 - Updated NUnit to 4.x (WL16279). - Removed deprecated OldGetStringBehavior option (WL16280). diff --git a/Documentation/templates/custom/partials/class.header.tmpl.partial b/Documentation/templates/custom/partials/class.header.tmpl.partial index 9df19ebdd..2eff37671 100644 --- a/Documentation/templates/custom/partials/class.header.tmpl.partial +++ b/Documentation/templates/custom/partials/class.header.tmpl.partial @@ -25,7 +25,7 @@ {{/implements.0}}
{{__global.namespace}}: {{{namespace.specName.0.value}}}
{{__global.assembly}}: {{assemblies.0}}.dll
-
Version: 9.0.0
+
Version: 9.1.0
{{__global.syntax}}
{{syntax.content.0.value}}
diff --git a/EntityFramework/src/MySql.Data.EntityFramework.csproj b/EntityFramework/src/MySql.Data.EntityFramework.csproj index eb256a715..15f1caca9 100644 --- a/EntityFramework/src/MySql.Data.EntityFramework.csproj +++ b/EntityFramework/src/MySql.Data.EntityFramework.csproj @@ -4,7 +4,7 @@ MySql.Data.EntityFramework Copyright © 2016, 2024, Oracle and/or its affiliates. en-US - 9.0.0 + 9.1.0 Oracle net462;net48; $(NoWarn);CS1591 diff --git a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/MySql.EntityFramework.Basic.Tests.csproj b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/MySql.EntityFramework.Basic.Tests.csproj index 3b3b43b7c..a421205e8 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/MySql.EntityFramework.Basic.Tests.csproj +++ b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/MySql.EntityFramework.Basic.Tests.csproj @@ -4,7 +4,7 @@ MySql.Data.EntityFramework.CodeFirTests Copyright © 2016, 2024, Oracle and/or its affiliates. en-US - 9.0.0 + 9.1.0 Oracle net462;net48; MySql.EntityFramework.Basic.Tests diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/MySql.EntityFramework.CodeFirst.Tests.csproj b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/MySql.EntityFramework.CodeFirst.Tests.csproj index ef07197bf..edc58b2ce 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/MySql.EntityFramework.CodeFirst.Tests.csproj +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/MySql.EntityFramework.CodeFirst.Tests.csproj @@ -4,7 +4,7 @@ MySql.Data.EntityFramework.CodeFirst.Tests Copyright © 2016, 2024, Oracle and/or its affiliates. en-US - 9.0.0 + 9.1.0 Oracle net462;net48; MySql.EntityFramework.CodeFirst.Tests diff --git a/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/MySql.EntityFramework.Migrations.Tests.csproj b/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/MySql.EntityFramework.Migrations.Tests.csproj index 323ac00d4..213dd36a9 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/MySql.EntityFramework.Migrations.Tests.csproj +++ b/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/MySql.EntityFramework.Migrations.Tests.csproj @@ -4,7 +4,7 @@ MySql.Data.EntityFramework.Migrations.Tests Copyright © 2016, 2024, Oracle and/or its affiliates. en-US - 9.0.0 + 9.1.0 Oracle net462;net48; MySql.EntityFramework.Migrations.Tests diff --git a/MySQL.Data.OpenTelemetry/src/MySQL.Data.OpenTelemetry.csproj b/MySQL.Data.OpenTelemetry/src/MySQL.Data.OpenTelemetry.csproj index 70d0f257f..96097c5f2 100644 --- a/MySQL.Data.OpenTelemetry/src/MySQL.Data.OpenTelemetry.csproj +++ b/MySQL.Data.OpenTelemetry/src/MySQL.Data.OpenTelemetry.csproj @@ -4,7 +4,7 @@ MySql.Data.OpenTelemetry Copyright © 2023, 2024, Oracle and/or its affiliates. en-US - 9.0.0 + 9.1.0 Oracle netstandard2.0 MySql.Data.OpenTelemetry diff --git a/MySQL.Data/src/MySql.Data.csproj b/MySQL.Data/src/MySql.Data.csproj index 8d18d61c7..39432847d 100644 --- a/MySQL.Data/src/MySql.Data.csproj +++ b/MySQL.Data/src/MySql.Data.csproj @@ -5,7 +5,7 @@ MySql.Data.MySqlClient .Net Core Class Library Copyright © 2016, 2024, Oracle and/or its affiliates. en-US - 9.0.0 + 9.1.0 Oracle MySql.Data netstandard2.0;netstandard2.1;net6.0;net8.0; diff --git a/MySQL.Data/src/Properties/VersionInfo.cs b/MySQL.Data/src/Properties/VersionInfo.cs index 545a5808b..123b70f96 100644 --- a/MySQL.Data/src/Properties/VersionInfo.cs +++ b/MySQL.Data/src/Properties/VersionInfo.cs @@ -40,7 +40,7 @@ // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("9.0.0")] -[assembly: AssemblyInformationalVersion("9.0.0")] -[assembly: AssemblyFileVersion("9.0.0")] +[assembly: AssemblyVersion("9.1.0")] +[assembly: AssemblyInformationalVersion("9.1.0")] +[assembly: AssemblyFileVersion("9.1.0")] [assembly: NeutralResourcesLanguage("en-US")] diff --git a/MySQL.Data/tests/MySql.Data.Tests/MySql.Data.Tests.csproj b/MySQL.Data/tests/MySql.Data.Tests/MySql.Data.Tests.csproj index b7ed1a817..3af700db8 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/MySql.Data.Tests.csproj +++ b/MySQL.Data/tests/MySql.Data.Tests/MySql.Data.Tests.csproj @@ -4,7 +4,7 @@ MySql.Data.Tests MySql.Data.Tests Class Library Copyright © 2016, 2024, Oracle and/or its affiliates. - 9.0.0 + 9.1.0 Oracle Oracle MySql.Data.Tests diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/MySqlX.Data.Tests.csproj b/MySQL.Data/tests/MySqlX.Data.Tests/MySqlX.Data.Tests.csproj index e404eda36..27f1dff62 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/MySqlX.Data.Tests.csproj +++ b/MySQL.Data/tests/MySqlX.Data.Tests/MySqlX.Data.Tests.csproj @@ -4,7 +4,7 @@ MySql.Data.Tests MySql.Data.Tests Class Library Copyright © 2016, 2024, Oracle and/or its affiliates. - 9.0.0 + 9.1.0 Oracle Oracle MySql.Data.Tests diff --git a/MySql.Web/src/MySql.Web.csproj b/MySql.Web/src/MySql.Web.csproj index c35ac7721..602a6e64c 100644 --- a/MySql.Web/src/MySql.Web.csproj +++ b/MySql.Web/src/MySql.Web.csproj @@ -4,7 +4,7 @@ MySql.Web Copyright © 2016, 2024, Oracle and/or its affiliates. en-US - 9.0.0 + 9.1.0 Oracle net462;net48; $(NoWarn);CS1591 diff --git a/MySql.Web/tests/MySql.Web.Tests.csproj b/MySql.Web/tests/MySql.Web.Tests.csproj index 4459f0cf9..1733d05a7 100644 --- a/MySql.Web/tests/MySql.Web.Tests.csproj +++ b/MySql.Web/tests/MySql.Web.Tests.csproj @@ -4,7 +4,7 @@ MySql.Web.Tests Copyright © 2016, 2024, Oracle and/or its affiliates. en-US - 9.0.0 + 9.1.0 Oracle net462;net48; MySql.Web.Tests From 6d2eb6be6bc1e4eefdd54755c15b33c0b216688c Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Sun, 30 Jun 2024 19:28:13 -0600 Subject: [PATCH 060/125] WL#16397 [Use constraint model in test assertions] Change-Id: Ia614f8291a307a074283b5ccf3e89753fb13632c --- CHANGES | 1 + .../BasicGuidTests.cs | 6 +- .../ConcurrencyTests.cs | 2 +- .../ConnectionTests.cs | 10 +- .../MySql.EFCore.Basic.Tests/DataTests.cs | 12 +- .../DbFunctionsMySQLTest.cs | 20 +- .../MySql.EFCore.Basic.Tests/EFCoreTests.cs | 18 +- .../FluentAPITests.cs | 36 +- .../FunctionalTests.cs | 18 +- .../MySql.EFCore.Basic.Tests/GlobalUsings.cs | 5 - .../LoadingRelatedDataTests.cs | 62 +- .../MySql.EFCore.Basic.Tests/ModelingTests.cs | 14 +- .../MultiSchemaTests.cs | 10 +- .../MySQLDatabaseFacadeTest.cs | 22 +- .../MySQLTypeMapperTests.cs | 64 +- .../ShadowPropertiesTests.cs | 14 +- .../Utils/EntityTestsFixtureClass.cs | 2 +- .../MySql.EFCore.Design.Tests/GlobalUsings.cs | 5 - .../MySQLAnnotationCodeGeneratorTest.cs | 4 +- .../MySQLCodeGeneratorTest.cs | 14 +- .../MySQLDatabaseModelFactoryTest.cs | 52 +- .../MySQLDesignTimeProviderServicesTest.cs | 6 +- .../GlobalUsings.cs | 5 - .../MySQLHistoryRepositoryTests.cs | 5 +- .../MySqlMigrationsGeneratorTest.cs | 26 +- .../CanonicalFunctions.cs | 66 +- .../DataTypeTests.cs | 8 +- .../DatesTypesTests.cs | 8 +- .../DefaultFixture.cs | 4 +- .../DeleteTests.cs | 8 +- .../ExpressionTests.cs | 14 +- .../GlobalUsings.cs | 5 - .../InsertTests.cs | 12 +- .../Paging.cs | 2 +- .../ProceduresAndFunctions.cs | 4 +- .../ProviderManifestTests.cs | 14 +- .../ProviderServicesTests.cs | 12 +- .../SetOperators.cs | 4 +- .../SimpleQuery.cs | 2 +- .../Wizard.cs | 14 +- .../CodeFirstFixture.cs | 6 +- .../CodeFirstTests.cs | 217 +++--- .../GlobalUsings.cs | 5 - .../GlobalUsings.cs | 5 - .../MySqlMigrationsTests.cs | 44 +- .../tests/MySql.Data.Tests/AttributeTests.cs | 46 +- .../tests/MySql.Data.Tests/AuthTests.cs | 236 +++--- .../tests/MySql.Data.Tests/BlobTests.cs | 54 +- .../tests/MySql.Data.Tests/CharSetTests.cs | 86 +-- .../MySql.Data.Tests/CharSetUTF8Tests.cs | 76 +- .../ClientSideFailoverTests.cs | 26 +- MySQL.Data/tests/MySql.Data.Tests/CmdTests.cs | 152 ++-- .../ConnectionStringBuilderTests.cs | 152 ++-- .../tests/MySql.Data.Tests/ConnectionTests.cs | 196 ++--- .../tests/MySql.Data.Tests/DataTypeTests.cs | 466 ++++++------ .../tests/MySql.Data.Tests/DateTimeTests.cs | 122 ++-- .../tests/MySql.Data.Tests/DnsSrvTests.cs | 12 +- .../tests/MySql.Data.Tests/ExceptionTests.cs | 10 +- .../Framework/netstandard2_0/CultureTests.cs | 26 +- .../Framework/netstandard2_0/DataTypeTests.cs | 14 +- .../Framework/netstandard2_0/DateTimeTests.cs | 32 +- .../netstandard2_0/GetSchemaTests.cs | 454 ++++++------ .../netstandard2_0/InstallerTests.cs | 2 +- .../netstandard2_0/MySQLHelperTests.cs | 76 +- .../MySqlCommandBuilderTests.cs | 73 +- .../netstandard2_0/MySqlDataAdapterTests.cs | 336 ++++----- .../netstandard2_0/MySqlDataReaderTests.cs | 6 +- .../netstandard2_0/NETCore20Tests.cs | 34 +- .../netstandard2_0/ProcedureParameterTests.cs | 410 ++++++----- .../netstandard2_0/ReplicationTests.cs | 2 +- .../netstandard2_0/ThreadingTests.cs | 4 +- .../netstandard2_0/TimeoutAndCancel.cs | 30 +- .../Framework/netstandard2_0/TypeTests.cs | 24 +- .../netstandard2_0/UsageAdvisorTests.cs | 102 +-- .../tests/MySql.Data.Tests/LoggingTests.cs | 36 +- .../MySql.Data.Tests/MySqlBulkLoaderTests.cs | 134 ++-- .../MySql.Data.Tests/MySqlDataReaderTests.cs | 298 ++++---- .../MySql.Data.Tests/OutputParametersBatch.cs | 87 ++- .../tests/MySql.Data.Tests/ParameterTests.cs | 188 ++--- .../tests/MySql.Data.Tests/PoolingTests.cs | 38 +- .../MySql.Data.Tests/PreparedStatements.cs | 187 +++-- .../tests/MySql.Data.Tests/ScriptExecution.cs | 40 +- .../MySql.Data.Tests/SimpleTransactions.cs | 18 +- .../tests/MySql.Data.Tests/SqlServerMode.cs | 4 +- MySQL.Data/tests/MySql.Data.Tests/SslTests.cs | 236 +++--- .../tests/MySql.Data.Tests/StoredProcedure.cs | 130 ++-- .../tests/MySql.Data.Tests/StressTests.cs | 12 +- MySQL.Data/tests/MySql.Data.Tests/Syntax.cs | 76 +- MySQL.Data/tests/MySql.Data.Tests/Syntax2.cs | 16 +- .../tests/MySql.Data.Tests/TableCaching.cs | 26 +- .../tests/MySql.Data.Tests/Tokenizer.cs | 242 +++---- .../tests/MySql.Data.Tests/Transactions.cs | 40 +- .../tests/MySql.Data.Tests/UnixSockets.cs | 2 +- .../tests/MySqlX.Data.Tests/BaseTest.cs | 2 +- .../tests/MySqlX.Data.Tests/BasicFindTests.cs | 622 ++++++++-------- .../MySqlX.Data.Tests/BasicSelectTests.cs | 18 +- .../CharsetAndCollationTests.cs | 504 ++++++------- .../ClientSideFailoverTests.cs | 206 +++--- .../tests/MySqlX.Data.Tests/ClientTests.cs | 344 ++++----- .../MySqlX.Data.Tests/CloseConnectionTests.cs | 42 +- .../MySqlX.Data.Tests/CollectionAsyncTests.cs | 10 +- .../MySqlX.Data.Tests/CollectionIndexTests.cs | 412 +++++------ .../MySqlX.Data.Tests/CollectionTests.cs | 378 +++++----- .../MySqlX.Data.Tests/CompressionTests.cs | 238 +++--- .../MySqlX.Data.Tests/CrudInsertTests.cs | 618 ++++++++-------- .../MySqlX.Data.Tests/CrudRemoveTests.cs | 138 ++-- .../CrudTests/CrudGCTests.cs | 6 +- .../CrudTests/DocBufferingTests.cs | 4 +- .../MySqlX.Data.Tests/CrudUpdateTests.cs | 458 ++++++------ .../MySqlX.Data.Tests/CustomTypeTests.cs | 30 +- .../tests/MySqlX.Data.Tests/DbDocTests.cs | 14 +- .../tests/MySqlX.Data.Tests/DnsSrvTests.cs | 28 +- .../MySqlX.Data.Tests/ExprParserTests.cs | 277 ++++--- .../tests/MySqlX.Data.Tests/GlobalUsings.cs | 5 - .../MySqlX.Data.Tests/JsonParserTests.cs | 48 +- .../tests/MySqlX.Data.Tests/MergePatch.cs | 678 +++++++++--------- .../PreparedStatementsTests.cs | 226 +++--- .../RelationalTests/ColumnMetadataTests.cs | 140 ++-- .../RelationalTests/DataTypeTests.cs | 209 +++--- .../RelationalTests/DateTimeTests.cs | 30 +- .../RelationalTests/RelationalGCTests.cs | 8 +- .../RelationalTests/RowBufferingTests.cs | 6 +- .../RelationalTests/SqlTests.cs | 158 ++-- .../RelationalTests/TableAsyncTests.cs | 18 +- .../RelationalTests/TableDeleteTests.cs | 14 +- .../RelationalTests/TableInsertTests.cs | 32 +- .../RelationalTests/TableSelectTests.cs | 344 ++++----- .../RelationalTests/TableUpdateTests.cs | 56 +- .../RelationalTests/ViewTests.cs | 46 +- .../tests/MySqlX.Data.Tests/SchemaTests.cs | 46 +- .../tests/MySqlX.Data.Tests/SessionTests.cs | 408 +++++------ .../tests/MySqlX.Data.Tests/SslTests.cs | 270 +++---- .../MySqlX.Data.Tests/TransactionTests.cs | 196 ++--- .../MySqlX.Data.Tests/UnixSocketsTests.cs | 80 +-- MySQL.Data/tests/MySqlX.Data.Tests/XAuth.cs | 162 ++--- .../XConnectionStringBuilderTests.cs | 38 +- MySql.Web/tests/GlobalUsings.cs | 5 - MySql.Web/tests/PersonalizationTests.cs | 14 +- MySql.Web/tests/ProfileTests.cs | 50 +- MySql.Web/tests/RoleManagement.cs | 30 +- MySql.Web/tests/SchemaManagerTests.cs | 112 +-- MySql.Web/tests/SchemaTests.cs | 28 +- MySql.Web/tests/SessionTests.cs | 12 +- MySql.Web/tests/SimpleMembership.cs | 60 +- MySql.Web/tests/SiteMapTests.cs | 32 +- MySql.Web/tests/UserManagement.cs | 192 ++--- 146 files changed, 6997 insertions(+), 7061 deletions(-) delete mode 100644 EFCore/tests/MySql.EFCore.Basic.Tests/GlobalUsings.cs delete mode 100644 EFCore/tests/MySql.EFCore.Design.Tests/GlobalUsings.cs delete mode 100644 EFCore/tests/MySql.EFCore.Migrations.Tests/GlobalUsings.cs delete mode 100644 EntityFramework/tests/MySql.EntityFramework.Basic.Tests/GlobalUsings.cs delete mode 100644 EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/GlobalUsings.cs delete mode 100644 EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/GlobalUsings.cs delete mode 100644 MySQL.Data/tests/MySqlX.Data.Tests/GlobalUsings.cs delete mode 100644 MySql.Web/tests/GlobalUsings.cs diff --git a/CHANGES b/CHANGES index c80c87130..6467ea3be 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,5 @@ 9.1.0 +- Updated test suite to use constraint-based assertions (WL16397). 9.0.0 diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/BasicGuidTests.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/BasicGuidTests.cs index 69bdcc775..3b0eb6bf3 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/BasicGuidTests.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/BasicGuidTests.cs @@ -59,17 +59,17 @@ public void TestEmptyGUID() context.Database.EnsureCreated(); var filter = new[] { Guid.Empty }; var resultFilter = context.Guidtable.Where(t => filter.Contains(t.Uuid)).ToArray(); - Assert.IsNotNull(resultFilter); + Assert.That(resultFilter, Is.Not.Null); Random rnd = new Random(); var guid = Guid.NewGuid(); var record = new GuidTable { Id = rnd.Next(100), Uuid = guid }; context.Guidtable.Add(record); context.SaveChanges(); var rows = context.Guidtable.Count(); - Assert.AreEqual(1, rows); + Assert.That(rows, Is.EqualTo(1)); filter[0] = guid; var resultFilter2 = context.Guidtable.Where(t => filter.Contains(t.Uuid)).ToArray(); - Assert.AreEqual(1, resultFilter2.Count()); + Assert.That(resultFilter2.Count(), Is.EqualTo(1)); } } diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/ConcurrencyTests.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/ConcurrencyTests.cs index 4a2572b8a..a0ac73b84 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/ConcurrencyTests.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/ConcurrencyTests.cs @@ -84,7 +84,7 @@ public void CanHandleConcurrencyConflicts() var originalValue = entry.Property(property.Name).OriginalValue; var databaseValue = databaseEntry.Property(property.Name).CurrentValue; entry.Property(property.Name).OriginalValue = databaseEntry.Property(property.Name).CurrentValue; - Assert.AreEqual("Jane", databaseValue); + Assert.That(databaseValue, Is.EqualTo("Jane")); } } } diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/ConnectionTests.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/ConnectionTests.cs index c54c09f04..e919b9341 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/ConnectionTests.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/ConnectionTests.cs @@ -137,7 +137,7 @@ public void CanCreateConnectionString() { using (var connection = CreateConnection(CreateOptions())) { - Assert.IsInstanceOf(connection.DbConnection); + Assert.That(connection.DbConnection, Is.InstanceOf()); } } @@ -150,10 +150,10 @@ public void CanCreateMainConnection() { var csb = new MySqlConnectionStringBuilder(source.ConnectionString); var csb1 = new MySqlConnectionStringBuilder(MySQLTestStore.BaseConnectionString); - Assert.True(csb.Database == csb1.Database); - Assert.True(csb.Port == csb1.Port); - Assert.True(csb.Server == csb1.Server); - Assert.True(csb.UserID == csb1.UserID); + Assert.That(csb.Database, Is.EqualTo(csb1.Database)); + Assert.That(csb.Port, Is.EqualTo(csb1.Port)); + Assert.That(csb.Server, Is.EqualTo(csb1.Server)); + Assert.That(csb.UserID, Is.EqualTo(csb1.UserID)); } } } diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/DataTests.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/DataTests.cs index a542c2e30..39db69db3 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/DataTests.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/DataTests.cs @@ -68,17 +68,17 @@ public async Task AsyncData() var result = context.SaveChangesAsync(); result.Wait(30_000); - Assert.IsNull(result.Exception); - Assert.AreEqual(4, result.Result); + Assert.That(result.Exception, Is.Null); + Assert.That(result.Result, Is.EqualTo(4)); } using (var context = new WorldContext()) { var continent = await context.FindAsync("AS"); - Assert.AreEqual("Asia", continent!.Name); + Assert.That(continent!.Name, Is.EqualTo("Asia")); var continents = await context.Continents.ToListAsync(); - Assert.AreEqual(4, continents.Count); + Assert.That(continents.Count, Is.EqualTo(4)); } } @@ -94,10 +94,10 @@ public void ZeroDatetime() context.Database.EnsureDeleted(); context.Database.EnsureCreated(); - Assert.AreEqual(1, context.Database.ExecuteSqlInterpolated($"INSERT IGNORE INTO MyTest (`Date`) VALUES('0000-00-00')")); + Assert.That(context.Database.ExecuteSqlInterpolated($"INSERT IGNORE INTO MyTest (`Date`) VALUES('0000-00-00')"), Is.EqualTo(1)); var item = context.MyTest.First(); - Assert.AreEqual(DateTime.MinValue, item.Date); + Assert.That(item.Date, Is.EqualTo(DateTime.MinValue)); } } diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/DbFunctionsMySQLTest.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/DbFunctionsMySQLTest.cs index 1085dba0f..3cab9cf34 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/DbFunctionsMySQLTest.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/DbFunctionsMySQLTest.cs @@ -68,7 +68,7 @@ public void DateDiffYear() var yearsDiff = DateTime.Now.Year - lastUpdate.Year; var count = context.Actor.Count(a => EF.Functions.DateDiffYear(a.LastUpdate, DateTime.Now) > 0); - Assert.AreEqual(200, count); + Assert.That(count, Is.EqualTo(200)); } } @@ -81,7 +81,7 @@ public void DateDiffMonth() var count = context.Actor .Count(a => EF.Functions.DateDiffMonth(a.LastUpdate, DateTime.Now) >= monthsDiff - 1); - Assert.AreEqual(200, count); + Assert.That(count, Is.EqualTo(200)); } } @@ -94,7 +94,7 @@ public void DateDiffDay() var count = context.Actor .Count(a => EF.Functions.DateDiffDay(a.LastUpdate, DateTime.Now) == daysDiff); - Assert.AreEqual(200, count, "TotalDays: " + daysDiff); + Assert.That(count, Is.EqualTo(200), "TotalDays: " + daysDiff); } } @@ -107,7 +107,7 @@ public void DateDiffHour() var count = context.Actor .Count(a => EF.Functions.DateDiffHour(a.LastUpdate, DateTime.Now) == hoursDiff); - Assert.AreEqual(200, count, "TotalHours: " + hoursDiff); + Assert.That(count, Is.EqualTo(200), "TotalHours: " + hoursDiff); } } @@ -120,7 +120,7 @@ public void DateDiffMinute() var count = context.Actor .Count(a => EF.Functions.DateDiffMinute(a.LastUpdate, DateTime.Now) == minutesDiff); - Assert.AreEqual(200, count, "TotalMinutes: " + minutesDiff); + Assert.That(count, Is.EqualTo(200), "TotalMinutes: " + minutesDiff); } } @@ -133,7 +133,7 @@ public void DateDiffSecond() var count = context.Actor .Count(a => EF.Functions.DateDiffSecond(a.LastUpdate, DateTime.Now) >= secondsDiff); - Assert.AreEqual(200, count, "TotalSeconds: " + secondsDiff); + Assert.That(count, Is.EqualTo(200), "TotalSeconds: " + secondsDiff); } } @@ -145,7 +145,7 @@ public void DateDiffMicrosecond() var count = context.Actor .Count(a => EF.Functions.DateDiffMicrosecond(a.LastUpdate, DateTime.Now) == 0); - Assert.AreEqual(0, count); + Assert.That(count, Is.EqualTo(0)); } } @@ -156,7 +156,7 @@ public void LikeIntLiteral() { var count = context.Actor.Count(o => EF.Functions.Like(o.ActorId, "%A%")); - Assert.AreEqual(0, count); + Assert.That(count, Is.EqualTo(0)); } } @@ -167,7 +167,7 @@ public void LikeDateTimeLiteral() { var count = context.Actor.Count(o => EF.Functions.Like(o.LastUpdate, "%A%")); - Assert.AreEqual(0, count); + Assert.That(count, Is.EqualTo(0)); } } @@ -178,7 +178,7 @@ public void LikeIntLiteralWithEscape() { var count = context.Actor.Count(o => EF.Functions.Like(o.ActorId, "!%", "!")); - Assert.AreEqual(0, count); + Assert.That(count, Is.EqualTo(0)); } } } diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/EFCoreTests.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/EFCoreTests.cs index fd84eb897..d062758c1 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/EFCoreTests.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/EFCoreTests.cs @@ -51,8 +51,8 @@ public void ExplicitlyCompiledQueries() using (SakilaLiteContext context = new SakilaLiteContext()) { var customer = _customerById(context, 9); - Assert.AreEqual(9, customer.CustomerId); - Assert.AreEqual("MOORE", customer.LastName); + Assert.That(customer.CustomerId, Is.EqualTo(9)); + Assert.That(customer.LastName, Is.EqualTo("MOORE")); } } @@ -68,14 +68,14 @@ public void GraphNewAndExistingEntities() context.Attach(actor = new Actor { ActorId = 21, FirstName = "KIRSTEN", LastName = "PALTROW" }); var changes = context.ChangeTracker.Entries(); - Assert.AreEqual(2, changes.Count()); + Assert.That(changes.Count(), Is.EqualTo(2)); Assert.That(changes.Select(c => c.State), Has.Exactly(1).Matches(state => state.Equals(EntityState.Added))); Assert.That(changes.Select(c => c.State), Has.Exactly(1).Matches(state => state.Equals(EntityState.Unchanged))); context.SaveChanges(); var list = context.Actor.ToList(); - Assert.AreEqual(1, list.Count); + Assert.That(list.Count, Is.EqualTo(1)); } } @@ -93,8 +93,8 @@ public void StringInterpolationInSqlCommands() context.Database.ExecuteSqlInterpolated($"INSERT INTO actor(actor_id, first_name, last_name, last_update) VALUES ({id}, {firstName}, {lastName}, {lastUpdate:u})"); Actor actor = context.Set().FromSqlInterpolated($"SELECT * FROM actor WHERE actor_id={id} and last_name={lastName}").First(); - Assert.AreEqual(id, actor.ActorId); - Assert.AreEqual(firstName, actor.FirstName); + Assert.That(actor.ActorId, Is.EqualTo(id)); + Assert.That(actor.FirstName, Is.EqualTo(firstName)); } } @@ -156,7 +156,7 @@ public void QueryWithDate() && w.LastUpdate >= DateTime.Today.AddDays(-15)); var res = scenario1.Count(); - Assert.AreEqual(0, res); + Assert.That(res, Is.EqualTo(0)); var dt = DateTime.Today.AddDays(-15); var scenario2 = context.Actor.Where( @@ -165,7 +165,7 @@ public void QueryWithDate() && w.LastUpdate >= dt); var res2 = scenario2.Count(); - Assert.AreEqual(0, res2); + Assert.That(res2, Is.EqualTo(0)); var scenario3 = context.Actor.Where( w => w.FirstName == "GARY" @@ -173,7 +173,7 @@ public void QueryWithDate() && w.LastUpdate >= DateTime.Today.AddDays(3)); var res3 = scenario3.Count(); - Assert.AreEqual(0, res3); + Assert.That(res3, Is.EqualTo(0)); } } diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/FluentAPITests.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/FluentAPITests.cs index c34dd7f03..8a81ddb6f 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/FluentAPITests.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/FluentAPITests.cs @@ -76,7 +76,7 @@ public void EnsureRelationalPatterns() context.Employees.Add(e); context.SaveChanges(); var employeeComputedColumn = context.Employees.FirstOrDefault(); - Assert.True(employeeComputedColumn!.DisplayName!.Equals("Stuart Jos"), "Wrong computed column"); + Assert.That(employeeComputedColumn!.DisplayName!.Equals("Stuart Jos"), "Wrong computed column"); context.Database.EnsureDeleted(); } } @@ -101,7 +101,7 @@ public void CanUseModelWithDateTimeOffset() context.QuickEntity.Add(e); context.SaveChanges(); var row = context.QuickEntity.FirstOrDefault(); - Assert.AreEqual(dt, row!.Created); + Assert.That(row!.Created, Is.EqualTo(dt)); } finally { @@ -130,7 +130,7 @@ public async Task CanUseModelWithDateTimeOffsetAsync() context.QuickEntity.Add(e); context.SaveChanges(); var result = await context.QuickEntity.FirstOrDefaultAsync(); - Assert.AreEqual(dt, result!.Created); + Assert.That(result!.Created, Is.EqualTo(dt)); } catch (Exception) { @@ -164,7 +164,7 @@ public void CanNameAlternateKey() var reader = cmd.ExecuteReader(); while (reader.Read()) { - Assert.True(reader.GetString(1).ToString().Equals("AlternateKey_LicensePlate"), "Wrong index creation"); + Assert.That(reader.GetString(1).ToString().Equals("AlternateKey_LicensePlate"), "Wrong index creation"); } } } @@ -189,7 +189,7 @@ public void CanUseToTable() var reader = cmd.ExecuteReader(); while (reader.Read()) { - Assert.True(reader.GetString(0).ToString().Equals("somecars"), "Wrong table name"); + Assert.That(reader.GetString(0).ToString().Equals("somecars"), "Wrong table name"); } } context.Database.EnsureDeleted(); @@ -216,7 +216,7 @@ public void CanUseConcurrency() var reader = cmd.ExecuteReader(); while (reader.Read()) { - Assert.True(reader.GetString(0).ToString().Equals("somecars"), "Wrong table name"); + Assert.That(reader.GetString(0).ToString().Equals("somecars"), "Wrong table name"); } } context.Database.EnsureDeleted(); @@ -247,7 +247,7 @@ public void CanUseConcurrencyToken() context.Employees.Add(e); context.SaveChanges(); var employeeComputedColumn = context.Employees.SingleOrDefault(); - Assert.True(employeeComputedColumn!.DisplayName!.Equals("Stuart Jos"), "Wrong computed column"); + Assert.That(employeeComputedColumn!.DisplayName!.Equals("Stuart Jos"), "Wrong computed column"); context.Database.EnsureDeleted(); } } @@ -329,9 +329,9 @@ public void CanUseContainsWithInvalidValue() context.Employees.Add(e); context.SaveChanges(); var result = context.Employees.Where(t => t.FirstName!.Contains("XXXXXXXX$%^&*()!")).ToList(); - Assert.IsEmpty(result); + Assert.That(result, Is.Empty); result = context.Employees.Where(t => t.FirstName!.Contains("null")).ToList(); - Assert.IsEmpty(result); + Assert.That(result, Is.Empty); context.Database.EnsureDeleted(); } } @@ -378,10 +378,10 @@ public void TableAttributeTest() MySqlCommand cmd = new MySqlCommand("SHOW TABLES", conn); using (MySqlDataReader reader = cmd.ExecuteReader()) { - Assert.True(reader.Read()); - StringAssert.AreEqualIgnoringCase("continentlist", reader.GetString(0)); - Assert.True(reader.Read()); - StringAssert.AreEqualIgnoringCase("countrylist", reader.GetString(0)); + Assert.That(reader.Read()); + Assert.That(reader.GetString(0), Is.EqualTo("continentlist").IgnoreCase); + Assert.That(reader.Read()); + Assert.That(reader.GetString(0), Is.EqualTo("countrylist").IgnoreCase); } } @@ -407,7 +407,7 @@ public void CharsetTest() string createTable = reader.GetString(1); createTable = Regex.Replace(createTable, @"\t|\n|\r", string.Empty); string txt = "CREATE TABLE `testcharsetda` ( `TestCharsetDAId` varbinary(255) NOT NULL, PRIMARY KEY (`TestCharsetDAId`)) ENGINE=InnoDB DEFAULT CHARSET=ascii"; - StringAssert.AreEqualIgnoringCase(txt, createTable); + Assert.That(createTable, Is.EqualTo(txt).IgnoreCase); } cmd.CommandText = "SHOW CREATE TABLE `TestCharsetFA`"; @@ -422,12 +422,12 @@ public void CharsetTest() if (createTable.Contains("COLLATE latin7_general_ci")) { txt = "CREATE TABLE `testcharsetfa` ( `TestCharsetFAId` varchar(255) CHARACTER SET latin7 COLLATE latin7_general_ci NOT NULL, PRIMARY KEY (`TestCharsetFAId`)) ENGINE=InnoDB DEFAULT CHARSET=utf16"; - StringAssert.AreEqualIgnoringCase(txt, createTable); + Assert.That(createTable, Is.EqualTo(txt).IgnoreCase); } else { txt = "CREATE TABLE `testcharsetfa` ( `TestCharsetFAId` varchar(255) CHARACTER SET latin7 NOT NULL, PRIMARY KEY (`TestCharsetFAId`)) ENGINE=InnoDB DEFAULT CHARSET=utf16"; - StringAssert.AreEqualIgnoringCase(txt, createTable); + Assert.That(createTable, Is.EqualTo(txt).IgnoreCase); } } @@ -438,7 +438,7 @@ public void CharsetTest() string createTable = reader.GetString(1); createTable = Regex.Replace(createTable, @"\t|\n|\r", string.Empty); string txt = "CREATE TABLE `testcollationda` ( `TestCollationDAId` varchar(255) CHARACTER SET greek COLLATE greek_bin NOT NULL, PRIMARY KEY (`TestCollationDAId`)) ENGINE=InnoDB DEFAULT CHARSET=cp932 COLLATE=cp932_bin"; - StringAssert.AreEqualIgnoringCase(txt, createTable); + Assert.That(createTable, Is.EqualTo(txt).IgnoreCase); } cmd.CommandText = "SHOW CREATE TABLE `TestCollationFA`"; @@ -448,7 +448,7 @@ public void CharsetTest() string createTable = reader.GetString(1); createTable = Regex.Replace(createTable, @"\t|\n|\r", string.Empty); string txt = "CREATE TABLE `testcollationfa` ( `TestCollationFAId` varchar(255) CHARACTER SET ucs2 COLLATE ucs2_bin NOT NULL, PRIMARY KEY (`TestCollationFAId`)) ENGINE=InnoDB DEFAULT CHARSET=koi8u COLLATE=koi8u_bin"; - StringAssert.AreEqualIgnoringCase(txt, createTable); + Assert.That(createTable, Is.EqualTo(txt).IgnoreCase); } } } diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/FunctionalTests.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/FunctionalTests.cs index 6c0d235c2..ef926a1b6 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/FunctionalTests.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/FunctionalTests.cs @@ -62,7 +62,7 @@ public void CanConnectWithConnectionOnConfiguring() { context.Database.EnsureDeleted(); context.Database.EnsureCreated(); - Assert.True(context.Posts.Count() == 0); + Assert.That(context.Posts.Count(), Is.EqualTo(0)); context.Database.EnsureDeleted(); } } @@ -79,7 +79,7 @@ public void CanThrowExceptionWhenNoConfiguration() using (var context = serviceProvider.GetRequiredService()) { - Assert.AreEqual(CoreStrings.NoProviderConfigured, Assert.Throws(() => context.Blogs.Any())!.Message); + Assert.That(Assert.Throws(() => context.Blogs.Any())!.Message, Is.EqualTo(CoreStrings.NoProviderConfigured)); } } @@ -104,7 +104,7 @@ public void CreatedDb() var reader = cmd.ExecuteReader(); while (reader.Read()) { - Assert.True(string.Equals(dbname, reader.GetString(0), StringComparison.CurrentCultureIgnoreCase), "Database was not created"); + Assert.That(string.Equals(dbname, reader.GetString(0), StringComparison.CurrentCultureIgnoreCase), "Database was not created"); } } context.Database.EnsureDeleted(); @@ -132,7 +132,7 @@ public void EnsureRelationalPatterns() var reader = cmd.ExecuteReader(); while (reader.Read()) { - Assert.True(string.Equals(dbname, reader.GetString(0), StringComparison.CurrentCultureIgnoreCase), "Database was not created"); + Assert.That(string.Equals(dbname, reader.GetString(0), StringComparison.CurrentCultureIgnoreCase), "Database was not created"); } } context.Database.EnsureDeleted(); @@ -152,8 +152,8 @@ public void CanUseIgnoreEntity() using (var context = serviceProvider.GetRequiredService()) { context.Database.EnsureCreated(); - Assert.True(context.Model.GetEntityTypes().Count() == 2, "Wrong model generation"); - Assert.True(context.Blogs.ToList().Count == 0, ""); + Assert.That(context.Model.GetEntityTypes().Count(), Is.EqualTo(2), "Wrong model generation"); + Assert.That(context.Blogs.ToList().Count, Is.EqualTo(0), ""); context.Database.EnsureDeleted(); } } @@ -167,7 +167,7 @@ public void CanUseOptionsInDbContextCtor() new MySqlConnection(MySQLTestStore.CreateConnectionString("db-optionsindbcontext")))) { context.Database.EnsureCreated(); - Assert.True(context.Blogs.Count() == 0); + Assert.That(context.Blogs.Count(), Is.EqualTo(0)); context.Database.EnsureDeleted(); } @@ -205,11 +205,11 @@ public OptionsContext(DbContextOptions options, MySqlConnection connection) protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { - Assert.AreSame(_options, optionsBuilder.Options); + Assert.That(optionsBuilder.Options, Is.SameAs(_options)); optionsBuilder.UseMySQL(_connection); - Assert.AreNotSame(_options, optionsBuilder.Options); + Assert.That(optionsBuilder.Options, Is.Not.SameAs(_options)); } public override void Dispose() diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/GlobalUsings.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/GlobalUsings.cs deleted file mode 100644 index 575c7cfd0..000000000 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/GlobalUsings.cs +++ /dev/null @@ -1,5 +0,0 @@ -global using Assert = NUnit.Framework.Legacy.ClassicAssert; -global using CollectionAssert = NUnit.Framework.Legacy.CollectionAssert; -global using StringAssert = NUnit.Framework.Legacy.StringAssert; -global using DirectoryAssert = NUnit.Framework.Legacy.DirectoryAssert; -global using FileAssert = NUnit.Framework.Legacy.FileAssert; diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/LoadingRelatedDataTests.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/LoadingRelatedDataTests.cs index cec6177a3..4378672b3 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/LoadingRelatedDataTests.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/LoadingRelatedDataTests.cs @@ -63,7 +63,7 @@ public void OneTimeTearDown() [Test] public void CanUseSkipAndTake() { - Assert.False(context.Database.EnsureCreated()); + Assert.That(!context.Database.EnsureCreated()); var people = context.Set() .Skip(2) @@ -76,56 +76,56 @@ var people [Test] public void CanIncludeAddressData() { - Assert.False(context.Database.EnsureCreated()); + Assert.That(!context.Database.EnsureCreated()); var people = context.Set() .Include(p => p.Address) .ToList(); - Assert.AreEqual(4, people.Count); - Assert.AreEqual(3, people.Count(p => p.Address != null)); + Assert.That(people.Count, Is.EqualTo(4)); + Assert.That(people.Count(p => p.Address != null), Is.EqualTo(3)); } [Test] public void CanIncludeGuestData() { - Assert.False(context.Database.EnsureCreated()); + Assert.That(!context.Database.EnsureCreated()); var ad = context.Set
() .Include(p => p.Guest) .ToList(); - Assert.AreEqual(3, ad.Count); + Assert.That(ad.Count, Is.EqualTo(3)); var rows = ad.Select(g => g.Guest).Where(a => a != null).ToList(); - Assert.AreEqual(3, rows.Count()); + Assert.That(rows.Count(), Is.EqualTo(3)); } [Test] public void CanIncludeGuestShadowProperty() { - Assert.False(context.Database.EnsureCreated()); + Assert.That(!context.Database.EnsureCreated()); var addressRelative = context.Set() .Include(a => a.Relative) .ToList(); - Assert.AreEqual(3, addressRelative.Count); - Assert.True(addressRelative.All(p => p.Relative != null)); + Assert.That(addressRelative.Count, Is.EqualTo(3)); + Assert.That(addressRelative.All(p => p.Relative != null)); } [Test] public void MixClientServerEvaluation() { - Assert.False(context.Database.EnsureCreated()); + Assert.That(!context.Database.EnsureCreated()); var list = context.Set
() .OrderByDescending(a => a.City) .Select(a => new { Id = a.IdAddress, City = SetCity(a.City!) }) .ToList(); - Assert.AreEqual(3, list.Count); - StringAssert.EndsWith(" city", list.First().City); + Assert.That(list.Count, Is.EqualTo(3)); + Assert.That(list.First().City, Does.EndWith(" city")); } private static string SetCity(string name) @@ -136,16 +136,16 @@ private static string SetCity(string name) [Test] public void RawSqlQueries() { - Assert.False(context.Database.EnsureCreated()); + Assert.That(!context.Database.EnsureCreated()); var guests = context.Set().FromSqlRaw("SELECT * FROM Guests") .ToList(); - Assert.AreEqual(4, guests.Count); + Assert.That(guests.Count, Is.EqualTo(4)); } [Test] public void UsingTransactions() { - Assert.False(context.Database.EnsureCreated()); + Assert.That(!context.Database.EnsureCreated()); using (var transaction = context.Database.BeginTransaction()) { context.Set().Add(new Guest() @@ -154,15 +154,15 @@ public void UsingTransactions() }); context.SaveChanges(); } - Assert.AreEqual(4, context.Set().Count()); + Assert.That(context.Set().Count(), Is.EqualTo(4)); } [Test] public void DbSetFind() { var address = context.Set
().Find(1); - Assert.NotNull(address); - Assert.AreEqual("Michigan", address!.City); + Assert.That(address, Is.Not.Null); + Assert.That(address!.City, Is.EqualTo("Michigan")); } @@ -199,10 +199,10 @@ public void JsonDataTest() } //Adding "COLLATION" to the string validation at table creation (this happens since MySql 8.0.5 Server) if (jsonTableDesc.Contains("COLLATE=utf8mb4_0900_ai_ci")) - StringAssert.AreEqualIgnoringCase($"CREATE TABLE `jsonentity` (\n `Id` smallint{smallintWidth} NOT NULL AUTO_INCREMENT," + - $"\n `jsoncol` json DEFAULT NULL,\n PRIMARY KEY (`Id`)\n) ENGINE=InnoDB DEFAULT CHARSET={charset} COLLATE=utf8mb4_0900_ai_ci", jsonTableDesc); - else StringAssert.AreEqualIgnoringCase($"CREATE TABLE `jsonentity` (\n `Id` smallint{smallintWidth} NOT NULL AUTO_INCREMENT,\n `jsoncol` json DEFAULT NULL,\n PRIMARY KEY (`Id`)\n) " + - $"ENGINE=InnoDB DEFAULT CHARSET={charset}", jsonTableDesc); + Assert.That(jsonTableDesc, Is.EqualTo($"CREATE TABLE `jsonentity` (\n `Id` smallint{smallintWidth} NOT NULL AUTO_INCREMENT," + + $"\n `jsoncol` json DEFAULT NULL,\n PRIMARY KEY (`Id`)\n) ENGINE=InnoDB DEFAULT CHARSET={charset} COLLATE=utf8mb4_0900_ai_ci").IgnoreCase); + else Assert.That(jsonTableDesc, Is.EqualTo($"CREATE TABLE `jsonentity` (\n `Id` smallint{smallintWidth} NOT NULL AUTO_INCREMENT,\n `jsoncol` json DEFAULT NULL,\n PRIMARY KEY (`Id`)\n) " + + $"ENGINE=InnoDB DEFAULT CHARSET={charset}").IgnoreCase); } context.JsonEntity.Add(new JsonData() @@ -211,7 +211,7 @@ public void JsonDataTest() }); context.SaveChanges(); JsonData json = context.JsonEntity.First(); - Assert.AreEqual("{ \"name\": \"Ronald\", \"city\": \"Austin\" }", json.jsoncol); + Assert.That(json.jsoncol, Is.EqualTo("{ \"name\": \"Ronald\", \"city\": \"Austin\" }")); } } @@ -234,7 +234,7 @@ public void JsonInvalidData() }); var ex = Assert.Throws(() => context.SaveChanges())?.GetBaseException(); - Assert.AreEqual(3140, ((MySqlException)ex!).Number); + Assert.That(((MySqlException)ex!).Number, Is.EqualTo(3140)); } } @@ -266,8 +266,8 @@ public void ComputedColumns() context.Triangle.AddRange(data); context.Triangle.Add(data[1]); context.SaveChanges(); - Assert.AreEqual(75, data[0].Area); - Assert.AreEqual(50, data[1].Area); + Assert.That(data[0].Area, Is.EqualTo(75)); + Assert.That(data[1].Area, Is.EqualTo(50)); } } @@ -278,12 +278,12 @@ public void ExplicitLoading() { context.PopulateData(); var america = context.Continents.Single(c => c.Code == "AM"); - Assert.Null(america.Countries); + Assert.That(america.Countries, Is.Null); context.Entry(america) .Collection(c => c.Countries!) .Load(); - Assert.AreEqual(5, america.Countries!.Count); - Assert.AreEqual("United States", america.Countries.Single(c => c.Code == "US").Name); + Assert.That(america.Countries!.Count, Is.EqualTo(5)); + Assert.That(america.Countries.Single(c => c.Code == "US").Name, Is.EqualTo("United States")); } } @@ -294,7 +294,7 @@ public void ExplicitLoadingQueryingRelatedEntitites() { context.PopulateData(); var asia = context.Continents.Single(c => c.Code == "AS"); - Assert.Null(asia.Countries); + Assert.That(asia.Countries, Is.Null); var list = context.Entry(asia) .Collection(c => c.Countries!) .Query() diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/ModelingTests.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/ModelingTests.cs index cf1746d64..8ba63fd0b 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/ModelingTests.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/ModelingTests.cs @@ -124,10 +124,10 @@ public void LikeFunction() using (SakilaLiteContext context = new SakilaLiteContext()) { var query = context.Actor.Where(c => EF.Functions.Like(c.LastName!, "A%")).ToList(); - Assert.IsNotEmpty(query); + Assert.That(query, Is.Not.Empty); foreach (Actor actor in query) { - StringAssert.StartsWith("A", actor.LastName); + Assert.That(actor.LastName, Does.StartWith("A")); } } } @@ -158,8 +158,8 @@ public void OwnedEntityTypes() context.SaveChanges(); var customer = context.Customer.Where(p => p.Address!.AddressId == 1).First(); - Assert.AreEqual(1, customer.CustomerId); - Assert.AreEqual("47 MySakila Drive", customer.Address!.Address); + Assert.That(customer.CustomerId, Is.EqualTo(1)); + Assert.That(customer.Address!.Address, Is.EqualTo("47 MySakila Drive")); } finally { @@ -173,8 +173,8 @@ public void ModelLevelQueryFilter() { using (SakilaLiteContext context = new SakilaLiteContext()) { - Assert.AreEqual(584, context.Customer.Count()); - Assert.AreEqual(599, context.Customer.IgnoreQueryFilters().Count()); + Assert.That(context.Customer.Count(), Is.EqualTo(584)); + Assert.That(context.Customer.IgnoreQueryFilters().Count(), Is.EqualTo(599)); } } @@ -194,7 +194,7 @@ public void ConvertToType() Text = b.FirstName, }).ToList(); - Assert.IsNotEmpty(ls); + Assert.That(ls, Is.Not.Empty); } } } diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/MultiSchemaTests.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/MultiSchemaTests.cs index c40e6a61f..0a4959aed 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/MultiSchemaTests.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/MultiSchemaTests.cs @@ -77,11 +77,11 @@ public void MultiSchemaTest() { while (reader.Read()) { - Assert.Contains(reader.GetString(0), databases); + Assert.That(databases.Contains(reader.GetString(0))); count++; } } - Assert.AreEqual(3, count); + Assert.That(count, Is.EqualTo(3)); } } } @@ -137,9 +137,9 @@ public void LoadingData() }); context.SaveChanges(); - Assert.AreEqual(2, context.Car.Count()); - Assert.AreEqual(2, context.BodyShop.Count()); - Assert.AreEqual(2, context.Employee.Count()); + Assert.That(context.Car.Count(), Is.EqualTo(2)); + Assert.That(context.BodyShop.Count(), Is.EqualTo(2)); + Assert.That(context.Employee.Count(), Is.EqualTo(2)); } } diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/MySQLDatabaseFacadeTest.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/MySQLDatabaseFacadeTest.cs index 6fb864f2b..1ce799ba6 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/MySQLDatabaseFacadeTest.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/MySQLDatabaseFacadeTest.cs @@ -46,7 +46,7 @@ public void IsMySQLWhenUsingOnConfiguring() { using (var context = new MySQLOnConfiguringContext()) { - Assert.True(context.Database.IsMySql()); + Assert.That(context.Database.IsMySql()); } } @@ -56,7 +56,7 @@ public void IsMySQLInOnModelCreatingWhenUsingOnConfiguring() using (var context = new MySQLOnModelContext()) { var _ = context.Model; // Trigger context initialization - Assert.True(context.IsMySQLSet); + Assert.That(context.IsMySQLSet == true); } } @@ -66,7 +66,7 @@ public void IsMySQLInConstructorWhenUsingOnConfiguring() using (var context = new MySQLConstructorContext()) { var _ = context.Model; // Trigger context initialization - Assert.True(context.IsMySQLSet); + Assert.That(context.IsMySQLSet == true); } } @@ -75,13 +75,12 @@ public void CannotUseIsMySQLInOnConfiguring() { using (var context = new MySQLUseInOnConfiguringContext()) { - Assert.AreEqual( - CoreStrings.RecursiveOnConfiguring, + Assert.That( Assert.Throws( () => { var _ = context.Model; // Trigger context initialization - })!.Message); + })!.Message, Is.EqualTo(CoreStrings.RecursiveOnConfiguring)); } } @@ -93,7 +92,7 @@ public void IsMySQLWhenUsingConstructor() .UseInternalServiceProvider(MySQLFixture.DefaultServiceProvider) .UseMySQL("Database=Maltesers").Options)) { - Assert.True(context.Database.IsMySql()); + Assert.That(context.Database.IsMySql()); } } @@ -106,7 +105,7 @@ public void IsMySQLInOnModelCreatingWhenUsingConstructor() .UseMySQL("Database=Maltesers").Options)) { var _ = context.Model; // Trigger context initialization - Assert.True(context.IsMySQLSet); + Assert.That(context.IsMySQLSet == true); } } @@ -119,7 +118,7 @@ public void IsMySQLInConstructorWhenUsingConstructor() .UseMySQL("Database=Maltesers").Options)) { var _ = context.Model; // Trigger context initialization - Assert.True(context.IsMySQLSet); + Assert.That(context.IsMySQLSet == true); } } @@ -131,13 +130,12 @@ public void CannotUseIsMySQLInOnConfiguringWithConstructor() .UseInternalServiceProvider(MySQLFixture.DefaultServiceProvider) .UseMySQL("Database=Maltesers").Options)) { - Assert.AreEqual( - CoreStrings.RecursiveOnConfiguring, + Assert.That( Assert.Throws( () => { var _ = context.Model; // Trigger context initialization - })!.Message); + })!.Message, Is.EqualTo(CoreStrings.RecursiveOnConfiguring)); } } diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/MySQLTypeMapperTests.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/MySQLTypeMapperTests.cs index b4aedf779..8e7173496 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/MySQLTypeMapperTests.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/MySQLTypeMapperTests.cs @@ -103,33 +103,33 @@ public void InsertAllDataTypes() using (var context = new AllDataTypesContext()) { var data = context.AllDataTypes.First(); - Assert.AreEqual(1, data.AddressNumber1); - Assert.AreEqual(2, data.AddressNumber2); - Assert.AreEqual(3, data.AddressNumber3); - Assert.AreEqual(4, data.AddressNumber4); - Assert.AreEqual((long)5, data.AddressNumber5); - Assert.AreEqual(6.36f, data.AddressNumber6); - Assert.AreEqual(7.49f, data.AddressNumber7); - Assert.AreEqual(8.64d, data.AddressNumber8); - Assert.AreEqual(9.81m, data.AddressNumber9); - Assert.AreEqual(10, data.AddressNumber10); - Assert.AreEqual("BuildingName1", data.BuildingName1); - Assert.AreEqual("BuildingName2", data.BuildingName2); - Assert.AreEqual("BuildingName3", data.BuildingName3); - Assert.AreEqual("BuildingName4", data.BuildingName4); - Assert.AreEqual("BuildingName5", data.BuildingName5); - Assert.AreEqual("BuildingName6".PadRight(120, '\0'), UTF8Encoding.UTF8.GetString(data.BuildingName6!)); - Assert.AreEqual("BuildingName7", UTF8Encoding.UTF8.GetString(data.BuildingName7!)); - Assert.AreEqual("BuildingName8", UTF8Encoding.UTF8.GetString(data.BuildingName8!)); - Assert.AreEqual("BuildingName9", UTF8Encoding.UTF8.GetString(data.BuildingName9!)); - Assert.AreEqual("BuildingName10", UTF8Encoding.UTF8.GetString(data.BuildingName10!)); - Assert.AreEqual("small", data.BuildingName11); - Assert.AreEqual("small,medium,large", data.BuildingName12); - Assert.AreEqual(now.Date, data.BuildingName13); - Assert.AreEqual(now, data.BuildingName14); - Assert.AreEqual(now.TimeOfDay, data.BuildingName15); - Assert.AreEqual(now, data.BuildingName16); - Assert.AreEqual(now.Year, data.BuildingName17); + Assert.That(data.AddressNumber1, Is.EqualTo(1)); + Assert.That(data.AddressNumber2, Is.EqualTo(2)); + Assert.That(data.AddressNumber3, Is.EqualTo(3)); + Assert.That(data.AddressNumber4, Is.EqualTo(4)); + Assert.That(data.AddressNumber5, Is.EqualTo((long)5)); + Assert.That(data.AddressNumber6, Is.EqualTo(6.36f)); + Assert.That(data.AddressNumber7, Is.EqualTo(7.49f)); + Assert.That(data.AddressNumber8, Is.EqualTo(8.64d)); + Assert.That(data.AddressNumber9, Is.EqualTo(9.81m)); + Assert.That(data.AddressNumber10, Is.EqualTo(10)); + Assert.That(data.BuildingName1, Is.EqualTo("BuildingName1")); + Assert.That(data.BuildingName2, Is.EqualTo("BuildingName2")); + Assert.That(data.BuildingName3, Is.EqualTo("BuildingName3")); + Assert.That(data.BuildingName4, Is.EqualTo("BuildingName4")); + Assert.That(data.BuildingName5, Is.EqualTo("BuildingName5")); + Assert.That(UTF8Encoding.UTF8.GetString(data.BuildingName6!), Is.EqualTo("BuildingName6".PadRight(120, '\0'))); + Assert.That(UTF8Encoding.UTF8.GetString(data.BuildingName7!), Is.EqualTo("BuildingName7")); + Assert.That(UTF8Encoding.UTF8.GetString(data.BuildingName8!), Is.EqualTo("BuildingName8")); + Assert.That(UTF8Encoding.UTF8.GetString(data.BuildingName9!), Is.EqualTo("BuildingName9")); + Assert.That(UTF8Encoding.UTF8.GetString(data.BuildingName10!), Is.EqualTo("BuildingName10")); + Assert.That(data.BuildingName11, Is.EqualTo("small")); + Assert.That(data.BuildingName12, Is.EqualTo("small,medium,large")); + Assert.That(data.BuildingName13, Is.EqualTo(now.Date)); + Assert.That(data.BuildingName14, Is.EqualTo(now)); + Assert.That(data.BuildingName15, Is.EqualTo(now.TimeOfDay)); + Assert.That(data.BuildingName16, Is.EqualTo(now)); + Assert.That(data.BuildingName17, Is.EqualTo(now.Year)); } } @@ -169,9 +169,9 @@ public void LongBlobMapping() var data = context.AllBlobTypes.First(); - Assert.AreEqual(data1.Length, data.Example1.Length); - Assert.AreEqual(data2.Length, data.Example2.Length); - Assert.AreEqual(data3.Length, data.Example3.Length); + Assert.That(data.Example1.Length, Is.EqualTo(data1.Length)); + Assert.That(data.Example2.Length, Is.EqualTo(data2.Length)); + Assert.That(data.Example3.Length, Is.EqualTo(data3.Length)); } } @@ -203,10 +203,10 @@ public void ValidateStringLength() { string field = reader.GetString("field"); string type = validation[field]; - Assert.AreEqual(type, reader.GetString("type")); + Assert.That(reader.GetString("type"), Is.EqualTo(type)); counter++; } - Assert.AreEqual(validation.Count, counter); + Assert.That(counter, Is.EqualTo(validation.Count)); } } } diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/ShadowPropertiesTests.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/ShadowPropertiesTests.cs index bd957825b..cbc676c76 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/ShadowPropertiesTests.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/ShadowPropertiesTests.cs @@ -60,7 +60,7 @@ public ShadowPropertiesTests() [Test] public void CanUseShadowPropertyWhenUpdatingEntry() { - Assert.False(context.Database.EnsureCreated()); + Assert.That(!context.Database.EnsureCreated()); var ad = new Address { Street = "New street two", City = "Chicago" }; var g = new Guest { Name = "Guest number two", Address = ad }; context.Set().Add(g); @@ -68,7 +68,7 @@ public void CanUseShadowPropertyWhenUpdatingEntry() // update entry var entry = context.Set().Where(t => t.Name!.Equals("Guest number two")).First(); - Assert.False(entry == null); + Assert.That(entry, Is.Not.Null); entry!.Name = "Guest number two updated"; context.SaveChanges(); @@ -81,15 +81,15 @@ public void CanUseShadowPropertyWhenUpdatingEntry() var cmd = new MySqlCommand("Select UpdatedAt from Guests where IdGuest=" + entry.IdGuest, cnn); var updatedAt = cmd.ExecuteScalar(); - Assert.False(updatedAt == null); - Assert.True(((DateTime)updatedAt!).Date.CompareTo(DateTime.Now.Date) == 0); + Assert.That(updatedAt, Is.Not.Null); + Assert.That(((DateTime)updatedAt!).Date.CompareTo(DateTime.Now.Date) == 0); } } [Test] public void CanUseShadowPropertyWhenAddingEntry() { - Assert.False(context.Database.EnsureCreated()); + Assert.That(!context.Database.EnsureCreated()); var ad = new Address { Street = "New street", City = "Oregon" }; var g = new Guest { Name = "Guest number one", Address = ad }; context.Set().Add(g); @@ -104,8 +104,8 @@ public void CanUseShadowPropertyWhenAddingEntry() var cmd = new MySqlCommand("Select CreatedAt from Guests Limit 1", cnn); var createdAt = cmd.ExecuteScalar(); - Assert.False(createdAt == null); - Assert.True(((DateTime)createdAt!).Date.CompareTo(DateTime.Now.Date) == 0); + Assert.That(createdAt, Is.Not.Null); + Assert.That(((DateTime)createdAt!).Date.CompareTo(DateTime.Now.Date) == 0); } } diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/Utils/EntityTestsFixtureClass.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/Utils/EntityTestsFixtureClass.cs index 4da09804f..87696ef1b 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/Utils/EntityTestsFixtureClass.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/Utils/EntityTestsFixtureClass.cs @@ -93,7 +93,7 @@ protected internal void CheckSql(string sql, string refSql) foreach (char c in refSql) if (!Char.IsWhiteSpace(c)) str2.Append(c); - Assert.AreEqual(0, String.Compare(str1.ToString(), str2.ToString(), true)); + Assert.That(String.Compare(str1.ToString(), str2.ToString(), true), Is.EqualTo(0)); } diff --git a/EFCore/tests/MySql.EFCore.Design.Tests/GlobalUsings.cs b/EFCore/tests/MySql.EFCore.Design.Tests/GlobalUsings.cs deleted file mode 100644 index 575c7cfd0..000000000 --- a/EFCore/tests/MySql.EFCore.Design.Tests/GlobalUsings.cs +++ /dev/null @@ -1,5 +0,0 @@ -global using Assert = NUnit.Framework.Legacy.ClassicAssert; -global using CollectionAssert = NUnit.Framework.Legacy.CollectionAssert; -global using StringAssert = NUnit.Framework.Legacy.StringAssert; -global using DirectoryAssert = NUnit.Framework.Legacy.DirectoryAssert; -global using FileAssert = NUnit.Framework.Legacy.FileAssert; diff --git a/EFCore/tests/MySql.EFCore.Design.Tests/MySQLAnnotationCodeGeneratorTest.cs b/EFCore/tests/MySql.EFCore.Design.Tests/MySQLAnnotationCodeGeneratorTest.cs index 61ff8b711..6e5e9d6ce 100644 --- a/EFCore/tests/MySql.EFCore.Design.Tests/MySQLAnnotationCodeGeneratorTest.cs +++ b/EFCore/tests/MySql.EFCore.Design.Tests/MySQLAnnotationCodeGeneratorTest.cs @@ -65,8 +65,8 @@ public void GenerateFluentApiHasCharset(string mySQLAnnotation) var annotation = key?.FindAnnotation(mySQLAnnotation); var result = MySQLAnnotationCodeGenerator.GenFluentApi((Microsoft.EntityFrameworkCore.Metadata.IProperty)key!, annotation!); - Assert.AreEqual(mySQLAnnotation == MySQLAnnotationNames.Charset ? "ForMySQLHasCharset" : "ForMySQLHasCollation", result?.Method); - Assert.AreEqual(1, result?.Arguments.Count); + Assert.That(result?.Method, Is.EqualTo(mySQLAnnotation == MySQLAnnotationNames.Charset ? "ForMySQLHasCharset" : "ForMySQLHasCollation")); + Assert.That(result?.Arguments.Count, Is.EqualTo(1)); } } } diff --git a/EFCore/tests/MySql.EFCore.Design.Tests/MySQLCodeGeneratorTest.cs b/EFCore/tests/MySql.EFCore.Design.Tests/MySQLCodeGeneratorTest.cs index c1549b537..b0e83d66f 100644 --- a/EFCore/tests/MySql.EFCore.Design.Tests/MySQLCodeGeneratorTest.cs +++ b/EFCore/tests/MySql.EFCore.Design.Tests/MySQLCodeGeneratorTest.cs @@ -50,9 +50,9 @@ public virtual void UseProviderMethodIsGeneratedCorrectly() var result = codeGenerator.GenerateUseProvider("Data Source=Test", providerOptions: null); - Assert.AreEqual("UseMySQL", result.Method); + Assert.That(result.Method, Is.EqualTo("UseMySQL")); Assert.That(result.Arguments, Has.Exactly(1).EqualTo("Data Source=Test")); - Assert.Null(result.ChainedCall); + Assert.That(result.ChainedCall, Is.Null); } [Test] @@ -66,13 +66,13 @@ public virtual void UseProviderMethodIsGeneratedCorrectlyWithOptions() var result = codeGenerator.GenerateUseProvider("Data Source=Test", providerOptions); - Assert.AreEqual("UseMySQL", result.Method); + Assert.That(result.Method, Is.EqualTo("UseMySQL")); Assert.That(result.Arguments, Has.Exactly(1).EqualTo("Data Source=Test")); - Assert.IsInstanceOf(result.Arguments[1]); + Assert.That(result.Arguments[1], Is.InstanceOf()); NestedClosureCodeFragment nestedClosure = (NestedClosureCodeFragment)result.Arguments[1]!; - Assert.AreEqual("x", nestedClosure?.Parameter); - Assert.AreSame(providerOptions, nestedClosure?.MethodCalls[0]); - Assert.Null(result.ChainedCall); + Assert.That(nestedClosure?.Parameter, Is.EqualTo("x")); + Assert.That(nestedClosure?.MethodCalls[0], Is.SameAs(providerOptions)); + Assert.That(result.ChainedCall, Is.Null); } private static readonly MethodInfo UseMySqlServerMethodInfo diff --git a/EFCore/tests/MySql.EFCore.Design.Tests/MySQLDatabaseModelFactoryTest.cs b/EFCore/tests/MySql.EFCore.Design.Tests/MySQLDatabaseModelFactoryTest.cs index d264c8c4d..a520b0c2c 100644 --- a/EFCore/tests/MySql.EFCore.Design.Tests/MySQLDatabaseModelFactoryTest.cs +++ b/EFCore/tests/MySql.EFCore.Design.Tests/MySQLDatabaseModelFactoryTest.cs @@ -102,7 +102,7 @@ PRIMARY KEY (description, id) Assert.Multiple(() => { - Assert.AreEqual("blogman", dbModel.DatabaseName); + Assert.That(dbModel.DatabaseName, Is.EqualTo("blogman")); Assert.That(dbModel.Tables.Select(c => c.Name), Has.Exactly(1).Matches(table => table.Contains("blogs"))); }); @@ -111,27 +111,27 @@ PRIMARY KEY (description, id) Assert.That(columns.Where(n => n.Name == "id").Select(a => a.Name), Has.Exactly(1).Matches(name => name.Contains("id"))); Assert.That(columns.Where(n => n.Name == "id").Select(a => a.GetDataType()), Has.One.Items.EqualTo("int" + smallintWidth)); Assert.That(columns.Where(n => n.Name == "id").Select(a => a.GetPrimaryKeyOrdinal(2)), Has.One.Items.EqualTo(2)); - Assert.False(columns.Where(n => n.Name == "id").Select(a => a.IsNullable).FirstOrDefault()); + Assert.That(!columns.Where(n => n.Name == "id").Select(a => a.IsNullable).FirstOrDefault()); Assert.That(columns.Where(n => n.Name == "id").Select(a => a.GetOrdinal(0)), Has.One.Items.EqualTo(0)); - Assert.IsNull(columns.Where(n => n.Name == "id").Select(a => a.GetDefaultValue()).FirstOrDefault()); + Assert.That(columns.Where(n => n.Name == "id").Select(a => a.GetDefaultValue()).FirstOrDefault(), Is.Null); Assert.That(columns.Where(n => n.Name == "description").Select(a => a.Name), Has.Exactly(1).Matches(name => name.Contains("description"))); Assert.That(columns.Where(n => n.Name == "description").Select(a => a.GetDataType()), Has.One.Items.EqualTo("varchar(100)")); Assert.That(columns.Where(n => n.Name == "description").Select(a => a.GetPrimaryKeyOrdinal(1)), Has.One.Items.EqualTo(1)); - Assert.False(columns.Where(n => n.Name == "description").Select(a => a.IsNullable).FirstOrDefault()); + Assert.That(!columns.Where(n => n.Name == "description").Select(a => a.IsNullable).FirstOrDefault()); Assert.That(columns.Where(n => n.Name == "description").Select(a => a.GetOrdinal(1)), Has.One.Items.EqualTo(1)); - Assert.IsNull(columns.Where(n => n.Name == "description").Select(a => a.GetDefaultValue()).FirstOrDefault()); + Assert.That(columns.Where(n => n.Name == "description").Select(a => a.GetDefaultValue()).FirstOrDefault(), Is.Null); Assert.That(columns.Where(n => n.Name == "description").Select(a => a.GetMaxLength(100)), Has.One.Items.EqualTo(100)); Assert.That(columns.Where(n => n.Name == "rate").Select(a => a.Name), Has.Exactly(1).Matches(name => name.Contains("rate"))); Assert.That(columns.Where(n => n.Name == "rate").Select(a => a.GetDataType()), Has.One.Items.EqualTo("decimal(5,2)")); - Assert.IsNull(columns.Where(n => n.Name == "rate").Select(a => a.GetPrimaryKeyOrdinal(null)).FirstOrDefault()); - Assert.True(columns.Where(n => n.Name == "rate").Select(a => a.IsNullable).FirstOrDefault()); + Assert.That(columns.Where(n => n.Name == "rate").Select(a => a.GetPrimaryKeyOrdinal(null)).FirstOrDefault(), Is.Null); + Assert.That(columns.Where(n => n.Name == "rate").Select(a => a.IsNullable).FirstOrDefault()); Assert.That(columns.Where(n => n.Name == "rate").Select(a => a.GetOrdinal(2)), Has.One.Items.EqualTo(2)); - StringAssert.AreEqualIgnoringCase(columns.Where(n => n.Name == "rate").Select(a => a.GetDefaultValue()).FirstOrDefault(), "'0.00'"); + Assert.That("'0.00'", Is.EqualTo(columns.Where(n => n.Name == "rate").Select(a => a.GetDefaultValue()).FirstOrDefault()).IgnoreCase); Assert.That(columns.Where(n => n.Name == "rate").Select(a => a.GetPrecision(5)), Has.One.Items.EqualTo(5)); Assert.That(columns.Where(n => n.Name == "rate").Select(a => a.GetScale(2)), Has.One.Items.EqualTo(2)); - Assert.IsNull(columns.Where(n => n.Name == "rate").Select(a => a.GetMaxLength(null)).FirstOrDefault()); + Assert.That(columns.Where(n => n.Name == "rate").Select(a => a.GetMaxLength(null)).FirstOrDefault(), Is.Null); Assert.That(columns.Where(n => n.Name == "created").Select(a => a.Name), Has.Exactly(1).Matches(name => name.Contains("created"))); Assert.That(columns.Where(n => n.Name == "created").Select(a => a.GetDefaultValue()), Has.One.Items.EqualTo("CURRENT_TIMESTAMP")); @@ -163,14 +163,14 @@ KEY idx_fk_country_id (country_id), var dbModel = _fixture!.CreateModel("sakiladb", sql, new List { "city", "country" }, new List()); var fk = (dbModel.Tables.Single(t => t.ForeignKeys.Count > 0).ForeignKeys); - Assert.IsNotNull(fk); - Assert.AreEqual("sakiladb", fk[0].Table.Database!.DatabaseName); - Assert.AreEqual("city", fk[0].Table.Name); - Assert.AreEqual("sakiladb", fk[0].PrincipalTable.Database!.DatabaseName); - Assert.AreEqual("country", fk[0].PrincipalTable.Name); - Assert.AreEqual("country_id", fk[0].GetColumn().Name); - Assert.AreEqual("country_id", fk[0].GetPrincipalColumn().Name); - Assert.AreEqual(ReferentialAction.Restrict, fk[0].OnDelete); + Assert.That(fk, Is.Not.Null); + Assert.That(fk[0].Table.Database!.DatabaseName, Is.EqualTo("sakiladb")); + Assert.That(fk[0].Table.Name, Is.EqualTo("city")); + Assert.That(fk[0].PrincipalTable.Database!.DatabaseName, Is.EqualTo("sakiladb")); + Assert.That(fk[0].PrincipalTable.Name, Is.EqualTo("country")); + Assert.That(fk[0].GetColumn().Name, Is.EqualTo("country_id")); + Assert.That(fk[0].GetPrincipalColumn().Name, Is.EqualTo("country_id")); + Assert.That(fk[0].OnDelete, Is.EqualTo(ReferentialAction.Restrict)); } [Test] @@ -195,23 +195,23 @@ PRIMARY KEY(actor_id), Assert.Multiple(() => { var c = indexes[0]; - Assert.AreEqual("sakilaIndex", c.Table!.Database!.DatabaseName); - Assert.AreEqual("actor", c.Table.Name); + Assert.That(c.Table!.Database!.DatabaseName, Is.EqualTo("sakilaIndex")); + Assert.That(c.Table.Name, Is.EqualTo("actor")); }); Assert.Multiple(() => { var composite = indexes[0]; - Assert.AreEqual("idx_actor_first_last_name", composite.Name); - Assert.False(composite.IsUnique); - Assert.AreEqual(new List { "first_name", "last_name" }, composite.GetColumns().Select(c => c.GetColumn().Name).ToList()); + Assert.That(composite.Name, Is.EqualTo("idx_actor_first_last_name")); + Assert.That(!composite.IsUnique); + Assert.That(composite.GetColumns().Select(c => c.GetColumn().Name).ToList(), Is.EqualTo(new List { "first_name", "last_name" })); }); Assert.Multiple(() => { var onecolumn = indexes[1]; - Assert.AreEqual("last_name", onecolumn.GetColumn().Name); - Assert.True(onecolumn.IsUnique); + Assert.That(onecolumn.GetColumn().Name, Is.EqualTo("last_name")); + Assert.That(onecolumn.IsUnique); } ); } @@ -250,7 +250,7 @@ private void Test(string createSql, IEnumerable tables, IEnumerable { "t1", "x1" }; var dbModel = _fixture!.CreateModel("testview", sql, selectionSet, new List()); - Assert.True(dbModel.Tables.Count == 2); + Assert.That(dbModel.Tables.Count == 2); } } } diff --git a/EFCore/tests/MySql.EFCore.Design.Tests/MySQLDesignTimeProviderServicesTest.cs b/EFCore/tests/MySql.EFCore.Design.Tests/MySQLDesignTimeProviderServicesTest.cs index ca39de4c1..5331e8b81 100644 --- a/EFCore/tests/MySql.EFCore.Design.Tests/MySQLDesignTimeProviderServicesTest.cs +++ b/EFCore/tests/MySql.EFCore.Design.Tests/MySQLDesignTimeProviderServicesTest.cs @@ -51,9 +51,9 @@ public void EnsureAssemblyIdentityMatches() var dtAttribute = runtimeAssembly.GetCustomAttribute(); var dtType = GetDesignTimeServicesType(); - Assert.NotNull(dtType); - Assert.NotNull(dtAttribute); - Assert.AreEqual(dtType.FullName, dtAttribute?.TypeName); + Assert.That(dtType, Is.Not.Null); + Assert.That(dtAttribute, Is.Not.Null); + Assert.That(dtAttribute?.TypeName, Is.EqualTo(dtType.FullName)); } } } diff --git a/EFCore/tests/MySql.EFCore.Migrations.Tests/GlobalUsings.cs b/EFCore/tests/MySql.EFCore.Migrations.Tests/GlobalUsings.cs deleted file mode 100644 index 575c7cfd0..000000000 --- a/EFCore/tests/MySql.EFCore.Migrations.Tests/GlobalUsings.cs +++ /dev/null @@ -1,5 +0,0 @@ -global using Assert = NUnit.Framework.Legacy.ClassicAssert; -global using CollectionAssert = NUnit.Framework.Legacy.CollectionAssert; -global using StringAssert = NUnit.Framework.Legacy.StringAssert; -global using DirectoryAssert = NUnit.Framework.Legacy.DirectoryAssert; -global using FileAssert = NUnit.Framework.Legacy.FileAssert; diff --git a/EFCore/tests/MySql.EFCore.Migrations.Tests/MySQLHistoryRepositoryTests.cs b/EFCore/tests/MySql.EFCore.Migrations.Tests/MySQLHistoryRepositoryTests.cs index 70085710b..7ae230162 100644 --- a/EFCore/tests/MySql.EFCore.Migrations.Tests/MySQLHistoryRepositoryTests.cs +++ b/EFCore/tests/MySql.EFCore.Migrations.Tests/MySQLHistoryRepositoryTests.cs @@ -81,9 +81,8 @@ public void CanCreateDatabase() var creator = context.GetService(); var cmdBuilder = context.GetService(); - Assert.False(creator.Exists()); - Assert.AreEqual("IF EXISTS(SELECT * FROM `__EFMigrationsHistory` WHERE `MigrationId` = 'MigrationId')\nBEGIN", - cmdBuilder.Build(repository.GetBeginIfExistsScript("MigrationId")).CommandText.Replace("\r", string.Empty)); + Assert.That(!creator.Exists()); + Assert.That(cmdBuilder.Build(repository.GetBeginIfExistsScript("MigrationId")).CommandText.Replace("\r", string.Empty), Is.EqualTo("IF EXISTS(SELECT * FROM `__EFMigrationsHistory` WHERE `MigrationId` = 'MigrationId')\nBEGIN")); } } } diff --git a/EFCore/tests/MySql.EFCore.Migrations.Tests/MySqlMigrationsGeneratorTest.cs b/EFCore/tests/MySql.EFCore.Migrations.Tests/MySqlMigrationsGeneratorTest.cs index bcb5c3ee2..7be723ae2 100644 --- a/EFCore/tests/MySql.EFCore.Migrations.Tests/MySqlMigrationsGeneratorTest.cs +++ b/EFCore/tests/MySql.EFCore.Migrations.Tests/MySqlMigrationsGeneratorTest.cs @@ -72,7 +72,7 @@ public override void CreateTableOperation() ");" + EOL; string fullResult = result.Replace(" NULL,", ","); - Assert.True(result == Sql || fullResult == Sql); + Assert.That(result == Sql || fullResult == Sql); } [Test] @@ -81,28 +81,28 @@ public override void AddColumnOperation_with_maxLength() base.AddColumnOperation_with_maxLength(); string result = "ALTER TABLE `Person` ADD `Name` varchar(30);" + EOL; string fullResult = "ALTER TABLE `Person` ADD `Name` varchar(30) NULL;" + EOL; - Assert.True(result == Sql || fullResult == Sql); + Assert.That(result == Sql || fullResult == Sql); } [Test] public override void AddColumnOperationWithComputedValueSql() { base.AddColumnOperationWithComputedValueSql(); - Assert.AreEqual("ALTER TABLE `People` ADD `DisplayName` varchar(50) AS (CONCAT_WS(' ', LastName , FirstName));" + EOL, Sql); + Assert.That(Sql, Is.EqualTo("ALTER TABLE `People` ADD `DisplayName` varchar(50) AS (CONCAT_WS(' ', LastName , FirstName));" + EOL)); } [Test] public override void AddColumnOperationWithDefaultValueSql() { base.AddColumnOperationWithDefaultValueSql(); - Assert.AreEqual("ALTER TABLE `People` ADD `Timestamp` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP;" + EOL, Sql); + Assert.That(Sql, Is.EqualTo("ALTER TABLE `People` ADD `Timestamp` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP;" + EOL)); } [Test] public override void AlterColumnOperation() { base.AlterColumnOperation(); - Assert.AreEqual("ALTER TABLE `Person` MODIFY `Age` int NOT NULL DEFAULT 7;" + EOL, Sql); + Assert.That(Sql, Is.EqualTo("ALTER TABLE `Person` MODIFY `Age` int NOT NULL DEFAULT 7;" + EOL)); } @@ -110,21 +110,21 @@ public override void AlterColumnOperation() public override void AlterColumnOperationWithoutType() { base.AlterColumnOperationWithoutType(); - Assert.AreEqual("ALTER TABLE `Person` MODIFY `Age` int NOT NULL;" + EOL, Sql); + Assert.That(Sql, Is.EqualTo("ALTER TABLE `Person` MODIFY `Age` int NOT NULL;" + EOL)); } [Test] public override void RenameTableOperationInSchema() { base.RenameTableOperationInSchema(); - Assert.AreEqual("ALTER TABLE t1 RENAME t2;" + EOL, Sql); + Assert.That(Sql, Is.EqualTo("ALTER TABLE t1 RENAME t2;" + EOL)); } [Test] public override void CreateUniqueIndexOperation() { base.CreateUniqueIndexOperation(); - Assert.AreEqual("CREATE UNIQUE INDEX `IXPersonName` ON `Person` (`FirstName`, `LastName`);" + EOL, Sql); + Assert.That(Sql, Is.EqualTo("CREATE UNIQUE INDEX `IXPersonName` ON `Person` (`FirstName`, `LastName`);" + EOL)); } [Test] @@ -132,7 +132,7 @@ public override void CreateNonUniqueIndexOperation() { base.CreateNonUniqueIndexOperation(); - Assert.AreEqual("CREATE INDEX `IXPersonName` ON `Person` (`Name`);" + EOL, Sql); + Assert.That(Sql, Is.EqualTo("CREATE INDEX `IXPersonName` ON `Person` (`Name`);" + EOL)); } [Test] @@ -140,28 +140,28 @@ public override void CreateNonUniqueIndexOperation() public override void RenameIndexOperation() { base.RenameIndexOperation(); - Assert.AreEqual("DROP INDEX IXPersonName ON Person; CREATE INDEX IXNombre;" + EOL, Sql); + Assert.That(Sql, Is.EqualTo("DROP INDEX IXPersonName ON Person; CREATE INDEX IXNombre;" + EOL)); } [Test] public override void DropIndexOperation() { base.DropIndexOperation(); - Assert.AreEqual("DROP INDEX IXPersonName ON Person;" + EOL, Sql); + Assert.That(Sql, Is.EqualTo("DROP INDEX IXPersonName ON Person;" + EOL)); } [Test] public override void DropPrimaryKeyOperation() { base.DropPrimaryKeyOperation(); - Assert.AreEqual(string.Empty, Sql); + Assert.That(Sql, Is.EqualTo(string.Empty)); } [Test] public override void AddPrimaryKeyOperation() { base.AddPrimaryKeyOperation(); - Assert.AreEqual(string.Empty, Sql); + Assert.That(Sql, Is.EqualTo(string.Empty)); } } } diff --git a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/CanonicalFunctions.cs b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/CanonicalFunctions.cs index 765b90ce5..cecb039a7 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/CanonicalFunctions.cs +++ b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/CanonicalFunctions.cs @@ -64,13 +64,13 @@ public void Bitwise() var context = ((IObjectContextAdapter)ctx).ObjectContext; ObjectQuery q = context.CreateQuery("BitwiseAnd(255,15)"); foreach (int i in q) - Assert.AreEqual(15, i); + Assert.That(i, Is.EqualTo(15)); q = context.CreateQuery("BitwiseOr(240,31)"); foreach (int i in q) - Assert.AreEqual(255, i); + Assert.That(i, Is.EqualTo(255)); q = context.CreateQuery("BitwiseXor(255,15)"); foreach (int i in q) - Assert.AreEqual(240, i); + Assert.That(i, Is.EqualTo(240)); } } @@ -85,9 +85,9 @@ public void CurrentDateTime() ObjectQuery q = context.CreateQuery("CurrentDateTime()"); foreach (DateTime dt in q) { - Assert.AreEqual(current.Year, dt.Year); - Assert.AreEqual(current.Month, dt.Month); - Assert.AreEqual(current.Day, dt.Day); + Assert.That(dt.Year, Is.EqualTo(current.Year)); + Assert.That(dt.Month, Is.EqualTo(current.Month)); + Assert.That(dt.Day, Is.EqualTo(current.Day)); // we don't check time as that will be always be different } } @@ -104,9 +104,9 @@ public void YearMonthDay() FROM Companies AS c WHERE c.Id=1"); foreach (DbDataRecord record in q) { - Assert.AreEqual(1996, record[1]); - Assert.AreEqual(11, record[2]); - Assert.AreEqual(15, record[3]); + Assert.That(record[1], Is.EqualTo(1996)); + Assert.That(record[2], Is.EqualTo(11)); + Assert.That(record[3], Is.EqualTo(15)); } } } @@ -122,9 +122,9 @@ public void HourMinuteSecond() FROM Companies AS c WHERE c.Id=1"); foreach (DbDataRecord record in q) { - Assert.AreEqual(5, record[1]); - Assert.AreEqual(18, record[2]); - Assert.AreEqual(23, record[3]); + Assert.That(record[1], Is.EqualTo(5)); + Assert.That(record[2], Is.EqualTo(18)); + Assert.That(record[3], Is.EqualTo(23)); } } } @@ -137,11 +137,11 @@ public void IndexOf() var context = ((IObjectContextAdapter)ctx).ObjectContext; ObjectQuery q = context.CreateQuery(@"IndexOf('needle', 'haystackneedle')"); foreach (int index in q) - Assert.AreEqual(9, index); + Assert.That(index, Is.EqualTo(9)); q = context.CreateQuery(@"IndexOf('haystack', 'needle')"); foreach (int index in q) - Assert.AreEqual(0, index); + Assert.That(index, Is.EqualTo(0)); } } @@ -154,17 +154,17 @@ public void LeftRight() string entitySQL = "CONCAT(LEFT('foo',3),RIGHT('bar',3))"; ObjectQuery query = context.CreateQuery(entitySQL); foreach (string s in query) - Assert.AreEqual("foobar", s); + Assert.That(s, Is.EqualTo("foobar")); entitySQL = "CONCAT(LEFT('foobar',3),RIGHT('barfoo',3))"; query = context.CreateQuery(entitySQL); foreach (string s in query) - Assert.AreEqual("foofoo", s); + Assert.That(s, Is.EqualTo("foofoo")); entitySQL = "CONCAT(LEFT('foobar',8),RIGHT('barfoo',8))"; query = context.CreateQuery(entitySQL); foreach (string s in query) - Assert.AreEqual("foobarbarfoo", s); + Assert.That(s, Is.EqualTo("foobarbarfoo")); } } @@ -177,7 +177,7 @@ public void Length() string entitySQL = "Length('abc')"; ObjectQuery query = context.CreateQuery(entitySQL); foreach (int len in query) - Assert.AreEqual(3, len); + Assert.That(len, Is.EqualTo(3)); } } @@ -189,13 +189,13 @@ public void Trims() var context = ((IObjectContextAdapter)ctx).ObjectContext; ObjectQuery query = context.CreateQuery("LTrim(' text ')"); foreach (string s in query) - Assert.AreEqual("text ", s); + Assert.That(s, Is.EqualTo("text ")); query = context.CreateQuery("RTrim(' text ')"); foreach (string s in query) - Assert.AreEqual(" text", s); + Assert.That(s, Is.EqualTo(" text")); query = context.CreateQuery("Trim(' text ')"); foreach (string s in query) - Assert.AreEqual("text", s); + Assert.That(s, Is.EqualTo("text")); } } @@ -213,11 +213,11 @@ public void Round() FROM Products AS p WHERE p.Id=1"); foreach (DbDataRecord r in q) { - Assert.AreEqual(1, r[0]); - Assert.AreEqual(8.865f, (float)r[1]); - Assert.AreEqual(9, Convert.ToInt32(r[2])); - Assert.AreEqual(8, Convert.ToInt32(r[3])); - Assert.AreEqual(9, Convert.ToInt32(r[4])); + Assert.That(r[0], Is.EqualTo(1)); + Assert.That((float)r[1], Is.EqualTo(8.865f)); + Assert.That(Convert.ToInt32(r[2]), Is.EqualTo(9)); + Assert.That(Convert.ToInt32(r[3]), Is.EqualTo(8)); + Assert.That(Convert.ToInt32(r[4]), Is.EqualTo(9)); } } } @@ -231,7 +231,7 @@ public void Substring() ObjectQuery query = context.CreateQuery("SUBSTRING('foobarfoo',4,3)"); query = context.CreateQuery("SUBSTRING('foobarfoo',4,30)"); foreach (string s in query) - Assert.AreEqual("barfoo", s); + Assert.That(s, Is.EqualTo("barfoo")); } } @@ -246,9 +246,9 @@ public void ToUpperToLowerReverse() Reverse(c.Name) FROM Companies AS c WHERE c.Id=1"); foreach (DbDataRecord r in q) { - Assert.AreEqual("HASBRO", r[0]); - Assert.AreEqual("hasbro", r[1]); - Assert.AreEqual("orbsaH", r[2]); + Assert.That(r[0], Is.EqualTo("HASBRO")); + Assert.That(r[1], Is.EqualTo("hasbro")); + Assert.That(r[2], Is.EqualTo("orbsaH")); } } } @@ -262,7 +262,7 @@ public void Replace() ObjectQuery q = context.CreateQuery( @"Replace('abcdefghi', 'def', 'zzz')"); foreach (string s in q) - Assert.AreEqual("abczzzghi", s); + Assert.That(s, Is.EqualTo("abczzzghi")); } } @@ -277,8 +277,8 @@ public void CanRoundToNonZeroDigits() Round(p.Weight, 2) AS [Rounded Weight] FROM Products AS p WHERE p.Id=1").First(); - Assert.AreEqual((float)8.865, (float)product[1]); - Assert.AreEqual((double)8.86, (double)product[2]); + Assert.That((float)product[1], Is.EqualTo((float)8.865)); + Assert.That((double)product[2], Is.EqualTo((double)8.86) ); } } diff --git a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/DataTypeTests.cs b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/DataTypeTests.cs index 3d620c5d1..f36994dc8 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/DataTypeTests.cs +++ b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/DataTypeTests.cs @@ -57,7 +57,7 @@ public void TimeType() ctx.SaveChanges(); Child d = ctx.Children.Where(x => x.ChildId == "ABC").Single(); - Assert.AreEqual(birth, d.BirthTime); + Assert.That(d.BirthTime, Is.EqualTo(birth)); } } @@ -111,7 +111,7 @@ public void TimestampColumn() ctx.SaveChanges(); p = ctx.Products.First(); - Assert.AreEqual(now, p.CreatedDate); + Assert.That(p.CreatedDate, Is.EqualTo(now)); } } @@ -135,7 +135,7 @@ public void GuidType() ctx.SaveChanges(); Child d = ctx.Children.Where(x => x.ChildId == "GUID").Single(); - Assert.AreEqual(g, d.Label); + Assert.That(d.Label, Is.EqualTo(g)); } } @@ -156,7 +156,7 @@ public void CanSetDbTypeDecimalFromNewDecimalParameter() IsNullable = true }; - Assert.AreEqual(DbType.Decimal, newDecimalParameter.DbType); + Assert.That(newDecimalParameter.DbType, Is.EqualTo(DbType.Decimal)); } } } diff --git a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/DatesTypesTests.cs b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/DatesTypesTests.cs index 22b246a55..edefa6f75 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/DatesTypesTests.cs +++ b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/DatesTypesTests.cs @@ -89,12 +89,12 @@ public void CanCreateDBScriptWithDateTimePrecision() DataTable schema = Connection.GetSchema("COLUMNS", new string[] { null, Connection.Database, "widgets" }); DataRow row = schema.Rows[3]; - Assert.AreEqual("datetime", (string)row["DATA_TYPE"]); - Assert.AreEqual("NO", (string)row["IS_NULLABLE"]); + Assert.That((string)row["DATA_TYPE"], Is.EqualTo("datetime")); + Assert.That((string)row["IS_NULLABLE"], Is.EqualTo("NO")); if (Version < new Version(8, 0)) - Assert.AreEqual((uint)6, (UInt64)row["DATETIME_PRECISION"]); + Assert.That((UInt64)row["DATETIME_PRECISION"], Is.EqualTo((uint)6)); else - Assert.AreEqual((uint)6, (UInt32)row["DATETIME_PRECISION"]); + Assert.That((UInt32)row["DATETIME_PRECISION"], Is.EqualTo((uint)6)); } } } diff --git a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/DefaultFixture.cs b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/DefaultFixture.cs index c575b0617..bd36e9c6c 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/DefaultFixture.cs +++ b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/DefaultFixture.cs @@ -147,14 +147,14 @@ public static void CheckSql(string actual, string expected) { var exp = Regex.Replace(expected, @"\s", string.Empty); var act = Regex.Replace(actual, @"\s", string.Empty); - Assert.AreEqual(act, exp); + Assert.That(exp, Is.EqualTo(act)); } public static void CheckSqlContains(string actual, string expected) { var exp = Regex.Replace(expected, @"\s", string.Empty); var act = Regex.Replace(actual, @"\s", string.Empty); - Assert.True(act.Contains(exp)); + Assert.That(act.Contains(exp)); } public DefaultContext GetDefaultContext() diff --git a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/DeleteTests.cs b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/DeleteTests.cs index 305a60805..eac1476b9 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/DeleteTests.cs +++ b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/DeleteTests.cs @@ -53,13 +53,13 @@ public void SimpleDeleteAllRows() { using (DefaultContext ctx = new DefaultContext(ConnectionString)) { - Assert.True(ctx.Products.Count() > 0); + Assert.That(ctx.Products.Count() > 0); foreach (Product p in ctx.Products) ctx.Products.Remove(p); ctx.SaveChanges(); - Assert.AreEqual(0, ctx.Products.Count()); + Assert.That(ctx.Products.Count(), Is.EqualTo(0)); } // set the flag that will cause the setup to happen again // since we just blew away a table @@ -74,12 +74,12 @@ public void SimpleDeleteRowByParameter() int total = ctx.Products.Count(); int cntLeft = ctx.Products.Where(b => b.MinAge >= 18).Count(); // make sure the test is valid - Assert.True(total > cntLeft); + Assert.That(total > cntLeft); foreach (Product p in ctx.Products.Where(b => b.MinAge < 18).ToList()) ctx.Products.Remove(p); ctx.SaveChanges(); - Assert.AreEqual(cntLeft, ctx.Products.Count()); + Assert.That(ctx.Products.Count(), Is.EqualTo(cntLeft)); } // set the flag that will cause the setup to happen again // since we just blew away a table diff --git a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/ExpressionTests.cs b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/ExpressionTests.cs index 9759feef3..9b2acc565 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/ExpressionTests.cs +++ b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/ExpressionTests.cs @@ -54,7 +54,7 @@ public void CheckStartsWithWhenUsingVariable() { string str = "Garbage"; var records = ctx.Products.Where(p => p.Name.StartsWith(str)).ToArray(); - Assert.AreEqual(1, records.Count()); + Assert.That(records.Count(), Is.EqualTo(1)); } } @@ -67,7 +67,7 @@ public void CheckStartsWithWhenUsingValue() using (DefaultContext ctx = new DefaultContext(ConnectionString)) { var records = ctx.Products.Where(p => p.Name.StartsWith("Garbage")).ToArray(); - Assert.AreEqual(1, records.Count()); + Assert.That(records.Count(), Is.EqualTo(1)); } } @@ -81,7 +81,7 @@ public void CheckEndsWithWhenUsingVariable() { string str = "Hoop"; var records = ctx.Products.Where(p => p.Name.EndsWith(str)).ToArray(); - Assert.AreEqual(1, records.Count()); + Assert.That(records.Count(), Is.EqualTo(1)); } } @@ -94,7 +94,7 @@ public void CheckEndsWithWhenUsingValue() using (DefaultContext ctx = new DefaultContext(ConnectionString)) { var records = ctx.Products.Where(p => p.Name.EndsWith("Hoop")).ToArray(); - Assert.AreEqual(1, records.Count()); + Assert.That(records.Count(), Is.EqualTo(1)); } } @@ -109,7 +109,7 @@ public void CheckContainsWhenUsingVariable() { string str = "bage"; var records = ctx.Products.Where(p => p.Name.Contains(str)).ToArray(); - Assert.AreEqual(1, records.Count()); + Assert.That(records.Count(), Is.EqualTo(1)); } } @@ -123,7 +123,7 @@ public void CheckContainsWhenUsingHardCodedValue() using (DefaultContext ctx = new DefaultContext(ConnectionString)) { var records = ctx.Products.Where(p => p.Name.Contains("bage")).ToArray(); - Assert.AreEqual(1, records.Count()); + Assert.That(records.Count(), Is.EqualTo(1)); } } @@ -136,7 +136,7 @@ public void CheckContainsWhenUsingHardCodedValueWithPercentageSymbol() using (DefaultContext ctx = new DefaultContext(ConnectionString)) { var records = ctx.Products.Where(p => p.Name.Contains("%")).ToArray(); - Assert.AreEqual(0, records.Count()); + Assert.That(records.Count(), Is.EqualTo(0)); } } diff --git a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/GlobalUsings.cs b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/GlobalUsings.cs deleted file mode 100644 index 575c7cfd0..000000000 --- a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/GlobalUsings.cs +++ /dev/null @@ -1,5 +0,0 @@ -global using Assert = NUnit.Framework.Legacy.ClassicAssert; -global using CollectionAssert = NUnit.Framework.Legacy.CollectionAssert; -global using StringAssert = NUnit.Framework.Legacy.StringAssert; -global using DirectoryAssert = NUnit.Framework.Legacy.DirectoryAssert; -global using FileAssert = NUnit.Framework.Legacy.FileAssert; diff --git a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/InsertTests.cs b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/InsertTests.cs index e2d7ec7a7..19c198969 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/InsertTests.cs +++ b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/InsertTests.cs @@ -58,11 +58,11 @@ public void InsertSingleRow() ctx.Companies.Add(c); int result = ctx.SaveChanges(); - Assert.AreEqual(beforeCnt + 1, ctx.Companies.Count()); + Assert.That(ctx.Companies.Count(), Is.EqualTo(beforeCnt + 1)); Company d = ctx.Companies.Find(c.Id); d.Id = c.Id; - Assert.AreEqual(c, d); + Assert.That(d, Is.EqualTo(c)); } } @@ -93,12 +93,12 @@ public async Task ExecuteNonQueryAndScalarAsyncAwait() proc.CommandType = CommandType.StoredProcedure; int result = await proc.ExecuteNonQueryAsync(); - Assert.AreNotEqual(-1, result); + Assert.That(result, Is.Not.EqualTo(-1)); EFMySqlCommand cmd = new EFMySqlCommand() { CommandText = "SELECT COUNT(*) FROM NonQueryAndScalarAsyncAwaitTest;", Connection = Connection }; cmd.CommandType = CommandType.Text; object cnt = await cmd.ExecuteScalarAsync(); - Assert.AreEqual(100, Convert.ToInt32(cnt)); + Assert.That(Convert.ToInt32(cnt), Is.EqualTo(100)); } [Test] @@ -147,14 +147,14 @@ public void SqlModeReplacedByANSI() LongDataTest longData = new LongDataTest(); longData.Data = "This does fit."; ctx.LongDataTests.Add(longData); - Assert.IsTrue(ctx.SaveChanges() == 1); + Assert.That(ctx.SaveChanges() == 1); // Try to insert a value that is larger than the max lenght of the column longData.Data = "This does not fit in the column!!!"; ctx.LongDataTests.Add(longData); var ex = Assert.Throws(() => ctx.SaveChanges()); Assert.That(ex.InnerException.InnerException is MySqlException); - StringAssert.AreEqualIgnoringCase("Data too long for column 'Data' at row 1", ex.InnerException.InnerException.Message); + Assert.That(ex.InnerException.InnerException.Message, Is.EqualTo("Data too long for column 'Data' at row 1").IgnoreCase); } } } diff --git a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/Paging.cs b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/Paging.cs index ad95562d2..2b04847a1 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/Paging.cs +++ b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/Paging.cs @@ -97,7 +97,7 @@ public void TakeWithCount() using (DefaultContext ctx = new DefaultContext(ConnectionString)) { int cnt = ctx.Products.Take(2).Count(); - Assert.AreEqual(2, cnt); + Assert.That(cnt, Is.EqualTo(2)); } } } diff --git a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/ProceduresAndFunctions.cs b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/ProceduresAndFunctions.cs index 0d436d480..fd2b0126a 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/ProceduresAndFunctions.cs +++ b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/ProceduresAndFunctions.cs @@ -53,7 +53,7 @@ public void CallStoredProcedure() using (DefaultContext ctx = new DefaultContext(ConnectionString)) { long count = ctx.Database.SqlQuery("call CallStoredProcedure").First(); - Assert.AreEqual(5, count); + Assert.That(count, Is.EqualTo(5)); } } @@ -69,7 +69,7 @@ public void UserDefinedFunction() using (DefaultContext ctx = new DefaultContext(ConnectionString)) { int val = ctx.Database.SqlQuery(@"SELECT spFunc()").Single(); - Assert.AreEqual(3, val); + Assert.That(val, Is.EqualTo(3)); } } diff --git a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/ProviderManifestTests.cs b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/ProviderManifestTests.cs index e24e37635..fb7e0f4cc 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/ProviderManifestTests.cs +++ b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/ProviderManifestTests.cs @@ -44,17 +44,17 @@ public void TestingMaxLengthFacet() TypeUsage tu = TypeUsage.CreateStringTypeUsage( PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.String), false, false); TypeUsage result = pm.GetStoreType(tu); - Assert.AreEqual("longtext", result.EdmType.Name); + Assert.That(result.EdmType.Name, Is.EqualTo("longtext")); tu = TypeUsage.CreateStringTypeUsage( PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.String), false, false, Int32.MaxValue); result = pm.GetStoreType(tu); - Assert.AreEqual("longtext", result.EdmType.Name); + Assert.That(result.EdmType.Name, Is.EqualTo("longtext")); tu = TypeUsage.CreateStringTypeUsage( PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.String), false, false, 70000); result = pm.GetStoreType(tu); - Assert.AreEqual("mediumtext", result.EdmType.Name); + Assert.That(result.EdmType.Name, Is.EqualTo("mediumtext")); } } @@ -72,7 +72,7 @@ public void CanMapByteTypeToUTinyInt() TypeUsage tu = TypeUsage.CreateDefaultTypeUsage( PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.Byte)); TypeUsage result = pm.GetStoreType(tu); - Assert.AreEqual("utinyint", result.EdmType.Name); + Assert.That(result.EdmType.Name, Is.EqualTo("utinyint")); } } @@ -86,17 +86,17 @@ public void TestingMaxLengthWithFixedLenghtTrueFacets() TypeUsage tu = TypeUsage.CreateStringTypeUsage( PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.String), false, true); TypeUsage result = pm.GetStoreType(tu); - Assert.AreEqual("char", result.EdmType.Name); + Assert.That(result.EdmType.Name, Is.EqualTo("char")); tu = TypeUsage.CreateStringTypeUsage( PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.String), false, true, Int32.MaxValue); result = pm.GetStoreType(tu); - Assert.AreEqual("char", result.EdmType.Name); + Assert.That(result.EdmType.Name, Is.EqualTo("char")); tu = TypeUsage.CreateStringTypeUsage( PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.String), false, true, 70000); result = pm.GetStoreType(tu); - Assert.AreEqual("char", result.EdmType.Name); + Assert.That(result.EdmType.Name, Is.EqualTo("char")); } } } diff --git a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/ProviderServicesTests.cs b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/ProviderServicesTests.cs index c6d928197..6a500f835 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/ProviderServicesTests.cs +++ b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/ProviderServicesTests.cs @@ -58,11 +58,11 @@ public void CreateAndDeleteDatabase() { if (ctx.Database.Exists()) ctx.Database.Delete(); - Assert.False(ctx.Database.Exists()); + Assert.That(!ctx.Database.Exists()); ctx.Database.Create(); - Assert.True(ctx.Database.Exists()); + Assert.That(ctx.Database.Exists()); ctx.Database.Delete(); - Assert.False(ctx.Database.Exists()); + Assert.That(!ctx.Database.Exists()); } NeedSetup = true; } @@ -73,7 +73,7 @@ public void DatabaseExists() using (DefaultContext ctx = new DefaultContext(ConnectionString)) { DataTable dt = Connection.GetSchema("DATABASES", new string[] { Connection.Database }); - Assert.AreEqual(1, dt.Rows.Count); + Assert.That(dt.Rows.Count, Is.EqualTo(1)); ctx.Database.Delete(); } NeedSetup = true; @@ -97,7 +97,7 @@ public void GetDbProviderManifestTokenDoesNotThrowWhenLocalized() { MySqlProviderServices providerServices = new MySqlProviderServices(); var token = providerServices.GetProviderManifestToken(connection); - Assert.NotNull(token); + Assert.That(token, Is.Not.Null); } } @@ -109,7 +109,7 @@ public void GetDbProviderManifestTokenDoesNotThrowWhenMissingPersistSecurityInfo conn.Open(); MySqlProviderServices providerServices = new MySqlProviderServices(); var token = providerServices.GetProviderManifestToken(conn); - Assert.NotNull(token); + Assert.That(token, Is.Not.Null); } } } diff --git a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/SetOperators.cs b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/SetOperators.cs index 2c6c37e86..3ebc28dbb 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/SetOperators.cs +++ b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/SetOperators.cs @@ -78,7 +78,7 @@ public void FirstSimple() select p; Product product = q.First() as Product; - Assert.AreEqual(id, product.Id); + Assert.That(product.Id, Is.EqualTo(id)); } } @@ -94,7 +94,7 @@ public void FirstPredicate() where p.MinAge > 8 select p; Product product = q.First() as Product; - Assert.AreEqual(id, product.Id); + Assert.That(product.Id, Is.EqualTo(id)); } } } diff --git a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/SimpleQuery.cs b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/SimpleQuery.cs index 28c1730e3..8ef037ed9 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/SimpleQuery.cs +++ b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/SimpleQuery.cs @@ -84,7 +84,7 @@ public void TablesWithSchemaWithoutUsingProperty() context.SaveChanges(); var q = (from u in context.User select u).ToArray(); - Assert.IsTrue(q.Length == 2); + Assert.That(q.Length == 2); } } } diff --git a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/Wizard.cs b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/Wizard.cs index fc4350fde..9ed361481 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/Wizard.cs +++ b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/Wizard.cs @@ -45,17 +45,17 @@ public void GetDbProviderManifestTokenReturnsCorrectSchemaVersion() string token = services.GetProviderManifestToken(Connection); if (Version < new Version(5, 1)) - Assert.AreEqual("5.0", token); + Assert.That(token, Is.EqualTo("5.0")); else if (Version < new Version(5, 5)) - Assert.AreEqual("5.1", token); + Assert.That(token, Is.EqualTo("5.1")); else if (Version < new Version(5, 6)) - Assert.AreEqual("5.5", token); + Assert.That(token, Is.EqualTo("5.5")); else if (Version < new Version(5, 7)) - Assert.AreEqual("5.6", token); + Assert.That(token, Is.EqualTo("5.6")); else if (Version < new Version(8, 0)) - Assert.AreEqual("5.7", token); + Assert.That(token, Is.EqualTo("5.7")); else - Assert.AreEqual("8.0", token); + Assert.That(token, Is.EqualTo("8.0")); } [Test] @@ -64,7 +64,7 @@ public void GetStoreSchemaDescriptionDoesNotThrowForServer50OrGreater() MySqlProviderManifest manifest = new MySqlProviderManifest(Version.Major + "." + Version.Minor); using (XmlReader reader = manifest.GetInformation(DbXmlEnabledProviderManifest.StoreSchemaDefinition)) { - Assert.NotNull(reader); + Assert.That(reader, Is.Not.Null); } } } diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/CodeFirstFixture.cs b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/CodeFirstFixture.cs index 4689889e1..49ea6b4e8 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/CodeFirstFixture.cs +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/CodeFirstFixture.cs @@ -174,19 +174,19 @@ private EntityConnection GetEntityConnection() foreach (char c in refSql) if (!Char.IsWhiteSpace(c)) str2.Append(c); - Assert.AreEqual(0, String.Compare(str1.ToString(), str2.ToString(), true)); + Assert.That(String.Compare(str1.ToString(), str2.ToString(), true), Is.EqualTo(0)); } private class AssertFailTraceListener : DefaultTraceListener { public override void Fail(string message) { - Assert.True(message == String.Empty, "Failure: " + message); + Assert.That(message == String.Empty, "Failure: " + message); } public override void Fail(string message, string detailMessage) { - Assert.True(message == String.Empty, "Failure: " + message); + Assert.That(message == String.Empty, "Failure: " + message); } } } diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/CodeFirstTests.cs b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/CodeFirstTests.cs index fb04f751c..1b247cd6c 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/CodeFirstTests.cs +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/CodeFirstTests.cs @@ -65,7 +65,7 @@ public void SimpleCodeFirstSelect() { j--; } - Assert.AreEqual(0, j); + Assert.That(j, Is.EqualTo(0)); } /// @@ -87,14 +87,14 @@ public void AlterTableTest() { j--; } - Assert.AreEqual(0, j); + Assert.That(j, Is.EqualTo(0)); MovieFormat m = new MovieFormat(); m.Format = 8.0f; db.MovieFormats.Add(m); db.SaveChanges(); MovieFormat m2 = db.MovieFormats.Where(p => p.Format == 8.0f).FirstOrDefault(); - Assert.NotNull(m2); - Assert.AreEqual(8.0f, m2.Format); + Assert.That(m2, Is.Not.Null); + Assert.That(m2.Format, Is.EqualTo(8.0f)); } /// @@ -168,7 +168,7 @@ public void CheckByteArray() ((IObjectContextAdapter)db).ObjectContext.CreateDatabaseScript(); Regex rx = new Regex(@"`Data` (?[^\),]*)", RegexOptions.Compiled | RegexOptions.Singleline); Match m = rx.Match(dbCreationScript); - Assert.AreEqual("longblob", m.Groups["type"].Value); + Assert.That(m.Groups["type"].Value, Is.EqualTo("longblob")); } /// @@ -187,7 +187,7 @@ public void CallStoredProcedure() context.Database.ExecuteSqlCommand(@"create procedure `GetCount`() begin select 5; end;"); long count = context.Database.SqlQuery("call GetCount").First(); - Assert.AreEqual(5, count); + Assert.That(count, Is.EqualTo(5)); } } @@ -220,7 +220,7 @@ public void Bug63920_Test1() records = Convert.ToInt32(cmd.ExecuteScalar()); } - Assert.AreEqual(context.Vehicles.Count(), records); + Assert.That(records, Is.EqualTo(context.Vehicles.Count())); } } @@ -253,7 +253,7 @@ public void Bug63920_Test2() records = Convert.ToInt32(cmd.ExecuteScalar()); } - Assert.AreEqual(context.Vehicles.Count(), records); + Assert.That(records, Is.EqualTo(context.Vehicles.Count())); } } @@ -275,8 +275,8 @@ public void TestPrecisionNscale() where table_schema = '{Connection.Database}' and table_name = 'movies' and column_name = 'Price'", Connection).ExecuteReader()) { r.Read(); - Assert.AreEqual(16, r.GetInt32(0)); - Assert.AreEqual(2, r.GetInt32(1)); + Assert.That(r.GetInt32(0), Is.EqualTo(16)); + Assert.That(r.GetInt32(1), Is.EqualTo(2)); } } @@ -310,9 +310,9 @@ public void TestStringTypeToStoreType() MySqlDataReader reader = query.ExecuteReader(); while (reader.Read()) { - Assert.AreEqual("Description", reader[0].ToString()); - Assert.AreEqual("NO", reader[1].ToString()); - Assert.AreEqual("mediumtext", reader[2].ToString()); + Assert.That(reader[0].ToString(), Is.EqualTo("Description")); + Assert.That(reader[1].ToString(), Is.EqualTo("NO")); + Assert.That(reader[2].ToString(), Is.EqualTo("mediumtext")); } reader.Close(); @@ -320,10 +320,10 @@ public void TestStringTypeToStoreType() reader = query.ExecuteReader(); while (reader.Read()) { - Assert.AreEqual("Name", reader[0].ToString()); - Assert.AreEqual("NO", reader[1].ToString()); - Assert.AreEqual("varchar", reader[2].ToString()); - Assert.AreEqual("255", reader[3].ToString()); + Assert.That(reader[0].ToString(), Is.EqualTo("Name")); + Assert.That(reader[1].ToString(), Is.EqualTo("NO")); + Assert.That(reader[2].ToString(), Is.EqualTo("varchar")); + Assert.That(reader[3].ToString(), Is.EqualTo("255")); } reader.Close(); @@ -331,10 +331,10 @@ public void TestStringTypeToStoreType() reader = query.ExecuteReader(); while (reader.Read()) { - Assert.AreEqual("LongDescription", reader[0].ToString()); - Assert.AreEqual("NO", reader[1].ToString()); - Assert.AreEqual("longtext", reader[2].ToString()); - Assert.AreEqual("4294967295", reader[3].ToString()); + Assert.That(reader[0].ToString(), Is.EqualTo("LongDescription")); + Assert.That(reader[1].ToString(), Is.EqualTo("NO")); + Assert.That(reader[2].ToString(), Is.EqualTo("longtext")); + Assert.That(reader[3].ToString(), Is.EqualTo("4294967295")); } } } @@ -360,7 +360,7 @@ public void AddingEmptyRow() using (MovieDBContext ctx2 = new MovieDBContext()) { var q = from esc in ctx2.EntitySingleColumns where esc.Id == 1 select esc; - Assert.AreEqual(1, q.Count()); + Assert.That(q.Count(), Is.EqualTo(1)); } } @@ -413,7 +413,7 @@ public void IdentityTest() // Validates Guid MySqlCommand cmd = new MySqlCommand("SELECT * FROM Manufacturers", conn); MySqlDataReader dr = cmd.ExecuteReader(); - Assert.False(!dr.HasRows, "No records found"); + Assert.That(dr.HasRows, "No records found"); while (dr.Read()) { @@ -421,12 +421,12 @@ public void IdentityTest() switch (name) { case "Nissan": - Assert.AreEqual(dr.GetGuid(0), nissan.ManufacturerId); - Assert.AreEqual(dr.GetGuid(2), nissan.GroupIdentifier); + Assert.That(nissan.ManufacturerId, Is.EqualTo(dr.GetGuid(0))); + Assert.That(nissan.GroupIdentifier, Is.EqualTo(dr.GetGuid(2))); break; case "Ford": - Assert.AreEqual(dr.GetGuid(0), ford.ManufacturerId); - Assert.AreEqual(dr.GetGuid(2), ford.GroupIdentifier); + Assert.That(ford.ManufacturerId, Is.EqualTo(dr.GetGuid(0))); + Assert.That(ford.GroupIdentifier, Is.EqualTo(dr.GetGuid(2))); break; default: //Assert.Fail(); @@ -446,10 +446,10 @@ public void IdentityTest() switch (name) { case "Distributor1": - Assert.AreEqual(dr.GetInt32(0), dis1.DistributorId); + Assert.That(dis1.DistributorId, Is.EqualTo(dr.GetInt32(0))); break; case "Distributor2": - Assert.AreEqual(dr.GetInt32(0), dis2.DistributorId); + Assert.That(dis2.DistributorId, Is.EqualTo(dr.GetInt32(0))); break; default: //Assert.Fail(); @@ -490,7 +490,7 @@ public void FirstOrDefaultNested() { j--; } - Assert.AreEqual(0, j); + Assert.That(j, Is.EqualTo(0)); } } @@ -523,7 +523,7 @@ orderby cu.customer_id descending { //Debug.WriteLine( r.country1 ); } - Assert.AreEqual(599, j); + Assert.That(j, Is.EqualTo(599)); } } @@ -550,10 +550,10 @@ public void CanDefineDatesWithPrecisionFor56() MySqlDataReader reader = query.ExecuteReader(); while (reader.Read()) { - Assert.AreEqual("DateTimeWithPrecision", reader[0].ToString()); - Assert.AreEqual("NO", reader[1].ToString()); - Assert.AreEqual("datetime", reader[2].ToString()); - Assert.AreEqual("3", reader[3].ToString()); + Assert.That(reader[0].ToString(), Is.EqualTo("DateTimeWithPrecision")); + Assert.That(reader[1].ToString(), Is.EqualTo("NO")); + Assert.That(reader[2].ToString(), Is.EqualTo("datetime")); + Assert.That(reader[3].ToString(), Is.EqualTo("3")); } reader.Close(); @@ -562,10 +562,10 @@ public void CanDefineDatesWithPrecisionFor56() reader = query.ExecuteReader(); while (reader.Read()) { - Assert.AreEqual("TimeStampWithPrecision", reader[0].ToString()); - Assert.AreEqual("NO", reader[1].ToString()); - Assert.AreEqual("timestamp", reader[2].ToString()); - Assert.AreEqual("3", reader[3].ToString()); + Assert.That(reader[0].ToString(), Is.EqualTo("TimeStampWithPrecision")); + Assert.That(reader[1].ToString(), Is.EqualTo("NO")); + Assert.That(reader[2].ToString(), Is.EqualTo("timestamp")); + Assert.That(reader[3].ToString(), Is.EqualTo("3")); } reader.Close(); } @@ -608,10 +608,10 @@ public void CanDefineDateTimeAndTimestampWithIdentity() updateProduct.DateTimeWithPrecision = new DateTime(2012, 3, 18, 23, 9, 7, 6); db.SaveChanges(); - Assert.NotNull(db.Products.First().Timestamp); - Assert.NotNull(db.Products.First().DateCreated); - Assert.AreEqual(new DateTime(2012, 3, 18, 23, 9, 7, 6), db.Products.First().DateTimeWithPrecision); - Assert.AreEqual(1, db.Products.Count()); + Assert.That(db.Products.First().Timestamp, Is.Not.Empty); + Assert.That(db.Products.First().DateCreated, Is.Not.Empty); + Assert.That(db.Products.First().DateTimeWithPrecision, Is.EqualTo(new DateTime(2012, 3, 18, 23, 9, 7, 6))); + Assert.That(db.Products.Count(), Is.EqualTo(1)); db.Database.Delete(); } } @@ -740,10 +740,10 @@ public void ShipTest() } } // check data integrity - Assert.AreEqual(outData.Count, data.Length); + Assert.That(data.Length, Is.EqualTo(outData.Count)); for (int i = 0; i < data.Length; i++) { - Assert.True(outData.ContainsKey(data[i])); + Assert.That(outData.ContainsKey(data[i])); } } } @@ -852,12 +852,12 @@ public void BadOrderBy() int i = 0; foreach (Movie m in q) { - Assert.AreEqual(data[i].ID, m.ID); - Assert.AreEqual(data[i].Title, m.Title); - Assert.AreEqual(data[i].ReleaseDate, m.ReleaseDate); + Assert.That(m.ID, Is.EqualTo(data[i].ID)); + Assert.That(m.Title, Is.EqualTo(data[i].Title)); + Assert.That(m.ReleaseDate, Is.EqualTo(data[i].ReleaseDate)); i++; } - Assert.AreEqual(2, i); + Assert.That(i, Is.EqualTo(2)); } } @@ -887,9 +887,9 @@ orderby m.ID descending int i = 0; foreach (var row in q1) { - Assert.AreEqual(MovieDBInitialize.data[i].ID, row.ID); - Assert.AreEqual(MovieDBInitialize.data[i].Title, row.Title); - Assert.AreEqual(MovieDBInitialize.data[i].ReleaseDate, row.ReleaseDate); + Assert.That(row.ID, Is.EqualTo(MovieDBInitialize.data[i].ID)); + Assert.That(row.Title, Is.EqualTo(MovieDBInitialize.data[i].Title)); + Assert.That(row.ReleaseDate, Is.EqualTo(MovieDBInitialize.data[i].ReleaseDate)); i++; } } @@ -953,7 +953,7 @@ public void BadContainsOrderByTake2() { j--; } - Assert.AreEqual(0, j); + Assert.That(j, Is.EqualTo(0)); } } @@ -992,7 +992,7 @@ public void BadContainsOrderByTake3() { j--; } - Assert.AreEqual(0, j); + Assert.That(j, Is.EqualTo(0)); } } @@ -1071,7 +1071,7 @@ where m.Title.Contains("x") && db.Medias.Where(mm => mm.Format == "Digital").Any { j--; } - Assert.AreEqual(0, j); + Assert.That(j, Is.EqualTo(0)); } } @@ -1092,7 +1092,7 @@ public void AutoIncrementBug() using (var reader = MySqlHelper.ExecuteReader(dbContext.Database.Connection.ConnectionString, $"SHOW COLUMNS FROM {nameof(dbContext.AutoIncrementBug)}s WHERE UPPER(EXTRA) LIKE '%AUTO_INCREMENT%'")) { - Assert.True(reader.HasRows); + Assert.That(reader.HasRows); } dbContext.Database.Delete(); } @@ -1143,7 +1143,7 @@ public void MigrationHistoryConfigurationTest() { } var result = MySqlHelper.ExecuteScalar($"server=localhost;User Id=root;database={db.Database.Connection.Database};logging=true; port=" + Port + ";", "SELECT COUNT(_MigrationId) FROM __MySqlMigrations;"); - Assert.AreEqual(1, int.Parse(result.ToString())); + Assert.That(int.Parse(result.ToString()), Is.EqualTo(1)); } [Test] @@ -1159,14 +1159,14 @@ public void DbSetRangeTest() db.Movies.AddRange(new Movie[] { m1, m2, m3, m4 }); db.SaveChanges(); var q = from m in db.Movies select m; - Assert.AreEqual(4, q.Count()); + Assert.That(q.Count(), Is.EqualTo(4)); foreach (var row in q) { } db.Movies.RemoveRange(q.ToList()); db.SaveChanges(); var q2 = from m in db.Movies select m; - Assert.AreEqual(0, q2.Count()); + Assert.That(q2.Count(), Is.EqualTo(0)); } } @@ -1183,8 +1183,8 @@ public void EnumSupportTest() where s.Subject == SchoolSubject.History select s).FirstOrDefault(); - Assert.AreNotEqual(null, schedule); - Assert.AreEqual(SchoolSubject.History, schedule.Subject); + Assert.That(schedule, Is.Not.EqualTo(null)); + Assert.That(schedule.Subject, Is.EqualTo(SchoolSubject.History)); } } @@ -1226,15 +1226,15 @@ public void SpatialSupportTest() var distance = (point.Distance(place.location) * 100); - Assert.AreNotEqual(null, place); - Assert.AreEqual(8.6944880240295852D, distance.Value); + Assert.That(place, Is.Not.Null); + Assert.That(distance.Value, Is.EqualTo(8.6944880240295852D)); var points = from p in dbCtx.MyPlaces select new { name = p.name, location = p.location }; foreach (var item in points) { var distanceX = DbGeometry.FromText("POINT(40.717957 -73.736501)").Distance(item.location) * 100; - Assert.IsNotNull(distanceX); + Assert.That(distanceX, Is.Not.Null); } foreach (MyPlace p in dbCtx.MyPlaces) @@ -1268,9 +1268,9 @@ public void SpatialSupportTest() var result = (from u in dbCtx.MyPlaces select u.location.CoordinateSystemId).ToList(); foreach (var item in result) - Assert.IsNotNull(item); + Assert.That(item, Is.Not.Empty); var res = dbCtx.MyPlaces.OrderBy(q => q.name.Take(1).Skip(1).ToList()); - Assert.IsNotNull(res); + Assert.That(res, Is.Not.Null); var pointA1 = DbGeometry.FromText(string.Format("POINT(40.644047 -73.782291)")); var pointB1 = DbGeometry.FromText("POINT(40.717957 -73.736501)"); @@ -1284,7 +1284,7 @@ public void SpatialSupportTest() var pointB3 = DbGeometry.FromText("POINT(-1 3)"); var distance3 = pointA3.Distance(pointB3); - Assert.True(distance1.Value == 0.086944880240295855 && distance2.Value == 2.2671568097509267 && + Assert.That(distance1.Value == 0.086944880240295855 && distance2.Value == 2.2671568097509267 && distance3.Value == 8.06225774829855); } @@ -1310,12 +1310,12 @@ public void BeginTransactionSupportTest() dbcontext.SaveChanges(); var result = MySqlHelper.ExecuteScalar("server=localhost;User Id=root;database=test;logging=true;port=" + Port + ";", "select COUNT(*) from moviecbcs;"); - Assert.AreEqual(0, int.Parse(result.ToString())); + Assert.That(int.Parse(result.ToString()), Is.EqualTo(0)); transaction.Commit(); result = MySqlHelper.ExecuteScalar("server=localhost;User Id=root;database=test;logging=true; port=" + Port + ";", "select COUNT(*) from moviecbcs;"); - Assert.AreEqual(1, int.Parse(result.ToString())); + Assert.That(int.Parse(result.ToString()), Is.EqualTo(1)); } catch (Exception) { @@ -1359,12 +1359,12 @@ public void UseTransactionSupportTest() dbcontext.SaveChanges(); } var result = MySqlHelper.ExecuteScalar("server=localhost;User Id=root;database=test;logging=true; port=" + Port + ";", "select COUNT(*) from moviecbcs;"); - Assert.AreEqual(0, int.Parse(result.ToString())); + Assert.That(int.Parse(result.ToString()), Is.EqualTo(0)); transaction.Commit(); result = MySqlHelper.ExecuteScalar("server=localhost;User Id=root;database=test;logging=true; port=" + Port + ";", "select COUNT(*) from moviecbcs;"); - Assert.AreEqual(1, int.Parse(result.ToString())); + Assert.That(int.Parse(result.ToString()), Is.EqualTo(1)); } catch (Exception) { @@ -1390,9 +1390,9 @@ public void HasChangesSupportTest() ReleaseDate = DateTime.Parse("01/07/2013") }); - Assert.True(dbcontext.ChangeTracker.HasChanges()); + Assert.That(dbcontext.ChangeTracker.HasChanges()); dbcontext.SaveChanges(); - Assert.False(dbcontext.ChangeTracker.HasChanges()); + Assert.That(!dbcontext.ChangeTracker.HasChanges()); } } @@ -1419,7 +1419,7 @@ public void MySqlLoggingToFileSupportTest() dbcontext.SaveChanges(); } - Assert.AreEqual(true, System.IO.File.Exists(logName)); + Assert.That(System.IO.File.Exists(logName), Is.EqualTo(true)); } [Test] @@ -1462,7 +1462,7 @@ public void MySqlLoggingToConsoleSupportTest() writer.Close(); file.Close(); - Assert.AreEqual(true, System.IO.File.Exists(logName)); + Assert.That(System.IO.File.Exists(logName), Is.EqualTo(true)); } [Test] @@ -1483,10 +1483,11 @@ public void EntityAndComplexTypeSupportTest() var student = (from s in dbContext.Students select s).FirstOrDefault(); - Assert.AreNotEqual(null, student); - Assert.AreNotEqual(null, student.Schedule); - Assert.AreNotEqual(true, string.IsNullOrEmpty(student.Address.Street)); - Assert.AreNotEqual(0, student.Schedule.Count()); + Assert.That(student, Is.Not.Null); + Assert.That(student.Schedule, Is.Not.Null); + Assert.That(student.Address.Street, Is.Not.Null); + Assert.That(student.Address.Street, Is.Not.Empty); + Assert.That(student.Schedule.Count(), Is.Not.EqualTo(0)); } } @@ -1516,7 +1517,7 @@ public void ExecutionStrategyTest() connection.Dispose(); } var result = MySqlHelper.ExecuteScalar("server=localhost;User Id=root;database=test;logging=true; port=" + Port + ";", "select COUNT(*) from moviecbcs;"); - Assert.AreEqual(1, int.Parse(result.ToString())); + Assert.That(int.Parse(result.ToString()), Is.EqualTo(1)); } [Test] @@ -1565,7 +1566,7 @@ public void StartsWithTest() { j--; } - Assert.AreEqual(0, j); + Assert.That(j, Is.EqualTo(0)); } [Test] @@ -1592,7 +1593,7 @@ public void EndsWithTest() { j--; } - Assert.AreEqual(0, j); + Assert.That(j, Is.EqualTo(0)); } [Test] @@ -1618,7 +1619,7 @@ public void ContainsTest() { j--; } - Assert.AreEqual(0, j); + Assert.That(j, Is.EqualTo(0)); } @@ -1708,7 +1709,7 @@ public void ReplaceTableNameVisitor() Debug.WriteLine(sql); #endif var result = rentals.ToList(); - Assert.AreEqual(520, rentals.Count()); + Assert.That(rentals.Count(), Is.EqualTo(520)); } } @@ -1748,9 +1749,9 @@ public void InvalidQuery() .Include(c => c.Orders.Select(o => o.Items)) .Include(c => c.Orders.Select(o => o.Discounts)).ToList(); - Assert.AreEqual(clients.Count(), 3); - Assert.AreEqual(clients.Where(t => t.Id == 1).Single().Orders.Count(), 1); - Assert.AreEqual(clients.Where(t => t.Id == 1).Single().Orders.Where(j => j.Id == 1).Single().Items.Count(), 3); + Assert.That(3, Is.EqualTo(clients.Count())); + Assert.That(1, Is.EqualTo(clients.Where(t => t.Id == 1).Single().Orders.Count())); + Assert.That(3, Is.EqualTo(clients.Where(t => t.Id == 1).Single().Orders.Where(j => j.Id == 1).Single().Items.Count())); } } @@ -1795,17 +1796,17 @@ BEFORE UPDATE ON `MovieRelease2` mr.Id = 1; mr.Name = "Commercial"; db.MovieReleases2.Add(mr); - Assert.AreEqual(mr.RowVersion, 0); + Assert.That(0, Is.EqualTo(mr.RowVersion)); db.SaveChanges(); // ADD - Assert.AreEqual(mr.RowVersion, 0); + Assert.That(0, Is.EqualTo(mr.RowVersion)); mr.Name = "Director's Cut"; db.SaveChanges(); // UPDATE #1 - Assert.AreEqual(mr.RowVersion, 1); + Assert.That(1, Is.EqualTo(mr.RowVersion)); mr.Name = "Avengers"; db.SaveChanges(); // UPDATE #2 - Assert.AreEqual(mr.RowVersion, 2); + Assert.That(2, Is.EqualTo(mr.RowVersion)); } finally { @@ -1847,13 +1848,13 @@ public void TablesWithSchema() context.Blog.Add(blog); context.SaveChanges(); - Assert.AreEqual(2, context.Blog.Count()); - Assert.AreEqual(2, context.Blog.First(b => b.Title == "Blog_2").BlogId); + Assert.That(context.Blog.Count(), Is.EqualTo(2)); + Assert.That(context.Blog.First(b => b.Title == "Blog_2").BlogId, Is.EqualTo(2)); context.Blog.Remove(blog); context.SaveChanges(); - Assert.AreEqual(1, context.Blog.Count()); - Assert.AreEqual("Blog_1", context.Blog.First().Title); + Assert.That(context.Blog.Count(), Is.EqualTo(1)); + Assert.That(context.Blog.First().Title, Is.EqualTo("Blog_1")); } } @@ -1909,7 +1910,7 @@ public void UnionSyntax() var query1 = context.StringUsers; var query2 = query1.Take(0).Concat(query1); var query3 = query1.Concat(query1.Take(0)); - Assert.True((query1.Count() == 5) & (query2.Count() == 5) & (query3.Count() == 5)); + Assert.That((query1.Count() == 5) & (query2.Count() == 5) & (query3.Count() == 5)); } } @@ -1935,7 +1936,7 @@ public void NormalForeignKey() while (reader.Read()) { var val = reader.GetValue(0); - Assert.True(val.ToString().Contains("FK_")); + Assert.That(val.ToString().Contains("FK_")); } } } @@ -1964,7 +1965,7 @@ public void LongForeignKey() while (reader.Read()) { var val = reader.GetValue(0); - Assert.True(val.ToString().Contains("FK_")); + Assert.That(val.ToString().Contains("FK_")); } } } @@ -2026,7 +2027,7 @@ public void SaveTinyIntAsPK() var query1 = context.TinyPkUseRs; var query2 = query1.Take(0).Concat(query1); var query3 = query1.Concat(query1.Take(0)); - Assert.True((query1.Count() == 5) & (query2.Count() == 5) & (query3.Count() == 5)); + Assert.That((query1.Count() == 5) & (query2.Count() == 5) & (query3.Count() == 5)); } } @@ -2085,7 +2086,7 @@ public void SaveBigIntAsPK() var query1 = context.BigIntPkUseRs; var query2 = query1.Take(0).Concat(query1); var query3 = query1.Concat(query1.Take(0)); - Assert.True((query1.Count() == 5) & (query2.Count() == 5) & (query3.Count() == 5)); + Assert.That((query1.Count() == 5) & (query2.Count() == 5) & (query3.Count() == 5)); } } @@ -2126,7 +2127,7 @@ public void BeginTransNested() trans.Commit(); } var count = context.SchoolSchedules.Count(); - Assert.AreEqual(3, count); + Assert.That(count, Is.EqualTo(3)); //Rollback using (var trans = context.Database.BeginTransaction()) { @@ -2145,7 +2146,7 @@ public void BeginTransNested() trans.Commit(); } count = context.SchoolSchedules.Count(); - Assert.AreEqual(4, count); + Assert.That(count, Is.EqualTo(4)); } } @@ -2186,7 +2187,7 @@ public void TransactionAfterFailStressTest() context.SaveChanges(); trans.Commit(); var count = context.SchoolSchedules.Count(); - Assert.True(count > 0); + Assert.That(count > 0); } } } @@ -2231,23 +2232,23 @@ public void TestListMatchingLike() string[] matchText = new string[] { "must", "tan" }; var list = context.Vehicles.Where(v => matchText.Any(t => v.Name.Contains(t))); - Assert.AreEqual(1, list.Count()); + Assert.That(list.Count(), Is.EqualTo(1)); matchText = new string[] { "mus't", "tan" }; list = context.Vehicles.Where(v => matchText.Any(t => v.Name.Contains(t))); - Assert.AreEqual(1, list.Count()); + Assert.That(list.Count(), Is.EqualTo(1)); matchText = new string[] { "%" }; list = context.Vehicles.Where(v => matchText.Any(t => v.Name.Contains(t))); - Assert.AreEqual(0, list.Count()); + Assert.That(list.Count(), Is.EqualTo(0)); matchText = new string[] { "tan" }; list = context.Vehicles.Where(v => matchText.Any(t => v.Name.Contains(t))); - Assert.AreEqual(1, list.Count()); + Assert.That(list.Count(), Is.EqualTo(1)); matchText = new string[] { "_" }; list = context.Vehicles.Where(v => matchText.Any(t => v.Name.Contains(t))); - Assert.AreEqual(0, list.Count()); + Assert.That(list.Count(), Is.EqualTo(0)); } } } diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/GlobalUsings.cs b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/GlobalUsings.cs deleted file mode 100644 index 575c7cfd0..000000000 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/GlobalUsings.cs +++ /dev/null @@ -1,5 +0,0 @@ -global using Assert = NUnit.Framework.Legacy.ClassicAssert; -global using CollectionAssert = NUnit.Framework.Legacy.CollectionAssert; -global using StringAssert = NUnit.Framework.Legacy.StringAssert; -global using DirectoryAssert = NUnit.Framework.Legacy.DirectoryAssert; -global using FileAssert = NUnit.Framework.Legacy.FileAssert; diff --git a/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/GlobalUsings.cs b/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/GlobalUsings.cs deleted file mode 100644 index 575c7cfd0..000000000 --- a/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/GlobalUsings.cs +++ /dev/null @@ -1,5 +0,0 @@ -global using Assert = NUnit.Framework.Legacy.ClassicAssert; -global using CollectionAssert = NUnit.Framework.Legacy.CollectionAssert; -global using StringAssert = NUnit.Framework.Legacy.StringAssert; -global using DirectoryAssert = NUnit.Framework.Legacy.DirectoryAssert; -global using FileAssert = NUnit.Framework.Legacy.FileAssert; diff --git a/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/MySqlMigrationsTests.cs b/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/MySqlMigrationsTests.cs index bf2974f29..e43268894 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/MySqlMigrationsTests.cs +++ b/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/MySqlMigrationsTests.cs @@ -85,15 +85,15 @@ public void AddColumnOperationMigration() using (MySqlConnection conn = new MySqlConnection(context.Database.Connection.ConnectionString)) { if (conn.State == System.Data.ConnectionState.Closed) conn.Open(); - Assert.AreEqual(true, GenerateAndExecuteMySQLStatements(migrationOperations)); + Assert.That(GenerateAndExecuteMySQLStatements(migrationOperations), Is.EqualTo(true)); MySqlCommand query = new MySqlCommand("Select Column_name, Is_Nullable, Data_Type from information_schema.Columns where table_schema ='" + conn.Database + "' and table_name = 'Blogs' and column_name ='TotalPosts'", conn); MySqlDataReader reader = query.ExecuteReader(); while (reader.Read()) { - Assert.AreEqual("TotalPosts", reader[0].ToString()); - Assert.AreEqual("NO", reader[1].ToString()); - Assert.AreEqual("int", reader[2].ToString()); + Assert.That(reader[0].ToString(), Is.EqualTo("TotalPosts")); + Assert.That(reader[1].ToString(), Is.EqualTo("NO")); + Assert.That(reader[2].ToString(), Is.EqualTo("int")); } reader.Close(); conn.Close(); @@ -122,7 +122,7 @@ public void CreateTableOperationMigration() using (var conn = new MySqlConnection(context.Database.Connection.ConnectionString)) { if (conn.State == System.Data.ConnectionState.Closed) conn.Open(); - Assert.True(GenerateAndExecuteMySQLStatements(migrationOperations)); + Assert.That(GenerateAndExecuteMySQLStatements(migrationOperations)); using (MySqlCommand query = new MySqlCommand($"SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA ='{conn.Database}'" + $" AND TABLE_NAME = 'Posts'", conn)) { @@ -137,7 +137,7 @@ public void CreateTableOperationMigration() query.CommandText = $"SELECT COLUMN_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = '{conn.Database}' AND " + $"TABLE_NAME = 'Posts' AND COLUMN_NAME = 'Password'"; - StringAssert.AreEqualIgnoringCase("binary(10)", query.ExecuteScalar().ToString()); + Assert.That(query.ExecuteScalar().ToString(), Is.EqualTo("binary(10)").IgnoreCase); } } } @@ -195,7 +195,7 @@ public void CreateForeignKeyOperation() if (context.Database.Exists()) context.Database.Delete(); context.Database.Create(); - Assert.AreEqual(true, GenerateAndExecuteMySQLStatements(migrationOperations)); + Assert.That(GenerateAndExecuteMySQLStatements(migrationOperations), Is.EqualTo(true)); using (var conn = new MySqlConnection(context.Database.Connection.ConnectionString)) { @@ -203,11 +203,11 @@ public void CreateForeignKeyOperation() // check for foreign key creation MySqlCommand query = new MySqlCommand("select Count(*) from information_schema.table_constraints where LOWER(constraint_type) = 'foreign key' and constraint_schema = '" + conn.Database + "' and constraint_name = 'FKBlogs'", conn); int rows = Convert.ToInt32(query.ExecuteScalar()); - Assert.AreEqual(1, rows); + Assert.That(rows, Is.EqualTo(1)); // check for table creation query = new MySqlCommand("select Count(*) from information_schema.Tables WHERE `table_name` = 'Posts' and `table_schema` = '" + conn.Database + "' ", conn); rows = Convert.ToInt32(query.ExecuteScalar()); - Assert.AreEqual(1, rows); + Assert.That(rows, Is.EqualTo(1)); conn.Close(); } @@ -221,7 +221,7 @@ public void CreateForeignKeyOperation() { r.Read(); string sql = r.GetString(1); - Assert.True(sql.IndexOf( + Assert.That(sql.IndexOf( " CONSTRAINT `FKBlogs` FOREIGN KEY (`BlogId`) REFERENCES `blogs` (`BlogId`) ON DELETE CASCADE ON UPDATE CASCADE", StringComparison.OrdinalIgnoreCase) != -1); } @@ -259,7 +259,7 @@ public void DropPrimaryKeyOperationWithAnonymousArguments() context.Database.Create(); - Assert.AreEqual(true, GenerateAndExecuteMySQLStatements(migrationOperations)); + Assert.That(GenerateAndExecuteMySQLStatements(migrationOperations), Is.EqualTo(true)); using (var conn = new MySqlConnection(context.Database.Connection.ConnectionString)) { @@ -268,21 +268,21 @@ public void DropPrimaryKeyOperationWithAnonymousArguments() // check for table creation var query = new MySqlCommand("select Count(*) from information_schema.Tables WHERE `table_name` = 'Posts' and `table_schema` = '" + conn.Database + "' ", conn); int rows = Convert.ToInt32(query.ExecuteScalar()); - Assert.AreEqual(1, rows); + Assert.That(rows, Is.EqualTo(1)); // check if PK exists query = new MySqlCommand("select Count(*) from information_schema.table_constraints where `constraint_type` = 'primary key' and `constraint_schema` = '" + conn.Database + "' and table_name= 'Posts'", conn); rows = Convert.ToInt32(query.ExecuteScalar()); - Assert.AreEqual(0, rows); + Assert.That(rows, Is.EqualTo(0)); //check the definition of the column that was PK query = new MySqlCommand("Select Column_name, Is_Nullable, Data_Type from information_schema.Columns where table_schema ='" + conn.Database + "' and table_name = 'Posts' and column_name ='PostId'", conn); MySqlDataReader reader = query.ExecuteReader(); while (reader.Read()) { - Assert.AreEqual("PostId", reader[0].ToString()); - Assert.AreEqual("NO", reader[1].ToString()); - Assert.AreEqual("int", reader[2].ToString()); + Assert.That(reader[0].ToString(), Is.EqualTo("PostId")); + Assert.That(reader[1].ToString(), Is.EqualTo("NO")); + Assert.That(reader[2].ToString(), Is.EqualTo("int")); } reader.Close(); conn.Close(); @@ -315,7 +315,7 @@ public void DropPrimaryKeyOperation() context.Database.Create(); - Assert.AreEqual(true, GenerateAndExecuteMySQLStatements(migrationOperations)); + Assert.That(GenerateAndExecuteMySQLStatements(migrationOperations), Is.EqualTo(true)); using (var conn = new MySqlConnection(context.Database.Connection.ConnectionString)) { @@ -324,21 +324,21 @@ public void DropPrimaryKeyOperation() // check for table creation var query = new MySqlCommand("select Count(*) from information_schema.Tables WHERE `table_name` = 'Posts' and `table_schema` = '" + conn.Database + "' ", conn); int rows = Convert.ToInt32(query.ExecuteScalar()); - Assert.AreEqual(1, rows); + Assert.That(rows, Is.EqualTo(1)); // check if PK exists query = new MySqlCommand("select Count(*) from information_schema.table_constraints where `constraint_type` = 'primary key' and `constraint_schema` = '" + conn.Database + "' and table_name= 'Posts'", conn); rows = Convert.ToInt32(query.ExecuteScalar()); - Assert.AreEqual(0, rows); + Assert.That(rows, Is.EqualTo(0)); //check the definition of the column that was PK query = new MySqlCommand("Select Column_name, Is_Nullable, Data_Type from information_schema.Columns where table_schema ='" + conn.Database + "' and table_name = 'Posts' and column_name ='PostId'", conn); MySqlDataReader reader = query.ExecuteReader(); while (reader.Read()) { - Assert.AreEqual("PostId", reader[0].ToString()); - Assert.AreEqual("NO", reader[1].ToString()); - Assert.AreEqual("int", reader[2].ToString()); + Assert.That(reader[0].ToString(), Is.EqualTo("PostId")); + Assert.That(reader[1].ToString(), Is.EqualTo("NO")); + Assert.That(reader[2].ToString(), Is.EqualTo("int")); } reader.Close(); conn.Close(); diff --git a/MySQL.Data/tests/MySql.Data.Tests/AttributeTests.cs b/MySQL.Data/tests/MySql.Data.Tests/AttributeTests.cs index e52a7279b..2dbeba0e0 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/AttributeTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/AttributeTests.cs @@ -57,15 +57,15 @@ public void SetAttributesWithoutParams(bool prepare) if (prepare) cmd.Prepare(); var result = cmd.ExecuteScalar(); - if (Version >= new Version(8, 0, 26) || !prepare) StringAssert.AreEqualIgnoringCase("v1", result.ToString()); - else Assert.IsEmpty(result.ToString()); + if (Version >= new Version(8, 0, 26) || !prepare) Assert.That(result.ToString(), Is.EqualTo("v1").IgnoreCase); + else Assert.That(result.ToString(), Is.Empty); cmd.Attributes.SetAttribute("n2", 123); cmd.CommandText = "SELECT mysql_query_attribute_string('n2')"; if (prepare) cmd.Prepare(); result = cmd.ExecuteScalar(); - if (Version >= new Version(8, 0, 26) || !prepare) StringAssert.AreEqualIgnoringCase("123", result.ToString()); - else Assert.IsEmpty(result.ToString()); + if (Version >= new Version(8, 0, 26) || !prepare) Assert.That(result.ToString(), Is.EqualTo("123").IgnoreCase); + else Assert.That(result.ToString(), Is.Empty); MySqlAttribute attr = new MySqlAttribute(); attr.AttributeName = "n3"; @@ -74,8 +74,8 @@ public void SetAttributesWithoutParams(bool prepare) cmd.CommandText = "SELECT mysql_query_attribute_string('n3')"; if (prepare) cmd.Prepare(); result = cmd.ExecuteScalar(); - if (Version >= new Version(8, 0, 26) || !prepare) StringAssert.AreEqualIgnoringCase("v3", result.ToString()); - else Assert.IsEmpty(result.ToString()); + if (Version >= new Version(8, 0, 26) || !prepare) Assert.That(result.ToString(), Is.EqualTo("v3").IgnoreCase); + else Assert.That(result.ToString(), Is.Empty); } [TestCase("StringType", "value1")] @@ -93,7 +93,7 @@ public void ValueTypes(string name, object value) cmd.Attributes.SetAttribute(name, value); cmd.CommandText = $"SELECT mysql_query_attribute_string('{name}')"; var result = cmd.ExecuteScalar(); - StringAssert.AreEqualIgnoringCase(value.ToString(), result.ToString()); + Assert.That(result.ToString(), Is.EqualTo(value.ToString()).IgnoreCase); } [Test] @@ -108,7 +108,7 @@ public void TimeSpanValueType() cmd.Attributes.SetAttribute("TimeSpan", time); cmd.CommandText = "SELECT mysql_query_attribute_string('TimeSpan')"; var result = cmd.ExecuteScalar(); - StringAssert.StartsWith(time.ToString(), result.ToString()); + Assert.That(result.ToString(), Does.StartWith(time.ToString())); } [Test] @@ -123,7 +123,7 @@ public void DateTimeValueType() cmd.Attributes.SetAttribute("DateTime", dateTime); cmd.CommandText = "SELECT mysql_query_attribute_string('DateTime')"; var result = cmd.ExecuteScalar(); - Assert.AreEqual(dateTime.ToString("yyyy-MM-dd HH:mm:ss.ffffff"), result.ToString()); + Assert.That(result.ToString(), Is.EqualTo(dateTime.ToString("yyyy-MM-dd HH:mm:ss.ffffff"))); } [Test] @@ -131,13 +131,13 @@ public void ClearAttributes() { using MySqlCommand cmd = new MySqlCommand(); cmd.Attributes.SetAttribute("foo", "bar"); - Assert.AreEqual(1, cmd.Attributes.Count); + Assert.That(cmd.Attributes.Count, Is.EqualTo(1)); cmd.Attributes.SetAttribute("bar", "foo"); - Assert.AreEqual(2, cmd.Attributes.Count); + Assert.That(cmd.Attributes.Count, Is.EqualTo(2)); cmd.Attributes.Clear(); - Assert.AreEqual(0, cmd.Attributes.Count); + Assert.That(cmd.Attributes.Count, Is.EqualTo(0)); } [Test] @@ -153,7 +153,7 @@ public void SameNameAttribute() cmd.CommandText = "SELECT mysql_query_attribute_string('foo')"; var result = cmd.ExecuteScalar(); - StringAssert.AreEqualIgnoringCase("bar", result.ToString()); + Assert.That(result.ToString(), Is.EqualTo("bar").IgnoreCase); } [TestCase(true)] @@ -177,8 +177,8 @@ public void QueryAttributesNotSupported(bool prepare) if (prepare) cmd.Prepare(); var result = cmd.ExecuteScalar(); - StringAssert.AreEqualIgnoringCase("test", result.ToString()); - StringAssert.Contains(string.Format(Resources.QueryAttributesNotSupported, Version), listener.Strings[0]); + Assert.That(result.ToString(), Is.EqualTo("test").IgnoreCase); + Assert.That(listener.Strings[0], Does.Contain(string.Format(Resources.QueryAttributesNotSupported, Version))); } [TestCase(true)] @@ -199,9 +199,9 @@ public void AttributesAndParameters(bool prepare) { while (reader.Read()) { - StringAssert.AreEqualIgnoringCase("Hello World", reader.GetString(0)); - StringAssert.AreEqualIgnoringCase("Goodbye World", reader.GetString(1)); - if (Version >= new Version(8, 0, 26) || !prepare) StringAssert.AreEqualIgnoringCase("bar", reader.GetString(2)); + Assert.That(reader.GetString(0), Is.EqualTo("Hello World").IgnoreCase); + Assert.That(reader.GetString(1), Is.EqualTo("Goodbye World").IgnoreCase); + if (Version >= new Version(8, 0, 26) || !prepare) Assert.That(reader.GetString(2), Is.EqualTo("bar").IgnoreCase); } } } @@ -236,11 +236,11 @@ public void ParameterOverridesAttributeValue(bool prepare) using var reader = cmd.ExecuteReader(); while (reader.Read()) { - StringAssert.AreEqualIgnoringCase("attribute", reader.GetValue(0).ToString()); - StringAssert.AreEqualIgnoringCase("attribute2", reader.GetValue(1).ToString()); - StringAssert.AreEqualIgnoringCase("parameter", reader.GetValue(2).ToString()); - StringAssert.AreEqualIgnoringCase("parameter2", reader.GetValue(3).ToString()); - StringAssert.AreEqualIgnoringCase("attribute3", reader.GetValue(4).ToString()); + Assert.That(reader.GetValue(0).ToString(), Is.EqualTo("attribute").IgnoreCase); + Assert.That(reader.GetValue(1).ToString(), Is.EqualTo("attribute2").IgnoreCase); + Assert.That(reader.GetValue(2).ToString(), Is.EqualTo("parameter").IgnoreCase); + Assert.That(reader.GetValue(3).ToString(), Is.EqualTo("parameter2").IgnoreCase); + Assert.That(reader.GetValue(4).ToString(), Is.EqualTo("attribute3").IgnoreCase); } } } diff --git a/MySQL.Data/tests/MySql.Data.Tests/AuthTests.cs b/MySQL.Data/tests/MySql.Data.Tests/AuthTests.cs index afd6beba9..29fe191f8 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/AuthTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/AuthTests.cs @@ -202,18 +202,18 @@ private void TestIntegratedSecurityWithoutProxy(string user, bool pooling) threadId = c.ServerThread; MySqlCommand command = new MySqlCommand("SELECT 1", c); long ret = (long)command.ExecuteScalar(); - Assert.AreEqual(1, ret); + Assert.That(ret, Is.EqualTo(1)); command.CommandText = "select user()"; string myUser = (string)command.ExecuteScalar(); // Check if proxy user is correct - StringAssert.StartsWith(UserName + "@", myUser); + Assert.That(myUser, Does.StartWith(UserName + "@")); // check if mysql user is correct // (foo_user is mapped to current OS user) command.CommandText = "select current_user()"; string currentUser = (string)command.ExecuteScalar(); - StringAssert.StartsWith(UserName, currentUser); + Assert.That(currentUser, Does.StartWith(UserName)); } } @@ -329,18 +329,18 @@ private void TestIntegratedSecurityWithUser(string user, bool pooling) threadId = c.ServerThread; MySqlCommand command = new MySqlCommand("SELECT 1", c); long ret = (long)command.ExecuteScalar(); - Assert.AreEqual(1, ret); + Assert.That(ret, Is.EqualTo(1)); command.CommandText = "select user()"; string myUser = (string)command.ExecuteScalar(); // Check if proxy user is correct - StringAssert.StartsWith(UserName + "@", myUser); + Assert.That(myUser, Does.StartWith(UserName + "@")); // check if mysql user is correct // (foo_user is mapped to current OS user) command.CommandText = "select current_user()"; string currentUser = (string)command.ExecuteScalar(); - StringAssert.StartsWith("foo_user@", currentUser); + Assert.That(currentUser, Does.StartWith("foo_user@")); } } @@ -377,16 +377,16 @@ public void ConnectUsingMySqlNativePasswordPlugin() MySqlCommand command = new MySqlCommand("SHOW SESSION STATUS LIKE 'Ssl_version';", connection); using (MySqlDataReader reader = command.ExecuteReader()) { - Assert.True(reader.Read()); - StringAssert.StartsWith("TLSv1", reader.GetString(1)); + Assert.That(reader.Read(), Is.True); + Assert.That(reader.GetString(1), Does.StartWith("TLSv1")); } command.CommandText = String.Format("SELECT `User`, `plugin` FROM `mysql`.`user` WHERE `User` = '{0}';", userName); using (MySqlDataReader reader = command.ExecuteReader()) { - Assert.True(reader.Read()); - Assert.AreEqual(userName, reader.GetString(0)); - Assert.AreEqual(pluginName, reader.GetString(1)); + Assert.That(reader.Read(), Is.True); + Assert.That(reader.GetString(0), Is.EqualTo(userName)); + Assert.That(reader.GetString(1), Is.EqualTo(pluginName)); } connection.Close(); @@ -427,16 +427,16 @@ public void ConnectUsingSha256PasswordPlugin() MySqlCommand command = new MySqlCommand("SHOW SESSION STATUS LIKE 'Ssl_version';", connection); using (MySqlDataReader reader = command.ExecuteReader()) { - Assert.True(reader.Read()); - StringAssert.StartsWith("TLSv1", reader.GetString(1)); + Assert.That(reader.Read(), Is.True); + Assert.That(reader.GetString(1), Does.StartWith("TLSv1")); } command.CommandText = String.Format("SELECT `User`, `plugin` FROM `mysql`.`user` WHERE `User` = '{0}';", userName); using (MySqlDataReader reader = command.ExecuteReader()) { - Assert.True(reader.Read()); - Assert.AreEqual(userName, reader.GetString(0)); - Assert.AreEqual(pluginName, reader.GetString(1)); + Assert.That(reader.Read(), Is.True); + Assert.That(reader.GetString(0), Is.EqualTo(userName)); + Assert.That(reader.GetString(1), Is.EqualTo(pluginName)); } connection.Close(); @@ -464,7 +464,7 @@ public void ConnectUsingSha256PasswordPlugin() if (serverCompiledUsingOpenSsl) { Exception ex = Assert.Throws(() => connection.Open()); - Assert.AreEqual("Retrieval of the RSA public key is not enabled for insecure connections.", ex.Message); + Assert.That(ex.Message, Is.EqualTo("Retrieval of the RSA public key is not enabled for insecure connections.")); } else Assert.Throws(() => connection.Open()); } @@ -491,16 +491,16 @@ public void ConnectUsingSha256PasswordPlugin() MySqlCommand command = new MySqlCommand("SHOW SESSION STATUS LIKE 'Ssl_version';", connection); using (MySqlDataReader reader = command.ExecuteReader()) { - Assert.True(reader.Read()); - StringAssert.StartsWith("TLSv1", reader.GetString(1)); + Assert.That(reader.Read(), Is.True); + Assert.That(reader.GetString(1), Does.StartWith("TLSv1")); } command.CommandText = String.Format("SELECT `User`, `plugin` FROM `mysql`.`user` WHERE `User` = '{0}';", userName); using (MySqlDataReader reader = command.ExecuteReader()) { - Assert.True(reader.Read()); - Assert.AreEqual(userName, reader.GetString(0)); - Assert.AreEqual(pluginName, reader.GetString(1)); + Assert.That(reader.Read(), Is.True); + Assert.That(reader.GetString(0), Is.EqualTo(userName)); + Assert.That(reader.GetString(1), Is.EqualTo(pluginName)); } connection.Close(); @@ -542,9 +542,9 @@ public void AllowPublicKeyRetrievalForSha256PasswordPlugin() { Exception ex = Assert.Throws(() => connection.Open()); ; if (serverCompiledUsingOpenSsl) - Assert.AreEqual("Retrieval of the RSA public key is not enabled for insecure connections.", ex.Message); + Assert.That(ex.Message, Is.EqualTo("Retrieval of the RSA public key is not enabled for insecure connections.")); else - StringAssert.StartsWith("Authentication to host", ex.Message); + Assert.That(ex.Message, Does.StartWith("Authentication to host")); } if (serverCompiledUsingOpenSsl) @@ -606,8 +606,8 @@ public void ConnectUsingCachingSha2Plugin() using (MySqlConnection connection = new MySqlConnection(builder.ConnectionString)) { connection.Open(); - Assert.AreEqual(ConnectionState.Open, connection.connectionState); - Assert.AreEqual(AuthStage.FULL_AUTH, CachingSha2AuthenticationPlugin._authStage); + Assert.That(connection.connectionState, Is.EqualTo(ConnectionState.Open)); + Assert.That(CachingSha2AuthenticationPlugin._authStage, Is.EqualTo(AuthStage.FULL_AUTH)); connection.Close(); } @@ -615,8 +615,8 @@ public void ConnectUsingCachingSha2Plugin() using (MySqlConnection connection = new MySqlConnection(builder.ConnectionString)) { connection.Open(); - Assert.AreEqual(ConnectionState.Open, connection.connectionState); - Assert.AreEqual(AuthStage.FAST_AUTH, CachingSha2AuthenticationPlugin._authStage); + Assert.That(connection.connectionState, Is.EqualTo(ConnectionState.Open)); + Assert.That(CachingSha2AuthenticationPlugin._authStage, Is.EqualTo(AuthStage.FAST_AUTH)); connection.Close(); } @@ -625,14 +625,14 @@ public void ConnectUsingCachingSha2Plugin() using (MySqlConnection connection = new MySqlConnection(builder.ConnectionString)) { connection.Open(); - Assert.AreEqual(AuthStage.FULL_AUTH, CachingSha2AuthenticationPlugin._authStage); + Assert.That(CachingSha2AuthenticationPlugin._authStage, Is.EqualTo(AuthStage.FULL_AUTH)); connection.Close(); } // Authentication failure - TLS connection. builder.Password = "incorrectPassword"; Exception ex = Assert.Throws(() => new MySqlConnection(builder.ConnectionString).Open()); - StringAssert.StartsWith("Access denied for user", ex.InnerException.Message); + Assert.That(ex.InnerException.Message, Does.StartWith("Access denied for user")); // Authentication success with empty password – Any connection. builder.UserID = "testCachingSha2NoPassword"; @@ -643,8 +643,8 @@ public void ConnectUsingCachingSha2Plugin() using (MySqlConnection connection = new MySqlConnection(builder.ConnectionString)) { connection.Open(); - Assert.AreEqual(ConnectionState.Open, connection.connectionState); - Assert.AreEqual(AuthStage.GENERATE_SCRAMBLE, CachingSha2AuthenticationPlugin._authStage); + Assert.That(connection.connectionState, Is.EqualTo(ConnectionState.Open)); + Assert.That(CachingSha2AuthenticationPlugin._authStage, Is.EqualTo(AuthStage.GENERATE_SCRAMBLE)); connection.Close(); } @@ -653,8 +653,8 @@ public void ConnectUsingCachingSha2Plugin() using (MySqlConnection connection = new MySqlConnection(builder.ConnectionString)) { connection.Open(); - Assert.AreEqual(ConnectionState.Open, connection.connectionState); - Assert.AreEqual(AuthStage.GENERATE_SCRAMBLE, CachingSha2AuthenticationPlugin._authStage); + Assert.That(connection.connectionState, Is.EqualTo(ConnectionState.Open)); + Assert.That(CachingSha2AuthenticationPlugin._authStage, Is.EqualTo(AuthStage.GENERATE_SCRAMBLE)); connection.Close(); } @@ -663,12 +663,12 @@ public void ConnectUsingCachingSha2Plugin() builder.UserID = "testCachingSha2"; builder.SslMode = MySqlSslMode.Required; ex = Assert.Throws(() => new MySqlConnection(builder.ConnectionString).Open()); - StringAssert.StartsWith("Access denied for user", ex.InnerException.Message); + Assert.That(ex.InnerException.Message, Does.StartWith("Access denied for user")); // TLS not enabled. builder.SslMode = MySqlSslMode.Disabled; ex = Assert.Throws(() => new MySqlConnection(builder.ConnectionString).Open()); - StringAssert.StartsWith("Access denied for user", ex.InnerException.Message); + Assert.That(ex.InnerException.Message, Does.StartWith("Access denied for user")); // Authentication using RSA keys. Only available in servers compiled with OpenSSL (E.g. Commercial). bool serverCompiledUsingOpenSsl = false; @@ -695,21 +695,21 @@ public void ConnectUsingCachingSha2Plugin() using (MySqlConnection connection = new MySqlConnection(builder.ConnectionString)) { ex = Assert.Throws(() => connection.Open()); - Assert.AreEqual("Retrieval of the RSA public key is not enabled for insecure connections.", ex.Message); + Assert.That(ex.Message, Is.EqualTo("Retrieval of the RSA public key is not enabled for insecure connections.")); } builder.AllowPublicKeyRetrieval = true; using (MySqlConnection connection = new MySqlConnection(builder.ConnectionString)) { connection.Open(); - Assert.AreEqual(AuthStage.FULL_AUTH, CachingSha2AuthenticationPlugin._authStage); + Assert.That(CachingSha2AuthenticationPlugin._authStage, Is.EqualTo(AuthStage.FULL_AUTH)); connection.Close(); } using (MySqlConnection connection = new MySqlConnection(builder.ConnectionString)) { connection.Open(); - Assert.AreEqual(AuthStage.FAST_AUTH, CachingSha2AuthenticationPlugin._authStage); + Assert.That(CachingSha2AuthenticationPlugin._authStage, Is.EqualTo(AuthStage.FAST_AUTH)); connection.Close(); } @@ -718,13 +718,13 @@ public void ConnectUsingCachingSha2Plugin() using (MySqlConnection connection = new MySqlConnection(builder.ConnectionString)) { connection.Open(); - Assert.AreEqual(AuthStage.FULL_AUTH, CachingSha2AuthenticationPlugin._authStage); + Assert.That(CachingSha2AuthenticationPlugin._authStage, Is.EqualTo(AuthStage.FULL_AUTH)); connection.Close(); } builder.Password = "incorrectPassword"; ex = Assert.Throws(() => new MySqlConnection(builder.ConnectionString).Open()); - StringAssert.StartsWith("Access denied for user", ex.InnerException.Message); + Assert.That(ex.InnerException.Message, Does.StartWith("Access denied for user")); } } @@ -763,9 +763,9 @@ public void AllowPublicKeyRetrievalForCachingSha2PasswordPlugin() { Exception ex = Assert.Throws(() => connection.Open()); if (serverCompiledUsingOpenSsl) - Assert.AreEqual("Retrieval of the RSA public key is not enabled for insecure connections.", ex.Message); + Assert.That(ex.Message, Is.EqualTo("Retrieval of the RSA public key is not enabled for insecure connections.")); else - StringAssert.StartsWith("Authentication to host", ex.Message); + Assert.That(ex.Message, Does.StartWith("Authentication to host")); } if (serverCompiledUsingOpenSsl) @@ -813,7 +813,7 @@ public void CachingSha2AuthFailsAfterFlushPrivileges() using (MySqlConnection connection = new MySqlConnection(settings.ConnectionString)) { connection.Open(); - Assert.True(connection.State == ConnectionState.Open); + Assert.That(connection.State == ConnectionState.Open, Is.True); connection.Close(); } @@ -822,7 +822,7 @@ public void CachingSha2AuthFailsAfterFlushPrivileges() using (MySqlConnection connection = new MySqlConnection(settings.ConnectionString)) { connection.Open(); - Assert.True(connection.State == ConnectionState.Open); + Assert.That(connection.State == ConnectionState.Open, Is.True); connection.Close(); } @@ -834,9 +834,9 @@ public void CachingSha2AuthFailsAfterFlushPrivileges() { ex = Assert.Throws(() => connection.Open()); if (serverCompiledUsingOpenSsl) - Assert.AreEqual("Retrieval of the RSA public key is not enabled for insecure connections.", ex.Message); + Assert.That(ex.Message, Is.EqualTo("Retrieval of the RSA public key is not enabled for insecure connections.")); else - StringAssert.StartsWith("Authentication to host", ex.Message); + Assert.That(ex.Message, Does.StartWith("Authentication to host")); } settings.AllowPublicKeyRetrieval = true; @@ -846,14 +846,14 @@ public void CachingSha2AuthFailsAfterFlushPrivileges() if (serverCompiledUsingOpenSsl) { connection.Open(); - Assert.True(connection.State == ConnectionState.Open); + Assert.That(connection.State == ConnectionState.Open); connection.Close(); } // Fail since AllowPublicKeyRetrieval is ignored in gpl servers. else { ex = Assert.Throws(() => connection.Open()); - StringAssert.StartsWith("Authentication to host", ex.Message); + Assert.That(ex.Message, Does.StartWith("Authentication to host")); } } } @@ -889,7 +889,7 @@ public void CheckAllowPublicKeyRetrievalOptionIsAvailable() using (MySqlConnection connection = new MySqlConnection(connectionString)) { connection.Open(); - Assert.True(connection.Settings.AllowPublicKeyRetrieval); + Assert.That(connection.Settings.AllowPublicKeyRetrieval, Is.True); connection.Close(); } } @@ -920,14 +920,14 @@ public void ConnectUsingClearPasswordPlugin() using (MySqlConnection connection = new MySqlConnection(settings.ConnectionString)) { connection.Open(); - Assert.AreEqual(ConnectionState.Open, connection.connectionState); + Assert.That(connection.connectionState, Is.EqualTo(ConnectionState.Open)); var sql = string.Format("select user,plugin from mysql.user where user like '{0}'", settings.UserID); MySqlCommand command = new MySqlCommand(sql, connection); using (MySqlDataReader reader = command.ExecuteReader()) { - Assert.True(reader.Read()); - StringAssert.AreEqualIgnoringCase("test1@MYSQL.LOCAL", reader.GetString(0)); - StringAssert.AreEqualIgnoringCase("authentication_ldap_simple", reader.GetString(1)); + Assert.That(reader.Read(), Is.True); + Assert.That(reader.GetString(0), Is.EqualTo("test1@MYSQL.LOCAL").IgnoreCase); + Assert.That(reader.GetString(1), Is.EqualTo("authentication_ldap_simple").IgnoreCase); } //test the new user can execute sql statements FR1_1 sql = "create table testinserts( id int, name varchar(50),age int)"; @@ -942,13 +942,13 @@ public void ConnectUsingClearPasswordPlugin() sql = "select count(*) from testinserts"; command = new MySqlCommand(sql, connection); var counter = command.ExecuteScalar(); - Assert.AreEqual(4, counter); + Assert.That(counter, Is.EqualTo(4)); //check ssl command = new MySqlCommand("SHOW SESSION STATUS LIKE 'Ssl_version';", connection); using (MySqlDataReader reader = command.ExecuteReader()) { - Assert.True(reader.Read()); - StringAssert.StartsWith("TLSv1", reader.GetString(1)); + Assert.That(reader.Read(), Is.True); + Assert.That(reader.GetString(1), Does.StartWith("TLSv1")); } } @@ -960,13 +960,13 @@ public void ConnectUsingClearPasswordPlugin() using (MySqlConnection conn = new MySqlConnection(unixConnectionString)) { conn.Open(); - Assert.AreEqual(ConnectionState.Open, conn.State); + Assert.That(conn.State, Is.EqualTo(ConnectionState.Open)); } using (MySqlConnection connection = new MySqlConnection(unixConnectionString + "sslmode=none")) { connection.Open(); - Assert.AreEqual(ConnectionState.Open, connection.State); + Assert.That(connection.State, Is.EqualTo(ConnectionState.Open)); } } @@ -981,7 +981,7 @@ public void ConnectUsingClearPasswordPlugin() using (MySqlConnection connection = new MySqlConnection(settings.ConnectionString)) { Exception ex = Assert.Throws(() => connection.Open()); - StringAssert.StartsWith("Access denied for user", ex.InnerException.Message); + Assert.That(ex.InnerException.Message, Does.StartWith("Access denied for user")); } // Test connection for INVALID user in LDAP server, expected result FAIL @@ -995,7 +995,7 @@ public void ConnectUsingClearPasswordPlugin() using (MySqlConnection connection = new MySqlConnection(settings.ConnectionString)) { Exception ex = Assert.Throws(() => connection.Open()); - StringAssert.StartsWith("Access denied for user", ex.InnerException.Message); + Assert.That(ex.InnerException.Message, Does.StartWith("Access denied for user")); } // Test connection for VALID user in LDAP server with SSLMode=none, expected result FAIL @@ -1010,7 +1010,7 @@ public void ConnectUsingClearPasswordPlugin() using (MySqlConnection connection = new MySqlConnection(settings.ConnectionString)) { Exception ex = Assert.Throws(() => connection.Open()); - StringAssert.Contains("Clear-password authentication is not supported over insecure channels", ex.Message); + Assert.That(ex.Message, Does.Contain("Clear-password authentication is not supported over insecure channels")); } // Test connection for VALID user in LDAP server with different SSLMode values, expected result pass @@ -1030,7 +1030,7 @@ public void ConnectUsingClearPasswordPlugin() using (MySqlConnection connection = new MySqlConnection(settings.ConnectionString)) { connection.Open(); - Assert.AreEqual(ConnectionState.Open, connection.State); + Assert.That(connection.State, Is.EqualTo(ConnectionState.Open)); connection.Close(); } @@ -1039,7 +1039,7 @@ public void ConnectUsingClearPasswordPlugin() using (MySqlConnection connection = new MySqlConnection(settings.ConnectionString)) { connection.Open(); - Assert.AreEqual(ConnectionState.Open, connection.State); + Assert.That(connection.State, Is.EqualTo(ConnectionState.Open)); connection.Close(); } @@ -1050,7 +1050,7 @@ public void ConnectUsingClearPasswordPlugin() using (MySqlConnection connection = new MySqlConnection(settings.ConnectionString)) { connection.Open(); - Assert.AreEqual(ConnectionState.Open, connection.State); + Assert.That(connection.State, Is.EqualTo(ConnectionState.Open)); connection.Close(); } @@ -1095,11 +1095,11 @@ public void ConnectUsingMySqlSASLPluginSCRAMSHA(string userName, string password MySqlCommand command = new MySqlCommand($"SELECT `User`, `plugin` FROM `mysql`.`user` WHERE `User` = '{userName}';", connection); using (MySqlDataReader reader = command.ExecuteReader()) { - StringAssert.AreEqualIgnoringCase(mechanism, MySqlSASLPlugin.scramMechanism.MechanismName); - Assert.AreEqual(ScramBase.AuthState.VALIDATE, MySqlSASLPlugin.scramMechanism._state); - Assert.True(reader.Read()); - StringAssert.AreEqualIgnoringCase(userName, reader.GetString(0)); - StringAssert.AreEqualIgnoringCase(plugin, reader.GetString(1)); + Assert.That(MySqlSASLPlugin.scramMechanism.MechanismName, Is.EqualTo(mechanism).IgnoreCase); + Assert.That(MySqlSASLPlugin.scramMechanism._state, Is.EqualTo(ScramBase.AuthState.VALIDATE)); + Assert.That(reader.Read(), Is.True); + Assert.That(reader.GetString(0), Is.EqualTo(userName).IgnoreCase); + Assert.That(reader.GetString(1), Is.EqualTo(plugin).IgnoreCase); } } else @@ -1118,19 +1118,19 @@ public void AssertScramSha1() ScramSha1Mechanism scramSha1 = new ScramSha1Mechanism("user", "pencil", Host); scramSha1._cnonce = fixedNonce; - Assert.AreEqual(ScramBase.AuthState.INITIAL, scramSha1._state); + Assert.That(scramSha1._state, Is.EqualTo(ScramBase.AuthState.INITIAL)); var challenge = Encoding.UTF8.GetString(scramSha1.Challenge(null)); - Assert.AreEqual("n,a=user,n=user,r=" + fixedNonce, challenge); - Assert.AreEqual(ScramBase.AuthState.FINAL, scramSha1._state); + Assert.That(challenge, Is.EqualTo("n,a=user,n=user,r=" + fixedNonce)); + Assert.That(scramSha1._state, Is.EqualTo(ScramBase.AuthState.FINAL)); response = Encoding.UTF8.GetBytes(challenge1); challenge = Encoding.UTF8.GetString(scramSha1.Challenge(response)); - Assert.AreEqual(expected, challenge); - Assert.AreEqual(ScramBase.AuthState.VALIDATE, scramSha1._state); + Assert.That(challenge, Is.EqualTo(expected)); + Assert.That(scramSha1._state, Is.EqualTo(ScramBase.AuthState.VALIDATE)); response = Encoding.UTF8.GetBytes(challenge2); - Assert.IsNull(scramSha1.Challenge(response)); + Assert.That(scramSha1.Challenge(response), Is.Null); } [Test] @@ -1144,19 +1144,19 @@ public void AssertScramSha256() ScramSha256Mechanism scramSha256 = new ScramSha256Mechanism("user", "pencil", Host); scramSha256._cnonce = fixedNonce; - Assert.AreEqual(ScramBase.AuthState.INITIAL, scramSha256._state); + Assert.That(scramSha256._state, Is.EqualTo(ScramBase.AuthState.INITIAL)); var challenge = Encoding.UTF8.GetString(scramSha256.Challenge(null)); - Assert.AreEqual("n,a=user,n=user,r=" + fixedNonce, challenge); - Assert.AreEqual(ScramBase.AuthState.FINAL, scramSha256._state); + Assert.That(challenge, Is.EqualTo("n,a=user,n=user,r=" + fixedNonce)); + Assert.That(scramSha256._state, Is.EqualTo(ScramBase.AuthState.FINAL)); response = Encoding.UTF8.GetBytes(challenge1); challenge = Encoding.UTF8.GetString(scramSha256.Challenge(response)); - Assert.AreEqual(expected, challenge); - Assert.AreEqual(ScramBase.AuthState.VALIDATE, scramSha256._state); + Assert.That(challenge, Is.EqualTo(expected)); + Assert.That(scramSha256._state, Is.EqualTo(ScramBase.AuthState.VALIDATE)); response = Encoding.UTF8.GetBytes(challenge2); - Assert.IsNull(scramSha256.Challenge(response)); + Assert.That(scramSha256.Challenge(response), Is.Null); } #endregion @@ -1192,9 +1192,9 @@ public void ConnectUsingMySqlSASLPluginGSSAPI(string userName, string password, MySqlCommand command = new MySqlCommand($"SELECT user();", connection); using (MySqlDataReader reader = command.ExecuteReader()) { - StringAssert.AreEqualIgnoringCase("GSSAPI", MySqlSASLPlugin.gssapiMechanism.MechanismName); - Assert.True(reader.Read()); - StringAssert.Contains(userName, reader.GetString(0)); + Assert.That(MySqlSASLPlugin.gssapiMechanism.MechanismName, Is.EqualTo("GSSAPI").IgnoreCase); + Assert.That(reader.Read(), Is.True); + Assert.That(reader.GetString(0), Does.Contain(userName)); } } else @@ -1207,27 +1207,27 @@ public void ConnectUsingMySqlSASLPluginGSSAPI(string userName, string password, public void AssertSaslPrep() { // Valid String - Assert.AreEqual("my,0TEXT", MySqlSASLPlugin.SaslPrep("my,0TEXT")); - Assert.AreEqual("my,0 TEXT", MySqlSASLPlugin.SaslPrep("my,0 TEXT")); + Assert.That(MySqlSASLPlugin.SaslPrep("my,0TEXT"), Is.EqualTo("my,0TEXT")); + Assert.That(MySqlSASLPlugin.SaslPrep("my,0 TEXT"), Is.EqualTo("my,0 TEXT")); // Queries for matching strings MAY contain unassigned code points. - Assert.AreEqual("\u0888my,0TEXT", MySqlSASLPlugin.SaslPrep("\u0888my,0TEXT")); - Assert.AreEqual("my,0\u0890TEXT", MySqlSASLPlugin.SaslPrep("my,0\u0890TEXT")); - Assert.AreEqual("my,0TEXT\u089F", MySqlSASLPlugin.SaslPrep("my,0TEXT\u089F")); + Assert.That(MySqlSASLPlugin.SaslPrep("\u0888my,0TEXT"), Is.EqualTo("\u0888my,0TEXT")); + Assert.That(MySqlSASLPlugin.SaslPrep("my,0\u0890TEXT"), Is.EqualTo("my,0\u0890TEXT")); + Assert.That(MySqlSASLPlugin.SaslPrep("my,0TEXT\u089F"), Is.EqualTo("my,0TEXT\u089F")); // Mapping: non-ASCII space characters. - Assert.AreEqual("my,0 TEXT", MySqlSASLPlugin.SaslPrep("my,0\u1680TEXT")); - Assert.AreEqual("my,0 TEXT", MySqlSASLPlugin.SaslPrep("my,0\u200BTEXT")); - Assert.AreEqual(" my,0 TEXT ", MySqlSASLPlugin.SaslPrep("\u00A0my,0\u2000TEXT\u3000")); + Assert.That(MySqlSASLPlugin.SaslPrep("my,0\u1680TEXT"), Is.EqualTo("my,0 TEXT")); + Assert.That(MySqlSASLPlugin.SaslPrep("my,0\u200BTEXT"), Is.EqualTo("my,0 TEXT")); + Assert.That(MySqlSASLPlugin.SaslPrep("\u00A0my,0\u2000TEXT\u3000"), Is.EqualTo(" my,0 TEXT ")); // Mapping: the "commonly mapped to nothing" characters. - Assert.AreEqual("my,0TEXT", MySqlSASLPlugin.SaslPrep("my,0\u00ADTEXT")); - Assert.AreEqual("my,0TEXT", MySqlSASLPlugin.SaslPrep("my,0\uFE0ATEXT")); - Assert.AreEqual("my,0TEXT", MySqlSASLPlugin.SaslPrep("\u00ADmy,0\u1806TE\uFE0FXT\uFEFF")); + Assert.That(MySqlSASLPlugin.SaslPrep("my,0\u00ADTEXT"), Is.EqualTo("my,0TEXT")); + Assert.That(MySqlSASLPlugin.SaslPrep("my,0\uFE0ATEXT"), Is.EqualTo("my,0TEXT")); + Assert.That(MySqlSASLPlugin.SaslPrep("\u00ADmy,0\u1806TE\uFE0FXT\uFEFF"), Is.EqualTo("my,0TEXT")); // KC Normalization. - Assert.AreEqual("my,0 fi TEXT", MySqlSASLPlugin.SaslPrep("my,0 \uFB01 TEXT")); - Assert.AreEqual("my,0 fi TEXT", MySqlSASLPlugin.SaslPrep("my,0 \uFB01 TEXT")); + Assert.That(MySqlSASLPlugin.SaslPrep("my,0 \uFB01 TEXT"), Is.EqualTo("my,0 fi TEXT")); + Assert.That(MySqlSASLPlugin.SaslPrep("my,0 \uFB01 TEXT"), Is.EqualTo("my,0 fi TEXT")); // Prohibited Output: ASCII control characters. Assert.Throws(() => MySqlSASLPlugin.SaslPrep("\u007Fmy,0TEXT")); @@ -1381,11 +1381,11 @@ private void TestKerberosConnection(bool shouldPass, string username, MySqlConne MySqlCommand command = new MySqlCommand($"SELECT user();", conn); using (MySqlDataReader reader = command.ExecuteReader()) { - Assert.True(reader.Read()); - StringAssert.Contains(username, reader.GetString(0)); + Assert.That(reader.Read(), Is.True); + Assert.That(reader.GetString(0), Does.Contain(username)); } - Assert.True(conn.Settings.KerberosAuthMode == mode); + Assert.That(conn.Settings.KerberosAuthMode == mode); } else Assert.Throws(() => conn.Open()); @@ -1425,9 +1425,9 @@ public void ConnectUsingOciIamAuthentication(string userName, string configFileP MySqlCommand command = new MySqlCommand($"SELECT user();", conn); using (MySqlDataReader reader = command.ExecuteReader()) { - Assert.True(reader.Read()); + Assert.That(reader.Read(), Is.True); userName = string.IsNullOrEmpty(userName) ? Environment.UserName : userName; - StringAssert.Contains(userName, reader.GetString(0)); + Assert.That(reader.GetString(0), Does.Contain(userName)); } } } @@ -1438,7 +1438,7 @@ public void NonExistingKeyFile() OciAuthenticationPlugin plugin = new OciAuthenticationPlugin(); string keyFileInvalidPath = "C:\\invalid\\Path"; string exMsg = Assert.Throws(() => OciAuthenticationPlugin.SignData(new byte[0], keyFileInvalidPath)).Message; - StringAssert.AreEqualIgnoringCase(Resources.OciKeyFileDoesNotExists, exMsg); + Assert.That(exMsg, Is.EqualTo(Resources.OciKeyFileDoesNotExists).IgnoreCase); } public struct Profiles @@ -1486,13 +1486,13 @@ public void ValidatesEntries(Profiles profiles) if (profiles.missingEntry) { exMsg = Assert.Throws(() => plugin.GetOciConfigValues(profiles.profiles, out string keyFile, out string fingerprint, out string securityTokenFilePath)).Message; - StringAssert.AreEqualIgnoringCase(Resources.OciEntryNotFound, exMsg); + Assert.That(exMsg, Is.EqualTo(Resources.OciEntryNotFound).IgnoreCase); } else { plugin.GetOciConfigValues(profiles.profiles, out string keyFile, out string fingerprint, out string securityTokenFilePath); exMsg = Assert.Throws(() => OciAuthenticationPlugin.SignData(new byte[0], keyFile)).Message; - StringAssert.AreEqualIgnoringCase(Resources.OciInvalidKeyFile, exMsg); + Assert.That(exMsg, Is.EqualTo(Resources.OciInvalidKeyFile).IgnoreCase); } } @@ -1509,9 +1509,9 @@ public void OtherThanDefaultProfile() plugin._ociConfigProfile = "TEST"; plugin.GetOciConfigValues(profiles, out string keyFilePath, out string fingerprint, out string securityTokenFilePath); - StringAssert.AreEqualIgnoringCase("keyFilePath", keyFilePath); - StringAssert.AreEqualIgnoringCase("66:55:44:33:22:11", fingerprint); - StringAssert.AreEqualIgnoringCase("securityTokenFilePath", securityTokenFilePath); + Assert.That(keyFilePath, Is.EqualTo("keyFilePath").IgnoreCase); + Assert.That(fingerprint, Is.EqualTo("66:55:44:33:22:11").IgnoreCase); + Assert.That(securityTokenFilePath, Is.EqualTo("securityTokenFilePath").IgnoreCase); } [DatapointSource] @@ -1541,7 +1541,7 @@ public void NonExistingConfigFile(string invalidPath) using (var conn = new MySqlConnection(connStringBuilder.ConnectionString)) { string exMsg = Assert.Throws(() => conn.Open()).Message; - StringAssert.AreEqualIgnoringCase(Resources.OciConfigFileNotFound, exMsg); + Assert.That(exMsg, Is.EqualTo(Resources.OciConfigFileNotFound).IgnoreCase); } } @@ -1551,7 +1551,7 @@ public void OciSdkNotInstalled() OciAuthenticationPlugin plugin = new OciAuthenticationPlugin(); string exMsg = Assert.Throws(() => plugin.AuthenticateAsync(false, false).GetAwaiter().GetResult()).Message; - StringAssert.AreEqualIgnoringCase(Resources.OciSDKNotFound, exMsg); + Assert.That(exMsg, Is.EqualTo(Resources.OciSDKNotFound).IgnoreCase); } [Test] @@ -1574,7 +1574,7 @@ public void NonExistingConfigProfile() using (var conn = new MySqlConnection(connStringBuilder.ConnectionString)) { string exMsg = Assert.Throws(() => conn.Open()).Message; - StringAssert.AreEqualIgnoringCase(Resources.OciConfigProfileNotFound, exMsg); + Assert.That(exMsg, Is.EqualTo(Resources.OciConfigProfileNotFound).IgnoreCase); } } @@ -1610,7 +1610,7 @@ public void ConnectUsing1FAuth() using var conn = new MySqlConnection(connStringBuilder.ConnectionString); conn.Open(); - Assert.AreEqual(ConnectionState.Open, conn.State); + Assert.That(conn.State, Is.EqualTo(ConnectionState.Open)); } [TestCase("user_2f", "password1", "password2", true)] @@ -1643,7 +1643,7 @@ public void ConnectUsing2FAuth(string user, string pwd, string pwd2, bool should else { conn.Open(); - Assert.AreEqual(ConnectionState.Open, conn.State); + Assert.That(conn.State, Is.EqualTo(ConnectionState.Open)); } } @@ -1677,7 +1677,7 @@ public void ConnectUsing3FAuth(string user, string pwd, string pwd2, string pwd3 else { conn.Open(); - Assert.AreEqual(ConnectionState.Open, conn.State); + Assert.That(conn.State, Is.EqualTo(ConnectionState.Open)); } } #endregion @@ -1709,7 +1709,7 @@ public void WebAuthnAuthenticationPasswordless() using var conn = new MySqlConnection(connStringBuilder.ConnectionString); conn.WebAuthnActionRequested += Conn_WebAuthnActionRequested; conn.Open(); - Assert.AreEqual(ConnectionState.Open, conn.State); + Assert.That(conn.State, Is.EqualTo(ConnectionState.Open)); } [Test] @@ -1735,7 +1735,7 @@ public void WebAuthnAuthentication2F() using var conn = new MySqlConnection(connStringBuilder.ConnectionString); conn.WebAuthnActionRequested += Conn_WebAuthnActionRequested; conn.Open(); - Assert.AreEqual(ConnectionState.Open, conn.State); + Assert.That(conn.State, Is.EqualTo(ConnectionState.Open)); } [Test] @@ -1762,7 +1762,7 @@ public void WebAuthnAuthentication3F() using var conn = new MySqlConnection(connStringBuilder.ConnectionString); conn.WebAuthnActionRequested += Conn_WebAuthnActionRequested; conn.Open(); - Assert.AreEqual(ConnectionState.Open, conn.State); + Assert.That(conn.State, Is.EqualTo(ConnectionState.Open)); } [Test] diff --git a/MySQL.Data/tests/MySql.Data.Tests/BlobTests.cs b/MySQL.Data/tests/MySql.Data.Tests/BlobTests.cs index 14f7e05be..a69bc6902 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/BlobTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/BlobTests.cs @@ -49,11 +49,11 @@ public void InsertNullBinary() cmd.CommandText = "SELECT * FROM Test"; using (MySqlDataReader reader = cmd.ExecuteReader()) { - Assert.True(reader.HasRows == true, "Checking HasRows"); + Assert.That(reader.HasRows, Is.EqualTo(true), "Checking HasRows"); reader.Read(); var value = reader.GetValue(1) as string; - Assert.True(value == null); + Assert.That(value, Is.EqualTo(null)); } } @@ -76,23 +76,23 @@ public void InsertBinary() cmd.Parameters[1].Value = dataIn2; rows += cmd.ExecuteNonQuery(); - Assert.True(rows == 2, "Checking insert rowcount"); + Assert.That(rows == 2, "Checking insert rowcount"); cmd.CommandText = "SELECT * FROM InsertBinary"; using (MySqlDataReader reader = cmd.ExecuteReader()) { - Assert.True(reader.HasRows == true, "Checking HasRows"); + Assert.That(reader.HasRows, Is.EqualTo(true), "Checking HasRows"); reader.Read(); byte[] dataOut = new byte[lenIn]; long lenOut = reader.GetBytes(1, 0, dataOut, 0, lenIn); - Assert.True(lenIn == lenOut, "Checking length of binary data (row 1)"); + Assert.That(lenIn, Is.EqualTo(lenOut), "Checking length of binary data (row 1)"); // now see if the buffer is intact for (int x = 0; x < dataIn.Length; x++) - Assert.True(dataIn[x] == dataOut[x], "Checking first binary array at " + x); + Assert.That(dataIn[x], Is.EqualTo(dataOut[x]), "Checking first binary array at " + x); // now we test chunking int pos = 0; @@ -106,15 +106,15 @@ public void InsertBinary() } // now see if the buffer is intact for (int x = 0; x < dataIn.Length; x++) - Assert.True(dataIn[x] == dataOut[x], "Checking first binary array at " + x); + Assert.That(dataIn[x], Is.EqualTo(dataOut[x]), "Checking first binary array at " + x); reader.Read(); lenOut = reader.GetBytes(1, 0, dataOut, 0, lenIn); - Assert.True(lenIn == lenOut, "Checking length of binary data (row 2)"); + Assert.That(lenIn == lenOut, "Checking length of binary data (row 2)"); // now see if the buffer is intact for (int x = 0; x < dataIn2.Length; x++) - Assert.True(dataIn2[x] == dataOut[x], "Checking second binary array at " + x); + Assert.That(dataIn2[x], Is.EqualTo(dataOut[x]), "Checking second binary array at " + x); } } @@ -167,7 +167,7 @@ private void InternalGetChars(bool prepare) } // now see if the buffer is intact for (int x = 0; x < data.Length; x++) - Assert.True(data[x] == dataOut[x], "Checking first text array at " + x); + Assert.That(data[x], Is.EqualTo(dataOut[x]), "Checking first text array at " + x); } } @@ -198,7 +198,7 @@ private void InternalInsertText(bool prepare) cmd.Parameters.Add(new MySqlParameter("?b1", "This is my blob data")); if (prepare) cmd.Prepare(); int rows = cmd.ExecuteNonQuery(); - Assert.True(rows == 1, "Checking insert rowcount"); + Assert.That(rows, Is.EqualTo(1), "Checking insert rowcount"); cmd.CommandText = "INSERT INTO InsertText VALUES(2, ?b1, ?t1)"; cmd.Parameters.Clear(); @@ -208,22 +208,22 @@ private void InternalInsertText(bool prepare) cmd.Parameters.AddWithValue("?b1", str); rows = cmd.ExecuteNonQuery(); - Assert.True(rows == 1, "Checking insert rowcount"); + Assert.That(rows, Is.EqualTo(1), "Checking insert rowcount"); cmd.CommandText = "SELECT * FROM InsertText"; if (prepare) cmd.Prepare(); using (MySqlDataReader reader = cmd.ExecuteReader()) { - Assert.True(reader.HasRows, "Checking HasRows"); + Assert.That(reader.HasRows, "Checking HasRows"); - Assert.True(reader.Read()); + Assert.That(reader.Read()); string s = reader.GetString(2); - Assert.True(s.Length == 1024, "Checking length returned "); - Assert.True(s.Substring(0, 9) == "ABCDEFGHI", "Checking first few chars of string"); + Assert.That(s.Length, Is.EqualTo(1024), "Checking length returned "); + Assert.That(s.Substring(0, 9), Is.EqualTo("ABCDEFGHI"), "Checking first few chars of string"); - Assert.True(reader.Read()); - Assert.AreEqual(DBNull.Value, reader.GetValue(2)); + Assert.That(reader.Read()); + Assert.That(reader.GetValue(2), Is.EqualTo(DBNull.Value)); } } @@ -240,8 +240,8 @@ public void GetCharsOnLongTextColumn() { reader.Read(); reader.GetChars(1, 0, buf, 0, 2); - Assert.AreEqual('T', buf[0]); - Assert.AreEqual('e', buf[1]); + Assert.That(buf[0], Is.EqualTo('T')); + Assert.That(buf[1], Is.EqualTo('e')); } } @@ -271,13 +271,13 @@ public void MediumIntBlobSize() { reader.Read(); uint actualsize = reader.GetUInt32(1); - Assert.AreEqual((uint)image.Length, actualsize); + Assert.That(actualsize, Is.EqualTo((uint)image.Length)); uint size = reader.GetUInt32(0); byte[] outImage = new byte[size]; long len = reader.GetBytes(reader.GetOrdinal("image"), 0, outImage, 0, (int)size); - Assert.AreEqual((uint)image.Length, size); - Assert.AreEqual((uint)image.Length, len); + Assert.That(size, Is.EqualTo((uint)image.Length)); + Assert.That(len, Is.EqualTo((uint)image.Length)); } } @@ -297,7 +297,7 @@ public void BlobBiggerThanMaxPacket() cmd.Parameters.AddWithValue("?image", image); Exception ex = Assert.Throws(() => cmd.ExecuteNonQuery()); - Assert.AreEqual(ex.Message, "Packets larger than max_allowed_packet are not allowed."); + Assert.That(ex.Message, Is.EqualTo("Packets larger than max_allowed_packet are not allowed.")); } } @@ -315,7 +315,7 @@ public void UpdateDataSet() MySqlCommandBuilder cb = new MySqlCommandBuilder(da); string s = (string)dt.Rows[0][2]; - Assert.AreEqual("Text field", s); + Assert.That(s, Is.EqualTo("Text field")); byte[] inBuf = Utils.CreateBlob(512); dt.Rows[0].BeginEdit(); @@ -330,10 +330,10 @@ public void UpdateDataSet() cb.Dispose(); byte[] outBuf = (byte[])dt.Rows[0]["blob1"]; - Assert.True(inBuf.Length == outBuf.Length, "checking length of updated buffer"); + Assert.That(inBuf.Length, Is.EqualTo(outBuf.Length), "checking length of updated buffer"); for (int y = 0; y < inBuf.Length; y++) - Assert.True(inBuf[y] == outBuf[y], "checking array data"); + Assert.That(inBuf[y] == outBuf[y], Is.True, "checking array data"); } } } diff --git a/MySQL.Data/tests/MySql.Data.Tests/CharSetTests.cs b/MySQL.Data/tests/MySql.Data.Tests/CharSetTests.cs index e527c3e01..698c274ca 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/CharSetTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/CharSetTests.cs @@ -64,9 +64,9 @@ public void VarBinary() MySqlCommand cmd = new MySqlCommand("SELECT * FROM Test", Connection); using (MySqlDataReader reader = cmd.ExecuteReader()) { - Assert.True(reader.Read()); + Assert.That(reader.Read()); object o = reader.GetValue(1); - Assert.True(o is string); + Assert.That(o is string); } } @@ -82,7 +82,7 @@ public void Latin1Connection() MySqlCommand cmd = new MySqlCommand("SELECT id FROM Test WHERE name LIKE 'Test'", conn); object id = cmd.ExecuteScalar(); - Assert.AreEqual(1, id); + Assert.That(id, Is.EqualTo(1)); } } @@ -103,7 +103,7 @@ public void FunctionReturnsStringWithCharSet() using (MySqlDataReader reader = cmd.ExecuteReader()) { reader.Read(); - Assert.AreEqual("Trädgårdsvägen1", reader.GetString(0)); + Assert.That(reader.GetString(0), Is.EqualTo("Trädgårdsvägen1")); } } } @@ -126,7 +126,7 @@ public void Encoding() using (MySqlDataReader reader = cmd.ExecuteReader()) { reader.Read(); - Assert.AreEqual("äâáàç", reader.GetString(0)); + Assert.That(reader.GetString(0), Is.EqualTo("äâáàç")); } } } @@ -145,7 +145,7 @@ public void RespectBinaryFlags() "SELECT CONCAT('Trädgårdsvägen', 1)", c); DataTable dt = new DataTable(); da.Fill(dt); - Assert.True(dt.Rows[0][0] is byte[]); + Assert.That(dt.Rows[0][0] is byte[]); } connStr = Connection.ConnectionString + ";respect binary flags=false"; using (MySqlConnection c = new MySqlConnection(connStr)) @@ -156,8 +156,8 @@ public void RespectBinaryFlags() "SELECT CONCAT('Trädgårdsvägen', 1)", c); DataTable dt = new DataTable(); da.Fill(dt); - Assert.True(dt.Rows[0][0] is string); - Assert.AreEqual("Trädgårdsvägen1", dt.Rows[0][0]); + Assert.That(dt.Rows[0][0] is string); + Assert.That(dt.Rows[0][0], Is.EqualTo("Trädgårdsvägen1")); } } @@ -183,7 +183,7 @@ public void RussianErrorMessagesShowCorrectly() } catch (MySqlException e) { - Assert.AreEqual(expected, e.Message); + Assert.That(e.Message, Is.EqualTo(expected)); } } @@ -224,10 +224,10 @@ public void UsingUtf16() { for (int i = 0; i < reader.FieldCount; i++) { - Assert.True(j == reader.GetInt32(0)); - Assert.True(firstNames[j] == reader.GetString(1)); - Assert.True(lastNames[j] == reader.GetString(2)); - Assert.True(lastUpdates[j] == reader.GetDateTime(3)); + Assert.That(j, Is.EqualTo(reader.GetInt32(0))); + Assert.That(firstNames[j], Is.EqualTo(reader.GetString(1))); + Assert.That(lastNames[j], Is.EqualTo(reader.GetString(2))); + Assert.That(lastUpdates[j], Is.EqualTo(reader.GetDateTime(3))); } j++; } @@ -269,10 +269,10 @@ public void UsingUtf32() { for (int i = 0; i < reader.FieldCount; i++) { - Assert.True(j == reader.GetInt32(0)); - Assert.True(firstNames[j] == reader.GetString(1)); - Assert.True(lastNames[j] == reader.GetString(2)); - Assert.True(lastUpdates[j] == reader.GetDateTime(3)); + Assert.That(j, Is.EqualTo(reader.GetInt32(0))); + Assert.That(firstNames[j], Is.EqualTo(reader.GetString(1))); + Assert.That(lastNames[j], Is.EqualTo(reader.GetString(2))); + Assert.That(lastUpdates[j], Is.EqualTo(reader.GetDateTime(3))); } j++; } @@ -306,9 +306,9 @@ public void CanInsertChineseCharacterSetGB18030() while (reader.Read()) { if (reader.GetUInt32(0) == 1) - Assert.AreEqual("㭋玤䂜蚌", reader.GetString(1)); + Assert.That(reader.GetString(1), Is.EqualTo("㭋玤䂜蚌")); if (reader.GetUInt32(0) == 2) - Assert.AreEqual("念奴娇·赤壁怀古 ·苏东坡", reader.GetString(1)); + Assert.That(reader.GetString(1), Is.EqualTo("念奴娇·赤壁怀古 ·苏东坡")); } } } @@ -343,7 +343,7 @@ public void CanCreateDbUsingChineseCharacterSetGB18030() using (MySqlConnection conn = new MySqlConnection(rootSb.ConnectionString)) { conn.Open(); - Assert.AreEqual(database, conn.Database); + Assert.That(conn.Database, Is.EqualTo(database)); } } finally @@ -366,7 +366,7 @@ public void UTF16LETest() { while (reader.Read()) { - Assert.AreEqual("瑵ㅦ氶⁥整瑳", reader[0].ToString()); + Assert.That(reader[0].ToString(), Is.EqualTo("瑵ㅦ氶⁥整瑳")); } } } @@ -382,7 +382,7 @@ public void CP932() connection.Open(); MySqlCommand cmd = new MySqlCommand("SELECT '涯割晦叶角'", connection); string s = (string)cmd.ExecuteScalar(); - Assert.AreEqual("涯割晦叶角", s); + Assert.That(s, Is.EqualTo("涯割晦叶角")); } } @@ -428,7 +428,7 @@ public void ExtendedCharsetOnConnection() using (MySqlConnection conn = new MySqlConnection(sb.ToString())) { conn.Open(); - Assert.AreEqual(database, conn.Database); + Assert.That(conn.Database, Is.EqualTo(database)); } } finally @@ -453,9 +453,9 @@ public void DefaultCharSet() reader.Read(); if (Connection.driver.Version.isAtLeast(8, 0, 1)) - Assert.AreEqual("utf8mb4", reader.GetString("Value")); + Assert.That(reader.GetString("Value"), Is.EqualTo("utf8mb4")); else - Assert.AreEqual("latin1", reader.GetString("Value")); + Assert.That(reader.GetString("Value"), Is.EqualTo("latin1")); } } @@ -470,21 +470,21 @@ public void CharacterVariablesByDefault() MySqlCommand cmd = rootConnection.CreateCommand(); cmd.CommandText = "SELECT @@character_set_server"; string characterSet = cmd.ExecuteScalar().ToString(); - Assert.False(string.IsNullOrWhiteSpace(characterSet)); + Assert.That(string.IsNullOrWhiteSpace(characterSet), Is.False); cmd.CommandText = "SHOW VARIABLES LIKE 'character_set_c%'"; using (MySqlDataReader dr = cmd.ExecuteReader()) { - Assert.True(dr.HasRows); + Assert.That(dr.HasRows); while (dr.Read()) { switch (dr.GetString(0).ToLowerInvariant()) { case "character_set_client": - Assert.AreEqual(characterSet, dr.GetString(1)); + Assert.That(dr.GetString(1), Is.EqualTo(characterSet)); break; case "character_set_connection": - Assert.AreEqual(characterSet, dr.GetString(1)); + Assert.That(dr.GetString(1), Is.EqualTo(characterSet)); break; default: throw new InvalidOperationException(string.Format("Variable '{0}' not expected.", dr.GetString(0))); @@ -493,7 +493,7 @@ public void CharacterVariablesByDefault() } cmd.CommandText = "SELECT @@character_set_results"; - Assert.AreEqual(DBNull.Value, cmd.ExecuteScalar()); + Assert.That(cmd.ExecuteScalar(), Is.EqualTo(DBNull.Value)); } } @@ -516,7 +516,7 @@ public void DatabaseCaseSentitive() { cmd.CommandType = CommandType.StoredProcedure; var result = cmd.ExecuteNonQuery(); - Assert.AreEqual(0, result); + Assert.That(result, Is.EqualTo(0)); } } } @@ -538,8 +538,8 @@ public void PoundSymbolInJsonColumn() { while (reader.Read()) { - StringAssert.AreEqualIgnoringCase("£", reader[0].ToString()); - StringAssert.AreEqualIgnoringCase("{\"Value\": \"£\"}", reader[1].ToString()); + Assert.That(reader[0].ToString(), Is.EqualTo("£").IgnoreCase); + Assert.That(reader[1].ToString(), Is.EqualTo("{\"Value\": \"£\"}").IgnoreCase); } } } @@ -561,26 +561,26 @@ public void CharacterVariablesByDefaultServerDefault() var cmd = rootConnection.CreateCommand(); cmd.CommandText = "SELECT @@character_set_server"; var characterSet = cmd.ExecuteScalar().ToString(); - Assert.AreEqual(false, string.IsNullOrWhiteSpace(characterSet)); + Assert.That(string.IsNullOrWhiteSpace(characterSet), Is.EqualTo(false)); cmd.CommandText = "SHOW VARIABLES LIKE 'character_set_c%'"; using (var dr = cmd.ExecuteReader()) { - Assert.AreEqual(true, dr.HasRows); + Assert.That(dr.HasRows, Is.EqualTo(true)); while (dr.Read()) switch (dr.GetString(0).ToLowerInvariant()) { case "character_set_client": - Assert.AreEqual(characterSet, dr.GetString(1)); + Assert.That(dr.GetString(1), Is.EqualTo(characterSet)); break; case "character_set_connection": - Assert.AreEqual(characterSet, dr.GetString(1)); + Assert.That(dr.GetString(1), Is.EqualTo(characterSet)); break; } } cmd.CommandText = "SELECT @@character_set_results"; - Assert.AreEqual(DBNull.Value, cmd.ExecuteScalar()); + Assert.That(cmd.ExecuteScalar(), Is.EqualTo(DBNull.Value)); } } @@ -601,20 +601,20 @@ public void CharacterVariablesByAssignedServerDefault() var cmd = rootConnection.CreateCommand(); cmd.CommandText = "SELECT @@character_set_server"; var characterSet = cmd.ExecuteScalar().ToString(); - Assert.AreEqual(false, string.IsNullOrWhiteSpace(characterSet)); + Assert.That(string.IsNullOrWhiteSpace(characterSet), Is.EqualTo(false)); cmd.CommandText = "SHOW VARIABLES LIKE 'character_set_c%'"; using (var dr = cmd.ExecuteReader()) { - Assert.AreEqual(true, dr.HasRows); + Assert.That(dr.HasRows, Is.EqualTo(true)); while (dr.Read()) switch (dr.GetString(0).ToLowerInvariant()) { case "character_set_client": - StringAssert.StartsWith(expectedCharSet, dr.GetString(1)); + Assert.That(dr.GetString(1), Does.StartWith(expectedCharSet)); break; case "character_set_connection": - StringAssert.StartsWith(expectedCharSet, dr.GetString(1)); + Assert.That(dr.GetString(1), Does.StartWith(expectedCharSet)); break; default: Assert.Fail($"Variable {dr.GetString(0)} not expected."); break; @@ -622,7 +622,7 @@ public void CharacterVariablesByAssignedServerDefault() } cmd.CommandText = "SELECT @@character_set_results"; - Assert.AreEqual(DBNull.Value, cmd.ExecuteScalar()); + Assert.That(cmd.ExecuteScalar(), Is.EqualTo(DBNull.Value)); } } diff --git a/MySQL.Data/tests/MySql.Data.Tests/CharSetUTF8Tests.cs b/MySQL.Data/tests/MySql.Data.Tests/CharSetUTF8Tests.cs index 4760e06d7..33bb95c5f 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/CharSetUTF8Tests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/CharSetUTF8Tests.cs @@ -67,7 +67,7 @@ public void UTF8BlogsTruncating() { reader.Read(); string s = reader.GetString(0); - Assert.AreEqual(szParam, s); + Assert.That(s, Is.EqualTo(szParam)); } } @@ -88,8 +88,8 @@ public void GetSchemaOnUTF8() using (MySqlDataReader reader = cmd.ExecuteReader()) { DataTable dt = reader.GetSchemaTable(); - Assert.AreEqual(40, dt.Rows[0]["ColumnSize"]); - Assert.AreEqual(20, dt.Rows[1]["ColumnSize"]); + Assert.That(dt.Rows[0]["ColumnSize"], Is.EqualTo(40)); + Assert.That(dt.Rows[1]["ColumnSize"], Is.EqualTo(20)); } } @@ -103,7 +103,7 @@ public void NonLatin1Exception() MySqlCommand cmd = new MySqlCommand("select `Numéro` from Test", Connection); var exception = Assert.Throws(() => cmd.ExecuteScalar()); - Assert.AreEqual("Unknown column 'Numéro' in 'field list'", exception.Message); + Assert.That(exception.Message, Is.EqualTo("Unknown column 'Numéro' in 'field list'")); } /// @@ -121,8 +121,8 @@ public void GetCharLengthInUTF8() DataSet ds = new DataSet(); ad.Fill(ds); ad.FillSchema(ds, SchemaType.Mapped); - Assert.AreEqual(1, ds.Tables[0].Columns["name"].MaxLength); - Assert.AreEqual(20, ds.Tables[0].Columns["longname"].MaxLength); + Assert.That(ds.Tables[0].Columns["name"].MaxLength, Is.EqualTo(1)); + Assert.That(ds.Tables[0].Columns["longname"].MaxLength, Is.EqualTo(20)); } [Test] @@ -156,10 +156,10 @@ public void BlobAsUtf8() da.Fill(dt); foreach (DataColumn col in dt.Columns) { - Assert.AreEqual(typeof(string), col.DataType); + Assert.That(col.DataType, Is.EqualTo(typeof(string))); string s = (string)dt.Rows[0][0]; byte[] b = utf8.GetBytes(s); - Assert.AreEqual(utf8_string, dt.Rows[0][col.Ordinal].ToString()); + Assert.That(dt.Rows[0][col.Ordinal].ToString(), Is.EqualTo(utf8_string)); } } @@ -174,11 +174,11 @@ public void BlobAsUtf8() foreach (DataColumn col in dt.Columns) { if (col.ColumnName.StartsWith("exclude", StringComparison.OrdinalIgnoreCase)) - Assert.AreEqual(typeof(byte[]), col.DataType); + Assert.That(col.DataType, Is.EqualTo(typeof(byte[]))); else { - Assert.AreEqual(typeof(string), col.DataType); - Assert.AreEqual(utf8_string, dt.Rows[0][col.Ordinal].ToString()); + Assert.That(col.DataType, Is.EqualTo(typeof(string))); + Assert.That(dt.Rows[0][col.Ordinal].ToString(), Is.EqualTo(utf8_string)); } } } @@ -195,11 +195,11 @@ public void BlobAsUtf8() { if (col.ColumnName.StartsWith("include", StringComparison.OrdinalIgnoreCase)) { - Assert.AreEqual(typeof(string), col.DataType); - Assert.AreEqual(utf8_string, dt.Rows[0][col.Ordinal].ToString()); + Assert.That(col.DataType, Is.EqualTo(typeof(string))); + Assert.That(dt.Rows[0][col.Ordinal].ToString(), Is.EqualTo(utf8_string)); } else - Assert.AreEqual(typeof(byte[]), col.DataType); + Assert.That(col.DataType, Is.EqualTo(typeof(byte[]))); } } } @@ -220,13 +220,13 @@ public void UTF8AsColumnNames() DataTable dt = new DataTable(); da.Fill(dt); - Assert.AreEqual("Numéro", dt.Columns[0].ColumnName); + Assert.That(dt.Columns[0].ColumnName, Is.EqualTo("Numéro")); MySqlCommand cmd = new MySqlCommand("SELECT NOW() AS 'Numéro'", c); using (MySqlDataReader reader = cmd.ExecuteReader()) { int ord = reader.GetOrdinal("Numéro"); - Assert.AreEqual(0, ord); + Assert.That(ord, Is.EqualTo(0)); } } } @@ -242,7 +242,7 @@ public void Unicode() { reader.Read(); string s1 = reader.GetString(0); - Assert.AreEqual("困巫忘否役", s1); + Assert.That(s1, Is.EqualTo("困巫忘否役")); } } @@ -279,21 +279,21 @@ public void UTF8() using (MySqlDataReader reader = cmd.ExecuteReader()) { reader.Read(); - Assert.AreEqual("ЁЄЉҖҚ", reader.GetString(1)); + Assert.That(reader.GetString(1), Is.EqualTo("ЁЄЉҖҚ")); reader.Read(); - Assert.AreEqual("兣冘凥凷冋", reader.GetString(1)); + Assert.That(reader.GetString(1), Is.EqualTo("兣冘凥凷冋")); reader.Read(); - Assert.AreEqual("困巫忘否役", reader.GetString(1)); + Assert.That(reader.GetString(1), Is.EqualTo("困巫忘否役")); reader.Read(); - Assert.AreEqual("涯割晦叶角", reader.GetString(1)); + Assert.That(reader.GetString(1), Is.EqualTo("涯割晦叶角")); reader.Read(); - Assert.AreEqual("ברחפע", reader.GetString(1)); + Assert.That(reader.GetString(1), Is.EqualTo("ברחפע")); reader.Read(); - Assert.AreEqual("ψόβΩΞ", reader.GetString(1)); + Assert.That(reader.GetString(1), Is.EqualTo("ψόβΩΞ")); reader.Read(); - Assert.AreEqual("þðüçöÝÞÐÜÇÖ", reader.GetString(1)); + Assert.That(reader.GetString(1), Is.EqualTo("þðüçöÝÞÐÜÇÖ")); reader.Read(); - Assert.AreEqual("ฅๆษ", reader.GetString(1)); + Assert.That(reader.GetString(1), Is.EqualTo("ฅๆษ")); } } @@ -334,21 +334,21 @@ public void UTF8PreparedAndUsingParameters() using (MySqlDataReader reader = cmd.ExecuteReader()) { reader.Read(); - Assert.AreEqual("ЁЄЉҖҚ", reader.GetString(0)); + Assert.That(reader.GetString(0), Is.EqualTo("ЁЄЉҖҚ")); reader.Read(); - Assert.AreEqual("兣冘凥凷冋", reader.GetString(0)); + Assert.That(reader.GetString(0), Is.EqualTo("兣冘凥凷冋")); reader.Read(); - Assert.AreEqual("困巫忘否役", reader.GetString(0)); + Assert.That(reader.GetString(0), Is.EqualTo("困巫忘否役")); reader.Read(); - Assert.AreEqual("涯割晦叶角", reader.GetString(0)); + Assert.That(reader.GetString(0), Is.EqualTo("涯割晦叶角")); reader.Read(); - Assert.AreEqual("ברחפע", reader.GetString(0)); + Assert.That(reader.GetString(0), Is.EqualTo("ברחפע")); reader.Read(); - Assert.AreEqual("ψόβΩΞ", reader.GetString(0)); + Assert.That(reader.GetString(0), Is.EqualTo("ψόβΩΞ")); reader.Read(); - Assert.AreEqual("þðüçöÝÞÐÜÇÖ", reader.GetString(0)); + Assert.That(reader.GetString(0), Is.EqualTo("þðüçöÝÞÐÜÇÖ")); reader.Read(); - Assert.AreEqual("ฅๆษ", reader.GetString(0)); + Assert.That(reader.GetString(0), Is.EqualTo("ฅๆษ")); } } @@ -362,8 +362,8 @@ public void Chinese() using (MySqlDataReader reader = ExecuteReader("SELECT * FROM Test")) { reader.Read(); - Assert.AreEqual("困巫忘否役", reader.GetString(1)); - Assert.AreEqual("涝搞谷侪魍", reader.GetString(2)); + Assert.That(reader.GetString(1), Is.EqualTo("困巫忘否役")); + Assert.That(reader.GetString(2), Is.EqualTo("涝搞谷侪魍")); } } @@ -379,7 +379,7 @@ public void Russian() using (MySqlDataReader reader = cmd.ExecuteReader()) { reader.Read(); - Assert.AreEqual("щьеи", reader.GetString(1)); + Assert.That(reader.GetString(1), Is.EqualTo("щьеи")); } } @@ -400,7 +400,7 @@ public void UTF8Parameters() cmd.Parameters.Add("?parameter", MySqlDbType.VarString); cmd.Parameters[0].Value = "šđč枊ĐČĆŽ"; object o = cmd.ExecuteScalar(); - Assert.AreEqual(1, o); + Assert.That(o, Is.EqualTo(1)); } [Test] @@ -415,7 +415,7 @@ public void Turkish() using (MySqlDataReader reader = cmd.ExecuteReader()) { reader.Read(); - Assert.AreEqual("ĞËÇÄŞ", reader.GetString(1)); + Assert.That(reader.GetString(1), Is.EqualTo("ĞËÇÄŞ")); } } } diff --git a/MySQL.Data/tests/MySql.Data.Tests/ClientSideFailoverTests.cs b/MySQL.Data/tests/MySql.Data.Tests/ClientSideFailoverTests.cs index cfd078190..829fae591 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/ClientSideFailoverTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/ClientSideFailoverTests.cs @@ -62,10 +62,10 @@ public void RandomMethod(string server, bool shouldPass = true) if (!shouldPass) { Exception ex = Assert.Throws(() => TryConnection(Settings.ConnectionString)); - Assert.AreEqual("Unable to connect to any of the specified MySQL hosts.", ex.Message); + Assert.That(ex.Message, Is.EqualTo("Unable to connect to any of the specified MySQL hosts.")); } else - Assert.AreEqual(ConnectionState.Open, TryConnection(Settings.ConnectionString)); + Assert.That(TryConnection(Settings.ConnectionString), Is.EqualTo(ConnectionState.Open)); } private static ConnectionState TryConnection(string connString) @@ -91,11 +91,11 @@ public void PriorityMethod() using (MySqlConnection conn = new MySqlConnection(Settings.ConnectionString)) { conn.Open(); - Assert.AreEqual(ConnectionState.Open, conn.State); - Assert.AreEqual(Host, conn.Settings.Server); - Assert.AreEqual("server.example", FailoverManager.FailoverGroup.Hosts[0].Host); - Assert.AreEqual("192.0.10.56", FailoverManager.FailoverGroup.Hosts[1].Host); - Assert.AreEqual(Host, FailoverManager.FailoverGroup.Hosts[2].Host); + Assert.That(conn.State, Is.EqualTo(ConnectionState.Open)); + Assert.That(conn.Settings.Server, Is.EqualTo(Host)); + Assert.That(FailoverManager.FailoverGroup.Hosts[0].Host, Is.EqualTo("server.example")); + Assert.That(FailoverManager.FailoverGroup.Hosts[1].Host, Is.EqualTo("192.0.10.56")); + Assert.That(FailoverManager.FailoverGroup.Hosts[2].Host, Is.EqualTo(Host)); } // Multiple hosts with IPv6 @@ -106,7 +106,7 @@ public void PriorityMethod() using (MySqlConnection conn = new MySqlConnection(Settings.ConnectionString)) { conn.Open(); - Assert.AreEqual(ConnectionState.Open, conn.State); + Assert.That(conn.State, Is.EqualTo(ConnectionState.Open)); } } @@ -124,11 +124,11 @@ public void PriorityMethod() using (MySqlConnection conn = new MySqlConnection(Settings.ConnectionString)) { conn.Open(); - Assert.AreEqual(ConnectionState.Open, conn.State); + Assert.That(conn.State, Is.EqualTo(ConnectionState.Open)); priority = 100; foreach (var host in FailoverManager.FailoverGroup.Hosts) { - Assert.AreEqual(priority != 0 ? priority-- : 0, host.Priority); + Assert.That(host.Priority, Is.EqualTo(priority != 0 ? priority-- : 0)); } } } @@ -149,7 +149,7 @@ public void PriorityMethodConnectionFail(string server, string exceptionMessage, else ex = Assert.Throws(() => conn.Open()); - Assert.AreEqual(exceptionMessage, ex.Message); + Assert.That(ex.Message, Is.EqualTo(exceptionMessage)); } } @@ -166,7 +166,7 @@ public void Pooling(string server) { connArray[i] = new MySqlConnection(Settings.ConnectionString); connArray[i].Open(); - Assert.AreEqual(ConnectionState.Open, connArray[i].State); + Assert.That(connArray[i].State, Is.EqualTo(ConnectionState.Open)); } // now make sure all the server ids are different @@ -175,7 +175,7 @@ public void Pooling(string server) for (int j = 0; j < connArray.Length; j++) { if (i != j) - Assert.True(connArray[i].ServerThread != connArray[j].ServerThread); + Assert.That(connArray[i].ServerThread != connArray[j].ServerThread); } } diff --git a/MySQL.Data/tests/MySql.Data.Tests/CmdTests.cs b/MySQL.Data/tests/MySql.Data.Tests/CmdTests.cs index c2454add3..cc377864e 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/CmdTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/CmdTests.cs @@ -83,7 +83,7 @@ public void InvalidCast() cmd.Parameters[1].Direction = ParameterDirection.ReturnValue; cmd.Parameters[0].Value = 20; cmd.ExecuteNonQuery(); - Assert.AreEqual(40, cmd.Parameters[1].Value); + Assert.That(cmd.Parameters[1].Value, Is.EqualTo(40)); cmd.CommandText = "spMyTwice"; cmd.CommandType = CommandType.StoredProcedure; @@ -93,7 +93,7 @@ public void InvalidCast() cmd.Parameters[0].Direction = ParameterDirection.Output; cmd.Parameters[1].Value = 20; cmd.ExecuteNonQuery(); - Assert.AreEqual(40, cmd.Parameters[0].Value); + Assert.That(cmd.Parameters[0].Value, Is.EqualTo(40)); } } @@ -104,25 +104,25 @@ public void InsertTest() // do the insert MySqlCommand cmd = new MySqlCommand("INSERT INTO Test (id,name) VALUES(10,'Test')", Connection); int cnt = cmd.ExecuteNonQuery(); - Assert.True(cnt == 1, "Insert Count"); + Assert.That(cnt == 1, "Insert Count"); // make sure we get the right value back out cmd.CommandText = "SELECT name FROM Test WHERE id=10"; string name = (string)cmd.ExecuteScalar(); - Assert.True(name == "Test", "Insert result"); + Assert.That(name == "Test", "Insert result"); // now do the insert with parameters cmd.CommandText = "INSERT INTO Test (id,name) VALUES(?id, ?name)"; cmd.Parameters.Add(new MySqlParameter("?id", 11)); cmd.Parameters.Add(new MySqlParameter("?name", "Test2")); cnt = cmd.ExecuteNonQuery(); - Assert.True(cnt == 1, "Insert with Parameters Count"); + Assert.That(cnt == 1, "Insert with Parameters Count"); // make sure we get the right value back out cmd.Parameters.Clear(); cmd.CommandText = "SELECT name FROM Test WHERE id=11"; name = (string)cmd.ExecuteScalar(); - Assert.True(name == "Test2", "Insert with parameters result"); + Assert.That(name == "Test2", "Insert with parameters result"); } [Test] @@ -135,29 +135,29 @@ public void UpdateTest() // do the update MySqlCommand cmd = new MySqlCommand("UPDATE test SET name='Test3' WHERE id=10 OR id=11", Connection); int cnt = cmd.ExecuteNonQuery(); - Assert.AreEqual(2, cnt); + Assert.That(cnt, Is.EqualTo(2)); // make sure we get the right value back out cmd.CommandText = "SELECT name FROM test WHERE id=10"; string name = (string)cmd.ExecuteScalar(); - Assert.AreEqual("Test3", name); + Assert.That(name, Is.EqualTo("Test3")); cmd.CommandText = "SELECT name FROM test WHERE id=11"; name = (string)cmd.ExecuteScalar(); - Assert.AreEqual("Test3", name); + Assert.That(name, Is.EqualTo("Test3")); // now do the update with parameters cmd.CommandText = "UPDATE test SET name=?name WHERE id=?id"; cmd.Parameters.Add(new MySqlParameter("?id", 11)); cmd.Parameters.Add(new MySqlParameter("?name", "Test5")); cnt = cmd.ExecuteNonQuery(); - Assert.True(cnt == 1, "Update with Parameters Count"); + Assert.That(cnt == 1, "Update with Parameters Count"); // make sure we get the right value back out cmd.Parameters.Clear(); cmd.CommandText = "SELECT name FROM test WHERE id=11"; name = (string)cmd.ExecuteScalar(); - Assert.AreEqual("Test5", name); + Assert.That(name, Is.EqualTo("Test5")); } @@ -171,12 +171,12 @@ public void DeleteTest() // make sure we get the right value back out MySqlCommand cmd = new MySqlCommand("DELETE FROM Test WHERE id=1 or id=2", Connection); int delcnt = cmd.ExecuteNonQuery(); - Assert.AreEqual(2, delcnt); + Assert.That(delcnt, Is.EqualTo(2)); // find out how many rows we have now cmd.CommandText = "SELECT COUNT(*) FROM Test"; object after_cnt = cmd.ExecuteScalar(); - Assert.AreEqual(0, Convert.ToInt32(after_cnt)); + Assert.That(Convert.ToInt32(after_cnt), Is.EqualTo(0)); } [Test] @@ -309,9 +309,9 @@ public void PreparedInsertUsingReader() { ExecuteSQL("CREATE TABLE Test (id int NOT NULL, name VARCHAR(100))"); MySqlCommand cmd = new MySqlCommand("INSERT INTO Test VALUES(1, 'Test')", Connection); - Assert.False(cmd.IsPrepared); + Assert.That(cmd.IsPrepared, Is.False); cmd.Prepare(); - Assert.True(cmd.IsPrepared); + Assert.That(cmd.IsPrepared); using (MySqlDataReader reader = cmd.ExecuteReader()) { } @@ -319,9 +319,9 @@ public void PreparedInsertUsingReader() cmd.CommandText = "SELECT * FROM Test"; using (MySqlDataReader reader = cmd.ExecuteReader()) { - Assert.True(reader.Read()); - Assert.False(reader.Read()); - Assert.False(reader.NextResult()); + Assert.That(reader.Read()); + Assert.That(reader.Read(), Is.False); + Assert.That(reader.NextResult(), Is.False); } } @@ -396,31 +396,31 @@ public void DefaultCommandTimeout() { MySqlConnection c = new MySqlConnection($"server={Host}"); MySqlCommand cmd = new MySqlCommand("", c); - Assert.AreEqual(30, cmd.CommandTimeout); + Assert.That(cmd.CommandTimeout, Is.EqualTo(30)); c = new MySqlConnection($"server={Host};default command timeout=47"); cmd = new MySqlCommand("", c); - Assert.AreEqual(47, cmd.CommandTimeout); + Assert.That(cmd.CommandTimeout, Is.EqualTo(47)); cmd = new MySqlCommand(""); - Assert.AreEqual(30, cmd.CommandTimeout); + Assert.That(cmd.CommandTimeout, Is.EqualTo(30)); cmd.CommandTimeout = 66; cmd.Connection = c; - Assert.AreEqual(66, cmd.CommandTimeout); + Assert.That(cmd.CommandTimeout, Is.EqualTo(66)); cmd.CommandTimeout = 0; - Assert.AreEqual(0, cmd.CommandTimeout); + Assert.That(cmd.CommandTimeout, Is.EqualTo(0)); c = new MySqlConnection($"server={Host};default command timeout=0"); cmd = new MySqlCommand("", c); - Assert.AreEqual(0, cmd.CommandTimeout); + Assert.That(cmd.CommandTimeout, Is.EqualTo(0)); // Defaults to Int32.MaxValue/1000 when provided value is larger. c = new MySqlConnection(Connection.ConnectionString); cmd = new MySqlCommand("", c); c.Open(); cmd.CommandTimeout = Int32.MaxValue; - Assert.AreEqual(Int32.MaxValue / 1000, cmd.CommandTimeout); + Assert.That(cmd.CommandTimeout, Is.EqualTo(Int32.MaxValue / 1000)); c.Close(); } @@ -454,7 +454,7 @@ public void UseAffectedRows() ExecuteSQL("INSERT INTO Test VALUES (3, 'C')"); MySqlCommand cmd = new MySqlCommand("UPDATE Test SET name='C' WHERE id=3", Connection); - Assert.AreEqual(1, cmd.ExecuteNonQuery()); + Assert.That(cmd.ExecuteNonQuery(), Is.EqualTo(1)); MySqlConnectionStringBuilder connStr = new MySqlConnectionStringBuilder(Connection.ConnectionString); connStr.UseAffectedRows = true; @@ -462,7 +462,7 @@ public void UseAffectedRows() { c.Open(); cmd.Connection = c; - Assert.AreEqual(0, cmd.ExecuteNonQuery()); + Assert.That(cmd.ExecuteNonQuery(), Is.EqualTo(0)); } } @@ -496,10 +496,10 @@ public void TableCommandType() using (MySqlDataReader reader = cmd.ExecuteReader()) { reader.Read(); - Assert.AreEqual(1, reader.GetInt32(0)); - Assert.AreEqual("A", reader.GetString(1)); - Assert.AreEqual(2, reader.GetInt32(2)); - Assert.AreEqual("B", reader.GetString(3)); + Assert.That(reader.GetInt32(0), Is.EqualTo(1)); + Assert.That(reader.GetString(1), Is.EqualTo("A")); + Assert.That(reader.GetInt32(2), Is.EqualTo(2)); + Assert.That(reader.GetString(3), Is.EqualTo("B")); } } @@ -530,8 +530,8 @@ public void SyntaxErrorWithCloseConnection() c.Open(); MySqlCommand cmd = new MySqlCommand("SELE 1", c); var ex = Assert.Throws(() => cmd.ExecuteReader(CommandBehavior.CloseConnection)); - Assert.AreEqual("You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'SELE 1' at line 1", ex.Message); - Assert.True(c.State == ConnectionState.Closed); + Assert.That(ex.Message, Is.EqualTo("You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'SELE 1' at line 1")); + Assert.That(c.State == ConnectionState.Closed); } } @@ -545,7 +545,7 @@ public void EmptyOrJustSemiCommand() cmd.CommandText = ";"; MySqlException ex = Assert.Throws(() => cmd.ExecuteNonQuery()); // Error: 1065 Message: Query was empty - Assert.AreEqual(1065, ex.Number); + Assert.That(ex.Number, Is.EqualTo(1065)); } /// @@ -558,7 +558,7 @@ public void CommandTextIsNull() { MySqlCommand cmd = new MySqlCommand(null, Connection); Exception ex = Assert.Throws(() => cmd.ExecuteReader()); - Assert.True(ex.Message != String.Empty); + Assert.That(ex.Message != String.Empty); } /// @@ -577,7 +577,7 @@ public void LongLastInsertId() { cmd.CommandText = "INSERT INTO longids VALUES ();"; cmd.ExecuteNonQuery(); - Assert.AreEqual(seed++, cmd.LastInsertedId); + Assert.That(cmd.LastInsertedId, Is.EqualTo(seed++)); } } @@ -593,12 +593,12 @@ public async Task ExecuteNonQueryAsync() proc.CommandType = CommandType.StoredProcedure; int result = await proc.ExecuteNonQueryAsync(); - Assert.AreNotEqual(-1, result); + Assert.That(result, Is.Not.EqualTo(-1)); MySqlCommand cmd = new MySqlCommand("SELECT COUNT(*) FROM CMDNonQueryAsyncTest;", Connection); cmd.CommandType = CommandType.Text; object cnt = cmd.ExecuteScalar(); - Assert.AreEqual(100, Convert.ToInt32(cnt)); + Assert.That(Convert.ToInt32(cnt), Is.EqualTo(100)); } [Test] @@ -612,17 +612,17 @@ public async Task ExecuteReaderAsync() using (MySqlDataReader reader = await proc.ExecuteReaderAsync() as MySqlDataReader) { - Assert.NotNull(reader); - Assert.True(reader.Read(), "can read"); - Assert.True(reader.NextResult()); - Assert.True(reader.Read()); - Assert.AreEqual("done", reader.GetString(0)); + Assert.That(reader, Is.Not.Null); + Assert.That(reader.Read(), "can read"); + Assert.That(reader.NextResult()); + Assert.That(reader.Read()); + Assert.That(reader.GetString(0), Is.EqualTo("done")); reader.Close(); proc.CommandType = CommandType.Text; proc.CommandText = "SELECT COUNT(*) FROM CMDReaderAsyncTest"; object cnt = proc.ExecuteScalar(); - Assert.AreEqual(1, Convert.ToInt32(cnt)); + Assert.That(Convert.ToInt32(cnt), Is.EqualTo(1)); } } @@ -638,8 +638,8 @@ public async Task ExecuteScalarAsync() cmd.Parameters[1].Direction = ParameterDirection.Output; object result = await cmd.ExecuteScalarAsync(); - Assert.AreEqual("Test", result); - Assert.AreEqual("valuein", cmd.Parameters[1].Value); + Assert.That(result, Is.EqualTo("Test")); + Assert.That(cmd.Parameters[1].Value, Is.EqualTo("valuein")); } #if NET452 @@ -691,7 +691,7 @@ public void BatchUpdatesAndDeletes() da.Update(dt); } - Assert.AreEqual(1, listener.Find("Query Opened: UPDATE")); + Assert.That(listener.Find("Query Opened: UPDATE"), Is.EqualTo(1)); } [Test] @@ -708,10 +708,10 @@ public void ExecuteReaderReturnsReaderAfterCancel() command = new MySqlCommand("SELECT PrimaryKey FROM TableWithStringAsPrimaryKey", Connection); reader = command.ExecuteReader(CommandBehavior.KeyInfo); - Assert.NotNull(reader); + Assert.That(reader, Is.Not.Null); dataTableSchema = reader.GetSchemaTable(); - Assert.True("PrimaryKey" == (string)dataTableSchema.Rows[0][dataTableSchema.Columns[0]]); + Assert.That("PrimaryKey" == (string)dataTableSchema.Rows[0][dataTableSchema.Columns[0]]); reader.Close(); } @@ -724,10 +724,10 @@ public void CloneCommand() var cmd2 = (MySqlCommand)cmd.Clone(); - Assert.AreEqual(1, cmd2.Parameters.Count); - Assert.AreEqual(1, cmd2.Attributes.Count); - StringAssert.AreEqualIgnoringCase("attr_value", cmd2.Attributes[0].Value.ToString()); - StringAssert.AreEqualIgnoringCase("param_value", cmd2.Parameters[0].Value.ToString()); + Assert.That(cmd2.Parameters.Count, Is.EqualTo(1)); + Assert.That(cmd2.Attributes.Count, Is.EqualTo(1)); + Assert.That(cmd2.Attributes[0].Value.ToString(), Is.EqualTo("attr_value").IgnoreCase); + Assert.That(cmd2.Parameters[0].Value.ToString(), Is.EqualTo("param_value").IgnoreCase); } /// @@ -747,9 +747,9 @@ public void ExecuteReaderAfterClosingCommand() reader = cmd.ExecuteReader(); } - Assert.True(reader.Read()); - Assert.AreEqual("TEST", reader.GetString(0)); - Assert.False(reader.Read()); + Assert.That(reader.Read()); + Assert.That(reader.GetString(0), Is.EqualTo("TEST")); + Assert.That(reader.Read(), Is.False); } } @@ -761,14 +761,14 @@ public void CommandNegativeTimeout() { MySqlConnection conn = new MySqlConnection($"server={Host};default command timeout=10"); MySqlCommand cmd = new MySqlCommand("", conn); - Assert.AreEqual(10, cmd.CommandTimeout); + Assert.That(cmd.CommandTimeout, Is.EqualTo(10)); Assert.Throws(() => conn = new MySqlConnection($"server={Host};default command timeout=-1")); var ex = Assert.Throws(() => cmd.CommandTimeout = -1); - StringAssert.AreEqualIgnoringCase("Command timeout must not be negative", ex.Message); + Assert.That(ex.Message, Is.EqualTo("Command timeout must not be negative").IgnoreCase); cmd.CommandTimeout = 15; - Assert.AreEqual(15, cmd.CommandTimeout); + Assert.That(cmd.CommandTimeout, Is.EqualTo(15)); } #region SQL Injection @@ -792,7 +792,7 @@ public void SqlInjection1() cmd.Parameters[0].Value = "\u2032 OR 1=1;-- --"; cmd.ExecuteNonQuery(); - Assert.AreEqual(count, (Int64)cnt.ExecuteScalar()); + Assert.That((Int64)cnt.ExecuteScalar(), Is.EqualTo(count)); } #endregion @@ -838,11 +838,11 @@ PRIMARY KEY (`inventory_id`) { while (reader.Read()) { - Assert.AreEqual(999999, cmd.CommandTimeout); - Assert.IsNotEmpty(reader.GetValue(0).ToString()); - Assert.IsNotEmpty(reader.GetValue(1).ToString()); - Assert.IsNotEmpty(reader.GetValue(2).ToString()); - Assert.IsNotEmpty(reader.GetValue(3).ToString()); + Assert.That(cmd.CommandTimeout, Is.EqualTo(999999)); + Assert.That(reader.GetValue(0).ToString(), Is.Not.Empty); + Assert.That(reader.GetValue(1).ToString(), Is.Not.Empty); + Assert.That(reader.GetValue(2).ToString(), Is.Not.Empty); + Assert.That(reader.GetValue(3).ToString(), Is.Not.Empty); } } } @@ -872,9 +872,9 @@ public void ReservedWordUse() { while (rdr.Read()) { - Assert.AreEqual("1", rdr[0]); - Assert.AreEqual("test", rdr[1]); - Assert.AreEqual("status", rdr[2]); + Assert.That(rdr[0], Is.EqualTo("1")); + Assert.That(rdr[1], Is.EqualTo("test")); + Assert.That(rdr[2], Is.EqualTo("status")); } } } @@ -924,10 +924,10 @@ public void ExecuteCmdWithTabsAndNewLines() using (var cmd = Connection.CreateCommand()) { cmd.CommandText = "SELECT\nCOUNT(*)\nFROM\nTest;"; - Assert.AreEqual(1, cmd.ExecuteScalar()); + Assert.That(cmd.ExecuteScalar(), Is.EqualTo(1)); cmd.CommandText = "SELECT\tCOUNT(*)\n\t\tFROM\tTest;"; - Assert.AreEqual(1, cmd.ExecuteScalar()); + Assert.That(cmd.ExecuteScalar(), Is.EqualTo(1)); } } @@ -945,10 +945,10 @@ public void LastInsertedIdInMultipleStatements() + "INSERT INTO TestForeignKey (foreign_id, column2) VALUES(LAST_INSERT_ID(), 'test');"; cmd.ExecuteNonQuery(); - Assert.AreEqual(1, cmd.LastInsertedId); + Assert.That(cmd.LastInsertedId, Is.EqualTo(1)); cmd.ExecuteNonQuery(); - Assert.AreEqual(2, cmd.LastInsertedId); + Assert.That(cmd.LastInsertedId, Is.EqualTo(2)); cmd.CommandText = "SELECT * FROM Test"; int id = 1; @@ -956,11 +956,11 @@ public void LastInsertedIdInMultipleStatements() using var reader = cmd.ExecuteReader(); while (reader.Read()) { - Assert.IsTrue(reader.GetInt32(0) == id); + Assert.That(reader.GetInt32(0) == id); id++; } - Assert.AreEqual(-1, cmd.LastInsertedId); + Assert.That(cmd.LastInsertedId, Is.EqualTo(-1)); } /// @@ -974,8 +974,8 @@ public void LastInserteIdRedux() using var cmd = Connection.CreateCommand(); cmd.CommandText = @"INSERT INTO Test (text) VALUES ('test1'); INSERT INTO Test (text) VALUES ('test2');"; - Assert.AreEqual(2, cmd.ExecuteNonQuery()); - Assert.AreEqual(2, cmd.LastInsertedId); + Assert.That(cmd.ExecuteNonQuery(), Is.EqualTo(2)); + Assert.That(cmd.LastInsertedId, Is.EqualTo(2)); } } diff --git a/MySQL.Data/tests/MySql.Data.Tests/ConnectionStringBuilderTests.cs b/MySQL.Data/tests/MySql.Data.Tests/ConnectionStringBuilderTests.cs index 3d50fa738..5f04d2c1b 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/ConnectionStringBuilderTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/ConnectionStringBuilderTests.cs @@ -54,48 +54,48 @@ public void Simple() sb.ConnectionString = "server=localhost;uid=reggie;pwd=pass;port=1111;" + "connection timeout=23; pooling=true; min pool size=33; " + "max pool size=66;keepalive=1"; - Assert.AreEqual("localhost", sb.Server); - Assert.AreEqual("reggie", sb.UserID); - Assert.AreEqual("pass", sb.Password); - Assert.AreEqual(1111, Convert.ToInt32(sb.Port)); - Assert.AreEqual(23, Convert.ToInt32(sb.ConnectionTimeout)); - Assert.True(sb.Pooling); - Assert.AreEqual(33, Convert.ToInt32(sb.MinimumPoolSize)); - Assert.AreEqual(66, Convert.ToInt32(sb.MaximumPoolSize)); - Assert.AreEqual(1, Convert.ToInt32(sb.Keepalive)); + Assert.That(sb.Server, Is.EqualTo("localhost")); + Assert.That(sb.UserID, Is.EqualTo("reggie")); + Assert.That(sb.Password, Is.EqualTo("pass")); + Assert.That(Convert.ToInt32(sb.Port), Is.EqualTo(1111)); + Assert.That(Convert.ToInt32(sb.ConnectionTimeout), Is.EqualTo(23)); + Assert.That(sb.Pooling); + Assert.That(Convert.ToInt32(sb.MinimumPoolSize), Is.EqualTo(33)); + Assert.That(Convert.ToInt32(sb.MaximumPoolSize), Is.EqualTo(66)); + Assert.That(Convert.ToInt32(sb.Keepalive), Is.EqualTo(1)); Exception ex = Assert.Throws(() => sb.ConnectionString = "server=localhost;badkey=badvalue"); #if NETFRAMEWORK - Assert.AreEqual($"Option not supported.{Environment.NewLine}Parameter name: badkey", ex.Message); + Assert.That(ex.Message, Is.EqualTo($"Option not supported.{Environment.NewLine}Parameter name: badkey")); #else - Assert.AreEqual("Option not supported. (Parameter 'badkey')", ex.Message); + Assert.That(ex.Message, Is.EqualTo("Option not supported. (Parameter 'badkey')")); #endif sb.Clear(); - Assert.AreEqual(15, Convert.ToInt32(sb.ConnectionTimeout)); - Assert.True(sb.Pooling); - Assert.True(sb.Pooling); - Assert.AreEqual(3306, Convert.ToInt32(sb.Port)); - Assert.AreEqual(String.Empty, sb.Server); - Assert.False(sb.PersistSecurityInfo); - Assert.AreEqual(0, Convert.ToInt32(sb.ConnectionLifeTime)); - Assert.False(sb.ConnectionReset); - Assert.AreEqual(0, Convert.ToInt32(sb.MinimumPoolSize)); - Assert.AreEqual(100, Convert.ToInt32(sb.MaximumPoolSize)); - Assert.AreEqual(String.Empty, sb.UserID); - Assert.AreEqual(String.Empty, sb.Password); - Assert.False(sb.UseUsageAdvisor); - Assert.AreEqual(String.Empty, sb.CharacterSet); - Assert.False(sb.UseCompression); - Assert.AreEqual("MYSQL", sb.PipeName); - Assert.False(sb.Logging); - Assert.True(sb.AllowBatch); - Assert.False(sb.ConvertZeroDateTime); - Assert.AreEqual("MYSQL", sb.SharedMemoryName); - Assert.AreEqual(String.Empty, sb.Database); - Assert.AreEqual(MySqlConnectionProtocol.Sockets, sb.ConnectionProtocol); - Assert.False(sb.AllowZeroDateTime); - Assert.False(sb.UsePerformanceMonitor); - Assert.AreEqual(25, Convert.ToInt32(sb.ProcedureCacheSize)); - Assert.AreEqual(0, Convert.ToInt32(sb.Keepalive)); + Assert.That(Convert.ToInt32(sb.ConnectionTimeout), Is.EqualTo(15)); + Assert.That(sb.Pooling); + Assert.That(sb.Pooling); + Assert.That(Convert.ToInt32(sb.Port), Is.EqualTo(3306)); + Assert.That(sb.Server, Is.EqualTo(String.Empty)); + Assert.That(sb.PersistSecurityInfo, Is.False); + Assert.That(Convert.ToInt32(sb.ConnectionLifeTime), Is.EqualTo(0)); + Assert.That(sb.ConnectionReset, Is.False); + Assert.That(Convert.ToInt32(sb.MinimumPoolSize), Is.EqualTo(0)); + Assert.That(Convert.ToInt32(sb.MaximumPoolSize), Is.EqualTo(100)); + Assert.That(sb.UserID, Is.EqualTo(String.Empty)); + Assert.That(sb.Password, Is.EqualTo(String.Empty)); + Assert.That(sb.UseUsageAdvisor, Is.False); + Assert.That(sb.CharacterSet, Is.EqualTo(String.Empty)); + Assert.That(sb.UseCompression, Is.False); + Assert.That(sb.PipeName, Is.EqualTo("MYSQL")); + Assert.That(sb.Logging, Is.False); + Assert.That(sb.AllowBatch); + Assert.That(sb.ConvertZeroDateTime, Is.False); + Assert.That(sb.SharedMemoryName, Is.EqualTo("MYSQL")); + Assert.That(sb.Database, Is.EqualTo(String.Empty)); + Assert.That(sb.ConnectionProtocol, Is.EqualTo(MySqlConnectionProtocol.Sockets)); + Assert.That(sb.AllowZeroDateTime, Is.False); + Assert.That(sb.UsePerformanceMonitor, Is.False); + Assert.That(Convert.ToInt32(sb.ProcedureCacheSize), Is.EqualTo(25)); + Assert.That(Convert.ToInt32(sb.Keepalive), Is.EqualTo(0)); } /// @@ -107,7 +107,7 @@ public void SettingValueMultipeTimes() MySqlConnectionStringBuilder s = new MySqlConnectionStringBuilder(); s["database"] = "test"; s["database"] = "test2"; - Assert.AreEqual("database=test2", s.ConnectionString); + Assert.That(s.ConnectionString, Is.EqualTo("database=test2")); } /// @@ -118,8 +118,8 @@ public void NoValueGivenForConnectionStringOption() { MySqlConnectionStringBuilder s = new MySqlConnectionStringBuilder(); s.ConnectionString = "compress=;pooling="; - Assert.False(s.UseCompression); - Assert.True(s.Pooling); + Assert.That(s.UseCompression, Is.False); + Assert.That(s.Pooling); } /// @@ -130,18 +130,18 @@ public void ContainsKey() { MySqlConnectionStringBuilder s = new MySqlConnectionStringBuilder(); s["database"] = "test"; - Assert.True(s.ContainsKey("initial catalog")); + Assert.That(s.ContainsKey("initial catalog")); s["server"] = "myserver"; - Assert.True(s.ContainsKey("server")); - Assert.True(s.ContainsKey("host")); - Assert.False(s.ContainsKey("badkey")); + Assert.That(s.ContainsKey("server")); + Assert.That(s.ContainsKey("host")); + Assert.That(s.ContainsKey("badkey"), Is.False); } [Test] public void SettingCheckParameters() { MySqlConnectionStringBuilder s = new MySqlConnectionStringBuilder("server=localhost;check parameters=false"); - Assert.False(s.CheckParameters); + Assert.That(s.CheckParameters, Is.False); } [TestCase("foo keyword")] @@ -151,9 +151,9 @@ public void SettingInvalidKeyThrowsArgumentException(string invalidKey) MySqlConnectionStringBuilder s = new MySqlConnectionStringBuilder(); Exception ex = Assert.Throws(() => s[invalidKey] = "foo"); #if NETFRAMEWORK - Assert.AreEqual($"Option not supported.{Environment.NewLine}Parameter name: {invalidKey}", ex.Message); + Assert.That(ex.Message, Is.EqualTo($"Option not supported.{Environment.NewLine}Parameter name: {invalidKey}")); #else - Assert.AreEqual($"Option not supported. (Parameter '{invalidKey}')", ex.Message); + Assert.That(ex.Message, Is.EqualTo($"Option not supported. (Parameter '{invalidKey}')")); #endif } @@ -166,7 +166,7 @@ public void SafeTryGetValue() object obj; MySqlConnectionStringBuilder s = new MySqlConnectionStringBuilder("server=localhost;"); s.TryGetValue("unknownproperty", out obj); - Assert.Null(obj); + Assert.That(obj, Is.Null); } #if !NETFRAMEWORK @@ -231,7 +231,7 @@ public void SettingTableCachingRaisesException() { var builder = new MySqlConnectionStringBuilder(); builder.TableCaching = true; - Assert.True(builder.TableCaching); + Assert.That(builder.TableCaching); } /// @@ -246,11 +246,11 @@ public void SettingInvalidAuthenticationMethod(string method) var builder = new MySqlConnectionStringBuilder(); builder.DefaultAuthenticationPlugin = " "; var ex = Assert.Throws(() => builder.DefaultAuthenticationPlugin = method); - StringAssert.AreEqualIgnoringCase(string.Format(Resources.AuthenticationMethodNotSupported, method), ex.Message); + Assert.That(ex.Message, Is.EqualTo(string.Format(Resources.AuthenticationMethodNotSupported, method)).IgnoreCase); var connStr = $"server=localhost;userid=root;defaultauthenticationplugin={method}"; ex = Assert.Throws(() => new MySqlConnection(connStr)); - StringAssert.AreEqualIgnoringCase(string.Format(Resources.AuthenticationMethodNotSupported, method), ex.Message); + Assert.That(ex.Message, Is.EqualTo(string.Format(Resources.AuthenticationMethodNotSupported, method)).IgnoreCase); connStr = "server=localhost;userid=root;defaultauthenticationplugin="; var conn = new MySqlConnection(connStr); @@ -266,17 +266,17 @@ public void UsingPwdAliases(string alias) { string value = "test"; var conn = new MySqlConnection($"{alias}={value};pwd2={value};pwd3={value}"); - StringAssert.AreEqualIgnoringCase(value, conn.Settings.Password); - StringAssert.AreEqualIgnoringCase(value, conn.Settings.Password2); - StringAssert.AreEqualIgnoringCase(value, conn.Settings.Password3); + Assert.That(conn.Settings.Password, Is.EqualTo(value).IgnoreCase); + Assert.That(conn.Settings.Password2, Is.EqualTo(value).IgnoreCase); + Assert.That(conn.Settings.Password3, Is.EqualTo(value).IgnoreCase); var connBuilder = new MySqlConnectionStringBuilder(); connBuilder[alias] = value; connBuilder["pwd2"] = value; connBuilder["pwd3"] = value; - StringAssert.AreEqualIgnoringCase(value, connBuilder.Password); - StringAssert.AreEqualIgnoringCase(value, connBuilder.Password2); - StringAssert.AreEqualIgnoringCase(value, connBuilder.Password3); + Assert.That(connBuilder.Password, Is.EqualTo(value).IgnoreCase); + Assert.That(connBuilder.Password2, Is.EqualTo(value).IgnoreCase); + Assert.That(connBuilder.Password3, Is.EqualTo(value).IgnoreCase); } [Test, Description("Session BaseString/MySQLConnectionString Builder")] @@ -299,7 +299,7 @@ public void ConnectionStringBuilderClassicTests() using (var conn = new MySqlConnection(mysql.ConnectionString)) { conn.Open(); - Assert.AreEqual(ConnectionState.Open, conn.connectionState); + Assert.That(conn.connectionState, Is.EqualTo(ConnectionState.Open)); } mysql = new MySqlConnectionStringBuilder(Settings.ConnectionString); @@ -316,7 +316,7 @@ public void ConnectionStringBuilderClassicTests() using (var conn = new MySqlConnection(mysql.ConnectionString)) { conn.Open(); - Assert.AreEqual(ConnectionState.Open, conn.connectionState); + Assert.That(conn.connectionState, Is.EqualTo(ConnectionState.Open)); } mysql = new MySqlConnectionStringBuilder(Settings.ConnectionString); @@ -329,7 +329,7 @@ public void ConnectionStringBuilderClassicTests() using (var conn = new MySqlConnection(mysql.ConnectionString)) { conn.Open(); - Assert.AreEqual(ConnectionState.Open, conn.connectionState); + Assert.That(conn.connectionState, Is.EqualTo(ConnectionState.Open)); } ////Scenario-2 @@ -382,7 +382,7 @@ public void ConnectionStringBuilderClassicTests() using (var conn = new MySqlConnection(mysql.ConnectionString)) { conn.Open(); - Assert.AreEqual(ConnectionState.Open, conn.connectionState); + Assert.That(conn.connectionState, Is.EqualTo(ConnectionState.Open)); } mysql.SslCa = _sslCa; @@ -390,7 +390,7 @@ public void ConnectionStringBuilderClassicTests() using (var conn = new MySqlConnection(mysql.ConnectionString)) { conn.Open(); - Assert.AreEqual(ConnectionState.Open, conn.connectionState); + Assert.That(conn.connectionState, Is.EqualTo(ConnectionState.Open)); } ////Basic Scenarios @@ -401,7 +401,7 @@ public void ConnectionStringBuilderClassicTests() using (var conn = new MySqlConnection(mysql.ConnectionString)) { conn.Open(); - Assert.AreEqual(ConnectionState.Open, conn.connectionState); + Assert.That(conn.connectionState, Is.EqualTo(ConnectionState.Open)); } } @@ -418,21 +418,21 @@ public void TryGetValue() MinimumPoolSize = 10, }; - Assert.IsTrue(connStringBuilder.ContainsKey("data source")); - Assert.IsTrue(connStringBuilder.TryGetValue("host", out var server)); - StringAssert.AreEqualIgnoringCase(connStringBuilder.Server, (string)server); + Assert.That(connStringBuilder.ContainsKey("data source")); + Assert.That(connStringBuilder.TryGetValue("host", out var server)); + Assert.That((string)server, Is.EqualTo(connStringBuilder.Server).IgnoreCase); - Assert.IsTrue(connStringBuilder.ContainsKey("MinimumPoolSize")); - Assert.IsTrue(connStringBuilder.TryGetValue("Minimum Pool Size", out var minpoolsize)); - Assert.AreEqual(connStringBuilder.MinimumPoolSize, (uint)minpoolsize); + Assert.That(connStringBuilder.ContainsKey("MinimumPoolSize")); + Assert.That(connStringBuilder.TryGetValue("Minimum Pool Size", out var minpoolsize)); + Assert.That((uint)minpoolsize, Is.EqualTo(connStringBuilder.MinimumPoolSize)); // Default value - Assert.IsTrue(connStringBuilder.TryGetValue("allowpublickeyretrieval", out var allowpublickeyretrieval)); - Assert.AreEqual(connStringBuilder.GetOption("allowpublickeyretrieval").DefaultValue, allowpublickeyretrieval); + Assert.That(connStringBuilder.TryGetValue("allowpublickeyretrieval", out var allowpublickeyretrieval)); + Assert.That(allowpublickeyretrieval, Is.EqualTo(connStringBuilder.GetOption("allowpublickeyretrieval").DefaultValue)); // Non existing option - Assert.IsFalse(connStringBuilder.TryGetValue("bar", out var nonexistingoption)); - Assert.IsNull(nonexistingoption); + Assert.That(connStringBuilder.TryGetValue("bar", out var nonexistingoption), Is.False); + Assert.That(nonexistingoption, Is.Null); } /// @@ -448,17 +448,17 @@ public void KerberosAuthModeTest() MySqlConnection conn; conn = new MySqlConnection(); - Assert.True(conn.Settings.KerberosAuthMode == KerberosAuthMode.AUTO); + Assert.That(conn.Settings.KerberosAuthMode == KerberosAuthMode.AUTO); foreach (KerberosAuthMode mode in Enum.GetValues(typeof(KerberosAuthMode))) { connString = $"kerberosauthmode={mode}"; conn = new MySqlConnection(connString); - Assert.True(conn.Settings.KerberosAuthMode == mode); + Assert.That(conn.Settings.KerberosAuthMode == mode); connString = $"kerberos auth mode={mode}"; conn = new MySqlConnection(connString); - Assert.True(conn.Settings.KerberosAuthMode == mode); + Assert.That(conn.Settings.KerberosAuthMode == mode); } connString = "kerberosauthmode=INVALID"; diff --git a/MySQL.Data/tests/MySql.Data.Tests/ConnectionTests.cs b/MySQL.Data/tests/MySql.Data.Tests/ConnectionTests.cs index 2e7f989fa..c2fef3dab 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/ConnectionTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/ConnectionTests.cs @@ -49,38 +49,38 @@ public void TestConnectionStrings() MySqlConnection c = new MySqlConnection(); // public properties - Assert.True(15 == c.ConnectionTimeout, "ConnectionTimeout"); - Assert.True(String.Empty == c.Database, "Database"); - Assert.True(String.Empty == c.DataSource, "DataSource"); - Assert.True(false == c.UseCompression, "Use Compression"); - Assert.True(ConnectionState.Closed == c.State, "State"); + Assert.That(15 == c.ConnectionTimeout, "ConnectionTimeout"); + Assert.That(String.Empty == c.Database, "Database"); + Assert.That(String.Empty == c.DataSource, "DataSource"); + Assert.That(false == c.UseCompression, "Use Compression"); + Assert.That(ConnectionState.Closed == c.State, "State"); c = new MySqlConnection("connection timeout=25; user id=myuser; " + "password=mypass; database=Test;server=myserver; use compression=true; " + "pooling=false;min pool size=5; max pool size=101"); // public properties - Assert.True(25 == c.ConnectionTimeout, "ConnectionTimeout"); - Assert.True("Test" == c.Database, "Database"); - Assert.True("myserver" == c.DataSource, "DataSource"); - Assert.True(true == c.UseCompression, "Use Compression"); - Assert.True(ConnectionState.Closed == c.State, "State"); + Assert.That(25 == c.ConnectionTimeout, "ConnectionTimeout"); + Assert.That("Test" == c.Database, "Database"); + Assert.That("myserver" == c.DataSource, "DataSource"); + Assert.That(true == c.UseCompression, "Use Compression"); + Assert.That(ConnectionState.Closed == c.State, "State"); c.ConnectionString = "connection timeout=15; user id=newuser; " + "password=newpass; port=3308; database=mydb; data source=myserver2; " + "use compression=true; pooling=true; min pool size=3; max pool size=76"; // public properties - Assert.True(15 == c.ConnectionTimeout, "ConnectionTimeout"); - Assert.True("mydb" == c.Database, "Database"); - Assert.True("myserver2" == c.DataSource, "DataSource"); - Assert.True(true == c.UseCompression, "Use Compression"); - Assert.True(ConnectionState.Closed == c.State, "State"); + Assert.That(15 == c.ConnectionTimeout, "ConnectionTimeout"); + Assert.That("mydb" == c.Database, "Database"); + Assert.That("myserver2" == c.DataSource, "DataSource"); + Assert.That(true == c.UseCompression, "Use Compression"); + Assert.That(ConnectionState.Closed == c.State, "State"); // Bug #30791289 - MYSQLCONNECTION(NULL) NOW THROWS NULLREFERENCEEXCEPTION var conn = new MySqlConnection($"server={Host};"); conn.ConnectionString = null; - Assert.AreEqual(string.Empty, conn.ConnectionString); + Assert.That(conn.ConnectionString, Is.EqualTo(string.Empty)); } [Test] @@ -91,12 +91,12 @@ public void ChangeDatabase() using (c) { c.Open(); - Assert.True(c.State == ConnectionState.Open); - Assert.AreEqual(connStr.Database, c.Database); + Assert.That(c.State == ConnectionState.Open); + Assert.That(c.Database, Is.EqualTo(connStr.Database)); string dbName = CreateDatabase("db1"); c.ChangeDatabase(dbName); - Assert.AreEqual(dbName, c.Database); + Assert.That(c.Database, Is.EqualTo(dbName)); } } @@ -110,7 +110,7 @@ public void ConnectionPoolExhaustion() { var ex = Assert.Catch(() => CreateCommandTimeoutException()); //Prior to the fix the exception thrown was 'error connecting: Timeout expired. The timeout period elapsed prior to obtaining a connection from the pool. This may have occurred because all pooled connections were in use and max pool size was reached.' after the 10th execution. - Assert.AreEqual("Fatal error encountered during command execution.", ex.Message); + Assert.That(ex.Message, Is.EqualTo("Fatal error encountered during command execution.")); } } @@ -197,8 +197,8 @@ public void ConnectingAsUTF8() MySqlCommand cmd2 = new MySqlCommand("SELECT id, active FROM test", d); using (MySqlDataReader reader = cmd2.ExecuteReader()) { - Assert.True(reader.Read()); - Assert.True(reader.GetBoolean(1)); + Assert.That(reader.Read()); + Assert.That(reader.GetBoolean(1)); } } } @@ -211,8 +211,8 @@ public void PingUpdatesState() { var conn2 = GetConnection(); KillConnection(conn2); - Assert.False(conn2.Ping()); - Assert.True(conn2.State == ConnectionState.Closed); + Assert.That(conn2.Ping(), Is.False); + Assert.That(conn2.State == ConnectionState.Closed); conn2.Open(); conn2.Close(); } @@ -245,7 +245,7 @@ public void TestConnectingSocketBadHostName() connStr.Server = "badHostName"; MySqlConnection c = new MySqlConnection(connStr.GetConnectionString(true)); var ex = Assert.Throws(() => c.Open()); - if (Platform.IsWindows()) Assert.IsTrue(ex.InnerException.GetType() == typeof(ArgumentException)); + if (Platform.IsWindows()) Assert.That(ex.InnerException.GetType() == typeof(ArgumentException)); } /// @@ -265,7 +265,7 @@ public void ConnectionStringNotAffectedByChangeDatabase() c.Open(); string str = c.ConnectionString; int index = str.IndexOf("Database="); - Assert.AreEqual(-1, index); + Assert.That(index, Is.EqualTo(-1)); } } } @@ -284,12 +284,12 @@ public void ConnectionCloseByGC() c.Open(); threadId = c.ServerThread; WeakReference wr = new WeakReference(c); - Assert.True(wr.IsAlive); + Assert.That(wr.IsAlive); c = null; GC.Collect(); GC.WaitForPendingFinalizers(); - Assert.False(wr.IsAlive); - Assert.True(check.closed); + Assert.That(wr.IsAlive, Is.False); + Assert.That(check.closed); MySqlCommand cmd = new MySqlCommand("KILL " + threadId, Connection); cmd.ExecuteNonQuery(); @@ -366,10 +366,10 @@ public async Task TransactionAsync() MySqlTransaction txn = await Connection.BeginTransactionAsync(); MySqlConnection c = txn.Connection; - Assert.AreEqual(Connection, c); + Assert.That(c, Is.EqualTo(Connection)); MySqlCommand cmd = new MySqlCommand("SELECT name, name2 FROM TranAsyncTest WHERE key2='P'", Connection, txn); MySqlTransaction t2 = cmd.Transaction; - Assert.AreEqual(txn, t2); + Assert.That(t2, Is.EqualTo(txn)); MySqlDataReader reader = null; try { @@ -379,7 +379,7 @@ public async Task TransactionAsync() } catch (Exception ex) { - Assert.False(ex.Message != string.Empty, ex.Message); + Assert.That(ex.Message != string.Empty, Is.False, ex.Message); txn.Rollback(); } finally @@ -407,9 +407,9 @@ public async Task OpenAndCloseConnectionAsync() { var conn = new MySqlConnection(Connection.ConnectionString); await conn.OpenAsync(); - Assert.True(conn.State == ConnectionState.Open); + Assert.That(conn.State == ConnectionState.Open); await conn.CloseAsync(); - Assert.True(conn.State == ConnectionState.Closed); + Assert.That(conn.State == ConnectionState.Closed); } [Test] @@ -442,7 +442,7 @@ public async Task ClearAllPoolsAsync() public async Task GetSchemaCollectionAsync() { var schemaColl = await Connection.GetSchemaCollectionAsync("MetaDataCollections", null); - Assert.NotNull(schemaColl); + Assert.That(schemaColl, Is.Not.Null); } #endregion @@ -481,7 +481,7 @@ public void TestPersistSecurityInfoCachingPasswords() c.Open(); c.Close(); MySqlConnectionStringBuilder afterOpenSettings = new MySqlConnectionStringBuilder(c.ConnectionString); - Assert.AreEqual(connStr.Password, afterOpenSettings.Password); + Assert.That(afterOpenSettings.Password, Is.EqualTo(connStr.Password)); // Persist Security Info = false means that it should not be returned connStr.PersistSecurityInfo = false; @@ -489,7 +489,7 @@ public void TestPersistSecurityInfoCachingPasswords() c.Open(); c.Close(); afterOpenSettings = new MySqlConnectionStringBuilder(c.ConnectionString); - Assert.True(String.IsNullOrEmpty(afterOpenSettings.Password)); + Assert.That(String.IsNullOrEmpty(afterOpenSettings.Password)); } /// @@ -505,48 +505,48 @@ public void CloneConnectionDisclosePassword() MySqlConnection c = new MySqlConnection(connStr.ConnectionString); // The password, is not returned as part of the connection if the connection is open or has ever been in an open state - StringAssert.Contains("password", c.ConnectionString); + Assert.That(c.ConnectionString, Does.Contain("password")); // After open password should not be displayed c.Open(); - StringAssert.DoesNotContain("password", c.ConnectionString); + Assert.That(c.ConnectionString, Does.Not.Contain("password")); // Verify clone from open connection should not show password var cloneConnection = (MySqlConnection)c.Clone(); - StringAssert.DoesNotContain("password", cloneConnection.ConnectionString); + Assert.That(cloneConnection.ConnectionString, Does.Not.Contain("password")); // After close connection the password should not be displayed c.Close(); - StringAssert.DoesNotContain("password", c.ConnectionString); + Assert.That(c.ConnectionString, Does.Not.Contain("password")); // Verify clone connection doesn't show password after open connection cloneConnection.Open(); - StringAssert.DoesNotContain("password", cloneConnection.ConnectionString); + Assert.That(cloneConnection.ConnectionString, Does.Not.Contain("password")); // Verify clone connection doesn't show password after close connection cloneConnection.Close(); - StringAssert.DoesNotContain("password", cloneConnection.ConnectionString); + Assert.That(cloneConnection.ConnectionString, Does.Not.Contain("password")); // Verify password for a clone of closed connection, password should appears var closedConnection = new MySqlConnection(connStr.ConnectionString); var cloneClosed = (MySqlConnection)closedConnection.Clone(); - StringAssert.Contains("password", cloneClosed.ConnectionString); + Assert.That(cloneClosed.ConnectionString, Does.Contain("password")); // Open connection of a closed connection clone, password should be empty - Assert.False(cloneClosed.hasBeenOpen); + Assert.That(cloneClosed.hasBeenOpen, Is.False); cloneClosed.Open(); - StringAssert.DoesNotContain("password", cloneClosed.ConnectionString); - Assert.True(cloneClosed.hasBeenOpen); + Assert.That(cloneClosed.ConnectionString, Does.Not.Contain("password")); + Assert.That(cloneClosed.hasBeenOpen); // Close connection of a closed connection clone, password should be empty cloneClosed.Close(); - StringAssert.DoesNotContain("password", cloneClosed.ConnectionString); + Assert.That(cloneClosed.ConnectionString, Does.Not.Contain("password")); // Clone Password shloud be present if PersistSecurityInfo is true connStr.PersistSecurityInfo = true; c = new MySqlConnection(connStr.ConnectionString); cloneConnection = (MySqlConnection)c.Clone(); - StringAssert.Contains("password", cloneConnection.ConnectionString); + Assert.That(cloneConnection.ConnectionString, Does.Contain("password")); } [Test] @@ -561,9 +561,9 @@ public void ConnectionTimeout() DateTime start = DateTime.Now; var ex = Assert.Throws(() => c.Open()); - Assert.True(ex.InnerException.InnerException is TimeoutException); + Assert.That(ex.InnerException.InnerException is TimeoutException); TimeSpan diff = DateTime.Now.Subtract(start); - Assert.True(diff.TotalSeconds < 6, $"Timeout exceeded: {diff.TotalSeconds}"); + Assert.That(diff.TotalSeconds < 6, $"Timeout exceeded: {diff.TotalSeconds}"); } [Test] @@ -624,12 +624,12 @@ public void PersistSecurityInfo() MySqlConnectionStringBuilder connStr = new MySqlConnectionStringBuilder(Connection.ConnectionString); connStr.PersistSecurityInfo = false; - Assert.False(String.IsNullOrEmpty(connStr.Password)); + Assert.That(String.IsNullOrEmpty(connStr.Password), Is.False); MySqlConnection c = new MySqlConnection(connStr.GetConnectionString(true)); c.Open(); c.Close(); connStr = new MySqlConnectionStringBuilder(c.ConnectionString); - Assert.True(String.IsNullOrEmpty(connStr.Password)); + Assert.That(String.IsNullOrEmpty(connStr.Password)); } /// @@ -657,13 +657,13 @@ public void CanOpenConnectionAfterAborting() { MySqlConnection connection = new MySqlConnection(Connection.ConnectionString); connection.Open(); - Assert.AreEqual(ConnectionState.Open, connection.State); + Assert.That(connection.State, Is.EqualTo(ConnectionState.Open)); connection.AbortAsync(false).GetAwaiter().GetResult(); - Assert.AreEqual(ConnectionState.Closed, connection.State); + Assert.That(connection.State, Is.EqualTo(ConnectionState.Closed)); connection.Open(); - Assert.AreEqual(ConnectionState.Open, connection.State); + Assert.That(connection.State, Is.EqualTo(ConnectionState.Open)); connection.Close(); } @@ -681,7 +681,7 @@ public void ConnectAttributes() MySqlCommand cmd = new MySqlCommand("SELECT * FROM performance_schema.session_connect_attrs WHERE PROCESSLIST_ID = connection_id()", Connection); MySqlDataReader dr = cmd.ExecuteReader(); - Assert.True(dr.HasRows, "No session_connect_attrs found"); + Assert.That(dr.HasRows, "No session_connect_attrs found"); MySqlConnectAttrs connectAttrs = new MySqlConnectAttrs(); bool isValidated = false; using (dr) @@ -690,13 +690,13 @@ public void ConnectAttributes() { if (dr.GetString(1).ToLowerInvariant().Contains("_client_name")) { - Assert.AreEqual(connectAttrs.ClientName, dr.GetString(2)); + Assert.That(dr.GetString(2), Is.EqualTo(connectAttrs.ClientName)); isValidated = true; break; } } } - Assert.True(isValidated, "Missing _client_name attribute"); + Assert.That(isValidated, "Missing _client_name attribute"); } /// @@ -727,7 +727,7 @@ public void PasswordExpiration() cmd.CommandText = "SELECT 1"; MySqlException ex = Assert.Throws(() => cmd.ExecuteScalar()); - Assert.AreEqual(1820, ex.Number); + Assert.That(ex.Number, Is.EqualTo(1820)); if (Version >= new Version(5, 7, 6)) cmd.CommandText = string.Format("SET PASSWORD = '{0}1'", _EXPIRED_USER); @@ -754,7 +754,7 @@ public void TestNonSupportedOptions() using (MySqlConnection c = new MySqlConnection(connstr)) { c.Open(); - Assert.AreEqual(ConnectionState.Open, c.State); + Assert.That(c.State, Is.EqualTo(ConnectionState.Open)); } } @@ -773,7 +773,7 @@ public void IPv6Connection() using (MySqlConnection conn = new MySqlConnection(sb.ToString())) { conn.Open(); - Assert.AreEqual(ConnectionState.Open, conn.State); + Assert.That(conn.State, Is.EqualTo(ConnectionState.Open)); } } @@ -793,10 +793,10 @@ public void ExpiredPassword(string sql) using (MySqlConnection conn = new MySqlConnection(sb.ConnectionString)) { conn.Open(); - Assert.AreEqual(ConnectionState.Open, conn.State); + Assert.That(conn.State, Is.EqualTo(ConnectionState.Open)); MySqlCommand cmd = new MySqlCommand(sql, conn); var ex = Assert.Throws(() => cmd.ExecuteNonQuery()); - Assert.AreEqual(1820, ex.Number); + Assert.That(ex.Number, Is.EqualTo(1820)); } } @@ -835,7 +835,7 @@ public void ExpiredPwdWithOldPassword() { conn.Open(); MySqlCommand cmd = new MySqlCommand("SELECT 8", conn); - StringAssert.StartsWith("8", cmd.ExecuteScalar().ToString()); + Assert.That(cmd.ExecuteScalar().ToString(), Does.StartWith("8")); } sb.Password = expiredPwd; @@ -869,7 +869,7 @@ public void ConnectUsingNamedPipes() // Named Pipes connection protocol is not allowed to use SSL connections. using var conn = new MySqlConnection(sb.ConnectionString); var ex = Assert.Throws(() => conn.Open()); - StringAssert.AreEqualIgnoringCase(string.Format(Resources.SslNotAllowedForConnectionProtocol, sb.ConnectionProtocol), ex.Message); + Assert.That(ex.Message, Is.EqualTo(string.Format(Resources.SslNotAllowedForConnectionProtocol, sb.ConnectionProtocol)).IgnoreCase); } /// @@ -941,7 +941,7 @@ public void ConnectUsingSharedMemory() using (var conn = new MySqlConnection(sb.ConnectionString)) { conn.Open(); - Assert.AreEqual(ConnectionState.Open, conn.State); + Assert.That(conn.State, Is.EqualTo(ConnectionState.Open)); } // Shared Memory connection protocol is not allowed to use SSL connections. @@ -949,7 +949,7 @@ public void ConnectUsingSharedMemory() using (var conn = new MySqlConnection(sb.ConnectionString)) { var ex = Assert.Throws(() => conn.Open()); - StringAssert.AreEqualIgnoringCase(string.Format(Resources.SslNotAllowedForConnectionProtocol, sb.ConnectionProtocol), ex.Message); + Assert.That(ex.Message, Is.EqualTo(string.Format(Resources.SslNotAllowedForConnectionProtocol, sb.ConnectionProtocol)).IgnoreCase); } } @@ -1199,7 +1199,7 @@ public void MediumTextMalformedPkg() string fullQuery = string.Format(query, sb.ToString(0, sb.Length - 2)); var res = MySqlHelper.ExecuteNonQuery(Connection.ConnectionString + ";ssl-mode=none", fullQuery, mySqlParameters.ToArray()); - Assert.AreEqual(res, 40000); + Assert.That(40000, Is.EqualTo(res)); ExecuteSQL("SET GLOBAL max_allowed_packet=1024000"); ExecuteSQL($"DROP TABLE `{Settings.Database}`.`testmalformed`;"); @@ -1225,9 +1225,9 @@ public void CompressionUnit() { if (i == 0) { - Assert.AreEqual("ON", reader.GetString(1)); + Assert.That(reader.GetString(1), Is.EqualTo("ON")); } - Assert.IsNotNull(reader.GetString(1)); + Assert.That(reader.GetString(1), Is.Not.Null); i++; } } @@ -1242,7 +1242,7 @@ public void CompressionUnit() { while (reader.Read()) { - Assert.IsNotNull(reader.GetString(0)); + Assert.That(reader.GetString(0), Is.Not.Null); i++; } } @@ -1266,9 +1266,9 @@ public void CompressionUnit() { if (i == 0) { - Assert.AreEqual("OFF", reader.GetString(1)); + Assert.That(reader.GetString(1), Is.EqualTo("OFF")); } - Assert.IsNotNull(reader.GetString(1)); + Assert.That(reader.GetString(1), Is.Not.Null); i++; } } @@ -1284,7 +1284,7 @@ public void CompressionUnit() { while (reader.Read()) { - Assert.IsNotNull(reader.GetString(0)); + Assert.That(reader.GetString(0), Is.Not.Null); i++; } } @@ -1310,7 +1310,7 @@ public void CompressionValidationInClassicProtocol() } dbConn.Open(); - Assert.AreEqual(ConnectionState.Open, dbConn.State); + Assert.That(dbConn.State, Is.EqualTo(ConnectionState.Open)); MySqlCommand cmd = new MySqlCommand(); cmd.Connection = dbConn; cmd.CommandText = "select * from performance_schema.session_status where variable_name like 'COMPRESSION%' order by 1"; @@ -1327,14 +1327,14 @@ public void CompressionValidationInClassicProtocol() { // Compression should have been set to OFF as UseCompression is set to True in connection string but server is // started with uncompressed and uncompressed/zstd - Assert.AreEqual("OFF", reader.GetString(1)); + Assert.That(reader.GetString(1), Is.EqualTo("OFF")); } else { - Assert.AreEqual("ON", reader.GetString(1)); + Assert.That(reader.GetString(1), Is.EqualTo("ON")); } } - Assert.IsNotNull(reader.GetString(1)); + Assert.That(reader.GetString(1), Is.Not.Null); i++; } } @@ -1349,7 +1349,7 @@ public void CompressionValidationInClassicProtocol() { while (reader.Read()) { - Assert.AreEqual(compressionAlgorithms[k], reader.GetString(0)); + Assert.That(reader.GetString(0), Is.EqualTo(compressionAlgorithms[k])); i++; } } @@ -1380,7 +1380,7 @@ public void CompressionValidationInClassicProtocol() } dbConn.Open(); - Assert.AreEqual(ConnectionState.Open, dbConn.State); + Assert.That(dbConn.State, Is.EqualTo(ConnectionState.Open)); MySqlCommand cmd = new MySqlCommand(); cmd.Connection = dbConn; cmd.CommandText = "select * from performance_schema.session_status where variable_name like 'COMPRESSION%' order by 1"; @@ -1393,9 +1393,9 @@ public void CompressionValidationInClassicProtocol() { if (i == 0) { - Assert.AreEqual("OFF", reader.GetString(1)); + Assert.That(reader.GetString(1), Is.EqualTo("OFF")); } - Assert.IsNotNull(reader.GetString(1)); + Assert.That(reader.GetString(1), Is.Not.Null); i++; } } @@ -1410,7 +1410,7 @@ public void CompressionValidationInClassicProtocol() { while (reader.Read()) { - Assert.AreEqual(compressionAlgorithms[k], reader.GetString(0)); + Assert.That(reader.GetString(0), Is.EqualTo(compressionAlgorithms[k])); i++; } } @@ -1514,7 +1514,7 @@ public void ExpiredPasswordBug3() using (MySqlConnection conn = new MySqlConnection(sb.ConnectionString)) { conn.Open(); - Assert.True(conn.IsPasswordExpired); + Assert.That(conn.IsPasswordExpired); } ExecuteSQL($"ALTER USER '{_EXPIRED_USER}'@'{host}' Identified BY '{_newPwd}'"); @@ -1532,9 +1532,9 @@ public void ExpiredPasswordBug3() using (var rdr = cmd.ExecuteReader()) { while (rdr.Read()) - Assert.IsNotNull(rdr[0].ToString()); + Assert.That(rdr[0].ToString(), Is.Not.Null); } - Assert.False(conn.IsPasswordExpired); + Assert.That(conn.IsPasswordExpired, Is.False); } } @@ -1556,7 +1556,7 @@ public void ExpiredPasswordBug4() using (MySqlConnection conn = new MySqlConnection(sb.ConnectionString)) { conn.Open(); - Assert.True(conn.IsPasswordExpired); + Assert.That(conn.IsPasswordExpired); } ExecuteSQL($"set password for {expiredFull}='{_newPwd}'"); @@ -1575,9 +1575,9 @@ public void ExpiredPasswordBug4() using (var rdr = cmd.ExecuteReader()) { while (rdr.Read()) - Assert.IsNotNull(rdr[0].ToString()); + Assert.That(rdr[0].ToString(), Is.Not.Null); } - Assert.False(conn.IsPasswordExpired); + Assert.That(conn.IsPasswordExpired, Is.False); } sb.UserID = _EXPIRED_USER; @@ -1598,7 +1598,7 @@ public void InvalidConnectTimeoutParameter() connStr = $"server={Settings.Server};user={Settings.UserID};port={Settings.Port};password={Settings.Password};connectiontimeout=10000"; using (var conn = new MySqlConnection(connStr)) { - Assert.IsInstanceOf(conn); + Assert.That(conn, Is.InstanceOf()); } } @@ -1607,9 +1607,9 @@ public void ConnectionDispose() { MySqlConnection conn = new MySqlConnection(Settings.ConnectionString); conn.Open(); - Assert.AreEqual(ConnectionState.Open, conn.connectionState); + Assert.That(conn.connectionState, Is.EqualTo(ConnectionState.Open)); conn.Dispose(); - Assert.AreEqual(ConnectionState.Closed, conn.connectionState); + Assert.That(conn.connectionState, Is.EqualTo(ConnectionState.Closed)); } [Test] @@ -1620,7 +1620,7 @@ public void ConnectionPasswordException() using (var conn = new MySqlConnection(myConnectionString)) { conn.Open(); - Assert.AreEqual(ConnectionState.Open, conn.State); + Assert.That(conn.State, Is.EqualTo(ConnectionState.Open)); } myConnectionString = $"server={Host};user={Settings.UserID};port={Port};password=wrong"; @@ -1628,7 +1628,7 @@ public void ConnectionPasswordException() { var ex = Assert.Throws(() => conn.Open()); code = ((MySqlException)ex.GetBaseException()).Number; - Assert.AreEqual(1045, code); + Assert.That(code, Is.EqualTo(1045)); } } @@ -1727,7 +1727,7 @@ private void ExecuteQueriesSuccess(string sql, string password) using (MySqlConnection conn = new MySqlConnection(sb.ConnectionString)) { conn.Open(); - Assert.AreEqual(ConnectionState.Open, conn.State); + Assert.That(conn.State, Is.EqualTo(ConnectionState.Open)); MySqlCommand cmd = new MySqlCommand(sql, conn); cmd.ExecuteNonQuery(); } @@ -1742,7 +1742,7 @@ private void ExecuteQueriesFail(string sql, string user, string password) using (MySqlConnection conn = new MySqlConnection(sb.ConnectionString)) { conn.Open(); - Assert.AreEqual(ConnectionState.Open, conn.State); + Assert.That(conn.State, Is.EqualTo(ConnectionState.Open)); MySqlCommand cmd = new MySqlCommand(sql, conn); Assert.Throws(() => cmd.ExecuteNonQuery()); } @@ -1758,7 +1758,7 @@ private void SetupExpirePasswordExecuteQueriesFail(string sql, string password) using (MySqlConnection conn = new MySqlConnection(sb.ConnectionString)) { conn.Open(); - Assert.AreEqual(ConnectionState.Open, conn.State); + Assert.That(conn.State, Is.EqualTo(ConnectionState.Open)); MySqlCommand cmd = new MySqlCommand(sql, conn); Assert.Throws(() => cmd.ExecuteNonQuery()); } diff --git a/MySQL.Data/tests/MySql.Data.Tests/DataTypeTests.cs b/MySQL.Data/tests/MySql.Data.Tests/DataTypeTests.cs index 25b9e198c..acb1cea84 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/DataTypeTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/DataTypeTests.cs @@ -65,19 +65,19 @@ private void InternalBytesAndBooleans(bool prepare) if (prepare) cmd.Prepare(); using (MySqlDataReader reader = cmd.ExecuteReader()) { - Assert.True(reader.Read()); + Assert.That(reader.Read()); Assert.Throws(() => reader.GetByte(0)); - Assert.AreEqual(140, reader.GetByte(1)); - Assert.True(reader.GetBoolean(1)); - Assert.AreEqual(20, Convert.ToInt32(reader.GetUInt32(2))); - Assert.AreEqual(20, reader.GetInt32(2)); + Assert.That(reader.GetByte(1), Is.EqualTo(140)); + Assert.That(reader.GetBoolean(1)); + Assert.That(Convert.ToInt32(reader.GetUInt32(2)), Is.EqualTo(20)); + Assert.That(reader.GetInt32(2), Is.EqualTo(20)); - Assert.True(reader.Read()); - Assert.AreEqual(0, reader.GetByte(0)); - Assert.AreEqual(0, reader.GetByte(1)); - Assert.False(reader.GetBoolean(1)); + Assert.That(reader.Read()); + Assert.That(reader.GetByte(0), Is.EqualTo(0)); + Assert.That(reader.GetByte(1), Is.EqualTo(0)); + Assert.That(reader.GetBoolean(1), Is.False); - Assert.False(reader.Read()); + Assert.That(reader.Read(), Is.False); } } @@ -98,21 +98,21 @@ public void TreatTinyAsBool() ExecuteSQL("INSERT INTO Test2 VALUES(0)"); ExecuteSQL("INSERT INTO Test2 VALUES(2)"); MySqlConnectionStringBuilder builder = new MySqlConnectionStringBuilder(Connection.ConnectionString); - Assert.True(builder.TreatTinyAsBoolean); + Assert.That(builder.TreatTinyAsBoolean); MySqlCommand cmd = new MySqlCommand("SELECT * from Test2", Connection); using (MySqlDataReader reader = cmd.ExecuteReader()) { bool b; - Assert.True(reader.Read()); + Assert.That(reader.Read()); b = (bool)reader.GetValue(0); - Assert.True(b); - Assert.True(reader.Read()); + Assert.That(b); + Assert.That(reader.Read()); b = (bool)reader.GetValue(0); - Assert.False(b); - Assert.True(reader.Read()); + Assert.That(b, Is.False); + Assert.That(reader.Read()); b = (bool)reader.GetValue(0); - Assert.True(b); + Assert.That(b); } } @@ -142,28 +142,28 @@ private void InternalTestFloats(bool prepared) if (prepared) cmd.Prepare(); int count = cmd.ExecuteNonQuery(); - Assert.AreEqual(1, count); + Assert.That(count, Is.EqualTo(1)); cmd.Parameters[0].Value = 1.5; cmd.Parameters[1].Value = 47.85; cmd.Parameters[2].Value = 123.85; count = cmd.ExecuteNonQuery(); - Assert.AreEqual(1, count); + Assert.That(count, Is.EqualTo(1)); cmd.CommandText = "SELECT * FROM Test"; if (prepared) cmd.Prepare(); using (MySqlDataReader reader = cmd.ExecuteReader()) { - Assert.True(reader.Read()); - Assert.True((decimal)2.3 == (decimal)reader.GetFloat(0)); - Assert.AreEqual(4.6, reader.GetDouble(1)); - Assert.True((decimal)23.82 == reader.GetDecimal(2)); - - Assert.True(reader.Read()); - Assert.True((decimal)1.5 == (decimal)reader.GetFloat(0)); - Assert.AreEqual(47.85, reader.GetDouble(1)); - Assert.True((decimal)123.85 == reader.GetDecimal(2)); + Assert.That(reader.Read()); + Assert.That((decimal)2.3 == (decimal)reader.GetFloat(0)); + Assert.That(reader.GetDouble(1), Is.EqualTo(4.6)); + Assert.That((decimal)23.82 == reader.GetDecimal(2)); + + Assert.That(reader.Read()); + Assert.That((decimal)1.5 == (decimal)reader.GetFloat(0)); + Assert.That(reader.GetDouble(1), Is.EqualTo(47.85)); + Assert.That((decimal)123.85 == reader.GetDecimal(2)); } } @@ -183,20 +183,20 @@ public void TestTime() reader.Read(); object value = reader["tm"]; - Assert.AreEqual(typeof(TimeSpan), value.GetType()); + Assert.That(value.GetType(), Is.EqualTo(typeof(TimeSpan))); TimeSpan ts = (TimeSpan)reader["tm"]; - Assert.AreEqual(0, ts.Hours); - Assert.AreEqual(0, ts.Minutes); - Assert.AreEqual(0, ts.Seconds); + Assert.That(ts.Hours, Is.EqualTo(0)); + Assert.That(ts.Minutes, Is.EqualTo(0)); + Assert.That(ts.Seconds, Is.EqualTo(0)); reader.Read(); value = reader["tm"]; - Assert.AreEqual(typeof(TimeSpan), value.GetType()); + Assert.That(value.GetType(), Is.EqualTo(typeof(TimeSpan))); ts = (TimeSpan)reader["tm"]; - Assert.AreEqual(21, ts.Days); - Assert.AreEqual(8, ts.Hours); - Assert.AreEqual(45, ts.Minutes); - Assert.AreEqual(17, ts.Seconds); + Assert.That(ts.Days, Is.EqualTo(21)); + Assert.That(ts.Hours, Is.EqualTo(8)); + Assert.That(ts.Minutes, Is.EqualTo(45)); + Assert.That(ts.Seconds, Is.EqualTo(17)); } } @@ -214,13 +214,13 @@ public void YearType() using (MySqlDataReader reader = cmd.ExecuteReader()) { reader.Read(); - Assert.True(1998 == reader.GetUInt32(0)); + Assert.That(1998 == reader.GetUInt32(0)); reader.Read(); - Assert.True(1990 == reader.GetUInt32(0)); + Assert.That(1990 == reader.GetUInt32(0)); reader.Read(); - Assert.True(2004 == reader.GetUInt32(0)); + Assert.That(2004 == reader.GetUInt32(0)); reader.Read(); - Assert.True(0 == reader.GetUInt32(0)); + Assert.That(0 == reader.GetUInt32(0)); } } @@ -228,16 +228,16 @@ public void YearType() public void TypeCoercion() { MySqlParameter p = new MySqlParameter("?test", 1); - Assert.AreEqual(DbType.Int32, p.DbType); - Assert.AreEqual(MySqlDbType.Int32, p.MySqlDbType); + Assert.That(p.DbType, Is.EqualTo(DbType.Int32)); + Assert.That(p.MySqlDbType, Is.EqualTo(MySqlDbType.Int32)); p.DbType = DbType.Int64; - Assert.AreEqual(DbType.Int64, p.DbType); - Assert.AreEqual(MySqlDbType.Int64, p.MySqlDbType); + Assert.That(p.DbType, Is.EqualTo(DbType.Int64)); + Assert.That(p.MySqlDbType, Is.EqualTo(MySqlDbType.Int64)); p.MySqlDbType = MySqlDbType.Int16; - Assert.AreEqual(DbType.Int16, p.DbType); - Assert.AreEqual(MySqlDbType.Int16, p.MySqlDbType); + Assert.That(p.DbType, Is.EqualTo(DbType.Int16)); + Assert.That(p.MySqlDbType, Is.EqualTo(MySqlDbType.Int16)); } [Test] @@ -288,18 +288,18 @@ public void BitAndDecimal() MySqlCommand cmd = new MySqlCommand("SELECT * FROM Test", c); using (MySqlDataReader reader = cmd.ExecuteReader()) { - Assert.True(reader.Read()); - Assert.AreEqual(2, reader.GetInt32(0)); - Assert.AreEqual(3, reader.GetInt32(1)); - Assert.AreEqual(120, reader.GetInt32(2)); - Assert.AreEqual(240, reader.GetInt32(3)); - Assert.AreEqual(1000, reader.GetInt32(4)); - Assert.True(reader.Read()); - Assert.True(reader.IsDBNull(0)); - Assert.True(reader.IsDBNull(1)); - Assert.AreEqual(100, reader.GetInt32(2)); - Assert.True(reader.IsDBNull(3)); - Assert.True(reader.IsDBNull(4)); + Assert.That(reader.Read()); + Assert.That(reader.GetInt32(0), Is.EqualTo(2)); + Assert.That(reader.GetInt32(1), Is.EqualTo(3)); + Assert.That(reader.GetInt32(2), Is.EqualTo(120)); + Assert.That(reader.GetInt32(3), Is.EqualTo(240)); + Assert.That(reader.GetInt32(4), Is.EqualTo(1000)); + Assert.That(reader.Read()); + Assert.That(reader.IsDBNull(0)); + Assert.That(reader.IsDBNull(1)); + Assert.That(reader.GetInt32(2), Is.EqualTo(100)); + Assert.That(reader.IsDBNull(3)); + Assert.That(reader.IsDBNull(4)); } } } @@ -311,24 +311,24 @@ public void DecimalTests() MySqlCommand cmd = new MySqlCommand("INSERT INTO Test VALUES(?dec)", Connection); cmd.Parameters.AddWithValue("?dec", (decimal)2.4); - Assert.AreEqual(1, cmd.ExecuteNonQuery()); + Assert.That(cmd.ExecuteNonQuery(), Is.EqualTo(1)); cmd.Prepare(); - Assert.AreEqual(1, cmd.ExecuteNonQuery()); + Assert.That(cmd.ExecuteNonQuery(), Is.EqualTo(1)); cmd.CommandText = "SELECT * FROM Test"; using (MySqlDataReader reader = cmd.ExecuteReader()) { - Assert.True(reader.Read()); - Assert.True(reader[0] is Decimal); - Assert.AreEqual((decimal)2.4, Convert.ToDecimal(reader[0])); + Assert.That(reader.Read()); + Assert.That(reader[0] is Decimal); + Assert.That(Convert.ToDecimal(reader[0]), Is.EqualTo((decimal)2.4)); - Assert.True(reader.Read()); - Assert.True(reader[0] is Decimal); - Assert.AreEqual((decimal)2.4, Convert.ToDecimal(reader[0])); + Assert.That(reader.Read()); + Assert.That(reader[0] is Decimal); + Assert.That(Convert.ToDecimal(reader[0]), Is.EqualTo((decimal)2.4)); - Assert.False(reader.Read()); - Assert.False(reader.NextResult()); + Assert.That(reader.Read(), Is.False); + Assert.That(reader.NextResult(), Is.False); } } @@ -339,24 +339,24 @@ public void DecimalTests2() MySqlCommand cmd = new MySqlCommand("INSERT INTO Test VALUES(?dec)", Connection); cmd.Parameters.AddWithValue("?dec", (decimal)2.4); - Assert.AreEqual(1, cmd.ExecuteNonQuery()); + Assert.That(cmd.ExecuteNonQuery(), Is.EqualTo(1)); cmd.Prepare(); - Assert.AreEqual(1, cmd.ExecuteNonQuery()); + Assert.That(cmd.ExecuteNonQuery(), Is.EqualTo(1)); cmd.CommandText = "SELECT * FROM Test"; using (MySqlDataReader reader = cmd.ExecuteReader()) { - Assert.True(reader.Read()); - Assert.True(reader[0] is Decimal); - Assert.AreEqual((decimal)2.4, Convert.ToDecimal(reader[0])); + Assert.That(reader.Read()); + Assert.That(reader[0] is Decimal); + Assert.That(Convert.ToDecimal(reader[0]), Is.EqualTo((decimal)2.4)); - Assert.True(reader.Read()); - Assert.True(reader[0] is Decimal); - Assert.AreEqual((decimal)2.4, Convert.ToDecimal(reader[0])); + Assert.That(reader.Read()); + Assert.That(reader[0] is Decimal); + Assert.That(Convert.ToDecimal(reader[0]), Is.EqualTo((decimal)2.4)); - Assert.False(reader.Read()); - Assert.False(reader.NextResult()); + Assert.That(reader.Read(), Is.False); + Assert.That(reader.NextResult(), Is.False); } } @@ -379,10 +379,10 @@ public void Bit() cmd.Prepare(); using (MySqlDataReader reader = cmd.ExecuteReader()) { - Assert.True(reader.Read()); - Assert.AreEqual(1, Convert.ToInt32(reader[0])); - Assert.AreEqual(2, Convert.ToInt32(reader[1])); - Assert.AreEqual(3, Convert.ToInt32(reader[2])); + Assert.That(reader.Read()); + Assert.That(Convert.ToInt32(reader[0]), Is.EqualTo(1)); + Assert.That(Convert.ToInt32(reader[1]), Is.EqualTo(2)); + Assert.That(Convert.ToInt32(reader[2]), Is.EqualTo(3)); } } @@ -400,10 +400,10 @@ public void UsingInt24InPreparedStatement(bool prepare, int value) command.Parameters.AddWithValue("@data", value).MySqlDbType = MySqlDbType.Int24; if (prepare) command.Prepare(); var rowsAffected = command.ExecuteNonQuery(); - Assert.AreEqual(1, rowsAffected); + Assert.That(rowsAffected, Is.EqualTo(1)); command.CommandText = "SELECT data FROM Test"; var data = command.ExecuteScalar(); - Assert.AreEqual(value, data); + Assert.That(data, Is.EqualTo(value)); } } @@ -438,9 +438,9 @@ public void TestNegativeTime() { reader.Read(); TimeSpan ts = reader.GetTimeSpan("t"); - Assert.AreEqual(-7, ts.Hours); - Assert.AreEqual(-24, ts.Minutes); - Assert.AreEqual(0, ts.Seconds); + Assert.That(ts.Hours, Is.EqualTo(-7)); + Assert.That(ts.Minutes, Is.EqualTo(-24)); + Assert.That(ts.Seconds, Is.EqualTo(0)); } } @@ -456,9 +456,9 @@ public void BinaryAndVarBinary() reader.Read(); byte[] buffer = new byte[2]; long read = reader.GetBytes(0, 0, buffer, 0, 2); - Assert.AreEqual('s', (char)buffer[0]); - Assert.AreEqual('o', (char)buffer[1]); - Assert.AreEqual(2, read); + Assert.That((char)buffer[0], Is.EqualTo('s')); + Assert.That((char)buffer[1], Is.EqualTo('o')); + Assert.That(read, Is.EqualTo(2)); } } @@ -470,10 +470,10 @@ public void NumericAsBinary() using (MySqlDataReader reader = cmd.ExecuteReader()) { reader.Read(); - Assert.AreEqual("BIGINT", reader.GetDataTypeName(0)); - Assert.AreEqual(typeof(Int64), reader.GetFieldType(0)); - Assert.AreEqual("System.Int64", reader.GetValue(0).GetType().FullName); - Assert.AreEqual(0, Convert.ToInt32(reader.GetValue(0))); + Assert.That(reader.GetDataTypeName(0), Is.EqualTo("BIGINT")); + Assert.That(reader.GetFieldType(0), Is.EqualTo(typeof(Int64))); + Assert.That(reader.GetValue(0).GetType().FullName, Is.EqualTo("System.Int64")); + Assert.That(Convert.ToInt32(reader.GetValue(0)), Is.EqualTo(0)); } } @@ -487,11 +487,11 @@ public void BinaryTypes() using (var reader = cmd.ExecuteReader()) { reader.Read(); - Assert.AreEqual(typeof(String), reader.GetFieldType("c1")); - Assert.AreEqual(typeof(byte[]), reader.GetFieldType("c2")); - Assert.AreEqual(typeof(String), reader.GetFieldType("c3")); - Assert.AreEqual(typeof(byte[]), reader.GetFieldType("c4")); - Assert.AreEqual(typeof(byte[]), reader.GetFieldType("c5")); + Assert.That(reader.GetFieldType("c1"), Is.EqualTo(typeof(String))); + Assert.That(reader.GetFieldType("c2"), Is.EqualTo(typeof(byte[]))); + Assert.That(reader.GetFieldType("c3"), Is.EqualTo(typeof(String))); + Assert.That(reader.GetFieldType("c4"), Is.EqualTo(typeof(byte[]))); + Assert.That(reader.GetFieldType("c5"), Is.EqualTo(typeof(byte[]))); } } @@ -508,8 +508,8 @@ AS TRUE_DEFAULT FROM INFORMATION_SCHEMA.COLUMNS using (var reader = cmd.ExecuteReader()) { reader.Read(); - Assert.AreEqual(typeof(string), reader.GetFieldType(0)); - Assert.AreEqual(typeof(Int64), reader.GetFieldType(1)); + Assert.That(reader.GetFieldType(0), Is.EqualTo(typeof(string))); + Assert.That(reader.GetFieldType(1), Is.EqualTo(typeof(Int64))); } } @@ -527,8 +527,8 @@ public void RespectBinaryFlag() using (var reader = cmd.ExecuteReader()) { reader.Read(); - Assert.AreEqual(typeof(string), reader.GetFieldType(0)); - Assert.AreEqual(typeof(System.Byte[]), reader.GetFieldType(1)); + Assert.That(reader.GetFieldType(0), Is.EqualTo(typeof(string))); + Assert.That(reader.GetFieldType(1), Is.EqualTo(typeof(System.Byte[]))); } } } @@ -546,14 +546,14 @@ public void Boolean() using (var reader = cmd.ExecuteReader()) { reader.Read(); - Assert.AreEqual(typeof(Boolean), reader.GetFieldType(1)); - Assert.AreEqual(typeof(SByte), reader.GetFieldType(2)); - Assert.True(reader.GetBoolean(1)); - Assert.AreEqual(1, Convert.ToInt32(reader.GetValue(2))); + Assert.That(reader.GetFieldType(1), Is.EqualTo(typeof(Boolean))); + Assert.That(reader.GetFieldType(2), Is.EqualTo(typeof(SByte))); + Assert.That(reader.GetBoolean(1)); + Assert.That(Convert.ToInt32(reader.GetValue(2)), Is.EqualTo(1)); reader.Read(); - Assert.False(reader.GetBoolean(1)); - Assert.AreEqual(0, Convert.ToInt32(reader.GetValue(2))); + Assert.That(reader.GetBoolean(1), Is.False); + Assert.That(Convert.ToInt32(reader.GetValue(2)), Is.EqualTo(0)); } } @@ -579,10 +579,10 @@ public void Binary16AsGuid() using (var reader = cmd2.ExecuteReader()) { reader.Read(); - Assert.AreEqual(typeof(Guid), reader.GetFieldType(1)); - Assert.AreEqual(typeof(byte[]), reader.GetFieldType(2)); - Assert.AreEqual(typeof(byte[]), reader.GetFieldType(3)); - Assert.AreEqual(g, reader.GetGuid(1)); + Assert.That(reader.GetFieldType(1), Is.EqualTo(typeof(Guid))); + Assert.That(reader.GetFieldType(2), Is.EqualTo(typeof(byte[]))); + Assert.That(reader.GetFieldType(3), Is.EqualTo(typeof(byte[]))); + Assert.That(reader.GetGuid(1), Is.EqualTo(g)); } string s = BitConverter.ToString(bytes); @@ -597,7 +597,7 @@ public void Binary16AsGuid() { reader.Read(); Guid g1 = reader.GetGuid(1); - Assert.AreEqual(g, g1); + Assert.That(g1, Is.EqualTo(g)); } } } @@ -641,22 +641,22 @@ Enabled bit(1) NOT NULL, PRIMARY KEY (`Id`)) LEFT OUTER JOIN Child c ON m.Id=c.MainId ORDER BY m.Descr", Connection); using (var reader = cmd.ExecuteReader()) { - Assert.True(reader.Read()); - Assert.AreEqual("AAA", reader.GetString(0)); - Assert.True(reader.IsDBNull(1)); - Assert.True(reader.IsDBNull(2)); - - Assert.True(reader.Read()); - Assert.AreEqual("BBB", reader.GetString(0)); - Assert.AreEqual(12345, Convert.ToInt32(reader.GetValue(1))); - Assert.AreEqual(1, Convert.ToInt32(reader.GetValue(2))); - - Assert.True(reader.Read()); - Assert.AreEqual("CCC", reader.GetString(0)); - Assert.True(reader.IsDBNull(1)); - Assert.True(reader.IsDBNull(2)); - - Assert.False(reader.Read()); + Assert.That(reader.Read()); + Assert.That(reader.GetString(0), Is.EqualTo("AAA")); + Assert.That(reader.IsDBNull(1)); + Assert.That(reader.IsDBNull(2)); + + Assert.That(reader.Read()); + Assert.That(reader.GetString(0), Is.EqualTo("BBB")); + Assert.That(Convert.ToInt32(reader.GetValue(1)), Is.EqualTo(12345)); + Assert.That(Convert.ToInt32(reader.GetValue(2)), Is.EqualTo(1)); + + Assert.That(reader.Read()); + Assert.That(reader.GetString(0), Is.EqualTo("CCC")); + Assert.That(reader.IsDBNull(1)); + Assert.That(reader.IsDBNull(2)); + + Assert.That(reader.Read(), Is.False); } } @@ -689,7 +689,7 @@ public void GeometryType() public void CanParseGeometryValueString() { var v = MySqlGeometry.Parse("POINT (47.37 -122.21)"); - Assert.AreEqual("POINT(47.37 -122.21)", v.ToString()); + Assert.That(v.ToString(), Is.EqualTo("POINT(47.37 -122.21)")); } [Test] @@ -697,7 +697,7 @@ public void CanTryParseGeometryValueString() { MySqlGeometry v = new MySqlGeometry(0, 0); MySqlGeometry.TryParse("POINT (47.37 -122.21)", out v); - Assert.AreEqual("POINT(47.37 -122.21)", v.ToString()); + Assert.That(v.ToString(), Is.EqualTo("POINT(47.37 -122.21)")); } [Test] @@ -705,7 +705,7 @@ public void CanTryParseGeometryValueStringWithSRIDValue() { var mysqlGeometryResult = new MySqlGeometry(0, 0); MySqlGeometry.TryParse("SRID=101;POINT (47.37 -122.21)", out mysqlGeometryResult); - Assert.AreEqual("SRID=101;POINT(47.37 -122.21)", mysqlGeometryResult.ToString()); + Assert.That(mysqlGeometryResult.ToString(), Is.EqualTo("SRID=101;POINT(47.37 -122.21)")); } [Test] @@ -755,7 +755,7 @@ public void CanFetchGeometryAsBinary() reader.Read(); var val = reader.GetValue(0) as Byte[]; var MyGeometry = new MySqlGeometry(MySqlDbType.Geometry, val); - Assert.AreEqual("POINT(47.37 -122.21)", MyGeometry.ToString()); + Assert.That(MyGeometry.ToString(), Is.EqualTo("POINT(47.37 -122.21)")); } } @@ -779,7 +779,7 @@ public void CanSaveSridValueOnGeometry() using var reader = cmd.ExecuteReader(); reader.Read(); var val = reader.GetInt32(0); - Assert.AreEqual(101, val); + Assert.That(val, Is.EqualTo(101)); } [Test] @@ -803,7 +803,7 @@ public void CanFetchGeometryAsText() { reader.Read(); var val = reader.GetString(0); - Assert.AreEqual("POINT(47.37 -122.21)", val); + Assert.That(val, Is.EqualTo("POINT(47.37 -122.21)")); } } @@ -830,8 +830,8 @@ public void CanUseReaderGetMySqlGeometry() reader.Read(); var val = reader.GetMySqlGeometry(0); var valWithName = reader.GetMySqlGeometry("v"); - Assert.AreEqual("POINT(47.37 -122.21)", val.ToString()); - Assert.AreEqual("POINT(47.37 -122.21)", valWithName.ToString()); + Assert.That(val.ToString(), Is.EqualTo("POINT(47.37 -122.21)")); + Assert.That(valWithName.ToString(), Is.EqualTo("POINT(47.37 -122.21)")); } // reading as geometry @@ -841,8 +841,8 @@ public void CanUseReaderGetMySqlGeometry() reader.Read(); var val = reader.GetMySqlGeometry(0); var valWithName = reader.GetMySqlGeometry("v"); - Assert.AreEqual("POINT(47.37 -122.21)", val.ToString()); - Assert.AreEqual("POINT(47.37 -122.21)", valWithName.ToString()); + Assert.That(val.ToString(), Is.EqualTo("POINT(47.37 -122.21)")); + Assert.That(valWithName.ToString(), Is.EqualTo("POINT(47.37 -122.21)")); } } @@ -852,7 +852,7 @@ public void CanGetToStringFromMySqlGeometry() { MySqlGeometry v = new MySqlGeometry(47.37, -122.21); var valToString = v.ToString(); - Assert.AreEqual("POINT(47.37 -122.21)", valToString); + Assert.That(valToString, Is.EqualTo("POINT(47.37 -122.21)")); } /// @@ -864,9 +864,9 @@ public void CanCreateMySqlGeometryFromEmptyGeometryCollection() var bytes = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; MySqlGeometry v = new MySqlGeometry(MySqlDbType.Geometry, bytes); #if !NETFRAMEWORK - Assert.AreEqual("POINT(3.5E-323 0)", v.ToString()); + Assert.That(v.ToString(), Is.EqualTo("POINT(3.5E-323 0)")); #else - Assert.AreEqual("POINT(3.45845952088873E-323 0)", v.ToString()); + Assert.That(v.ToString(), Is.EqualTo("POINT(3.45845952088873E-323 0)")); #endif } @@ -890,8 +890,8 @@ public void CanGetMySqlGeometryFromEmptyGeometryCollection() reader.Read(); var val = reader.GetMySqlGeometry(0); var valWithName = reader.GetMySqlGeometry("v"); - Assert.AreEqual("POINT(0 0)", val.ToString()); - Assert.AreEqual("POINT(0 0)", valWithName.ToString()); + Assert.That(val.ToString(), Is.EqualTo("POINT(0 0)")); + Assert.That(valWithName.ToString(), Is.EqualTo("POINT(0 0)")); } // reading as geometry @@ -902,11 +902,11 @@ public void CanGetMySqlGeometryFromEmptyGeometryCollection() var val = reader.GetMySqlGeometry(0); var valWithName = reader.GetMySqlGeometry("v"); #if !NETFRAMEWORK - Assert.AreEqual("POINT(3.5E-323 0)", val.ToString()); - Assert.AreEqual("POINT(3.5E-323 0)", valWithName.ToString()); + Assert.That(val.ToString(), Is.EqualTo("POINT(3.5E-323 0)")); + Assert.That(valWithName.ToString(), Is.EqualTo("POINT(3.5E-323 0)")); #else - Assert.AreEqual("POINT(3.45845952088873E-323 0)", val.ToString()); - Assert.AreEqual("POINT(3.45845952088873E-323 0)", valWithName.ToString()); + Assert.That(val.ToString(), Is.EqualTo("POINT(3.45845952088873E-323 0)")); + Assert.That(valWithName.ToString(), Is.EqualTo("POINT(3.45845952088873E-323 0)")); #endif } } @@ -928,7 +928,7 @@ public void Bug30169716() command.CommandText = "INSERT INTO geometries(data) VALUES(@data); "; command.Parameters.AddWithValue("@data", geometry); int result = command.ExecuteNonQuery(); - Assert.AreEqual(1, result); + Assert.That(result, Is.EqualTo(1)); } } @@ -952,7 +952,7 @@ public void StoringAndRetrievingDouble() { reader.Read(); double d = reader.GetDouble(0); - Assert.AreEqual(Math.PI, d); + Assert.That(d, Is.EqualTo(Math.PI)); } } @@ -970,9 +970,9 @@ public void SByteFromReader() using (MySqlDataReader reader = cmd.ExecuteReader()) { reader.Read(); - Assert.AreEqual(99, reader.GetSByte(0)); - Assert.AreEqual(217, reader.GetByte(1)); - Assert.AreEqual(99, reader.GetByte(0)); + Assert.That(reader.GetSByte(0), Is.EqualTo(99)); + Assert.That(reader.GetByte(1), Is.EqualTo(217)); + Assert.That(reader.GetByte(0), Is.EqualTo(99)); } } @@ -995,8 +995,8 @@ public void NewGuidDataType() using (var reader = cmd.ExecuteReader()) { reader.Read(); - Assert.AreEqual(1, reader.GetValue(0)); - Assert.AreEqual(guid, reader.GetGuid(1)); + Assert.That(reader.GetValue(0), Is.EqualTo(1)); + Assert.That(reader.GetGuid(1), Is.EqualTo(guid)); } } } @@ -1029,11 +1029,11 @@ public void ReadBinary16AsBinary() reader.Read(); object o = reader.GetValue(1); - Assert.True(o is Guid); + Assert.That(o is Guid); byte[] bytes = new byte[16]; long size = reader.GetBytes(1, 0, bytes, 0, 16); - Assert.AreEqual(16, size); + Assert.That(size, Is.EqualTo(16)); } } } @@ -1050,7 +1050,7 @@ public void ReadingUUIDAsGuid() cmd.CommandText = "SELECT guid FROM Test"; Guid g = (Guid)cmd.ExecuteScalar(); - Assert.AreEqual(serverGuid, g); + Assert.That(g, Is.EqualTo(serverGuid)); } [Test] @@ -1065,7 +1065,7 @@ public void NewGuidType() cmd.CommandText = "SELECT guid FROM Test"; Guid readG = (Guid)cmd.ExecuteScalar(); - Assert.AreEqual(g, readG); + Assert.That(readG, Is.EqualTo(g)); } /// @@ -1088,9 +1088,9 @@ public void NotGuidType() using (MySqlDataReader reader = cmd.ExecuteReader()) { reader.Read(); - Assert.True(reader["id"] is int); - Assert.True(reader["val"] is string); - Assert.True(reader["guid"] is Guid); + Assert.That(reader["id"] is int); + Assert.That(reader["val"] is string); + Assert.That(reader["guid"] is Guid); } } @@ -1149,7 +1149,7 @@ public void UTF8Char12AsGuid() { reader.Read(); string s = reader.GetString(1); - Assert.AreEqual("Name", s); + Assert.That(s, Is.EqualTo("Name")); } } } @@ -1169,13 +1169,13 @@ public void MySqlDecimal() reader.Read(); MySqlDecimal dec = reader.GetMySqlDecimal(1); string s = dec.ToString(); - Assert.AreEqual(9999999999999999999999999999999999.99, dec.ToDouble()); - Assert.AreEqual("9999999999999999999999999999999999.99", dec.ToString()); + Assert.That(dec.ToDouble(), Is.EqualTo(9999999999999999999999999999999999.99)); + Assert.That(dec.ToString(), Is.EqualTo("9999999999999999999999999999999999.99")); void Value() { _ = dec.Value; } Exception ex = Assert.Throws(() => Value()); - Assert.AreEqual("Value was either too large or too small for a Decimal.", ex.Message); + Assert.That(ex.Message, Is.EqualTo("Value was either too large or too small for a Decimal.")); } } @@ -1199,10 +1199,10 @@ public void DoubleMinValue() { reader.Read(); double d = reader.GetDouble(0); - Assert.AreEqual(d, double.MinValue); + Assert.That(double.MinValue, Is.EqualTo(d)); reader.Read(); d = reader.GetDouble(0); - Assert.AreEqual(d, double.MaxValue); + Assert.That(double.MaxValue, Is.EqualTo(d)); } } @@ -1234,7 +1234,7 @@ public void Timediff() { MySqlCommand cmd = new MySqlCommand("select timediff('2 0:1:1.0', '4 1:2:3.123456')", Connection); var result = cmd.ExecuteScalar(); - Assert.AreEqual(new TimeSpan(new TimeSpan(-2, -1, -1, -2).Ticks - 1234560), result); + Assert.That(result, Is.EqualTo(new TimeSpan(new TimeSpan(-2, -1, -1, -2).Ticks - 1234560))); } [Test] @@ -1252,8 +1252,8 @@ public void CanReadJsonValue() cmd = new MySqlCommand("SELECT jsoncolumn from Test where id = 2 ", Connection); using (MySqlDataReader reader = cmd.ExecuteReader()) { - Assert.True(reader.Read()); - Assert.AreEqual("[\"a\", {\"b\": [true, false]}, [10, 20]]", reader.GetString(0)); + Assert.That(reader.Read()); + Assert.That(reader.GetString(0), Is.EqualTo("[\"a\", {\"b\": [true, false]}, [10, 20]]")); } ExecuteSQL("delete from Test"); @@ -1280,13 +1280,13 @@ public void CanReadJsonValue() cmd = new MySqlCommand("SELECT jsoncolumn from Test where id = 2", Connection); using (var reader = cmd.ExecuteReader()) { - Assert.AreEqual(true, reader.Read(), "Matching the values"); + Assert.That(reader.Read(), Is.EqualTo(true), "Matching the values"); var checkValue = "{\"age\": 25, \"name\": \"Bob\"}"; - Assert.AreEqual(checkValue, reader.GetString(0), "Matching the values"); + Assert.That(reader.GetString(0), Is.EqualTo(checkValue), "Matching the values"); } cmd = new MySqlCommand("SELECT count(*) from Test", Connection); var count = cmd.ExecuteScalar(); - Assert.AreEqual(5, count); + Assert.That(count, Is.EqualTo(5)); cmd = new MySqlCommand(@"INSERT INTO Test VALUES(@id,' { ""name"" : ""harald"",""Date"": ""2013-08-07"",""Time"": ""11:18:29.000000"",""DateTimeOfRegistration"": ""2013-08-07 12:18:29.000000""} ')", Connection); @@ -1296,10 +1296,10 @@ public void CanReadJsonValue() cmd = new MySqlCommand("SELECT jsoncolumn from Test where id=1000", Connection); using (var reader = cmd.ExecuteReader()) { - Assert.AreEqual(true, reader.Read(), "Matching the values"); + Assert.That(reader.Read(), Is.EqualTo(true), "Matching the values"); var checkValue = "{\"Date\": \"2013-08-07\", \"Time\": \"11:18:29.000000\", \"name\": \"harald\", \"DateTimeOfRegistration\": \"2013-08-07 12:18:29.000000\"}"; - Assert.AreEqual(checkValue, reader.GetString(0), "Matching the values"); + Assert.That(reader.GetString(0), Is.EqualTo(checkValue), "Matching the values"); } //Multiple Columns @@ -1314,25 +1314,25 @@ public void CanReadJsonValue() cmd = new MySqlCommand("SELECT jsoncolumn1 from Test where id=100000", Connection); using (var reader = cmd.ExecuteReader()) { - Assert.AreEqual(true, reader.Read(), "Matching the values"); + Assert.That(reader.Read(), Is.EqualTo(true), "Matching the values"); var checkValue = "{\"name\": \"bob\"}"; - Assert.AreEqual(checkValue, reader.GetString(0), "Matching the values"); + Assert.That(reader.GetString(0), Is.EqualTo(checkValue), "Matching the values"); } cmd = new MySqlCommand("SELECT jsoncolumn2 from Test where id=100000", Connection); using (var reader = cmd.ExecuteReader()) { - Assert.AreEqual(true, reader.Read(), "Matching the values"); + Assert.That(reader.Read(), Is.EqualTo(true), "Matching the values"); var checkValue = "{\"marks\": 97}"; - Assert.AreEqual(checkValue, reader.GetString(0), "Matching the values"); + Assert.That(reader.GetString(0), Is.EqualTo(checkValue), "Matching the values"); } cmd = new MySqlCommand("SELECT jsoncolumn3 from Test where id=100000", Connection); using (var reader = cmd.ExecuteReader()) { - Assert.AreEqual(true, reader.Read(), "Matching the values"); + Assert.That(reader.Read(), Is.EqualTo(true), "Matching the values"); var checkValue = "{\"distinction\": true}"; - Assert.AreEqual(checkValue, reader.GetString(0), "Matching the values"); + Assert.That(reader.GetString(0), Is.EqualTo(checkValue), "Matching the values"); } } @@ -1355,8 +1355,8 @@ public void CanUpdateJsonValue() using (MySqlDataReader reader = cmd.ExecuteReader()) { - Assert.True(reader.Read()); - Assert.AreEqual("[\"a\", {\"b\": [true, false]}, [10, 20]]", reader.GetString(0)); + Assert.That(reader.Read()); + Assert.That(reader.GetString(0), Is.EqualTo("[\"a\", {\"b\": [true, false]}, [10, 20]]")); } cmd = new MySqlCommand(@"INSERT INTO Test VALUES(@id,' { ""name"" : ""bob"",""Date"": ""2015-10-09"",""Time"": ""12:18:29.000000"",""DateTimeOfRegistration"": ""2015-10-09 12:18:29.000000""} ')", @@ -1371,10 +1371,10 @@ public void CanUpdateJsonValue() cmd = new MySqlCommand("SELECT jsoncolumn from Test where id=100000", Connection); using (var reader = cmd.ExecuteReader()) { - Assert.AreEqual(true, reader.Read(), "Matching the values"); + Assert.That(reader.Read(), Is.EqualTo(true), "Matching the values"); var checkValue = "{\"Date\": \"2013-08-07\", \"Time\": \"11:18:29.000000\", \"name\": \"harald\", \"DateTimeOfRegistration\": \"2013-08-07 12:18:29.000000\"}"; - Assert.AreEqual(checkValue, reader.GetString(0), "Matching the values"); + Assert.That(reader.GetString(0), Is.EqualTo(checkValue), "Matching the values"); } } @@ -1412,8 +1412,8 @@ public void CanUseGeneratedColumns() using (MySqlDataReader reader = cmd.ExecuteReader()) { - Assert.True(reader.Read()); - Assert.True(reader.GetString(0).Equals("Berlin", StringComparison.CurrentCulture)); + Assert.That(reader.Read()); + Assert.That(reader.GetString(0).Equals("Berlin", StringComparison.CurrentCulture)); } } @@ -1434,7 +1434,7 @@ public void DateTimeTreatedAsVarChar() using (DataTable schema = reader.GetSchemaTable()) { MySqlDbType providerType = (MySqlDbType)(int)schema.Rows[0]["ProviderType"]; - Assert.AreEqual(MySqlDbType.DateTime, providerType); + Assert.That(providerType, Is.EqualTo(MySqlDbType.DateTime)); } } } @@ -1452,7 +1452,7 @@ public void NullGuid() using var reader = cmd.ExecuteReader(); while (reader.Read()) { - Assert.True(reader.IsDBNull(0)); + Assert.That(reader.IsDBNull(0)); } } @@ -1470,7 +1470,7 @@ public void ReadChar36ColumnPrepared() using var reader = cmd.ExecuteReader(); while (reader.Read()) { - StringAssert.AreEqualIgnoringCase(guid, reader.GetGuid(0).ToString()); + Assert.That(reader.GetGuid(0).ToString(), Is.EqualTo(guid).IgnoreCase); } } @@ -1492,10 +1492,10 @@ public void UnexpectedColumnSize() using (var reader = cmd.ExecuteReader()) { var schemaTable = reader.GetSchemaTable(); - Assert.AreEqual("36", schemaTable.Rows[0]["ColumnSize"].ToString(), "Matching the Column Size"); - Assert.AreEqual("37", schemaTable.Rows[1]["ColumnSize"].ToString(), "Matching the Column Size"); - Assert.AreEqual("255", schemaTable.Rows[2]["ColumnSize"].ToString(), "Matching the Column Size"); - Assert.AreEqual("65535", schemaTable.Rows[3]["ColumnSize"].ToString(), "Matching the Column Size"); + Assert.That(schemaTable.Rows[0]["ColumnSize"].ToString(), Is.EqualTo("36"), "Matching the Column Size"); + Assert.That(schemaTable.Rows[1]["ColumnSize"].ToString(), Is.EqualTo("37"), "Matching the Column Size"); + Assert.That(schemaTable.Rows[2]["ColumnSize"].ToString(), Is.EqualTo("255"), "Matching the Column Size"); + Assert.That(schemaTable.Rows[3]["ColumnSize"].ToString(), Is.EqualTo("65535"), "Matching the Column Size"); } } } @@ -1522,9 +1522,9 @@ public void ReadJSONLongValues() cmd = new MySqlCommand("SELECT jsoncolumn from Test where id = " + i, Connection); using (var reader = cmd.ExecuteReader()) { - Assert.AreEqual(true, reader.Read(), "Matching the values"); + Assert.That(reader.Read(), Is.EqualTo(true), "Matching the values"); var checkValue = @"{""age"": " + i + "}"; - Assert.AreEqual(checkValue, reader.GetString(0), "Matching the values"); + Assert.That(reader.GetString(0), Is.EqualTo(checkValue), "Matching the values"); } // long string @@ -1537,10 +1537,10 @@ public void ReadJSONLongValues() cmd = new MySqlCommand("SELECT jsoncolumn from Test where id = 2", Connection); using (var reader = cmd.ExecuteReader()) { - Assert.AreEqual(true, reader.Read(), "Matching the values"); + Assert.That(reader.Read(), Is.EqualTo(true), "Matching the values"); var checkValue = @"{""name"": """ + sb.ToString() + @"""}"; - Assert.AreEqual(checkValue, reader.GetString(0), "Matching the values"); + Assert.That(reader.GetString(0), Is.EqualTo(checkValue), "Matching the values"); } } @@ -1562,9 +1562,9 @@ public void ReadJSONValueStress() using (var reader = cmd.ExecuteReader()) { - Assert.AreEqual(true, reader.Read(), "Matching the values"); + Assert.That(reader.Read(), Is.EqualTo(true), "Matching the values"); var checkValue = @"{""age"": " + i + "}"; - Assert.AreEqual(checkValue, reader.GetString(0), "Matching the values"); + Assert.That(reader.GetString(0), Is.EqualTo(checkValue), "Matching the values"); } } } @@ -1586,17 +1586,17 @@ public void ZeroTimeValues() command.Prepare(); using (var reader = command.ExecuteReader()) { - Assert.True(reader.Read()); - Assert.AreEqual("00:00:00", reader.GetValue(0).ToString()); - Assert.AreEqual("00:00:00", reader.GetTimeSpan(0).ToString()); + Assert.That(reader.Read()); + Assert.That(reader.GetValue(0).ToString(), Is.EqualTo("00:00:00")); + Assert.That(reader.GetTimeSpan(0).ToString(), Is.EqualTo("00:00:00")); - Assert.True(reader.Read()); - Assert.AreEqual("01:01:01", reader.GetValue(0).ToString()); - Assert.AreEqual("01:01:01", reader.GetTimeSpan(0).ToString()); + Assert.That(reader.Read()); + Assert.That(reader.GetValue(0).ToString(), Is.EqualTo("01:01:01")); + Assert.That(reader.GetTimeSpan(0).ToString(), Is.EqualTo("01:01:01")); - Assert.True(reader.Read()); - Assert.AreEqual("00:00:00", reader.GetValue(0).ToString()); - Assert.AreEqual("00:00:00", reader.GetTimeSpan(0).ToString()); + Assert.That(reader.Read()); + Assert.That(reader.GetValue(0).ToString(), Is.EqualTo("00:00:00")); + Assert.That(reader.GetTimeSpan(0).ToString(), Is.EqualTo("00:00:00")); } } } @@ -1618,14 +1618,14 @@ public void TimespanWithMicrosecondsPrepared() // Try the INSERT cmd.CommandText = "INSERT INTO Test VALUES(@value)"; cmd.Prepare(); - Assert.AreEqual(1, cmd.ExecuteNonQuery()); + Assert.That(cmd.ExecuteNonQuery(), Is.EqualTo(1)); // Try the SELECT cmd.CommandText = "SELECT tm FROM Test WHERE tm = @value;"; cmd.Prepare(); using var reader = cmd.ExecuteReader(); - Assert.IsTrue(reader.Read()); - Assert.AreEqual(value, reader.GetValue(0)); + Assert.That(reader.Read()); + Assert.That(reader.GetValue(0), Is.EqualTo(value)); } /// @@ -1648,17 +1648,17 @@ public void GetIntForTinyInt(bool treatAsBool, bool isPrepared) using var reader = cmd.ExecuteReader(); reader.Read(); - Assert.AreEqual(treatAsBool ? 1 : -2, reader.GetSByte(0)); + Assert.That(reader.GetSByte(0), Is.EqualTo(treatAsBool ? 1 : -2)); Assert.Throws(() => reader.GetByte(0)); - Assert.AreEqual(treatAsBool ? 1 : -2, reader.GetInt16(0)); - Assert.AreEqual(treatAsBool ? 1 : -2, reader.GetInt32(0)); - Assert.AreEqual(treatAsBool ? 1 : -2, reader.GetInt64(0)); + Assert.That(reader.GetInt16(0), Is.EqualTo(treatAsBool ? 1 : -2)); + Assert.That(reader.GetInt32(0), Is.EqualTo(treatAsBool ? 1 : -2)); + Assert.That(reader.GetInt64(0), Is.EqualTo(treatAsBool ? 1 : -2)); - Assert.AreEqual(treatAsBool ? 1 : -2, reader.GetFieldValue(0)); + Assert.That(reader.GetFieldValue(0), Is.EqualTo(treatAsBool ? 1 : -2)); Assert.Throws(() => reader.GetFieldValue(0)); - Assert.AreEqual(treatAsBool ? 1 : -2, reader.GetFieldValue(0)); - Assert.AreEqual(treatAsBool ? 1 : -2, reader.GetFieldValue(0)); - Assert.AreEqual(treatAsBool ? 1 : -2, reader.GetFieldValue(0)); + Assert.That(reader.GetFieldValue(0), Is.EqualTo(treatAsBool ? 1 : -2)); + Assert.That(reader.GetFieldValue(0), Is.EqualTo(treatAsBool ? 1 : -2)); + Assert.That(reader.GetFieldValue(0), Is.EqualTo(treatAsBool ? 1 : -2)); } [Test] @@ -1708,16 +1708,16 @@ public void InsertAndSelectVector(bool prepared) using var reader = cmd.ExecuteReader(); reader.Read(); var value = reader.GetValue(0); - Assert.IsInstanceOf(typeof(byte[]), value); + Assert.That(value, Is.InstanceOf(typeof(byte[]))); byteArray = (byte[])value; float[] floatArray2 = new float[byteArray.Length / 4]; Buffer.BlockCopy(byteArray, 0, floatArray2, 0, byteArray.Length); - Assert.AreEqual(3, floatArray2.Length); - Assert.AreEqual(1.2f, floatArray2[0]); - Assert.AreEqual(2.3f, floatArray2[1]); - Assert.AreEqual(3.4f, floatArray2[2]); + Assert.That(floatArray2.Length, Is.EqualTo(3)); + Assert.That(floatArray2[0], Is.EqualTo(1.2f)); + Assert.That(floatArray2[1], Is.EqualTo(2.3f)); + Assert.That(floatArray2[2], Is.EqualTo(3.4f)); } [TestCase(false)] @@ -1742,17 +1742,17 @@ public void VectorReturnedFromSproc(bool prepared) cmd.ExecuteNonQuery(); // now the parameter should contain the output value - Assert.IsInstanceOf(typeof(byte[]), cmd.Parameters[0].Value); + Assert.That(cmd.Parameters[0].Value, Is.InstanceOf(typeof(byte[]))); byte[] byteArray = (byte[])cmd.Parameters[0].Value; // now check to see if it has the correct values float[] floatArray = new float[byteArray.Length / 4]; Buffer.BlockCopy(byteArray, 0, floatArray, 0, byteArray.Length); - Assert.AreEqual(3, floatArray.Length); - Assert.AreEqual(1.2f, floatArray[0]); - Assert.AreEqual(2.3f, floatArray[1]); - Assert.AreEqual(3.4f, floatArray[2]); + Assert.That(floatArray.Length, Is.EqualTo(3)); + Assert.That(floatArray[0], Is.EqualTo(1.2f)); + Assert.That(floatArray[1], Is.EqualTo(2.3f)); + Assert.That(floatArray[2], Is.EqualTo(3.4f)); } } diff --git a/MySQL.Data/tests/MySql.Data.Tests/DateTimeTests.cs b/MySQL.Data/tests/MySql.Data.Tests/DateTimeTests.cs index 8ccb87cf9..2b48c1816 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/DateTimeTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/DateTimeTests.cs @@ -60,9 +60,9 @@ public void ConvertZeroDateTime() MySqlCommand cmd = new MySqlCommand("SELECT * FROM Test", c); using (MySqlDataReader reader = cmd.ExecuteReader()) { - Assert.True(reader.Read()); - Assert.AreEqual(DateTime.MinValue.Date, reader.GetDateTime(1).Date); - Assert.AreEqual(DateTime.MinValue.Date, reader.GetDateTime(2).Date); + Assert.That(reader.Read()); + Assert.That(reader.GetDateTime(1).Date, Is.EqualTo(DateTime.MinValue.Date)); + Assert.That(reader.GetDateTime(2).Date, Is.EqualTo(DateTime.MinValue.Date)); } } } @@ -80,18 +80,18 @@ public void TestNotAllowZeroDateAndTime() MySqlCommand cmd = new MySqlCommand("SELECT * FROM Test", Connection); using (MySqlDataReader reader = cmd.ExecuteReader()) { - Assert.True(reader.Read()); + Assert.That(reader.Read()); MySqlDateTime testDate = reader.GetMySqlDateTime(2); - Assert.False(testDate.IsValidDateTime, "IsZero is false"); + Assert.That(testDate.IsValidDateTime, Is.False, "IsZero is false"); Exception ex = Assert.Throws(() => reader.GetValue(2)); - Assert.AreEqual("Unable to convert MySQL date/time value to System.DateTime", ex.Message); + Assert.That(ex.Message, Is.EqualTo("Unable to convert MySQL date/time value to System.DateTime")); - Assert.True(reader.Read()); + Assert.That(reader.Read()); DateTime dt2 = (DateTime)reader.GetValue(2); - Assert.AreEqual(new DateTime(2004, 11, 11).Date, dt2.Date); + Assert.That(dt2.Date, Is.EqualTo(new DateTime(2004, 11, 11).Date)); } ExecuteSQL($"SET SQL_MODE = '{sql_mode}'"); @@ -108,12 +108,12 @@ public void DateAdd() cmd.Parameters.AddWithValue("?someday", now); using (MySqlDataReader reader = cmd.ExecuteReader()) { - Assert.True(reader.Read()); + Assert.That(reader.Read()); DateTime dt = reader.GetDateTime(0); - Assert.AreEqual(later.Date, dt.Date); - Assert.AreEqual(later.Hour, dt.Hour); - Assert.AreEqual(later.Minute, dt.Minute); - Assert.AreEqual(later.Second, dt.Second); + Assert.That(dt.Date, Is.EqualTo(later.Date)); + Assert.That(dt.Hour, Is.EqualTo(later.Hour)); + Assert.That(dt.Minute, Is.EqualTo(later.Minute)); + Assert.That(dt.Second, Is.EqualTo(later.Second)); } } @@ -130,7 +130,7 @@ public void TestZeroDateTimeException() { reader.Read(); Exception ex = Assert.Throws(() => reader.GetDateTime(2)); - Assert.AreEqual("Unable to convert MySQL date/time value to System.DateTime", ex.Message); + Assert.That(ex.Message, Is.EqualTo("Unable to convert MySQL date/time value to System.DateTime")); } } @@ -157,12 +157,12 @@ public void LargeDateTime() cmd.CommandText = "SELECT id,dt FROM Test"; using (MySqlDataReader reader = cmd.ExecuteReader()) { - Assert.True(reader.Read()); - Assert.AreEqual(DateTime.Parse("9997-10-29").Date, reader.GetDateTime(1).Date); - Assert.True(reader.Read()); - Assert.AreEqual(DateTime.Parse("9997-10-30").Date, reader.GetDateTime(1).Date); - Assert.True(reader.Read()); - Assert.AreEqual(DateTime.Parse("9999-12-31").Date, reader.GetDateTime(1).Date); + Assert.That(reader.Read()); + Assert.That(reader.GetDateTime(1).Date, Is.EqualTo(DateTime.Parse("9997-10-29").Date)); + Assert.That(reader.Read()); + Assert.That(reader.GetDateTime(1).Date, Is.EqualTo(DateTime.Parse("9997-10-30").Date)); + Assert.That(reader.Read()); + Assert.That(reader.GetDateTime(1).Date, Is.EqualTo(DateTime.Parse("9999-12-31").Date)); } } @@ -180,12 +180,12 @@ public void UsingDatesAsStrings() MySqlCommand cmd2 = new MySqlCommand("SELECT * FROM Test", Connection); using (var reader = cmd2.ExecuteReader()) { - Assert.True(reader.Read()); + Assert.That(reader.Read()); DateTime dt = reader.GetDateTime("dt"); - Assert.AreEqual(2005, dt.Year); - Assert.AreEqual(3, dt.Month); - Assert.AreEqual(4, dt.Day); - Assert.False(reader.Read()); + Assert.That(dt.Year, Is.EqualTo(2005)); + Assert.That(dt.Month, Is.EqualTo(3)); + Assert.That(dt.Day, Is.EqualTo(4)); + Assert.That(reader.Read(), Is.False); } } @@ -258,7 +258,7 @@ public void MySqlDateTimeFormatting() { DateTime dt = DateTime.Now; MySqlDateTime mdt = new MySqlDateTime(dt); - Assert.AreEqual(dt.ToString(CultureInfo.InvariantCulture), mdt.ToString()); + Assert.That(mdt.ToString(), Is.EqualTo(dt.ToString(CultureInfo.InvariantCulture))); } /// @@ -280,7 +280,7 @@ public void DateFormat() cmd.Parameters.AddWithValue("?datefilter", dt.Date); using (MySqlDataReader reader = cmd.ExecuteReader()) { - Assert.True(reader.Read()); + Assert.That(reader.Read()); } } @@ -307,7 +307,7 @@ public void TimeColumnWithMicrosecondsOnPrepare() { command.Prepare(); var result = (TimeSpan)command.ExecuteScalar(); - Assert.True(result.ToString() == "1.02:03:04.5670000"); + Assert.That(result.ToString() == "1.02:03:04.5670000"); } ExecuteSQL(@"Delete from test_time;"); @@ -322,7 +322,7 @@ public void TimeColumnWithMicrosecondsOnPrepare() { command.Prepare(); var result = (TimeSpan)command.ExecuteScalar(); - Assert.True(result.ToString() == "1.02:03:04.0005600"); + Assert.That(result.ToString() == "1.02:03:04.0005600"); } } @@ -360,7 +360,7 @@ public void CanUpdateMicroseconds() while (rdr.Read()) { - Assert.AreEqual("12:34:56.123456", rdr.GetDateTime(0).ToString("hh:mm:ss.ffffff")); + Assert.That(rdr.GetDateTime(0).ToString("hh:mm:ss.ffffff"), Is.EqualTo("12:34:56.123456")); } rdr.Close(); } @@ -418,7 +418,7 @@ public void CanUpdateMicrosecondsWithPrepare() while (rdr.Read()) { - Assert.AreEqual("12:34:59.999999", rdr.GetDateTime(0).ToString("hh:mm:ss.ffffff")); + Assert.That(rdr.GetDateTime(0).ToString("hh:mm:ss.ffffff"), Is.EqualTo("12:34:59.999999")); } rdr.Close(); } @@ -457,9 +457,9 @@ public void CanUpdateMillisecondsUsingTimeType() while (rdr.Read()) { #if !NETFRAMEWORK - Assert.AreEqual(345, rdr.GetTimeSpan(0).Milliseconds); + Assert.That(rdr.GetTimeSpan(0).Milliseconds, Is.EqualTo(345)); #else - Assert.AreEqual(346, rdr.GetTimeSpan(0).Milliseconds); + Assert.That(rdr.GetTimeSpan(0).Milliseconds, Is.EqualTo(346)); #endif } } @@ -505,7 +505,7 @@ public void CanUpdateMillisecondsUsingTimeTypeOnPrepareStatements() { while (rdr.Read()) { - Assert.AreEqual(2, rdr.GetTimeSpan(0).Milliseconds); + Assert.That(rdr.GetTimeSpan(0).Milliseconds, Is.EqualTo(2)); } } } @@ -547,7 +547,7 @@ public void CanUpdateMillisecondsUsingTimeStampType() while (rdr.Read()) { - Assert.AreEqual(123456, rdr.GetMySqlDateTime(0).Microsecond); + Assert.That(rdr.GetMySqlDateTime(0).Microsecond, Is.EqualTo(123456)); } rdr.Close(); } @@ -590,7 +590,7 @@ public void CanUpdateMillisecondsUsingTimeStampTypeWithPrepare() { while (rdr.Read()) { - Assert.AreEqual(123456, rdr.GetMySqlDateTime(0).Microsecond); + Assert.That(rdr.GetMySqlDateTime(0).Microsecond, Is.EqualTo(123456)); } } } @@ -617,8 +617,8 @@ public void TimestampValuesAreLocal() reader.Read(); DateTime dt1 = reader.GetDateTime(0); DateTime ts = reader.GetDateTime(1); - Assert.AreEqual(DateTimeKind.Unspecified, dt1.Kind); - Assert.AreEqual(DateTimeKind.Local, ts.Kind); + Assert.That(dt1.Kind, Is.EqualTo(DateTimeKind.Unspecified)); + Assert.That(ts.Kind, Is.EqualTo(DateTimeKind.Local)); } } @@ -656,7 +656,7 @@ public void TimestampCorrectTimezone() { reader.Read(); DateTime ts = reader.GetDateTime(1); - Assert.AreEqual(DateTimeKind.Utc, ts.Kind); + Assert.That(ts.Kind, Is.EqualTo(DateTimeKind.Utc)); } // Now set it to non-UTC cmd.CommandText = "set @@global.time_zone = '+5:00'"; @@ -669,7 +669,7 @@ public void TimestampCorrectTimezone() { reader.Read(); DateTime ts = reader.GetDateTime(1); - Assert.AreEqual(DateTimeKind.Local, ts.Kind); + Assert.That(ts.Kind, Is.EqualTo(DateTimeKind.Local)); } } finally @@ -716,7 +716,7 @@ public void CanSaveMillisecondsPrecision3WithPrepare() while (rdr.Read()) { - Assert.AreEqual("11:09:07.0060", rdr.GetDateTime(0).ToString("hh:mm:ss.ffff")); + Assert.That(rdr.GetDateTime(0).ToString("hh:mm:ss.ffff"), Is.EqualTo("11:09:07.0060")); } rdr.Close(); } @@ -743,7 +743,7 @@ public void CanSaveMillisecondsPrecision3() while (rdr.Read()) { - Assert.AreEqual("11:09:07.0060", rdr.GetDateTime(0).ToString("hh:mm:ss.ffff")); + Assert.That(rdr.GetDateTime(0).ToString("hh:mm:ss.ffff"), Is.EqualTo("11:09:07.0060")); } rdr.Close(); } @@ -769,7 +769,7 @@ public void CanSaveMicrosecondsPrecision4() while (rdr.Read()) { - Assert.AreEqual(dt.ToString("hh:mm:ss.ffff"), rdr.GetDateTime(0).ToString("hh:mm:ss.ffff")); + Assert.That(rdr.GetDateTime(0).ToString("hh:mm:ss.ffff"), Is.EqualTo(dt.ToString("hh:mm:ss.ffff"))); } rdr.Close(); } @@ -783,7 +783,7 @@ public void ShowMicrosecondError() cmd.Connection = Connection; string date = cmd.ExecuteScalar().ToString(); DateTime temp; - Assert.True(DateTime.TryParse(date, out temp)); + Assert.That(DateTime.TryParse(date, out temp)); } /// @@ -811,7 +811,7 @@ public void CanDefineCurrentTimeStampAsDefaultOnDateTime() while (reader.Read()) { - Assert.True(DateTime.TryParse(reader.GetDateTime(0).ToString(), out tempDate)); + Assert.That(DateTime.TryParse(reader.GetDateTime(0).ToString(), out tempDate)); } reader.Close(); } @@ -837,13 +837,13 @@ public void ReadAndWriteMicroseconds() cmd.CommandText = " SELECT * from ReadAndWriteMicroseconds"; using (MySqlDataReader reader = cmd.ExecuteReader()) { - Assert.True(reader.Read()); - Assert.AreEqual(milliseconds.Ticks, reader.GetTimeSpan(1).Ticks); - Assert.AreEqual(microseconds.Ticks, reader.GetTimeSpan(2).Ticks); - Assert.AreEqual(microseconds.Ticks, reader.GetDateTime(3).Ticks); - Assert.AreEqual(microseconds.Millisecond, reader.GetDateTime(3).Millisecond); - Assert.AreEqual(microseconds.Millisecond, reader.GetMySqlDateTime(3).Millisecond); - Assert.AreEqual((microseconds.Ticks % 10000000) / 10, reader.GetMySqlDateTime(3).Microsecond); + Assert.That(reader.Read()); + Assert.That(reader.GetTimeSpan(1).Ticks, Is.EqualTo(milliseconds.Ticks)); + Assert.That(reader.GetTimeSpan(2).Ticks, Is.EqualTo(microseconds.Ticks)); + Assert.That(reader.GetDateTime(3).Ticks, Is.EqualTo(microseconds.Ticks)); + Assert.That(reader.GetDateTime(3).Millisecond, Is.EqualTo(microseconds.Millisecond)); + Assert.That(reader.GetMySqlDateTime(3).Millisecond, Is.EqualTo(microseconds.Millisecond)); + Assert.That(reader.GetMySqlDateTime(3).Microsecond, Is.EqualTo((microseconds.Ticks % 10000000) / 10)); } } @@ -864,7 +864,7 @@ public void TimeZoneOffset() { using (MySqlConnection conn2 = GetConnection()) { - Assert.AreEqual(timeZoneHours, conn2.driver.timeZoneOffset); + Assert.That(conn2.driver.timeZoneOffset, Is.EqualTo(timeZoneHours)); } } finally @@ -894,9 +894,9 @@ public void TimeZoneOffsetUsingReader() var myTimestampSb = (DateTime)reader["mytimestampcolumn"]; var myTimestampGdt = reader.GetDateTime("mytimestampcolumn"); - Assert.True(myTimestampSb.Kind == myTimestampGdt.Kind); - Assert.True(conn.driver.timeZoneOffset == ((DateTimeOffset)myTimestampSb).Offset.Hours, $"Driver: {conn.driver.timeZoneOffset}; Sb: {((DateTimeOffset)myTimestampSb).Offset.Hours}"); - Assert.True(conn.driver.timeZoneOffset == ((DateTimeOffset)myTimestampGdt).Offset.Hours); + Assert.That(myTimestampSb.Kind == myTimestampGdt.Kind); + Assert.That(conn.driver.timeZoneOffset == ((DateTimeOffset)myTimestampSb).Offset.Hours, $"Driver: {conn.driver.timeZoneOffset}; Sb: {((DateTimeOffset)myTimestampSb).Offset.Hours}"); + Assert.That(conn.driver.timeZoneOffset == ((DateTimeOffset)myTimestampGdt).Offset.Hours); reader.Close(); } @@ -932,7 +932,7 @@ public void MilisecondsWithTimeColumn() { reader.Read(); var val = reader.GetValue(0); - StringAssert.StartsWith(timeValue.Substring(0, 14), val.ToString()); + Assert.That(val.ToString(), Does.StartWith(timeValue.Substring(0, 14))); } cmd.CommandText = "DROP TABLE IF EXISTS T"; @@ -951,7 +951,7 @@ public void MilisecondsWithTimeColumn() { reader.Read(); var val = reader.GetTimeSpan(0); - StringAssert.StartsWith(timeValue.Substring(0, 12), val.ToString()); + Assert.That(val.ToString(), Does.StartWith(timeValue.Substring(0, 12))); } } } @@ -986,9 +986,9 @@ public void IConvertibleImplementation() { var mySqlDateTime = new MySqlDateTime(DateTime.Now); - Assert.AreEqual(TypeCode.DateTime, ((IConvertible)mySqlDateTime).GetTypeCode()); - Assert.NotNull(((IConvertible)mySqlDateTime).ToString()); - Assert.NotNull(Convert.ToString(mySqlDateTime)); + Assert.That(((IConvertible)mySqlDateTime).GetTypeCode(), Is.EqualTo(TypeCode.DateTime)); + Assert.That(((IConvertible)mySqlDateTime).ToString(), Is.Not.Null); + Assert.That(Convert.ToString(mySqlDateTime), Is.Not.Null); } } } diff --git a/MySQL.Data/tests/MySql.Data.Tests/DnsSrvTests.cs b/MySQL.Data/tests/MySql.Data.Tests/DnsSrvTests.cs index 59a074e65..205c5d3c6 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/DnsSrvTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/DnsSrvTests.cs @@ -61,7 +61,7 @@ public void DnsSrvConnectionStringInvalidOptions(string connString) public void DnsSrvConnectionStringInvalidConfiguration(string connString, string exceptionMessage) { var exception = Assert.Throws(() => new MySqlConnection(connString)); - Assert.AreEqual(exceptionMessage, exception.Message); + Assert.That(exception.Message, Is.EqualTo(exceptionMessage)); } [TestCase("server=localhost;port=33060;dns-srv=false;")] @@ -75,7 +75,7 @@ public void DnsSrvConnectionStringInvalidConfiguration(string connString, string public void DnsSrvConnectionStringValidConfiguration(string connString) { var conn = new MySqlConnection(connString); - Assert.NotNull(conn); + Assert.That(conn, Is.Not.Null); } [Test] @@ -86,21 +86,21 @@ public void DnsSrvConnectionAnonymousTypeInvalidConfiguration() sb.Port = 3306; sb.Server = "localhost"; var exception = Assert.Throws(() => new MySqlConnection(sb.ConnectionString)); - Assert.AreEqual(Resources.DnsSrvInvalidConnOptionPort, exception.Message); + Assert.That(exception.Message, Is.EqualTo(Resources.DnsSrvInvalidConnOptionPort)); sb = new MySqlConnectionStringBuilder(); sb.DnsSrv = true; sb.Server = "_mysqlx._tcp.foo.abc.com"; sb.ConnectionProtocol = MySqlConnectionProtocol.Unix; exception = Assert.Throws(() => new MySqlConnection(sb.ConnectionString)); - Assert.AreEqual(Resources.DnsSrvInvalidConnOptionUnixSocket, exception.Message); + Assert.That(exception.Message, Is.EqualTo(Resources.DnsSrvInvalidConnOptionUnixSocket)); sb = new MySqlConnectionStringBuilder(); sb.DnsSrv = true; sb.Server = "localhost, 10.10.10.10"; sb.ConnectionProtocol = MySqlConnectionProtocol.Unix; exception = Assert.Throws(() => new MySqlConnection(sb.ConnectionString)); - Assert.AreEqual(Resources.DnsSrvInvalidConnOptionMultihost, exception.Message); + Assert.That(exception.Message, Is.EqualTo(Resources.DnsSrvInvalidConnOptionMultihost)); } [Test] @@ -126,7 +126,7 @@ public void DnsSrvRecordsTest() var sortedRecords = DnsSrv.SortSrvRecords(dnsRecords.ToList()); - Assert.True(sortedRecords.Select(r => r.Target).SequenceEqual(expectedOrder.Select(r => r.Target))); + Assert.That(sortedRecords.Select(r => r.Target).SequenceEqual(expectedOrder.Select(r => r.Target))); } } } diff --git a/MySQL.Data/tests/MySql.Data.Tests/ExceptionTests.cs b/MySQL.Data/tests/MySql.Data.Tests/ExceptionTests.cs index ecb0e9a82..af753b7da 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/ExceptionTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/ExceptionTests.cs @@ -58,8 +58,8 @@ public void Timeout() MySqlCommand cmd = new MySqlCommand("SELECT * FROM Test", connection); Exception ex = Assert.Throws(() => cmd.ExecuteReader()); - Assert.AreEqual("Connection must be valid and open.", ex.Message); - Assert.AreEqual(ConnectionState.Closed, connection.State); + Assert.That(ex.Message, Is.EqualTo("Connection must be valid and open.")); + Assert.That(connection.State, Is.EqualTo(ConnectionState.Closed)); connection.Close(); } @@ -76,7 +76,7 @@ public void ErrorData() } catch (Exception ex) { - Assert.AreEqual(1064, ex.Data["Server Error Code"]); + Assert.That(ex.Data["Server Error Code"], Is.EqualTo(1064)); } } @@ -100,7 +100,7 @@ public void TimeoutErrorMessages() Thread.Sleep(6000); command = new MySqlCommand("SELECT CONNECTION_ID();", connection); var ex = Assert.Throws(() => command.ExecuteScalar()); - Assert.AreEqual((int)MySqlErrorCode.ErrorClientInteractionTimeout, ex.Number); + Assert.That(ex.Number, Is.EqualTo((int)MySqlErrorCode.ErrorClientInteractionTimeout)); } } @@ -158,7 +158,7 @@ public void AuthenticationExceptionNumber(string propertyName, object propertyVa ExecuteSQL("SET GLOBAL max_connections = 1;"); } MySqlException exDefault = Assert.Throws(() => conn.Open()); - Assert.AreEqual(exNumber, exDefault.Number); + Assert.That(exDefault.Number, Is.EqualTo(exNumber)); } } } diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/CultureTests.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/CultureTests.cs index 52f2c24ed..b2b136626 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/CultureTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/CultureTests.cs @@ -75,7 +75,7 @@ private void InternalTestFloats(bool prepared) if (prepared) cmd.Prepare(); int count = cmd.ExecuteNonQuery(); - Assert.AreEqual(1, count); + Assert.That(count, Is.EqualTo(1)); try { @@ -84,9 +84,9 @@ private void InternalTestFloats(bool prepared) using (MySqlDataReader reader = cmd.ExecuteReader()) { reader.Read(); - Assert.AreEqual((decimal)2.3, (decimal)reader.GetFloat(0)); - Assert.AreEqual(4.6, reader.GetDouble(1)); - Assert.AreEqual((decimal)23.82, reader.GetDecimal(2)); + Assert.That((decimal)reader.GetFloat(0), Is.EqualTo((decimal)2.3)); + Assert.That(reader.GetDouble(1), Is.EqualTo(4.6)); + Assert.That(reader.GetDecimal(2), Is.EqualTo((decimal)23.82)); } } finally @@ -134,12 +134,12 @@ public void ArabicCalendars() MySqlCommand cmd = new MySqlCommand("SELECT dt FROM test", Connection); DateTime dt = (DateTime)cmd.ExecuteScalar(); - Assert.AreEqual(2007, dt.Year); - Assert.AreEqual(1, dt.Month); - Assert.AreEqual(1, dt.Day); - Assert.AreEqual(12, dt.Hour); - Assert.AreEqual(30, dt.Minute); - Assert.AreEqual(45, dt.Second); + Assert.That(dt.Year, Is.EqualTo(2007)); + Assert.That(dt.Month, Is.EqualTo(1)); + Assert.That(dt.Day, Is.EqualTo(1)); + Assert.That(dt.Hour, Is.EqualTo(12)); + Assert.That(dt.Minute, Is.EqualTo(30)); + Assert.That(dt.Second, Is.EqualTo(45)); Thread.CurrentThread.CurrentCulture = curCulture; Thread.CurrentThread.CurrentUICulture = curUICulture; @@ -172,9 +172,9 @@ public void FunctionsReturnStringAndDecimal() "select *,(select b from bug52187b) as field_b from bug52187a", con); DataTable dt = new DataTable(); da.Fill(dt); - Assert.AreEqual(1, dt.Rows.Count); - Assert.AreEqual((decimal)1.25, (decimal)dt.Rows[0][0]); - Assert.AreEqual((decimal)5.99, (decimal)dt.Rows[0][1]); + Assert.That(dt.Rows.Count, Is.EqualTo(1)); + Assert.That((decimal)dt.Rows[0][0], Is.EqualTo((decimal)1.25)); + Assert.That((decimal)dt.Rows[0][1], Is.EqualTo((decimal)5.99)); } } finally diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/DataTypeTests.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/DataTypeTests.cs index dedd778f2..223ab385a 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/DataTypeTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/DataTypeTests.cs @@ -57,9 +57,9 @@ public void UpdateDecimalColumns() dt.Clear(); da.Fill(dt); - Assert.AreEqual(1, dt.Rows.Count); - Assert.AreEqual(1, dt.Rows[0]["id"]); - Assert.AreEqual((decimal)23.4, Convert.ToDecimal(dt.Rows[0]["dec1"])); + Assert.That(dt.Rows.Count, Is.EqualTo(1)); + Assert.That(dt.Rows[0]["id"], Is.EqualTo(1)); + Assert.That(Convert.ToDecimal(dt.Rows[0]["dec1"]), Is.EqualTo((decimal)23.4)); cb.Dispose(); } @@ -100,7 +100,7 @@ public void UnsignedTypes() using (MySqlDataReader dr = cmd.ExecuteReader()) { dr.Read(); - Assert.AreEqual(20, dr.GetUInt16(0)); + Assert.That(dr.GetUInt16(0), Is.EqualTo(20)); } } @@ -118,11 +118,11 @@ public void DecimalPrecision() { DataTable dt = reader.GetSchemaTable(); DataRow columnDefinition = dt.Rows[0]; - Assert.AreEqual(35, columnDefinition[SchemaTableColumn.NumericPrecision]); + Assert.That(columnDefinition[SchemaTableColumn.NumericPrecision], Is.EqualTo(35)); columnDefinition = dt.Rows[1]; - Assert.AreEqual(36, columnDefinition[SchemaTableColumn.NumericPrecision]); + Assert.That(columnDefinition[SchemaTableColumn.NumericPrecision], Is.EqualTo(36)); columnDefinition = dt.Rows[2]; - Assert.AreEqual(36, columnDefinition[SchemaTableColumn.NumericPrecision]); + Assert.That(columnDefinition[SchemaTableColumn.NumericPrecision], Is.EqualTo(36)); } } } diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/DateTimeTests.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/DateTimeTests.cs index 07be3e8a5..cba2a0718 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/DateTimeTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/DateTimeTests.cs @@ -58,14 +58,14 @@ public void TestAllowZeroDateTime() { reader.Read(); - Assert.True(reader.GetValue(1) is MySqlDateTime); - Assert.True(reader.GetValue(2) is MySqlDateTime); + Assert.That(reader.GetValue(1) is MySqlDateTime); + Assert.That(reader.GetValue(2) is MySqlDateTime); - Assert.False(reader.GetMySqlDateTime(1).IsValidDateTime); - Assert.False(reader.GetMySqlDateTime(2).IsValidDateTime); + Assert.That(!reader.GetMySqlDateTime(1).IsValidDateTime); + Assert.That(!reader.GetMySqlDateTime(2).IsValidDateTime); Exception ex = Assert.Throws(() =>reader.GetDateTime(1)); - Assert.AreEqual("Unable to convert MySQL date/time value to System.DateTime", ex.Message); + Assert.That(ex.Message, Is.EqualTo("Unable to convert MySQL date/time value to System.DateTime")); } DataTable dt = new DataTable(); @@ -83,11 +83,11 @@ public void TestAllowZeroDateTime() dt.Clear(); da.Fill(dt); - Assert.AreEqual(2, dt.Rows.Count); + Assert.That(dt.Rows.Count, Is.EqualTo(2)); MySqlDateTime date = (MySqlDateTime)dt.Rows[1]["d"]; - Assert.AreEqual(2003, date.Year); - Assert.AreEqual(9, date.Month); - Assert.AreEqual(24, date.Day); + Assert.That(date.Year, Is.EqualTo(2003)); + Assert.That(date.Month, Is.EqualTo(9)); + Assert.That(date.Day, Is.EqualTo(24)); cb.Dispose(); } } @@ -118,10 +118,10 @@ public void SortingMySqlDateTimes() DataView dv = dt.DefaultView; dv.Sort = "dt ASC"; - Assert.AreEqual(new DateTime(2004, 10, 1).Date, Convert.ToDateTime(dv[0]["dt"]).Date); - Assert.AreEqual(new DateTime(2004, 10, 2).Date, Convert.ToDateTime(dv[1]["dt"]).Date); - Assert.AreEqual(new DateTime(2004, 11, 1).Date, Convert.ToDateTime(dv[2]["dt"]).Date); - Assert.AreEqual(new DateTime(2004, 11, 2).Date, Convert.ToDateTime(dv[3]["dt"]).Date); + Assert.That(Convert.ToDateTime(dv[0]["dt"]).Date, Is.EqualTo(new DateTime(2004, 10, 1).Date)); + Assert.That(Convert.ToDateTime(dv[1]["dt"]).Date, Is.EqualTo(new DateTime(2004, 10, 2).Date)); + Assert.That(Convert.ToDateTime(dv[2]["dt"]).Date, Is.EqualTo(new DateTime(2004, 11, 1).Date)); + Assert.That(Convert.ToDateTime(dv[3]["dt"]).Date, Is.EqualTo(new DateTime(2004, 11, 2).Date)); Thread.CurrentThread.CurrentCulture = curCulture; Thread.CurrentThread.CurrentUICulture = curUICulture; @@ -158,8 +158,8 @@ public void InsertDateTimeValue() da.Fill(dt); cb.Dispose(); - Assert.AreEqual(1, dt.Rows.Count); - Assert.AreEqual(now.Date, ((DateTime)dt.Rows[0]["dt"]).Date); + Assert.That(dt.Rows.Count, Is.EqualTo(1)); + Assert.That(((DateTime)dt.Rows[0]["dt"]).Date, Is.EqualTo(now.Date)); } } @@ -192,7 +192,7 @@ public void DateTimeInDataTable() dt.Rows.Clear(); da.Fill(dt); - Assert.AreEqual(2, dt.Rows.Count); + Assert.That(dt.Rows.Count, Is.EqualTo(2)); cb.Dispose(); } } diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/GetSchemaTests.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/GetSchemaTests.cs index 71214f36b..115f2b263 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/GetSchemaTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/GetSchemaTests.cs @@ -48,25 +48,25 @@ public void Collections() DataTable dt = Connection.GetSchema(); int row = 0; - Assert.AreEqual("MetaDataCollections", dt.Rows[row++][0]); - Assert.AreEqual("DataSourceInformation", dt.Rows[row++][0]); - Assert.AreEqual("DataTypes", dt.Rows[row++][0]); - Assert.AreEqual("Restrictions", dt.Rows[row++][0]); - Assert.AreEqual("ReservedWords", dt.Rows[row++][0]); - Assert.AreEqual("Databases", dt.Rows[row++][0]); - Assert.AreEqual("Tables", dt.Rows[row++][0]); - Assert.AreEqual("Columns", dt.Rows[row++][0]); - Assert.AreEqual("Users", dt.Rows[row++][0]); - Assert.AreEqual("Foreign Keys", dt.Rows[row++][0]); - Assert.AreEqual("IndexColumns", dt.Rows[row++][0]); - Assert.AreEqual("Indexes", dt.Rows[row++][0]); - Assert.AreEqual("Foreign Key Columns", dt.Rows[row++][0]); - Assert.AreEqual("UDF", dt.Rows[row++][0]); - Assert.AreEqual("Views", dt.Rows[row++][0]); - Assert.AreEqual("ViewColumns", dt.Rows[row++][0]); - Assert.AreEqual("Procedure Parameters", dt.Rows[row++][0]); - Assert.AreEqual("Procedures", dt.Rows[row++][0]); - Assert.AreEqual("Triggers", dt.Rows[row++][0]); + Assert.That(dt.Rows[row++][0], Is.EqualTo("MetaDataCollections")); + Assert.That(dt.Rows[row++][0], Is.EqualTo("DataSourceInformation")); + Assert.That(dt.Rows[row++][0], Is.EqualTo("DataTypes")); + Assert.That(dt.Rows[row++][0], Is.EqualTo("Restrictions")); + Assert.That(dt.Rows[row++][0], Is.EqualTo("ReservedWords")); + Assert.That(dt.Rows[row++][0], Is.EqualTo("Databases")); + Assert.That(dt.Rows[row++][0], Is.EqualTo("Tables")); + Assert.That(dt.Rows[row++][0], Is.EqualTo("Columns")); + Assert.That(dt.Rows[row++][0], Is.EqualTo("Users")); + Assert.That(dt.Rows[row++][0], Is.EqualTo("Foreign Keys")); + Assert.That(dt.Rows[row++][0], Is.EqualTo("IndexColumns")); + Assert.That(dt.Rows[row++][0], Is.EqualTo("Indexes")); + Assert.That(dt.Rows[row++][0], Is.EqualTo("Foreign Key Columns")); + Assert.That(dt.Rows[row++][0], Is.EqualTo("UDF")); + Assert.That(dt.Rows[row++][0], Is.EqualTo("Views")); + Assert.That(dt.Rows[row++][0], Is.EqualTo("ViewColumns")); + Assert.That(dt.Rows[row++][0], Is.EqualTo("Procedure Parameters")); + Assert.That(dt.Rows[row++][0], Is.EqualTo("Procedures")); + Assert.That(dt.Rows[row++][0], Is.EqualTo("Triggers")); } /// @@ -86,63 +86,63 @@ public void DataTypes() string type = row["TypeName"].ToString(); Type systemType = Type.GetType(row["DataType"].ToString()); if (type == "BIT") - Assert.AreEqual(typeof(System.UInt64), systemType); + Assert.That(systemType, Is.EqualTo(typeof(System.UInt64))); else if (type == "DATE" || type == "DATETIME" || type == "TIMESTAMP") - Assert.AreEqual(typeof(System.DateTime), systemType); + Assert.That(systemType, Is.EqualTo(typeof(System.DateTime))); else if (type == "BLOB" || type == "TINYBLOB" || type == "MEDIUMBLOB" || type == "LONGBLOB") - Assert.AreEqual(typeof(System.Byte[]), systemType); + Assert.That(systemType, Is.EqualTo(typeof(System.Byte[]))); else if (type == "TIME") - Assert.AreEqual(typeof(System.TimeSpan), systemType); + Assert.That(systemType, Is.EqualTo(typeof(System.TimeSpan))); else if (type == "CHAR" || type == "VARCHAR") { - Assert.AreEqual(typeof(System.String), systemType); - Assert.False(Convert.ToBoolean(row["IsFixedLength"])); + Assert.That(systemType, Is.EqualTo(typeof(System.String))); + Assert.That(!Convert.ToBoolean(row["IsFixedLength"])); string format = type + "({0})"; - Assert.AreEqual(format, row["CreateFormat"].ToString()); + Assert.That(row["CreateFormat"].ToString(), Is.EqualTo(format)); } else if (type == "SET" || type == "ENUM") - Assert.AreEqual(typeof(System.String), systemType); + Assert.That(systemType, Is.EqualTo(typeof(System.String))); else if (type == "DOUBLE") - Assert.AreEqual(typeof(System.Double), systemType); + Assert.That(systemType, Is.EqualTo(typeof(System.Double))); else if (type == "SINGLE") - Assert.AreEqual(typeof(System.Single), systemType); + Assert.That(systemType, Is.EqualTo(typeof(System.Single))); else if (type == "TINYINT") { if (row["CreateFormat"].ToString().EndsWith("UNSIGNED", StringComparison.OrdinalIgnoreCase)) - Assert.AreEqual(typeof(System.Byte), systemType); + Assert.That(systemType, Is.EqualTo(typeof(System.Byte))); else - Assert.AreEqual(typeof(System.SByte), systemType); + Assert.That(systemType, Is.EqualTo(typeof(System.SByte))); } else if (type == "SMALLINT") { if (row["CreateFormat"].ToString().EndsWith("UNSIGNED", StringComparison.OrdinalIgnoreCase)) - Assert.AreEqual(typeof(System.UInt16), systemType); + Assert.That(systemType, Is.EqualTo(typeof(System.UInt16))); else - Assert.AreEqual(typeof(System.Int16), systemType); + Assert.That(systemType, Is.EqualTo(typeof(System.Int16))); } else if (type == "MEDIUMINT" || type == "INT") { if (row["CreateFormat"].ToString().EndsWith("UNSIGNED", StringComparison.OrdinalIgnoreCase)) - Assert.AreEqual(typeof(System.UInt32), systemType); + Assert.That(systemType, Is.EqualTo(typeof(System.UInt32))); else - Assert.AreEqual(typeof(System.Int32), systemType); + Assert.That(systemType, Is.EqualTo(typeof(System.Int32))); } else if (type == "BIGINT") { if (row["CreateFormat"].ToString().EndsWith("UNSIGNED", StringComparison.OrdinalIgnoreCase)) - Assert.AreEqual(typeof(System.UInt64), systemType); + Assert.That(systemType, Is.EqualTo(typeof(System.UInt64))); else - Assert.AreEqual(typeof(System.Int64), systemType); + Assert.That(systemType, Is.EqualTo(typeof(System.Int64))); } else if (type == "DECIMAL") { - Assert.AreEqual(typeof(System.Decimal), systemType); - Assert.AreEqual("DECIMAL({0},{1})", row["CreateFormat"].ToString()); + Assert.That(systemType, Is.EqualTo(typeof(System.Decimal))); + Assert.That(row["CreateFormat"].ToString(), Is.EqualTo("DECIMAL({0},{1})")); } else if (type == "TINYINT") - Assert.AreEqual(typeof(System.Byte), systemType); + Assert.That(systemType, Is.EqualTo(typeof(System.Byte))); } } @@ -156,20 +156,20 @@ public void Tables() restrictions[1] = Connection.Database; restrictions[2] = "test1"; DataTable dt = Connection.GetSchema("Tables", restrictions); - Assert.True(dt.Columns["VERSION"].DataType == typeof(UInt64) + Assert.That(dt.Columns["VERSION"].DataType == typeof(UInt64) || dt.Columns["VERSION"].DataType == typeof(Int64)); - Assert.True(dt.Columns["TABLE_ROWS"].DataType == typeof(UInt64)); - Assert.True(dt.Columns["AVG_ROW_LENGTH"].DataType == typeof(UInt64)); - Assert.True(dt.Columns["DATA_LENGTH"].DataType == typeof(UInt64)); - Assert.True(dt.Columns["MAX_DATA_LENGTH"].DataType == typeof(UInt64)); - Assert.True(dt.Columns["INDEX_LENGTH"].DataType == typeof(UInt64)); - Assert.True(dt.Columns["DATA_FREE"].DataType == typeof(UInt64)); - Assert.True(dt.Columns["AUTO_INCREMENT"].DataType == typeof(UInt64)); - Assert.True(dt.Columns["CHECKSUM"].DataType == typeof(UInt64) + Assert.That(dt.Columns["TABLE_ROWS"].DataType == typeof(UInt64)); + Assert.That(dt.Columns["AVG_ROW_LENGTH"].DataType == typeof(UInt64)); + Assert.That(dt.Columns["DATA_LENGTH"].DataType == typeof(UInt64)); + Assert.That(dt.Columns["MAX_DATA_LENGTH"].DataType == typeof(UInt64)); + Assert.That(dt.Columns["INDEX_LENGTH"].DataType == typeof(UInt64)); + Assert.That(dt.Columns["DATA_FREE"].DataType == typeof(UInt64)); + Assert.That(dt.Columns["AUTO_INCREMENT"].DataType == typeof(UInt64)); + Assert.That(dt.Columns["CHECKSUM"].DataType == typeof(UInt64) || dt.Columns["CHECKSUM"].DataType == typeof(Int64)); - Assert.True(dt.Rows.Count == 1); - Assert.AreEqual("Tables", dt.TableName); - Assert.AreEqual("test1", dt.Rows[0][2]); + Assert.That(dt.Rows.Count == 1); + Assert.That(dt.TableName, Is.EqualTo("Tables")); + Assert.That(dt.Rows[0][2], Is.EqualTo("test1")); } [Test] @@ -183,63 +183,63 @@ col3 varchar(50) character set utf8, col4 tinyint unsigned, restrictions[1] = Connection.Database; restrictions[2] = "Test"; DataTable dt = Connection.GetSchema("Columns", restrictions); - Assert.AreEqual(5, dt.Rows.Count); - Assert.AreEqual("Columns", dt.TableName); + Assert.That(dt.Rows.Count, Is.EqualTo(5)); + Assert.That(dt.TableName, Is.EqualTo("Columns")); if (Connection.driver.Version.isAtLeast(8, 0, 1)) { - Assert.True(dt.Columns["ORDINAL_POSITION"].DataType == typeof(UInt32)); - Assert.True(dt.Columns["CHARACTER_MAXIMUM_LENGTH"].DataType == typeof(Int64)); - Assert.True(dt.Columns["NUMERIC_PRECISION"].DataType == typeof(UInt64)); - Assert.True(dt.Columns["NUMERIC_SCALE"].DataType == typeof(UInt64)); + Assert.That(dt.Columns["ORDINAL_POSITION"].DataType == typeof(UInt32)); + Assert.That(dt.Columns["CHARACTER_MAXIMUM_LENGTH"].DataType == typeof(Int64)); + Assert.That(dt.Columns["NUMERIC_PRECISION"].DataType == typeof(UInt64)); + Assert.That(dt.Columns["NUMERIC_SCALE"].DataType == typeof(UInt64)); } else { - Assert.True(dt.Columns["ORDINAL_POSITION"].DataType == typeof(UInt64)); - Assert.True(dt.Columns["CHARACTER_MAXIMUM_LENGTH"].DataType == typeof(UInt64)); - Assert.True(dt.Columns["NUMERIC_PRECISION"].DataType == typeof(UInt64)); - Assert.True(dt.Columns["NUMERIC_SCALE"].DataType == typeof(UInt64)); + Assert.That(dt.Columns["ORDINAL_POSITION"].DataType == typeof(UInt64)); + Assert.That(dt.Columns["CHARACTER_MAXIMUM_LENGTH"].DataType == typeof(UInt64)); + Assert.That(dt.Columns["NUMERIC_PRECISION"].DataType == typeof(UInt64)); + Assert.That(dt.Columns["NUMERIC_SCALE"].DataType == typeof(UInt64)); } // first column - Assert.AreEqual((Connection.Database).ToUpper(), dt.Rows[0]["TABLE_SCHEMA"].ToString().ToUpper()); - Assert.AreEqual("COL1", dt.Rows[0]["COLUMN_NAME"].ToString().ToUpper()); - Assert.AreEqual(1, Convert.ToInt32(dt.Rows[0]["ORDINAL_POSITION"])); - Assert.AreEqual("YES", dt.Rows[0]["IS_NULLABLE"]); - Assert.AreEqual("INT", dt.Rows[0]["DATA_TYPE"].ToString().ToUpper()); + Assert.That(dt.Rows[0]["TABLE_SCHEMA"].ToString().ToUpper(), Is.EqualTo((Connection.Database).ToUpper())); + Assert.That(dt.Rows[0]["COLUMN_NAME"].ToString().ToUpper(), Is.EqualTo("COL1")); + Assert.That(Convert.ToInt32(dt.Rows[0]["ORDINAL_POSITION"]), Is.EqualTo(1)); + Assert.That(dt.Rows[0]["IS_NULLABLE"], Is.EqualTo("YES")); + Assert.That(dt.Rows[0]["DATA_TYPE"].ToString().ToUpper(), Is.EqualTo("INT")); // second column - Assert.AreEqual((Connection.Database).ToUpper(), dt.Rows[1]["TABLE_SCHEMA"].ToString().ToUpper()); - Assert.AreEqual("COL2", dt.Rows[1]["COLUMN_NAME"].ToString().ToUpper()); - Assert.AreEqual(2, Convert.ToInt32(dt.Rows[1]["ORDINAL_POSITION"])); - Assert.AreEqual("YES", dt.Rows[1]["IS_NULLABLE"]); - Assert.AreEqual("DECIMAL", dt.Rows[1]["DATA_TYPE"].ToString().ToUpper()); - Assert.AreEqual("DECIMAL(20,5)", dt.Rows[1]["COLUMN_TYPE"].ToString().ToUpper()); - Assert.AreEqual(20, Convert.ToInt32(dt.Rows[1]["NUMERIC_PRECISION"])); - Assert.AreEqual(5, Convert.ToInt32(dt.Rows[1]["NUMERIC_SCALE"])); + Assert.That(dt.Rows[1]["TABLE_SCHEMA"].ToString().ToUpper(), Is.EqualTo((Connection.Database).ToUpper())); + Assert.That(dt.Rows[1]["COLUMN_NAME"].ToString().ToUpper(), Is.EqualTo("COL2")); + Assert.That(Convert.ToInt32(dt.Rows[1]["ORDINAL_POSITION"]), Is.EqualTo(2)); + Assert.That(dt.Rows[1]["IS_NULLABLE"], Is.EqualTo("YES")); + Assert.That(dt.Rows[1]["DATA_TYPE"].ToString().ToUpper(), Is.EqualTo("DECIMAL")); + Assert.That(dt.Rows[1]["COLUMN_TYPE"].ToString().ToUpper(), Is.EqualTo("DECIMAL(20,5)")); + Assert.That(Convert.ToInt32(dt.Rows[1]["NUMERIC_PRECISION"]), Is.EqualTo(20)); + Assert.That(Convert.ToInt32(dt.Rows[1]["NUMERIC_SCALE"]), Is.EqualTo(5)); // third column - Assert.AreEqual((Connection.Database).ToUpper(), dt.Rows[2]["TABLE_SCHEMA"].ToString().ToUpper()); - Assert.AreEqual("COL3", dt.Rows[2]["COLUMN_NAME"].ToString().ToUpper()); - Assert.AreEqual(3, Convert.ToInt32(dt.Rows[2]["ORDINAL_POSITION"])); - Assert.AreEqual("YES", dt.Rows[2]["IS_NULLABLE"]); - Assert.AreEqual("VARCHAR", dt.Rows[2]["DATA_TYPE"].ToString().ToUpper()); - Assert.AreEqual("VARCHAR(50)", dt.Rows[2]["COLUMN_TYPE"].ToString().ToUpper()); + Assert.That(dt.Rows[2]["TABLE_SCHEMA"].ToString().ToUpper(), Is.EqualTo((Connection.Database).ToUpper())); + Assert.That(dt.Rows[2]["COLUMN_NAME"].ToString().ToUpper(), Is.EqualTo("COL3")); + Assert.That(Convert.ToInt32(dt.Rows[2]["ORDINAL_POSITION"]), Is.EqualTo(3)); + Assert.That(dt.Rows[2]["IS_NULLABLE"], Is.EqualTo("YES")); + Assert.That(dt.Rows[2]["DATA_TYPE"].ToString().ToUpper(), Is.EqualTo("VARCHAR")); + Assert.That(dt.Rows[2]["COLUMN_TYPE"].ToString().ToUpper(), Is.EqualTo("VARCHAR(50)")); // fourth column - Assert.AreEqual((Connection.Database).ToUpper(), dt.Rows[3]["TABLE_SCHEMA"].ToString().ToUpper()); - Assert.AreEqual("COL4", dt.Rows[3]["COLUMN_NAME"].ToString().ToUpper()); - Assert.AreEqual(4, Convert.ToInt32(dt.Rows[3]["ORDINAL_POSITION"])); - Assert.AreEqual("YES", dt.Rows[3]["IS_NULLABLE"]); - Assert.AreEqual("TINYINT", dt.Rows[3]["DATA_TYPE"].ToString().ToUpper()); + Assert.That(dt.Rows[3]["TABLE_SCHEMA"].ToString().ToUpper(), Is.EqualTo((Connection.Database).ToUpper())); + Assert.That(dt.Rows[3]["COLUMN_NAME"].ToString().ToUpper(), Is.EqualTo("COL4")); + Assert.That(Convert.ToInt32(dt.Rows[3]["ORDINAL_POSITION"]), Is.EqualTo(4)); + Assert.That(dt.Rows[3]["IS_NULLABLE"], Is.EqualTo("YES")); + Assert.That(dt.Rows[3]["DATA_TYPE"].ToString().ToUpper(), Is.EqualTo("TINYINT")); // fifth column - Assert.AreEqual((Connection.Database).ToUpper(), dt.Rows[4]["TABLE_SCHEMA"].ToString().ToUpper()); - Assert.AreEqual("COL5", dt.Rows[4]["COLUMN_NAME"].ToString().ToUpper()); - Assert.AreEqual(5, Convert.ToInt32(dt.Rows[4]["ORDINAL_POSITION"])); - Assert.AreEqual("YES", dt.Rows[4]["IS_NULLABLE"]); - Assert.AreEqual("VARCHAR", dt.Rows[4]["DATA_TYPE"].ToString().ToUpper()); - Assert.AreEqual("VARCHAR(20)", dt.Rows[4]["COLUMN_TYPE"].ToString().ToUpper()); - Assert.AreEqual("BOO", dt.Rows[4]["COLUMN_DEFAULT"].ToString().ToUpper()); + Assert.That(dt.Rows[4]["TABLE_SCHEMA"].ToString().ToUpper(), Is.EqualTo((Connection.Database).ToUpper())); + Assert.That(dt.Rows[4]["COLUMN_NAME"].ToString().ToUpper(), Is.EqualTo("COL5")); + Assert.That(Convert.ToInt32(dt.Rows[4]["ORDINAL_POSITION"]), Is.EqualTo(5)); + Assert.That(dt.Rows[4]["IS_NULLABLE"], Is.EqualTo("YES")); + Assert.That(dt.Rows[4]["DATA_TYPE"].ToString().ToUpper(), Is.EqualTo("VARCHAR")); + Assert.That(dt.Rows[4]["COLUMN_TYPE"].ToString().ToUpper(), Is.EqualTo("VARCHAR(20)")); + Assert.That(dt.Rows[4]["COLUMN_DEFAULT"].ToString().ToUpper(), Is.EqualTo("BOO")); } @@ -259,13 +259,13 @@ public void CanGetSchemaInformationGeneratedColumns() cmd.ExecuteNonQuery(); DataTable dt = Connection.GetSchema("Columns", new string[] { null, null, "Test", null }); - Assert.AreEqual(3, dt.Rows.Count); - Assert.AreEqual("Columns", dt.TableName); + Assert.That(dt.Rows.Count, Is.EqualTo(3)); + Assert.That(dt.TableName, Is.EqualTo("Columns")); if (Version.Major >= 5 && Version.Minor >= 7 && Version.Build >= 6) { - Assert.AreEqual("char", dt.Rows[2]["DATA_TYPE"]); - Assert.AreEqual("Name", dt.Rows[2]["GENERATION_EXPRESSION"].ToString().Trim('`')); - Assert.AreEqual("STORED GENERATED", dt.Rows[2]["EXTRA"]); + Assert.That(dt.Rows[2]["DATA_TYPE"], Is.EqualTo("char")); + Assert.That(dt.Rows[2]["GENERATION_EXPRESSION"].ToString().Trim('`'), Is.EqualTo("Name")); + Assert.That(dt.Rows[2]["EXTRA"], Is.EqualTo("STORED GENERATED")); } } @@ -279,11 +279,11 @@ public void EnumAndSetColumns() ExecuteSQL("CREATE TABLE Test (col1 set('A','B','C'), col2 enum('A','B','C'))"); DataTable dt = Connection.GetSchema("Columns", new string[] { null, null, "Test", null }); - Assert.AreEqual(2, dt.Rows.Count); - Assert.AreEqual("set", dt.Rows[0]["DATA_TYPE"]); - Assert.AreEqual("enum", dt.Rows[1]["DATA_TYPE"]); - Assert.AreEqual("set('A','B','C')", dt.Rows[0]["COLUMN_TYPE"]); - Assert.AreEqual("enum('A','B','C')", dt.Rows[1]["COLUMN_TYPE"]); + Assert.That(dt.Rows.Count, Is.EqualTo(2)); + Assert.That(dt.Rows[0]["DATA_TYPE"], Is.EqualTo("set")); + Assert.That(dt.Rows[1]["DATA_TYPE"], Is.EqualTo("enum")); + Assert.That(dt.Rows[0]["COLUMN_TYPE"], Is.EqualTo("set('A','B','C')")); + Assert.That(dt.Rows[1]["COLUMN_TYPE"], Is.EqualTo("enum('A','B','C')")); } [Test] @@ -296,9 +296,9 @@ public void Procedures() restrictions[1] = Connection.Database; restrictions[2] = "spTest"; DataTable dt = Connection.GetSchema("Procedures", restrictions); - Assert.True(dt.Rows.Count == 1); - Assert.AreEqual("Procedures", dt.TableName); - Assert.AreEqual("spTest", dt.Rows[0][3]); + Assert.That(dt.Rows.Count == 1); + Assert.That(dt.TableName, Is.EqualTo("Procedures")); + Assert.That(dt.Rows[0][3], Is.EqualTo("spTest")); } /// @@ -310,8 +310,8 @@ public void ProcedureParameters() { var dt = Connection.GetSchema("PROCEDURE PARAMETERS"); - Assert.AreEqual("Procedure Parameters", dt.TableName); - Assert.True(dt.Rows.Count > 0); + Assert.That(dt.TableName, Is.EqualTo("Procedure Parameters")); + Assert.That(dt.Rows.Count > 0); } [Test] @@ -324,9 +324,9 @@ public void Functions() restrictions[1] = Connection.Database; restrictions[2] = "spFunc"; DataTable dt = Connection.GetSchema("Procedures", restrictions); - Assert.True(dt.Rows.Count == 1); - Assert.AreEqual("Procedures", dt.TableName); - Assert.AreEqual("spFunc", dt.Rows[0][3]); + Assert.That(dt.Rows.Count == 1); + Assert.That(dt.TableName, Is.EqualTo("Procedures")); + Assert.That(dt.Rows[0][3], Is.EqualTo("spFunc")); } [Test] @@ -337,29 +337,29 @@ public void Indexes() restrictions[2] = "Test"; restrictions[1] = Connection.Database; DataTable dt = Connection.GetSchema("Indexes", restrictions); - Assert.AreEqual(1, dt.Rows.Count); - StringAssert.AreEqualIgnoringCase("test", dt.Rows[0]["TABLE_NAME"].ToString()); - Assert.True((bool)dt.Rows[0]["PRIMARY"]); - Assert.True((bool)dt.Rows[0]["UNIQUE"]); + Assert.That(dt.Rows.Count, Is.EqualTo(1)); + Assert.That(dt.Rows[0]["TABLE_NAME"].ToString(), Is.EqualTo("test").IgnoreCase); + Assert.That((bool)dt.Rows[0]["PRIMARY"]); + Assert.That((bool)dt.Rows[0]["UNIQUE"]); ExecuteSQL("DROP TABLE IF EXISTS Test"); ExecuteSQL("CREATE TABLE Test (id int, name varchar(50), " + "UNIQUE KEY key2 (name))"); dt = Connection.GetSchema("Indexes", restrictions); - Assert.AreEqual(1, dt.Rows.Count); - StringAssert.AreEqualIgnoringCase("test", dt.Rows[0]["TABLE_NAME"].ToString()); - Assert.AreEqual("key2", dt.Rows[0]["INDEX_NAME"]); - Assert.False((bool)dt.Rows[0]["PRIMARY"]); - Assert.True((bool)dt.Rows[0]["UNIQUE"]); + Assert.That(dt.Rows.Count, Is.EqualTo(1)); + Assert.That(dt.Rows[0]["TABLE_NAME"].ToString(), Is.EqualTo("test").IgnoreCase); + Assert.That(dt.Rows[0]["INDEX_NAME"], Is.EqualTo("key2")); + Assert.That(!(bool)dt.Rows[0]["PRIMARY"]); + Assert.That((bool)dt.Rows[0]["UNIQUE"]); restrictions[3] = "key2"; dt = Connection.GetSchema("Indexes", restrictions); - Assert.AreEqual(1, dt.Rows.Count); - StringAssert.AreEqualIgnoringCase("test", dt.Rows[0]["TABLE_NAME"].ToString()); - Assert.AreEqual("key2", dt.Rows[0]["INDEX_NAME"]); - Assert.False((bool)dt.Rows[0]["PRIMARY"]); - Assert.True((bool)dt.Rows[0]["UNIQUE"]); + Assert.That(dt.Rows.Count, Is.EqualTo(1)); + Assert.That(dt.Rows[0]["TABLE_NAME"].ToString(), Is.EqualTo("test").IgnoreCase); + Assert.That(dt.Rows[0]["INDEX_NAME"], Is.EqualTo("key2")); + Assert.That(!(bool)dt.Rows[0]["PRIMARY"]); + Assert.That((bool)dt.Rows[0]["UNIQUE"]); /// /// Bug #48101 MySqlConnection.GetSchema on "Indexes" throws when there's a table named "b`a`d" @@ -370,11 +370,11 @@ public void Indexes() restrictions[2] = "Te`s`t"; dt = Connection.GetSchema("Indexes", restrictions); - Assert.AreEqual(1, dt.Rows.Count); - StringAssert.AreEqualIgnoringCase("te`s`t", dt.Rows[0]["TABLE_NAME"].ToString()); - Assert.AreEqual("key2", dt.Rows[0]["INDEX_NAME"]); - Assert.False((bool)dt.Rows[0]["PRIMARY"]); - Assert.False((bool)dt.Rows[0]["UNIQUE"]); + Assert.That(dt.Rows.Count, Is.EqualTo(1)); + Assert.That(dt.Rows[0]["TABLE_NAME"].ToString(), Is.EqualTo("te`s`t").IgnoreCase); + Assert.That(dt.Rows[0]["INDEX_NAME"], Is.EqualTo("key2")); + Assert.That(!(bool)dt.Rows[0]["PRIMARY"]); + Assert.That(!(bool)dt.Rows[0]["UNIQUE"]); } [Test] @@ -385,9 +385,9 @@ public void IndexColumns() restrictions[2] = "Test"; restrictions[1] = Connection.Database; DataTable dt = Connection.GetSchema("IndexColumns", restrictions); - Assert.AreEqual(1, dt.Rows.Count); - StringAssert.AreEqualIgnoringCase("test", dt.Rows[0]["TABLE_NAME"].ToString()); - Assert.AreEqual("id", dt.Rows[0]["COLUMN_NAME"]); + Assert.That(dt.Rows.Count, Is.EqualTo(1)); + Assert.That(dt.Rows[0]["TABLE_NAME"].ToString(), Is.EqualTo("test").IgnoreCase); + Assert.That(dt.Rows[0]["COLUMN_NAME"], Is.EqualTo("id")); ExecuteSQL("DROP TABLE IF EXISTS Test"); ExecuteSQL("CREATE TABLE Test (id int, id1 int, id2 int, " + @@ -396,29 +396,29 @@ public void IndexColumns() restrictions[1] = Connection.Database; restrictions[4] = "id2"; dt = Connection.GetSchema("IndexColumns", restrictions); - Assert.AreEqual(1, dt.Rows.Count); - StringAssert.AreEqualIgnoringCase("test", dt.Rows[0]["TABLE_NAME"].ToString()); - Assert.AreEqual("id2", dt.Rows[0]["COLUMN_NAME"]); - Assert.AreEqual(2, dt.Rows[0]["ORDINAL_POSITION"]); + Assert.That(dt.Rows.Count, Is.EqualTo(1)); + Assert.That(dt.Rows[0]["TABLE_NAME"].ToString(), Is.EqualTo("test").IgnoreCase); + Assert.That(dt.Rows[0]["COLUMN_NAME"], Is.EqualTo("id2")); + Assert.That(dt.Rows[0]["ORDINAL_POSITION"], Is.EqualTo(2)); restrictions[3] = "key1"; dt = Connection.GetSchema("IndexColumns", restrictions); - Assert.AreEqual(1, dt.Rows.Count); - StringAssert.AreEqualIgnoringCase("test", dt.Rows[0]["TABLE_NAME"].ToString()); - Assert.AreEqual("id2", dt.Rows[0]["COLUMN_NAME"]); - Assert.AreEqual(2, dt.Rows[0]["ORDINAL_POSITION"]); + Assert.That(dt.Rows.Count, Is.EqualTo(1)); + Assert.That(dt.Rows[0]["TABLE_NAME"].ToString(), Is.EqualTo("test").IgnoreCase); + Assert.That(dt.Rows[0]["COLUMN_NAME"], Is.EqualTo("id2")); + Assert.That(dt.Rows[0]["ORDINAL_POSITION"], Is.EqualTo(2)); restrictions = new string[3]; restrictions[1] = Connection.Database; restrictions[2] = "Test"; dt = Connection.GetSchema("IndexColumns", restrictions); - Assert.AreEqual(2, dt.Rows.Count); - StringAssert.AreEqualIgnoringCase("test", dt.Rows[0]["TABLE_NAME"].ToString()); - Assert.AreEqual("id1", dt.Rows[0]["COLUMN_NAME"]); - Assert.AreEqual(1, dt.Rows[0]["ORDINAL_POSITION"]); - StringAssert.AreEqualIgnoringCase("test", dt.Rows[0]["TABLE_NAME"].ToString()); - Assert.AreEqual("id2", dt.Rows[1]["COLUMN_NAME"]); - Assert.AreEqual(2, dt.Rows[1]["ORDINAL_POSITION"]); + Assert.That(dt.Rows.Count, Is.EqualTo(2)); + Assert.That(dt.Rows[0]["TABLE_NAME"].ToString(), Is.EqualTo("test").IgnoreCase); + Assert.That(dt.Rows[0]["COLUMN_NAME"], Is.EqualTo("id1")); + Assert.That(dt.Rows[0]["ORDINAL_POSITION"], Is.EqualTo(1)); + Assert.That(dt.Rows[0]["TABLE_NAME"].ToString(), Is.EqualTo("test").IgnoreCase); + Assert.That(dt.Rows[1]["COLUMN_NAME"], Is.EqualTo("id2")); + Assert.That(dt.Rows[1]["ORDINAL_POSITION"], Is.EqualTo(2)); restrictions = new string[4]; ExecuteSQL("DROP TABLE IF EXISTS Test"); @@ -439,9 +439,9 @@ public void Views() restrictions[1] = Connection.Database; restrictions[2] = "vw"; DataTable dt = Connection.GetSchema("Views", restrictions); - Assert.True(dt.Rows.Count == 1); - Assert.AreEqual("Views", dt.TableName); - Assert.AreEqual("vw", dt.Rows[0]["TABLE_NAME"]); + Assert.That(dt.Rows.Count == 1); + Assert.That(dt.TableName, Is.EqualTo("Views")); + Assert.That(dt.Rows[0]["TABLE_NAME"], Is.EqualTo("vw")); } [Test] @@ -454,11 +454,11 @@ public void ViewColumns() restrictions[1] = Connection.Database; restrictions[2] = "vw"; DataTable dt = Connection.GetSchema("ViewColumns", restrictions); - Assert.True(dt.Rows.Count == 1); - Assert.AreEqual("ViewColumns", dt.TableName); - Assert.AreEqual(Connection.Database.ToLower(), dt.Rows[0]["VIEW_SCHEMA"].ToString().ToLower()); - Assert.AreEqual("vw", dt.Rows[0]["VIEW_NAME"]); - Assert.AreEqual("theTime", dt.Rows[0]["COLUMN_NAME"]); + Assert.That(dt.Rows.Count == 1); + Assert.That(dt.TableName, Is.EqualTo("ViewColumns")); + Assert.That(dt.Rows[0]["VIEW_SCHEMA"].ToString().ToLower(), Is.EqualTo(Connection.Database.ToLower())); + Assert.That(dt.Rows[0]["VIEW_NAME"], Is.EqualTo("vw")); + Assert.That(dt.Rows[0]["COLUMN_NAME"], Is.EqualTo("theTime")); } [Test] @@ -474,14 +474,14 @@ public void SingleForeignKey() restrictions[1] = Connection.Database; restrictions[2] = "child"; DataTable dt = Connection.GetSchema("Foreign Keys", restrictions); - Assert.AreEqual(1, dt.Rows.Count); + Assert.That(dt.Rows.Count, Is.EqualTo(1)); DataRow row = dt.Rows[0]; - Assert.AreEqual(Connection.Database.ToLower(), row[1].ToString().ToLower()); - Assert.AreEqual("c1", row[2]); - Assert.AreEqual(Connection.Database.ToLower(), row[4].ToString().ToLower()); - Assert.AreEqual("child", row[5]); - Assert.AreEqual(Connection.Database.ToLower(), row[10].ToString().ToLower()); - Assert.AreEqual("parent", row[11]); + Assert.That(row[1].ToString().ToLower(), Is.EqualTo(Connection.Database.ToLower())); + Assert.That(row[2], Is.EqualTo("c1")); + Assert.That(row[4].ToString().ToLower(), Is.EqualTo(Connection.Database.ToLower())); + Assert.That(row[5], Is.EqualTo("child")); + Assert.That(row[10].ToString().ToLower(), Is.EqualTo(Connection.Database.ToLower())); + Assert.That(row[11], Is.EqualTo("parent")); } /// @@ -507,7 +507,7 @@ public void ForeignKeys() "FOREIGN KEY (customer_id) REFERENCES customer(id)) ENGINE=INNODB"); DataTable dt = Connection.GetSchema("Foreign Keys"); - Assert.True(dt.Columns.Contains("REFERENCED_TABLE_CATALOG")); + Assert.That(dt.Columns.Contains("REFERENCED_TABLE_CATALOG")); } [Test] @@ -532,22 +532,22 @@ public void MultiSingleForeignKey() restrictions[1] = Connection.Database; restrictions[2] = "product_order"; DataTable dt = Connection.GetSchema("Foreign Keys", restrictions); - Assert.AreEqual(2, dt.Rows.Count); + Assert.That(dt.Rows.Count, Is.EqualTo(2)); DataRow row = dt.Rows[0]; - Assert.AreEqual(Connection.Database.ToLower(), row[1].ToString().ToLower()); - Assert.AreEqual("product_order_ibfk_1", row[2]); - Assert.AreEqual(Connection.Database.ToLower(), row[4].ToString().ToLower()); - Assert.AreEqual("product_order", row[5]); - Assert.AreEqual(Connection.Database.ToLower(), row[10].ToString().ToLower()); - Assert.AreEqual("product", row[11]); + Assert.That(row[1].ToString().ToLower(), Is.EqualTo(Connection.Database.ToLower())); + Assert.That(row[2], Is.EqualTo("product_order_ibfk_1")); + Assert.That(row[4].ToString().ToLower(), Is.EqualTo(Connection.Database.ToLower())); + Assert.That(row[5], Is.EqualTo("product_order")); + Assert.That(row[10].ToString().ToLower(), Is.EqualTo(Connection.Database.ToLower())); + Assert.That(row[11], Is.EqualTo("product")); row = dt.Rows[1]; - Assert.AreEqual(Connection.Database.ToLower(), row[1].ToString().ToLower()); - Assert.AreEqual("product_order_ibfk_2", row[2]); - Assert.AreEqual(Connection.Database.ToLower(), row[4].ToString().ToLower()); - Assert.AreEqual("product_order", row[5]); - Assert.AreEqual(Connection.Database.ToLower(), row[10].ToString().ToLower()); - Assert.AreEqual("customer", row[11]); + Assert.That(row[1].ToString().ToLower(), Is.EqualTo(Connection.Database.ToLower())); + Assert.That(row[2], Is.EqualTo("product_order_ibfk_2")); + Assert.That(row[4].ToString().ToLower(), Is.EqualTo(Connection.Database.ToLower())); + Assert.That(row[5], Is.EqualTo("product_order")); + Assert.That(row[10].ToString().ToLower(), Is.EqualTo(Connection.Database.ToLower())); + Assert.That(row[11], Is.EqualTo("customer")); } [Test] @@ -565,13 +565,13 @@ public void Triggers() restrictions[1] = Connection.Database; restrictions[2] = "test1"; DataTable dt = Connection.GetSchema("Triggers", restrictions); - Assert.True(dt.Rows.Count == 1); - Assert.AreEqual("Triggers", dt.TableName); - Assert.AreEqual("trigger1", dt.Rows[0]["TRIGGER_NAME"]); - Assert.AreEqual("INSERT", dt.Rows[0]["EVENT_MANIPULATION"]); - Assert.AreEqual("test1", dt.Rows[0]["EVENT_OBJECT_TABLE"]); - Assert.AreEqual("ROW", dt.Rows[0]["ACTION_ORIENTATION"]); - Assert.AreEqual("AFTER", dt.Rows[0]["ACTION_TIMING"]); + Assert.That(dt.Rows.Count == 1); + Assert.That(dt.TableName, Is.EqualTo("Triggers")); + Assert.That(dt.Rows[0]["TRIGGER_NAME"], Is.EqualTo("trigger1")); + Assert.That(dt.Rows[0]["EVENT_MANIPULATION"], Is.EqualTo("INSERT")); + Assert.That(dt.Rows[0]["EVENT_OBJECT_TABLE"], Is.EqualTo("test1")); + Assert.That(dt.Rows[0]["ACTION_ORIENTATION"], Is.EqualTo("ROW")); + Assert.That(dt.Rows[0]["ACTION_TIMING"], Is.EqualTo("AFTER")); } [Test] @@ -584,10 +584,10 @@ public void UsingQuotedRestrictions() restrictions[1] = Connection.Database; restrictions[2] = "`test1`"; DataTable dt = Connection.GetSchema("Tables", restrictions); - Assert.True(dt.Rows.Count == 1); - Assert.AreEqual("Tables", dt.TableName); - Assert.AreEqual("test1", dt.Rows[0][2]); - Assert.AreEqual("`test1`", restrictions[2]); + Assert.That(dt.Rows.Count == 1); + Assert.That(dt.TableName, Is.EqualTo("Tables")); + Assert.That(dt.Rows[0][2], Is.EqualTo("test1")); + Assert.That(restrictions[2], Is.EqualTo("`test1`")); } [Test] @@ -595,8 +595,8 @@ public void ReservedWords() { DataTable dt = Connection.GetSchema("ReservedWords"); foreach (DataRow row in dt.Rows) - Assert.False(String.IsNullOrEmpty(row[0] as string)); - Assert.AreEqual(235, dt.Rows.Count); // number of keywords: 235 + Assert.That(!String.IsNullOrEmpty(row[0] as string)); + Assert.That(dt.Rows.Count, Is.EqualTo(235)); // number of keywords: 235 } [Test] @@ -615,22 +615,22 @@ public void GetSchemaCollections() MySqlSchemaCollection schemaCollection = schema.GetSchema("columns", restrictions); - Assert.True(schemaCollection.Columns.Count == 20); - Assert.True(schemaCollection.Rows.Count == 2); - Assert.AreEqual("parent", schemaCollection.Rows[0]["TABLE_NAME"]); - Assert.AreEqual("id", schemaCollection.Rows[0]["COLUMN_NAME"]); + Assert.That(schemaCollection.Columns.Count == 20); + Assert.That(schemaCollection.Rows.Count == 2); + Assert.That(schemaCollection.Rows[0]["TABLE_NAME"], Is.EqualTo("parent")); + Assert.That(schemaCollection.Rows[0]["COLUMN_NAME"], Is.EqualTo("id")); schemaCollection = schema.GetForeignKeysAsync(restrictions, false).GetAwaiter().GetResult(); - Assert.True(schemaCollection.AsDataTable().Columns.Contains("REFERENCED_TABLE_NAME")); + Assert.That(schemaCollection.AsDataTable().Columns.Contains("REFERENCED_TABLE_NAME")); schemaCollection = schema.GetForeignKeyColumnsAsync(restrictions, false).GetAwaiter().GetResult(); - Assert.True(schemaCollection.AsDataTable().Columns.Contains("REFERENCED_COLUMN_NAME")); + Assert.That(schemaCollection.AsDataTable().Columns.Contains("REFERENCED_COLUMN_NAME")); schemaCollection = schema.GetUDFAsync(restrictions, false).GetAwaiter().GetResult(); - Assert.True(schemaCollection.AsDataTable().Columns.Contains("RETURN_TYPE")); + Assert.That(schemaCollection.AsDataTable().Columns.Contains("RETURN_TYPE")); schemaCollection = schema.GetUsersAsync(restrictions, false).GetAwaiter().GetResult(); - Assert.True(schemaCollection.AsDataTable().Columns.Contains("USERNAME")); + Assert.That(schemaCollection.AsDataTable().Columns.Contains("USERNAME")); using (var conn = new MySqlConnection(Connection.ConnectionString)) { @@ -639,8 +639,8 @@ public void GetSchemaCollections() foreach (DataRow row in table.Rows) foreach (DataColumn col in table.Columns) { - Assert.IsNotNull(col.ColumnName); - Assert.IsNotNull(row[col]); + Assert.That(col.ColumnName, Is.Not.Null); + Assert.That(row[col], Is.Not.Null); } } @@ -665,11 +665,11 @@ public void ColumnSizeWithOldGuids() { DataTable schemaTable = reader.GetSchemaTable(); - Assert.AreEqual(36, schemaTable.Rows[0]["ColumnSize"]); - Assert.AreEqual(16, schemaTable.Rows[1]["ColumnSize"]); - Assert.AreEqual(37, schemaTable.Rows[2]["ColumnSize"]); - Assert.AreEqual(255, schemaTable.Rows[3]["ColumnSize"]); - Assert.AreEqual(65535, schemaTable.Rows[4]["ColumnSize"]); + Assert.That(schemaTable.Rows[0]["ColumnSize"], Is.EqualTo(36)); + Assert.That(schemaTable.Rows[1]["ColumnSize"], Is.EqualTo(16)); + Assert.That(schemaTable.Rows[2]["ColumnSize"], Is.EqualTo(37)); + Assert.That(schemaTable.Rows[3]["ColumnSize"], Is.EqualTo(255)); + Assert.That(schemaTable.Rows[4]["ColumnSize"], Is.EqualTo(65535)); } } } @@ -692,10 +692,10 @@ public void IsLongProperty() using (var reader = cmd.ExecuteReader()) { var schemaTable = reader.GetSchemaTable(); - Assert.AreEqual("-1", schemaTable.Rows[0]["ColumnSize"].ToString(), "Matching the Column Size"); - Assert.AreEqual("True", schemaTable.Rows[0]["IsLong"].ToString(), "Matching the Column Size"); - Assert.AreEqual("-1", schemaTable.Rows[1]["ColumnSize"].ToString(), "Matching the Column Size"); - Assert.AreEqual("True", schemaTable.Rows[1]["IsLong"].ToString(), "Matching the Column Size"); + Assert.That(schemaTable.Rows[0]["ColumnSize"].ToString(), Is.EqualTo("-1"), "Matching the Column Size"); + Assert.That(schemaTable.Rows[0]["IsLong"].ToString(), Is.EqualTo("True"), "Matching the Column Size"); + Assert.That(schemaTable.Rows[1]["ColumnSize"].ToString(), Is.EqualTo("-1"), "Matching the Column Size"); + Assert.That(schemaTable.Rows[1]["IsLong"].ToString(), Is.EqualTo("True"), "Matching the Column Size"); } } } @@ -716,8 +716,8 @@ public void NumericPrecisionProperty() using (var reader = cmd.ExecuteReader()) { var schemaTable = reader.GetSchemaTable(); - Assert.AreEqual(8, schemaTable.Rows[0]["NumericPrecision"]); - Assert.AreEqual(0, schemaTable.Rows[0]["NumericScale"]); + Assert.That(schemaTable.Rows[0]["NumericPrecision"], Is.EqualTo(8)); + Assert.That(schemaTable.Rows[0]["NumericScale"], Is.EqualTo(0)); } } } @@ -738,7 +738,7 @@ public void GetSchemaReturnColumnsByOrdinalPosition() string[] expected = new string[] { "x", "a", "z", "c" }; for (int i = 0; i < rows.Count; i++) - Assert.AreEqual(rows[i]["COLUMN_NAME"], expected[i]); + Assert.That(expected[i], Is.EqualTo(rows[i]["COLUMN_NAME"])); } [Test, Description("Test to verify different variations in Generated Coloumns")] @@ -763,22 +763,22 @@ c2 double GENERATED ALWAYS AS(c1 * 101 / 102) Stored COMMENT 'First Gen Col', using (var reader = cmd.ExecuteReader()) { - Assert.True(reader.Read(), "Matching the values"); - Assert.True(reader.GetInt32(0).Equals(1000), "Matching the values"); - Assert.True(reader.GetDouble(1).Equals(990.196078431), "Matching the values"); - Assert.True(reader.GetInt64(2).Equals(10000000), "Matching the values"); + Assert.That(reader.Read(), "Matching the values"); + Assert.That(reader.GetInt32(0).Equals(1000), "Matching the values"); + Assert.That(reader.GetDouble(1).Equals(990.196078431), "Matching the values"); + Assert.That(reader.GetInt64(2).Equals(10000000), "Matching the values"); } var dt = conn.GetSchema("Columns", new[] { null, null, "Test", null }); - Assert.AreEqual(3, dt.Rows.Count, "Matching the values"); - Assert.AreEqual("Columns", dt.TableName, "Matching the values"); - Assert.AreEqual("int", dt.Rows[0]["DATA_TYPE"].ToString(), "Matching the values"); - Assert.AreEqual("double", dt.Rows[1]["DATA_TYPE"].ToString(), "Matching the values"); - Assert.AreEqual("bigint", dt.Rows[2]["DATA_TYPE"].ToString(), "Matching the values"); - Assert.AreEqual("", dt.Rows[0]["GENERATION_EXPRESSION"].ToString(), "Matching the values"); - Assert.AreEqual("", dt.Rows[0]["EXTRA"].ToString(), "Matching the values"); - Assert.AreEqual("STORED GENERATED", dt.Rows[1]["EXTRA"].ToString(), "Matching the values"); - Assert.AreEqual("VIRTUAL GENERATED", dt.Rows[2]["EXTRA"].ToString(), "Matching the values"); + Assert.That(dt.Rows.Count, Is.EqualTo(3), "Matching the values"); + Assert.That(dt.TableName, Is.EqualTo("Columns"), "Matching the values"); + Assert.That(dt.Rows[0]["DATA_TYPE"].ToString(), Is.EqualTo("int"), "Matching the values"); + Assert.That(dt.Rows[1]["DATA_TYPE"].ToString(), Is.EqualTo("double"), "Matching the values"); + Assert.That(dt.Rows[2]["DATA_TYPE"].ToString(), Is.EqualTo("bigint"), "Matching the values"); + Assert.That(dt.Rows[0]["GENERATION_EXPRESSION"].ToString(), Is.EqualTo(""), "Matching the values"); + Assert.That(dt.Rows[0]["EXTRA"].ToString(), Is.EqualTo(""), "Matching the values"); + Assert.That(dt.Rows[1]["EXTRA"].ToString(), Is.EqualTo("STORED GENERATED"), "Matching the values"); + Assert.That(dt.Rows[2]["EXTRA"].ToString(), Is.EqualTo("VIRTUAL GENERATED"), "Matching the values"); } } @@ -796,12 +796,12 @@ public void GetIndexColumnsWithFullTextIndex() { string cmdText = $"SELECT name, index_id, table_id, space from INFORMATION_SCHEMA.INNODB_INDEXES WHERE name = '{indexName}'"; MySqlCommand cmd = new MySqlCommand(cmdText, Connection); - StringAssert.AreEqualIgnoringCase(indexName, cmd.ExecuteScalar().ToString()); + Assert.That(cmd.ExecuteScalar().ToString(), Is.EqualTo(indexName).IgnoreCase); } var indexColumns = Connection.GetSchema("IndexColumns"); var row = indexColumns.Select("TABLE_NAME = 'Test'"); - StringAssert.AreEqualIgnoringCase(indexName, row[0]["INDEX_NAME"].ToString()); + Assert.That(row[0]["INDEX_NAME"].ToString(), Is.EqualTo(indexName).IgnoreCase); } } } diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/InstallerTests.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/InstallerTests.cs index d028719b0..a8fcbe190 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/InstallerTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/InstallerTests.cs @@ -112,7 +112,7 @@ public void CanRemoveAssemblyBinding() && nodesDependantAssembly[0].ChildNodes[0].Attributes[0].Value.Contains("MySql")) { - Assert.True(true, "Error when removing assembly binding redirection"); + Assert.That(true, "Error when removing assembly binding redirection"); } } } diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MySQLHelperTests.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MySQLHelperTests.cs index bdeff2071..c16d037f8 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MySQLHelperTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MySQLHelperTests.cs @@ -61,7 +61,7 @@ public void EscapeStringMethodCanEscapeQuotationMark() cmd.CommandText = "SELECT name FROM Test WHERE id=1"; string name = (string)cmd.ExecuteScalar(); - Assert.True("test\"name\"" == name, "Update result with quotation mark"); + Assert.That("test\"name\"" == name, "Update result with quotation mark"); } #region Async @@ -74,12 +74,12 @@ public async Task ExecuteNonQueryAsync() try { int result = await MySqlHelper.ExecuteNonQueryAsync(Connection, "call MSHNonQueryAsyncSpTest", null); - Assert.AreNotEqual(-1, result); + Assert.That(result, Is.Not.EqualTo(-1)); MySqlCommand cmd = new MySqlCommand("SELECT COUNT(*) FROM MSHNonQueryAsyncTest;", Connection); cmd.CommandType = System.Data.CommandType.Text; object cnt = cmd.ExecuteScalar(); - Assert.AreEqual(100, Convert.ToInt32(cnt)); + Assert.That(Convert.ToInt32(cnt), Is.EqualTo(100)); } finally { @@ -101,34 +101,34 @@ public async Task ExecuteDataSetAsync() string sql = "SELECT MSHDataSetAsyncTable1.key FROM MSHDataSetAsyncTable1 WHERE MSHDataSetAsyncTable1.key=1; " + "SELECT MSHDataSetAsyncTable2.key FROM MSHDataSetAsyncTable2 WHERE MSHDataSetAsyncTable2.key=1"; DataSet ds = await MySqlHelper.ExecuteDatasetAsync(Connection, sql, null); - Assert.AreEqual(2, ds.Tables.Count); - Assert.AreEqual(1, ds.Tables[0].Rows.Count); - Assert.AreEqual(1, ds.Tables[1].Rows.Count); - Assert.AreEqual(1, ds.Tables[0].Rows[0]["key"]); - Assert.AreEqual(1, ds.Tables[1].Rows[0]["key"]); + Assert.That(ds.Tables.Count, Is.EqualTo(2)); + Assert.That(ds.Tables[0].Rows.Count, Is.EqualTo(1)); + Assert.That(ds.Tables[1].Rows.Count, Is.EqualTo(1)); + Assert.That(ds.Tables[0].Rows[0]["key"], Is.EqualTo(1)); + Assert.That(ds.Tables[1].Rows[0]["key"], Is.EqualTo(1)); ds = await MySqlHelper.ExecuteDatasetAsync(Connection, sql); - Assert.AreEqual(2, ds.Tables.Count); - Assert.AreEqual(1, ds.Tables[0].Rows.Count); - Assert.AreEqual(1, ds.Tables[1].Rows[0]["key"]); + Assert.That(ds.Tables.Count, Is.EqualTo(2)); + Assert.That(ds.Tables[0].Rows.Count, Is.EqualTo(1)); + Assert.That(ds.Tables[1].Rows[0]["key"], Is.EqualTo(1)); ds = await MySqlHelper.ExecuteDatasetAsync(Connection.ConnectionString, sql, null); - Assert.AreEqual(1, ds.Tables[0].Rows.Count); - Assert.AreEqual(1, ds.Tables[1].Rows.Count); - Assert.AreEqual(1, ds.Tables[0].Rows[0]["key"]); + Assert.That(ds.Tables[0].Rows.Count, Is.EqualTo(1)); + Assert.That(ds.Tables[1].Rows.Count, Is.EqualTo(1)); + Assert.That(ds.Tables[0].Rows[0]["key"], Is.EqualTo(1)); ds = await MySqlHelper.ExecuteDatasetAsync(Connection.ConnectionString, sql); - Assert.AreEqual(2, ds.Tables.Count); - Assert.AreEqual(1, ds.Tables[0].Rows.Count); - Assert.AreEqual(1, ds.Tables[1].Rows[0]["key"]); + Assert.That(ds.Tables.Count, Is.EqualTo(2)); + Assert.That(ds.Tables[0].Rows.Count, Is.EqualTo(1)); + Assert.That(ds.Tables[1].Rows[0]["key"], Is.EqualTo(1)); ds = await MySqlHelper.ExecuteDatasetAsync(Connection.ConnectionString, sql, CancellationToken.None, null); - Assert.AreEqual(2, ds.Tables.Count); - Assert.AreEqual(1, ds.Tables[0].Rows.Count); + Assert.That(ds.Tables.Count, Is.EqualTo(2)); + Assert.That(ds.Tables[0].Rows.Count, Is.EqualTo(1)); ds = await MySqlHelper.ExecuteDatasetAsync(Connection, sql, CancellationToken.None); - Assert.AreEqual(2, ds.Tables.Count); - Assert.AreEqual(1, ds.Tables[0].Rows[0]["key"]); + Assert.That(ds.Tables.Count, Is.EqualTo(2)); + Assert.That(ds.Tables[0].Rows[0]["key"], Is.EqualTo(1)); } finally { @@ -147,17 +147,17 @@ public async Task ExecuteReaderAsync() { using (MySqlDataReader reader = await MySqlHelper.ExecuteReaderAsync(Connection, "call MSHReaderAsyncSpTest")) { - Assert.NotNull(reader); - Assert.True(reader.Read(), "can read"); - Assert.True(reader.NextResult()); - Assert.True(reader.Read()); - Assert.AreEqual("done", reader.GetString(0)); + Assert.That(reader, Is.Not.Null); + Assert.That(reader.Read(), "can read"); + Assert.That(reader.NextResult()); + Assert.That(reader.Read()); + Assert.That(reader.GetString(0), Is.EqualTo("done")); reader.Close(); MySqlCommand cmd = new MySqlCommand("SELECT COUNT(*) FROM MSHReaderAsyncTest", Connection); cmd.CommandType = CommandType.Text; object cnt = cmd.ExecuteScalar(); - Assert.AreEqual(1, Convert.ToInt32(cnt)); + Assert.That(Convert.ToInt32(cnt), Is.EqualTo(1)); } } finally @@ -176,7 +176,7 @@ public async Task ExecuteScalarAsync() try { object result = await MySqlHelper.ExecuteScalarAsync(Connection, "SELECT MSHScalarAsyncTable1.key FROM MSHScalarAsyncTable1 WHERE MSHScalarAsyncTable1.key=1;"); - Assert.AreEqual(1, int.Parse(result.ToString())); + Assert.That(int.Parse(result.ToString()), Is.EqualTo(1)); } finally { @@ -193,7 +193,7 @@ public async Task ExecuteDataRowAsync() try { DataRow result = await MySqlHelper.ExecuteDataRowAsync(Connection.ConnectionString, "SELECT name FROM Test WHERE id=1", null); - Assert.AreEqual("name", result[0]); + Assert.That(result[0], Is.EqualTo("name")); } finally @@ -216,7 +216,7 @@ public void UpdateDataSet() MySqlHelper.UpdateDataSet(Connection.ConnectionString, "SELECT * FROM Test", ds, "Test"); DataRow result = ds.Tables["Test"].Rows[0]; - Assert.AreEqual("updatedName", result["name"]); + Assert.That(result["name"], Is.EqualTo("updatedName")); } [Test] @@ -235,7 +235,7 @@ public async Task UpdateDataSetAsync() { await MySqlHelper.UpdateDataSetAsync(Connection.ConnectionString, "SELECT * FROM Test", ds, "Test"); DataRow result = ds.Tables["Test"].Rows[0]; - Assert.AreEqual("updatedName", result["name"]); + Assert.That(result["name"], Is.EqualTo("updatedName")); } finally { @@ -252,20 +252,20 @@ public void ExecuteDataset() DataSet ds = MySqlHelper.ExecuteDataset(Connection, "SELECT * FROM Test"); Assert.That(ds.Tables, Has.One.Items); - Assert.AreEqual(2, ds.Tables[0].Rows.Count); - Assert.AreEqual("name", ds.Tables[0].Rows[0][1]); + Assert.That(ds.Tables[0].Rows.Count, Is.EqualTo(2)); + Assert.That(ds.Tables[0].Rows[0][1], Is.EqualTo("name")); MySqlParameter mySqlParameter = new MySqlParameter("@id", 2); ds = MySqlHelper.ExecuteDataset(Connection, "SELECT * FROM Test WHERE id = @id", mySqlParameter); Assert.That(ds.Tables, Has.One.Items); - Assert.AreEqual(1, ds.Tables[0].Rows.Count); - Assert.AreEqual("name2", ds.Tables[0].Rows[0][1]); + Assert.That(ds.Tables[0].Rows.Count, Is.EqualTo(1)); + Assert.That(ds.Tables[0].Rows[0][1], Is.EqualTo("name2")); ds = MySqlHelper.ExecuteDataset(Connection.ConnectionString, "SELECT * FROM Test", null); Assert.That(ds.Tables, Has.One.Items); - Assert.AreEqual(2, ds.Tables[0].Rows.Count); - Assert.AreEqual("name", ds.Tables[0].Rows[0][1]); - Assert.AreEqual("name2", ds.Tables[0].Rows[1][1]); + Assert.That(ds.Tables[0].Rows.Count, Is.EqualTo(2)); + Assert.That(ds.Tables[0].Rows[0][1], Is.EqualTo("name")); + Assert.That(ds.Tables[0].Rows[1][1], Is.EqualTo("name2")); } #endregion } diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MySqlCommandBuilderTests.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MySqlCommandBuilderTests.cs index 542c70aa8..ae2b38de7 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MySqlCommandBuilderTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MySqlCommandBuilderTests.cs @@ -58,14 +58,14 @@ public void MultiWord() row["multi word"] = 2; dt.Rows.Add(row); da.Update(dt); - Assert.AreEqual(1, dt.Rows.Count); - Assert.AreEqual(2, dt.Rows[0]["multi word"]); + Assert.That(dt.Rows.Count, Is.EqualTo(1)); + Assert.That(dt.Rows[0]["multi word"], Is.EqualTo(2)); dt.Rows[0]["multi word"] = 3; da.Update(dt); cb.Dispose(); - Assert.AreEqual(1, dt.Rows.Count); - Assert.AreEqual(3, dt.Rows[0]["multi word"]); + Assert.That(dt.Rows.Count, Is.EqualTo(1)); + Assert.That(dt.Rows[0]["multi word"], Is.EqualTo(3)); } [Test] @@ -80,17 +80,17 @@ public void LastOneWins() cb.ConflictOption = ConflictOption.OverwriteChanges; DataTable dt = new DataTable(); da.Fill(dt); - Assert.AreEqual(1, dt.Rows.Count); + Assert.That(dt.Rows.Count, Is.EqualTo(1)); ExecuteSQL("UPDATE Test SET name='Test2' WHERE id=1"); dt.Rows[0]["name"] = "Test3"; - Assert.AreEqual(1, da.Update(dt)); + Assert.That(da.Update(dt), Is.EqualTo(1)); dt.Rows.Clear(); da.Fill(dt); - Assert.AreEqual(1, dt.Rows.Count); - Assert.AreEqual("Test3", dt.Rows[0]["name"]); + Assert.That(dt.Rows.Count, Is.EqualTo(1)); + Assert.That(dt.Rows[0]["name"], Is.EqualTo("Test3")); } [Test] @@ -104,18 +104,18 @@ public void NotLastOneWins() cb.ConflictOption = ConflictOption.CompareAllSearchableValues; DataTable dt = new DataTable(); da.Fill(dt); - Assert.AreEqual(1, dt.Rows.Count); + Assert.That(dt.Rows.Count, Is.EqualTo(1)); ExecuteSQL("UPDATE Test SET name='Test2' WHERE id=1"); dt.Rows[0]["name"] = "Test3"; void Update() { da.Update(dt); } Exception ex = Assert.Throws(() => Update()); - Assert.AreEqual("Concurrency violation: the UpdateCommand affected 0 of the expected 1 records.", ex.Message); + Assert.That(ex.Message, Is.EqualTo("Concurrency violation: the UpdateCommand affected 0 of the expected 1 records.")); dt.Rows.Clear(); da.Fill(dt); - Assert.AreEqual(1, dt.Rows.Count); - Assert.AreEqual("Test2", dt.Rows[0]["name"]); + Assert.That(dt.Rows.Count, Is.EqualTo(1)); + Assert.That(dt.Rows[0]["name"], Is.EqualTo("Test2")); } /// @@ -141,9 +141,9 @@ public void UsingFunctions() da.SelectCommand.CommandText = "SELECT id, name, CONCAT(name, ' boo') as newname from Test where id=4"; dt.Clear(); da.Fill(dt); - Assert.AreEqual(1, dt.Rows.Count); - Assert.AreEqual("test1", dt.Rows[0]["name"]); - Assert.AreEqual("test1 boo", dt.Rows[0]["newname"]); + Assert.That(dt.Rows.Count, Is.EqualTo(1)); + Assert.That(dt.Rows[0]["name"], Is.EqualTo("test1")); + Assert.That(dt.Rows[0]["newname"], Is.EqualTo("test1 boo")); dt.Rows[0]["id"] = 5; da.Update(dt); @@ -151,8 +151,8 @@ public void UsingFunctions() dt.Clear(); da.SelectCommand.CommandText = "SELECT * FROM Test WHERE id=5"; da.Fill(dt); - Assert.AreEqual(1, dt.Rows.Count); - Assert.AreEqual("test1", dt.Rows[0]["name"]); + Assert.That(dt.Rows.Count, Is.EqualTo(1)); + Assert.That(dt.Rows[0]["name"], Is.EqualTo("test1")); da.SelectCommand.CommandText = "SELECT *, now() as stime FROM Test WHERE id<4"; cb = new MySqlCommandBuilder(da); @@ -235,8 +235,8 @@ public void SemicolonAtEndOfSQL() dt.Clear(); da.Fill(dt); cb.Dispose(); - Assert.AreEqual(1, dt.Rows.Count); - Assert.AreEqual(2, dt.Rows[0]["id"]); + Assert.That(dt.Rows.Count, Is.EqualTo(1)); + Assert.That(dt.Rows[0]["id"], Is.EqualTo(2)); } /// @@ -257,7 +257,7 @@ public void AutoIncrementColumnsOnInsert() DataTable dt = new DataTable(); da.Fill(dt); dt.Columns[0].AutoIncrement = true; - Assert.True(dt.Columns[0].AutoIncrement); + Assert.That(dt.Columns[0].AutoIncrement); dt.Columns[0].AutoIncrementSeed = -1; dt.Columns[0].AutoIncrementStep = -1; DataRow row = dt.NewRow(); @@ -268,9 +268,9 @@ public void AutoIncrementColumnsOnInsert() dt.Clear(); da.Fill(dt); - Assert.AreEqual(1, dt.Rows.Count); - Assert.AreEqual(1, dt.Rows[0]["id"]); - Assert.AreEqual("Test", dt.Rows[0]["name"]); + Assert.That(dt.Rows.Count, Is.EqualTo(1)); + Assert.That(dt.Rows[0]["id"], Is.EqualTo(1)); + Assert.That(dt.Rows[0]["name"], Is.EqualTo("Test")); cb.Dispose(); } @@ -298,17 +298,17 @@ public void AutoIncrementColumnsOnInsert2() row["name"] = "Test"; dt.Rows.Add(row); da.Update(dt); - Assert.AreEqual(1, Convert.ToInt32(dt.Rows[0]["id"])); - Assert.AreEqual("Test", dt.Rows[0]["name"]); + Assert.That(Convert.ToInt32(dt.Rows[0]["id"]), Is.EqualTo(1)); + Assert.That(dt.Rows[0]["name"], Is.EqualTo("Test")); row = dt.NewRow(); row["name"] = "Test2"; dt.Rows.Add(row); da.Update(dt); - Assert.AreEqual(2, Convert.ToInt32(dt.Rows[1]["id"])); - Assert.AreEqual("Test2", dt.Rows[1]["name"]); + Assert.That(Convert.ToInt32(dt.Rows[1]["id"]), Is.EqualTo(2)); + Assert.That(dt.Rows[1]["name"], Is.EqualTo("Test2")); - Assert.AreEqual(1, Convert.ToInt32(dt.Rows[0]["id"])); + Assert.That(Convert.ToInt32(dt.Rows[0]["id"]), Is.EqualTo(1)); } [Test] @@ -369,7 +369,7 @@ public void UpdatingWithDateInKey() dt.Clear(); da.SelectCommand.CommandText = "SELECT * FROM Test WHERE cod=6"; da.Fill(dt); - Assert.AreEqual(6, dt.Rows[0]["cod"]); + Assert.That(dt.Rows[0]["cod"], Is.EqualTo(6)); } /// @@ -379,14 +379,14 @@ public void UpdatingWithDateInKey() public void QuoteAndUnquoteIdentifiers() { MySqlCommandBuilder cb = new MySqlCommandBuilder(); - Assert.AreEqual("`boo`", cb.QuoteIdentifier("boo")); - Assert.AreEqual("`bo``o`", cb.QuoteIdentifier("bo`o")); - Assert.AreEqual("`boo`", cb.QuoteIdentifier("`boo`")); + Assert.That(cb.QuoteIdentifier("boo"), Is.EqualTo("`boo`")); + Assert.That(cb.QuoteIdentifier("bo`o"), Is.EqualTo("`bo``o`")); + Assert.That(cb.QuoteIdentifier("`boo`"), Is.EqualTo("`boo`")); // now do the unquoting - Assert.AreEqual("boo", cb.UnquoteIdentifier("`boo`")); - Assert.AreEqual("`boo", cb.UnquoteIdentifier("`boo")); - Assert.AreEqual("bo`o", cb.UnquoteIdentifier("`bo``o`")); + Assert.That(cb.UnquoteIdentifier("`boo`"), Is.EqualTo("boo")); + Assert.That(cb.UnquoteIdentifier("`boo"), Is.EqualTo("`boo")); + Assert.That(cb.UnquoteIdentifier("`bo``o`"), Is.EqualTo("bo`o")); } /// @@ -403,8 +403,7 @@ public void BigintUnsignedAsPK() var commandBuilder = new MySqlCommandBuilder(adapter); var myCommand = commandBuilder.GetUpdateCommand(); - StringAssert.AreEqualIgnoringCase($"UPDATE `test` SET `field1` = @p1 WHERE ((`id` = @p2) AND (`field1` = @p3))", - myCommand.CommandText); + Assert.That(myCommand.CommandText, Is.EqualTo($"UPDATE `test` SET `field1` = @p1 WHERE ((`id` = @p2) AND (`field1` = @p3))").IgnoreCase); } } } diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MySqlDataAdapterTests.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MySqlDataAdapterTests.cs index 27effd8f6..0df4429a5 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MySqlDataAdapterTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MySqlDataAdapterTests.cs @@ -76,15 +76,15 @@ private void FillImpl(bool prepare) da.Fill(ds, "Test"); Assert.That(ds.Tables, Has.One.Items); - Assert.AreEqual(3, ds.Tables[0].Rows.Count); + Assert.That(ds.Tables[0].Rows.Count, Is.EqualTo(3)); - Assert.AreEqual(1, ds.Tables[0].Rows[0]["id2"]); - Assert.AreEqual(2, ds.Tables[0].Rows[1]["id2"]); - Assert.AreEqual(3, ds.Tables[0].Rows[2]["id2"]); + Assert.That(ds.Tables[0].Rows[0]["id2"], Is.EqualTo(1)); + Assert.That(ds.Tables[0].Rows[1]["id2"], Is.EqualTo(2)); + Assert.That(ds.Tables[0].Rows[2]["id2"], Is.EqualTo(3)); - Assert.AreEqual("Name 1", ds.Tables[0].Rows[0]["name"]); - Assert.AreEqual(DBNull.Value, ds.Tables[0].Rows[1]["name"]); - Assert.AreEqual(String.Empty, ds.Tables[0].Rows[2]["name"]); + Assert.That(ds.Tables[0].Rows[0]["name"], Is.EqualTo("Name 1")); + Assert.That(ds.Tables[0].Rows[1]["name"], Is.EqualTo(DBNull.Value)); + Assert.That(ds.Tables[0].Rows[2]["name"], Is.EqualTo(String.Empty)); } [Test] @@ -103,8 +103,8 @@ public void TestUpdate() int count = da.Update(dt); // make sure our refresh of auto increment values worked - Assert.True(count == 1, "checking insert count"); - Assert.True(dt.Rows[dt.Rows.Count - 1]["id"] != null, "Checking auto increment column"); + Assert.That(count == 1, "checking insert count"); + Assert.That(dt.Rows[dt.Rows.Count - 1]["id"] != null, "Checking auto increment column"); dt.Rows.Clear(); da.Fill(dt); @@ -116,25 +116,25 @@ public void TestUpdate() dt.Rows[0]["tm"] = day1.TimeOfDay; count = da.Update(dt); - Assert.True(dt.Rows[0]["ts"] != null, "checking refresh of record"); - Assert.True(dt.Rows[0]["id2"] != null, "checking refresh of primary column"); + Assert.That(dt.Rows[0]["ts"] != null, "checking refresh of record"); + Assert.That(dt.Rows[0]["id2"] != null, "checking refresh of primary column"); dt.Rows.Clear(); da.Fill(dt); - Assert.True(count == 1, "checking update count"); + Assert.That(count == 1, "checking update count"); DateTime dateTime = (DateTime)dt.Rows[0]["dt"]; - Assert.True(day1.Date == dateTime.Date, "checking date"); - Assert.True(day1.TimeOfDay == (TimeSpan)dt.Rows[0]["tm"], "checking time"); + Assert.That(day1.Date == dateTime.Date, "checking date"); + Assert.That(day1.TimeOfDay == (TimeSpan)dt.Rows[0]["tm"], "checking time"); dt.Rows[0].Delete(); count = da.Update(dt); - Assert.True(count == 1, "checking insert count"); + Assert.That(count == 1, "checking insert count"); dt.Rows.Clear(); da.Fill(dt); - Assert.True(dt.Rows.Count == 0, "checking row count"); + Assert.That(dt.Rows.Count == 0, "checking row count"); cb.Dispose(); } @@ -159,8 +159,8 @@ public void OriginalInName() dt.Rows.Add(row); da.Update(dt); - Assert.AreEqual(1, dt.Rows.Count); - Assert.AreEqual(2, dt.Rows[0]["OriginalId"]); + Assert.That(dt.Rows.Count, Is.EqualTo(1)); + Assert.That(dt.Rows[0]["OriginalId"], Is.EqualTo(2)); } [Test] @@ -179,13 +179,13 @@ public void UseAdapterPropertyOfCommandBuilder() dt.Rows[0]["name"] = "Test Update"; int updateCnt = da.Update(dt); - Assert.AreEqual(1, updateCnt); + Assert.That(updateCnt, Is.EqualTo(1)); dt.Rows.Clear(); da.Fill(dt); - Assert.AreEqual(1, dt.Rows.Count); - Assert.AreEqual("Test Update", dt.Rows[0]["name"]); + Assert.That(dt.Rows.Count, Is.EqualTo(1)); + Assert.That(dt.Rows[0]["name"], Is.EqualTo("Test Update")); } [Test] @@ -204,13 +204,13 @@ public void UpdateNullTextFieldToEmptyString() dt.Rows[0]["name"] = ""; int updateCnt = da.Update(dt); - Assert.AreEqual(1, updateCnt); + Assert.That(updateCnt, Is.EqualTo(1)); dt.Rows.Clear(); da.Fill(dt); - Assert.AreEqual(1, dt.Rows.Count); - Assert.AreEqual("", dt.Rows[0]["name"]); + Assert.That(dt.Rows.Count, Is.EqualTo(1)); + Assert.That(dt.Rows[0]["name"], Is.EqualTo("")); } [Test] @@ -230,7 +230,7 @@ public void UpdateExtendedTextFields() dt.Clear(); da.Fill(dt); - Assert.AreEqual("This is my new note", dt.Rows[0]["notes"]); + Assert.That(dt.Rows[0]["notes"], Is.EqualTo("This is my new note")); } [Test] @@ -244,7 +244,7 @@ public void SelectMoreThan252Rows() DataTable dt = new DataTable(); da.Fill(dt); - Assert.AreEqual(500, dt.Rows.Count); + Assert.That(dt.Rows.Count, Is.EqualTo(500)); } [Test] @@ -258,14 +258,14 @@ public void DiscreteValues() DataTable dt = new DataTable(); da.Fill(dt); - Assert.AreEqual("Test", dt.Rows[0]["name"]); - Assert.AreEqual("Test 1", dt.Rows[1]["name"]); + Assert.That(dt.Rows[0]["name"], Is.EqualTo("Test")); + Assert.That(dt.Rows[1]["name"], Is.EqualTo("Test 1")); - Assert.AreEqual("Text 1", dt.Rows[0]["b1"]); - Assert.AreEqual("Text 2", dt.Rows[1]["b1"]); + Assert.That(dt.Rows[0]["b1"], Is.EqualTo("Text 1")); + Assert.That(dt.Rows[1]["b1"], Is.EqualTo("Text 2")); - Assert.AreEqual(new DateTime(2004, 8, 1, 0, 0, 0).ToString(), dt.Rows[0]["dt"].ToString()); - Assert.AreEqual(new DateTime(2004, 7, 2, 0, 0, 0).ToString(), dt.Rows[1]["dt"].ToString()); + Assert.That(dt.Rows[0]["dt"].ToString(), Is.EqualTo(new DateTime(2004, 8, 1, 0, 0, 0).ToString())); + Assert.That(dt.Rows[1]["dt"].ToString(), Is.EqualTo(new DateTime(2004, 7, 2, 0, 0, 0).ToString())); } [Test] @@ -280,14 +280,14 @@ public void Bug5798() DataTable dt = new DataTable(); da.Fill(dt); - Assert.AreEqual(String.Empty, dt.Rows[0]["name"]); + Assert.That(dt.Rows[0]["name"], Is.EqualTo(String.Empty)); dt.Rows[0]["name"] = "Test"; da.Update(dt); dt.Clear(); da.Fill(dt); - Assert.AreEqual("Test", dt.Rows[0]["name"]); + Assert.That(dt.Rows[0]["name"], Is.EqualTo("Test")); } [Test] @@ -312,11 +312,11 @@ public void TestFillWithHelper() string sql = "SELECT table1.key FROM table1 WHERE table1.key=1; " + "SELECT table2.key FROM table2 WHERE table2.key=1"; DataSet ds = MySqlHelper.ExecuteDataset(Connection, sql, null); - Assert.AreEqual(2, ds.Tables.Count); - Assert.AreEqual(1, ds.Tables[0].Rows.Count); - Assert.AreEqual(1, ds.Tables[1].Rows.Count); - Assert.AreEqual(1, ds.Tables[0].Rows[0]["key"]); - Assert.AreEqual(1, ds.Tables[1].Rows[0]["key"]); + Assert.That(ds.Tables.Count, Is.EqualTo(2)); + Assert.That(ds.Tables[0].Rows.Count, Is.EqualTo(1)); + Assert.That(ds.Tables[1].Rows.Count, Is.EqualTo(1)); + Assert.That(ds.Tables[0].Rows[0]["key"], Is.EqualTo(1)); + Assert.That(ds.Tables[1].Rows[0]["key"], Is.EqualTo(1)); } /// @@ -332,7 +332,7 @@ public void AutoIncrementColumns() MySqlCommandBuilder cb = new MySqlCommandBuilder(da); DataSet ds = new DataSet(); da.Fill(ds); - Assert.AreEqual(1, Convert.ToInt32(ds.Tables[0].Rows[0]["id"])); + Assert.That(Convert.ToInt32(ds.Tables[0].Rows[0]["id"]), Is.EqualTo(1)); DataRow row = ds.Tables[0].NewRow(); ds.Tables[0].Rows.Add(row); @@ -340,8 +340,8 @@ public void AutoIncrementColumns() ds.Clear(); da.Fill(ds); - Assert.AreEqual(1, Convert.ToInt32(ds.Tables[0].Rows[0]["id"])); - Assert.AreEqual(2, Convert.ToInt32(ds.Tables[0].Rows[1]["id"])); + Assert.That(Convert.ToInt32(ds.Tables[0].Rows[0]["id"]), Is.EqualTo(1)); + Assert.That(Convert.ToInt32(ds.Tables[0].Rows[1]["id"]), Is.EqualTo(2)); cb.Dispose(); } @@ -360,9 +360,9 @@ public void Rollup() da.Fill(ds); Assert.That(ds.Tables, Has.One.Items); - Assert.AreEqual(3, ds.Tables[0].Rows.Count); - Assert.AreEqual(88, ds.Tables[0].Rows[2]["amount"]); - Assert.AreEqual(DBNull.Value, ds.Tables[0].Rows[2]["id"]); + Assert.That(ds.Tables[0].Rows.Count, Is.EqualTo(3)); + Assert.That(ds.Tables[0].Rows[2]["amount"], Is.EqualTo(88)); + Assert.That(ds.Tables[0].Rows[2]["id"], Is.EqualTo(DBNull.Value)); } /// @@ -407,7 +407,7 @@ public void Bug16307() { reader.Read(); int intCallNum = Int32.Parse(reader.GetValue(0).ToString()); - Assert.AreEqual(1, intCallNum); + Assert.That(intCallNum, Is.EqualTo(1)); } } @@ -424,24 +424,24 @@ public void QuietOpenAndClose() { MySqlDataAdapter da = new MySqlDataAdapter("SELECT * FROM Test", c); MySqlCommandBuilder cb = new MySqlCommandBuilder(da); - Assert.True(c.State == ConnectionState.Closed); + Assert.That(c.State == ConnectionState.Closed); DataTable dt = new DataTable(); da.Fill(dt); - Assert.True(c.State == ConnectionState.Closed); - Assert.AreEqual(1, dt.Rows.Count); + Assert.That(c.State == ConnectionState.Closed); + Assert.That(dt.Rows.Count, Is.EqualTo(1)); dt.Rows[0][0] = 2; DataRow[] rows = new DataRow[1]; rows[0] = dt.Rows[0]; da.Update(dt); - Assert.True(c.State == ConnectionState.Closed); + Assert.That(c.State == ConnectionState.Closed); dt.Clear(); c.Open(); - Assert.True(c.State == ConnectionState.Open); + Assert.That(c.State == ConnectionState.Open); da.Fill(dt); - Assert.True(c.State == ConnectionState.Open); - Assert.AreEqual(1, dt.Rows.Count); + Assert.That(c.State == ConnectionState.Open); + Assert.That(dt.Rows.Count, Is.EqualTo(1)); cb.Dispose(); } } @@ -481,9 +481,9 @@ public void FillWithNulls() dt.Clear(); da.Fill(dt); - Assert.AreEqual(1, dt.Rows.Count); - Assert.AreEqual(1, dt.Rows[0]["id"]); - Assert.AreEqual("Test1", dt.Rows[0]["name"]); + Assert.That(dt.Rows.Count, Is.EqualTo(1)); + Assert.That(dt.Rows[0]["id"], Is.EqualTo(1)); + Assert.That(dt.Rows[0]["name"], Is.EqualTo("Test1")); row = dt.NewRow(); row["name"] = System.DBNull.Value; @@ -493,9 +493,9 @@ public void FillWithNulls() dt.Clear(); da.Fill(dt); - Assert.AreEqual(2, dt.Rows.Count); - Assert.AreEqual(2, dt.Rows[1]["id"]); - Assert.AreEqual(DBNull.Value, dt.Rows[1]["name"]); + Assert.That(dt.Rows.Count, Is.EqualTo(2)); + Assert.That(dt.Rows[1]["id"], Is.EqualTo(2)); + Assert.That(dt.Rows[1]["name"], Is.EqualTo(DBNull.Value)); row = dt.NewRow(); row["name"] = "Test3"; @@ -505,9 +505,9 @@ public void FillWithNulls() dt.Clear(); da.Fill(dt); - Assert.AreEqual(3, dt.Rows.Count); - Assert.AreEqual(3, dt.Rows[2]["id"]); - Assert.AreEqual("Test3", dt.Rows[2]["name"]); + Assert.That(dt.Rows.Count, Is.EqualTo(3)); + Assert.That(dt.Rows[2]["id"], Is.EqualTo(3)); + Assert.That(dt.Rows[2]["name"], Is.EqualTo("Test3")); cb.Dispose(); } @@ -530,7 +530,7 @@ public void PagingFill() MySqlDataAdapter da = new MySqlDataAdapter("SELECT * FROM Test", Connection); DataTable dt = new DataTable(); da.Fill(0, 10, new DataTable[] { dt }); - Assert.AreEqual(10, dt.Rows.Count); + Assert.That(dt.Rows.Count, Is.EqualTo(10)); } private string MakeLargeString(int len) @@ -591,11 +591,11 @@ public void TestBatchingInserts() dt.Rows.Clear(); da.Fill(dt); - Assert.AreEqual(100, dt.Rows.Count); + Assert.That(dt.Rows.Count, Is.EqualTo(100)); for (int i = 0; i < 100; i++) { - Assert.AreEqual(i + 1, dt.Rows[i]["id"]); - Assert.AreEqual("name " + (i + 1), dt.Rows[i]["name"]); + Assert.That(dt.Rows[i]["id"], Is.EqualTo(i + 1)); + Assert.That(dt.Rows[i]["name"], Is.EqualTo("name " + (i + 1))); } } @@ -627,13 +627,13 @@ public void TestBatchingUpdates() dt.Rows.Clear(); da.Fill(dt); - Assert.AreEqual(3, dt.Rows.Count); - Assert.AreEqual(2, dt.Rows[0]["id"]); - Assert.AreEqual(4, dt.Rows[1]["id"]); - Assert.AreEqual(6, dt.Rows[2]["id"]); - Assert.AreEqual("new test value", dt.Rows[0]["name"]); - Assert.AreEqual("Test 1", dt.Rows[1]["name"]); - Assert.AreEqual("new test value #2", dt.Rows[2]["name"]); + Assert.That(dt.Rows.Count, Is.EqualTo(3)); + Assert.That(dt.Rows[0]["id"], Is.EqualTo(2)); + Assert.That(dt.Rows[1]["id"], Is.EqualTo(4)); + Assert.That(dt.Rows[2]["id"], Is.EqualTo(6)); + Assert.That(dt.Rows[0]["name"], Is.EqualTo("new test value")); + Assert.That(dt.Rows[1]["name"], Is.EqualTo("Test 1")); + Assert.That(dt.Rows[2]["name"], Is.EqualTo("new test value #2")); } [Test] @@ -675,13 +675,13 @@ public void TestBatchingMixed() dt.Rows.Clear(); da.Fill(dt); - Assert.AreEqual(3, dt.Rows.Count); - Assert.AreEqual(4, dt.Rows[0]["id"]); - Assert.AreEqual(6, dt.Rows[1]["id"]); - Assert.AreEqual(7, dt.Rows[2]["id"]); - Assert.AreEqual("Test 1", dt.Rows[0]["name"]); - Assert.AreEqual("new test value #2", dt.Rows[1]["name"]); - Assert.AreEqual("foobar", dt.Rows[2]["name"]); + Assert.That(dt.Rows.Count, Is.EqualTo(3)); + Assert.That(dt.Rows[0]["id"], Is.EqualTo(4)); + Assert.That(dt.Rows[1]["id"], Is.EqualTo(6)); + Assert.That(dt.Rows[2]["id"], Is.EqualTo(7)); + Assert.That(dt.Rows[0]["name"], Is.EqualTo("Test 1")); + Assert.That(dt.Rows[1]["name"], Is.EqualTo("new test value #2")); + Assert.That(dt.Rows[2]["name"], Is.EqualTo("foobar")); } [Test] @@ -717,9 +717,9 @@ public void TestBatchingInsertsMoreThanMaxPacket() dt.Rows.Clear(); da.Fill(dt); - Assert.AreEqual(numRows, dt.Rows.Count); + Assert.That(dt.Rows.Count, Is.EqualTo(numRows)); for (int i = 0; i < numRows; i++) - Assert.AreEqual(i, dt.Rows[i]["id"]); + Assert.That(dt.Rows[i]["id"], Is.EqualTo(i)); } [Test] @@ -733,9 +733,9 @@ public void FunctionsReturnString() MySqlDataAdapter da = new MySqlDataAdapter("SELECT CONCAT(1,2)", c); DataTable dt = new DataTable(); da.Fill(dt); - Assert.AreEqual(1, dt.Rows.Count); - Assert.AreEqual("12", dt.Rows[0][0]); - Assert.True(dt.Rows[0][0] is string); + Assert.That(dt.Rows.Count, Is.EqualTo(1)); + Assert.That(dt.Rows[0][0], Is.EqualTo("12")); + Assert.That(dt.Rows[0][0] is string); } } @@ -804,7 +804,7 @@ public void AdapterConcurrentException() table.Rows.Add(r); da.Update(table); - Assert.AreEqual(DataRowState.Unchanged, r.RowState); + Assert.That(r.RowState, Is.EqualTo(DataRowState.Unchanged)); table.Rows[0].Delete(); @@ -814,8 +814,8 @@ public void AdapterConcurrentException() da.Update(table); // here was concurrencyviolation da.Fill(ds); - Assert.AreEqual(1, ds.Tables["T"].Rows.Count); - Assert.AreEqual("row2", ds.Tables["T"].Rows[0]["field"]); + Assert.That(ds.Tables["T"].Rows.Count, Is.EqualTo(1)); + Assert.That(ds.Tables["T"].Rows[0]["field"], Is.EqualTo("row2")); } /// @@ -866,11 +866,11 @@ public void BatchingConnectionClosed() dt.Rows.Clear(); da.Fill(dt); - Assert.AreEqual(100, dt.Rows.Count); + Assert.That(dt.Rows.Count, Is.EqualTo(100)); for (int i = 0; i < 100; i++) { - Assert.AreEqual(i + 1, dt.Rows[i]["id"]); - Assert.AreEqual("name " + (i + 1), dt.Rows[i]["name"]); + Assert.That(dt.Rows[i]["id"], Is.EqualTo(i + 1)); + Assert.That(dt.Rows[i]["name"], Is.EqualTo("name " + (i + 1))); } foreach (DataRow row in dt.Rows) @@ -885,7 +885,7 @@ public void BatchingConnectionClosed() da.Update(dt); dt.Rows.Clear(); da.Fill(dt); - Assert.AreEqual(0, dt.Rows.Count); + Assert.That(dt.Rows.Count, Is.EqualTo(0)); } @@ -950,13 +950,13 @@ public void UpdateReturnFirstRecord() DataTable table = ds.Tables["bugtable"]; DataRow row = table.Rows[0]; row["field"] = "newvalue"; - Assert.AreEqual(DataRowState.Modified, row.RowState); - Assert.AreEqual(0, (int)row["counter"]); + Assert.That(row.RowState, Is.EqualTo(DataRowState.Modified)); + Assert.That((int)row["counter"], Is.EqualTo(0)); da.Update(table); // Verify that "counter" field was changed by updating stored procedure. - Assert.AreEqual(1, (int)row["counter"]); + Assert.That((int)row["counter"], Is.EqualTo(1)); } [Test] @@ -973,13 +973,13 @@ public void FillFromStoredProcedureMultipleTimesCreatesExpectedRows() adapter.SelectCommand.CommandType = CommandType.StoredProcedure; DataTable table = new DataTable(); adapter.Fill(table); - Assert.AreEqual(1, table.Rows.Count); + Assert.That(table.Rows.Count, Is.EqualTo(1)); adapter = new MySqlDataAdapter("SimpleSelect", connection); adapter.SelectCommand.CommandType = CommandType.StoredProcedure; table = new DataTable(); adapter.Fill(table); - Assert.AreEqual(1, table.Rows.Count); + Assert.That(table.Rows.Count, Is.EqualTo(1)); MySqlConnection.ClearPool(connection); } @@ -1000,7 +1000,7 @@ public void ChangeStoredProcedureBasedSelectCommandDoesNotThrow() adapter.SelectCommand.CommandType = CommandType.StoredProcedure; DataTable table = new DataTable(); adapter.Fill(table); - Assert.AreEqual(1, table.Rows.Count); + Assert.That(table.Rows.Count, Is.EqualTo(1)); adapter.SelectCommand = new MySqlCommand("SimpleSelect2", connection); adapter.SelectCommand.CommandType = CommandType.StoredProcedure; @@ -1009,7 +1009,7 @@ public void ChangeStoredProcedureBasedSelectCommandDoesNotThrow() try { adapter.Fill(table); - Assert.AreEqual(1, table.Rows.Count); + Assert.That(table.Rows.Count, Is.EqualTo(1)); } finally { @@ -1037,7 +1037,7 @@ public async Task CommandBuilderAsync() var changes = dt.GetChanges(); var count = da.Update(changes); dt.AcceptChanges(); - Assert.True(count == 1, "checking update count"); + Assert.That(count == 1, "checking update count"); await conn.CloseAsync(); } @@ -1054,7 +1054,7 @@ public async Task CommandBuilderAsync() var changes = dt.GetChanges(); var count = da.Update(changes); dt.AcceptChanges(); - Assert.True(count == 1, "checking update count"); + Assert.That(count == 1, "checking update count"); await conn.CloseAsync(); } } @@ -1105,7 +1105,7 @@ public void BatchOverMaxPacketAllowed() dataAdapter.UpdateBatchSize = 2; var ex = Assert.Throws(() => dataAdapter.Update(dataRows)); - StringAssert.AreEqualIgnoringCase(Resources.QueryTooLarge, ex.Message); + Assert.That(ex.Message, Is.EqualTo(Resources.QueryTooLarge).IgnoreCase); } // setting back to the initial value @@ -1126,31 +1126,31 @@ public async Task FillAsyncDataSet() await da.FillAsync(ds, "DAFillAsyncTest"); Assert.That(ds.Tables, Has.One.Items); - Assert.AreEqual(3, ds.Tables[0].Rows.Count); + Assert.That(ds.Tables[0].Rows.Count, Is.EqualTo(3)); - Assert.AreEqual(1, ds.Tables[0].Rows[0]["id2"]); - Assert.AreEqual(2, ds.Tables[0].Rows[1]["id2"]); - Assert.AreEqual(3, ds.Tables[0].Rows[2]["id2"]); + Assert.That(ds.Tables[0].Rows[0]["id2"], Is.EqualTo(1)); + Assert.That(ds.Tables[0].Rows[1]["id2"], Is.EqualTo(2)); + Assert.That(ds.Tables[0].Rows[2]["id2"], Is.EqualTo(3)); - Assert.AreEqual("Name 1", ds.Tables[0].Rows[0]["name"]); - Assert.AreEqual(DBNull.Value, ds.Tables[0].Rows[1]["name"]); - Assert.AreEqual(String.Empty, ds.Tables[0].Rows[2]["name"]); + Assert.That(ds.Tables[0].Rows[0]["name"], Is.EqualTo("Name 1")); + Assert.That(ds.Tables[0].Rows[1]["name"], Is.EqualTo(DBNull.Value)); + Assert.That(ds.Tables[0].Rows[2]["name"], Is.EqualTo(String.Empty)); ds.Reset(); await da.FillAsync(ds); Assert.That(ds.Tables, Has.One.Items); - Assert.AreEqual(3, ds.Tables[0].Rows.Count); - Assert.AreEqual("Name 1", ds.Tables[0].Rows[0]["name"]); + Assert.That(ds.Tables[0].Rows.Count, Is.EqualTo(3)); + Assert.That(ds.Tables[0].Rows[0]["name"], Is.EqualTo("Name 1")); ds.Reset(); await da.FillAsync(ds, 1, 2, "DAFillAsyncTest"); Assert.That(ds.Tables, Has.One.Items); - Assert.AreEqual(2, ds.Tables[0].Rows.Count); - Assert.AreEqual(2, ds.Tables[0].Rows[0]["id2"]); - Assert.AreEqual(DBNull.Value, ds.Tables[0].Rows[0]["name"]); - Assert.AreEqual(String.Empty, ds.Tables[0].Rows[1]["name"]); + Assert.That(ds.Tables[0].Rows.Count, Is.EqualTo(2)); + Assert.That(ds.Tables[0].Rows[0]["id2"], Is.EqualTo(2)); + Assert.That(ds.Tables[0].Rows[0]["name"], Is.EqualTo(DBNull.Value)); + Assert.That(ds.Tables[0].Rows[1]["name"], Is.EqualTo(String.Empty)); ds.Reset(); using (MySqlCommand cmd = new MySqlCommand("select * from DAFillAsyncTest", Connection)) @@ -1158,18 +1158,18 @@ public async Task FillAsyncDataSet() await da.FillAsync(ds, "DAFillAsyncTest", reader, 0, 1); Assert.That(ds.Tables, Has.One.Items); - Assert.AreEqual(1, ds.Tables[0].Rows.Count); - Assert.AreEqual(1, ds.Tables[0].Rows[0]["id2"]); - Assert.AreEqual("Name 1", ds.Tables[0].Rows[0]["name"]); + Assert.That(ds.Tables[0].Rows.Count, Is.EqualTo(1)); + Assert.That(ds.Tables[0].Rows[0]["id2"], Is.EqualTo(1)); + Assert.That(ds.Tables[0].Rows[0]["name"], Is.EqualTo("Name 1")); ds.Reset(); using (MySqlCommand cmd = new MySqlCommand("select * from DAFillAsyncTest", Connection)) await da.FillAsync(ds, 0, 2, "DAFillAsyncTest", cmd, CommandBehavior.Default); Assert.That(ds.Tables, Has.One.Items); - Assert.AreEqual(2, ds.Tables[0].Rows.Count); - Assert.AreEqual(1, ds.Tables[0].Rows[0]["id2"]); - Assert.AreEqual(DBNull.Value, ds.Tables[0].Rows[1]["name"]); + Assert.That(ds.Tables[0].Rows.Count, Is.EqualTo(2)); + Assert.That(ds.Tables[0].Rows[0]["id2"], Is.EqualTo(1)); + Assert.That(ds.Tables[0].Rows[1]["name"], Is.EqualTo(DBNull.Value)); } [Test] @@ -1185,51 +1185,51 @@ public async Task FillAsyncDataTable() DataTable dt = new DataTable(); await da.FillAsync(dt); - Assert.AreEqual(3, dt.Rows.Count); - Assert.AreEqual(7, dt.Columns.Count); - Assert.AreEqual("Name 1", dt.Rows[0]["name"]); - Assert.AreEqual(DBNull.Value, dt.Rows[1]["name"]); - Assert.AreEqual(String.Empty, dt.Rows[2]["name"]); + Assert.That(dt.Rows.Count, Is.EqualTo(3)); + Assert.That(dt.Columns.Count, Is.EqualTo(7)); + Assert.That(dt.Rows[0]["name"], Is.EqualTo("Name 1")); + Assert.That(dt.Rows[1]["name"], Is.EqualTo(DBNull.Value)); + Assert.That(dt.Rows[2]["name"], Is.EqualTo(String.Empty)); dt.Reset(); using (MySqlCommand cmd = new MySqlCommand("select * from DAFillAsyncDtTest", Connection)) using (MySqlDataReader reader = cmd.ExecuteReader()) await da.FillAsync(dt, reader); - Assert.AreEqual(3, dt.Rows.Count); - Assert.AreEqual(7, dt.Columns.Count); - Assert.AreEqual(1, dt.Rows[0]["id2"]); - Assert.AreEqual(2, dt.Rows[1]["id2"]); - Assert.AreEqual(3, dt.Rows[2]["id2"]); + Assert.That(dt.Rows.Count, Is.EqualTo(3)); + Assert.That(dt.Columns.Count, Is.EqualTo(7)); + Assert.That(dt.Rows[0]["id2"], Is.EqualTo(1)); + Assert.That(dt.Rows[1]["id2"], Is.EqualTo(2)); + Assert.That(dt.Rows[2]["id2"], Is.EqualTo(3)); dt.Reset(); using (MySqlCommand cmd = new MySqlCommand("select * from DAFillAsyncDtTest", Connection)) await da.FillAsync(dt, cmd, CommandBehavior.Default); - Assert.AreEqual(3, dt.Rows.Count); - Assert.AreEqual(7, dt.Columns.Count); - Assert.AreEqual(DBNull.Value, dt.Rows[1]["name"]); - Assert.AreEqual(2, dt.Rows[1]["id2"]); - Assert.AreEqual(3, dt.Rows[2]["id2"]); + Assert.That(dt.Rows.Count, Is.EqualTo(3)); + Assert.That(dt.Columns.Count, Is.EqualTo(7)); + Assert.That(dt.Rows[1]["name"], Is.EqualTo(DBNull.Value)); + Assert.That(dt.Rows[1]["id2"], Is.EqualTo(2)); + Assert.That(dt.Rows[2]["id2"], Is.EqualTo(3)); dt.Reset(); DataTable[] dataTables = { dt }; await da.FillAsync(0, 1, dataTables); Assert.That(dataTables, Has.One.Items); - Assert.AreEqual(1, dataTables[0].Rows.Count); - Assert.AreEqual(1, dataTables[0].Rows[0]["id2"]); - Assert.AreEqual("Name 1", dataTables[0].Rows[0]["name"]); + Assert.That(dataTables[0].Rows.Count, Is.EqualTo(1)); + Assert.That(dataTables[0].Rows[0]["id2"], Is.EqualTo(1)); + Assert.That(dataTables[0].Rows[0]["name"], Is.EqualTo("Name 1")); dt.Reset(); using (MySqlCommand cmd = new MySqlCommand("select * from DAFillAsyncDtTest", Connection)) await da.FillAsync(dataTables, 1, 2, cmd, CommandBehavior.Default); Assert.That(dataTables, Has.One.Items); - Assert.AreEqual(2, dataTables[0].Rows.Count); - Assert.AreEqual(2, dataTables[0].Rows[0]["id2"]); - Assert.AreEqual(DBNull.Value, dataTables[0].Rows[0]["name"]); - Assert.AreEqual(String.Empty, dataTables[0].Rows[1]["name"]); + Assert.That(dataTables[0].Rows.Count, Is.EqualTo(2)); + Assert.That(dataTables[0].Rows[0]["id2"], Is.EqualTo(2)); + Assert.That(dataTables[0].Rows[0]["name"], Is.EqualTo(DBNull.Value)); + Assert.That(dataTables[0].Rows[1]["name"], Is.EqualTo(String.Empty)); } [Test] @@ -1248,48 +1248,48 @@ public async Task FillSchemaAsync() MySqlDataAdapter da = new MySqlDataAdapter(cmd); DataTable schema = new DataTable(); await da.FillSchemaAsync(schema, SchemaType.Source); - Assert.AreEqual(2, schema.Columns.Count); + Assert.That(schema.Columns.Count, Is.EqualTo(2)); DataSet ds = new DataSet(); await da.FillSchemaAsync(ds, SchemaType.Source); - Assert.True(ds.Tables.Count == 1); - Assert.AreEqual(2, ds.Tables[0].Columns.Count); + Assert.That(ds.Tables.Count == 1); + Assert.That(ds.Tables[0].Columns.Count, Is.EqualTo(2)); ds.Reset(); using (cmd) using (reader = cmd.ExecuteReader(CommandBehavior.SchemaOnly)) await da.FillSchemaAsync(ds, SchemaType.Source, "DAFillSchemaAsyncTest", reader); - Assert.True(ds.Tables.Count == 1); - Assert.AreEqual(2, ds.Tables[0].Columns.Count); + Assert.That(ds.Tables.Count == 1); + Assert.That(ds.Tables[0].Columns.Count, Is.EqualTo(2)); ds.Reset(); using (cmd) await da.FillSchemaAsync(ds, SchemaType.Source, cmd, "DAFillSchemaAsyncTest", CommandBehavior.SchemaOnly); - Assert.True(ds.Tables.Count == 1); - Assert.AreEqual(2, ds.Tables[0].Columns.Count); + Assert.That(ds.Tables.Count == 1); + Assert.That(ds.Tables[0].Columns.Count, Is.EqualTo(2)); ds.Reset(); using (cmd) await da.FillSchemaAsync(ds, SchemaType.Source, "DAFillSchemaAsyncTest", CancellationToken.None); - Assert.True(ds.Tables.Count == 1); - Assert.AreEqual(2, ds.Tables[0].Columns.Count); + Assert.That(ds.Tables.Count == 1); + Assert.That(ds.Tables[0].Columns.Count, Is.EqualTo(2)); DataTable dataTable = new DataTable(); using (cmd) using (reader = cmd.ExecuteReader(CommandBehavior.SchemaOnly)) await da.FillSchemaAsync(dataTable, SchemaType.Source, reader); - Assert.AreEqual(2, dataTable.Columns.Count); + Assert.That(dataTable.Columns.Count, Is.EqualTo(2)); dataTable.Reset(); using (cmd) await da.FillSchemaAsync(dataTable, SchemaType.Source, cmd, CommandBehavior.SchemaOnly); - Assert.AreEqual(2, dataTable.Columns.Count); - Assert.AreEqual("id", dataTable.Columns[0].ColumnName); + Assert.That(dataTable.Columns.Count, Is.EqualTo(2)); + Assert.That(dataTable.Columns[0].ColumnName, Is.EqualTo("id")); } [Test] @@ -1307,8 +1307,8 @@ public async Task UpdateAsync() dt.Rows.Add(dr); int count = await da.UpdateAsync(dt); - Assert.True(count == 1, "checking insert count"); - Assert.True(dt.Rows[dt.Rows.Count - 1]["id"] != null, "Checking auto increment column"); + Assert.That(count == 1, "checking insert count"); + Assert.That(dt.Rows[dt.Rows.Count - 1]["id"] != null, "Checking auto increment column"); dt.Rows.Clear(); da.Fill(dt); @@ -1320,25 +1320,25 @@ public async Task UpdateAsync() dt.Rows[0]["tm"] = day1.TimeOfDay; count = await da.UpdateAsync(dt); - Assert.True(dt.Rows[0]["ts"] != null, "checking refresh of record"); - Assert.True(dt.Rows[0]["id2"] != null, "checking refresh of primary column"); + Assert.That(dt.Rows[0]["ts"] != null, "checking refresh of record"); + Assert.That(dt.Rows[0]["id2"] != null, "checking refresh of primary column"); dt.Rows.Clear(); da.Fill(dt); - Assert.True(count == 1, "checking update count"); + Assert.That(count == 1, "checking update count"); DateTime dateTime = (DateTime)dt.Rows[0]["dt"]; - Assert.True(day1.Date == dateTime.Date, "checking date"); - Assert.True(day1.TimeOfDay == (TimeSpan)dt.Rows[0]["tm"], "checking time"); + Assert.That(day1.Date == dateTime.Date, "checking date"); + Assert.That(day1.TimeOfDay == (TimeSpan)dt.Rows[0]["tm"], "checking time"); dt.Rows[0].Delete(); count = await da.UpdateAsync(dt); - Assert.True(count == 1, "checking insert count"); + Assert.That(count == 1, "checking insert count"); dt.Rows.Clear(); da.Fill(dt); - Assert.True(dt.Rows.Count == 0, "checking row count"); + Assert.That(dt.Rows.Count == 0, "checking row count"); dr = dt.NewRow(); dr["id2"] = 3; @@ -1347,7 +1347,7 @@ public async Task UpdateAsync() DataRow[] dataRows = dt.Select(null, null, DataViewRowState.Added); count = await da.UpdateAsync(dataRows); - Assert.True(count == 1, "checking update count"); + Assert.That(count == 1, "checking update count"); DataSet ds = new DataSet(); da.Fill(ds); @@ -1357,7 +1357,7 @@ public async Task UpdateAsync() ds.Tables[0].Rows.Add(dr); count = await da.UpdateAsync(ds); - Assert.True(count == 1, "checking update count"); + Assert.That(count == 1, "checking update count"); dr = dt.NewRow(); dr["id2"] = 4; @@ -1370,7 +1370,7 @@ public async Task UpdateAsync() dataRows = dt.Select(null, null, DataViewRowState.Added); count = await da.UpdateAsync(dataRows, mapping); - Assert.True(count == 1, "checking update count"); + Assert.That(count == 1, "checking update count"); ds.Reset(); da.FillSchema(ds, SchemaType.Mapped); @@ -1381,7 +1381,7 @@ public async Task UpdateAsync() ds.Tables[0].Rows.Add(dr); count = await da.UpdateAsync(ds, "Table"); - Assert.True(count == 1, "checking update count"); + Assert.That(count == 1, "checking update count"); cb.Dispose(); } diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MySqlDataReaderTests.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MySqlDataReaderTests.cs index 542ea6f54..0843a85a3 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MySqlDataReaderTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MySqlDataReaderTests.cs @@ -50,9 +50,9 @@ public void SchemaOnly() using (MySqlDataReader reader = cmd.ExecuteReader(CommandBehavior.SchemaOnly)) { DataTable table = reader.GetSchemaTable(); - Assert.AreEqual(5, table.Rows.Count); - Assert.AreEqual(22, table.Columns.Count); - Assert.False(reader.Read()); + Assert.That(table.Rows.Count, Is.EqualTo(5)); + Assert.That(table.Columns.Count, Is.EqualTo(22)); + Assert.That(!reader.Read()); } } diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/NETCore20Tests.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/NETCore20Tests.cs index 2d984200c..c559a33e5 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/NETCore20Tests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/NETCore20Tests.cs @@ -74,11 +74,11 @@ public void ConstraintsTest() ds.Relations.Add(dataRelation); Assert.That(ds.Tables[0].Constraints, Has.One.Items); - Assert.IsInstanceOf(ds.Tables[0].Constraints[0]); + Assert.That(ds.Tables[0].Constraints[0], Is.InstanceOf()); - Assert.AreEqual(2, ds.Tables[1].Constraints.Count); - Assert.IsInstanceOf(ds.Tables[0].Constraints[0]); - Assert.IsInstanceOf(ds.Tables[1].Constraints[1]); + Assert.That(ds.Tables[1].Constraints.Count, Is.EqualTo(2)); + Assert.That(ds.Tables[0].Constraints[0], Is.InstanceOf()); + Assert.That(ds.Tables[1].Constraints[1], Is.InstanceOf()); } [Test] @@ -96,16 +96,16 @@ public void DataTableReaderTest() using (DataTableReader dataTableReader = new DataTableReader(childDt)) { - Assert.True(dataTableReader.HasRows); - Assert.AreEqual(3, dataTableReader.FieldCount); + Assert.That(dataTableReader.HasRows); + Assert.That(dataTableReader.FieldCount, Is.EqualTo(3)); } PropertyCollection propertyCollection = childDt.ExtendedProperties; propertyCollection.Add("TimeStamp", DateTime.Now); propertyCollection.Add("Version", 1); - CollectionAssert.IsNotEmpty(childDt.ExtendedProperties); - Assert.AreEqual(2, childDt.ExtendedProperties.Count); + Assert.That(childDt.ExtendedProperties, Is.Not.Empty); + Assert.That(childDt.ExtendedProperties.Count, Is.EqualTo(2)); } [Test] @@ -139,9 +139,9 @@ public void DataViewSettingsTest() dataViewManager.DataViewSettings[parentDt].Sort = "name"; - Assert.True(dataViewManager.DataViewSettings[childDt].Sort == ""); - Assert.AreEqual("name", dataViewManager.DataViewSettings[parentDt].Sort); - CollectionAssert.IsNotEmpty(dataViewManager.DataViewSettings); + Assert.That(dataViewManager.DataViewSettings[childDt].Sort == ""); + Assert.That(dataViewManager.DataViewSettings[parentDt].Sort, Is.EqualTo("name")); + Assert.That(dataViewManager.DataViewSettings, Is.Not.Empty); } [Test] @@ -157,13 +157,13 @@ public void SchemaColumnTest() parentDa.Fill(parentDt); parentDt.Columns["id"].Unique = true; - Assert.True(parentDt.Columns[0].Unique); - Assert.False(parentDt.Columns[0].AllowDBNull); - Assert.AreEqual("name", parentDt.Columns[1].ColumnName); + Assert.That(parentDt.Columns[0].Unique); + Assert.That(!parentDt.Columns[0].AllowDBNull); + Assert.That(parentDt.Columns[1].ColumnName, Is.EqualTo("name")); - Assert.AreEqual(0, parentDt.Columns[0].AutoIncrementSeed); - Assert.False(parentDt.Columns[0].ReadOnly); - Assert.False(parentDt.Columns[1].AutoIncrement); + Assert.That(parentDt.Columns[0].AutoIncrementSeed, Is.EqualTo(0)); + Assert.That(!parentDt.Columns[0].ReadOnly); + Assert.That(!parentDt.Columns[1].AutoIncrement); } } } \ No newline at end of file diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/ProcedureParameterTests.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/ProcedureParameterTests.cs index c84deb683..928091759 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/ProcedureParameterTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/ProcedureParameterTests.cs @@ -44,23 +44,23 @@ public void ProcedureParameters() restrictions[1] = Connection.Database; restrictions[2] = "ProcedureParameters"; DataTable dt = Connection.GetSchema("Procedure Parameters", restrictions); - Assert.True(dt.Rows.Count == 2, "Actual result " + dt.Rows.Count); - Assert.AreEqual("Procedure Parameters", dt.TableName); - Assert.AreEqual(Connection.Database, dt.Rows[0]["SPECIFIC_SCHEMA"].ToString()); - Assert.AreEqual("ProcedureParameters", dt.Rows[0]["SPECIFIC_NAME"].ToString()); - Assert.AreEqual("id", dt.Rows[0]["PARAMETER_NAME"].ToString().ToLower()); - Assert.AreEqual(1, dt.Rows[0]["ORDINAL_POSITION"]); - Assert.AreEqual("IN", dt.Rows[0]["PARAMETER_MODE"]); + Assert.That(dt.Rows.Count == 2, "Actual result " + dt.Rows.Count); + Assert.That(dt.TableName, Is.EqualTo("Procedure Parameters")); + Assert.That(dt.Rows[0]["SPECIFIC_SCHEMA"].ToString(), Is.EqualTo(Connection.Database)); + Assert.That(dt.Rows[0]["SPECIFIC_NAME"].ToString(), Is.EqualTo("ProcedureParameters")); + Assert.That(dt.Rows[0]["PARAMETER_NAME"].ToString().ToLower(), Is.EqualTo("id")); + Assert.That(dt.Rows[0]["ORDINAL_POSITION"], Is.EqualTo(1)); + Assert.That(dt.Rows[0]["PARAMETER_MODE"], Is.EqualTo("IN")); restrictions[4] = "name"; dt.Clear(); dt = Connection.GetSchema("Procedure Parameters", restrictions); - Assert.AreEqual(1, dt.Rows.Count); - Assert.AreEqual(Connection.Database, dt.Rows[0]["SPECIFIC_SCHEMA"].ToString()); - Assert.AreEqual("ProcedureParameters", dt.Rows[0]["SPECIFIC_NAME"].ToString()); - Assert.AreEqual("name", dt.Rows[0]["PARAMETER_NAME"].ToString().ToLower()); - Assert.AreEqual(2, dt.Rows[0]["ORDINAL_POSITION"]); - Assert.AreEqual("IN", dt.Rows[0]["PARAMETER_MODE"]); + Assert.That(dt.Rows.Count, Is.EqualTo(1)); + Assert.That(dt.Rows[0]["SPECIFIC_SCHEMA"].ToString(), Is.EqualTo(Connection.Database)); + Assert.That(dt.Rows[0]["SPECIFIC_NAME"].ToString(), Is.EqualTo("ProcedureParameters")); + Assert.That(dt.Rows[0]["PARAMETER_NAME"].ToString().ToLower(), Is.EqualTo("name")); + Assert.That(dt.Rows[0]["ORDINAL_POSITION"], Is.EqualTo(2)); + Assert.That(dt.Rows[0]["PARAMETER_MODE"], Is.EqualTo("IN")); ExecuteSQL("DROP FUNCTION IF EXISTS spFunc"); ExecuteSQL("CREATE FUNCTION spFunc (id int) RETURNS INT BEGIN RETURN 1; END"); @@ -69,17 +69,17 @@ public void ProcedureParameters() restrictions[1] = Connection.Database; restrictions[2] = "spFunc"; dt = Connection.GetSchema("Procedure Parameters", restrictions); - Assert.True(dt.Rows.Count == 2); - Assert.AreEqual("Procedure Parameters", dt.TableName); - Assert.AreEqual(Connection.Database.ToLower(), dt.Rows[0]["SPECIFIC_SCHEMA"].ToString().ToLower()); - Assert.AreEqual("spfunc", dt.Rows[0]["SPECIFIC_NAME"].ToString().ToLower()); - Assert.AreEqual(0, dt.Rows[0]["ORDINAL_POSITION"]); - - Assert.AreEqual(Connection.Database.ToLower(), dt.Rows[1]["SPECIFIC_SCHEMA"].ToString().ToLower()); - Assert.AreEqual("spfunc", dt.Rows[1]["SPECIFIC_NAME"].ToString().ToLower()); - Assert.AreEqual("id", dt.Rows[1]["PARAMETER_NAME"].ToString().ToLower()); - Assert.AreEqual(1, dt.Rows[1]["ORDINAL_POSITION"]); - Assert.AreEqual("IN", dt.Rows[1]["PARAMETER_MODE"]); + Assert.That(dt.Rows.Count == 2); + Assert.That(dt.TableName, Is.EqualTo("Procedure Parameters")); + Assert.That(dt.Rows[0]["SPECIFIC_SCHEMA"].ToString().ToLower(), Is.EqualTo(Connection.Database.ToLower())); + Assert.That(dt.Rows[0]["SPECIFIC_NAME"].ToString().ToLower(), Is.EqualTo("spfunc")); + Assert.That(dt.Rows[0]["ORDINAL_POSITION"], Is.EqualTo(0)); + + Assert.That(dt.Rows[1]["SPECIFIC_SCHEMA"].ToString().ToLower(), Is.EqualTo(Connection.Database.ToLower())); + Assert.That(dt.Rows[1]["SPECIFIC_NAME"].ToString().ToLower(), Is.EqualTo("spfunc")); + Assert.That(dt.Rows[1]["PARAMETER_NAME"].ToString().ToLower(), Is.EqualTo("id")); + Assert.That(dt.Rows[1]["ORDINAL_POSITION"], Is.EqualTo(1)); + Assert.That(dt.Rows[1]["PARAMETER_MODE"], Is.EqualTo("IN")); } /// @@ -98,24 +98,24 @@ public void ProcedureParameters2() restrictions[2] = "spTest"; DataTable dt = Connection.GetSchema("Procedure Parameters", restrictions); - Assert.True(dt.Rows.Count == 2, "Actual result " + dt.Rows.Count); - Assert.AreEqual(Connection.Database.ToLower(), dt.Rows[0]["SPECIFIC_SCHEMA"].ToString().ToLower()); - Assert.AreEqual("sptest", dt.Rows[0]["SPECIFIC_NAME"].ToString().ToLower()); - Assert.AreEqual("/*id*/", dt.Rows[0]["PARAMETER_NAME"].ToString().ToLower()); - Assert.AreEqual(1, dt.Rows[0]["ORDINAL_POSITION"]); - Assert.AreEqual("IN", dt.Rows[0]["PARAMETER_MODE"]); - Assert.AreEqual("VARCHAR", dt.Rows[0]["DATA_TYPE"].ToString().ToUpper()); - Assert.AreEqual(20, dt.Rows[0]["CHARACTER_MAXIMUM_LENGTH"]); - Assert.AreEqual(20, dt.Rows[0]["CHARACTER_OCTET_LENGTH"]); - - Assert.AreEqual(Connection.Database.ToLower(), dt.Rows[1]["SPECIFIC_SCHEMA"].ToString().ToLower()); - Assert.AreEqual("sptest", dt.Rows[1]["SPECIFIC_NAME"].ToString().ToLower()); - Assert.AreEqual("result2", dt.Rows[1]["PARAMETER_NAME"].ToString().ToLower()); - Assert.AreEqual(2, dt.Rows[1]["ORDINAL_POSITION"]); - Assert.AreEqual("OUT", dt.Rows[1]["PARAMETER_MODE"]); - Assert.AreEqual("DECIMAL", dt.Rows[1]["DATA_TYPE"].ToString().ToUpper()); - Assert.AreEqual(10, Convert.ToInt32(dt.Rows[1]["NUMERIC_PRECISION"])); - Assert.AreEqual(2, dt.Rows[1]["NUMERIC_SCALE"]); + Assert.That(dt.Rows.Count == 2, "Actual result " + dt.Rows.Count); + Assert.That(dt.Rows[0]["SPECIFIC_SCHEMA"].ToString().ToLower(), Is.EqualTo(Connection.Database.ToLower())); + Assert.That(dt.Rows[0]["SPECIFIC_NAME"].ToString().ToLower(), Is.EqualTo("sptest")); + Assert.That(dt.Rows[0]["PARAMETER_NAME"].ToString().ToLower(), Is.EqualTo("/*id*/")); + Assert.That(dt.Rows[0]["ORDINAL_POSITION"], Is.EqualTo(1)); + Assert.That(dt.Rows[0]["PARAMETER_MODE"], Is.EqualTo("IN")); + Assert.That(dt.Rows[0]["DATA_TYPE"].ToString().ToUpper(), Is.EqualTo("VARCHAR")); + Assert.That(dt.Rows[0]["CHARACTER_MAXIMUM_LENGTH"], Is.EqualTo(20)); + Assert.That(dt.Rows[0]["CHARACTER_OCTET_LENGTH"], Is.EqualTo(20)); + + Assert.That(dt.Rows[1]["SPECIFIC_SCHEMA"].ToString().ToLower(), Is.EqualTo(Connection.Database.ToLower())); + Assert.That(dt.Rows[1]["SPECIFIC_NAME"].ToString().ToLower(), Is.EqualTo("sptest")); + Assert.That(dt.Rows[1]["PARAMETER_NAME"].ToString().ToLower(), Is.EqualTo("result2")); + Assert.That(dt.Rows[1]["ORDINAL_POSITION"], Is.EqualTo(2)); + Assert.That(dt.Rows[1]["PARAMETER_MODE"], Is.EqualTo("OUT")); + Assert.That(dt.Rows[1]["DATA_TYPE"].ToString().ToUpper(), Is.EqualTo("DECIMAL")); + Assert.That(Convert.ToInt32(dt.Rows[1]["NUMERIC_PRECISION"]), Is.EqualTo(10)); + Assert.That(dt.Rows[1]["NUMERIC_SCALE"], Is.EqualTo(2)); } [Test] @@ -147,96 +147,96 @@ _SONGS_LIST varchar(8000) character set latin1, restrictions[2] = "spTest"; DataTable dt = Connection.GetSchema("Procedure Parameters", restrictions); - Assert.True(dt.Rows.Count == 12, "Rows count failed"); - Assert.AreEqual(Connection.Database.ToLower(), dt.Rows[0]["SPECIFIC_SCHEMA"].ToString().ToLower()); - Assert.AreEqual("sptest", dt.Rows[0]["SPECIFIC_NAME"].ToString().ToLower()); - Assert.AreEqual("_action", dt.Rows[0]["PARAMETER_NAME"].ToString().ToLower()); - Assert.AreEqual(1, dt.Rows[0]["ORDINAL_POSITION"]); - Assert.AreEqual("IN", dt.Rows[0]["PARAMETER_MODE"]); - Assert.AreEqual("VARCHAR", dt.Rows[0]["DATA_TYPE"].ToString().ToUpper()); - Assert.AreEqual(20, dt.Rows[0]["CHARACTER_OCTET_LENGTH"]); - - Assert.AreEqual(Connection.Database.ToLower(), dt.Rows[1]["SPECIFIC_SCHEMA"].ToString().ToLower()); - Assert.AreEqual("sptest", dt.Rows[1]["SPECIFIC_NAME"].ToString().ToLower()); - Assert.AreEqual("/*dumb-identifier-1*/", dt.Rows[1]["PARAMETER_NAME"].ToString().ToLower()); - Assert.AreEqual(2, dt.Rows[1]["ORDINAL_POSITION"]); - Assert.AreEqual("IN", dt.Rows[1]["PARAMETER_MODE"]); - Assert.AreEqual("INT", dt.Rows[1]["DATA_TYPE"].ToString().ToUpper()); - - Assert.AreEqual(Connection.Database.ToLower(), dt.Rows[2]["SPECIFIC_SCHEMA"].ToString().ToLower()); - Assert.AreEqual("sptest", dt.Rows[2]["SPECIFIC_NAME"].ToString().ToLower()); - Assert.AreEqual("#dumb-identifier-2", dt.Rows[2]["PARAMETER_NAME"].ToString().ToLower()); - Assert.AreEqual(3, dt.Rows[2]["ORDINAL_POSITION"]); - Assert.AreEqual("IN", dt.Rows[2]["PARAMETER_MODE"]); - Assert.AreEqual("INT", dt.Rows[2]["DATA_TYPE"].ToString().ToUpper()); - - Assert.AreEqual(Connection.Database.ToLower(), dt.Rows[3]["SPECIFIC_SCHEMA"].ToString().ToLower()); - Assert.AreEqual("sptest", dt.Rows[3]["SPECIFIC_NAME"].ToString().ToLower()); - Assert.AreEqual("--dumb-identifier-3", dt.Rows[3]["PARAMETER_NAME"].ToString().ToLower()); - Assert.AreEqual(4, dt.Rows[3]["ORDINAL_POSITION"]); - Assert.AreEqual("IN", dt.Rows[3]["PARAMETER_MODE"]); - Assert.AreEqual("INT", dt.Rows[3]["DATA_TYPE"].ToString().ToUpper()); - - Assert.AreEqual(Connection.Database.ToLower(), dt.Rows[4]["SPECIFIC_SCHEMA"].ToString().ToLower()); - Assert.AreEqual("sptest", dt.Rows[4]["SPECIFIC_NAME"].ToString().ToLower()); - Assert.AreEqual("_client_id", dt.Rows[4]["PARAMETER_NAME"].ToString().ToLower()); - Assert.AreEqual(5, dt.Rows[4]["ORDINAL_POSITION"]); - Assert.AreEqual("IN", dt.Rows[4]["PARAMETER_MODE"]); - Assert.AreEqual("INT", dt.Rows[4]["DATA_TYPE"].ToString().ToUpper()); - - Assert.AreEqual(Connection.Database.ToLower(), dt.Rows[5]["SPECIFIC_SCHEMA"].ToString().ToLower()); - Assert.AreEqual("sptest", dt.Rows[5]["SPECIFIC_NAME"].ToString().ToLower()); - Assert.AreEqual("_login_id", dt.Rows[5]["PARAMETER_NAME"].ToString().ToLower()); - Assert.AreEqual(6, dt.Rows[5]["ORDINAL_POSITION"]); - Assert.AreEqual("IN", dt.Rows[5]["PARAMETER_MODE"]); - Assert.AreEqual("INT", dt.Rows[5]["DATA_TYPE"].ToString().ToUpper()); - - Assert.AreEqual(Connection.Database.ToLower(), dt.Rows[6]["SPECIFIC_SCHEMA"].ToString().ToLower()); - Assert.AreEqual("sptest", dt.Rows[6]["SPECIFIC_NAME"].ToString().ToLower()); - Assert.AreEqual("_where", dt.Rows[6]["PARAMETER_NAME"].ToString().ToLower()); - Assert.AreEqual(7, dt.Rows[6]["ORDINAL_POSITION"]); - Assert.AreEqual("IN", dt.Rows[6]["PARAMETER_MODE"]); - Assert.AreEqual("VARCHAR", dt.Rows[6]["DATA_TYPE"].ToString().ToUpper()); - Assert.AreEqual(2000, dt.Rows[6]["CHARACTER_OCTET_LENGTH"]); - - Assert.AreEqual(Connection.Database.ToLower(), dt.Rows[7]["SPECIFIC_SCHEMA"].ToString().ToLower()); - Assert.AreEqual("sptest", dt.Rows[7]["SPECIFIC_NAME"].ToString().ToLower()); - Assert.AreEqual("_sort", dt.Rows[7]["PARAMETER_NAME"].ToString().ToLower()); - Assert.AreEqual(8, dt.Rows[7]["ORDINAL_POSITION"]); - Assert.AreEqual("IN", dt.Rows[7]["PARAMETER_MODE"]); - Assert.AreEqual("VARCHAR", dt.Rows[7]["DATA_TYPE"].ToString().ToUpper()); - Assert.AreEqual(8000, dt.Rows[7]["CHARACTER_OCTET_LENGTH"]); - - Assert.AreEqual(Connection.Database.ToLower(), dt.Rows[8]["SPECIFIC_SCHEMA"].ToString().ToLower()); - Assert.AreEqual("sptest", dt.Rows[8]["SPECIFIC_NAME"].ToString().ToLower()); - Assert.AreEqual("_sql", dt.Rows[8]["PARAMETER_NAME"].ToString().ToLower()); - Assert.AreEqual(9, dt.Rows[8]["ORDINAL_POSITION"]); - Assert.AreEqual("OUT", dt.Rows[8]["PARAMETER_MODE"]); - Assert.AreEqual("VARCHAR", dt.Rows[8]["DATA_TYPE"].ToString().ToUpper()); - Assert.AreEqual(8000, dt.Rows[8]["CHARACTER_OCTET_LENGTH"]); - - Assert.AreEqual(Connection.Database.ToLower(), dt.Rows[9]["SPECIFIC_SCHEMA"].ToString().ToLower()); - Assert.AreEqual("sptest", dt.Rows[9]["SPECIFIC_NAME"].ToString().ToLower()); - Assert.AreEqual("_song_id", dt.Rows[9]["PARAMETER_NAME"].ToString().ToLower()); - Assert.AreEqual(10, dt.Rows[9]["ORDINAL_POSITION"]); - Assert.AreEqual("IN", dt.Rows[9]["PARAMETER_MODE"]); - Assert.AreEqual("INT", dt.Rows[9]["DATA_TYPE"].ToString().ToUpper()); - - Assert.AreEqual(Connection.Database.ToLower(), dt.Rows[10]["SPECIFIC_SCHEMA"].ToString().ToLower()); - Assert.AreEqual("sptest", dt.Rows[10]["SPECIFIC_NAME"].ToString().ToLower()); - Assert.AreEqual("_notes", dt.Rows[10]["PARAMETER_NAME"].ToString().ToLower()); - Assert.AreEqual(11, dt.Rows[10]["ORDINAL_POSITION"]); - Assert.AreEqual("IN", dt.Rows[10]["PARAMETER_MODE"]); - Assert.AreEqual("VARCHAR", dt.Rows[10]["DATA_TYPE"].ToString().ToUpper()); - Assert.AreEqual(2000, dt.Rows[10]["CHARACTER_OCTET_LENGTH"]); - - Assert.AreEqual(Connection.Database.ToLower(), dt.Rows[11]["SPECIFIC_SCHEMA"].ToString().ToLower()); - Assert.AreEqual("sptest", dt.Rows[11]["SPECIFIC_NAME"].ToString().ToLower()); - Assert.AreEqual("_result", dt.Rows[11]["PARAMETER_NAME"].ToString().ToLower()); - Assert.AreEqual(12, dt.Rows[11]["ORDINAL_POSITION"]); - Assert.AreEqual("OUT", dt.Rows[11]["PARAMETER_MODE"]); - Assert.AreEqual("VARCHAR", dt.Rows[11]["DATA_TYPE"].ToString().ToUpper()); - Assert.AreEqual(10, dt.Rows[11]["CHARACTER_OCTET_LENGTH"]); + Assert.That(dt.Rows.Count == 12, Is.True, "Rows count failed"); + Assert.That(dt.Rows[0]["SPECIFIC_SCHEMA"].ToString().ToLower(), Is.EqualTo(Connection.Database.ToLower())); + Assert.That(dt.Rows[0]["SPECIFIC_NAME"].ToString().ToLower(), Is.EqualTo("sptest")); + Assert.That(dt.Rows[0]["PARAMETER_NAME"].ToString().ToLower(), Is.EqualTo("_action")); + Assert.That(dt.Rows[0]["ORDINAL_POSITION"], Is.EqualTo(1)); + Assert.That(dt.Rows[0]["PARAMETER_MODE"], Is.EqualTo("IN")); + Assert.That(dt.Rows[0]["DATA_TYPE"].ToString().ToUpper(), Is.EqualTo("VARCHAR")); + Assert.That(dt.Rows[0]["CHARACTER_OCTET_LENGTH"], Is.EqualTo(20)); + + Assert.That(dt.Rows[1]["SPECIFIC_SCHEMA"].ToString().ToLower(), Is.EqualTo(Connection.Database.ToLower())); + Assert.That(dt.Rows[1]["SPECIFIC_NAME"].ToString().ToLower(), Is.EqualTo("sptest")); + Assert.That(dt.Rows[1]["PARAMETER_NAME"].ToString().ToLower(), Is.EqualTo("/*dumb-identifier-1*/")); + Assert.That(dt.Rows[1]["ORDINAL_POSITION"], Is.EqualTo(2)); + Assert.That(dt.Rows[1]["PARAMETER_MODE"], Is.EqualTo("IN")); + Assert.That(dt.Rows[1]["DATA_TYPE"].ToString().ToUpper(), Is.EqualTo("INT")); + + Assert.That(dt.Rows[2]["SPECIFIC_SCHEMA"].ToString().ToLower(), Is.EqualTo(Connection.Database.ToLower())); + Assert.That(dt.Rows[2]["SPECIFIC_NAME"].ToString().ToLower(), Is.EqualTo("sptest")); + Assert.That(dt.Rows[2]["PARAMETER_NAME"].ToString().ToLower(), Is.EqualTo("#dumb-identifier-2")); + Assert.That(dt.Rows[2]["ORDINAL_POSITION"], Is.EqualTo(3)); + Assert.That(dt.Rows[2]["PARAMETER_MODE"], Is.EqualTo("IN")); + Assert.That(dt.Rows[2]["DATA_TYPE"].ToString().ToUpper(), Is.EqualTo("INT")); + + Assert.That(dt.Rows[3]["SPECIFIC_SCHEMA"].ToString().ToLower(), Is.EqualTo(Connection.Database.ToLower())); + Assert.That(dt.Rows[3]["SPECIFIC_NAME"].ToString().ToLower(), Is.EqualTo("sptest")); + Assert.That(dt.Rows[3]["PARAMETER_NAME"].ToString().ToLower(), Is.EqualTo("--dumb-identifier-3")); + Assert.That(dt.Rows[3]["ORDINAL_POSITION"], Is.EqualTo(4)); + Assert.That(dt.Rows[3]["PARAMETER_MODE"], Is.EqualTo("IN")); + Assert.That(dt.Rows[3]["DATA_TYPE"].ToString().ToUpper(), Is.EqualTo("INT")); + + Assert.That(dt.Rows[4]["SPECIFIC_SCHEMA"].ToString().ToLower(), Is.EqualTo(Connection.Database.ToLower())); + Assert.That(dt.Rows[4]["SPECIFIC_NAME"].ToString().ToLower(), Is.EqualTo("sptest")); + Assert.That(dt.Rows[4]["PARAMETER_NAME"].ToString().ToLower(), Is.EqualTo("_client_id")); + Assert.That(dt.Rows[4]["ORDINAL_POSITION"], Is.EqualTo(5)); + Assert.That(dt.Rows[4]["PARAMETER_MODE"], Is.EqualTo("IN")); + Assert.That(dt.Rows[4]["DATA_TYPE"].ToString().ToUpper(), Is.EqualTo("INT")); + + Assert.That(dt.Rows[5]["SPECIFIC_SCHEMA"].ToString().ToLower(), Is.EqualTo(Connection.Database.ToLower())); + Assert.That(dt.Rows[5]["SPECIFIC_NAME"].ToString().ToLower(), Is.EqualTo("sptest")); + Assert.That(dt.Rows[5]["PARAMETER_NAME"].ToString().ToLower(), Is.EqualTo("_login_id")); + Assert.That(dt.Rows[5]["ORDINAL_POSITION"], Is.EqualTo(6)); + Assert.That(dt.Rows[5]["PARAMETER_MODE"], Is.EqualTo("IN")); + Assert.That(dt.Rows[5]["DATA_TYPE"].ToString().ToUpper(), Is.EqualTo("INT")); + + Assert.That(dt.Rows[6]["SPECIFIC_SCHEMA"].ToString().ToLower(), Is.EqualTo(Connection.Database.ToLower())); + Assert.That(dt.Rows[6]["SPECIFIC_NAME"].ToString().ToLower(), Is.EqualTo("sptest")); + Assert.That(dt.Rows[6]["PARAMETER_NAME"].ToString().ToLower(), Is.EqualTo("_where")); + Assert.That(dt.Rows[6]["ORDINAL_POSITION"], Is.EqualTo(7)); + Assert.That(dt.Rows[6]["PARAMETER_MODE"], Is.EqualTo("IN")); + Assert.That(dt.Rows[6]["DATA_TYPE"].ToString().ToUpper(), Is.EqualTo("VARCHAR")); + Assert.That(dt.Rows[6]["CHARACTER_OCTET_LENGTH"], Is.EqualTo(2000)); + + Assert.That(dt.Rows[7]["SPECIFIC_SCHEMA"].ToString().ToLower(), Is.EqualTo(Connection.Database.ToLower())); + Assert.That(dt.Rows[7]["SPECIFIC_NAME"].ToString().ToLower(), Is.EqualTo("sptest")); + Assert.That(dt.Rows[7]["PARAMETER_NAME"].ToString().ToLower(), Is.EqualTo("_sort")); + Assert.That(dt.Rows[7]["ORDINAL_POSITION"], Is.EqualTo(8)); + Assert.That(dt.Rows[7]["PARAMETER_MODE"], Is.EqualTo("IN")); + Assert.That(dt.Rows[7]["DATA_TYPE"].ToString().ToUpper(), Is.EqualTo("VARCHAR")); + Assert.That(dt.Rows[7]["CHARACTER_OCTET_LENGTH"], Is.EqualTo(8000)); + + Assert.That(dt.Rows[8]["SPECIFIC_SCHEMA"].ToString().ToLower(), Is.EqualTo(Connection.Database.ToLower())); + Assert.That(dt.Rows[8]["SPECIFIC_NAME"].ToString().ToLower(), Is.EqualTo("sptest")); + Assert.That(dt.Rows[8]["PARAMETER_NAME"].ToString().ToLower(), Is.EqualTo("_sql")); + Assert.That(dt.Rows[8]["ORDINAL_POSITION"], Is.EqualTo(9)); + Assert.That(dt.Rows[8]["PARAMETER_MODE"], Is.EqualTo("OUT")); + Assert.That(dt.Rows[8]["DATA_TYPE"].ToString().ToUpper(), Is.EqualTo("VARCHAR")); + Assert.That(dt.Rows[8]["CHARACTER_OCTET_LENGTH"], Is.EqualTo(8000)); + + Assert.That(dt.Rows[9]["SPECIFIC_SCHEMA"].ToString().ToLower(), Is.EqualTo(Connection.Database.ToLower())); + Assert.That(dt.Rows[9]["SPECIFIC_NAME"].ToString().ToLower(), Is.EqualTo("sptest")); + Assert.That(dt.Rows[9]["PARAMETER_NAME"].ToString().ToLower(), Is.EqualTo("_song_id")); + Assert.That(dt.Rows[9]["ORDINAL_POSITION"], Is.EqualTo(10)); + Assert.That(dt.Rows[9]["PARAMETER_MODE"], Is.EqualTo("IN")); + Assert.That(dt.Rows[9]["DATA_TYPE"].ToString().ToUpper(), Is.EqualTo("INT")); + + Assert.That(dt.Rows[10]["SPECIFIC_SCHEMA"].ToString().ToLower(), Is.EqualTo(Connection.Database.ToLower())); + Assert.That(dt.Rows[10]["SPECIFIC_NAME"].ToString().ToLower(), Is.EqualTo("sptest")); + Assert.That(dt.Rows[10]["PARAMETER_NAME"].ToString().ToLower(), Is.EqualTo("_notes")); + Assert.That(dt.Rows[10]["ORDINAL_POSITION"], Is.EqualTo(11)); + Assert.That(dt.Rows[10]["PARAMETER_MODE"], Is.EqualTo("IN")); + Assert.That(dt.Rows[10]["DATA_TYPE"].ToString().ToUpper(), Is.EqualTo("VARCHAR")); + Assert.That(dt.Rows[10]["CHARACTER_OCTET_LENGTH"], Is.EqualTo(2000)); + + Assert.That(dt.Rows[11]["SPECIFIC_SCHEMA"].ToString().ToLower(), Is.EqualTo(Connection.Database.ToLower())); + Assert.That(dt.Rows[11]["SPECIFIC_NAME"].ToString().ToLower(), Is.EqualTo("sptest")); + Assert.That(dt.Rows[11]["PARAMETER_NAME"].ToString().ToLower(), Is.EqualTo("_result")); + Assert.That(dt.Rows[11]["ORDINAL_POSITION"], Is.EqualTo(12)); + Assert.That(dt.Rows[11]["PARAMETER_MODE"], Is.EqualTo("OUT")); + Assert.That(dt.Rows[11]["DATA_TYPE"].ToString().ToUpper(), Is.EqualTo("VARCHAR")); + Assert.That(dt.Rows[11]["CHARACTER_OCTET_LENGTH"], Is.EqualTo(10)); } [Test] @@ -252,17 +252,17 @@ public void ProcedureParameters4() restrictions[2] = "ProcedureParameters4"; DataTable dt = Connection.GetSchema("Procedure Parameters", restrictions); - Assert.True(dt.Rows.Count == 1, "Actual Result " + dt.Rows.Count); - Assert.AreEqual(Connection.Database, dt.Rows[0]["SPECIFIC_SCHEMA"].ToString()); - Assert.AreEqual("ProcedureParameters4", dt.Rows[0]["SPECIFIC_NAME"].ToString()); - Assert.AreEqual("name", dt.Rows[0]["PARAMETER_NAME"].ToString().ToLower()); - Assert.AreEqual(1, dt.Rows[0]["ORDINAL_POSITION"]); - Assert.AreEqual("IN", dt.Rows[0]["PARAMETER_MODE"]); - Assert.AreEqual("VARCHAR", dt.Rows[0]["DATA_TYPE"].ToString().ToUpper()); - Assert.AreEqual(1200, dt.Rows[0]["CHARACTER_MAXIMUM_LENGTH"]); - Assert.AreEqual(3600, dt.Rows[0]["CHARACTER_OCTET_LENGTH"]); - Assert.AreEqual(charset, dt.Rows[0]["CHARACTER_SET_NAME"]); - Assert.AreEqual($"{charset}_general_ci", dt.Rows[0]["COLLATION_NAME"]); + Assert.That(dt.Rows.Count == 1, Is.True, "Actual Result " + dt.Rows.Count); + Assert.That(dt.Rows[0]["SPECIFIC_SCHEMA"].ToString(), Is.EqualTo(Connection.Database)); + Assert.That(dt.Rows[0]["SPECIFIC_NAME"].ToString(), Is.EqualTo("ProcedureParameters4")); + Assert.That(dt.Rows[0]["PARAMETER_NAME"].ToString().ToLower(), Is.EqualTo("name")); + Assert.That(dt.Rows[0]["ORDINAL_POSITION"], Is.EqualTo(1)); + Assert.That(dt.Rows[0]["PARAMETER_MODE"], Is.EqualTo("IN")); + Assert.That(dt.Rows[0]["DATA_TYPE"].ToString().ToUpper(), Is.EqualTo("VARCHAR")); + Assert.That(dt.Rows[0]["CHARACTER_MAXIMUM_LENGTH"], Is.EqualTo(1200)); + Assert.That(dt.Rows[0]["CHARACTER_OCTET_LENGTH"], Is.EqualTo(3600)); + Assert.That(dt.Rows[0]["CHARACTER_SET_NAME"], Is.EqualTo(charset)); + Assert.That(dt.Rows[0]["COLLATION_NAME"], Is.EqualTo($"{charset}_general_ci")); } [Test] @@ -276,23 +276,23 @@ public void ProcedureParameters5() restrictions[2] = "ProcedureParameters5"; DataTable dt = Connection.GetSchema("Procedure Parameters", restrictions); - Assert.True(dt.Rows.Count == 2); - Assert.AreEqual(Connection.Database, dt.Rows[0]["SPECIFIC_SCHEMA"].ToString()); - Assert.AreEqual("ProcedureParameters5", dt.Rows[0]["SPECIFIC_NAME"].ToString()); - Assert.AreEqual("name", dt.Rows[0]["PARAMETER_NAME"].ToString().ToLower()); - Assert.AreEqual(1, dt.Rows[0]["ORDINAL_POSITION"]); - Assert.AreEqual("IN", dt.Rows[0]["PARAMETER_MODE"]); - Assert.AreEqual("VARCHAR", dt.Rows[0]["DATA_TYPE"].ToString().ToUpper()); - Assert.AreEqual("latin1", dt.Rows[0]["CHARACTER_SET_NAME"]); - Assert.AreEqual(1200, dt.Rows[0]["CHARACTER_OCTET_LENGTH"]); - - Assert.AreEqual(Connection.Database, dt.Rows[1]["SPECIFIC_SCHEMA"].ToString()); - Assert.AreEqual("ProcedureParameters5", dt.Rows[1]["SPECIFIC_NAME"].ToString()); - Assert.AreEqual("name2", dt.Rows[1]["PARAMETER_NAME"].ToString().ToLower()); - Assert.AreEqual(2, dt.Rows[1]["ORDINAL_POSITION"]); - Assert.AreEqual("IN", dt.Rows[1]["PARAMETER_MODE"]); - Assert.AreEqual("TEXT", dt.Rows[1]["DATA_TYPE"].ToString().ToUpper()); - Assert.AreEqual("ucs2", dt.Rows[1]["CHARACTER_SET_NAME"]); + Assert.That(dt.Rows.Count == 2, Is.True); + Assert.That(dt.Rows[0]["SPECIFIC_SCHEMA"].ToString(), Is.EqualTo(Connection.Database)); + Assert.That(dt.Rows[0]["SPECIFIC_NAME"].ToString(), Is.EqualTo("ProcedureParameters5")); + Assert.That(dt.Rows[0]["PARAMETER_NAME"].ToString().ToLower(), Is.EqualTo("name")); + Assert.That(dt.Rows[0]["ORDINAL_POSITION"], Is.EqualTo(1)); + Assert.That(dt.Rows[0]["PARAMETER_MODE"], Is.EqualTo("IN")); + Assert.That(dt.Rows[0]["DATA_TYPE"].ToString().ToUpper(), Is.EqualTo("VARCHAR")); + Assert.That(dt.Rows[0]["CHARACTER_SET_NAME"], Is.EqualTo("latin1")); + Assert.That(dt.Rows[0]["CHARACTER_OCTET_LENGTH"], Is.EqualTo(1200)); + + Assert.That(dt.Rows[1]["SPECIFIC_SCHEMA"].ToString(), Is.EqualTo(Connection.Database)); + Assert.That(dt.Rows[1]["SPECIFIC_NAME"].ToString(), Is.EqualTo("ProcedureParameters5")); + Assert.That(dt.Rows[1]["PARAMETER_NAME"].ToString().ToLower(), Is.EqualTo("name2")); + Assert.That(dt.Rows[1]["ORDINAL_POSITION"], Is.EqualTo(2)); + Assert.That(dt.Rows[1]["PARAMETER_MODE"], Is.EqualTo("IN")); + Assert.That(dt.Rows[1]["DATA_TYPE"].ToString().ToUpper(), Is.EqualTo("TEXT")); + Assert.That(dt.Rows[1]["CHARACTER_SET_NAME"], Is.EqualTo("ucs2")); } [Test] @@ -314,19 +314,13 @@ name VARCHAR(20) /* this is a comment */ CHARACTER SET ascii, restrictions[2] = "DTD_Identifier"; DataTable dt = Connection.GetSchema("Procedure Parameters", restrictions); - Assert.True(dt.Rows.Count == 6, "Actual Result " + dt.Rows.Count); - Assert.AreEqual("INT(10) UNSIGNED ZEROFILL", - dt.Rows[0]["DTD_IDENTIFIER"].ToString().ToUpper()); - Assert.AreEqual("DECIMAL(10,2)", - dt.Rows[1]["DTD_IDENTIFIER"].ToString().ToUpper()); - Assert.AreEqual("VARCHAR(20)", - dt.Rows[2]["DTD_IDENTIFIER"].ToString().ToUpper()); - Assert.AreEqual("TINYTEXT", - dt.Rows[3]["DTD_IDENTIFIER"].ToString().ToUpper()); - Assert.AreEqual("ENUM('A','B','C')", - dt.Rows[4]["DTD_IDENTIFIER"].ToString().ToUpper()); - Assert.AreEqual("SET('1','2','3')", - dt.Rows[5]["DTD_IDENTIFIER"].ToString().ToUpper()); + Assert.That(dt.Rows.Count == 6, Is.True, "Actual Result " + dt.Rows.Count); + Assert.That(dt.Rows[0]["DTD_IDENTIFIER"].ToString().ToUpper(), Is.EqualTo("INT(10) UNSIGNED ZEROFILL")); + Assert.That(dt.Rows[1]["DTD_IDENTIFIER"].ToString().ToUpper(), Is.EqualTo("DECIMAL(10,2)")); + Assert.That(dt.Rows[2]["DTD_IDENTIFIER"].ToString().ToUpper(), Is.EqualTo("VARCHAR(20)")); + Assert.That(dt.Rows[3]["DTD_IDENTIFIER"].ToString().ToUpper(), Is.EqualTo("TINYTEXT")); + Assert.That(dt.Rows[4]["DTD_IDENTIFIER"].ToString().ToUpper(), Is.EqualTo("ENUM('A','B','C')")); + Assert.That(dt.Rows[5]["DTD_IDENTIFIER"].ToString().ToUpper(), Is.EqualTo("SET('1','2','3')")); conn.Close(); } } @@ -351,20 +345,20 @@ name VARCHAR(20) /* this is a comment */ CHARACTER SET ascii, cmd.CommandText = "PossibleValues"; cmd.CommandType = CommandType.StoredProcedure; MySqlCommandBuilder.DeriveParameters(cmd); - Assert.Null(cmd.Parameters["@id"].PossibleValues); - Assert.Null(cmd.Parameters["@dec1"].PossibleValues); - Assert.Null(cmd.Parameters["@name"].PossibleValues); - Assert.Null(cmd.Parameters["@t1"].PossibleValues); + Assert.That(cmd.Parameters["@id"].PossibleValues, Is.Null); + Assert.That(cmd.Parameters["@dec1"].PossibleValues, Is.Null); + Assert.That(cmd.Parameters["@name"].PossibleValues, Is.Null); + Assert.That(cmd.Parameters["@t1"].PossibleValues, Is.Null); MySqlParameter t2 = cmd.Parameters["@t2"]; - Assert.NotNull(t2.PossibleValues); - Assert.AreEqual("a", t2.PossibleValues[0]); - Assert.AreEqual("b", t2.PossibleValues[1]); - Assert.AreEqual("c", t2.PossibleValues[2]); + Assert.That(t2.PossibleValues, Is.Not.Null); + Assert.That(t2.PossibleValues[0], Is.EqualTo("a")); + Assert.That(t2.PossibleValues[1], Is.EqualTo("b")); + Assert.That(t2.PossibleValues[2], Is.EqualTo("c")); MySqlParameter t3 = cmd.Parameters["@t3"]; - Assert.NotNull(t3.PossibleValues); - Assert.AreEqual("1", t3.PossibleValues[0]); - Assert.AreEqual("2", t3.PossibleValues[1]); - Assert.AreEqual("3", t3.PossibleValues[2]); + Assert.That(t3.PossibleValues, Is.Not.Null); + Assert.That(t3.PossibleValues[0], Is.EqualTo("1")); + Assert.That(t3.PossibleValues[1], Is.EqualTo("2")); + Assert.That(t3.PossibleValues[2], Is.EqualTo("3")); conn.Close(); } @@ -379,20 +373,20 @@ name VARCHAR(20) /* this is a comment */ CHARACTER SET ascii, cmd.CommandText = "PossibleValues"; cmd.CommandType = CommandType.StoredProcedure; MySqlCommandBuilder.DeriveParameters(cmd); - Assert.Null(cmd.Parameters["@id"].PossibleValues); - Assert.Null(cmd.Parameters["@dec1"].PossibleValues); - Assert.Null(cmd.Parameters["@name"].PossibleValues); - Assert.Null(cmd.Parameters["@t1"].PossibleValues); + Assert.That(cmd.Parameters["@id"].PossibleValues, Is.Null); + Assert.That(cmd.Parameters["@dec1"].PossibleValues, Is.Null); + Assert.That(cmd.Parameters["@name"].PossibleValues, Is.Null); + Assert.That(cmd.Parameters["@t1"].PossibleValues, Is.Null); MySqlParameter t2 = cmd.Parameters["@t2"]; - Assert.NotNull(t2.PossibleValues); - Assert.AreEqual("a", t2.PossibleValues[0]); - Assert.AreEqual("b", t2.PossibleValues[1]); - Assert.AreEqual("c", t2.PossibleValues[2]); + Assert.That(t2.PossibleValues, Is.Not.Null); + Assert.That(t2.PossibleValues[0], Is.EqualTo("a")); + Assert.That(t2.PossibleValues[1], Is.EqualTo("b")); + Assert.That(t2.PossibleValues[2], Is.EqualTo("c")); MySqlParameter t3 = cmd.Parameters["@t3"]; - Assert.NotNull(t3.PossibleValues); - Assert.AreEqual("1", t3.PossibleValues[0]); - Assert.AreEqual("2", t3.PossibleValues[1]); - Assert.AreEqual("3", t3.PossibleValues[2]); + Assert.That(t3.PossibleValues, Is.Not.Null); + Assert.That(t3.PossibleValues[0], Is.EqualTo("1")); + Assert.That(t3.PossibleValues[1], Is.EqualTo("2")); + Assert.That(t3.PossibleValues[2], Is.EqualTo("3")); conn.Close(); } } @@ -468,7 +462,7 @@ SQL SECURITY INVOKER da.SelectCommand = cmd; DataSet ds = new DataSet(); da.Fill(ds); - Assert.True(ds.Tables.Count > 0); + Assert.That(ds.Tables.Count > 0, Is.True); //Test with not existing procedure cmd.CommandText = "get_hello3"; @@ -481,7 +475,7 @@ SQL SECURITY INVOKER if (hasPrivileges) { da.Fill(ds); - Assert.True(ds.Tables.Count > 0); + Assert.That(ds.Tables.Count > 0, Is.True); } else { @@ -528,15 +522,15 @@ OUT value INT while (reader.Read()) { var stdout1 = reader.GetInt32(0); - Assert.AreEqual(2, stdout1); + Assert.That(stdout1, Is.EqualTo(2)); var schema = reader.GetSchemaTable(); - Assert.NotNull(schema); - Assert.True(reader.HasRows); - Assert.AreEqual(1, reader.FieldCount); + Assert.That(schema, Is.Not.Null); + Assert.That(reader.HasRows, Is.True); + Assert.That(reader.FieldCount, Is.EqualTo(1)); } } var outparam1 = _outputParam.Value; - Assert.AreEqual(1, outparam1); + Assert.That(outparam1, Is.EqualTo(1)); } @@ -562,12 +556,12 @@ OUT value INT { reader.Read(); var schema = reader.GetSchemaTable(); - Assert.Null(schema); - Assert.False(reader.HasRows); - Assert.AreEqual(0, reader.FieldCount); + Assert.That(schema, Is.Null); + Assert.That(reader.HasRows, Is.False); + Assert.That(reader.FieldCount, Is.EqualTo(0)); } var outparam1 = _outputParam2.Value; - Assert.AreEqual(1, outparam1); + Assert.That(outparam1, Is.EqualTo(1)); } } } diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/ReplicationTests.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/ReplicationTests.cs index 7f9f37d80..67c647fa6 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/ReplicationTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/ReplicationTests.cs @@ -46,7 +46,7 @@ public void Simple() } catch (MySqlException ex) { - StringAssert.Contains("Replicated", ex.Message); + Assert.That(ex.Message, Does.Contain("Replicated")); } } } diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/ThreadingTests.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/ThreadingTests.cs index 865d0c484..825615432 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/ThreadingTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/ThreadingTests.cs @@ -125,7 +125,7 @@ public void HardenedThreadAbortException() t.Abort(); t.Join(); - Assert.NotNull(lastException); + Assert.That(lastException, Is.Not.Null); if (lastException is MySqlException) { @@ -134,7 +134,7 @@ public void HardenedThreadAbortException() } //Assert.InstanceOf(typeof(ThreadAbortException), lastException); - Assert.IsInstanceOf(lastException); + Assert.That(lastException, Is.InstanceOf()); } } } diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/TimeoutAndCancel.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/TimeoutAndCancel.cs index be448303a..51ff85733 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/TimeoutAndCancel.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/TimeoutAndCancel.cs @@ -50,7 +50,7 @@ private void CommandRunner(MySqlCommand cmdToRun) { object o = cmdToRun.ExecuteScalar(); resetEvent.Set(); - Assert.Null(o); + Assert.That(o, Is.Null); } #if NETFRAMEWORK @@ -77,7 +77,7 @@ public void CancelSingleQuery() // now cancel the command cmd.Cancel(); - Assert.True(resetEvent.WaitOne(30 * 1000), "timeout"); + Assert.That(resetEvent.WaitOne(30 * 1000), "timeout"); } #endif @@ -115,13 +115,13 @@ public void WaitTimeoutExpiring() catch (MySqlException ex) { if (Version < new Version("8.0.24")) - StringAssert.StartsWith("Fatal", ex.Message); + Assert.That(ex.Message, Does.StartWith("Fatal")); else - StringAssert.StartsWith("The client was disconnected", ex.Message); + Assert.That(ex.Message, Does.StartWith("The client was disconnected")); } - Assert.AreEqual(1, stateChangeCount); - Assert.AreEqual(ConnectionState.Closed, c.State); + Assert.That(stateChangeCount, Is.EqualTo(1)); + Assert.That(c.State, Is.EqualTo(ConnectionState.Closed)); } using (MySqlConnection c = new MySqlConnection(connStr)) @@ -130,7 +130,7 @@ public void WaitTimeoutExpiring() MySqlCommand cmd = new MySqlCommand("SELECT now() as thetime, database() as db", c); using (MySqlDataReader r = cmd.ExecuteReader()) { - Assert.True(r.Read()); + Assert.That(r.Read(), Is.True); } } } @@ -218,17 +218,17 @@ public void CancelSelect() } catch (MySqlException ex) { - Assert.True(ex.Number == (int)MySqlErrorCode.QueryInterrupted); + Assert.That(ex.Number, Is.EqualTo((int)MySqlErrorCode.QueryInterrupted)); if (rows < 1000) { bool readOK = reader.Read(); - Assert.False(readOK); + Assert.That(readOK, Is.False); } } } } - Assert.True(rows < 1000); + Assert.That(rows < 1000); } /// @@ -262,11 +262,11 @@ public void ConnectionStringModifiedAfterCancel() } catch (MySqlException ex) { - Assert.True(ex.InnerException is TimeoutException); - Assert.True(c.State == ConnectionState.Open); + Assert.That(ex.InnerException is TimeoutException, Is.True); + Assert.That(c.State, Is.EqualTo(ConnectionState.Open)); } string connStr2 = c.ConnectionString.ToLower(CultureInfo.InvariantCulture); - Assert.AreEqual(connStr1.ToLower(CultureInfo.InvariantCulture), connStr2); + Assert.That(connStr2, Is.EqualTo(connStr1.ToLower(CultureInfo.InvariantCulture))); c.Close(); } @@ -311,7 +311,7 @@ public void NetWriteTimeoutExpiring() // normally and then the problem, described above, occurs for (; i < rows; i++) { - Assert.False(!reader.Read(),"unexpected 'false' from reader.Read"); + Assert.That(!reader.Read(), Is.False, "unexpected 'false' from reader.Read"); if (i % 10 == 0) Thread.Sleep(1); object v = reader.GetValue(1); @@ -337,7 +337,7 @@ public void NetWriteTimeoutExpiring() // IT is relatively hard to predict where Console.WriteLine("Warning: all reads completed!"); - Assert.True(i == rows); + Assert.That(i, Is.EqualTo(rows)); } } } diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/TypeTests.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/TypeTests.cs index 62ccf2c49..290638392 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/TypeTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/TypeTests.cs @@ -44,12 +44,12 @@ public class TypeTests : TestBase public void TestSerializationMySqlDataTime() { MySqlDateTime dt = new MySqlDateTime(2011, 10, 6, 11, 38, 01, 0); - Assert.AreEqual(2011, dt.Year); - Assert.AreEqual(10, dt.Month); - Assert.AreEqual(6, dt.Day); - Assert.AreEqual(11, dt.Hour); - Assert.AreEqual(38, dt.Minute); - Assert.AreEqual(1, dt.Second); + Assert.That(dt.Year, Is.EqualTo(2011)); + Assert.That(dt.Month, Is.EqualTo(10)); + Assert.That(dt.Day, Is.EqualTo(6)); + Assert.That(dt.Hour, Is.EqualTo(11)); + Assert.That(dt.Minute, Is.EqualTo(38)); + Assert.That(dt.Second, Is.EqualTo(1)); System.Runtime.Serialization.Formatters.Binary.BinaryFormatter bf = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter(); MemoryStream ms = new MemoryStream(1024); @@ -57,12 +57,12 @@ public void TestSerializationMySqlDataTime() ms.Position = 0; object o = bf.Deserialize(ms); dt = (MySqlDateTime)o; - Assert.AreEqual(2011, dt.Year); - Assert.AreEqual(10, dt.Month); - Assert.AreEqual(6, dt.Day); - Assert.AreEqual(11, dt.Hour); - Assert.AreEqual(38, dt.Minute); - Assert.AreEqual(1, dt.Second); + Assert.That(dt.Year, Is.EqualTo(2011)); + Assert.That(dt.Month, Is.EqualTo(10)); + Assert.That(dt.Day, Is.EqualTo(6)); + Assert.That(dt.Hour, Is.EqualTo(11)); + Assert.That(dt.Minute, Is.EqualTo(38)); + Assert.That(dt.Second, Is.EqualTo(1)); } #endif } diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/UsageAdvisorTests.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/UsageAdvisorTests.cs index 5ac06fdc8..84652a091 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/UsageAdvisorTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/UsageAdvisorTests.cs @@ -65,25 +65,25 @@ public void NotReadingEveryField() reader.Read(); reader.GetInt32(0); // access the first field reader.Read(); - Assert.True(reader.NextResult()); + Assert.That(reader.NextResult(), Is.True); reader.Read(); - Assert.AreEqual("Test3", reader.GetString(1)); - Assert.False(reader.NextResult()); + Assert.That(reader.GetString(1), Is.EqualTo("Test3")); + Assert.That(reader.NextResult(), Is.False); } - Assert.AreEqual(12, listener.Strings.Count); - StringAssert.Contains("Query Opened: SELECT * FROM Test; SELECT * FROM Test WHERE id > 2", listener.Strings[0]); - StringAssert.Contains("Resultset Opened: field(s) = 2, affected rows = -1, inserted id = -1", listener.Strings[1]); - StringAssert.Contains("Usage Advisor Warning: Query does not use an index", listener.Strings[2]); - StringAssert.Contains("Usage Advisor Warning: Skipped 2 rows. Consider a more focused query.", listener.Strings[3]); - StringAssert.Contains("Usage Advisor Warning: The following columns were not accessed: name", listener.Strings[4]); - StringAssert.Contains("Resultset Closed. Total rows=4, skipped rows=2, size (bytes)=32", listener.Strings[5]); - StringAssert.Contains("Resultset Opened: field(s) = 2, affected rows = -1, inserted id = -1", listener.Strings[6]); - StringAssert.Contains("Usage Advisor Warning: Query does not use an index", listener.Strings[7]); - StringAssert.Contains("Usage Advisor Warning: Skipped 1 rows. Consider a more focused query.", listener.Strings[8]); - StringAssert.Contains("Usage Advisor Warning: The following columns were not accessed: id", listener.Strings[9]); - StringAssert.Contains("Resultset Closed. Total rows=2, skipped rows=1, size (bytes)=16", listener.Strings[10]); - StringAssert.Contains("Query Closed", listener.Strings[11]); + Assert.That(listener.Strings.Count, Is.EqualTo(12)); + Assert.That(listener.Strings[0], Does.Contain("Query Opened: SELECT * FROM Test; SELECT * FROM Test WHERE id > 2")); + Assert.That(listener.Strings[1], Does.Contain("Resultset Opened: field(s) = 2, affected rows = -1, inserted id = -1")); + Assert.That(listener.Strings[2], Does.Contain("Usage Advisor Warning: Query does not use an index")); + Assert.That(listener.Strings[3], Does.Contain("Usage Advisor Warning: Skipped 2 rows. Consider a more focused query.")); + Assert.That(listener.Strings[4], Does.Contain("Usage Advisor Warning: The following columns were not accessed: name")); + Assert.That(listener.Strings[5], Does.Contain("Resultset Closed. Total rows=4, skipped rows=2, size (bytes)=32")); + Assert.That(listener.Strings[6], Does.Contain("Resultset Opened: field(s) = 2, affected rows = -1, inserted id = -1")); + Assert.That(listener.Strings[7], Does.Contain("Usage Advisor Warning: Query does not use an index")); + Assert.That(listener.Strings[8], Does.Contain("Usage Advisor Warning: Skipped 1 rows. Consider a more focused query.")); + Assert.That(listener.Strings[9], Does.Contain("Usage Advisor Warning: The following columns were not accessed: id")); + Assert.That(listener.Strings[10], Does.Contain("Resultset Closed. Total rows=2, skipped rows=1, size (bytes)=16")); + Assert.That(listener.Strings[11], Does.Contain("Query Closed")); } [Test] @@ -105,24 +105,24 @@ public void NotReadingEveryRow() { reader.Read(); reader.Read(); - Assert.True(reader.NextResult()); + Assert.That(reader.NextResult(), Is.True); reader.Read(); reader.Read(); - Assert.False(reader.NextResult()); + Assert.That(reader.NextResult(), Is.False); } - Assert.AreEqual(11, listener.Strings.Count); - StringAssert.Contains("Query Opened: SELECT * FROM Test; SELECT * FROM Test WHERE id > 2", listener.Strings[0]); - StringAssert.Contains("Resultset Opened: field(s) = 2, affected rows = -1, inserted id = -1", listener.Strings[1]); - StringAssert.Contains("Usage Advisor Warning: Query does not use an index", listener.Strings[2]); - StringAssert.Contains("Usage Advisor Warning: Skipped 2 rows. Consider a more focused query.", listener.Strings[3]); - StringAssert.Contains("Usage Advisor Warning: The following columns were not accessed: id,name", listener.Strings[4]); - StringAssert.Contains("Resultset Closed. Total rows=4, skipped rows=2, size (bytes)=32", listener.Strings[5]); - StringAssert.Contains("Resultset Opened: field(s) = 2, affected rows = -1, inserted id = -1", listener.Strings[6]); - StringAssert.Contains("Usage Advisor Warning: Query does not use an index", listener.Strings[7]); - StringAssert.Contains("Usage Advisor Warning: The following columns were not accessed: id,name", listener.Strings[8]); - StringAssert.Contains("Resultset Closed. Total rows=2, skipped rows=0, size (bytes)=16", listener.Strings[9]); - StringAssert.Contains("Query Closed", listener.Strings[10]); + Assert.That(listener.Strings, Has.Count.EqualTo(11)); + Assert.That(listener.Strings[0], Does.Contain("Query Opened: SELECT * FROM Test; SELECT * FROM Test WHERE id > 2")); + Assert.That(listener.Strings[1], Does.Contain("Resultset Opened: field(s) = 2, affected rows = -1, inserted id = -1")); + Assert.That(listener.Strings[2], Does.Contain("Usage Advisor Warning: Query does not use an index")); + Assert.That(listener.Strings[3], Does.Contain("Usage Advisor Warning: Skipped 2 rows. Consider a more focused query.")); + Assert.That(listener.Strings[4], Does.Contain("Usage Advisor Warning: The following columns were not accessed: id,name")); + Assert.That(listener.Strings[5], Does.Contain("Resultset Closed. Total rows=4, skipped rows=2, size (bytes)=32")); + Assert.That(listener.Strings[6], Does.Contain("Resultset Opened: field(s) = 2, affected rows = -1, inserted id = -1")); + Assert.That(listener.Strings[7], Does.Contain("Usage Advisor Warning: Query does not use an index")); + Assert.That(listener.Strings[8], Does.Contain("Usage Advisor Warning: The following columns were not accessed: id,name")); + Assert.That(listener.Strings[9], Does.Contain("Resultset Closed. Total rows=2, skipped rows=0, size (bytes)=16")); + Assert.That(listener.Strings[10], Does.Contain("Query Closed")); } [Test] @@ -145,13 +145,13 @@ public void FieldConversion() string str = reader.GetString(1); } - Assert.AreEqual(6, listener.Strings.Count); - StringAssert.Contains("Query Opened: SELECT * FROM Test", listener.Strings[0]); - StringAssert.Contains("Resultset Opened: field(s) = 2, affected rows = -1, inserted id = -1", listener.Strings[1]); - StringAssert.Contains("Usage Advisor Warning: Query does not use an index", listener.Strings[2]); - StringAssert.Contains("Usage Advisor Warning: The field 'id' was converted to the following types: Int16,Int64", listener.Strings[3]); - StringAssert.Contains("Resultset Closed. Total rows=1, skipped rows=0, size (bytes)=8", listener.Strings[4]); - StringAssert.Contains("Query Closed", listener.Strings[5]); + Assert.That(listener.Strings.Count, Is.EqualTo(6)); + Assert.That(listener.Strings[0], Does.Contain("Query Opened: SELECT * FROM Test")); + Assert.That(listener.Strings[1], Does.Contain("Resultset Opened: field(s) = 2, affected rows = -1, inserted id = -1")); + Assert.That(listener.Strings[2], Does.Contain("Usage Advisor Warning: Query does not use an index")); + Assert.That(listener.Strings[3], Does.Contain("Usage Advisor Warning: The field 'id' was converted to the following types: Int16,Int64")); + Assert.That(listener.Strings[4], Does.Contain("Resultset Closed. Total rows=1, skipped rows=0, size (bytes)=8")); + Assert.That(listener.Strings[5], Does.Contain("Query Closed")); } [Test] @@ -174,13 +174,13 @@ public void NoIndexUsed() reader.Read(); } - Assert.AreEqual(6, listener.Strings.Count); - StringAssert.Contains("Query Opened: SELECT name FROM Test WHERE id=3", listener.Strings[0]); - StringAssert.Contains("Resultset Opened: field(s) = 1, affected rows = -1, inserted id = -1", listener.Strings[1]); - StringAssert.Contains("Usage Advisor Warning: Query does not use an index", listener.Strings[2]); - StringAssert.Contains("Usage Advisor Warning: The following columns were not accessed: name", listener.Strings[3]); - StringAssert.Contains("Resultset Closed. Total rows=1, skipped rows=0, size (bytes)=6", listener.Strings[4]); - StringAssert.Contains("Query Closed", listener.Strings[5]); + Assert.That(listener.Strings.Count, Is.EqualTo(6)); + Assert.That(listener.Strings[0], Does.Contain("Query Opened: SELECT name FROM Test WHERE id=3")); + Assert.That(listener.Strings[1], Does.Contain("Resultset Opened: field(s) = 1, affected rows = -1, inserted id = -1")); + Assert.That(listener.Strings[2], Does.Contain("Usage Advisor Warning: Query does not use an index")); + Assert.That(listener.Strings[3], Does.Contain("Usage Advisor Warning: The following columns were not accessed: name")); + Assert.That(listener.Strings[4], Does.Contain("Resultset Closed. Total rows=1, skipped rows=0, size (bytes)=6")); + Assert.That(listener.Strings[5], Does.Contain("Query Closed")); } [Test] @@ -203,13 +203,13 @@ public void BadIndexUsed() reader.Read(); } - Assert.AreEqual(6, listener.Strings.Count); - StringAssert.Contains("Query Opened: SELECT name FROM Test WHERE id=3", listener.Strings[0]); - StringAssert.Contains("Resultset Opened: field(s) = 1, affected rows = -1, inserted id = -1", listener.Strings[1]); - StringAssert.Contains("Usage Advisor Warning: Query does not use an index", listener.Strings[2]); - StringAssert.Contains("Usage Advisor Warning: The following columns were not accessed: name", listener.Strings[3]); - StringAssert.Contains("Resultset Closed. Total rows=1, skipped rows=0, size (bytes)=6", listener.Strings[4]); - StringAssert.Contains("Query Closed", listener.Strings[5]); + Assert.That(listener.Strings.Count, Is.EqualTo(6)); + Assert.That(listener.Strings[0], Does.Contain("Query Opened: SELECT name FROM Test WHERE id=3")); + Assert.That(listener.Strings[1], Does.Contain("Resultset Opened: field(s) = 1, affected rows = -1, inserted id = -1")); + Assert.That(listener.Strings[2], Does.Contain("Usage Advisor Warning: Query does not use an index")); + Assert.That(listener.Strings[3], Does.Contain("Usage Advisor Warning: The following columns were not accessed: name")); + Assert.That(listener.Strings[4], Does.Contain("Resultset Closed. Total rows=1, skipped rows=0, size (bytes)=6")); + Assert.That(listener.Strings[5], Does.Contain("Query Closed")); } } } diff --git a/MySQL.Data/tests/MySql.Data.Tests/LoggingTests.cs b/MySQL.Data/tests/MySql.Data.Tests/LoggingTests.cs index f5b437ce5..152b6a5a7 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/LoggingTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/LoggingTests.cs @@ -67,11 +67,11 @@ public void SimpleLogging() } } //Assert.AreEqual(4, listener.Strings.Count); - Assert.AreEqual(27, listener.Strings.Count); - StringAssert.Contains("Query Opened: SELECT * FROM Test", listener.Strings[listener.Strings.Count - 5]); - StringAssert.Contains("Resultset Opened: field(s) = 2, affected rows = -1, inserted id = -1", listener.Strings[listener.Strings.Count - 4]); - StringAssert.Contains("Resultset Closed. Total rows=4, skipped rows=4, size (bytes)=32", listener.Strings[listener.Strings.Count - 3]); - StringAssert.Contains("Query Closed", listener.Strings[listener.Strings.Count - 2]); + Assert.That(listener.Strings.Count, Is.EqualTo(27)); + Assert.That(listener.Strings[listener.Strings.Count - 5], Does.Contain("Query Opened: SELECT * FROM Test")); + Assert.That(listener.Strings[listener.Strings.Count - 4], Does.Contain("Resultset Opened: field(s) = 2, affected rows = -1, inserted id = -1")); + Assert.That(listener.Strings[listener.Strings.Count - 3], Does.Contain("Resultset Closed. Total rows=4, skipped rows=4, size (bytes)=32")); + Assert.That(listener.Strings[listener.Strings.Count - 2], Does.Contain("Query Closed")); } [Test] @@ -91,16 +91,16 @@ public void Warnings() cmd.ExecuteNonQuery(); } - Assert.AreEqual(32, listener.Strings.Count); - StringAssert.Contains("Query Opened: INSERT IGNORE INTO Test VALUES (1, 'abcdef')", listener.Strings[listener.Strings.Count - 10]); - StringAssert.Contains("Resultset Opened: field(s) = 0, affected rows = 1, inserted id = 0", listener.Strings[listener.Strings.Count - 9]); - StringAssert.Contains("Resultset Closed. Total rows=0, skipped rows=0, size (bytes)=0", listener.Strings[listener.Strings.Count - 8]); - StringAssert.Contains("Query Opened: SHOW WARNINGS", listener.Strings[listener.Strings.Count - 7]); - StringAssert.Contains("Resultset Opened: field(s) = 3, affected rows = -1, inserted id = -1", listener.Strings[listener.Strings.Count - 6]); - StringAssert.Contains("Resultset Closed. Total rows=1, skipped rows=0, size (bytes)=55", listener.Strings[listener.Strings.Count - 5]); - StringAssert.Contains("Query Closed", listener.Strings[listener.Strings.Count - 4]); - StringAssert.Contains("MySql Warning: Level=Warning, Code=1265, Message=Data truncated for column 'name' at row 1", listener.Strings[listener.Strings.Count - 3]); - StringAssert.Contains("Query Closed", listener.Strings[listener.Strings.Count - 2]); + Assert.That(listener.Strings.Count, Is.EqualTo(32)); + Assert.That(listener.Strings[listener.Strings.Count - 10], Does.Contain("Query Opened: INSERT IGNORE INTO Test VALUES (1, 'abcdef')")); + Assert.That(listener.Strings[listener.Strings.Count - 9], Does.Contain("Resultset Opened: field(s) = 0, affected rows = 1, inserted id = 0")); + Assert.That(listener.Strings[listener.Strings.Count - 8], Does.Contain("Resultset Closed. Total rows=0, skipped rows=0, size (bytes)=0")); + Assert.That(listener.Strings[listener.Strings.Count - 7], Does.Contain("Query Opened: SHOW WARNINGS")); + Assert.That(listener.Strings[listener.Strings.Count - 6], Does.Contain("Resultset Opened: field(s) = 3, affected rows = -1, inserted id = -1")); + Assert.That(listener.Strings[listener.Strings.Count - 5], Does.Contain("Resultset Closed. Total rows=1, skipped rows=0, size (bytes)=55")); + Assert.That(listener.Strings[listener.Strings.Count - 4], Does.Contain("Query Closed")); + Assert.That(listener.Strings[listener.Strings.Count - 3], Does.Contain("MySql Warning: Level=Warning, Code=1265, Message=Data truncated for column 'name' at row 1")); + Assert.That(listener.Strings[listener.Strings.Count - 2], Does.Contain("Query Closed")); } [Test] @@ -121,10 +121,10 @@ public void ProviderNormalizingQuery() logConn.Open(); MySqlCommand cmd = new MySqlCommand(sql.ToString(), logConn); cmd.ExecuteNonQuery(); - } + } - Assert.AreEqual(28, listener.Strings.Count); - StringAssert.EndsWith("SELECT ?", listener.Strings[listener.Strings.Count - 5]); + Assert.That(listener.Strings.Count, Is.EqualTo(28)); + Assert.That(listener.Strings[listener.Strings.Count - 5], Does.EndWith("SELECT ?")); } /// diff --git a/MySQL.Data/tests/MySql.Data.Tests/MySqlBulkLoaderTests.cs b/MySQL.Data/tests/MySql.Data.Tests/MySqlBulkLoaderTests.cs index 869f11e03..8432c7a44 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/MySqlBulkLoaderTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/MySqlBulkLoaderTests.cs @@ -72,11 +72,11 @@ public void BulkLoadSimple() loader.Timeout = 0; loader.Local = true; int count = loader.Load(); - Assert.AreEqual(200, count); + Assert.That(count, Is.EqualTo(200)); DataTable dt = Utils.FillTable("SELECT * FROM Test", Connection); - Assert.AreEqual(200, dt.Rows.Count); - Assert.AreEqual("'Test'", dt.Rows[0][1].ToString().Trim()); + Assert.That(dt.Rows.Count, Is.EqualTo(200)); + Assert.That(dt.Rows[0][1].ToString().Trim(), Is.EqualTo("'Test'")); } [Test] @@ -103,11 +103,11 @@ public void BulkLoadReadOnlyFile() loader.Timeout = 0; loader.Local = true; int count = loader.Load(); - Assert.AreEqual(200, count); + Assert.That(count, Is.EqualTo(200)); DataTable dt = Utils.FillTable("SELECT * FROM Test", Connection); - Assert.AreEqual(200, dt.Rows.Count); - Assert.AreEqual("'Test'", dt.Rows[0][1].ToString().Trim()); + Assert.That(dt.Rows.Count, Is.EqualTo(200)); + Assert.That(dt.Rows[0][1].ToString().Trim(), Is.EqualTo("'Test'")); } finally { @@ -137,10 +137,10 @@ public void BulkLoadSimple2() loader.LineTerminator = "xxx"; loader.Local = true; int count = loader.Load(); - Assert.AreEqual(200, count); + Assert.That(count, Is.EqualTo(200)); MySqlCommand cmd = new MySqlCommand("SELECT COUNT(*) FROM Test", Connection); - Assert.AreEqual(200, Convert.ToInt32(cmd.ExecuteScalar())); + Assert.That(Convert.ToInt32(cmd.ExecuteScalar()), Is.EqualTo(200)); } [Test] @@ -165,10 +165,10 @@ public void BulkLoadSimple3() loader.NumberOfLinesToSkip = 50; loader.Local = true; int count = loader.Load(); - Assert.AreEqual(150, count); + Assert.That(count, Is.EqualTo(150)); MySqlCommand cmd = new MySqlCommand("SELECT COUNT(*) FROM Test", Connection); - Assert.AreEqual(150, Convert.ToInt32(cmd.ExecuteScalar())); + Assert.That(Convert.ToInt32(cmd.ExecuteScalar()), Is.EqualTo(150)); } [Test] @@ -199,10 +199,10 @@ public void BulkLoadSimple4() loader.LinePrefix = "bbb"; loader.Local = true; int count = loader.Load(); - Assert.AreEqual(200, count); + Assert.That(count, Is.EqualTo(200)); MySqlCommand cmd = new MySqlCommand("SELECT COUNT(*) FROM Test", Connection); - Assert.AreEqual(200, Convert.ToInt32(cmd.ExecuteScalar())); + Assert.That(Convert.ToInt32(cmd.ExecuteScalar()), Is.EqualTo(200)); } [Test] @@ -226,12 +226,12 @@ public void BulkLoadFieldQuoting() loader.FieldQuotationOptional = true; loader.Local = true; int count = loader.Load(); - Assert.AreEqual(200, count); + Assert.That(count, Is.EqualTo(200)); DataTable dt = Utils.FillTable("SELECT * FROM Test", Connection); - Assert.AreEqual(200, dt.Rows.Count); - Assert.AreEqual("col1", dt.Rows[0][1]); - Assert.AreEqual("col2", dt.Rows[0][2].ToString().Trim()); + Assert.That(dt.Rows.Count, Is.EqualTo(200)); + Assert.That(dt.Rows[0][1], Is.EqualTo("col1")); + Assert.That(dt.Rows[0][2].ToString().Trim(), Is.EqualTo("col2")); } [Test] @@ -255,12 +255,12 @@ public void BulkLoadEscaping() loader.FieldTerminator = ","; loader.Local = true; int count = loader.Load(); - Assert.AreEqual(200, count); + Assert.That(count, Is.EqualTo(200)); DataTable dt = Utils.FillTable("SELECT * FROM Test", Connection); - Assert.AreEqual(200, dt.Rows.Count); - Assert.AreEqual("col1still col1", dt.Rows[0][1]); - Assert.AreEqual("col2", dt.Rows[0][2].ToString().Trim()); + Assert.That(dt.Rows.Count, Is.EqualTo(200)); + Assert.That(dt.Rows[0][1], Is.EqualTo("col1still col1")); + Assert.That(dt.Rows[0][2].ToString().Trim(), Is.EqualTo("col2")); } [Test] @@ -283,7 +283,7 @@ public void BulkLoadConflictOptionReplace() loader.FieldTerminator = ","; loader.Local = true; int count = loader.Load(); - Assert.AreEqual(20, count); + Assert.That(count, Is.EqualTo(20)); path = Path.GetTempFileName(); sw = new StreamWriter(new FileStream(path, FileMode.Create)); @@ -302,8 +302,8 @@ public void BulkLoadConflictOptionReplace() loader.Load(); DataTable dt = Utils.FillTable("SELECT * FROM Test", Connection); - Assert.AreEqual(20, dt.Rows.Count); - Assert.AreEqual("col2", dt.Rows[0][1].ToString().Trim()); + Assert.That(dt.Rows.Count, Is.EqualTo(20)); + Assert.That(dt.Rows[0][1].ToString().Trim(), Is.EqualTo("col2")); } [Test] @@ -326,7 +326,7 @@ public void BulkLoadConflictOptionIgnore() loader.FieldTerminator = ","; loader.Local = true; int count = loader.Load(); - Assert.AreEqual(20, count); + Assert.That(count, Is.EqualTo(20)); path = Path.GetTempFileName(); sw = new StreamWriter(new FileStream(path, FileMode.Create)); @@ -345,8 +345,8 @@ public void BulkLoadConflictOptionIgnore() loader.Load(); DataTable dt = Utils.FillTable("SELECT * FROM Test", Connection); - Assert.AreEqual(20, dt.Rows.Count); - Assert.AreEqual("col1", dt.Rows[0][1].ToString().Trim()); + Assert.That(dt.Rows.Count, Is.EqualTo(20)); + Assert.That(dt.Rows[0][1].ToString().Trim(), Is.EqualTo("col1")); } #region AsyncTests @@ -373,8 +373,8 @@ public void BulkLoadSimpleAsync() int dataLoaded = loadResult.Result; DataTable dt = Utils.FillTable("SELECT * FROM BulkLoadSimpleAsyncTest", Connection); - Assert.AreEqual(dataLoaded, dt.Rows.Count); - Assert.AreEqual("'Test'", dt.Rows[0][1].ToString().Trim()); + Assert.That(dt.Rows.Count, Is.EqualTo(dataLoaded)); + Assert.That(dt.Rows[0][1].ToString().Trim(), Is.EqualTo("'Test'")); }).Wait(); } @@ -406,8 +406,8 @@ public void BulkLoadReadOnlyFileAsync() int dataLoaded = loadResult.Result; DataTable dt = Utils.FillTable("SELECT * FROM BulkLoadReadOnlyFileAsyncTest", Connection); - Assert.AreEqual(dataLoaded, dt.Rows.Count); - Assert.AreEqual("'Test'", dt.Rows[0][1].ToString().Trim()); + Assert.That(dt.Rows.Count, Is.EqualTo(dataLoaded)); + Assert.That(dt.Rows[0][1].ToString().Trim(), Is.EqualTo("'Test'")); }).Wait(); } finally @@ -442,9 +442,9 @@ public void BulkLoadFieldQuotingAsync() int dataLoaded = loadResult.Result; DataTable dt = Utils.FillTable("SELECT * FROM BulkLoadFieldQuotingAsyncTest", Connection); - Assert.AreEqual(dataLoaded, dt.Rows.Count); - Assert.AreEqual("col1", dt.Rows[0][1]); - Assert.AreEqual("col2", dt.Rows[0][2].ToString().Trim()); + Assert.That(dt.Rows.Count, Is.EqualTo(dataLoaded)); + Assert.That(dt.Rows[0][1], Is.EqualTo("col1")); + Assert.That(dt.Rows[0][2].ToString().Trim(), Is.EqualTo("col2")); }).Wait(); } @@ -473,9 +473,9 @@ public void BulkLoadEscapingAsync() int dataLoaded = loadResult.Result; DataTable dt = Utils.FillTable("SELECT * FROM BulkLoadEscapingAsyncTest", Connection); - Assert.AreEqual(dataLoaded, dt.Rows.Count); - Assert.AreEqual("col1still col1", dt.Rows[0][1]); - Assert.AreEqual("col2", dt.Rows[0][2].ToString().Trim()); + Assert.That(dt.Rows.Count, Is.EqualTo(dataLoaded)); + Assert.That(dt.Rows[0][1], Is.EqualTo("col1still col1")); + Assert.That(dt.Rows[0][2].ToString().Trim(), Is.EqualTo("col2")); }).Wait(); } @@ -517,8 +517,8 @@ public void BulkLoadConflictOptionReplaceAsync() loader.LoadAsync().Wait(); DataTable dt = Utils.FillTable("SELECT * FROM BulkLoadConflictOptionReplaceAsyncTest", Connection); - Assert.AreEqual(20, dt.Rows.Count); - Assert.AreEqual("col2", dt.Rows[0][1].ToString().Trim()); + Assert.That(dt.Rows.Count, Is.EqualTo(20)); + Assert.That(dt.Rows[0][1].ToString().Trim(), Is.EqualTo("col2")); } [Test] @@ -563,8 +563,8 @@ public void BulkLoadConflictOptionIgnoreAsync() { int dataLoaded = loadResult.Result; DataTable dt = Utils.FillTable("SELECT * FROM BulkLoadConflictOptionIgnoreAsyncTest", Connection); - Assert.AreEqual(20, dt.Rows.Count); - Assert.AreEqual("col1", dt.Rows[0][1].ToString().Trim()); + Assert.That(dt.Rows.Count, Is.EqualTo(20)); + Assert.That(dt.Rows[0][1].ToString().Trim(), Is.EqualTo("col1")); }).Wait(); } @@ -596,10 +596,10 @@ public void BulkLoadColumnOrderAsync() { int dataLoaded = loadResult.Result; DataTable dt = Utils.FillTable("SELECT * FROM BulkLoadColumnOrderAsyncTest", Connection); - Assert.AreEqual(20, dt.Rows.Count); - Assert.AreEqual("col1", dt.Rows[0][1]); - Assert.AreEqual("col2", dt.Rows[0][2]); - Assert.AreEqual("col3", dt.Rows[0][3].ToString().Trim()); + Assert.That(dt.Rows.Count, Is.EqualTo(20)); + Assert.That(dt.Rows[0][1], Is.EqualTo("col1")); + Assert.That(dt.Rows[0][2], Is.EqualTo("col2")); + Assert.That(dt.Rows[0][3].ToString().Trim(), Is.EqualTo("col3")); }).Wait(); } #endregion @@ -636,13 +636,13 @@ public void BulkLoadColumnOrder() loader.Columns.Add("n1"); loader.Local = true; int count = loader.Load(); - Assert.AreEqual(20, count); + Assert.That(count, Is.EqualTo(20)); DataTable dt = Utils.FillTable("SELECT * FROM Test", Connection); - Assert.AreEqual(20, dt.Rows.Count); - Assert.AreEqual("col1", dt.Rows[0][1]); - Assert.AreEqual("col2", dt.Rows[0][2]); - Assert.AreEqual("col3", dt.Rows[0][3].ToString().Trim()); + Assert.That(dt.Rows.Count, Is.EqualTo(20)); + Assert.That(dt.Rows[0][1], Is.EqualTo("col1")); + Assert.That(dt.Rows[0][2], Is.EqualTo("col2")); + Assert.That(dt.Rows[0][3].ToString().Trim(), Is.EqualTo("col3")); } /// @@ -703,11 +703,11 @@ public void BulkLoadUsingSafePath(bool allowLoadLocalInfile, string allowLoadLoc if (shouldPass) { int count = loader.Load(); - Assert.AreEqual(200, count); + Assert.That(count, Is.EqualTo(200)); DataTable dt = Utils.FillTable("SELECT * FROM Test", Connection); - Assert.AreEqual(200, dt.Rows.Count); - Assert.AreEqual("'Test'", dt.Rows[0][1].ToString().Trim()); + Assert.That(dt.Rows.Count, Is.EqualTo(200)); + Assert.That(dt.Rows[0][1].ToString().Trim(), Is.EqualTo("'Test'")); } else if (isSymLink && !Directory.Exists(allowLoadLocalInfileInPath)) Assert.Ignore("For the symbolic link test to run, it should be manually created before executing it."); @@ -716,11 +716,11 @@ public void BulkLoadUsingSafePath(bool allowLoadLocalInfile, string allowLoadLoc var ex = Assert.Throws(() => loader.Load()); if (allowLoadLocalInfileInPath == " " || allowLoadLocalInfileInPath is null) if (Version > new Version(8, 0)) - Assert.AreEqual("Loading local data is disabled; this must be enabled on both the client and server sides", ex.Message); + Assert.That(ex.Message, Is.EqualTo("Loading local data is disabled; this must be enabled on both the client and server sides")); else - Assert.AreEqual("The used command is not allowed with this MySQL version", ex.Message); + Assert.That(ex.Message, Is.EqualTo("The used command is not allowed with this MySQL version")); else - StringAssert.Contains("allowloadlocalinfileinpath", ex.Message); + Assert.That(ex.Message, Does.Contain("allowloadlocalinfileinpath")); } File.Delete(path); @@ -755,10 +755,10 @@ public void InsertFilesInDatabase() cmd.Parameters.AddWithValue("@FileSize", fileSize); cmd.Parameters.AddWithValue("@File", rawData); var result = cmd.ExecuteNonQuery(); - Assert.IsNotNull(result); + Assert.That(result, Is.Not.Null); cmd.CommandText = "select count(*) from file;"; var count = cmd.ExecuteScalar(); - Assert.AreEqual(1, count); + Assert.That(count, Is.EqualTo(1)); } } @@ -783,11 +783,11 @@ public void BulkLoadStream() loader.Timeout = 0; loader.Local = true; int count = loader.Load(stream); - Assert.AreEqual(200, count); + Assert.That(count, Is.EqualTo(200)); DataTable dt = Utils.FillTable("SELECT * FROM Test", Connection); - Assert.AreEqual(200, dt.Rows.Count); - Assert.AreEqual("'Test'", dt.Rows[0][1].ToString().Trim()); + Assert.That(dt.Rows.Count, Is.EqualTo(200)); + Assert.That(dt.Rows[0][1].ToString().Trim(), Is.EqualTo("'Test'")); } [Test] @@ -817,10 +817,10 @@ public void BulkLoadStream2() loader.LinePrefix = "bbb"; loader.Local = true; int count = loader.Load(stream); - Assert.AreEqual(200, count); + Assert.That(count, Is.EqualTo(200)); using MySqlCommand cmd = new MySqlCommand("SELECT COUNT(*) FROM Test", Connection); - Assert.AreEqual(200, Convert.ToInt32(cmd.ExecuteScalar())); + Assert.That(Convert.ToInt32(cmd.ExecuteScalar()), Is.EqualTo(200)); } [Test] @@ -847,13 +847,13 @@ public void BulkLoadStreamColumnOrder() loader.Columns.Add("n1"); loader.Local = true; int count = loader.Load(stream); - Assert.AreEqual(20, count); + Assert.That(count, Is.EqualTo(20)); DataTable dt = Utils.FillTable("SELECT * FROM Test", Connection); - Assert.AreEqual(20, dt.Rows.Count); - Assert.AreEqual("col1", dt.Rows[0][1]); - Assert.AreEqual("col2", dt.Rows[0][2]); - Assert.AreEqual("col3", dt.Rows[0][3].ToString().Trim()); + Assert.That(dt.Rows.Count, Is.EqualTo(20)); + Assert.That(dt.Rows[0][1], Is.EqualTo("col1")); + Assert.That(dt.Rows[0][2], Is.EqualTo("col2")); + Assert.That(dt.Rows[0][3].ToString().Trim(), Is.EqualTo("col3")); } } } diff --git a/MySQL.Data/tests/MySql.Data.Tests/MySqlDataReaderTests.cs b/MySQL.Data/tests/MySql.Data.Tests/MySqlDataReaderTests.cs index 9ebad9a27..29f4647b5 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/MySqlDataReaderTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/MySqlDataReaderTests.cs @@ -68,25 +68,25 @@ public void TestMultipleResultsets() cmd = new MySqlCommand("SELECT id FROM Test WHERE id<50; SELECT * FROM Test WHERE id >= 50;", Connection); using (MySqlDataReader reader = cmd.ExecuteReader()) { - Assert.NotNull(reader); - Assert.True(reader.HasRows); - Assert.True(reader.Read()); - Assert.AreEqual(1, reader.FieldCount); - Assert.True(reader.NextResult()); - Assert.True(reader.HasRows); - Assert.AreEqual(5, reader.FieldCount); + Assert.That(reader, Is.Not.Null); + Assert.That(reader.HasRows); + Assert.That(reader.Read()); + Assert.That(reader.FieldCount, Is.EqualTo(1)); + Assert.That(reader.NextResult()); + Assert.That(reader.HasRows); + Assert.That(reader.FieldCount, Is.EqualTo(5)); } // now do it again using (MySqlDataReader reader = cmd.ExecuteReader()) { - Assert.NotNull(reader); - Assert.True(reader.HasRows); - Assert.True(reader.Read()); - Assert.AreEqual(1, reader.FieldCount); - Assert.True(reader.NextResult()); - Assert.True(reader.HasRows); - Assert.AreEqual(5, reader.FieldCount); + Assert.That(reader, Is.Not.Null); + Assert.That(reader.HasRows); + Assert.That(reader.Read()); + Assert.That(reader.FieldCount, Is.EqualTo(1)); + Assert.That(reader.NextResult()); + Assert.That(reader.HasRows); + Assert.That(reader.FieldCount, Is.EqualTo(5)); } } @@ -107,26 +107,26 @@ public void GetBytes() reader.Read(); long sizeBytes = reader.GetBytes(4, 0, null, 0, 0); - Assert.AreEqual(len, sizeBytes); + Assert.That(sizeBytes, Is.EqualTo(len)); byte[] buff1 = new byte[len / 2]; byte[] buff2 = new byte[len - (len / 2)]; long buff1cnt = reader.GetBytes(4, 0, buff1, 0, len / 2); long buff2cnt = reader.GetBytes(4, buff1cnt, buff2, 0, buff2.Length); - Assert.AreEqual(buff1.Length, buff1cnt); - Assert.AreEqual(buff2.Length, buff2cnt); + Assert.That(buff1cnt, Is.EqualTo(buff1.Length)); + Assert.That(buff2cnt, Is.EqualTo(buff2.Length)); for (int i = 0; i < buff1.Length; i++) - Assert.AreEqual(bytes[i], buff1[i]); + Assert.That(buff1[i], Is.EqualTo(bytes[i])); for (int i = 0; i < buff2.Length; i++) - Assert.AreEqual(bytes[buff1.Length + i], buff2[i]); + Assert.That(buff2[i], Is.EqualTo(bytes[buff1.Length + i])); } // now check with sequential access using (MySqlDataReader reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess)) { - Assert.True(reader.Read()); + Assert.That(reader.Read()); int mylen = len; byte[] buff = new byte[8192]; int startIndex = 0; @@ -134,9 +134,9 @@ public void GetBytes() { int readLen = Math.Min(mylen, buff.Length); int retVal = (int)reader.GetBytes(4, startIndex, buff, 0, readLen); - Assert.AreEqual(readLen, retVal); + Assert.That(retVal, Is.EqualTo(readLen)); for (int i = 0; i < readLen; i++) - Assert.AreEqual(bytes[startIndex + i], buff[i]); + Assert.That(buff[i], Is.EqualTo(bytes[startIndex + i])); startIndex += readLen; mylen -= readLen; } @@ -155,10 +155,10 @@ public void TestSingleResultSetBehavior() using (MySqlDataReader reader = cmd.ExecuteReader(CommandBehavior.SingleResult)) { bool result = reader.Read(); - Assert.True(result); + Assert.That(result); result = reader.NextResult(); - Assert.False(result); + Assert.That(result, Is.False); } } @@ -180,23 +180,23 @@ public void GetSchema() using (MySqlDataReader reader = cmd.ExecuteReader()) { DataTable dt = reader.GetSchemaTable(); - Assert.True(true == (Boolean)dt.Rows[0]["IsAutoIncrement"], "Checking auto increment"); - Assert.False((bool)dt.Rows[0]["IsUnique"], "Checking IsUnique"); - Assert.True((bool)dt.Rows[0]["IsKey"]); - Assert.True(false == (Boolean)dt.Rows[0]["AllowDBNull"], "Checking AllowDBNull"); - Assert.True(false == (Boolean)dt.Rows[1]["AllowDBNull"], "Checking AllowDBNull"); - Assert.AreEqual(255, dt.Rows[1]["ColumnSize"]); - Assert.AreEqual(40, dt.Rows[2]["ColumnSize"]); + Assert.That(true == (Boolean)dt.Rows[0]["IsAutoIncrement"], "Checking auto increment"); + Assert.That((bool)dt.Rows[0]["IsUnique"], Is.False, "Checking IsUnique"); + Assert.That((bool)dt.Rows[0]["IsKey"]); + Assert.That(false == (Boolean)dt.Rows[0]["AllowDBNull"], "Checking AllowDBNull"); + Assert.That(false == (Boolean)dt.Rows[1]["AllowDBNull"], "Checking AllowDBNull"); + Assert.That(dt.Rows[1]["ColumnSize"], Is.EqualTo(255)); + Assert.That(dt.Rows[2]["ColumnSize"], Is.EqualTo(40)); // udec column - Assert.AreEqual(21, dt.Rows[5]["ColumnSize"]); - Assert.AreEqual(20, dt.Rows[5]["NumericPrecision"]); - Assert.AreEqual(6, dt.Rows[5]["NumericScale"]); + Assert.That(dt.Rows[5]["ColumnSize"], Is.EqualTo(21)); + Assert.That(dt.Rows[5]["NumericPrecision"], Is.EqualTo(20)); + Assert.That(dt.Rows[5]["NumericScale"], Is.EqualTo(6)); // dec column - Assert.AreEqual(46, dt.Rows[6]["ColumnSize"]); - Assert.AreEqual(44, dt.Rows[6]["NumericPrecision"]); - Assert.AreEqual(3, dt.Rows[6]["NumericScale"]); + Assert.That(dt.Rows[6]["ColumnSize"], Is.EqualTo(46)); + Assert.That(dt.Rows[6]["NumericPrecision"], Is.EqualTo(44)); + Assert.That(dt.Rows[6]["NumericScale"], Is.EqualTo(3)); } } @@ -212,9 +212,9 @@ public void CloseConnectionBehavior() MySqlCommand cmd = new MySqlCommand("SELECT * FROM Test", c2); using (MySqlDataReader reader = cmd.ExecuteReader(CommandBehavior.CloseConnection)) { - Assert.True(reader.Read()); + Assert.That(reader.Read()); reader.Close(); - Assert.True(c2.State == ConnectionState.Closed); + Assert.That(c2.State == ConnectionState.Closed); } } } @@ -230,18 +230,18 @@ public void SingleRowBehavior() MySqlCommand cmd = new MySqlCommand("SELECT * FROM Test", Connection); using (MySqlDataReader reader = cmd.ExecuteReader(CommandBehavior.SingleRow)) { - Assert.True(reader.Read(), "First read"); - Assert.False(reader.Read(), "Second read"); - Assert.False(reader.NextResult(), "Trying NextResult"); + Assert.That(reader.Read(), "First read"); + Assert.That(reader.Read(), Is.False, "Second read"); + Assert.That(reader.NextResult(), Is.False, "Trying NextResult"); } cmd.CommandText = "SELECT * FROM Test where id=1"; using (MySqlDataReader reader = cmd.ExecuteReader(CommandBehavior.SingleRow)) { - Assert.True(reader.Read()); - Assert.AreEqual("test1", reader.GetString(1)); - Assert.False(reader.Read()); - Assert.False(reader.NextResult()); + Assert.That(reader.Read()); + Assert.That(reader.GetString(1), Is.EqualTo("test1")); + Assert.That(reader.Read(), Is.False); + Assert.That(reader.NextResult(), Is.False); } } @@ -256,23 +256,23 @@ public void SingleRowBehaviorWithLimit() MySqlCommand cmd = new MySqlCommand("SELECT * FROM Test LIMIT 2", Connection); using (MySqlDataReader reader = cmd.ExecuteReader(CommandBehavior.SingleRow)) { - Assert.True(reader.Read(), "First read"); - Assert.False(reader.Read(), "Second read"); - Assert.False(reader.NextResult(), "Trying NextResult"); + Assert.That(reader.Read(), "First read"); + Assert.That(reader.Read(), Is.False, "Second read"); + Assert.That(reader.NextResult(), Is.False, "Trying NextResult"); } using (MySqlDataReader reader = cmd.ExecuteReader(CommandBehavior.SingleRow)) { - Assert.True(reader.Read(), "First read"); - Assert.False(reader.Read(), "Second read"); - Assert.False(reader.NextResult(), "Trying NextResult"); + Assert.That(reader.Read(), "First read"); + Assert.That(reader.Read(), Is.False, "Second read"); + Assert.That(reader.NextResult(), Is.False, "Trying NextResult"); } using (MySqlDataReader reader = cmd.ExecuteReader(CommandBehavior.SingleRow)) { - Assert.True(reader.Read(), "First read"); - Assert.False(reader.Read(), "Second read"); - Assert.False(reader.NextResult(), "Trying NextResult"); + Assert.That(reader.Read(), "First read"); + Assert.That(reader.Read(), Is.False, "Second read"); + Assert.That(reader.NextResult(), Is.False, "Trying NextResult"); } } @@ -285,11 +285,11 @@ public void SimpleSingleRow() MySqlCommand cmd = new MySqlCommand("SELECT * FROM Test", Connection); using (MySqlDataReader reader = cmd.ExecuteReader()) { - Assert.True(reader.Read(), "First read"); - Assert.AreEqual(1, reader.GetInt32(0)); - Assert.AreEqual("test1", reader.GetString(1)); - Assert.False(reader.Read(), "Second read"); - Assert.False(reader.NextResult(), "Trying NextResult"); + Assert.That(reader.Read(), "First read"); + Assert.That(reader.GetInt32(0), Is.EqualTo(1)); + Assert.That(reader.GetString(1), Is.EqualTo("test1")); + Assert.That(reader.Read(), Is.False, "Second read"); + Assert.That(reader.NextResult(), Is.False, "Trying NextResult"); } } @@ -305,25 +305,25 @@ public void ConsecutiveNulls() using (MySqlDataReader reader = cmd.ExecuteReader()) { reader.Read(); - Assert.AreEqual(1, reader.GetValue(0)); - Assert.AreEqual("Test", reader.GetValue(1)); - Assert.AreEqual("Test", reader.GetString(1)); - Assert.AreEqual(DBNull.Value, reader.GetValue(2)); + Assert.That(reader.GetValue(0), Is.EqualTo(1)); + Assert.That(reader.GetValue(1), Is.EqualTo("Test")); + Assert.That(reader.GetString(1), Is.EqualTo("Test")); + Assert.That(reader.GetValue(2), Is.EqualTo(DBNull.Value)); reader.Read(); - Assert.AreEqual(2, reader.GetValue(0)); - Assert.AreEqual(DBNull.Value, reader.GetValue(1)); + Assert.That(reader.GetValue(0), Is.EqualTo(2)); + Assert.That(reader.GetValue(1), Is.EqualTo(DBNull.Value)); Exception ex = Assert.Throws(() => reader.GetString(1)); - Assert.AreEqual("Data is Null. This method or property cannot be called on Null values.", ex.Message); - Assert.False(reader.IsDBNull(2)); + Assert.That(ex.Message, Is.EqualTo("Data is Null. This method or property cannot be called on Null values.")); + Assert.That(reader.IsDBNull(2), Is.False); reader.Read(); - Assert.AreEqual(3, reader.GetValue(0)); - Assert.AreEqual("Test2", reader.GetValue(1)); - Assert.AreEqual("Test2", reader.GetString(1)); - Assert.AreEqual(DBNull.Value, reader.GetValue(2)); + Assert.That(reader.GetValue(0), Is.EqualTo(3)); + Assert.That(reader.GetValue(1), Is.EqualTo("Test2")); + Assert.That(reader.GetString(1), Is.EqualTo("Test2")); + Assert.That(reader.GetValue(2), Is.EqualTo(DBNull.Value)); ex = Assert.Throws(() => reader.GetMySqlDateTime(2)); - Assert.AreEqual("Data is Null. This method or property cannot be called on Null values.", ex.Message); - Assert.False(reader.Read()); - Assert.False(reader.NextResult()); + Assert.That(ex.Message, Is.EqualTo("Data is Null. This method or property cannot be called on Null values.")); + Assert.That(reader.Read(), Is.False); + Assert.That(reader.NextResult(), Is.False); } } @@ -352,16 +352,16 @@ public void SequentialAccessBehavior() MySqlCommand cmd = new MySqlCommand("SELECT * FROM Test", Connection); using (MySqlDataReader reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess)) { - Assert.True(reader.Read()); - Assert.False(reader.IsDBNull(0)); + Assert.That(reader.Read()); + Assert.That(reader.IsDBNull(0), Is.False); int i = reader.GetInt32(0); string s = reader.GetString(1); - Assert.AreEqual(1, i); - Assert.AreEqual("test1", s); + Assert.That(i, Is.EqualTo(1)); + Assert.That(s, Is.EqualTo("test1")); // this next line should throw an exception Exception ex = Assert.Throws(() => i = reader.GetInt32(0)); - Assert.AreEqual("Invalid attempt to read a prior column using SequentialAccess", ex.Message); + Assert.That(ex.Message, Is.EqualTo("Invalid attempt to read a prior column using SequentialAccess")); } } @@ -377,7 +377,7 @@ public void ReadingTextFields() { reader.Read(); string s = reader["t1"].ToString(); - Assert.AreEqual("Text value", s); + Assert.That(s, Is.EqualTo("Text value")); } } @@ -408,7 +408,7 @@ public void GetChar() { reader.Read(); char achar = reader.GetChar(1); - Assert.AreEqual('a', achar); + Assert.That(achar, Is.EqualTo('a')); } } @@ -419,12 +419,12 @@ public void ReaderOnNonQuery() MySqlCommand cmd = new MySqlCommand("INSERT INTO Test (id,name) VALUES (1,'Test')", Connection); using (MySqlDataReader reader = cmd.ExecuteReader()) { - Assert.False(reader.Read()); + Assert.That(reader.Read(), Is.False); reader.Close(); cmd.CommandText = "SELECT name FROM Test"; object v = cmd.ExecuteScalar(); - Assert.AreEqual("Test", v); + Assert.That(v, Is.EqualTo("Test")); } } @@ -456,69 +456,69 @@ public void TestManyDifferentResultsets() { //First ResultSet, should have 49 rows. //SELECT id FROM Test WHERE id= ?param1; - Assert.True(reader.NextResult()); - Assert.True(reader.HasRows); - Assert.AreEqual(5, reader.FieldCount); + Assert.That(reader.NextResult()); + Assert.That(reader.HasRows); + Assert.That(reader.FieldCount, Is.EqualTo(5)); for (int i = 0; i < 51; i++) { - Assert.True(reader.Read()); + Assert.That(reader.Read()); } - Assert.False(reader.Read()); + Assert.That(reader.Read(), Is.False); //Fourth ResultSet, should have no rows. //SELECT id, dt, b1 FROM Test WHERE id = -50; - Assert.True(reader.NextResult()); - Assert.False(reader.HasRows); - Assert.AreEqual(3, reader.FieldCount); //Will Fail if uncommented expected 3 returned 5 - Assert.False(reader.Read()); + Assert.That(reader.NextResult()); + Assert.That(reader.HasRows, Is.False); + Assert.That(reader.FieldCount, Is.EqualTo(3)); //Will Fail if uncommented expected 3 returned 5 + Assert.That(reader.Read(), Is.False); //Fifth ResultSet, should have no rows. //SELECT b1 FROM Test WHERE id = -50; - Assert.True(reader.NextResult()); - Assert.False(reader.HasRows); - Assert.AreEqual(1, reader.FieldCount); //Will Fail if uncommented expected 1 returned 5 - Assert.False(reader.Read()); + Assert.That(reader.NextResult()); + Assert.That(reader.HasRows, Is.False); + Assert.That(reader.FieldCount, Is.EqualTo(1)); //Will Fail if uncommented expected 1 returned 5 + Assert.That(reader.Read(), Is.False); //Sixth ResultSet, should have 49 rows. //SELECT id, dt, b1 FROM Test WHERE id < ?param1; - Assert.True(reader.NextResult()); - Assert.True(reader.HasRows); - Assert.AreEqual(3, reader.FieldCount); //Will Fail if uncommented expected 3 returned 5 + Assert.That(reader.NextResult()); + Assert.That(reader.HasRows); + Assert.That(reader.FieldCount, Is.EqualTo(3)); //Will Fail if uncommented expected 3 returned 5 for (int i = 0; i < 49; i++) { - Assert.True(reader.Read()); + Assert.That(reader.Read()); } - Assert.False(reader.Read()); + Assert.That(reader.Read(), Is.False); //Seventh ResultSet, should have 51 rows. //SELECT b1 FROM Test WHERE id >= ?param1; - Assert.True(reader.NextResult()); - Assert.True(reader.HasRows); - Assert.AreEqual(1, reader.FieldCount); //Will Fail if uncommented expected 1 returned 5 + Assert.That(reader.NextResult()); + Assert.That(reader.HasRows); + Assert.That(reader.FieldCount, Is.EqualTo(1)); //Will Fail if uncommented expected 1 returned 5 for (int i = 0; i < 51; i++) { - Assert.True(reader.Read()); + Assert.That(reader.Read()); } - Assert.False(reader.Read()); + Assert.That(reader.Read(), Is.False); } } @@ -539,25 +539,25 @@ public void TestMultipleResultsWithQueryCacheOn() using (MySqlDataReader reader = cmd.ExecuteReader()) { - Assert.NotNull(reader); - Assert.True(reader.HasRows); - Assert.True(reader.Read()); - Assert.AreEqual(1, reader.FieldCount); - Assert.True(reader.NextResult()); - Assert.True(reader.HasRows); - Assert.AreEqual(5, reader.FieldCount); + Assert.That(reader, Is.Not.Null); + Assert.That(reader.HasRows); + Assert.That(reader.Read()); + Assert.That(reader.FieldCount, Is.EqualTo(1)); + Assert.That(reader.NextResult()); + Assert.That(reader.HasRows); + Assert.That(reader.FieldCount, Is.EqualTo(5)); } // now do it again using (MySqlDataReader reader = cmd.ExecuteReader()) { - Assert.NotNull(reader); - Assert.True(reader.HasRows); - Assert.True(reader.Read()); - Assert.AreEqual(1, reader.FieldCount); - Assert.True(reader.NextResult()); - Assert.True(reader.HasRows); - Assert.AreEqual(5, reader.FieldCount); + Assert.That(reader, Is.Not.Null); + Assert.That(reader.HasRows); + Assert.That(reader.Read()); + Assert.That(reader.FieldCount, Is.EqualTo(1)); + Assert.That(reader.NextResult()); + Assert.That(reader.HasRows); + Assert.That(reader.FieldCount, Is.EqualTo(5)); } } @@ -572,7 +572,7 @@ public void AffectedRows() { reader.Read(); reader.Close(); - Assert.AreEqual(-1, reader.RecordsAffected); + Assert.That(reader.RecordsAffected, Is.EqualTo(-1)); } } @@ -591,7 +591,7 @@ public void InvalidTimestamp() Assert.Throws(() => reader = cmd.ExecuteReader()); else { - CollectionAssert.IsEmpty(reader = cmd.ExecuteReader()); + Assert.That(reader = cmd.ExecuteReader(), Is.Empty); reader.Close(); } } @@ -629,7 +629,7 @@ public void GetSchemaTableOnEmptyResultset() using (MySqlDataReader reader = cmd.ExecuteReader()) { DataTable dt = reader.GetSchemaTable(); - Assert.Null(dt); + Assert.That(dt, Is.Null); } } @@ -645,8 +645,8 @@ public void IsDbNullOnNonNullFields() MySqlCommand cmd = new MySqlCommand("SELECT * FROM Test", Connection); using (MySqlDataReader reader = cmd.ExecuteReader()) { - Assert.True(reader.Read()); - Assert.False(reader.IsDBNull(1)); + Assert.That(reader.Read()); + Assert.That(reader.IsDBNull(1), Is.False); } } @@ -691,7 +691,7 @@ public void CloseConnectionBehavior2() MySqlCommand cmd = new MySqlCommand("SELECT * FROM Test", c2); using (MySqlDataReader reader = cmd.ExecuteReader(CommandBehavior.CloseConnection)) { - Assert.True(reader.Read()); + Assert.That(reader.Read()); } } } @@ -710,26 +710,26 @@ public void CommandBehaviorSchemaOnly() MySqlCommand cmd = new MySqlCommand("select * from doesnotexist", Connection); MySqlDataReader reader; Exception ex = Assert.Throws(() => reader = cmd.ExecuteReader(CommandBehavior.SchemaOnly)); - StringAssert.Contains(".doesnotexist' doesn't exist", ex.Message); + Assert.That(ex.Message, Does.Contain(".doesnotexist' doesn't exist")); // Check that failed ExecuteReader did not leave SQL_SELECT_LIMIT // set to 0. cmd.CommandText = "select now()"; reader = cmd.ExecuteReader(); - Assert.True(reader.Read()); + Assert.That(reader.Read()); reader.Close(); // Check that CommandBehavior.SchemaOnly does not return rows reader = cmd.ExecuteReader(CommandBehavior.SchemaOnly); - Assert.False(reader.Read()); + Assert.That(reader.Read(), Is.False); reader.Close(); reader = cmd.ExecuteReader(); // Check that prior setting of CommandBehavior did not // leave SQL_SELECT_LIMIT set to 0 - Assert.True(reader.Read()); + Assert.That(reader.Read()); reader.Close(); } @@ -748,8 +748,8 @@ public void ColumnsWithSameName() reader.Read(); string name1 = reader.GetString(0); string name2 = reader.GetString(1); - Assert.AreEqual(name1, name2); - Assert.AreEqual("test", name1); + Assert.That(name2, Is.EqualTo(name1)); + Assert.That(name1, Is.EqualTo("test")); } cmd.CommandText = "SELECT 'a' AS XYZ, 'b' as Xyz"; @@ -773,7 +773,7 @@ public void Bug47467() reader.Read(); Type t = reader.GetFieldType("c1"); Exception ex = Assert.Throws(() => reader.GetOrdinal("nocol")); - Assert.True(ex.Message.IndexOf("nocol") != -1); + Assert.That(ex.Message.IndexOf("nocol") != -1); } } @@ -802,7 +802,7 @@ public void GetStream() using (var stream = reader.GetStream(0)) { string result = UTF8Encoding.UTF8.GetString(((MemoryStream)stream).ToArray()); - StringAssert.AreEqualIgnoringCase(str, result); + Assert.That(result, Is.EqualTo(str).IgnoreCase); } } } @@ -835,12 +835,12 @@ public void GetFieldValue() using (var reader = cmd.ExecuteReader()) { reader.Read(); - Assert.AreEqual(1, reader.GetFieldValue(0)); - Assert.AreEqual(1.23, reader.GetFieldValue(1)); - Assert.AreEqual("test", reader.GetFieldValue(2)); - Assert.AreEqual(dateTime.ToShortDateString(), reader.GetFieldValue(3).ToShortDateString()); - Assert.AreEqual(true, reader.GetFieldValue(4)); - StringAssert.AreEqualIgnoringCase(str, Encoding.UTF8.GetString(((MemoryStream)reader.GetFieldValue(5)).ToArray())); + Assert.That(reader.GetFieldValue(0), Is.EqualTo(1)); + Assert.That(reader.GetFieldValue(1), Is.EqualTo(1.23)); + Assert.That(reader.GetFieldValue(2), Is.EqualTo("test")); + Assert.That(reader.GetFieldValue(3).ToShortDateString(), Is.EqualTo(dateTime.ToShortDateString())); + Assert.That(reader.GetFieldValue(4), Is.EqualTo(true)); + Assert.That(Encoding.UTF8.GetString(((MemoryStream)reader.GetFieldValue(5)).ToArray()), Is.EqualTo(str).IgnoreCase); } } } diff --git a/MySQL.Data/tests/MySql.Data.Tests/OutputParametersBatch.cs b/MySQL.Data/tests/MySql.Data.Tests/OutputParametersBatch.cs index 2f1ddbbee..9fb16057c 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/OutputParametersBatch.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/OutputParametersBatch.cs @@ -58,7 +58,7 @@ protected override void Cleanup() public void OutputParameters() { // we don't want to run this test under no access - Assert.True(Settings.CheckParameters); + Assert.That(Settings.CheckParameters); // create our procedure ExecuteSQL("CREATE PROCEDURE spTest(out value VARCHAR(350), OUT intVal INT, " + @@ -89,14 +89,13 @@ public void OutputParameters() if (prepare) cmd.Prepare(); int rowsAffected = cmd.ExecuteNonQuery(); - Assert.AreEqual(0, rowsAffected); - Assert.AreEqual("42", cmd.Parameters[0].Value); - Assert.AreEqual(33, cmd.Parameters[1].Value); - Assert.AreEqual(new DateTime(2004, 6, 5, 7, 58, 9), - Convert.ToDateTime(cmd.Parameters[2].Value)); - Assert.AreEqual((decimal)1.2, (decimal)(float)cmd.Parameters[3].Value); - Assert.AreEqual("test", cmd.Parameters[4].Value); - Assert.AreEqual(66, cmd.Parameters[5].Value); + Assert.That(rowsAffected, Is.EqualTo(0)); + Assert.That(cmd.Parameters[0].Value, Is.EqualTo("42")); + Assert.That(cmd.Parameters[1].Value, Is.EqualTo(33)); + Assert.That(Convert.ToDateTime(cmd.Parameters[2].Value), Is.EqualTo(new DateTime(2004, 6, 5, 7, 58, 9))); + Assert.That((decimal)(float)cmd.Parameters[3].Value, Is.EqualTo((decimal)1.2)); + Assert.That(cmd.Parameters[4].Value, Is.EqualTo("test")); + Assert.That(cmd.Parameters[5].Value, Is.EqualTo(66)); } [Test] @@ -116,10 +115,10 @@ public void InputOutputParameters() cmd.Parameters[2].Direction = ParameterDirection.Output; if (prepare) cmd.Prepare(); int rowsAffected = cmd.ExecuteNonQuery(); - Assert.AreEqual(0, rowsAffected); - Assert.AreEqual("beginningending", cmd.Parameters[0].Value); - Assert.AreEqual(66, cmd.Parameters[1].Value); - Assert.AreEqual(99, cmd.Parameters[2].Value); + Assert.That(rowsAffected, Is.EqualTo(0)); + Assert.That(cmd.Parameters[0].Value, Is.EqualTo("beginningending")); + Assert.That(cmd.Parameters[1].Value, Is.EqualTo(66)); + Assert.That(cmd.Parameters[2].Value, Is.EqualTo(99)); } [Test] @@ -136,8 +135,8 @@ public void ExecuteScalar() cmd.Parameters[1].Direction = ParameterDirection.Output; if (prepare) cmd.Prepare(); object result = cmd.ExecuteScalar(); - Assert.AreEqual("Test", result); - Assert.AreEqual("valuein", cmd.Parameters[1].Value); + Assert.That(result, Is.EqualTo("Test")); + Assert.That(cmd.Parameters[1].Value, Is.EqualTo("valuein")); } [Test] @@ -154,11 +153,11 @@ public void ExecuteReaderTest() if (prepare) cmd.Prepare(); using (MySqlDataReader reader = cmd.ExecuteReader()) { - Assert.True(reader.Read()); - Assert.False(reader.NextResult()); - Assert.False(reader.Read()); + Assert.That(reader.Read()); + Assert.That(reader.NextResult(), Is.False); + Assert.That(reader.Read(), Is.False); } - Assert.AreEqual(2, cmd.Parameters[0].Value); + Assert.That(cmd.Parameters[0].Value, Is.EqualTo(2)); } [Test] @@ -171,7 +170,7 @@ public void FunctionNoParams() cmd.CommandType = CommandType.Text; if (prepare) cmd.Prepare(); object result = cmd.ExecuteScalar(); - Assert.AreEqual("Test", result); + Assert.That(result, Is.EqualTo("Test")); } [Test] @@ -184,7 +183,7 @@ public void FunctionParams() cmd.CommandType = CommandType.Text; if (prepare) cmd.Prepare(); object result = cmd.ExecuteScalar(); - Assert.AreEqual(26, result); + Assert.That(result, Is.EqualTo(26)); } /// @@ -206,7 +205,7 @@ public void CallingStoredFunctionasProcedure() cmd.Parameters.Add(retVal); if (prepare) cmd.Prepare(); cmd.ExecuteNonQuery(); - Assert.AreEqual(44, cmd.Parameters[1].Value); + Assert.That(cmd.Parameters[1].Value, Is.EqualTo(44)); } [Test] @@ -260,8 +259,8 @@ public void UnsignedOutputParameters() cmd.ExecuteNonQuery(); object o = cmd.Parameters[0].Value; - Assert.True(o is ulong); - Assert.AreEqual(1, Convert.ToInt32(o)); + Assert.That(o is ulong); + Assert.That(Convert.ToInt32(o), Is.EqualTo(1)); } [Test] @@ -276,7 +275,7 @@ public void CallingFunctionWithoutReturnParameter() cmd.Parameters.AddWithValue("?p_kiosk", 2); cmd.Parameters.AddWithValue("?p_user", 4); Exception ex = Assert.Throws(() => { if (prepare) cmd.Prepare(); cmd.ExecuteNonQuery(); }); - Assert.AreEqual(ex.Message, "Attempt to call stored function 'fnTest' without specifying a return parameter"); + Assert.That("Attempt to call stored function 'fnTest' without specifying a return parameter", Is.EqualTo(ex.Message)); } /// @@ -318,16 +317,16 @@ public void BinaryAndVarBinaryParameters() cmd.ExecuteNonQuery(); byte[] out1 = (byte[])cmd.Parameters[0].Value; - Assert.AreEqual('o', (char)out1[0]); - Assert.AreEqual('u', (char)out1[1]); - Assert.AreEqual('t', (char)out1[2]); - Assert.AreEqual('1', (char)out1[3]); + Assert.That((char)out1[0], Is.EqualTo('o')); + Assert.That((char)out1[1], Is.EqualTo('u')); + Assert.That((char)out1[2], Is.EqualTo('t')); + Assert.That((char)out1[3], Is.EqualTo('1')); out1 = (byte[])cmd.Parameters[1].Value; - Assert.AreEqual('o', (char)out1[0]); - Assert.AreEqual('u', (char)out1[1]); - Assert.AreEqual('t', (char)out1[2]); - Assert.AreEqual('2', (char)out1[3]); + Assert.That((char)out1[0], Is.EqualTo('o')); + Assert.That((char)out1[1], Is.EqualTo('u')); + Assert.That((char)out1[2], Is.EqualTo('t')); + Assert.That((char)out1[3], Is.EqualTo('2')); } /// @@ -350,7 +349,7 @@ RETURNS double NOT DETERMINISTIC CONTAINS SQL SQL SECURITY DEFINER if (prepare) command.Prepare(); command.ExecuteNonQuery(); double balance = Convert.ToDouble(command.Parameters["?Balance"].Value); - Assert.AreEqual(1.0, balance); + Assert.That(balance, Is.EqualTo(1.0)); } /// @@ -373,8 +372,8 @@ public void OutputParametersWithNewParamHandling() if (prepare) cmd.Prepare(); int rowsAffected = cmd.ExecuteNonQuery(); - Assert.AreEqual(0, rowsAffected); - Assert.AreEqual("42", cmd.Parameters[0].Value); + Assert.That(rowsAffected, Is.EqualTo(0)); + Assert.That(cmd.Parameters[0].Value, Is.EqualTo("42")); } } @@ -399,8 +398,8 @@ public void FunctionWithNewParamHandling() if (prepare) cmd.Prepare(); int rowsAffected = cmd.ExecuteNonQuery(); - Assert.AreEqual(0, rowsAffected); - Assert.AreEqual(22, cmd.Parameters[1].Value); + Assert.That(rowsAffected, Is.EqualTo(0)); + Assert.That(cmd.Parameters[1].Value, Is.EqualTo(22)); } } @@ -421,7 +420,7 @@ public void BitTypeAsOutParameter() cmd.Parameters.Add("x", MySqlDbType.Bit).Direction = ParameterDirection.Output; if (prepare) cmd.Prepare(); cmd.ExecuteNonQuery(); - Assert.AreEqual(0, Convert.ToInt32(cmd.Parameters[0].Value)); + Assert.That(Convert.ToInt32(cmd.Parameters[0].Value), Is.EqualTo(0)); } /// @@ -463,12 +462,12 @@ public void RunWithoutSelectPrivsThrowException() if (prepare) cmd.Prepare(); cmd.ExecuteNonQuery(); - Assert.AreEqual(6, cmd.Parameters[1].Value); - Assert.AreEqual(6, cmd.Parameters[2].Value); + Assert.That(cmd.Parameters[1].Value, Is.EqualTo(6)); + Assert.That(cmd.Parameters[2].Value, Is.EqualTo(6)); } catch (InvalidOperationException iex) { - StringAssert.StartsWith("Unable to retrieve", iex.Message); + Assert.That(iex.Message, Does.StartWith("Unable to retrieve")); } finally { @@ -500,8 +499,8 @@ public void NoAccessToProcedureBodies() if (prepare) cmd.Prepare(); cmd.ExecuteNonQuery(); - Assert.AreEqual(6, cmd.Parameters[1].Value); - Assert.AreEqual(3, cmd.Parameters[2].Value); + Assert.That(cmd.Parameters[1].Value, Is.EqualTo(6)); + Assert.That(cmd.Parameters[2].Value, Is.EqualTo(3)); } } } diff --git a/MySQL.Data/tests/MySql.Data.Tests/ParameterTests.cs b/MySQL.Data/tests/MySql.Data.Tests/ParameterTests.cs index 41448db0a..ce075ed76 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/ParameterTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/ParameterTests.cs @@ -76,19 +76,19 @@ public void TestQuoting() { reader = cmd.ExecuteReader(); reader.Read(); - Assert.AreEqual("my ' value", reader.GetString(1)); + Assert.That(reader.GetString(1), Is.EqualTo("my ' value")); reader.Read(); - Assert.AreEqual(@"my "" value", reader.GetString(1)); + Assert.That(reader.GetString(1), Is.EqualTo(@"my "" value")); reader.Read(); - Assert.AreEqual("my ` value", reader.GetString(1)); + Assert.That(reader.GetString(1), Is.EqualTo("my ` value")); reader.Read(); - Assert.AreEqual("my ´ value", reader.GetString(1)); + Assert.That(reader.GetString(1), Is.EqualTo("my ´ value")); reader.Read(); - Assert.AreEqual(@"my \ value", reader.GetString(1)); + Assert.That(reader.GetString(1), Is.EqualTo(@"my \ value")); } catch (Exception ex) { - Assert.False(ex.Message == String.Empty, ex.Message); + Assert.That(ex.Message == String.Empty, Is.False, ex.Message); } finally { @@ -109,41 +109,41 @@ public void TestDateTimeParameter() cmd.Parameters.Add(new MySqlParameter("?time", time)); cmd.Parameters.Add(new MySqlParameter("?dt", dt)); int cnt = cmd.ExecuteNonQuery(); - Assert.True(cnt == 1, "Insert count"); + Assert.That(cnt == 1, "Insert count"); cmd = new MySqlCommand("SELECT tm, dt, ts FROM Test WHERE id=1", Connection); MySqlDataReader reader = cmd.ExecuteReader(); reader.Read(); TimeSpan time2 = (TimeSpan)reader.GetValue(0); - Assert.AreEqual(time, time2); + Assert.That(time2, Is.EqualTo(time)); DateTime dt2 = reader.GetDateTime(1); - Assert.AreEqual(dt, dt2); + Assert.That(dt2, Is.EqualTo(dt)); DateTime ts2 = reader.GetDateTime(2); reader.Close(); // now check the timestamp column. We won't check the minute or second for obvious reasons DateTime now = DateTime.Now; - Assert.AreEqual(now.Year, ts2.Year); - Assert.AreEqual(now.Month, ts2.Month); - Assert.AreEqual(now.Day, ts2.Day); - Assert.AreEqual(now.Hour, ts2.Hour); + Assert.That(ts2.Year, Is.EqualTo(now.Year)); + Assert.That(ts2.Month, Is.EqualTo(now.Month)); + Assert.That(ts2.Day, Is.EqualTo(now.Day)); + Assert.That(ts2.Hour, Is.EqualTo(now.Hour)); // now we'll set some nulls and see how they are handled cmd = new MySqlCommand("UPDATE Test SET tm=?ts, dt=?dt WHERE id=1", Connection); cmd.Parameters.Add(new MySqlParameter("?ts", DBNull.Value)); cmd.Parameters.Add(new MySqlParameter("?dt", DBNull.Value)); cnt = cmd.ExecuteNonQuery(); - Assert.True(cnt == 1, "Update null count"); + Assert.That(cnt == 1, "Update null count"); cmd = new MySqlCommand("SELECT tm, dt FROM Test WHERE id=1", Connection); reader = cmd.ExecuteReader(); reader.Read(); object tso = reader.GetValue(0); object dto = reader.GetValue(1); - Assert.True(tso == DBNull.Value, "Time column"); - Assert.True(dto == DBNull.Value, "DateTime column"); + Assert.That(tso == DBNull.Value, "Time column"); + Assert.That(dto == DBNull.Value, "DateTime column"); reader.Close(); @@ -159,7 +159,7 @@ public void NestedQuoting() MySqlCommand cmd = new MySqlCommand("INSERT INTO Test (id, name) " + "VALUES(1, 'this is ?\"my value\"')", Connection); int count = cmd.ExecuteNonQuery(); - Assert.AreEqual(1, count); + Assert.That(count, Is.EqualTo(1)); } [Test] @@ -168,16 +168,16 @@ public void SetDbType() IDbCommand cmd = Connection.CreateCommand(); IDbDataParameter prm = cmd.CreateParameter(); prm.DbType = DbType.Int64; - Assert.AreEqual(DbType.Int64, prm.DbType); + Assert.That(prm.DbType, Is.EqualTo(DbType.Int64)); prm.Value = 3; - Assert.AreEqual(DbType.Int64, prm.DbType); + Assert.That(prm.DbType, Is.EqualTo(DbType.Int64)); MySqlParameter p = new MySqlParameter("name", MySqlDbType.Int64); - Assert.AreEqual(DbType.Int64, p.DbType); - Assert.AreEqual(MySqlDbType.Int64, p.MySqlDbType); + Assert.That(p.DbType, Is.EqualTo(DbType.Int64)); + Assert.That(p.MySqlDbType, Is.EqualTo(MySqlDbType.Int64)); p.Value = 3; - Assert.AreEqual(DbType.Int64, p.DbType); - Assert.AreEqual(MySqlDbType.Int64, p.MySqlDbType); + Assert.That(p.DbType, Is.EqualTo(DbType.Int64)); + Assert.That(p.MySqlDbType, Is.EqualTo(MySqlDbType.Int64)); } [Test] @@ -236,9 +236,9 @@ public void MemoryStreamAsParameterValue() using (MySqlDataReader reader = cmd.ExecuteReader()) { reader.Read(); - Assert.AreEqual("abcd", Convert.ToString(reader[0])); - Assert.AreEqual("efgh", Encoding.Default.GetString((byte[])reader[1])); - Assert.AreEqual("5678", Convert.ToString(reader[2])); + Assert.That(Convert.ToString(reader[0]), Is.EqualTo("abcd")); + Assert.That(Encoding.Default.GetString((byte[])reader[1]), Is.EqualTo("efgh")); + Assert.That(Convert.ToString(reader[2]), Is.EqualTo("5678")); } } } @@ -251,8 +251,8 @@ public void ParameterClone2() { var param = new MySqlParameter("@param", MySqlDbType.MediumText); var clone = param.Clone(); - Assert.AreEqual(MySqlDbType.MediumText, param.MySqlDbType); // Prints "MediumText" - Assert.AreEqual(MySqlDbType.MediumText, clone.MySqlDbType); // Prints "VarChar" + Assert.That(param.MySqlDbType, Is.EqualTo(MySqlDbType.MediumText)); // Prints "MediumText" + Assert.That(clone.MySqlDbType, Is.EqualTo(MySqlDbType.MediumText)); // Prints "VarChar" } @@ -279,17 +279,17 @@ public void ParameterClone() var clonedparam = param.Clone(); - Assert.AreEqual(DbType.Int32, clonedparam.DbType); - Assert.AreEqual(ParameterDirection.Output, clonedparam.Direction); - Assert.AreEqual(System.Text.Encoding.UTF8, clonedparam.Encoding); - Assert.IsTrue(clonedparam.IsNullable); - Assert.AreEqual(MySqlDbType.Int32, clonedparam.MySqlDbType); - Assert.AreEqual("test", clonedparam.ParameterName); - Assert.AreEqual((byte)3, clonedparam.Precision); - Assert.AreEqual((byte)2, clonedparam.Scale); - Assert.AreEqual(1, clonedparam.Size); - Assert.IsTrue(clonedparam.SourceColumnNullMapping); - Assert.AreEqual(1, clonedparam.Value); + Assert.That(clonedparam.DbType, Is.EqualTo(DbType.Int32)); + Assert.That(clonedparam.Direction, Is.EqualTo(ParameterDirection.Output)); + Assert.That(clonedparam.Encoding, Is.EqualTo(System.Text.Encoding.UTF8)); + Assert.That(clonedparam.IsNullable); + Assert.That(clonedparam.MySqlDbType, Is.EqualTo(MySqlDbType.Int32)); + Assert.That(clonedparam.ParameterName, Is.EqualTo("test")); + Assert.That(clonedparam.Precision, Is.EqualTo((byte)3)); + Assert.That(clonedparam.Scale, Is.EqualTo((byte)2)); + Assert.That(clonedparam.Size, Is.EqualTo(1)); + Assert.That(clonedparam.SourceColumnNullMapping); + Assert.That(clonedparam.Value, Is.EqualTo(1)); } /// @@ -311,7 +311,7 @@ public void ParameterDirectionOutputTextCommand(bool preparedCommand) if (preparedCommand) cmd.Prepare(); cmd.ExecuteNonQuery(); - Assert.AreEqual(1234, cmd.Parameters["@outputParam"].Value); + Assert.That(cmd.Parameters["@outputParam"].Value, Is.EqualTo(1234)); } } @@ -338,10 +338,10 @@ public void AllowUnnamedParameters() cmd.ExecuteNonQuery(); cmd.CommandText = "SELECT id FROM Test"; - Assert.AreEqual(1, cmd.ExecuteScalar()); + Assert.That(cmd.ExecuteScalar(), Is.EqualTo(1)); cmd.CommandText = "SELECT name FROM Test"; - Assert.AreEqual("test", cmd.ExecuteScalar()); + Assert.That(cmd.ExecuteScalar(), Is.EqualTo("test")); } [Test] @@ -355,7 +355,7 @@ public void NullParameterValue() cmd.CommandText = "SELECT name FROM Test WHERE id=1"; object name = cmd.ExecuteScalar(); - Assert.AreEqual(DBNull.Value, name); + Assert.That(name, Is.EqualTo(DBNull.Value)); } /// @@ -369,7 +369,7 @@ public void DefaultType() p.ParameterName = "?boo"; p.Value = "test"; MySqlParameter mp = (MySqlParameter)p; - Assert.AreEqual(MySqlDbType.VarChar, mp.MySqlDbType); + Assert.That(mp.MySqlDbType, Is.EqualTo(MySqlDbType.VarChar)); } [Test] @@ -393,15 +393,15 @@ public void OddCharsInParameterNames() cmd.CommandText = "SELECT name FROM Test WHERE id=1"; object name = cmd.ExecuteScalar(); - Assert.AreEqual("Test", name); + Assert.That(name, Is.EqualTo("Test")); cmd.CommandText = "SELECT name FROM Test WHERE id=2"; name = cmd.ExecuteScalar(); - Assert.AreEqual("Test2", name); + Assert.That(name, Is.EqualTo("Test2")); cmd.CommandText = "SELECT name FROM Test WHERE id=3"; name = cmd.ExecuteScalar(); - Assert.AreEqual("Test3", name); + Assert.That(name, Is.EqualTo("Test3")); } /// @@ -429,10 +429,10 @@ public void UnTypedParameterBeingReused() using (MySqlDataReader reader = cmd.ExecuteReader()) { reader.Read(); - Assert.True(reader.IsDBNull(2)); + Assert.That(reader.IsDBNull(2)); reader.Read(); - Assert.False(reader.IsDBNull(2)); - Assert.False(reader.Read()); + Assert.That(reader.IsDBNull(2), Is.False); + Assert.That(reader.Read(), Is.False); } } @@ -461,19 +461,19 @@ public void WithAndWithoutMarker() MySqlCommand cmd = new MySqlCommand("INSERT INTO Test (id, name) VALUES (?id, ?name)", Connection); cmd.Parameters.AddWithValue("id", 1); - Assert.AreEqual(-1, cmd.Parameters.IndexOf("?id")); + Assert.That(cmd.Parameters.IndexOf("?id"), Is.EqualTo(-1)); cmd.Parameters.AddWithValue("name", "test"); cmd.ExecuteNonQuery(); cmd.Parameters.Clear(); cmd.Parameters.AddWithValue("?id", 2); - Assert.AreEqual(-1, cmd.Parameters.IndexOf("id")); + Assert.That(cmd.Parameters.IndexOf("id"), Is.EqualTo(-1)); cmd.Parameters.AddWithValue("?name", "test2"); cmd.ExecuteNonQuery(); cmd.CommandText = "SELECT COUNT(*) FROM Test"; object count = cmd.ExecuteScalar(); - Assert.AreEqual(2, Convert.ToInt32(count)); + Assert.That(Convert.ToInt32(count), Is.EqualTo(2)); } [Test] @@ -482,11 +482,11 @@ public void DoubleAddingParameters() ExecuteSQL("CREATE TABLE Test (id INT NOT NULL, name VARCHAR(100), dt DATETIME, tm TIME, ts TIMESTAMP, PRIMARY KEY(id))"); MySqlCommand cmd = new MySqlCommand("INSERT INTO Test (id, name) VALUES (?id, ?name)", Connection); cmd.Parameters.AddWithValue("id", 1); - Assert.AreEqual(-1, cmd.Parameters.IndexOf("?id")); - Assert.AreEqual(-1, cmd.Parameters.IndexOf("@id")); + Assert.That(cmd.Parameters.IndexOf("?id"), Is.EqualTo(-1)); + Assert.That(cmd.Parameters.IndexOf("@id"), Is.EqualTo(-1)); cmd.Parameters.AddWithValue("name", "test"); Exception ex = Assert.Throws(() => cmd.Parameters.AddWithValue("?id", 2)); - Assert.AreEqual("Parameter '?id' has already been defined.", ex.Message); + Assert.That(ex.Message, Is.EqualTo("Parameter '?id' has already been defined.")); } /// @@ -519,7 +519,7 @@ public void AddingParametersUsingInsert() MySqlCommand cmd = new MySqlCommand(); cmd.Parameters.Insert(0, new MySqlParameter("?id", MySqlDbType.Int32)); MySqlParameter p = cmd.Parameters["?id"]; - Assert.AreEqual("?id", p.ParameterName); + Assert.That(p.ParameterName, Is.EqualTo("?id")); } /// @@ -538,7 +538,7 @@ public void FindParameterAfterRemoval() cmd.Parameters.Add("?id6", MySqlDbType.Int32); cmd.Parameters.RemoveAt("?id1"); MySqlParameter p = cmd.Parameters["?id6"]; - Assert.AreEqual("?id6", p.ParameterName); + Assert.That(p.ParameterName, Is.EqualTo("?id6")); } /// @@ -576,7 +576,7 @@ public void StringParameterSizeSetAfterValue() MySqlDataAdapter da = new MySqlDataAdapter("SELECT * FROM Test", Connection); DataTable dt = new DataTable(); da.Fill(dt); - Assert.AreEqual("123", dt.Rows[0][0]); + Assert.That(dt.Rows[0][0], Is.EqualTo("123")); cmd.Parameters.Clear(); cmd.Parameters.Add("?p1", MySqlDbType.VarChar); @@ -586,7 +586,7 @@ public void StringParameterSizeSetAfterValue() dt.Clear(); da.Fill(dt); - Assert.AreEqual("1234567890", dt.Rows[1][0]); + Assert.That(dt.Rows[1][0], Is.EqualTo("1234567890")); } /// @@ -597,11 +597,11 @@ public void NonInputParametersToCtor() { MySqlParameter p = new MySqlParameter("?p1", MySqlDbType.VarChar, 20, ParameterDirection.InputOutput, true, 0, 0, "id", DataRowVersion.Current, 0); - Assert.AreEqual(ParameterDirection.InputOutput, p.Direction); + Assert.That(p.Direction, Is.EqualTo(ParameterDirection.InputOutput)); MySqlParameter p1 = new MySqlParameter("?p1", MySqlDbType.VarChar, 20, ParameterDirection.Output, true, 0, 0, "id", DataRowVersion.Current, 0); - Assert.AreEqual(ParameterDirection.Output, p1.Direction); + Assert.That(p1.Direction, Is.EqualTo(ParameterDirection.Output)); } [Test] @@ -618,8 +618,8 @@ public void UseAtSignForParameters() using (MySqlDataReader reader = cmd.ExecuteReader()) { reader.Read(); - Assert.AreEqual(33, reader.GetInt32(0)); - Assert.AreEqual("Test", reader.GetString(1)); + Assert.That(reader.GetInt32(0), Is.EqualTo(33)); + Assert.That(reader.GetString(1), Is.EqualTo("Test")); } } @@ -634,7 +634,7 @@ public void CanCreateMySQLParameterWithNullability() MySqlParameter p = new MySqlParameter("?id", MySqlDbType.Decimal, 2, ParameterDirection.Input, true, 1, 1, "sourceColumn", DataRowVersion.Default, 1); - Assert.True(p.IsNullable); + Assert.That(p.IsNullable); } /// @@ -647,7 +647,7 @@ public void CanCreateMySQLParameterWithPrecision() MySqlParameter p = new MySqlParameter("?id", MySqlDbType.Decimal, 2, ParameterDirection.Input, true, Byte.MaxValue, 1, "sourceColumn", DataRowVersion.Default, 1); - Assert.AreEqual(p.Precision, Byte.MaxValue); + Assert.That(Byte.MaxValue, Is.EqualTo(p.Precision)); } @@ -662,7 +662,7 @@ public void CanCreateMySQLParameterWithScale() MySqlParameter p = new MySqlParameter("?id", MySqlDbType.Decimal, 2, ParameterDirection.Input, true, 1, Byte.MaxValue, "sourceColumn", DataRowVersion.Default, 1); - Assert.AreEqual(p.Scale, Byte.MaxValue); + Assert.That(Byte.MaxValue, Is.EqualTo(p.Scale)); } /// @@ -680,10 +680,10 @@ public void CanIdentifyParameterWithOutName() cmd.ExecuteNonQuery(); cmd.CommandText = "SELECT id FROM Test"; - Assert.AreEqual(1, cmd.ExecuteScalar()); + Assert.That(cmd.ExecuteScalar(), Is.EqualTo(1)); cmd.CommandText = "SELECT name FROM Test"; - Assert.AreEqual("test", cmd.ExecuteScalar()); + Assert.That(cmd.ExecuteScalar(), Is.EqualTo("test")); } /// @@ -696,7 +696,7 @@ public void CanThrowAnExceptionWhenMixingParameterNaming() cmd.Parameters.AddWithValue("?Id", 1); cmd.Parameters.AddWithValue("?name", "test"); Exception ex = Assert.Throws(() => cmd.ExecuteNonQuery()); - Assert.AreEqual("Fatal error encountered during command execution.", ex.Message); + Assert.That(ex.Message, Is.EqualTo("Fatal error encountered during command execution.")); } /// @@ -718,7 +718,7 @@ public void TreatTinyAsBooleanWhenNull() while (reader.Read()) { if (!(reader["testcol"] is DBNull)) - Assert.True(reader["testcol"] is bool); + Assert.That(reader["testcol"] is bool); } } } @@ -750,7 +750,7 @@ public void TreatTinyAsBooleanWhenCallingPrepare() using (var reader = cmd.ExecuteReader(CommandBehavior.SingleRow)) { reader.Read(); - Assert.False(reader["test_val"] is bool); + Assert.That(reader["test_val"] is bool, Is.False); } } @@ -769,7 +769,7 @@ public void TreatTinyAsBooleanWhenCallingPrepare() using (var reader = cmd.ExecuteReader(CommandBehavior.SingleRow)) { reader.Read(); - Assert.True(reader["test_val"] is bool); + Assert.That(reader["test_val"] is bool); } } @@ -790,7 +790,7 @@ public void ZeroParameterAsNull() var query = "SELECT * FROM audit t1 WHERE t1.Permanent = ?IsFalse"; MySqlParameter[] parameters = { new MySqlParameter() { ParameterName = "IsFalse", Value = 0 } }; var ds = MySqlHelper.ExecuteDataset(Connection.ConnectionString, query, parameters); - Assert.AreEqual(ds.Tables[0].Rows.Count, 1); + Assert.That(1, Is.EqualTo(ds.Tables[0].Rows.Count)); } /// @@ -813,7 +813,7 @@ public void DefaultNullValue() { while (reader.Read()) { - Assert.IsTrue(reader.IsDBNull(0)); + Assert.That(reader.IsDBNull(0)); } } } @@ -851,7 +851,7 @@ public void CastingEnum(Enum name, string typeName) MySqlCommand command = new MySqlCommand(sql, conn); command.Parameters.AddWithValue("@ID", name); MySqlDataReader rdr = command.ExecuteReader(); - Assert.IsNotNull(rdr); + Assert.That(rdr, Is.Not.Null); } } @@ -869,16 +869,16 @@ public void InvalidParameterIndex() cmd.Parameters.Insert(1, new MySqlParameter("test1", "test1")); cmd.Parameters.Insert(0, new MySqlParameter("testNew0", "test2")); - Assert.True(cmd.Parameters.IndexOf("testNew0") == 0); - Assert.True(cmd.Parameters.IndexOf("test0") == 1); - Assert.True(cmd.Parameters.IndexOf("test1") == 2); + Assert.That(cmd.Parameters.IndexOf("testNew0") == 0); + Assert.That(cmd.Parameters.IndexOf("test0") == 1); + Assert.That(cmd.Parameters.IndexOf("test1") == 2); cmd.Parameters.AddWithValue("", "test3"); - Assert.True(cmd.Parameters.Count == 4); - Assert.True(cmd.Parameters.IndexOf("Parameter4") == 3); + Assert.That(cmd.Parameters.Count == 4); + Assert.That(cmd.Parameters.IndexOf("Parameter4") == 3); cmd.Parameters.Insert(1, new MySqlParameter("lastTest", "test4")); - Assert.True(cmd.Parameters.IndexOf("lastTest") == 1); + Assert.That(cmd.Parameters.IndexOf("lastTest") == 1); } /// @@ -905,8 +905,8 @@ public void InsertValueAfterNull() dt.Clear(); da.Fill(dt); - Assert.AreEqual(2, dt.Rows.Count); - Assert.AreEqual(2, dt.Rows[1]["foo"]); + Assert.That(dt.Rows.Count, Is.EqualTo(2)); + Assert.That(dt.Rows[1]["foo"], Is.EqualTo(2)); } /// @@ -926,15 +926,15 @@ public void CloneParameterAssignSourceColumnNullMapping() dataAdapter.Fill(dataTable); using (var cmd = new MySqlCommand(query, Connection)) - Assert.AreEqual(1, cmd.ExecuteScalar()); - Assert.AreEqual(1, dataTable.Rows.Count); + Assert.That(cmd.ExecuteScalar(), Is.EqualTo(1)); + Assert.That(dataTable.Rows.Count, Is.EqualTo(1)); dataTable.Rows[0].Delete(); dataAdapter.Update(dataTable); using (var cmd = new MySqlCommand(query, Connection)) - Assert.IsNull(cmd.ExecuteScalar()); - Assert.AreEqual(0, dataTable.Rows.Count); + Assert.That(cmd.ExecuteScalar(), Is.Null); + Assert.That(dataTable.Rows.Count, Is.EqualTo(0)); } /// @@ -948,10 +948,10 @@ public void InitializeParameter() var newParam = cmd.CreateParameter(); var newIntParam = new MySqlParameter("newIntParam", 3); - Assert.AreEqual(MySqlDbType.VarChar, newParam.MySqlDbType); - Assert.AreEqual(DbType.String, newParam.DbType); - Assert.AreEqual(MySqlDbType.Int32, newIntParam.MySqlDbType); - Assert.AreEqual(DbType.Int32, newIntParam.DbType); + Assert.That(newParam.MySqlDbType, Is.EqualTo(MySqlDbType.VarChar)); + Assert.That(newParam.DbType, Is.EqualTo(DbType.String)); + Assert.That(newIntParam.MySqlDbType, Is.EqualTo(MySqlDbType.Int32)); + Assert.That(newIntParam.DbType, Is.EqualTo(DbType.Int32)); } /// @@ -988,8 +988,8 @@ public void AddObjectPerformance() sw2.Stop(); Console.Write(sw2.Elapsed); - Assert.True(sw1.Elapsed.TotalSeconds < 1); - Assert.True(sw2.Elapsed.TotalSeconds < 1); + Assert.That(sw1.Elapsed.TotalSeconds < 1); + Assert.That(sw2.Elapsed.TotalSeconds < 1); } } } diff --git a/MySQL.Data/tests/MySql.Data.Tests/PoolingTests.cs b/MySQL.Data/tests/MySql.Data.Tests/PoolingTests.cs index 5ad5212e1..5e502aed6 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/PoolingTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/PoolingTests.cs @@ -59,7 +59,7 @@ public void BasicConnection() { c = new MySqlConnection(Settings.ConnectionString); c.Open(); - Assert.AreEqual(serverThread, c.ServerThread); + Assert.That(c.ServerThread, Is.EqualTo(serverThread)); c.Close(); } @@ -81,7 +81,7 @@ public void BasicConnection() for (int j = 0; j < connArray.Length; j++) { if (i != j) - Assert.True(connArray[i].ServerThread != connArray[j].ServerThread); + Assert.That(connArray[i].ServerThread != connArray[j].ServerThread); } } @@ -110,7 +110,7 @@ public void OpenKilled() int secondThreadId = c.ServerThread; KillConnection(c); c.Close(); - Assert.False(threadId == secondThreadId); + Assert.That(threadId == secondThreadId, Is.False); } [Test] @@ -126,7 +126,7 @@ public void ReclaimBrokenConnection() // now attempting to open a connection should fail MySqlConnection c2 = new MySqlConnection(connStr); Exception ex = Assert.Throws(() => c2.Open()); - StringAssert.Contains("error connecting: Timeout expired. The timeout period elapsed prior to obtaining a connection from the pool.", ex.Message); + Assert.That(ex.Message, Does.Contain("error connecting: Timeout expired. The timeout period elapsed prior to obtaining a connection from the pool.")); // we now kill the first connection to simulate a server stoppage KillConnection(c); @@ -134,7 +134,7 @@ public void ReclaimBrokenConnection() // now we do something on the first connection ex = Assert.Throws(() => c.ChangeDatabase("mysql")); - StringAssert.Contains("The connection is not open.", ex.Message); + Assert.That(ex.Message, Does.Contain("The connection is not open.")); // Opening a connection now should work MySqlConnection connection = new MySqlConnection(connStr); @@ -155,12 +155,12 @@ public void TestUserReset() cmd.CommandText = "SELECT @testvar"; object var = cmd.ExecuteScalar(); - Assert.AreEqual("5", var); + Assert.That(var, Is.EqualTo("5")); c.Close(); c.Open(); object var2 = cmd.ExecuteScalar(); - Assert.AreEqual(DBNull.Value, var2); + Assert.That(var2, Is.EqualTo(DBNull.Value)); KillConnection(c); } } @@ -182,7 +182,7 @@ public void TestAbort() using (MySqlConnection c1 = new MySqlConnection(connStr)) { c1.Open(); - Assert.True(c1.ServerThread != threadId); + Assert.That(c1.ServerThread != threadId); KillConnection(c1); } } @@ -211,7 +211,7 @@ public void UTF8AfterClosing() cmd = new MySqlCommand("SELECT value FROM test WHERE id = 1", con); string firstS = cmd.ExecuteScalar().ToString(); - Assert.AreEqual(originalValue, firstS); + Assert.That(firstS, Is.EqualTo(originalValue)); con.Close(); con.Open(); @@ -222,7 +222,7 @@ public void UTF8AfterClosing() KillConnection(con); con.Close(); - Assert.AreEqual(firstS, secondS); + Assert.That(secondS, Is.EqualTo(firstS)); } } @@ -285,7 +285,7 @@ public void NewTest() if (recdr.Read()) { int x = recdr.GetOrdinal("name"); - Assert.AreEqual(1, x); + Assert.That(x, Is.EqualTo(1)); } } } @@ -465,7 +465,7 @@ public void TestBadConnections() using (MySqlConnection connection = new MySqlConnection(builder.ConnectionString)) { Exception ex = Assert.Throws(() => connection.Open()); - if (Platform.IsWindows()) Assert.True(ex.InnerException.GetType() == typeof(ArgumentException)); + if (Platform.IsWindows()) Assert.That(ex.InnerException.GetType() == typeof(ArgumentException)); } Thread.Sleep(50); } @@ -558,7 +558,7 @@ private void CacheServerPropertiesInternal(bool cache) KillConnection(c); } int count = listener.CountLinesContaining("SHOW VARIABLES"); - Assert.AreEqual(cache ? 1 : 2, count); + Assert.That(count, Is.EqualTo(cache ? 1 : 2)); } [Test] @@ -588,7 +588,7 @@ public void CacheServerPropertiesCausePacketTooLarge() c1.Open(); MySqlCommand cmd = new MySqlCommand("SELECT Count(*) from test", c1); var count = cmd.ExecuteScalar(); - Assert.AreEqual(3, Convert.ToInt32(count)); + Assert.That(Convert.ToInt32(count), Is.EqualTo(3)); } ExecuteSQL("DROP TABLE test "); @@ -626,13 +626,13 @@ public void MultipleConnectionWithPooling() // Get a connection out of the pool. myConnection1.Open(); - Assert.AreEqual(ConnectionState.Open, myConnection1.State); + Assert.That(myConnection1.State, Is.EqualTo(ConnectionState.Open)); // Get a second connection out of the pool. myConnection2.Open(); - Assert.AreEqual(ConnectionState.Open, myConnection2.State); + Assert.That(myConnection2.State, Is.EqualTo(ConnectionState.Open)); // Open a third connection. myConnection3.Open(); - Assert.AreEqual(ConnectionState.Open, myConnection3.State); + Assert.That(myConnection3.State, Is.EqualTo(ConnectionState.Open)); // Return the all connections to the pool. myConnection1.Close(); myConnection2.Close(); @@ -644,7 +644,7 @@ public void MultipleConnectionWithPooling() myConnection3.Open(); myConnection4.Open(); Exception ex = Assert.Throws(() => myConnection5.Open()); - StringAssert.Contains("Timeout", ex.Message); + Assert.That(ex.Message, Does.Contain("Timeout")); myConnection1.Close(); myConnection2.Close(); @@ -677,7 +677,7 @@ public void CloseWaitScenario1() var tcpConnections = ipProperties.GetActiveTcpConnections(); foreach (var info in tcpConnections) if (info.LocalEndPoint.Address.ToString() == "127.0.0.1" && info.LocalEndPoint.Port.ToString() == Port.ToString()) - Assert.True(info.State.ToString() != "CLOSE_WAIT"); + Assert.That(info.State.ToString() != "CLOSE_WAIT"); } foreach (var item in connectionList) { diff --git a/MySQL.Data/tests/MySql.Data.Tests/PreparedStatements.cs b/MySQL.Data/tests/MySql.Data.Tests/PreparedStatements.cs index 9c0e94a3f..226e5abcb 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/PreparedStatements.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/PreparedStatements.cs @@ -55,11 +55,11 @@ public void Simple() cmd.Prepare(); using (MySqlDataReader reader = cmd.ExecuteReader()) { - Assert.True(reader.Read()); - Assert.AreEqual(1, reader.GetInt32(0)); - Assert.AreEqual((decimal)345.12, reader.GetDecimal(1)); - Assert.AreEqual("abcd", reader.GetString(2)); - Assert.AreEqual(2019, reader.GetInt16(3)); + Assert.That(reader.Read()); + Assert.That(reader.GetInt32(0), Is.EqualTo(1)); + Assert.That(reader.GetDecimal(1), Is.EqualTo((decimal)345.12)); + Assert.That(reader.GetString(2), Is.EqualTo("abcd")); + Assert.That(reader.GetInt16(3), Is.EqualTo(2019)); } } @@ -89,8 +89,8 @@ public void SimplePrepareBeforeParms() { // Fetch the first record reader.Read(); - Assert.AreEqual(1, reader.GetInt32(0)); - Assert.AreEqual(2, reader.GetInt32(1)); + Assert.That(reader.GetInt32(0), Is.EqualTo(1)); + Assert.That(reader.GetInt32(1), Is.EqualTo(2)); } } @@ -120,7 +120,7 @@ public void DateAndTimes() cmd.Parameters.AddWithValue("?tm", timeSp); cmd.Prepare(); int count = cmd.ExecuteNonQuery(); - Assert.True(count == 1, "Records affected by insert"); + Assert.That(count == 1, "Records affected by insert"); cmd.CommandText = "SELECT * FROM Test"; cmd.Prepare(); @@ -128,21 +128,21 @@ public void DateAndTimes() using (MySqlDataReader reader = cmd.ExecuteReader()) { reader.Read(); - Assert.True(reader.GetInt32(0) == 1, "Id column"); - Assert.True(dt.Date == reader.GetDateTime(1).Date, "Date column"); + Assert.That(reader.GetInt32(0) == 1, "Id column"); + Assert.That(dt.Date == reader.GetDateTime(1).Date, "Date column"); DateTime dt2 = reader.GetDateTime(2); - Assert.AreEqual(dt.Date, dt2.Date); - Assert.AreEqual(dt.Hour, dt2.Hour); - Assert.AreEqual(dt.Minute, dt2.Minute); - Assert.AreEqual(dt.Second, dt2.Second); + Assert.That(dt2.Date, Is.EqualTo(dt.Date)); + Assert.That(dt2.Hour, Is.EqualTo(dt.Hour)); + Assert.That(dt2.Minute, Is.EqualTo(dt.Minute)); + Assert.That(dt2.Second, Is.EqualTo(dt.Second)); TimeSpan ts2 = reader.GetTimeSpan(3); - Assert.AreEqual(timeSp.Days, ts2.Days); - Assert.AreEqual(timeSp.Hours, ts2.Hours); - Assert.AreEqual(timeSp.Minutes, ts2.Minutes); - Assert.AreEqual(timeSp.Seconds, ts2.Seconds); - Assert.True(dt.Date == reader.GetDateTime(4).Date, "Timestamp column"); + Assert.That(ts2.Days, Is.EqualTo(timeSp.Days)); + Assert.That(ts2.Hours, Is.EqualTo(timeSp.Hours)); + Assert.That(ts2.Minutes, Is.EqualTo(timeSp.Minutes)); + Assert.That(ts2.Seconds, Is.EqualTo(timeSp.Seconds)); + Assert.That(dt.Date == reader.GetDateTime(4).Date, "Timestamp column"); } } @@ -155,12 +155,12 @@ public void ResetCommandText() MySqlCommand cmd = new MySqlCommand("SELECT id FROM Test", Connection); cmd.Prepare(); object o = cmd.ExecuteScalar(); - Assert.AreEqual(1, o); + Assert.That(o, Is.EqualTo(1)); cmd.CommandText = "SELECT name FROM Test"; cmd.Prepare(); o = cmd.ExecuteScalar(); - Assert.AreEqual("Test", o); + Assert.That(o, Is.EqualTo("Test")); } @@ -199,7 +199,7 @@ public void DifferentParameterOrder() cmd.Parameters.Add(name); cmd.Parameters.Add(id3); cmd.Prepare(); - Assert.AreEqual(1, cmd.ExecuteNonQuery()); + Assert.That(cmd.ExecuteNonQuery(), Is.EqualTo(1)); cmd.Parameters.Clear(); @@ -211,13 +211,13 @@ public void DifferentParameterOrder() cmd.Parameters.Add(name); cmd.Prepare(); - Assert.AreEqual(1, cmd.ExecuteNonQuery()); + Assert.That(cmd.ExecuteNonQuery(), Is.EqualTo(1)); cmd.CommandText = "SELECT id3 FROM Test WHERE id=1"; - Assert.AreEqual(3, cmd.ExecuteScalar()); + Assert.That(cmd.ExecuteScalar(), Is.EqualTo(3)); cmd.CommandText = "SELECT name FROM Test WHERE id=2"; - Assert.AreEqual(DBNull.Value, cmd.ExecuteScalar()); + Assert.That(cmd.ExecuteScalar(), Is.EqualTo(DBNull.Value)); } [Test] @@ -235,20 +235,20 @@ public void Blobs() cmd.Parameters.AddWithValue("?text1", inStr); cmd.Prepare(); int count = cmd.ExecuteNonQuery(); - Assert.AreEqual(1, count); + Assert.That(count, Is.EqualTo(1)); cmd.CommandText = "SELECT * FROM Test"; cmd.Prepare(); using (MySqlDataReader reader = cmd.ExecuteReader()) { - Assert.True(reader.Read()); - Assert.AreEqual(1, reader.GetInt32(0)); - Assert.AreEqual(bytes.Length, reader.GetBytes(1, 0, null, 0, 0)); + Assert.That(reader.Read()); + Assert.That(reader.GetInt32(0), Is.EqualTo(1)); + Assert.That(reader.GetBytes(1, 0, null, 0, 0), Is.EqualTo(bytes.Length)); byte[] outBytes = new byte[bytes.Length]; reader.GetBytes(1, 0, outBytes, 0, bytes.Length); for (int x = 0; x < bytes.Length; x++) - Assert.AreEqual(bytes[x], outBytes[x]); - Assert.AreEqual(inStr, reader.GetString(2)); + Assert.That(outBytes[x], Is.EqualTo(bytes[x])); + Assert.That(reader.GetString(2), Is.EqualTo(inStr)); } } @@ -268,13 +268,13 @@ public void SimpleTest2() // Fetch the first record reader.Read(); - Assert.AreEqual(1, reader.GetInt32(0)); - Assert.AreEqual(2, reader.GetInt32(1)); - Assert.AreEqual(3, reader.GetInt32(2)); - Assert.AreEqual(4, reader.GetInt32(3)); - Assert.AreEqual(5, reader.GetInt32(4)); - Assert.AreEqual(6, reader.GetInt32(5)); - Assert.AreEqual(7, reader.GetInt32(6)); + Assert.That(reader.GetInt32(0), Is.EqualTo(1)); + Assert.That(reader.GetInt32(1), Is.EqualTo(2)); + Assert.That(reader.GetInt32(2), Is.EqualTo(3)); + Assert.That(reader.GetInt32(3), Is.EqualTo(4)); + Assert.That(reader.GetInt32(4), Is.EqualTo(5)); + Assert.That(reader.GetInt32(5), Is.EqualTo(6)); + Assert.That(reader.GetInt32(6), Is.EqualTo(7)); } } @@ -314,23 +314,23 @@ public void Bug6271() cmd.Parameters.AddWithValue("?dt", dt); cmd.Prepare(); int count = cmd.ExecuteNonQuery(); - Assert.AreEqual(1, count); + Assert.That(count, Is.EqualTo(1)); cmd.CommandText = "SELECT * FROM Test2"; using (MySqlDataReader reader = cmd.ExecuteReader()) { - Assert.True(reader.Read()); - Assert.AreEqual("Ceci est un nom", reader.GetString(1)); - Assert.AreEqual(dt.ToString("G"), reader.GetDateTime(4).ToString("G")); - Assert.AreEqual("Ceci est une description facile à plantouiller", reader.GetString(2)); + Assert.That(reader.Read()); + Assert.That(reader.GetString(1), Is.EqualTo("Ceci est un nom")); + Assert.That(reader.GetDateTime(4).ToString("G"), Is.EqualTo(dt.ToString("G"))); + Assert.That(reader.GetString(2), Is.EqualTo("Ceci est une description facile à plantouiller")); long len = reader.GetBytes(3, 0, null, 0, 0); - Assert.AreEqual(xpDOSG_Avatar.Length, len); + Assert.That(len, Is.EqualTo(xpDOSG_Avatar.Length)); byte[] outBytes = new byte[len]; reader.GetBytes(3, 0, outBytes, 0, (int)len); for (int x = 0; x < xpDOSG_Avatar.Length; x++) - Assert.AreEqual(xpDOSG_Avatar[x], outBytes[x]); + Assert.That(outBytes[x], Is.EqualTo(xpDOSG_Avatar[x])); } } @@ -387,8 +387,7 @@ public void InsertAccentedCharacters() cmd.ExecuteNonQuery(); MySqlCommand cmd2 = new MySqlCommand("SELECT input FROM Test", conn2); - Assert.AreEqual("irache martínez@yahoo.es aol.com", - cmd2.ExecuteScalar()); + Assert.That(cmd2.ExecuteScalar(), Is.EqualTo("irache martínez@yahoo.es aol.com")); } } @@ -413,17 +412,17 @@ public void UsingParametersTwice() cmd.Parameters["?st"].Value = 1; cmd.Parameters["?sc"].Value = 42; int result = cmd.ExecuteNonQuery(); - Assert.AreEqual(1, result); + Assert.That(result, Is.EqualTo(1)); MySqlCommand cmd2 = new MySqlCommand("SELECT * FROM Test", Connection); using (var reader = cmd2.ExecuteReader()) { - Assert.True(reader.Read()); - Assert.AreEqual("test", reader.GetString("input")); - Assert.AreEqual(1, reader.GetValue(reader.GetOrdinal("state"))); - Assert.AreEqual(42, reader.GetValue(reader.GetOrdinal("score"))); + Assert.That(reader.Read()); + Assert.That(reader.GetString("input"), Is.EqualTo("test")); + Assert.That(reader.GetValue(reader.GetOrdinal("state")), Is.EqualTo(1)); + Assert.That(reader.GetValue(reader.GetOrdinal("score")), Is.EqualTo(42)); - Assert.False(reader.Read()); + Assert.That(reader.Read(), Is.False); } } @@ -470,7 +469,7 @@ public void MoreParametersOutOfOrder() cmd.Prepare(); int cnt = cmd.ExecuteNonQuery(); - Assert.AreEqual(1, cnt); + Assert.That(cnt, Is.EqualTo(1)); } /// @@ -494,11 +493,11 @@ public void ParameterLengths() MySqlCommand cmd2 = new MySqlCommand("SELECT * FROM Test", Connection); using (var reader = cmd2.ExecuteReader()) { - Assert.True(reader.Read()); - Assert.AreEqual(1, reader.GetValue(reader.GetOrdinal("id"))); - Assert.AreEqual("short string", reader.GetString("name")); + Assert.That(reader.Read()); + Assert.That(reader.GetValue(reader.GetOrdinal("id")), Is.EqualTo(1)); + Assert.That(reader.GetString("name"), Is.EqualTo("short string")); - Assert.False(reader.Read()); + Assert.That(reader.Read(), Is.False); } } @@ -525,22 +524,22 @@ public void UnsignedTinyInt() command.Parameters.AddWithValue("?id", (byte)127); command.Prepare(); int count = Convert.ToInt32(command.ExecuteScalar()); - Assert.AreEqual(1, count); + Assert.That(count, Is.EqualTo(1)); command.Parameters.Clear(); command.Parameters.AddWithValue("?id", (byte)128); count = Convert.ToInt32(command.ExecuteScalar()); - Assert.AreEqual(1, count); + Assert.That(count, Is.EqualTo(1)); command.Parameters.Clear(); command.Parameters.AddWithValue("?id", (byte)255); count = Convert.ToInt32(command.ExecuteScalar()); - Assert.AreEqual(1, count); + Assert.That(count, Is.EqualTo(1)); command.Parameters.Clear(); command.Parameters.AddWithValue("?id", "255"); count = Convert.ToInt32(command.ExecuteScalar()); - Assert.AreEqual(1, count); + Assert.That(count, Is.EqualTo(1)); } /// @@ -563,16 +562,16 @@ public void UnsignedValues() cmd.Parameters[1].Value = UInt32.MaxValue; cmd.Parameters[2].Value = 16777215; cmd.Parameters[3].Value = UInt16.MaxValue; - Assert.AreEqual(1, cmd.ExecuteNonQuery()); + Assert.That(cmd.ExecuteNonQuery(), Is.EqualTo(1)); cmd.CommandText = "SELECT * FROM Test"; cmd.CommandType = CommandType.Text; using (MySqlDataReader reader = cmd.ExecuteReader()) { reader.Read(); - Assert.AreEqual(UInt64.MaxValue, reader.GetUInt64(0)); - Assert.AreEqual(UInt32.MaxValue, reader.GetUInt32(1)); - Assert.AreEqual(16777215, Convert.ToInt32(reader.GetUInt32(2))); - Assert.AreEqual(UInt16.MaxValue, reader.GetUInt16(3)); + Assert.That(reader.GetUInt64(0), Is.EqualTo(UInt64.MaxValue)); + Assert.That(reader.GetUInt32(1), Is.EqualTo(UInt32.MaxValue)); + Assert.That(Convert.ToInt32(reader.GetUInt32(2)), Is.EqualTo(16777215)); + Assert.That(reader.GetUInt16(3), Is.EqualTo(UInt16.MaxValue)); } } @@ -608,7 +607,7 @@ PRIMARY KEY(`one`) cmd.Parameters.AddWithValue("@One", "test").MySqlDbType = MySqlDbType.VarChar; cmd.Prepare(); var result = cmd.ExecuteNonQuery(); - Assert.AreEqual(1, result); + Assert.That(result, Is.EqualTo(1)); } } @@ -621,7 +620,7 @@ public void PrepareEmptyString() MySqlCommand cmd = new MySqlCommand("", Connection); cmd.Prepare(); Exception ex = Assert.Throws(() => cmd.ExecuteNonQuery()); - Assert.AreEqual("The CommandText property has not been properly initialized.", ex.Message); + Assert.That(ex.Message, Is.EqualTo("The CommandText property has not been properly initialized.")); } /// @@ -640,7 +639,7 @@ public void CompoundStatements() cmd.Parameters.Add("?t1", MySqlDbType.Int32); cmd.Parameters.Add("?t2", MySqlDbType.Int32); Exception ex = Assert.Throws(() => cmd.Prepare()); - StringAssert.Contains("You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version", ex.Message); + Assert.That(ex.Message, Does.Contain("You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version")); } [Test] @@ -693,7 +692,7 @@ public void ClosingCommandsProperly() } } c.Ping(); - Assert.AreEqual(initialCount, GetPreparedStatementCount()); + Assert.That(GetPreparedStatementCount(), Is.EqualTo(initialCount)); } } @@ -723,13 +722,13 @@ public void InsertingUnsignedTinyInt() MySqlCommand cmd2 = new MySqlCommand("SELECT * FROM Test", Connection); using (var reader = cmd2.ExecuteReader()) { - Assert.True(reader.Read()); - Assert.AreEqual(127, Convert.ToInt32(reader.GetValue(0))); - Assert.AreEqual(1, Convert.ToInt32(reader.GetValue(1))); - Assert.AreEqual(2, Convert.ToInt32(reader.GetValue(2))); - Assert.AreEqual(3, Convert.ToInt32(reader.GetValue(3))); + Assert.That(reader.Read()); + Assert.That(Convert.ToInt32(reader.GetValue(0)), Is.EqualTo(127)); + Assert.That(Convert.ToInt32(reader.GetValue(1)), Is.EqualTo(1)); + Assert.That(Convert.ToInt32(reader.GetValue(2)), Is.EqualTo(2)); + Assert.That(Convert.ToInt32(reader.GetValue(3)), Is.EqualTo(3)); - Assert.False(reader.Read()); + Assert.That(reader.Read(), Is.False); } } @@ -784,7 +783,7 @@ internal void NegativeTime(bool prepared) { reader.Read(); TimeSpan t = reader.GetTimeSpan(1); - Assert.AreEqual(ts, t); + Assert.That(t, Is.EqualTo(ts)); } } } @@ -802,9 +801,9 @@ private void ReadNegativeTime(bool prepared) { reader.Read(); TimeSpan ts = reader.GetTimeSpan(1); - Assert.AreEqual(0, ts.Hours); - Assert.AreEqual(-10, ts.Minutes); - Assert.AreEqual(0, ts.Seconds); + Assert.That(ts.Hours, Is.EqualTo(0)); + Assert.That(ts.Minutes, Is.EqualTo(-10)); + Assert.That(ts.Seconds, Is.EqualTo(0)); } } @@ -825,12 +824,12 @@ public void ZeroTimePrepared() { reader.Read(); var t = reader.GetValue(0); - Assert.AreEqual("00:00:00", t.ToString()); + Assert.That(t.ToString(), Is.EqualTo("00:00:00")); TimeSpan timeSpan = reader.GetTimeSpan(0); - Assert.AreEqual(0, timeSpan.Hours); - Assert.AreEqual(0, timeSpan.Minutes); - Assert.AreEqual(0, timeSpan.Seconds); + Assert.That(timeSpan.Hours, Is.EqualTo(0)); + Assert.That(timeSpan.Minutes, Is.EqualTo(0)); + Assert.That(timeSpan.Seconds, Is.EqualTo(0)); } } @@ -847,17 +846,17 @@ public void SprocOutputParams() cmd.Prepare(); cmd.Parameters[0].Value = 20; - Assert.AreEqual(0, cmd.ExecuteNonQuery()); - Assert.AreEqual(20, cmd.Parameters[1].Value); + Assert.That(cmd.ExecuteNonQuery(), Is.EqualTo(0)); + Assert.That(cmd.Parameters[1].Value, Is.EqualTo(20)); ExecuteSQL("DROP PROCEDURE IF EXISTS spOutTest"); ExecuteSQL("CREATE PROCEDURE spOutTest(id INT, OUT age INT) BEGIN SET age=age*2; END"); cmd.Parameters[0].Value = 1; cmd.Parameters[1].Value = 20; - Assert.AreEqual(0, cmd.ExecuteNonQuery()); + Assert.That(cmd.ExecuteNonQuery(), Is.EqualTo(0)); - Assert.IsInstanceOf(cmd.Parameters[1].Value); + Assert.That(cmd.Parameters[1].Value, Is.InstanceOf()); } @@ -874,8 +873,8 @@ public void SprocInputOutputParams() cmd.Parameters[0].Value = 1; cmd.Parameters[1].Value = 20; - Assert.AreEqual(0, cmd.ExecuteNonQuery()); - Assert.AreEqual(40, cmd.Parameters[1].Value); + Assert.That(cmd.ExecuteNonQuery(), Is.EqualTo(0)); + Assert.That(cmd.Parameters[1].Value, Is.EqualTo(40)); } /// @@ -898,7 +897,7 @@ public void BigIntUnsigned() { rdr.Read(); UInt64 v = rdr.GetUInt64(0); - Assert.AreEqual(3000000000, v); + Assert.That(v, Is.EqualTo(3000000000)); } } @@ -924,7 +923,7 @@ public void InconsistentBehaviorForSelectLimit() int rows = 0; while (result.Read()) rows += 1; - Assert.AreEqual(3, rows); + Assert.That(rows, Is.EqualTo(3)); } } @@ -953,7 +952,7 @@ public void MySqlDbTypeEnumParameter() command.CommandText = "SELECT * FROM Test"; using var reader = command.ExecuteReader(); while (reader.Read()) - Assert.True(dataEnum.Contains(reader.GetString(0))); + Assert.That(dataEnum.Contains(reader.GetString(0))); } } } diff --git a/MySQL.Data/tests/MySql.Data.Tests/ScriptExecution.cs b/MySQL.Data/tests/MySql.Data.Tests/ScriptExecution.cs index b6d5b6f42..2baad18ac 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/ScriptExecution.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/ScriptExecution.cs @@ -58,19 +58,19 @@ public void ExecuteScriptWithProcedures() script.Connection = Connection; script.Delimiter = "$$"; int count = script.Execute(); - Assert.AreEqual(10, count); + Assert.That(count, Is.EqualTo(10)); MySqlCommand cmd = new MySqlCommand( String.Format(@"SELECT COUNT(*) FROM information_schema.routines WHERE routine_schema = '{0}' AND routine_name LIKE 'spTest1-%'", Connection.Database), Connection); - Assert.AreEqual(10, Convert.ToInt32(cmd.ExecuteScalar())); + Assert.That(Convert.ToInt32(cmd.ExecuteScalar()), Is.EqualTo(10)); } void ExecuteScriptWithProcedures_QueryExecuted(object sender, MySqlScriptEventArgs e) { string stmt = String.Format(statementTemplate1, statementCount++, null); - Assert.AreEqual(stmt, e.StatementText); + Assert.That(e.StatementText, Is.EqualTo(stmt)); } private string statementTemplate2 = @"INSERT INTO Test (id, name) VALUES ({0}, 'a "" na;me'){1}"; @@ -89,16 +89,16 @@ public void ExecuteScriptWithInserts() script.Connection = Connection; script.StatementExecuted += new MySqlStatementExecutedEventHandler(ExecuteScriptWithInserts_StatementExecuted); int count = script.Execute(); - Assert.AreEqual(10, count); + Assert.That(count, Is.EqualTo(10)); MySqlCommand cmd = new MySqlCommand("SELECT COUNT(*) FROM Test", Connection); - Assert.AreEqual(10, Convert.ToInt32(cmd.ExecuteScalar())); + Assert.That(Convert.ToInt32(cmd.ExecuteScalar()), Is.EqualTo(10)); } void ExecuteScriptWithInserts_StatementExecuted(object sender, MySqlScriptEventArgs e) { string stmt = String.Format(statementTemplate2, statementCount++, null); - Assert.AreEqual(stmt, e.StatementText); + Assert.That(e.StatementText, Is.EqualTo(stmt)); } [Test] @@ -116,11 +116,11 @@ public void ExecuteScriptContinueOnFailure() script.Connection = Connection; script.Error += new MySqlScriptErrorEventHandler(ExecuteScript_ContinueOnError); int count = script.Execute(); - Assert.AreEqual((int)10, count); - Assert.AreEqual((int)1, statementCount); + Assert.That(count, Is.EqualTo((int)10)); + Assert.That(statementCount, Is.EqualTo((int)1)); MySqlCommand cmd = new MySqlCommand("SELECT COUNT(*) FROM Test", Connection); - Assert.AreEqual(10, Convert.ToInt32(cmd.ExecuteScalar())); + Assert.That(Convert.ToInt32(cmd.ExecuteScalar()), Is.EqualTo(10)); } void ExecuteScript_ContinueOnError(object sender, MySqlScriptErrorEventArgs args) @@ -144,11 +144,11 @@ public void ExecuteScriptNotContinueOnFailure() script.Connection = Connection; script.Error += new MySqlScriptErrorEventHandler(ExecuteScript_NotContinueOnError); int count = script.Execute(); - Assert.AreEqual(5, count); - Assert.AreEqual(1, statementCount); + Assert.That(count, Is.EqualTo(5)); + Assert.That(statementCount, Is.EqualTo(1)); MySqlCommand cmd = new MySqlCommand("SELECT COUNT(*) FROM Test", Connection); - Assert.AreEqual(5, Convert.ToInt32(cmd.ExecuteScalar())); + Assert.That(Convert.ToInt32(cmd.ExecuteScalar()), Is.EqualTo(5)); } void ExecuteScript_NotContinueOnError(object sender, MySqlScriptErrorEventArgs args) @@ -170,7 +170,7 @@ public void ExecuteScriptWithUserVariables() MySqlScript script = new MySqlScript(scriptText); script.Connection = c; int count = script.Execute(); - Assert.AreEqual(1, count); + Assert.That(count, Is.EqualTo(1)); } } @@ -256,17 +256,17 @@ public async Task ExecuteScriptWithProceduresAsync() script.StatementExecuted += new MySqlStatementExecutedEventHandler(delegate(object sender, MySqlScriptEventArgs e) { string stmt = String.Format(spTpl, statementCount++, null); - Assert.AreEqual(stmt, e.StatementText); + Assert.That(e.StatementText, Is.EqualTo(stmt)); }); script.Connection = Connection; script.Delimiter = "$$"; int count = await script.ExecuteAsync(); - Assert.AreEqual(10, count); + Assert.That(count, Is.EqualTo(10)); MySqlCommand cmd = new MySqlCommand( String.Format(@"SELECT COUNT(*) FROM information_schema.routines WHERE routine_schema = '{0}' AND routine_name LIKE 'SEScriptWithProceduresAsyncSpTest%'", Connection.Database), Connection); - Assert.AreEqual(10, Convert.ToInt32(cmd.ExecuteScalar())); + Assert.That(Convert.ToInt32(cmd.ExecuteScalar()), Is.EqualTo(10)); } [Test] @@ -285,13 +285,13 @@ public async Task ExecuteScriptWithInsertsAsync() script.StatementExecuted += new MySqlStatementExecutedEventHandler(delegate(object sender, MySqlScriptEventArgs e) { string stmt = String.Format(queryTpl, statementCount++, null); - Assert.AreEqual(stmt, e.StatementText); + Assert.That(e.StatementText, Is.EqualTo(stmt)); }); int count = await script.ExecuteAsync(); - Assert.AreEqual(10, count); + Assert.That(count, Is.EqualTo(10)); MySqlCommand cmd = new MySqlCommand("SELECT COUNT(*) FROM SEScriptWithInsertsAsyncTest", Connection); - Assert.AreEqual(10, Convert.ToInt32(cmd.ExecuteScalar())); + Assert.That(Convert.ToInt32(cmd.ExecuteScalar()), Is.EqualTo(10)); } #endregion @@ -313,7 +313,7 @@ public void ScriptDelimiter() script.Query = sql; script.Delimiter = "??"; var count = script.Execute(); - Assert.AreEqual(3, count); + Assert.That(count, Is.EqualTo(3)); } } diff --git a/MySQL.Data/tests/MySql.Data.Tests/SimpleTransactions.cs b/MySQL.Data/tests/MySql.Data.Tests/SimpleTransactions.cs index bea676d27..b2719f841 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/SimpleTransactions.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/SimpleTransactions.cs @@ -49,11 +49,11 @@ public void TestReader() MySqlTransaction txn = Connection.BeginTransaction(); MySqlConnection c = txn.Connection; - Assert.AreEqual(Connection, c); + Assert.That(c, Is.EqualTo(Connection)); MySqlCommand cmd = new MySqlCommand("SELECT name, name2 FROM Test WHERE key2='P'", Connection, txn); MySqlTransaction t2 = cmd.Transaction; - Assert.AreEqual(txn, t2); + Assert.That(t2, Is.EqualTo(txn)); MySqlDataReader reader = null; try { @@ -63,7 +63,7 @@ public void TestReader() } catch (Exception ex) { - Assert.False(ex.Message != string.Empty, ex.Message); + Assert.That(ex.Message != string.Empty, Is.False, ex.Message); txn.Rollback(); } finally @@ -81,7 +81,7 @@ public void NestedTransactions() MySqlTransaction t1 = Connection.BeginTransaction(); Exception ex = Assert.Throws(() => { Connection.BeginTransaction(); }); - Assert.AreEqual("Nested transactions are not supported.", ex.Message); + Assert.That(ex.Message, Is.EqualTo("Nested transactions are not supported.")); t1.Rollback(); } @@ -99,7 +99,7 @@ public void BeginTransactionOnPreviouslyOpenConnection() } catch (Exception ex) { - Assert.AreEqual("The connection is not open.", ex.Message); + Assert.That(ex.Message, Is.EqualTo("The connection is not open.")); } } @@ -128,12 +128,12 @@ public void CommitAfterConnectionDead() //try //{ Exception ex = Assert.Throws(() => trans.Commit()); - Assert.AreEqual("Connection must be valid and open to commit transaction", ex.Message); + Assert.That(ex.Message, Is.EqualTo("Connection must be valid and open to commit transaction")); //} //catch (Exception) //{ //} - Assert.AreEqual(ConnectionState.Closed, c.State); + Assert.That(c.State, Is.EqualTo(ConnectionState.Closed)); c.Close(); // this should work even though we are closed } } @@ -155,7 +155,7 @@ public void DisposingCallsRollback() Type t = txn.GetType(); FieldInfo fi = t.GetField("open", BindingFlags.Instance | BindingFlags.NonPublic); bool isOpen = (bool)fi.GetValue(txn); - Assert.False(isOpen); + Assert.That(isOpen, Is.False); } [Test] @@ -197,7 +197,7 @@ public void TransactionScope() myTransaction.Rollback(); // to rollback actions cmdtoexec.CommandText = "select count(*) from transactiontable"; var count = cmdtoexec.ExecuteScalar(); - Assert.AreEqual(0,count); + Assert.That(count, Is.EqualTo(0)); } } diff --git a/MySQL.Data/tests/MySql.Data.Tests/SqlServerMode.cs b/MySQL.Data/tests/MySql.Data.Tests/SqlServerMode.cs index c3129f6bd..a6579225c 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/SqlServerMode.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/SqlServerMode.cs @@ -48,8 +48,8 @@ public void Simple() using (MySqlDataReader reader = cmd.ExecuteReader()) { reader.Read(); - Assert.AreEqual(1, reader.GetInt32(0)); - Assert.AreEqual("A", reader.GetString(1)); + Assert.That(reader.GetInt32(0), Is.EqualTo(1)); + Assert.That(reader.GetString(1), Is.EqualTo("A")); } } } diff --git a/MySQL.Data/tests/MySql.Data.Tests/SslTests.cs b/MySQL.Data/tests/MySql.Data.Tests/SslTests.cs index 5dce64220..713fb3a99 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/SslTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/SslTests.cs @@ -64,8 +64,8 @@ public void SslModePreferredByDefault() MySqlCommand command = new MySqlCommand("SHOW SESSION STATUS LIKE 'Ssl_version';", Connection); using (MySqlDataReader reader = command.ExecuteReader()) { - Assert.True(reader.Read()); - StringAssert.StartsWith("TLSv1", reader.GetString(1)); + Assert.That(reader.Read()); + Assert.That(reader.GetString(1), Does.StartWith("TLSv1")); } } @@ -83,8 +83,8 @@ public void SslModeOverriden() MySqlCommand command = new MySqlCommand("SHOW SESSION STATUS LIKE 'Ssl_version';", connection); using (MySqlDataReader reader = command.ExecuteReader()) { - Assert.True(reader.Read()); - Assert.AreEqual(string.Empty, reader.GetString(1)); + Assert.That(reader.Read()); + Assert.That(reader.GetString(1), Is.EqualTo(string.Empty)); } } } @@ -98,42 +98,42 @@ public void RepeatedSslConnectionOptions() var builder = new MySqlConnectionStringBuilder(Settings.ConnectionString); builder.SslCa = _sslCa; var conn = new MySqlConnection($"{builder.ConnectionString};sslca={repeatedOption}"); - Assert.AreEqual(repeatedOption, conn.Settings.SslCa); + Assert.That(conn.Settings.SslCa, Is.EqualTo(repeatedOption)); builder = new MySqlConnectionStringBuilder(Settings.ConnectionString); builder.CertificateFile = _sslCa; conn = new MySqlConnection($"{builder.ConnectionString};certificatefile={repeatedOption}"); - Assert.AreEqual(repeatedOption, conn.Settings.CertificateFile); + Assert.That(conn.Settings.CertificateFile, Is.EqualTo(repeatedOption)); builder = new MySqlConnectionStringBuilder(Settings.ConnectionString); builder.SslCa = _sslCa; conn = new MySqlConnection($"{builder.ConnectionString};certificatefile={repeatedOption}"); - Assert.AreEqual(repeatedOption, conn.Settings.CertificateFile); + Assert.That(conn.Settings.CertificateFile, Is.EqualTo(repeatedOption)); builder = new MySqlConnectionStringBuilder(Settings.ConnectionString); builder.CertificateFile = _sslCa; conn = new MySqlConnection($"{builder.ConnectionString};sslca={repeatedOption}"); - Assert.AreEqual(repeatedOption, conn.Settings.SslCa); + Assert.That(conn.Settings.SslCa, Is.EqualTo(repeatedOption)); builder = new MySqlConnectionStringBuilder(Settings.ConnectionString); builder.SslCa = _sslCa; conn = new MySqlConnection($"{builder.ConnectionString};sslcert={_sslCert};sslkey={_sslKey};sslca={repeatedOption}"); - Assert.AreEqual(repeatedOption, conn.Settings.SslCa); + Assert.That(conn.Settings.SslCa, Is.EqualTo(repeatedOption)); builder = new MySqlConnectionStringBuilder(Settings.ConnectionString); builder.CertificatePassword = "pass"; conn = new MySqlConnection($"{builder.ConnectionString};certificatepassword={repeatedOption}"); - Assert.AreEqual(repeatedOption, conn.Settings.CertificatePassword); + Assert.That(conn.Settings.CertificatePassword, Is.EqualTo(repeatedOption)); builder = new MySqlConnectionStringBuilder(Settings.ConnectionString); builder.SslCert = _sslCert; conn = new MySqlConnection($"{builder.ConnectionString};sslcert={repeatedOption}"); - Assert.AreEqual(repeatedOption, conn.Settings.SslCert); + Assert.That(conn.Settings.SslCert, Is.EqualTo(repeatedOption)); builder = new MySqlConnectionStringBuilder(Settings.ConnectionString); builder.SslKey = _sslKey; conn = new MySqlConnection($"{builder.ConnectionString};sslkey={repeatedOption}"); - Assert.AreEqual(repeatedOption, conn.Settings.SslKey); + Assert.That(conn.Settings.SslKey, Is.EqualTo(repeatedOption)); } [Test] @@ -173,8 +173,8 @@ public void SslPreferredByDefault() MySqlCommand command = new MySqlCommand("SHOW SESSION STATUS LIKE 'Ssl_version';", Connection); using (MySqlDataReader reader = command.ExecuteReader()) { - Assert.True(reader.Read()); - StringAssert.StartsWith("TLSv1", reader.GetString(1)); + Assert.That(reader.Read()); + Assert.That(reader.GetString(1), Does.StartWith("TLSv1")); } } @@ -192,8 +192,8 @@ public void SslOverrided() MySqlCommand command = new MySqlCommand("SHOW SESSION STATUS LIKE 'Ssl_version';", connection); using (MySqlDataReader reader = command.ExecuteReader()) { - Assert.True(reader.Read()); - Assert.AreEqual(string.Empty, reader.GetString(1)); + Assert.That(reader.Read()); + Assert.That(reader.GetString(1), Is.EqualTo(string.Empty)); } } } @@ -226,15 +226,15 @@ public void TlsVersionTest(string tlsVersion, int error) { case 1: ex = Assert.Throws(SetTlsVersion).Message; - StringAssert.AreEqualIgnoringCase(Resources.TlsVersionsEmpty, ex); + Assert.That(ex, Is.EqualTo(Resources.TlsVersionsEmpty).IgnoreCase); break; case 2: ex = Assert.Throws(SetTlsVersion).Message; - StringAssert.AreEqualIgnoringCase(Resources.TlsUnsupportedVersions, ex); + Assert.That(ex, Is.EqualTo(Resources.TlsUnsupportedVersions).IgnoreCase); break; case 3: ex = Assert.Throws(SetTlsVersion).Message; - StringAssert.AreEqualIgnoringCase(Resources.TlsNonValidProtocols, ex); + Assert.That(ex, Is.EqualTo(Resources.TlsNonValidProtocols).IgnoreCase); break; default: SetTlsVersion(); @@ -243,17 +243,17 @@ public void TlsVersionTest(string tlsVersion, int error) using (conn) { conn.Open(); - Assert.AreEqual(ConnectionState.Open, conn.State); + Assert.That(conn.State, Is.EqualTo(ConnectionState.Open)); MySqlCommand cmd = conn.CreateCommand(); cmd.CommandText = "SHOW SESSION STATUS LIKE 'ssl_version'"; using MySqlDataReader dr = cmd.ExecuteReader(); - Assert.True(dr.Read()); + Assert.That(dr.Read()); if (error==4) - StringAssert.AreEqualIgnoringCase(tlsVersion, dr[1].ToString()); + Assert.That(dr[1].ToString(), Is.EqualTo(tlsVersion).IgnoreCase); else - StringAssert.AreEqualIgnoringCase(tlsdefault, dr[1].ToString()); + Assert.That(dr[1].ToString(), Is.EqualTo(tlsdefault).IgnoreCase); } break; } @@ -275,14 +275,14 @@ public void TlsVersionNoSslTest(string tlsVersion) using (var conn = new MySqlConnection(builder.ConnectionString)) { conn.Open(); - Assert.AreEqual(ConnectionState.Open, conn.State); + Assert.That(conn.State, Is.EqualTo(ConnectionState.Open)); MySqlCommand cmd = conn.CreateCommand(); cmd.CommandText = "SHOW SESSION STATUS LIKE 'ssl_version'"; using MySqlDataReader dr = cmd.ExecuteReader(); - Assert.True(dr.Read()); - Assert.IsEmpty(dr[1].ToString()); + Assert.That(dr.Read()); + Assert.That(dr[1].ToString(), Is.Empty); } } #endregion @@ -306,12 +306,12 @@ public void CanConnectUsingFileBasedCertificate() using (MySqlConnection c = new MySqlConnection(connstr)) { c.Open(); - Assert.AreEqual(ConnectionState.Open, c.State); + Assert.That(c.State, Is.EqualTo(ConnectionState.Open)); MySqlCommand command = new MySqlCommand("SHOW SESSION STATUS LIKE 'Ssl_version';", c); using (MySqlDataReader reader = command.ExecuteReader()) { - Assert.True(reader.Read()); - StringAssert.StartsWith("TLSv1", reader.GetString(1)); + Assert.That(reader.Read()); + Assert.That(reader.GetString(1), Does.StartWith("TLSv1")); } } } @@ -325,19 +325,19 @@ public void ConnectUsingPFXCertificates() using (MySqlConnection c = new MySqlConnection(connstr)) { c.Open(); - Assert.AreEqual(ConnectionState.Open, c.State); + Assert.That(c.State, Is.EqualTo(ConnectionState.Open)); MySqlCommand command = new MySqlCommand("SHOW SESSION STATUS LIKE 'Ssl_version';", c); using (MySqlDataReader reader = command.ExecuteReader()) { - Assert.True(reader.Read()); - StringAssert.StartsWith("TLSv1", reader.GetString(1)); + Assert.That(reader.Read()); + Assert.That(reader.GetString(1), Does.StartWith("TLSv1")); } command = new MySqlCommand("show variables like 'tls_version'", c); using (MySqlDataReader reader = command.ExecuteReader()) { - Assert.True(reader.Read()); - StringAssert.Contains("TLS", reader.GetString(1)); + Assert.That(reader.Read()); + Assert.That(reader.GetString(1), Does.Contain("TLS")); } } @@ -386,7 +386,7 @@ public void InvalidCertificateThumbprint() using (var conn = new MySqlConnection(csb.ConnectionString)) { conn.Open(); - Assert.AreEqual(ConnectionState.Open, conn.connectionState); + Assert.That(conn.connectionState, Is.EqualTo(ConnectionState.Open)); } } @@ -401,20 +401,20 @@ public void SslCertificateConnectionOptionsExistAndDefaultToNull() var builder = new MySqlConnectionStringBuilder(); // Options exist. - Assert.True(builder.values.ContainsKey("sslca")); - Assert.True(builder.values.ContainsKey("sslcert")); - Assert.True(builder.values.ContainsKey("sslkey")); + Assert.That(builder.values.ContainsKey("sslca")); + Assert.That(builder.values.ContainsKey("sslcert")); + Assert.That(builder.values.ContainsKey("sslkey")); // Options default to null. - Assert.Null(builder["sslca"]); - Assert.Null(builder["sslcert"]); - Assert.Null(builder["sslkey"]); - Assert.Null(builder["ssl-ca"]); - Assert.Null(builder["ssl-cert"]); - Assert.Null(builder["ssl-key"]); - Assert.Null(builder.SslCa); - Assert.Null(builder.SslCert); - Assert.Null(builder.SslKey); + Assert.That(builder["sslca"], Is.Null); + Assert.That(builder["sslcert"], Is.Null); + Assert.That(builder["sslkey"], Is.Null); + Assert.That(builder["ssl-ca"], Is.Null); + Assert.That(builder["ssl-cert"], Is.Null); + Assert.That(builder["ssl-key"], Is.Null); + Assert.That(builder.SslCa, Is.Null); + Assert.That(builder.SslCert, Is.Null); + Assert.That(builder.SslKey, Is.Null); // Null or whitespace options are ignored. var connectionString = $"host={Settings.Server};user={Settings.UserID};port={Settings.Port};password={Settings.Password};"; @@ -424,9 +424,9 @@ public void SslCertificateConnectionOptionsExistAndDefaultToNull() builder.SslKey = " "; using (var connection = new MySqlConnection(builder.ConnectionString)) { - Assert.Null(connection.Settings.SslCa); - Assert.Null(connection.Settings.SslCert); - Assert.AreEqual(" ", connection.Settings.SslKey); + Assert.That(connection.Settings.SslCa, Is.Null); + Assert.That(connection.Settings.SslCert, Is.Null); + Assert.That(connection.Settings.SslKey, Is.EqualTo(" ")); connection.Open(); connection.Close(); } @@ -435,9 +435,9 @@ public void SslCertificateConnectionOptionsExistAndDefaultToNull() connectionString = $"{connectionString}sslca=;sslcert=;sslkey="; using (var connection = new MySqlConnection(connectionString)) { - Assert.Null(connection.Settings.SslCa); - Assert.Null(connection.Settings.SslCert); - Assert.Null(connection.Settings.SslKey); + Assert.That(connection.Settings.SslCa, Is.Null); + Assert.That(connection.Settings.SslCert, Is.Null); + Assert.That(connection.Settings.SslKey, Is.Null); connection.Open(); connection.Close(); } @@ -452,16 +452,16 @@ public void MissingSslCaConnectionOption() using (var connection = new MySqlConnection(builder.ConnectionString)) { var exception = Assert.Throws(() => connection.Open()); - Assert.AreEqual(Resources.SslConnectionError, exception.Message); - Assert.AreEqual(string.Format(Resources.FilePathNotSet, nameof(Settings.SslCa)), exception.InnerException.Message); + Assert.That(exception.Message, Is.EqualTo(Resources.SslConnectionError)); + Assert.That(exception.InnerException.Message, Is.EqualTo(string.Format(Resources.FilePathNotSet, nameof(Settings.SslCa)))); } builder.SslMode = MySqlSslMode.VerifyFull; using (var connection = new MySqlConnection(builder.ConnectionString)) { var exception = Assert.Throws(() => connection.Open()); - Assert.AreEqual(Resources.SslConnectionError, exception.Message); - Assert.AreEqual(string.Format(Resources.FilePathNotSet, nameof(Settings.SslCa)), exception.InnerException.Message); + Assert.That(exception.Message, Is.EqualTo(Resources.SslConnectionError)); + Assert.That(exception.InnerException.Message, Is.EqualTo(string.Format(Resources.FilePathNotSet, nameof(Settings.SslCa)))); } } @@ -476,8 +476,8 @@ public void MissingSslCertConnectionOption() using (var connection = new MySqlConnection(builder.ConnectionString)) { var exception = Assert.Throws(() => connection.Open()); - Assert.AreEqual(Resources.SslConnectionError, exception.Message); - Assert.AreEqual(string.Format(Resources.FilePathNotSet, nameof(Settings.SslCert)), exception.InnerException.Message); + Assert.That(exception.Message, Is.EqualTo(Resources.SslConnectionError)); + Assert.That(exception.InnerException.Message, Is.EqualTo(string.Format(Resources.FilePathNotSet, nameof(Settings.SslCert)))); } } @@ -493,8 +493,8 @@ public void MissingSslKeyConnectionOption() using (var connection = new MySqlConnection(builder.ConnectionString)) { var exception = Assert.Throws(() => connection.Open()); - Assert.AreEqual(Resources.SslConnectionError, exception.Message); - Assert.AreEqual(string.Format(Resources.FilePathNotSet, nameof(Settings.SslKey)), exception.InnerException.Message); + Assert.That(exception.Message, Is.EqualTo(Resources.SslConnectionError)); + Assert.That(exception.InnerException.Message, Is.EqualTo(string.Format(Resources.FilePathNotSet, nameof(Settings.SslKey)))); } } @@ -508,8 +508,8 @@ public void InvalidFileNameForSslCaConnectionOption() using (var connection = new MySqlConnection(builder.ConnectionString)) { var exception = Assert.Throws(() => connection.Open()); - Assert.AreEqual(Resources.SslConnectionError, exception.Message); - Assert.AreEqual(Resources.FileNotFound, exception.InnerException.Message); + Assert.That(exception.Message, Is.EqualTo(Resources.SslConnectionError)); + Assert.That(exception.InnerException.Message, Is.EqualTo(Resources.FileNotFound)); } } @@ -524,8 +524,8 @@ public void InvalidFileNameForSslCertConnectionOption() using (var connection = new MySqlConnection(builder.ConnectionString)) { var exception = Assert.Throws(() => connection.Open()); - Assert.AreEqual(Resources.SslConnectionError, exception.Message); - Assert.AreEqual(Resources.FileNotFound, exception.InnerException.Message); + Assert.That(exception.Message, Is.EqualTo(Resources.SslConnectionError)); + Assert.That(exception.InnerException.Message, Is.EqualTo(Resources.FileNotFound)); } } @@ -541,8 +541,8 @@ public void InvalidFileNameForSslKeyConnectionOption() using (var connection = new MySqlConnection(builder.ConnectionString)) { var exception = Assert.Throws(() => connection.Open()); - Assert.AreEqual(Resources.SslConnectionError, exception.Message); - Assert.AreEqual(Resources.FileNotFound, exception.InnerException.Message); + Assert.That(exception.Message, Is.EqualTo(Resources.SslConnectionError)); + Assert.That(exception.InnerException.Message, Is.EqualTo(Resources.FileNotFound)); } } @@ -582,7 +582,7 @@ public void ConnectUsingAllCertificates() try { connection.Open(); } catch (Exception ex) { - Assert.True(ex is MySqlException || + Assert.That(ex is MySqlException || ex is AuthenticationException || ex is FormatException, ex.Message); } @@ -633,8 +633,8 @@ public void AttemptConnectionWithDummyPemCertificates() using (var connection = new MySqlConnection(builder.ConnectionString)) { var exception = Assert.Throws(() => connection.Open()); - Assert.AreEqual(Resources.SslConnectionError, exception.Message); - Assert.AreEqual(Resources.FileIsNotACertificate, exception.InnerException.Message, $"Cert. path: {_sslCa}"); + Assert.That(exception.Message, Is.EqualTo(Resources.SslConnectionError)); + Assert.That(exception.InnerException.Message, Is.EqualTo(Resources.FileIsNotACertificate), $"Cert. path: {_sslCa}"); } builder.SslCa = _sslCa; @@ -643,8 +643,8 @@ public void AttemptConnectionWithDummyPemCertificates() using (var connection = new MySqlConnection(builder.ConnectionString)) { var exception = Assert.Throws(() => connection.Open()); - Assert.AreEqual(Resources.SslConnectionError, exception.Message); - Assert.AreEqual(Resources.FileIsNotACertificate, exception.InnerException.Message); + Assert.That(exception.Message, Is.EqualTo(Resources.SslConnectionError)); + Assert.That(exception.InnerException.Message, Is.EqualTo(Resources.FileIsNotACertificate)); } builder.SslCa = _sslCa; @@ -654,8 +654,8 @@ public void AttemptConnectionWithDummyPemCertificates() using (var connection = new MySqlConnection(builder.ConnectionString)) { var exception = Assert.Throws(() => connection.Open()); - Assert.AreEqual(Resources.SslConnectionError, exception.Message); - Assert.AreEqual(Resources.FileIsNotAKey, exception.InnerException.Message); + Assert.That(exception.Message, Is.EqualTo(Resources.SslConnectionError)); + Assert.That(exception.InnerException.Message, Is.EqualTo(Resources.FileIsNotAKey)); } } @@ -669,8 +669,8 @@ public void AttemptConnectionWithSwitchedPemCertificates() using (var connection = new MySqlConnection(builder.ConnectionString)) { var exception = Assert.Throws(() => connection.Open()); - Assert.AreEqual(Resources.SslConnectionError, exception.Message); - Assert.AreEqual(Resources.SslCertificateIsNotCA, exception.InnerException.Message); + Assert.That(exception.Message, Is.EqualTo(Resources.SslConnectionError)); + Assert.That(exception.InnerException.Message, Is.EqualTo(Resources.SslCertificateIsNotCA)); } builder.SslCa = _sslKey; @@ -678,8 +678,8 @@ public void AttemptConnectionWithSwitchedPemCertificates() using (var connection = new MySqlConnection(builder.ConnectionString)) { var exception = Assert.Throws(() => connection.Open()); - Assert.AreEqual(Resources.SslConnectionError, exception.Message); - Assert.AreEqual(Resources.FileIsNotACertificate, exception.InnerException.Message); + Assert.That(exception.Message, Is.EqualTo(Resources.SslConnectionError)); + Assert.That(exception.InnerException.Message, Is.EqualTo(Resources.FileIsNotACertificate)); } builder.SslCa = _sslCa; @@ -688,8 +688,8 @@ public void AttemptConnectionWithSwitchedPemCertificates() using (var connection = new MySqlConnection(builder.ConnectionString)) { var exception = Assert.Throws(() => connection.Open()); - Assert.AreEqual(Resources.SslConnectionError, exception.Message); - Assert.AreEqual(Resources.InvalidSslCertificate, exception.InnerException.Message); + Assert.That(exception.Message, Is.EqualTo(Resources.SslConnectionError)); + Assert.That(exception.InnerException.Message, Is.EqualTo(Resources.InvalidSslCertificate)); } builder.SslCert = _sslCert; @@ -698,8 +698,8 @@ public void AttemptConnectionWithSwitchedPemCertificates() using (var connection = new MySqlConnection(builder.ConnectionString)) { var exception = Assert.Throws(() => connection.Open()); - Assert.AreEqual(Resources.SslConnectionError, exception.Message); - Assert.AreEqual(Resources.FileIsNotAKey, exception.InnerException.Message); + Assert.That(exception.Message, Is.EqualTo(Resources.SslConnectionError)); + Assert.That(exception.InnerException.Message, Is.EqualTo(Resources.FileIsNotAKey)); } } @@ -722,7 +722,7 @@ public void MaxConnectionsWithPersistAndGlobalVariables() connectionList.Add(c1); } Exception ex = Assert.Throws(() => conn.Open()); - StringAssert.Contains("Too many connections", ex.Message); + Assert.That(ex.Message, Does.Contain("Too many connections")); } foreach (var item in connectionList) { @@ -742,7 +742,7 @@ public void MaxConnectionsWithPersistAndGlobalVariables() connectionList.Add(c1); } Exception ex = Assert.Throws(() => conn.Open()); - StringAssert.Contains("Too many connections", ex.Message); + Assert.That(ex.Message, Does.Contain("Too many connections")); } foreach (var item in connectionList) { @@ -760,7 +760,7 @@ public void ShowVariablesRemoved() using (var dbConn = new MySqlConnection(Settings.ConnectionString)) { dbConn.Open();//Manually verify in server log that show variables is not present - Assert.AreEqual(ConnectionState.Open, dbConn.State); + Assert.That(dbConn.State, Is.EqualTo(ConnectionState.Open)); } } @@ -779,22 +779,22 @@ public void ConnectUsingCertificateFileAndTlsVersion() MySqlCommand cmd = new MySqlCommand("show variables like '%tls_version%'", connection); using (MySqlDataReader reader = cmd.ExecuteReader()) { - Assert.True(reader.Read()); - StringAssert.Contains("TLSv1", reader.GetString(1)); + Assert.That(reader.Read()); + Assert.That(reader.GetString(1), Does.Contain("TLSv1")); } cmd = new MySqlCommand("show status like 'Ssl_cipher'", connection); using (MySqlDataReader reader = cmd.ExecuteReader()) { - Assert.True(reader.Read()); - Assert.True(reader.GetString(1).ToString().Length > 0); + Assert.That(reader.Read()); + Assert.That(reader.GetString(1).ToString().Length > 0); } cmd = new MySqlCommand("show status like 'Ssl_version'", connection); using (MySqlDataReader reader = cmd.ExecuteReader()) { - Assert.True(reader.Read()); - StringAssert.AreEqualIgnoringCase("TLSv1.2", reader.GetString(1)); + Assert.That(reader.Read()); + Assert.That(reader.GetString(1), Is.EqualTo("TLSv1.2").IgnoreCase); } } } @@ -821,7 +821,7 @@ public void CorrectSslcaWrongSslkeySslcertRequiredMode() using (var c = new MySqlConnection(connClassic.ConnectionString)) { c.Open(); - Assert.AreEqual(ConnectionState.Open, c.State); + Assert.That(c.State, Is.EqualTo(ConnectionState.Open)); } connClassic = new MySqlConnectionStringBuilder(); @@ -835,7 +835,7 @@ public void CorrectSslcaWrongSslkeySslcertRequiredMode() using (var c = new MySqlConnection(connClassic.ConnectionString)) { c.Open(); - Assert.AreEqual(ConnectionState.Open, c.State); + Assert.That(c.State, Is.EqualTo(ConnectionState.Open)); } connClassic = new MySqlConnectionStringBuilder(); @@ -850,7 +850,7 @@ public void CorrectSslcaWrongSslkeySslcertRequiredMode() using (var c = new MySqlConnection(connClassic.ConnectionString)) { c.Open(); - Assert.AreEqual(ConnectionState.Open, c.State); + Assert.That(c.State, Is.EqualTo(ConnectionState.Open)); } var conn = new MySqlXConnectionStringBuilder(); @@ -865,7 +865,7 @@ public void CorrectSslcaWrongSslkeySslcertRequiredMode() using (var c = new MySqlConnection(connClassic.ConnectionString)) { c.Open(); - Assert.AreEqual(ConnectionState.Open, c.State); + Assert.That(c.State, Is.EqualTo(ConnectionState.Open)); } conn = new MySqlXConnectionStringBuilder(); @@ -879,7 +879,7 @@ public void CorrectSslcaWrongSslkeySslcertRequiredMode() using (var c = new MySqlConnection(connClassic.ConnectionString)) { c.Open(); - Assert.AreEqual(ConnectionState.Open, c.State); + Assert.That(c.State, Is.EqualTo(ConnectionState.Open)); } } } @@ -899,7 +899,7 @@ public void CorrectSslcaNoSslkeyorCertRequiredMode() using (var c = new MySqlConnection(connClassic.ConnectionString)) { c.Open(); - Assert.AreEqual(ConnectionState.Open, c.State); + Assert.That(c.State, Is.EqualTo(ConnectionState.Open)); } connClassic = new MySqlConnectionStringBuilder(); @@ -911,7 +911,7 @@ public void CorrectSslcaNoSslkeyorCertRequiredMode() using (var c = new MySqlConnection(connClassic.ConnectionString)) { c.Open(); - Assert.AreEqual(ConnectionState.Open, c.State); + Assert.That(c.State, Is.EqualTo(ConnectionState.Open)); } connClassic = new MySqlConnectionStringBuilder(); @@ -924,7 +924,7 @@ public void CorrectSslcaNoSslkeyorCertRequiredMode() using (var c = new MySqlConnection(connClassic.ConnectionString)) { c.Open(); - Assert.AreEqual(ConnectionState.Open, c.State); + Assert.That(c.State, Is.EqualTo(ConnectionState.Open)); } connClassic = new MySqlConnectionStringBuilder(); @@ -937,7 +937,7 @@ public void CorrectSslcaNoSslkeyorCertRequiredMode() using (var c = new MySqlConnection(connClassic.ConnectionString)) { c.Open(); - Assert.AreEqual(ConnectionState.Open, c.State); + Assert.That(c.State, Is.EqualTo(ConnectionState.Open)); } var conn = new MySqlXConnectionStringBuilder(); @@ -950,7 +950,7 @@ public void CorrectSslcaNoSslkeyorCertRequiredMode() using (var c = new MySqlConnection(conn.ConnectionString)) { c.Open(); - Assert.AreEqual(ConnectionState.Open, c.State); + Assert.That(c.State, Is.EqualTo(ConnectionState.Open)); } conn = new MySqlXConnectionStringBuilder(); @@ -962,7 +962,7 @@ public void CorrectSslcaNoSslkeyorCertRequiredMode() using (var c = new MySqlConnection(conn.ConnectionString)) { c.Open(); - Assert.AreEqual(ConnectionState.Open, c.State); + Assert.That(c.State, Is.EqualTo(ConnectionState.Open)); } } @@ -987,7 +987,7 @@ public void SecurityTlsCheck() conn.Open(); MySqlCommand cmd = new MySqlCommand("SELECT variable_value FROM performance_schema.session_status WHERE VARIABLE_NAME='Ssl_version'", conn); object result = cmd.ExecuteScalar(); - Assert.AreEqual(tlsVersion, result); + Assert.That(result, Is.EqualTo(tlsVersion)); } } @@ -998,10 +998,10 @@ public void SecurityTlsCheck() { // TLSv1.0 and TLSv1.1 has been deprecated in Ubuntu 20.04 so an exception is thrown try { conn.Open(); } - catch (Exception ex) { Assert.True(ex is AuthenticationException); return; } + catch (Exception ex) { Assert.That(ex is AuthenticationException); return; } MySqlCommand cmd = new MySqlCommand("SELECT variable_value FROM performance_schema.session_status WHERE VARIABLE_NAME='Ssl_version'", conn); object result = cmd.ExecuteScalar(); - Assert.True(result.ToString().StartsWith("TLSv1")); + Assert.That(result.ToString().StartsWith("TLSv1")); } } } @@ -1023,7 +1023,7 @@ public void InvalidTlsversionValues() // Not supported protocols var ex = Assert.Throws(() => conn = new MySqlConnection(conStr + $";ssl-mode={MySqlSslMode.Required};tls-version=[TLSv1];tls-version=[TLSv1]")); - StringAssert.AreEqualIgnoringCase("TLS protocols TLSv1 and TLSv1.1 are no longer supported. Accepted values are TLSv1.2 and TLSv1.3", ex.Message); + Assert.That(ex.Message, Is.EqualTo("TLS protocols TLSv1 and TLSv1.1 are no longer supported. Accepted values are TLSv1.2 and TLSv1.3").IgnoreCase); // Repeated options are allowed Assert.DoesNotThrow(() => conn = new MySqlConnection(conStr + $";ssl-mode={MySqlSslMode.Required};tls-version=[TLSv1.1,TLSv1.2];tls-version=[TLSv1.2]")); @@ -1043,7 +1043,7 @@ public void SslUserWithoutSslParams() cmd.ExecuteNonQuery(); var rdr1 = cmd.ExecuteReader(); while (rdr1.Read()) - Assert.True(rdr1.GetValue(1).ToString().Trim() == ""); + Assert.That(rdr1.GetValue(1).ToString().Trim() == ""); } connstr = $"server={Host};user={Settings.UserID};port={Port};password=;sslmode={MySqlSslMode.Disabled}"; @@ -1070,7 +1070,7 @@ public void PositiveSslConnectionWithCertificates() { while (rdr.Read()) { - Assert.True(rdr.GetValue(1).ToString().Trim().Contains("TLSv1")); + Assert.That(rdr.GetValue(1).ToString().Trim().Contains("TLSv1")); } } @@ -1079,7 +1079,7 @@ public void PositiveSslConnectionWithCertificates() { while (rdr.Read()) { - Assert.True(rdr.GetValue(1).ToString().Trim().Length > 0); + Assert.That(rdr.GetValue(1).ToString().Trim().Length > 0); } } @@ -1088,7 +1088,7 @@ public void PositiveSslConnectionWithCertificates() { while (rdr.Read()) { - Assert.True(rdr.GetValue(1).ToString().StartsWith("TLSv1")); + Assert.That(rdr.GetValue(1).ToString().StartsWith("TLSv1")); } } } @@ -1103,7 +1103,7 @@ public void PositiveSslConnectionWithCertificates() { while (rdr.Read()) { - Assert.True(rdr.GetValue(1).ToString().Trim().Contains("TLSv1")); + Assert.That(rdr.GetValue(1).ToString().Trim().Contains("TLSv1")); } } @@ -1113,7 +1113,7 @@ public void PositiveSslConnectionWithCertificates() { while (rdr.Read()) { - Assert.True(rdr.GetValue(1).ToString().Trim().Length > 0); + Assert.That(rdr.GetValue(1).ToString().Trim().Length > 0); } } cmd.Connection = c; @@ -1122,7 +1122,7 @@ public void PositiveSslConnectionWithCertificates() { while (rdr.Read()) { - Assert.True(rdr.GetValue(1).ToString().StartsWith("TLSv1")); + Assert.That(rdr.GetValue(1).ToString().StartsWith("TLSv1")); } } } @@ -1149,8 +1149,8 @@ public void SslOptionsCombinedWhenDisabled(MySqlSslMode sslMode, string sslOptio reader.Read(); string encryption = reader.GetString(1); - Assert.IsEmpty(encryption); - Assert.AreEqual(ConnectionState.Open, conn.State); + Assert.That(encryption, Is.Empty); + Assert.That(conn.State, Is.EqualTo(ConnectionState.Open)); } [Test] @@ -1165,8 +1165,8 @@ public void SslRequiredOverDisabled() reader.Read(); string encryption = reader.GetString(1); - Assert.IsNotEmpty(encryption); - Assert.AreEqual(ConnectionState.Open, conn.State); + Assert.That(encryption, Is.Not.Empty); + Assert.That(conn.State, Is.EqualTo(ConnectionState.Open)); } /// @@ -1194,7 +1194,7 @@ public void SslChainedCertificates(MySqlSslMode sslMode) using var conn = new MySqlConnection(stringBuilder.ConnectionString); conn.Open(); - Assert.IsTrue(conn.State == ConnectionState.Open); + Assert.That(conn.State == ConnectionState.Open); } #region Methods diff --git a/MySQL.Data/tests/MySql.Data.Tests/StoredProcedure.cs b/MySQL.Data/tests/MySql.Data.Tests/StoredProcedure.cs index 1a053144b..8a96eafd1 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/StoredProcedure.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/StoredProcedure.cs @@ -65,7 +65,7 @@ public void ReturningResultset() p.Value = 21; decimal id = (decimal)cmd.ExecuteScalar(); - Assert.AreEqual(21, id); + Assert.That(id, Is.EqualTo(21)); } } @@ -81,17 +81,17 @@ public void NonQuery() cmd.CommandType = CommandType.StoredProcedure; cmd.Parameters.AddWithValue("?value", 2); int rowsAffected = cmd.ExecuteNonQuery(); - Assert.AreEqual(1, rowsAffected); + Assert.That(rowsAffected, Is.EqualTo(1)); cmd.CommandText = "SELECT * FROM Test"; cmd.CommandType = CommandType.Text; using (MySqlDataReader reader = cmd.ExecuteReader()) { - Assert.True(reader.Read()); - Assert.AreEqual(2, reader.GetInt32(0)); - Assert.AreEqual("Test", reader.GetString(1)); - Assert.False(reader.Read()); - Assert.False(reader.NextResult()); + Assert.That(reader.Read()); + Assert.That(reader.GetInt32(0), Is.EqualTo(2)); + Assert.That(reader.GetString(1), Is.EqualTo("Test")); + Assert.That(reader.Read(), Is.False); + Assert.That(reader.NextResult(), Is.False); } } @@ -123,7 +123,7 @@ public void NoInOutMarker() cmd.CommandType = CommandType.StoredProcedure; cmd.Parameters.AddWithValue("?valin", "myvalue"); object val = cmd.ExecuteScalar(); - Assert.AreEqual("myvalue", val); + Assert.That(val, Is.EqualTo("myvalue")); } [Test] @@ -147,8 +147,8 @@ public void ExecuteScalar2() MySqlCommand cmd = new MySqlCommand("spTest", Connection); cmd.CommandType = CommandType.StoredProcedure; object result = cmd.ExecuteScalar(); - Assert.AreEqual(1, result); - Assert.True(result is Int32); + Assert.That(result, Is.EqualTo(1)); + Assert.That(result is Int32); } [Test] @@ -174,11 +174,11 @@ private void MultipleResultsetsImpl(bool prepare) if (prepare) cmd.Prepare(); cmd.CommandType = CommandType.StoredProcedure; MySqlDataReader reader = cmd.ExecuteReader(); - Assert.True(reader.Read()); - Assert.True(reader.NextResult()); - Assert.True(reader.Read()); - Assert.False(reader.NextResult()); - Assert.False(reader.Read()); + Assert.That(reader.Read()); + Assert.That(reader.NextResult()); + Assert.That(reader.Read()); + Assert.That(reader.NextResult(), Is.False); + Assert.That(reader.Read(), Is.False); reader.Close(); DataSet ds = new DataSet(); @@ -188,12 +188,12 @@ private void MultipleResultsetsImpl(bool prepare) da.FillError += new FillErrorEventHandler(da_FillError); fillError = null; da.Fill(ds); - Assert.AreEqual(2, ds.Tables.Count); - Assert.AreEqual(1, Convert.ToInt32(ds.Tables[0].Rows.Count)); - Assert.AreEqual(1, Convert.ToInt32(ds.Tables[1].Rows.Count)); - Assert.AreEqual(1, Convert.ToInt32(ds.Tables[0].Rows[0][0])); - Assert.AreEqual(2, Convert.ToInt32(ds.Tables[1].Rows[0][0])); - Assert.Null(fillError); + Assert.That(ds.Tables.Count, Is.EqualTo(2)); + Assert.That(Convert.ToInt32(ds.Tables[0].Rows.Count), Is.EqualTo(1)); + Assert.That(Convert.ToInt32(ds.Tables[1].Rows.Count), Is.EqualTo(1)); + Assert.That(Convert.ToInt32(ds.Tables[0].Rows[0][0]), Is.EqualTo(1)); + Assert.That(Convert.ToInt32(ds.Tables[1].Rows[0][0]), Is.EqualTo(2)); + Assert.That(fillError, Is.Null); } private static string fillError = null; @@ -213,7 +213,7 @@ public void ExecuteWithCreate() MySqlCommand cmd = new MySqlCommand(sql, Connection); cmd.Parameters.Add(new MySqlParameter("?v", 33)); object val = cmd.ExecuteScalar(); - Assert.AreEqual(33, val); + Assert.That(val, Is.EqualTo(33)); } /// @@ -232,14 +232,14 @@ public void OtherProcSigs() cmd.Parameters.AddWithValue("?val2", 4); decimal val = (decimal)cmd.ExecuteScalar(); Decimal d = new Decimal(20.4); - Assert.AreEqual(d, val); + Assert.That(val, Is.EqualTo(d)); // create our second procedure ExecuteSQL("DROP PROCEDURE IF EXISTS spTest"); ExecuteSQL("CREATE PROCEDURE spTest( \r\n) BEGIN SELECT 4; END"); cmd.Parameters.Clear(); object val1 = cmd.ExecuteScalar(); - Assert.AreEqual(4, Convert.ToInt32(val1)); + Assert.That(Convert.ToInt32(val1), Is.EqualTo(4)); } /// @@ -255,7 +255,7 @@ public void NoDefaultDatabase() MySqlCommand cmd = new MySqlCommand("spTest", Connection); cmd.CommandType = CommandType.StoredProcedure; object val = cmd.ExecuteScalar(); - Assert.AreEqual(4, Convert.ToInt32(val)); + Assert.That(Convert.ToInt32(val), Is.EqualTo(4)); cmd.CommandText = String.Format("USE `{0}`", dbName); cmd.CommandType = CommandType.Text; @@ -264,7 +264,7 @@ public void NoDefaultDatabase() cmd.CommandText = String.Format("`{0}`.spTest", Connection.Database); cmd.CommandType = CommandType.StoredProcedure; val = cmd.ExecuteScalar(); - Assert.AreEqual(4, Convert.ToInt32(val)); + Assert.That(Convert.ToInt32(val), Is.EqualTo(4)); cmd.CommandText = String.Format("USE `{0}`", Connection.Database); cmd.CommandType = CommandType.Text; @@ -300,7 +300,7 @@ public void DecimalAsParameter() cmd.CommandType = CommandType.StoredProcedure; cmd.Parameters.AddWithValue("?d", 21); decimal d = (decimal)cmd.ExecuteScalar(); - Assert.AreEqual(21, d); + Assert.That(d, Is.EqualTo(21)); } /// @@ -316,7 +316,7 @@ public void ParmWithCharacterSet() cmd.CommandType = CommandType.StoredProcedure; cmd.Parameters.AddWithValue("?P", "This is my value"); string p = (string)cmd.ExecuteScalar(); - Assert.AreEqual("This is my value", p); + Assert.That(p, Is.EqualTo("This is my value")); } /// @@ -335,7 +335,7 @@ public void SpecialCharacters() cmd.CommandType = CommandType.StoredProcedure; string val = (string)cmd.ExecuteScalar(); - Assert.AreEqual("This is my value", val); + Assert.That(val, Is.EqualTo("This is my value")); } finally { @@ -354,7 +354,7 @@ public void CallingSPWithPrepare() cmd.Prepare(); int p = (int)cmd.ExecuteScalar(); - Assert.AreEqual(33, p); + Assert.That(p, Is.EqualTo(33)); } /// @@ -383,10 +383,10 @@ public void MultipleRecords() DataTable dt = new DataTable(); da.Fill(dt); - Assert.AreEqual(1, dt.Rows[0]["id"]); - Assert.AreEqual(2, dt.Rows[1]["id"]); - Assert.AreEqual("First record", dt.Rows[0]["name"]); - Assert.AreEqual("Second record", dt.Rows[1]["name"]); + Assert.That(dt.Rows[0]["id"], Is.EqualTo(1)); + Assert.That(dt.Rows[1]["id"], Is.EqualTo(2)); + Assert.That(dt.Rows[0]["name"], Is.EqualTo("First record")); + Assert.That(dt.Rows[1]["name"], Is.EqualTo("Second record")); } /// @@ -440,8 +440,8 @@ public void ProcedureCache() System.Diagnostics.Trace.Listeners.Remove(myListener); // now see how many times our listener recorded a cache hit - Assert.AreEqual(190, myListener.Find("from procedure cache")); - Assert.AreEqual(10, myListener.Find("from server")); + Assert.That(myListener.Find("from procedure cache"), Is.EqualTo(190)); + Assert.That(myListener.Find("from server"), Is.EqualTo(10)); } } @@ -542,7 +542,7 @@ public void ProcEnumParamTest() using (MySqlDataReader reader = cmd.ExecuteReader()) { reader.Read(); - Assert.AreEqual("P", reader.GetString(0)); + Assert.That(reader.GetString(0), Is.EqualTo("P")); } } @@ -565,7 +565,7 @@ public void GetSchema() MySqlDataAdapter da = new MySqlDataAdapter(cmd); DataTable schema = new DataTable(); da.FillSchema(schema, SchemaType.Source); - Assert.AreEqual(2, schema.Columns.Count); + Assert.That(schema.Columns.Count, Is.EqualTo(2)); } /// @@ -622,14 +622,14 @@ public void UsingUInt64AsParam() public void CatalogWithHyphens() { // make sure this test is valid - Assert.True(Connection.Database.IndexOf('-') != -1); + Assert.That(Connection.Database.IndexOf('-') != -1); MySqlCommand cmd = new MySqlCommand("CREATE PROCEDURE spTest() BEGIN SELECT 1; END", Connection); cmd.ExecuteNonQuery(); cmd.CommandText = "spTest"; cmd.CommandType = CommandType.StoredProcedure; - Assert.AreEqual(1, Convert.ToInt32(cmd.ExecuteScalar())); + Assert.That(Convert.ToInt32(cmd.ExecuteScalar()), Is.EqualTo(1)); } [Test] @@ -677,7 +677,7 @@ public void SPWithSpaceInParameterType() cmd.Parameters.Add("@myparam", MySqlDbType.Decimal).Value = 20; cmd.CommandType = CommandType.StoredProcedure; object o = cmd.ExecuteScalar(); - Assert.AreEqual(1, Convert.ToInt32(o)); + Assert.That(Convert.ToInt32(o), Is.EqualTo(1)); } private void ParametersInReverseOrderInternal(bool isOwner) @@ -705,13 +705,13 @@ private void ParametersInReverseOrderInternal(bool isOwner) da.Fill(dt); if (!isOwner) { - Assert.AreEqual("World", dt.Rows[0][0]); - Assert.AreEqual("Hello", dt.Rows[0][1]); + Assert.That(dt.Rows[0][0], Is.EqualTo("World")); + Assert.That(dt.Rows[0][1], Is.EqualTo("Hello")); } else { - Assert.AreEqual("Hello", dt.Rows[0]["P1"]); - Assert.AreEqual("World", dt.Rows[0]["P2"]); + Assert.That(dt.Rows[0]["P1"], Is.EqualTo("Hello")); + Assert.That(dt.Rows[0]["P2"], Is.EqualTo("World")); } } } @@ -737,7 +737,7 @@ public void DeriveParameters() MySqlCommand cmd = new MySqlCommand("spTest", Connection); cmd.CommandType = CommandType.StoredProcedure; MySqlCommandBuilder.DeriveParameters(cmd); - Assert.AreEqual(2, cmd.Parameters.Count); + Assert.That(cmd.Parameters.Count, Is.EqualTo(2)); } /// @@ -795,7 +795,7 @@ public void GetProcedureParametersDoesNotRequireSelectFromMySqlProceduresTable() MySqlSchemaCollection parametersTable = isp.GetProcedureParametersAsync(rest, new MySqlSchemaCollection(procTable), false).GetAwaiter().GetResult(); - Assert.NotNull(parametersTable); + Assert.That(parametersTable, Is.Not.Null); } } @@ -816,7 +816,7 @@ public void NamesWithPeriods() cmd.Parameters.AddWithValue("?p", 2); cmd.CommandType = CommandType.StoredProcedure; var result = cmd.ExecuteScalar(); - Assert.AreEqual(2, result); + Assert.That(result, Is.EqualTo(2)); } } //Database and stored procedure contains "." @@ -830,7 +830,7 @@ public void NamesWithPeriods() cmd.Parameters.AddWithValue("?p", 3); cmd.CommandType = CommandType.StoredProcedure; var result = cmd.ExecuteScalar(); - Assert.AreEqual(3, result); + Assert.That(result, Is.EqualTo(3)); } } } @@ -849,7 +849,7 @@ public void GetSchemaProcedures() if (table.Rows.Count > 0) { var column = table.Rows[0]["ROUTINE_DEFINITION"]; - Assert.IsNotEmpty(column.ToString()); + Assert.That(column.ToString(), Is.Not.Empty); } } } @@ -870,11 +870,11 @@ public void ProcedureWithoutDbNameInConnString() MySqlCommand command = conn.CreateCommand(); command.CommandText = $"test_prepare.spTest"; command.CommandType = CommandType.StoredProcedure; - Assert.AreEqual(1, command.ExecuteScalar()); + Assert.That(command.ExecuteScalar(), Is.EqualTo(1)); command.CommandText = $"`test_prepare`.`spTest`"; command.CommandType = CommandType.StoredProcedure; - Assert.AreEqual(1, command.ExecuteScalar()); + Assert.That(command.ExecuteScalar(), Is.EqualTo(1)); } } @@ -913,7 +913,7 @@ public void VerifyParametersType() cmd.Prepare(); cmd.ExecuteNonQuery(); var result = cmd.Parameters["@value"].Value; - Assert.AreEqual("test value", result); + Assert.That(result, Is.EqualTo("test value")); //call Prepare() when SP and MySqlParameter have different data types cmd = new MySqlCommand("spTest", connection); @@ -950,7 +950,7 @@ public void PassJsonParameter() cmd = new MySqlCommand("SELECT jsonValue FROM Test", conn); cmd.CommandType = CommandType.Text; - StringAssert.AreEqualIgnoringCase(json, cmd.ExecuteScalar().ToString().Replace(" ", "")); + Assert.That(cmd.ExecuteScalar().ToString().Replace(" ", ""), Is.EqualTo(json).IgnoreCase); } } @@ -967,7 +967,7 @@ public void PassBoolParameter() cmd.CommandType = CommandType.StoredProcedure; cmd.Parameters.Add(new MySqlParameter { ParameterName = "success", Value = true, MySqlDbType = MySqlDbType.Int32 }); cmd.Prepare(); - Assert.IsTrue(Convert.ToBoolean(cmd.ExecuteScalar())); + Assert.That(Convert.ToBoolean(cmd.ExecuteScalar())); } } @@ -994,7 +994,7 @@ public void PassDateTimeParameter() var result = cmd.Parameters["@value"].Value; DateTime dateTime = new DateTime(2020, 11, 27, 12, 25, 59); - Assert.AreEqual(dateTime, result); + Assert.That(result, Is.EqualTo(dateTime)); } ExecuteSQL("DROP PROCEDURE spTest"); @@ -1013,7 +1013,7 @@ public void PassDateTimeParameter() cmd = new MySqlCommand("SELECT dateTime FROM Test", conn); cmd.CommandType = CommandType.Text; - Assert.AreEqual(dateTime, cmd.ExecuteScalar()); + Assert.That(cmd.ExecuteScalar(), Is.EqualTo(dateTime)); } } @@ -1067,7 +1067,7 @@ public void EventsStatementsHistory() { while (rdr.Read()) { - Assert.AreEqual("5", rdr.GetString(0)); + Assert.That(rdr.GetString(0), Is.EqualTo("5")); } } @@ -1082,11 +1082,11 @@ public void EventsStatementsHistory() } } } - Assert.True(testResult); + Assert.That(testResult); cmd = new MySqlCommand($"SELECT count(*) FROM information_schema.routines WHERE 1=1 AND ROUTINE_SCHEMA='{Settings.Database}' AND ROUTINE_NAME='{spName}';", Connection); var count = cmd.ExecuteScalar(); - Assert.AreEqual(1, count); + Assert.That(count, Is.EqualTo(1)); } @@ -1106,11 +1106,11 @@ public void FullyQualifiedProcedures() MySqlCommand command = conn.CreateCommand(); command.CommandText = $"`Test`.`spTest`"; command.CommandType = CommandType.StoredProcedure; - Assert.AreEqual(1, command.ExecuteScalar()); + Assert.That(command.ExecuteScalar(), Is.EqualTo(1)); command.CommandText = $"Test.spTest"; command.CommandType = CommandType.StoredProcedure; - Assert.AreEqual(1, command.ExecuteScalar()); + Assert.That(command.ExecuteScalar(), Is.EqualTo(1)); } } @@ -1135,7 +1135,7 @@ public void StoredProceduresWithBackticks(string quotedName, string spNameCnet) command.CommandText = spNameCnet; command.CommandType = CommandType.StoredProcedure; - Assert.AreEqual(1, command.ExecuteScalar()); + Assert.That(command.ExecuteScalar(), Is.EqualTo(1)); } } @@ -1157,7 +1157,7 @@ public void StoredProceduresWithBackticks2(string schema, string spName, string command.CommandText = spNameCnet; command.CommandType = CommandType.StoredProcedure; - Assert.AreEqual(1, command.ExecuteScalar()); + Assert.That(command.ExecuteScalar(), Is.EqualTo(1)); } ExecuteSQL($"DROP SCHEMA {schema};", true); @@ -1220,7 +1220,7 @@ public void StoredProceduresWithBackticksExceptionRaised(string schema, string s [TestCase("` foo`.bar", true)] public void IsSyntacticallyCorrect(string spName, bool isIt) { - Assert.IsTrue(MySqlClient.StoredProcedure.IsSyntacticallyCorrect(spName) == isIt); + Assert.That(MySqlClient.StoredProcedure.IsSyntacticallyCorrect(spName) == isIt); } } } diff --git a/MySQL.Data/tests/MySql.Data.Tests/StressTests.cs b/MySQL.Data/tests/MySql.Data.Tests/StressTests.cs index 66a4334ff..bb46478ba 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/StressTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/StressTests.cs @@ -76,12 +76,12 @@ public void TestMultiPacket() reader.Read(); byte[] dataOut = new byte[len]; long count = reader.GetBytes(2, 0, dataOut, 0, len); - Assert.AreEqual(len, count); + Assert.That(count, Is.EqualTo(len)); int i = 0; try { for (; i < len; i++) - Assert.AreEqual(dataIn[i], dataOut[i]); + Assert.That(dataOut[i], Is.EqualTo(dataIn[i])); } catch (Exception) { @@ -90,10 +90,10 @@ public void TestMultiPacket() reader.Read(); count = reader.GetBytes(2, 0, dataOut, 0, len); - Assert.AreEqual(len, count); + Assert.That(count, Is.EqualTo(len)); for (int x = 0; x < len; x++) - Assert.AreEqual(dataIn2[x], dataOut[x]); + Assert.That(dataOut[x], Is.EqualTo(dataIn2[x])); } } } @@ -121,12 +121,12 @@ public void TestSequence() { while (reader.Read()) { - Assert.True(i2 + 1 == reader.GetInt32(0), "Sequence out of order"); + Assert.That(i2 + 1 == reader.GetInt32(0), "Sequence out of order"); i2++; } reader.Close(); - Assert.AreEqual(8000, i2); + Assert.That(i2, Is.EqualTo(8000)); cmd = new MySqlCommand("delete from Test where id >= 100", Connection); cmd.ExecuteNonQuery(); } diff --git a/MySQL.Data/tests/MySql.Data.Tests/Syntax.cs b/MySQL.Data/tests/MySql.Data.Tests/Syntax.cs index 23b31e307..9b27c98ff 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Syntax.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Syntax.cs @@ -48,7 +48,7 @@ public void ShowCreateTable() DataTable dt = Utils.FillTable("SHOW CREATE TABLE Test", Connection); Assert.That(dt.Rows, Has.One.Items); - Assert.AreEqual(2, dt.Columns.Count); + Assert.That(dt.Columns.Count, Is.EqualTo(2)); } [Test] @@ -72,10 +72,10 @@ public void ProblemCharsInSQLUTF8() cmd.CommandText = "SELECT * FROM Test"; using (MySqlDataReader reader = cmd.ExecuteReader()) { - Assert.True(reader.Read()); - Assert.AreEqual(1, reader.GetInt32(0)); - Assert.AreEqual("This is my;test ? string–’‘’“”…", reader.GetString(1)); - Assert.AreEqual("My MT string: ?", reader.GetString(2)); + Assert.That(reader.Read()); + Assert.That(reader.GetInt32(0), Is.EqualTo(1)); + Assert.That(reader.GetString(1), Is.EqualTo("This is my;test ? string–’‘’“”…")); + Assert.That(reader.GetString(2), Is.EqualTo("My MT string: ?")); } } } @@ -96,10 +96,10 @@ public void ProblemCharsInSQL() cmd.CommandText = "SELECT * FROM Test"; using (MySqlDataReader reader = cmd.ExecuteReader()) { - Assert.True(reader.Read()); - Assert.AreEqual(1, reader.GetInt32(0)); - Assert.AreEqual("This is my;test ? string-'''\"\".", reader.GetString(1)); - Assert.AreEqual("My MT string: ?", reader.GetString(2)); + Assert.That(reader.Read()); + Assert.That(reader.GetInt32(0), Is.EqualTo(1)); + Assert.That(reader.GetString(1), Is.EqualTo("This is my;test ? string-'''\"\".")); + Assert.That(reader.GetString(2), Is.EqualTo("My MT string: ?")); } } @@ -136,11 +136,11 @@ private void LoadFile(MySqlConnection conn, string path) object cnt = 0; cnt = cmd.ExecuteNonQuery(); - Assert.AreEqual(200000, Convert.ToInt32(cnt)); + Assert.That(Convert.ToInt32(cnt), Is.EqualTo(200000)); cmd.CommandText = "SELECT COUNT(*) FROM Test"; cnt = cmd.ExecuteScalar(); - Assert.AreEqual(200000, Convert.ToInt32(cnt)); + Assert.That(Convert.ToInt32(cnt), Is.EqualTo(200000)); } } @@ -196,7 +196,7 @@ public void Sum() { reader.Read(); object o = reader[0]; - Assert.AreEqual(1, Convert.ToInt32(o)); + Assert.That(Convert.ToInt32(o), Is.EqualTo(1)); } } @@ -213,8 +213,8 @@ public void Sum2() using (MySqlDataReader reader = cmd.ExecuteReader()) { reader.Read(); - Assert.AreEqual(1, reader.GetInt32(0)); - Assert.AreEqual(110, reader.GetDouble(1)); + Assert.That(reader.GetInt32(0), Is.EqualTo(1)); + Assert.That(reader.GetDouble(1), Is.EqualTo(110)); } } @@ -239,11 +239,11 @@ public void SettingAutoIncrementColumns() MySqlCommand cmd = new MySqlCommand("SELECT name FROM Test WHERE id=1", Connection); object name = cmd.ExecuteScalar(); - Assert.AreEqual("One", name); + Assert.That(name, Is.EqualTo("One")); cmd.CommandText = "SELECT name FROM Test WHERE id=3"; name = cmd.ExecuteScalar(); - Assert.AreEqual("Two", name); + Assert.That(name, Is.EqualTo("Two")); Assert.Throws(() => ExecuteSQL("INSERT INTO Test (id, name2) values (5, 'Three')")); } @@ -262,7 +262,7 @@ public void FoundRows() cmd.ExecuteNonQuery(); cmd.CommandText = "SELECT FOUND_ROWS()"; object cnt = cmd.ExecuteScalar(); - Assert.AreEqual(1000, Convert.ToInt32(cnt)); + Assert.That(Convert.ToInt32(cnt), Is.EqualTo(1000)); } [Test] @@ -277,7 +277,7 @@ public void AutoIncrement() { reader.Read(); int ident = Int32.Parse(reader.GetValue(0).ToString()); - Assert.AreEqual(1, ident); + Assert.That(ident, Is.EqualTo(1)); } } @@ -312,7 +312,7 @@ public void ErrorMessage() catch (MySqlException ex) { string s = ex.Message; - Assert.False(s.StartsWith("#", StringComparison.Ordinal)); + Assert.That(s.StartsWith("#", StringComparison.Ordinal), Is.False); } } @@ -326,12 +326,12 @@ public void Describe() var reader = ExecuteReader("DESCRIBE Test"); using (reader) { - Assert.True(reader.GetFieldType(0) == typeof(string)); - Assert.True(reader.GetFieldType(1) == typeof(string)); - Assert.True(reader.GetFieldType(2) == typeof(string)); - Assert.True(reader.GetFieldType(3) == typeof(string)); - Assert.True(reader.GetFieldType(4) == typeof(string)); - Assert.True(reader.GetFieldType(5) == typeof(string)); + Assert.That(reader.GetFieldType(0) == typeof(string)); + Assert.That(reader.GetFieldType(1) == typeof(string)); + Assert.That(reader.GetFieldType(2) == typeof(string)); + Assert.That(reader.GetFieldType(3) == typeof(string)); + Assert.That(reader.GetFieldType(4) == typeof(string)); + Assert.That(reader.GetFieldType(5) == typeof(string)); } } @@ -343,7 +343,7 @@ public void ShowTableStatus() using (reader) { reader.Read(); - Assert.True(reader[0].GetType() == typeof(string)); + Assert.That(reader[0].GetType() == typeof(string)); } } @@ -355,9 +355,9 @@ public void NullAsAType() { DataTable dt = Utils.FillTable(@"SELECT 'localhost' as SERVER_NAME, null as CATALOG_NAME, database() as SCHEMA_NAME", Connection); - Assert.True(dt.Rows[0][0].GetType() == typeof(string)); - Assert.AreEqual(DBNull.Value, dt.Rows[0][1]); - Assert.True(dt.Rows[0][2].GetType() == typeof(string)); + Assert.That(dt.Rows[0][0].GetType() == typeof(string)); + Assert.That(dt.Rows[0][1], Is.EqualTo(DBNull.Value)); + Assert.That(dt.Rows[0][2].GetType() == typeof(string)); } [Test] @@ -396,9 +396,9 @@ public void ShowProcessList() } DataRow row = dt.Rows[0]; - Assert.True(row["User"].GetType().Name == "String"); - Assert.True(row["Host"].GetType().Name == "String"); - Assert.True(row["Command"].GetType().Name == "String"); + Assert.That(row["User"].GetType().Name == "String"); + Assert.That(row["Host"].GetType().Name == "String"); + Assert.That(row["Command"].GetType().Name == "String"); } } @@ -407,7 +407,7 @@ public void SemisAtStartAndEnd() { using (MySqlCommand cmd = new MySqlCommand(";;SELECT 1;;;", Connection)) { - Assert.AreEqual(1, Convert.ToInt32(cmd.ExecuteScalar())); + Assert.That(Convert.ToInt32(cmd.ExecuteScalar()), Is.EqualTo(1)); } } @@ -421,23 +421,23 @@ public void Bug51610() using (MySqlDataReader reader = cmd.ExecuteReader()) { reader.Read(); - Assert.AreEqual("ABC", reader.GetString(0)); - Assert.AreEqual(0, reader.GetInt32(1)); + Assert.That(reader.GetString(0), Is.EqualTo("ABC")); + Assert.That(reader.GetInt32(1), Is.EqualTo(0)); } cmd.CommandText = "SELECT 'ABC', (0-`QOH`) from (SELECT 1 as `QOH`) `d1`"; using (MySqlDataReader reader = cmd.ExecuteReader()) { reader.Read(); - Assert.AreEqual("ABC", reader.GetString(0)); - Assert.AreEqual(-1, reader.GetInt32(1)); + Assert.That(reader.GetString(0), Is.EqualTo("ABC")); + Assert.That(reader.GetInt32(1), Is.EqualTo(-1)); } cmd.CommandText = "SELECT 'test 2010-03-04 @ 10:14'"; using (MySqlDataReader reader = cmd.ExecuteReader()) { reader.Read(); - Assert.AreEqual("test 2010-03-04 @ 10:14", reader.GetString(0)); + Assert.That(reader.GetString(0), Is.EqualTo("test 2010-03-04 @ 10:14")); } } diff --git a/MySQL.Data/tests/MySql.Data.Tests/Syntax2.cs b/MySQL.Data/tests/MySql.Data.Tests/Syntax2.cs index 15a090262..453e707c5 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Syntax2.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Syntax2.cs @@ -58,11 +58,11 @@ public void CommentsInSQL() MySqlDataAdapter da = new MySqlDataAdapter("SELECT * FROM Test", Connection); DataTable table = new DataTable(); da.Fill(table); - Assert.AreEqual(1, table.Rows[0]["id"]); - Assert.AreEqual("Test", table.Rows[0]["name"]); - Assert.AreEqual(2, table.Rows.Count); - Assert.AreEqual(2, table.Rows[1]["id"]); - Assert.AreEqual("Test2", table.Rows[1]["name"]); + Assert.That(table.Rows[0]["id"], Is.EqualTo(1)); + Assert.That(table.Rows[0]["name"], Is.EqualTo("Test")); + Assert.That(table.Rows.Count, Is.EqualTo(2)); + Assert.That(table.Rows[1]["id"], Is.EqualTo(2)); + Assert.That(table.Rows[1]["name"], Is.EqualTo("Test2")); } [Test] @@ -71,17 +71,17 @@ public void LastInsertid() ExecuteSQL("CREATE TABLE Test(id int auto_increment, name varchar(20), primary key(id))"); MySqlCommand cmd = new MySqlCommand("INSERT INTO Test VALUES(NULL, 'test')", Connection); cmd.ExecuteNonQuery(); - Assert.AreEqual(1, cmd.LastInsertedId); + Assert.That(cmd.LastInsertedId, Is.EqualTo(1)); using (MySqlDataReader reader = cmd.ExecuteReader()) { reader.Read(); } - Assert.AreEqual(2, cmd.LastInsertedId); + Assert.That(cmd.LastInsertedId, Is.EqualTo(2)); cmd.CommandText = "SELECT id FROM Test"; cmd.ExecuteScalar(); - Assert.AreEqual(-1, cmd.LastInsertedId); + Assert.That(cmd.LastInsertedId, Is.EqualTo(-1)); } [Test] diff --git a/MySQL.Data/tests/MySql.Data.Tests/TableCaching.cs b/MySQL.Data/tests/MySql.Data.Tests/TableCaching.cs index 68eefe76b..828a75ef7 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/TableCaching.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/TableCaching.cs @@ -58,7 +58,7 @@ public void SimpleTableCaching() // now run the query again but this time it shouldn't generate a call to the database ConsumeReader(cmd); } - Assert.AreEqual(1, listener.Find("Resultset Opened: field(s) = 3")); + Assert.That(listener.Find("Resultset Opened: field(s) = 3"), Is.EqualTo(1)); } [Test] @@ -83,7 +83,7 @@ public void ConnectionStringExpiry() // since our next query is past the cache age of 1 second ConsumeReader(cmd); } - Assert.AreEqual(2, listener.Find("Resultset Opened: field(s) = 3")); + Assert.That(listener.Find("Resultset Opened: field(s) = 3"), Is.EqualTo(2)); } [Test] @@ -111,7 +111,7 @@ public void SettingAgeOnCommand() // to 20 seconds on our command ConsumeReader(cmd); } - Assert.AreEqual(1, listener.Find("Resultset Opened: field(s) = 3")); + Assert.That(listener.Find("Resultset Opened: field(s) = 3"), Is.EqualTo(1)); } private void ConsumeReader(MySqlCommand cmd) @@ -119,18 +119,18 @@ private void ConsumeReader(MySqlCommand cmd) using (MySqlDataReader reader = cmd.ExecuteReader()) { reader.Read(); - Assert.AreEqual(1, reader.GetInt32(0)); - Assert.AreEqual("boo", reader.GetString(1)); - Assert.AreEqual("hoo", reader.GetString(2)); + Assert.That(reader.GetInt32(0), Is.EqualTo(1)); + Assert.That(reader.GetString(1), Is.EqualTo("boo")); + Assert.That(reader.GetString(2), Is.EqualTo("hoo")); reader.Read(); - Assert.AreEqual(2, reader.GetInt32(0)); - Assert.AreEqual("first", reader.GetString(1)); - Assert.AreEqual("last", reader.GetString(2)); + Assert.That(reader.GetInt32(0), Is.EqualTo(2)); + Assert.That(reader.GetString(1), Is.EqualTo("first")); + Assert.That(reader.GetString(2), Is.EqualTo("last")); reader.Read(); - Assert.AreEqual(3, reader.GetInt32(0)); - Assert.AreEqual("fred", reader.GetString(1)); - Assert.AreEqual("flintstone", reader.GetString(2)); - Assert.False(reader.Read()); + Assert.That(reader.GetInt32(0), Is.EqualTo(3)); + Assert.That(reader.GetString(1), Is.EqualTo("fred")); + Assert.That(reader.GetString(2), Is.EqualTo("flintstone")); + Assert.That(reader.Read(), Is.False); } } } diff --git a/MySQL.Data/tests/MySql.Data.Tests/Tokenizer.cs b/MySQL.Data/tests/MySql.Data.Tests/Tokenizer.cs index a8a0b83f5..fcaa8b25e 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Tokenizer.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Tokenizer.cs @@ -38,11 +38,11 @@ public class Tokenizer : TestBase public void Simple() { SqlTokenizer tokenizer = new SqlTokenizer("SELECT * FROM Test"); - Assert.AreEqual("SELECT", tokenizer.NextToken()); - Assert.AreEqual("*", tokenizer.NextToken()); - Assert.AreEqual("FROM", tokenizer.NextToken()); - Assert.AreEqual("Test", tokenizer.NextToken()); - Assert.Null(tokenizer.NextToken()); + Assert.That(tokenizer.NextToken(), Is.EqualTo("SELECT")); + Assert.That(tokenizer.NextToken(), Is.EqualTo("*")); + Assert.That(tokenizer.NextToken(), Is.EqualTo("FROM")); + Assert.That(tokenizer.NextToken(), Is.EqualTo("Test")); + Assert.That(tokenizer.NextToken(), Is.Null); } [Test] @@ -52,20 +52,20 @@ public void DashSingleLineComment() string sql = String.Format("SELECT {0} * FROM Test", comment); SqlTokenizer tokenizer = new SqlTokenizer(sql); tokenizer.ReturnComments = true; - Assert.AreEqual("SELECT", tokenizer.NextToken()); - Assert.AreEqual(comment, tokenizer.NextToken()); - Assert.AreEqual("*", tokenizer.NextToken()); - Assert.AreEqual("FROM", tokenizer.NextToken()); - Assert.AreEqual("Test", tokenizer.NextToken()); - Assert.Null(tokenizer.NextToken()); + Assert.That(tokenizer.NextToken(), Is.EqualTo("SELECT")); + Assert.That(tokenizer.NextToken(), Is.EqualTo(comment)); + Assert.That(tokenizer.NextToken(), Is.EqualTo("*")); + Assert.That(tokenizer.NextToken(), Is.EqualTo("FROM")); + Assert.That(tokenizer.NextToken(), Is.EqualTo("Test")); + Assert.That(tokenizer.NextToken(), Is.Null); tokenizer = new SqlTokenizer(sql); tokenizer.ReturnComments = false; - Assert.AreEqual("SELECT", tokenizer.NextToken()); - Assert.AreEqual("*", tokenizer.NextToken()); - Assert.AreEqual("FROM", tokenizer.NextToken()); - Assert.AreEqual("Test", tokenizer.NextToken()); - Assert.Null(tokenizer.NextToken()); + Assert.That(tokenizer.NextToken(), Is.EqualTo("SELECT")); + Assert.That(tokenizer.NextToken(), Is.EqualTo("*")); + Assert.That(tokenizer.NextToken(), Is.EqualTo("FROM")); + Assert.That(tokenizer.NextToken(), Is.EqualTo("Test")); + Assert.That(tokenizer.NextToken(), Is.Null); } [Test] @@ -75,20 +75,20 @@ public void HashSingleLineComment() string sql = String.Format("SELECT {0} * FROM Test", comment); SqlTokenizer tokenizer = new SqlTokenizer(sql); tokenizer.ReturnComments = true; - Assert.AreEqual("SELECT", tokenizer.NextToken()); - Assert.AreEqual(comment, tokenizer.NextToken()); - Assert.AreEqual("*", tokenizer.NextToken()); - Assert.AreEqual("FROM", tokenizer.NextToken()); - Assert.AreEqual("Test", tokenizer.NextToken()); - Assert.Null(tokenizer.NextToken()); + Assert.That(tokenizer.NextToken(), Is.EqualTo("SELECT")); + Assert.That(tokenizer.NextToken(), Is.EqualTo(comment)); + Assert.That(tokenizer.NextToken(), Is.EqualTo("*")); + Assert.That(tokenizer.NextToken(), Is.EqualTo("FROM")); + Assert.That(tokenizer.NextToken(), Is.EqualTo("Test")); + Assert.That(tokenizer.NextToken(), Is.Null); tokenizer = new SqlTokenizer(sql); tokenizer.ReturnComments = false; - Assert.AreEqual("SELECT", tokenizer.NextToken()); - Assert.AreEqual("*", tokenizer.NextToken()); - Assert.AreEqual("FROM", tokenizer.NextToken()); - Assert.AreEqual("Test", tokenizer.NextToken()); - Assert.Null(tokenizer.NextToken()); + Assert.That(tokenizer.NextToken(), Is.EqualTo("SELECT")); + Assert.That(tokenizer.NextToken(), Is.EqualTo("*")); + Assert.That(tokenizer.NextToken(), Is.EqualTo("FROM")); + Assert.That(tokenizer.NextToken(), Is.EqualTo("Test")); + Assert.That(tokenizer.NextToken(), Is.Null); } [Test] @@ -98,20 +98,20 @@ public void MultiLineComment() string sql = String.Format("SELECT{0} * FROM Test", comment); SqlTokenizer tokenizer = new SqlTokenizer(sql); tokenizer.ReturnComments = true; - Assert.AreEqual("SELECT", tokenizer.NextToken()); - Assert.AreEqual(comment.Trim(), tokenizer.NextToken()); - Assert.AreEqual("*", tokenizer.NextToken()); - Assert.AreEqual("FROM", tokenizer.NextToken()); - Assert.AreEqual("Test", tokenizer.NextToken()); - Assert.Null(tokenizer.NextToken()); + Assert.That(tokenizer.NextToken(), Is.EqualTo("SELECT")); + Assert.That(tokenizer.NextToken(), Is.EqualTo(comment.Trim())); + Assert.That(tokenizer.NextToken(), Is.EqualTo("*")); + Assert.That(tokenizer.NextToken(), Is.EqualTo("FROM")); + Assert.That(tokenizer.NextToken(), Is.EqualTo("Test")); + Assert.That(tokenizer.NextToken(), Is.Null); tokenizer = new SqlTokenizer(sql); tokenizer.ReturnComments = false; - Assert.AreEqual("SELECT", tokenizer.NextToken()); - Assert.AreEqual("*", tokenizer.NextToken()); - Assert.AreEqual("FROM", tokenizer.NextToken()); - Assert.AreEqual("Test", tokenizer.NextToken()); - Assert.Null(tokenizer.NextToken()); + Assert.That(tokenizer.NextToken(), Is.EqualTo("SELECT")); + Assert.That(tokenizer.NextToken(), Is.EqualTo("*")); + Assert.That(tokenizer.NextToken(), Is.EqualTo("FROM")); + Assert.That(tokenizer.NextToken(), Is.EqualTo("Test")); + Assert.That(tokenizer.NextToken(), Is.Null); } [Test] @@ -120,19 +120,19 @@ public void Parameter() string sql = "SELECT * FROM Test WHERE id=@id AND id2=?id2"; SqlTokenizer tokenizer = new SqlTokenizer(sql); tokenizer.ReturnComments = true; - Assert.AreEqual("SELECT", tokenizer.NextToken()); - Assert.AreEqual("*", tokenizer.NextToken()); - Assert.AreEqual("FROM", tokenizer.NextToken()); - Assert.AreEqual("Test", tokenizer.NextToken()); - Assert.AreEqual("WHERE", tokenizer.NextToken()); - Assert.AreEqual("id", tokenizer.NextToken()); - Assert.AreEqual("=", tokenizer.NextToken()); - Assert.AreEqual("@id", tokenizer.NextToken()); - Assert.AreEqual("AND", tokenizer.NextToken()); - Assert.AreEqual("id2", tokenizer.NextToken()); - Assert.AreEqual("=", tokenizer.NextToken()); - Assert.AreEqual("?id2", tokenizer.NextToken()); - Assert.Null(tokenizer.NextToken()); + Assert.That(tokenizer.NextToken(), Is.EqualTo("SELECT")); + Assert.That(tokenizer.NextToken(), Is.EqualTo("*")); + Assert.That(tokenizer.NextToken(), Is.EqualTo("FROM")); + Assert.That(tokenizer.NextToken(), Is.EqualTo("Test")); + Assert.That(tokenizer.NextToken(), Is.EqualTo("WHERE")); + Assert.That(tokenizer.NextToken(), Is.EqualTo("id")); + Assert.That(tokenizer.NextToken(), Is.EqualTo("=")); + Assert.That(tokenizer.NextToken(), Is.EqualTo("@id")); + Assert.That(tokenizer.NextToken(), Is.EqualTo("AND")); + Assert.That(tokenizer.NextToken(), Is.EqualTo("id2")); + Assert.That(tokenizer.NextToken(), Is.EqualTo("=")); + Assert.That(tokenizer.NextToken(), Is.EqualTo("?id2")); + Assert.That(tokenizer.NextToken(), Is.Null); } [Test] @@ -141,9 +141,9 @@ public void NextParameter() string sql = "SELECT * FROM Test WHERE id=@id AND id2=?id2"; SqlTokenizer tokenizer = new SqlTokenizer(sql); tokenizer.ReturnComments = true; - Assert.AreEqual("@id", tokenizer.NextParameter()); - Assert.AreEqual("?id2", tokenizer.NextParameter()); - Assert.Null(tokenizer.NextParameter()); + Assert.That(tokenizer.NextParameter(), Is.EqualTo("@id")); + Assert.That(tokenizer.NextParameter(), Is.EqualTo("?id2")); + Assert.That(tokenizer.NextParameter(), Is.Null); } [Test] @@ -152,15 +152,15 @@ public void ParameterWithSpecialCharacters() string sql = "SELECT * FROM Test WHERE id=@id_$123"; SqlTokenizer tokenizer = new SqlTokenizer(sql); tokenizer.ReturnComments = true; - Assert.AreEqual("SELECT", tokenizer.NextToken()); - Assert.AreEqual("*", tokenizer.NextToken()); - Assert.AreEqual("FROM", tokenizer.NextToken()); - Assert.AreEqual("Test", tokenizer.NextToken()); - Assert.AreEqual("WHERE", tokenizer.NextToken()); - Assert.AreEqual("id", tokenizer.NextToken()); - Assert.AreEqual("=", tokenizer.NextToken()); - Assert.AreEqual("@id_$123", tokenizer.NextToken()); - Assert.Null(tokenizer.NextToken()); + Assert.That(tokenizer.NextToken(), Is.EqualTo("SELECT")); + Assert.That(tokenizer.NextToken(), Is.EqualTo("*")); + Assert.That(tokenizer.NextToken(), Is.EqualTo("FROM")); + Assert.That(tokenizer.NextToken(), Is.EqualTo("Test")); + Assert.That(tokenizer.NextToken(), Is.EqualTo("WHERE")); + Assert.That(tokenizer.NextToken(), Is.EqualTo("id")); + Assert.That(tokenizer.NextToken(), Is.EqualTo("=")); + Assert.That(tokenizer.NextToken(), Is.EqualTo("@id_$123")); + Assert.That(tokenizer.NextToken(), Is.Null); } [Test] @@ -169,13 +169,13 @@ public void StringLiteral() string sql = "SELECT 'a', 1, 'b'"; SqlTokenizer tokenizer = new SqlTokenizer(sql); tokenizer.ReturnComments = false; - Assert.AreEqual("SELECT", tokenizer.NextToken()); - Assert.AreEqual("'a'", tokenizer.NextToken()); - Assert.AreEqual(",", tokenizer.NextToken()); - Assert.AreEqual("1", tokenizer.NextToken()); - Assert.AreEqual(",", tokenizer.NextToken()); - Assert.AreEqual("'b'", tokenizer.NextToken()); - Assert.Null(tokenizer.NextToken()); + Assert.That(tokenizer.NextToken(), Is.EqualTo("SELECT")); + Assert.That(tokenizer.NextToken(), Is.EqualTo("'a'")); + Assert.That(tokenizer.NextToken(), Is.EqualTo(",")); + Assert.That(tokenizer.NextToken(), Is.EqualTo("1")); + Assert.That(tokenizer.NextToken(), Is.EqualTo(",")); + Assert.That(tokenizer.NextToken(), Is.EqualTo("'b'")); + Assert.That(tokenizer.NextToken(), Is.Null); } [Test] @@ -184,13 +184,13 @@ public void UserVariable() string sql = "SELECT 'a', 1, @@myVar"; SqlTokenizer tokenizer = new SqlTokenizer(sql); tokenizer.ReturnComments = false; - Assert.AreEqual("SELECT", tokenizer.NextToken()); - Assert.AreEqual("'a'", tokenizer.NextToken()); - Assert.AreEqual(",", tokenizer.NextToken()); - Assert.AreEqual("1", tokenizer.NextToken()); - Assert.AreEqual(",", tokenizer.NextToken()); - Assert.AreEqual("@@myVar", tokenizer.NextToken()); - Assert.Null(tokenizer.NextToken()); + Assert.That(tokenizer.NextToken(), Is.EqualTo("SELECT")); + Assert.That(tokenizer.NextToken(), Is.EqualTo("'a'")); + Assert.That(tokenizer.NextToken(), Is.EqualTo(",")); + Assert.That(tokenizer.NextToken(), Is.EqualTo("1")); + Assert.That(tokenizer.NextToken(), Is.EqualTo(",")); + Assert.That(tokenizer.NextToken(), Is.EqualTo("@@myVar")); + Assert.That(tokenizer.NextToken(), Is.Null); } [Test] @@ -199,16 +199,16 @@ public void AnsiQuotes() string sql = "SELECT 'a', \"a\", `a`"; SqlTokenizer tokenizer = new SqlTokenizer(sql); tokenizer.AnsiQuotes = false; - Assert.AreEqual("SELECT", tokenizer.NextToken()); - Assert.AreEqual("'a'", tokenizer.NextToken()); - Assert.True(tokenizer.Quoted); - Assert.AreEqual(",", tokenizer.NextToken()); - Assert.AreEqual("\"a\"", tokenizer.NextToken()); - Assert.True(tokenizer.Quoted); - Assert.AreEqual(",", tokenizer.NextToken()); - Assert.AreEqual("`a`", tokenizer.NextToken()); - Assert.True(tokenizer.Quoted); - Assert.Null(tokenizer.NextToken()); + Assert.That(tokenizer.NextToken(), Is.EqualTo("SELECT")); + Assert.That(tokenizer.NextToken(), Is.EqualTo("'a'")); + Assert.That(tokenizer.Quoted); + Assert.That(tokenizer.NextToken(), Is.EqualTo(",")); + Assert.That(tokenizer.NextToken(), Is.EqualTo("\"a\"")); + Assert.That(tokenizer.Quoted); + Assert.That(tokenizer.NextToken(), Is.EqualTo(",")); + Assert.That(tokenizer.NextToken(), Is.EqualTo("`a`")); + Assert.That(tokenizer.Quoted); + Assert.That(tokenizer.NextToken(), Is.Null); } [Test] @@ -217,25 +217,25 @@ public void ParseProcBody() string sql = "CREATE PROCEDURE spTest(testid INT, testname VARCHAR(20)) BEGIN SELECT 1; END"; SqlTokenizer tokenizer = new SqlTokenizer(sql); tokenizer.AnsiQuotes = false; - Assert.AreEqual("CREATE", tokenizer.NextToken()); - Assert.AreEqual("PROCEDURE", tokenizer.NextToken()); - Assert.AreEqual("spTest", tokenizer.NextToken()); - Assert.AreEqual("(", tokenizer.NextToken()); - Assert.AreEqual("testid", tokenizer.NextToken()); - Assert.AreEqual("INT", tokenizer.NextToken()); - Assert.AreEqual(",", tokenizer.NextToken()); - Assert.AreEqual("testname", tokenizer.NextToken()); - Assert.AreEqual("VARCHAR", tokenizer.NextToken()); - Assert.AreEqual("(", tokenizer.NextToken()); - Assert.AreEqual("20", tokenizer.NextToken()); - Assert.AreEqual(")", tokenizer.NextToken()); - Assert.AreEqual(")", tokenizer.NextToken()); - Assert.AreEqual("BEGIN", tokenizer.NextToken()); - Assert.AreEqual("SELECT", tokenizer.NextToken()); - Assert.AreEqual("1", tokenizer.NextToken()); - Assert.AreEqual(";", tokenizer.NextToken()); - Assert.AreEqual("END", tokenizer.NextToken()); - Assert.Null(tokenizer.NextToken()); + Assert.That(tokenizer.NextToken(), Is.EqualTo("CREATE")); + Assert.That(tokenizer.NextToken(), Is.EqualTo("PROCEDURE")); + Assert.That(tokenizer.NextToken(), Is.EqualTo("spTest")); + Assert.That(tokenizer.NextToken(), Is.EqualTo("(")); + Assert.That(tokenizer.NextToken(), Is.EqualTo("testid")); + Assert.That(tokenizer.NextToken(), Is.EqualTo("INT")); + Assert.That(tokenizer.NextToken(), Is.EqualTo(",")); + Assert.That(tokenizer.NextToken(), Is.EqualTo("testname")); + Assert.That(tokenizer.NextToken(), Is.EqualTo("VARCHAR")); + Assert.That(tokenizer.NextToken(), Is.EqualTo("(")); + Assert.That(tokenizer.NextToken(), Is.EqualTo("20")); + Assert.That(tokenizer.NextToken(), Is.EqualTo(")")); + Assert.That(tokenizer.NextToken(), Is.EqualTo(")")); + Assert.That(tokenizer.NextToken(), Is.EqualTo("BEGIN")); + Assert.That(tokenizer.NextToken(), Is.EqualTo("SELECT")); + Assert.That(tokenizer.NextToken(), Is.EqualTo("1")); + Assert.That(tokenizer.NextToken(), Is.EqualTo(";")); + Assert.That(tokenizer.NextToken(), Is.EqualTo("END")); + Assert.That(tokenizer.NextToken(), Is.Null); } /// @@ -251,13 +251,13 @@ public void NoSpaceAroundEquals() cmd.ExecuteNonQuery(); cmd.CommandText = "SELECT name FROM Test"; object o = cmd.ExecuteScalar(); - Assert.AreEqual("test -- test", o); + Assert.That(o, Is.EqualTo("test -- test")); cmd.CommandText = "UPDATE Test SET name='Can you explain this ?';"; cmd.ExecuteNonQuery(); cmd.CommandText = "SELECT name FROM Test"; o = cmd.ExecuteScalar(); - Assert.AreEqual("Can you explain this ?", o); + Assert.That(o, Is.EqualTo("Can you explain this ?")); } [Test] @@ -266,11 +266,11 @@ public void Slash() string sql = "AND // OR"; SqlTokenizer tokenizer = new SqlTokenizer(sql); tokenizer.AnsiQuotes = false; - Assert.AreEqual("AND", tokenizer.NextToken()); - Assert.AreEqual("/", tokenizer.NextToken()); - Assert.AreEqual("/", tokenizer.NextToken()); - Assert.AreEqual("OR", tokenizer.NextToken()); - Assert.Null(tokenizer.NextToken()); + Assert.That(tokenizer.NextToken(), Is.EqualTo("AND")); + Assert.That(tokenizer.NextToken(), Is.EqualTo("/")); + Assert.That(tokenizer.NextToken(), Is.EqualTo("/")); + Assert.That(tokenizer.NextToken(), Is.EqualTo("OR")); + Assert.That(tokenizer.NextToken(), Is.Null); } [Test] @@ -280,17 +280,17 @@ public void SqlServerMode() SqlTokenizer tokenizer = new SqlTokenizer(sql); tokenizer.SqlServerMode = true; tokenizer.NextToken(); - Assert.AreEqual("`a`", tokenizer.NextToken()); - Assert.True(tokenizer.Quoted); + Assert.That(tokenizer.NextToken(), Is.EqualTo("`a`")); + Assert.That(tokenizer.Quoted); tokenizer.NextToken(); // read , - Assert.AreEqual("[id]", tokenizer.NextToken()); - Assert.True(tokenizer.Quoted); + Assert.That(tokenizer.NextToken(), Is.EqualTo("[id]")); + Assert.That(tokenizer.Quoted); tokenizer.NextToken(); // read , - Assert.AreEqual("[name]", tokenizer.NextToken()); - Assert.True(tokenizer.Quoted); + Assert.That(tokenizer.NextToken(), Is.EqualTo("[name]")); + Assert.That(tokenizer.Quoted); tokenizer.NextToken(); // read FROM - Assert.AreEqual("[Test]", tokenizer.NextToken()); - Assert.True(tokenizer.Quoted); + Assert.That(tokenizer.NextToken(), Is.EqualTo("[Test]")); + Assert.That(tokenizer.Quoted); } } } diff --git a/MySQL.Data/tests/MySql.Data.Tests/Transactions.cs b/MySQL.Data/tests/MySql.Data.Tests/Transactions.cs index 665f677ed..585875433 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Transactions.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Transactions.cs @@ -57,7 +57,7 @@ void TransactionScopeInternal(bool commit) cmd.CommandText = "SELECT COUNT(*) FROM Test"; object count = cmd.ExecuteScalar(); - Assert.AreEqual(commit ? 1 : 0, Convert.ToInt32(count)); + Assert.That(Convert.ToInt32(count), Is.EqualTo(commit ? 1 : 0)); } } @@ -96,7 +96,7 @@ public void TransactionScopeWithIsolationLevel() { reader.Read(); string level = reader.GetString(1); - Assert.AreEqual("READ-COMMITTED", level); + Assert.That(level, Is.EqualTo("READ-COMMITTED")); } } } @@ -116,7 +116,7 @@ public void TransactionScopeWithIsolationLevel() { reader.Read(); string level = reader.GetString(1); - Assert.AreEqual("READ-UNCOMMITTED", level); + Assert.That(level, Is.EqualTo("READ-UNCOMMITTED")); } } } @@ -137,7 +137,7 @@ public void TransactionReadOnlyIsAvailable() { reader.Read(); if (Connection.driver.Version.isAtLeast(5, 7, 0)) - Assert.AreEqual("OFF", reader.GetString(1)); + Assert.That(reader.GetString(1), Is.EqualTo("OFF")); } } } @@ -170,7 +170,7 @@ public void RollingBackOnClose() MySqlCommand cmd2 = new MySqlCommand("SELECT COUNT(*) from Test", c2); c2.BeginTransaction(); object count = cmd2.ExecuteScalar(); - Assert.AreEqual(0, Convert.ToInt32(count)); + Assert.That(Convert.ToInt32(count), Is.EqualTo(0)); } MySqlConnection connection = new MySqlConnection(connStr); @@ -270,7 +270,7 @@ public void ManualEnlistment() ExecuteSQL("UNLOCK TABLES"); } MySqlCommand cmd2 = new MySqlCommand("LOCK TABLES test READ; SELECT COUNT(*) FROM test", c); - Assert.AreEqual(1, Convert.ToInt32(cmd2.ExecuteScalar())); + Assert.That(Convert.ToInt32(cmd2.ExecuteScalar()), Is.EqualTo(1)); ExecuteSQL("UNLOCK TABLES"); c.Dispose(); KillPooledConnection(connStr); @@ -432,8 +432,8 @@ private void NestedScopeInternalTest( ((long)MySqlHelper.ExecuteScalar(Connection, "select count(*) from T where str = 'inner'") == 1); bool outerChangesVisible = ((long)MySqlHelper.ExecuteScalar(Connection, "select count(*) from T where str = 'outer'") == 1); - Assert.AreEqual(innerChangesVisible, expectInnerChangesVisible); - Assert.AreEqual(outerChangesVisible, expectOuterChangesVisible); + Assert.That(expectInnerChangesVisible, Is.EqualTo(innerChangesVisible)); + Assert.That(expectOuterChangesVisible, Is.EqualTo(outerChangesVisible)); } finally { @@ -526,7 +526,7 @@ private void ReusingSameConnection(bool pooling, bool complete) c2.Open(); MySqlCommand cmd2 = new MySqlCommand("INSERT INTO Test (key2) VALUES ('b')", c2); cmd2.ExecuteNonQuery(); - Assert.AreEqual(c1Thread, c2.ServerThread); + Assert.That(c2.ServerThread, Is.EqualTo(c1Thread)); } if (complete) @@ -538,13 +538,13 @@ private void ReusingSameConnection(bool pooling, bool complete) da.Fill(dt); if (complete) { - Assert.AreEqual(2, dt.Rows.Count); - Assert.AreEqual("a", dt.Rows[0][0]); - Assert.AreEqual("b", dt.Rows[1][0]); + Assert.That(dt.Rows.Count, Is.EqualTo(2)); + Assert.That(dt.Rows[0][0], Is.EqualTo("a")); + Assert.That(dt.Rows[1][0], Is.EqualTo("b")); } else { - Assert.AreEqual(0, dt.Rows.Count); + Assert.That(dt.Rows.Count, Is.EqualTo(0)); } } @@ -586,7 +586,7 @@ public void ScopeTimeoutWithMySqlHelper() } } long count = (long)MySqlHelper.ExecuteScalar(connStr, "select count(*) from test"); - Assert.AreEqual(0, count); + Assert.That(count, Is.EqualTo(0)); } /// @@ -629,10 +629,10 @@ public void AttemptToUseConnectionAfterScopeTimeout() Thread.Sleep(500); Assert.Throws(() => cmd.ExecuteNonQuery()); } - Assert.True(c.State == ConnectionState.Open); + Assert.That(c.State == ConnectionState.Open); cmd.CommandText = "select count(*) from Test"; long count = (long)cmd.ExecuteScalar(); - Assert.AreEqual(0, count); + Assert.That(count, Is.EqualTo(0)); } } @@ -661,7 +661,7 @@ public void SnapshotIsolationLevelThrowsNotSupportedException() { newcon.Open(); var ex = Assert.Throws(() => newcon.BeginTransaction(System.Data.IsolationLevel.Snapshot)); - Assert.AreEqual("Snapshot isolation level is not supported.", ex.Message); + Assert.That(ex.Message, Is.EqualTo("Snapshot isolation level is not supported.")); } } @@ -706,7 +706,7 @@ public void Bug26035791() cmd2 = new MySqlCommand(@"select count(*) from TransTest", db, transaction); int.TryParse(cmd2.ExecuteScalar().ToString(), out int n1); // If ReadUncommitted is applied we should be able to read inserted record before commit - Assert.True(n1 == 2); + Assert.That(n1 == 2); transaction.Commit(); } ExecuteSQL("drop table TransTest"); @@ -716,7 +716,7 @@ public void Bug26035791() reader.Read(); finalLevel = reader.GetString(1); } - Assert.AreEqual(initialLevel, finalLevel); // Isolation level should be the same after the transaction + Assert.That(finalLevel, Is.EqualTo(initialLevel)); // Isolation level should be the same after the transaction } } @@ -766,7 +766,7 @@ public void TransactionWithAutoCommit() { connection.Open(); var transaction = connection.BeginTransaction(); - Assert.IsNotNull(transaction); + Assert.That(transaction, Is.Not.Null); var myCommand = connection.CreateCommand(); myCommand.CommandText = "INSERT INTO `Test` VALUES (1);"; var result = myCommand.ExecuteNonQuery(); diff --git a/MySQL.Data/tests/MySql.Data.Tests/UnixSockets.cs b/MySQL.Data/tests/MySql.Data.Tests/UnixSockets.cs index ce79a457a..3499e1f32 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/UnixSockets.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/UnixSockets.cs @@ -51,7 +51,7 @@ public void ConnectionTest() using (MySqlConnection conn = new MySqlConnection(unixConnectionString)) { conn.Open(); - Assert.AreEqual(ConnectionState.Open, conn.State); + Assert.That(conn.State, Is.EqualTo(ConnectionState.Open)); } } } diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/BaseTest.cs b/MySQL.Data/tests/MySqlX.Data.Tests/BaseTest.cs index 764700cf3..9f2055353 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/BaseTest.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/BaseTest.cs @@ -111,7 +111,7 @@ public virtual void BaseTearDown() if (SchemaExistsInDatabase(schema)) s.DropSchema(schemaName); schema.Session.DropSchema(schemaName); - Assert.False(SchemaExistsInDatabase(schema)); + Assert.That(SchemaExistsInDatabase(schema), Is.False); } DropUsers(); diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/BasicFindTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/BasicFindTests.cs index 6bb3b881b..d04d0e200 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/BasicFindTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/BasicFindTests.cs @@ -51,16 +51,16 @@ public void SimpleFind() new { _id = 4, title = "Book 4", pages = 50 }, }; Result r = ExecuteAddStatement(coll.Add(docs)); - Assert.AreEqual(4, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(4)); var foundDocs = ExecuteFindStatement(coll.Find("pages > 20")); - Assert.True(foundDocs.Next()); - Assert.True(foundDocs.Current["title"].ToString() == "Book 2"); - Assert.True(foundDocs.Next()); - Assert.True(foundDocs.Current["title"].ToString() == "Book 3"); - Assert.True(foundDocs.Next()); - Assert.True(foundDocs.Current["title"].ToString() == "Book 4"); - Assert.False(foundDocs.Next()); + Assert.That(foundDocs.Next()); + Assert.That(foundDocs.Current["title"].ToString() == "Book 2"); + Assert.That(foundDocs.Next()); + Assert.That(foundDocs.Current["title"].ToString() == "Book 3"); + Assert.That(foundDocs.Next()); + Assert.That(foundDocs.Current["title"].ToString() == "Book 4"); + Assert.That(foundDocs.Next(), Is.False); } [Test] @@ -75,16 +75,16 @@ public void SimpleFindWithSort() new { _id = 4, title = "Book 4", pages = 50 }, }; Result r = ExecuteAddStatement(coll.Add(docs)); - Assert.AreEqual(4, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(4)); var foundDocs = ExecuteFindStatement(coll.Find("pages > 20").Sort("pages DESC")); - Assert.True(foundDocs.Next()); - Assert.True(foundDocs.Current["title"].ToString() == "Book 4"); - Assert.True(foundDocs.Next()); - Assert.True(foundDocs.Current["title"].ToString() == "Book 3"); - Assert.True(foundDocs.Next()); - Assert.True(foundDocs.Current["title"].ToString() == "Book 2"); - Assert.False(foundDocs.Next()); + Assert.That(foundDocs.Next()); + Assert.That(foundDocs.Current["title"].ToString() == "Book 4"); + Assert.That(foundDocs.Next()); + Assert.That(foundDocs.Current["title"].ToString() == "Book 3"); + Assert.That(foundDocs.Next()); + Assert.That(foundDocs.Current["title"].ToString() == "Book 2"); + Assert.That(foundDocs.Next(), Is.False); } [Test] @@ -99,16 +99,16 @@ public void SimpleFindWithLimitAndOffset() new { _id = 4, title = "Book 4", pages = 50 }, }; Result r = ExecuteAddStatement(coll.Add(docs)); - Assert.AreEqual(4, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(4)); var foundDocs = ExecuteFindStatement(coll.Find("pages > 20").Limit(1)); - Assert.True(foundDocs.Next()); - Assert.True(foundDocs.Current["title"].ToString() == "Book 2"); - Assert.False(foundDocs.Next()); + Assert.That(foundDocs.Next()); + Assert.That(foundDocs.Current["title"].ToString() == "Book 2"); + Assert.That(foundDocs.Next(), Is.False); var resultDocs = ExecuteFindStatement(coll.Find("pages > 20").Offset(1).Limit(2)).FetchAll(); - Assert.AreEqual(40, resultDocs[0]["pages"]); - Assert.AreEqual(50, resultDocs[1]["pages"]); + Assert.That(resultDocs[0]["pages"], Is.EqualTo(40)); + Assert.That(resultDocs[1]["pages"], Is.EqualTo(50)); // Limit out of range. Assert.Throws(() => ExecuteFindStatement(coll.Find().Limit(0))); @@ -127,12 +127,12 @@ public void FindConditional() new { _id = 4, title = "Book 4", pages = 50 }, }; Result r = ExecuteAddStatement(coll.Add(docs)); - Assert.AreEqual(4, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(4)); var foundDocs = ExecuteFindStatement(coll.Find("pages = :Pages").Bind("pAges", 40)); - Assert.True(foundDocs.Next()); - Assert.True(foundDocs.Current["title"].ToString() == "Book 3"); - Assert.False(foundDocs.Next()); + Assert.That(foundDocs.Next()); + Assert.That(foundDocs.Current["title"].ToString() == "Book 3"); + Assert.That(foundDocs.Next(), Is.False); } [Test] @@ -147,15 +147,15 @@ public void BindDbDoc() new { _id = 4, title = "Book 4", pages = 50 }, }; Result r = ExecuteAddStatement(coll.Add(docs)); - Assert.AreEqual(4, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(4)); DbDoc docParams = new DbDoc(new { pages1 = 30, pages2 = 40 }); var foundDocs = ExecuteFindStatement(coll.Find("pages = :Pages1 || pages = :Pages2").Bind(docParams)); - Assert.True(foundDocs.Next()); - Assert.AreEqual("Book 2", foundDocs.Current["title"]); - Assert.True(foundDocs.Next()); - Assert.AreEqual("Book 3", foundDocs.Current["title"]); - Assert.False(foundDocs.Next()); + Assert.That(foundDocs.Next()); + Assert.That(foundDocs.Current["title"], Is.EqualTo("Book 2")); + Assert.That(foundDocs.Next()); + Assert.That(foundDocs.Current["title"], Is.EqualTo("Book 3")); + Assert.That(foundDocs.Next(), Is.False); } [Test] @@ -170,15 +170,15 @@ public void BindJsonAsAnonymous() new { _id = 4, title = "Book 4", pages = 50 }, }; Result r = ExecuteAddStatement(coll.Add(docs)); - Assert.AreEqual(4, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(4)); var jsonParams = new { pages1 = 30, pages2 = 40 }; var foundDocs = ExecuteFindStatement(coll.Find("pages = :Pages1 || pages = :Pages2").Bind(jsonParams)); - Assert.True(foundDocs.Next()); - Assert.AreEqual("Book 2", foundDocs.Current["title"]); - Assert.True(foundDocs.Next()); - Assert.AreEqual("Book 3", foundDocs.Current["title"]); - Assert.False(foundDocs.Next()); + Assert.That(foundDocs.Next()); + Assert.That(foundDocs.Current["title"], Is.EqualTo("Book 2")); + Assert.That(foundDocs.Next()); + Assert.That(foundDocs.Current["title"], Is.EqualTo("Book 3")); + Assert.That(foundDocs.Next(), Is.False); } [Test] @@ -193,15 +193,15 @@ public void BindJsonAsString() new { _id = 4, title = "Book 4", pages = 50 }, }; Result r = ExecuteAddStatement(coll.Add(docs)); - Assert.AreEqual(4, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(4)); var jsonParams = "{ \"pages1\" : 30, \"pages2\" : 40 }"; var foundDocs = ExecuteFindStatement(coll.Find("pages = :Pages1 || pages = :Pages2").Bind(jsonParams)); - Assert.True(foundDocs.Next()); - Assert.AreEqual("Book 2", foundDocs.Current["title"]); - Assert.True(foundDocs.Next()); - Assert.AreEqual("Book 3", foundDocs.Current["title"]); - Assert.False(foundDocs.Next()); + Assert.That(foundDocs.Next()); + Assert.That(foundDocs.Current["title"], Is.EqualTo("Book 2")); + Assert.That(foundDocs.Next()); + Assert.That(foundDocs.Current["title"], Is.EqualTo("Book 3")); + Assert.That(foundDocs.Next(), Is.False); } [Test] @@ -211,10 +211,10 @@ public void RowLockingNotSupportedInOlderVersions() Collection coll = CreateCollection("test"); Exception ex = Assert.Throws(() => ExecuteFindStatement(coll.Find().LockShared())); - Assert.AreEqual("This functionality is only supported from server version 8.0.3 onwards.", ex.Message); + Assert.That(ex.Message, Is.EqualTo("This functionality is only supported from server version 8.0.3 onwards.")); ex = Assert.Throws(() => ExecuteFindStatement(coll.Find().LockExclusive())); - Assert.AreEqual("This functionality is only supported from server version 8.0.3 onwards.", ex.Message); + Assert.That(ex.Message, Is.EqualTo("This functionality is only supported from server version 8.0.3 onwards.")); } [Test] @@ -283,11 +283,11 @@ public void SharedLockForbidsToModifyDocuments() // Modify() is allowed for non-locked documents. Result result = ExecuteModifyStatement(coll2.Modify("_id = 2").Set("a", 2)); - Assert.AreEqual(1, result.AffectedItemsCount); + Assert.That(result.AffectedItemsCount, Is.EqualTo(1)); // Session1 blocks, Modify() is not allowed for locked documents. ExecuteSQLStatement(session2.SQL("SET SESSION innodb_lock_wait_timeout=1")); Exception ex = Assert.Throws(() => ExecuteModifyStatement(coll2.Modify("_id = 1").Set("a", 2))); - Assert.AreEqual("Lock wait timeout exceeded; try restarting transaction", ex.Message); + Assert.That(ex.Message, Is.EqualTo("Lock wait timeout exceeded; try restarting transaction")); ExecuteSQLStatement(session.SQL("ROLLBACK")); // Modify() is allowed since document isn't locked anymore. @@ -323,13 +323,13 @@ public void ExclusiveLockForbidsToModifyDocuments() // Modify() is allowed for non-locked documents. Result result = ExecuteModifyStatement(coll2.Modify("_id = 2").Set("a", 2)); - Assert.AreEqual(1, result.AffectedItemsCount); + Assert.That(result.AffectedItemsCount, Is.EqualTo(1)); // Session2 blocks, Modify() is not allowed for locked documents. ExecuteSQLStatement(session2.SQL("SET SESSION innodb_lock_wait_timeout=1")); Exception ex = Assert.Throws(() => ExecuteModifyStatement(coll2.Modify("_id = 1").Set("a", 2))); - Assert.AreEqual("Lock wait timeout exceeded; try restarting transaction", ex.Message); + Assert.That(ex.Message, Is.EqualTo("Lock wait timeout exceeded; try restarting transaction")); ex = Assert.Throws(() => ExecuteModifyStatement(coll2.Modify("_id = 1").Change("a", 12))); - Assert.AreEqual("Lock wait timeout exceeded; try restarting transaction", ex.Message); + Assert.That(ex.Message, Is.EqualTo("Lock wait timeout exceeded; try restarting transaction")); ExecuteSQLStatement(session.SQL("ROLLBACK")); // Modify() is allowed since document isn't locked anymore. @@ -369,7 +369,7 @@ public void SharedLockAfterExclusiveLock() // Session2 blocks due to LockExclusive() not allowing to read locked documents. ExecuteSQLStatement(session2.SQL("SET SESSION innodb_lock_wait_timeout=1")); Exception ex = Assert.Throws(() => ExecuteFindStatement(coll2.Find("_id = 1").LockShared())); - Assert.AreEqual("Lock wait timeout exceeded; try restarting transaction", ex.Message); + Assert.That(ex.Message, Is.EqualTo("Lock wait timeout exceeded; try restarting transaction")); // Session unlocks documents. ExecuteSQLStatement(session.SQL("ROLLBACK")); @@ -402,7 +402,7 @@ public void ExclusiveLockAfterSharedLock() ExecuteSQLStatement(session.SQL("START TRANSACTION")); var docResult = ExecuteFindStatement(coll.Find("_id in (1, 3)").LockShared()); - Assert.AreEqual(2, docResult.FetchAll().Count); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(2)); ExecuteSQLStatement(session2.SQL("START TRANSACTION")); // Should return immediately since document isn't locked. @@ -413,7 +413,7 @@ public void ExclusiveLockAfterSharedLock() // Session2 blocks due to to LockExclusive() not allowing to read locked documents. ExecuteSQLStatement(session2.SQL("SET SESSION innodb_lock_wait_timeout=1")); Exception ex = Assert.Throws(() => ExecuteFindStatement(coll2.Find("_id = 1").LockExclusive())); - Assert.AreEqual("Lock wait timeout exceeded; try restarting transaction", ex.Message); + Assert.That(ex.Message, Is.EqualTo("Lock wait timeout exceeded; try restarting transaction")); // Session unlocks documents. ExecuteSQLStatement(session.SQL("ROLLBACK")); @@ -454,7 +454,7 @@ public void ExclusiveLockAfterExclusiveLock() // Session2 blocks due to to LockExclusive() not allowing to read locked documents. ExecuteSQLStatement(session2.SQL("SET SESSION innodb_lock_wait_timeout=1")); Exception ex = Assert.Throws(() => ExecuteFindStatement(coll2.Find("_id = 1").LockExclusive())); - Assert.AreEqual("Lock wait timeout exceeded; try restarting transaction", ex.Message); + Assert.That(ex.Message, Is.EqualTo("Lock wait timeout exceeded; try restarting transaction")); // Session unlocks documents. ExecuteSQLStatement(session.SQL("ROLLBACK")); @@ -481,13 +481,13 @@ public void InOperatorWithListOfValues() Assert.That(ExecuteFindStatement(coll.Find("b[0] NOT IN (0,2,3)")).FetchAll(), Has.One.Items); Assert.That(ExecuteFindStatement(coll.Find("b[1] not in (\"a\", \"b\", \"c\")")).FetchAll(), Has.One.Items); Assert.That(ExecuteFindStatement(coll.Find("a in [1,2,3]")).FetchAll(), Has.One.Items); - CollectionAssert.IsEmpty(ExecuteFindStatement(coll.Find("a in [2,3,4]")).FetchAll()); + Assert.That(ExecuteFindStatement(coll.Find("a in [2,3,4]")).FetchAll(), Is.Empty); Assert.That(ExecuteFindStatement(coll.Find("a NOT in [0,2,3]")).FetchAll(), Has.One.Items); Assert.That(ExecuteFindStatement(coll.Find("b not IN [1,2,3]")).FetchAll(), Has.One.Items); - CollectionAssert.IsEmpty(ExecuteFindStatement(coll.Find("b[0] not IN [1,2,3]")).FetchAll()); - CollectionAssert.IsEmpty(ExecuteFindStatement(coll.Find("c NOT IN [1,2,3]")).FetchAll()); - CollectionAssert.IsEmpty(ExecuteFindStatement(coll.Find("a IN ('', ' ')")).FetchAll()); - CollectionAssert.IsEmpty(ExecuteFindStatement(coll.Find("'' IN (1,2,3)")).FetchAll()); + Assert.That(ExecuteFindStatement(coll.Find("b[0] not IN [1,2,3]")).FetchAll(), Is.Empty); + Assert.That(ExecuteFindStatement(coll.Find("c NOT IN [1,2,3]")).FetchAll(), Is.Empty); + Assert.That(ExecuteFindStatement(coll.Find("a IN ('', ' ')")).FetchAll(), Is.Empty); + Assert.That(ExecuteFindStatement(coll.Find("'' IN (1,2,3)")).FetchAll(), Is.Empty); Assert.That(ExecuteFindStatement(coll.Find("d IN ('')")).FetchAll(), Has.One.Items); Collection movies = CreateCollection("movies"); @@ -495,28 +495,28 @@ public void InOperatorWithListOfValues() ExecuteAddStatement(movies.Add(new DbDoc(docString))); Assert.That(ExecuteFindStatement(movies.Find("(1>5) in (true, false)")).FetchAll(), Has.One.Items); - CollectionAssert.IsEmpty(ExecuteFindStatement(movies.Find("(1+5) in (1, 2, 3, 4, 5)")).FetchAll()); + Assert.That(ExecuteFindStatement(movies.Find("(1+5) in (1, 2, 3, 4, 5)")).FetchAll(), Is.Empty); Assert.That(ExecuteFindStatement(movies.Find("('a'>'b') in (true, false)")).FetchAll(), Has.One.Items); Assert.Throws(() => ExecuteFindStatement(movies.Find("(1>5) in [true, false]")).FetchAll()); Assert.Throws(() => ExecuteFindStatement(movies.Find("(1+5) in [1, 2, 3, 4, 5]")).FetchAll()); Assert.Throws(() => ExecuteFindStatement(movies.Find("('a'>'b') in [true, false]")).FetchAll()); Assert.That(ExecuteFindStatement(movies.Find("true IN [(1>5), !(false), (true || false), (false && true)]")).FetchAll(), Has.One.Items); Assert.That(ExecuteFindStatement(movies.Find("true IN ((1>5), !(false), (true || false), (false && true))")).FetchAll(), Has.One.Items); - CollectionAssert.IsEmpty(ExecuteFindStatement(movies.Find("{\"field\":true} IN (\"mystring\", 124, myvar, othervar.jsonobj)")).FetchAll()); - CollectionAssert.IsEmpty(ExecuteFindStatement(movies.Find("actor.name IN ['a name', null, (1<5-4), myvar.jsonobj.name]")).FetchAll()); + Assert.That(ExecuteFindStatement(movies.Find("{\"field\":true} IN (\"mystring\", 124, myvar, othervar.jsonobj)")).FetchAll(), Is.Empty); + Assert.That(ExecuteFindStatement(movies.Find("actor.name IN ['a name', null, (1<5-4), myvar.jsonobj.name]")).FetchAll(), Is.Empty); Assert.That(ExecuteFindStatement(movies.Find("!false && true IN [true]")).FetchAll(), Has.One.Items); Assert.Throws(() => ExecuteFindStatement(movies.Find("1-5/2*2 > 3-2/1*2 IN [true, false]")).FetchAll()); - CollectionAssert.IsEmpty(ExecuteFindStatement(movies.Find("true IN [1-5/2*2 > 3-2/1*2]")).FetchAll()); + Assert.That(ExecuteFindStatement(movies.Find("true IN [1-5/2*2 > 3-2/1*2]")).FetchAll(), Is.Empty); Assert.That(ExecuteFindStatement(movies.Find(" 'African Egg' IN ('African Egg', 1, true, NULL, [0,1,2], { 'title' : 'Atomic Firefighter' }) ")).FetchAll(), Has.One.Items); Assert.That(ExecuteFindStatement(movies.Find(" 1 IN ('African Egg', 1, true, NULL, [0,1,2], { 'title' : 'Atomic Firefighter' }) ")).FetchAll(), Has.One.Items); Assert.That(ExecuteFindStatement(movies.Find(" [0,1,2] IN ('African Egg', 1, true, NULL, [0,1,2], { 'title' : 'Atomic Firefighter' }) ")).FetchAll(), Has.One.Items); Assert.That(ExecuteFindStatement(movies.Find(" { 'title' : 'Atomic Firefighter' } IN ('African Egg', 1, true, NULL, [0,1,2], { 'title' : 'Atomic Firefighter' }) ")).FetchAll(), Has.One.Items); - CollectionAssert.IsEmpty(ExecuteFindStatement(movies.Find("title IN ('African Egg', 'The Witcher', 'Jurassic Perk')")).FetchAll()); + Assert.That(ExecuteFindStatement(movies.Find("title IN ('African Egg', 'The Witcher', 'Jurassic Perk')")).FetchAll(), Is.Empty); Assert.That(ExecuteFindStatement(movies.Find("releaseyear IN (2006, 2010, 2017)")).FetchAll(), Has.One.Items); Assert.That(ExecuteFindStatement(movies.Find("1 IN [1,2,3]")).FetchAll(), Has.One.Items); - CollectionAssert.IsEmpty(ExecuteFindStatement(movies.Find("0 IN [1,2,3]")).FetchAll()); + Assert.That(ExecuteFindStatement(movies.Find("0 IN [1,2,3]")).FetchAll(), Is.Empty); Assert.That(ExecuteFindStatement(movies.Find("0 NOT IN [1,2,3]")).FetchAll(), Has.One.Items); - CollectionAssert.IsEmpty(ExecuteFindStatement(movies.Find("1 NOT IN [1,2,3]")).FetchAll()); + Assert.That(ExecuteFindStatement(movies.Find("1 NOT IN [1,2,3]")).FetchAll(), Is.Empty); Assert.That(ExecuteFindStatement(movies.Find("releaseyear IN [2006, 2007, 2008]")).FetchAll(), Has.One.Items); } @@ -534,10 +534,10 @@ public void InOperatorWithCompExpr() Assert.That(ExecuteFindStatement(coll.Find("c.e[0] in [1,2,3]")).FetchAll(), Has.One.Items); Assert.That(ExecuteFindStatement(coll.Find("5 in f[*].x")).FetchAll(), Has.One.Items); Assert.That(ExecuteFindStatement(coll.Find("3 in c.e")).FetchAll(), Has.One.Items); - CollectionAssert.IsEmpty(ExecuteFindStatement(coll.Find("5 in c.e")).FetchAll()); - CollectionAssert.IsEmpty(ExecuteFindStatement(coll.Find("\"foo\" in " + docString)).FetchAll()); - CollectionAssert.IsEmpty(ExecuteFindStatement(coll.Find("\"a\" in " + docString)).FetchAll()); - CollectionAssert.IsEmpty(ExecuteFindStatement(coll.Find("a in " + docString)).FetchAll()); + Assert.That(ExecuteFindStatement(coll.Find("5 in c.e")).FetchAll(), Is.Empty); + Assert.That(ExecuteFindStatement(coll.Find("\"foo\" in " + docString)).FetchAll(), Is.Empty); + Assert.That(ExecuteFindStatement(coll.Find("\"a\" in " + docString)).FetchAll(), Is.Empty); + Assert.That(ExecuteFindStatement(coll.Find("a in " + docString)).FetchAll(), Is.Empty); Assert.That(ExecuteFindStatement(coll.Find("{\"a\":1} in " + docString)).FetchAll(), Has.One.Items); Assert.That(ExecuteFindStatement(coll.Find("\"foo\" in b")).FetchAll(), Has.One.Items); @@ -546,13 +546,13 @@ public void InOperatorWithCompExpr() ExecuteAddStatement(movies.Add(new DbDoc(docString))); Assert.That(ExecuteFindStatement(movies.Find("{ \"name\" : \"MILLA PECK\" } IN actors")).FetchAll(), Has.One.Items); - CollectionAssert.IsEmpty(ExecuteFindStatement(movies.Find("'African Egg' in movietitle")).FetchAll()); + Assert.That(ExecuteFindStatement(movies.Find("'African Egg' in movietitle")).FetchAll(), Is.Empty); Assert.Throws(() => ExecuteFindStatement(movies.Find("(1 = NULL) IN title")).FetchAll()); Assert.Throws(() => ExecuteFindStatement(movies.Find("NOT NULL IN title")).FetchAll()); Assert.That(ExecuteFindStatement(movies.Find("[\"Rusty Couturier\", \"Angelic Orduno\", \"Carin Postell\"] IN additionalinfo.writers")).FetchAll(), Has.One.Items); Assert.That(ExecuteFindStatement(movies.Find("{ \"name\" : \"MILLA PECK\", \"country\" : \"Mexico\", \"birthdate\": \"12 Jan 1984\"} IN actors")).FetchAll(), Has.One.Items); - CollectionAssert.IsEmpty(ExecuteFindStatement(movies.Find("true IN title")).FetchAll()); - CollectionAssert.IsEmpty(ExecuteFindStatement(movies.Find("false IN genre")).FetchAll()); + Assert.That(ExecuteFindStatement(movies.Find("true IN title")).FetchAll(), Is.Empty); + Assert.That(ExecuteFindStatement(movies.Find("false IN genre")).FetchAll(), Is.Empty); Assert.That(ExecuteFindStatement(movies.Find("'Sharice Legaspi' IN additionalinfo.director")).FetchAll(), Has.One.Items); Assert.That(ExecuteFindStatement(movies.Find("'Mexico' IN actors[*].country")).FetchAll(), Has.One.Items); Assert.That(ExecuteFindStatement(movies.Find("'Angelic Orduno' IN additionalinfo.writers")).FetchAll(), Has.One.Items); @@ -568,7 +568,7 @@ public void InOperatorWithJsonArrays() ExecuteAddStatement(coll.Add(new DbDoc(docString))); Assert.That(ExecuteFindStatement(coll.Find("\"1001\" in $._id")).FetchAll(), Has.One.Items); - CollectionAssert.IsEmpty(ExecuteFindStatement(coll.Find("\"1002\" in $._id")).FetchAll()); + Assert.That(ExecuteFindStatement(coll.Find("\"1002\" in $._id")).FetchAll(), Is.Empty); Assert.That(ExecuteFindStatement(coll.Find("(1+2) in (1, 2, 3)")).FetchAll(), Has.One.Items); Assert.Throws(() => ExecuteFindStatement(coll.Find("(1+2) in [1, 2, 3]")).FetchAll()); Assert.Throws(() => ExecuteFindStatement(coll.Find("(1+2) in $.ARR")).FetchAll()); @@ -586,7 +586,7 @@ public void GetOne() new { _id = 4, title = "Book 4", pages = 50 }, }; Result r = ExecuteAddStatement(coll.Add(docs)); - Assert.AreEqual(4, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(4)); // Expected exceptions. Assert.Throws(() => coll.GetOne(null)); @@ -595,19 +595,19 @@ public void GetOne() // Get document using numeric parameter. DbDoc document = coll.GetOne(1); - Assert.AreEqual(1, document.Id); - Assert.AreEqual("Book 1", document["title"]); - Assert.AreEqual(20, Convert.ToInt32(document["pages"])); + Assert.That(document.Id, Is.EqualTo(1)); + Assert.That(document["title"], Is.EqualTo("Book 1")); + Assert.That(Convert.ToInt32(document["pages"]), Is.EqualTo(20)); // Get document using string parameter. document = coll.GetOne("3"); - Assert.AreEqual(3, document.Id); - Assert.AreEqual("Book 3", document["title"]); - Assert.AreEqual(40, Convert.ToInt32(document["pages"])); + Assert.That(document.Id, Is.EqualTo(3)); + Assert.That(document["title"], Is.EqualTo("Book 3")); + Assert.That(Convert.ToInt32(document["pages"]), Is.EqualTo(40)); // Get a non-existing document. document = coll.GetOne(5); - Assert.Null(document); + Assert.That(document, Is.Null); } public enum LockMode { Exclusive, Shared } @@ -650,7 +650,7 @@ public void LockExclusiveAndSharedWithWaitingOptions(LockContention lockOption, { case LockContention.Default: // error 1205 Lock wait timeout exceeded; try restarting transaction - Assert.AreEqual(1205u, Assert.Throws(() => ExecuteFindStatement(stmt2).FetchAll()).Code); + Assert.That(Assert.Throws(() => ExecuteFindStatement(stmt2).FetchAll()).Code, Is.EqualTo(1205u)); break; case LockContention.NoWait: // error 1205 Lock wait timeout exceeded; try restarting transaction @@ -658,16 +658,16 @@ public void LockExclusiveAndSharedWithWaitingOptions(LockContention lockOption, if (session.XSession.GetServerVersion().isAtLeast(8, 0, 5)) // error 3572 Statement aborted because lock(s) could not be acquired immediately and NOWAIT is set expectedError = 3572; - Assert.AreEqual(expectedError, Assert.Throws(() => ExecuteFindStatement(stmt2).FetchAll()).Code); + Assert.That(Assert.Throws(() => ExecuteFindStatement(stmt2).FetchAll()).Code, Is.EqualTo(expectedError)); break; case LockContention.SkipLocked: if (!session.XSession.GetServerVersion().isAtLeast(8, 0, 5)) { // error 1205 Lock wait timeout exceeded; try restarting transaction - Assert.AreEqual(1205u, Assert.Throws(() => ExecuteFindStatement(stmt2).FetchAll()).Code); + Assert.That(Assert.Throws(() => ExecuteFindStatement(stmt2).FetchAll()).Code, Is.EqualTo(1205u)); break; } - CollectionAssert.IsEmpty(ExecuteFindStatement(stmt2).FetchAll()); + Assert.That(ExecuteFindStatement(stmt2).FetchAll(), Is.Empty); break; default: throw new NotImplementedException(lockOption.ToString()); @@ -694,56 +694,56 @@ public void Grouping() new { _id = 7, name = "elizabeth olsen", age = 31} }; Result r = ExecuteAddStatement(collection.Add(docs)); - Assert.AreEqual(7, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(7)); // GroupBy operation. // GroupBy returns 5 rows since age 45 and 24 is repeated. var result = ExecuteFindStatement(collection.Find().Fields("_id as ID", "name as Name", "age as Age").GroupBy("age")); - Assert.AreEqual(5, result.FetchAll().Count); + Assert.That(result.FetchAll().Count, Is.EqualTo(5)); // GroupBy with null. result = ExecuteFindStatement(collection.Find().Fields("_id as ID", "name as Name", "age as Age").GroupBy(null)); - Assert.AreEqual(7, result.FetchAll().Count); + Assert.That(result.FetchAll().Count, Is.EqualTo(7)); result = ExecuteFindStatement(collection.Find().Fields("_id as ID", "name as Name", "age as Age").GroupBy(null, null)); - Assert.AreEqual(7, result.FetchAll().Count); + Assert.That(result.FetchAll().Count, Is.EqualTo(7)); result = ExecuteFindStatement(collection.Find().Fields("_id as ID", "name as Name", "age as Age").GroupBy(null, "age")); - Assert.AreEqual(5, result.FetchAll().Count); + Assert.That(result.FetchAll().Count, Is.EqualTo(5)); // Having operation. // Having reduces the original 5 rows to 3 since 2 rows have a cnt=2, due to the repeated names. result = ExecuteFindStatement(collection.Find().Fields("_id as ID", "count(name) as cnt", "age as Age").GroupBy("age").Having("cnt = 1")); - Assert.AreEqual(3, result.FetchAll().Count); + Assert.That(result.FetchAll().Count, Is.EqualTo(3)); // Having with null. result = ExecuteFindStatement(collection.Find().Fields("_id as ID", "count(name) as cnt", "age as Age").GroupBy("age").Having(null)); - Assert.AreEqual(5, result.FetchAll().Count); + Assert.That(result.FetchAll().Count, Is.EqualTo(5)); // GroupBy with invalid field name. var ex = Assert.Throws(() => ExecuteFindStatement(collection.Find().Fields("_id as ID", "name as Name", "age as Age").GroupBy("none"))); - Assert.AreEqual("Unknown column 'none' in 'group statement'", ex.Message); + Assert.That(ex.Message, Is.EqualTo("Unknown column 'none' in 'group statement'")); // GroupBy with empty strings. var ex2 = Assert.Throws(() => ExecuteFindStatement(collection.Find().Fields("_id as ID", "name as Name", "age as Age").GroupBy(""))); - Assert.AreEqual("No more tokens when expecting one at token pos 0", ex2.Message); + Assert.That(ex2.Message, Is.EqualTo("No more tokens when expecting one at token pos 0")); ex2 = Assert.Throws(() => ExecuteFindStatement(collection.Find().Fields("_id as ID", "name as Name", "age as Age").GroupBy(" "))); - Assert.AreEqual("No more tokens when expecting one at token pos 0", ex2.Message); + Assert.That(ex2.Message, Is.EqualTo("No more tokens when expecting one at token pos 0")); ex2 = Assert.Throws(() => ExecuteFindStatement(collection.Find().Fields("_id as ID", "name as Name", "age as Age").GroupBy(string.Empty))); - Assert.AreEqual("No more tokens when expecting one at token pos 0", ex2.Message); + Assert.That(ex2.Message, Is.EqualTo("No more tokens when expecting one at token pos 0")); // Having with invalid field name. ex = Assert.Throws(() => ExecuteFindStatement(collection.Find().Fields("_id as ID", "count(name) as cnt", "age as Age").GroupBy("age").Having("none = 1"))); - Assert.AreEqual("Invalid expression in grouping criteria", ex.Message); + Assert.That(ex.Message, Is.EqualTo("Invalid expression in grouping criteria")); // Having with empty strings. ex2 = Assert.Throws(() => ExecuteFindStatement(collection.Find().Fields("_id as ID", "count(name) as cnt", "age as Age").GroupBy("age").Having(""))); - Assert.AreEqual("Unable to parse query ''", ex2.Message); - Assert.AreEqual("No more tokens when expecting one at token pos 0", ex2.InnerException.Message); + Assert.That(ex2.Message, Is.EqualTo("Unable to parse query ''")); + Assert.That(ex2.InnerException.Message, Is.EqualTo("No more tokens when expecting one at token pos 0")); ex2 = Assert.Throws(() => ExecuteFindStatement(collection.Find().Fields("_id as ID", "count(name) as cnt", "age as Age").GroupBy("age").Having(" "))); - Assert.AreEqual("Unable to parse query ' '", ex2.Message); - Assert.AreEqual("No more tokens when expecting one at token pos 0", ex2.InnerException.Message); + Assert.That(ex2.Message, Is.EqualTo("Unable to parse query ' '")); + Assert.That(ex2.InnerException.Message, Is.EqualTo("No more tokens when expecting one at token pos 0")); ex2 = Assert.Throws(() => ExecuteFindStatement(collection.Find().Fields("_id as ID", "count(name) as cnt", "age as Age").GroupBy("age").Having(string.Empty))); - Assert.AreEqual("Unable to parse query ''", ex2.Message); - Assert.AreEqual("No more tokens when expecting one at token pos 0", ex2.InnerException.Message); + Assert.That(ex2.Message, Is.EqualTo("Unable to parse query ''")); + Assert.That(ex2.InnerException.Message, Is.EqualTo("No more tokens when expecting one at token pos 0")); } [Test] @@ -758,18 +758,18 @@ public void Fields() new { _id = 4, title = "Book 4", pages = 50 }, }; Result r = ExecuteAddStatement(coll.Add(docs)); - Assert.AreEqual(4ul, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(4ul)); // Single field. var result = ExecuteFindStatement(coll.Find("pages = :Pages").Bind("pAges", 40).Fields("title")); var document = result.FetchOne(); Assert.That(document.values, Has.One.Items); - Assert.AreEqual("Book 3", document["title"]); + Assert.That(document["title"], Is.EqualTo("Book 3")); // Null values are ignored. result = ExecuteFindStatement(coll.Find("pages = :Pages").Bind("pAges", 40).Fields(null)); document = result.FetchOne(); - Assert.AreEqual(3, document.values.Count); + Assert.That(document.values.Count, Is.EqualTo(3)); // Null values are ignored. result = ExecuteFindStatement(coll.Find("pages = :Pages").Bind("pAges", 40).Fields("title", null)); @@ -780,41 +780,41 @@ public void Fields() result = ExecuteFindStatement(coll.Find("pages = :Pages").Bind("pAges", 40).Fields(new string[] { "title" })); document = result.FetchOne(); Assert.That(document.values, Has.One.Items); - Assert.AreEqual("Book 3", document["title"]); + Assert.That(document["title"], Is.EqualTo("Book 3")); // Single field with alias. result = ExecuteFindStatement(coll.Find("pages = :Pages").Bind("pages", 20).Fields("title as title2")); document = result.FetchOne(); Assert.That(document.values, Has.One.Items); - Assert.AreEqual("Book 1", document["title2"]); - Assert.False(document.values.ContainsKey("title")); + Assert.That(document["title2"], Is.EqualTo("Book 1")); + Assert.That(document.values.ContainsKey("title"), Is.False); // Unexistent field returns null. result = ExecuteFindStatement(coll.Find("pages = :Pages").Bind("pages", 20).Fields("book")); document = result.FetchOne(); Assert.That(document.values, Has.One.Items); - Assert.Null(document["book"]); + Assert.That(document["book"], Is.Null); // Unexistent field with alias returns null. result = ExecuteFindStatement(coll.Find("pages = :Pages").Bind("pages", 20).Fields("book as book1")); document = result.FetchOne(); Assert.That(document.values, Has.One.Items); - Assert.Null(document["book1"]); + Assert.That(document["book1"], Is.Null); // Multiple fields. result = ExecuteFindStatement(coll.Find("pages = :Pages").Bind("pAges", 40).Fields("title", "pages", "other")); document = result.FetchOne(); - Assert.AreEqual(3, document.values.Count); - Assert.AreEqual("Book 3", document["title"]); - Assert.AreEqual(40, document["pages"]); - Assert.Null(document["other"]); + Assert.That(document.values.Count, Is.EqualTo(3)); + Assert.That(document["title"], Is.EqualTo("Book 3")); + Assert.That(document["pages"], Is.EqualTo(40)); + Assert.That(document["other"], Is.Null); // Multiple fields in array. result = ExecuteFindStatement(coll.Find("pages = :Pages").Bind("pAges", 40).Fields(new string[] { "title", "pages" })); document = result.FetchOne(); - Assert.AreEqual(2, document.values.Count); - Assert.AreEqual("Book 3", document["title"]); - Assert.AreEqual(40, document["pages"]); + Assert.That(document.values.Count, Is.EqualTo(2)); + Assert.That(document["title"], Is.EqualTo("Book 3")); + Assert.That(document["pages"], Is.EqualTo(40)); // Sending a document doesn't generate an error. result = ExecuteFindStatement(coll.Find("pages = :Pages").Bind("pages", 20).Fields("{\"_id\":\"1004\",\"F1\": 1234 }")); @@ -822,15 +822,15 @@ public void Fields() // Empty string and white space raises error. var ex = Assert.Throws(() => ExecuteFindStatement(coll.Find("pages = :Pages").Bind("pAges", 40).Fields(""))); - Assert.AreEqual("No more tokens when expecting one at token pos 0", ex.Message); + Assert.That(ex.Message, Is.EqualTo("No more tokens when expecting one at token pos 0")); ex = Assert.Throws(() => ExecuteFindStatement(coll.Find("pages = :Pages").Bind("pAges", 40).Fields(" "))); - Assert.AreEqual("No more tokens when expecting one at token pos 0", ex.Message); + Assert.That(ex.Message, Is.EqualTo("No more tokens when expecting one at token pos 0")); ex = Assert.Throws(() => ExecuteFindStatement(coll.Find("pages = :Pages").Bind("pAges", 40).Fields(string.Empty))); - Assert.AreEqual("No more tokens when expecting one at token pos 0", ex.Message); + Assert.That(ex.Message, Is.EqualTo("No more tokens when expecting one at token pos 0")); // Multiple word field name raises error. ex = Assert.Throws(() => result = ExecuteFindStatement(coll.Find("pages = :Pages").Bind("pAges", 40).Fields("Book 1"))); - Assert.AreEqual("Expression has unexpected token '1' at position 1.", ex.Message); + Assert.That(ex.Message, Is.EqualTo("Expression has unexpected token '1' at position 1.")); } [TestCase("", "")] @@ -849,26 +849,26 @@ public void FindIdAsString(string prefix, string suffix) new { _id = $"{prefix}4{suffix}", title = $"{prefix}Book 4{suffix}", pages = 50 }, }; r = coll.Add(docs).Execute(); - Assert.AreEqual(4, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(4)); var findStmt = coll.Find("_id = :id and pages = :pages").Bind("id", $"{prefix}3{suffix}").Bind("pages", 40); var doc = ExecuteFindStatement(findStmt); var books = doc.FetchAll(); Assert.That(books, Has.One.Items); - Assert.AreEqual($"{prefix}3{suffix}", books[0]["_id"]); + Assert.That(books[0]["_id"], Is.EqualTo($"{prefix}3{suffix}")); findStmt = coll.Find("_id = :id and pages = :pages").Bind("Id", $"{prefix}2{suffix}").Bind("Pages", 30); doc = ExecuteFindStatement(findStmt); books = doc.FetchAll(); Assert.That(books, Has.One.Items); - Assert.AreEqual($"{prefix}2{suffix}", books[0]["_id"]); + Assert.That(books[0]["_id"], Is.EqualTo($"{prefix}2{suffix}")); findStmt = coll.Find("title = :title").Bind("Title", $"{prefix}Book 4{suffix}"); doc = ExecuteFindStatement(findStmt); books = doc.FetchAll(); Assert.That(books, Has.One.Items); - Assert.AreEqual($"{prefix}4{suffix}", books[0]["_id"]); - Assert.AreEqual(50, books[0]["pages"]); + Assert.That(books[0]["_id"], Is.EqualTo($"{prefix}4{suffix}")); + Assert.That(books[0]["pages"], Is.EqualTo(50)); } [TestCase(":hobbies IN $.additionalinfo.hobbies", "hobbies", "painting", 4)] @@ -886,15 +886,15 @@ public void InOperatorBindingJson(string condition, string bind, string value, i new { _id = 4, title = $"Book 4", pages = 50, additionalinfo = new DbDoc("{\"company\":\"zxc\",\"vehicle\":\"boat\",\"hobbies\":\"painting\"}") }, }; r = coll.Add(docs).Execute(); - Assert.AreEqual(4, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(4)); var findStmt = coll.Find(condition); if (bind != null) findStmt.Bind(bind, value); var result = findStmt.Execute().FetchAll(); - Assert.AreEqual(id == 0 ? 0 : 1, result.Count); + Assert.That(result.Count, Is.EqualTo(id == 0 ? 0 : 1)); if (id > 0) { - Assert.AreEqual(id, result[0]["_id"]); + Assert.That(result[0]["_id"], Is.EqualTo(id)); } } @@ -911,36 +911,36 @@ public void FindUsingOverlaps() coll.Add("{ \"_id\":6, \"title\": \"Book 6\",\"list\":[\" \"]}").Execute(); var result = ExecuteFindStatement(coll.Find("[7] OVERLAPS $.list")).FetchAll(); - Assert.AreEqual("Book 2", result[0]["title"]); + Assert.That(result[0]["title"], Is.EqualTo("Book 2")); result = ExecuteFindStatement(coll.Find("[8] overlaps $.list")).FetchAll(); - CollectionAssert.IsEmpty(result); + Assert.That(result, Is.Empty); result = ExecuteFindStatement(coll.Find("[1, 4] OVERLAPS $.list")).FetchAll(); - CollectionAssert.IsNotEmpty(result); - Assert.AreEqual("Book 1", result[0]["title"]); - Assert.AreEqual("Book 3", result[1]["title"]); + Assert.That(result, Is.Not.Empty); + Assert.That(result[0]["title"], Is.EqualTo("Book 1")); + Assert.That(result[1]["title"], Is.EqualTo("Book 3")); result = ExecuteFindStatement(coll.Find("$.list OVERLAPS [1, 2]")).FetchAll(); - CollectionAssert.IsNotEmpty(result); - Assert.AreEqual("Book 1", result[0]["title"]); - Assert.AreEqual("Book 4", result[1]["title"]); + Assert.That(result, Is.Not.Empty); + Assert.That(result[0]["title"], Is.EqualTo("Book 1")); + Assert.That(result[1]["title"], Is.EqualTo("Book 4")); result = ExecuteFindStatement(coll.Find("'Book 1' NOT OVERLAPS $.title").Fields("_id")).FetchAll(); - Assert.AreEqual(5, result.Count); - Assert.AreEqual(3, result[1].Id); + Assert.That(result.Count, Is.EqualTo(5)); + Assert.That(result[1].Id, Is.EqualTo(3)); result = ExecuteFindStatement(coll.Find(":title NOT OVERLAPS $.title").Bind("title", "Book 1").Fields("_id")).FetchAll(); - Assert.AreEqual(5, result.Count); - Assert.AreEqual(4, result[2].Id); + Assert.That(result.Count, Is.EqualTo(5)); + Assert.That(result[2].Id, Is.EqualTo(4)); result = ExecuteFindStatement(coll.Find("$.list OVERLAPS :list").Bind("list", 9)).FetchAll(); - Assert.AreEqual("Book 3", result[0]["title"]); + Assert.That(result[0]["title"], Is.EqualTo("Book 3")); var jsonParams = new { list = 4 }; result = ExecuteFindStatement(coll.Find("$.list OVERLAPS :list").Bind(jsonParams).Fields("count(_id) as ID", "title as Title", "list as List"). GroupBy("title", "list").Having("ID > 0")).FetchAll(); - Assert.AreEqual(2, result.Count); - Assert.AreEqual("Book 1", result[0]["Title"]); + Assert.That(result.Count, Is.EqualTo(2)); + Assert.That(result[0]["Title"], Is.EqualTo("Book 1")); result = ExecuteFindStatement(coll.Find("[''] OVERLAPS $.list")).FetchAll(); Assert.That(result, Has.One.Items); - Assert.AreEqual(5, result[0].Id); + Assert.That(result[0].Id, Is.EqualTo(5)); result = ExecuteFindStatement(coll.Find("[' '] OVERLAPS $.list")).FetchAll(); Assert.That(result, Has.One.Items); - Assert.AreEqual(6, result[0].Id); + Assert.That(result[0].Id, Is.EqualTo(6)); Assert.Throws(() => ExecuteFindStatement(coll.Find("$.list OVERLAPS -")).FetchAll()); Assert.Throws(() => ExecuteFindStatement(coll.Find("[2, 9] OVERLAPS")).FetchAll()); @@ -968,43 +968,43 @@ public void FindGroupByHaving() }; Result r = collection.Add(docs1).Execute(); - Assert.AreEqual(8, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(8)); // GroupBy operation. // GroupBy returns 5 rows since age 45 and 24 is repeated. var result = collection.Find().Fields("_id as ID", "name as Name", "age as Age").GroupBy("age").Execute(); - Assert.AreEqual(5, result.FetchAll().Count); + Assert.That(result.FetchAll().Count, Is.EqualTo(5)); result = collection.Find().Fields("_id as ID", "name as Name", "profit as Profit", "test as test").GroupBy("test").Having("test=1.92").Execute(); - Assert.AreEqual(1, result.FetchAll().Count); + Assert.That(result.FetchAll().Count, Is.EqualTo(1)); result = collection.Find().Fields("max($.age) as age", "max($.profit) as Profit", "max($.test) as test").GroupBy("$.test").Having("max($.age)>=31"). Sort("profit DESC").Execute(); - Assert.AreEqual(result.FetchAll().Count, result.FetchAll().Count); + Assert.That(result.FetchAll().Count, Is.EqualTo(result.FetchAll().Count)); result = collection.Find().Fields("max($.age) as age", "max($.profit) as Profit", "max($.test) as test").GroupBy("$.test").Having("max($.age)>30 && max($.age)<32") .Execute(); - Assert.AreEqual(2, result.FetchAll().Count); + Assert.That(result.FetchAll().Count, Is.EqualTo(2)); result = collection.Find().Fields("max($.age) as age", "max($.profit) as Profit", "max($.test) as test").GroupBy("$.test").Having("max($.age)>300000000") .Execute(); - Assert.AreEqual(0, result.FetchAll().Count); + Assert.That(result.FetchAll().Count, Is.EqualTo(0)); result = collection.Find().Fields("max($.age) as age", "max($.profit) as Profit", "max($.test) as test").GroupBy("$.test").Having("max($.age)>30"). Having("max($.age)<32") .Execute(); - Assert.AreEqual(5, result.FetchAll().Count); + Assert.That(result.FetchAll().Count, Is.EqualTo(5)); result = collection.Find().Fields("max($.age) as age", "max($.profit) as Profit", "max($.test) as test").GroupBy("$.test").Having("max($.age)>30"). Having("max($.age)<32").Limit(5) .Execute(); - Assert.AreEqual(5, result.FetchAll().Count); + Assert.That(result.FetchAll().Count, Is.EqualTo(5)); result = collection.Find().Fields("max($.age) as age", "max($.profit) as Profit", "max($.test) as test").GroupBy("$.test").Having("max($.age)>30"). Having("max($.age)<32").Limit(3) .Execute(); - Assert.AreEqual(3, result.FetchAll().Count); + Assert.That(result.FetchAll().Count, Is.EqualTo(3)); result = collection.Find().Fields("max($.age) as age", "max($.profit) as Profit", "max($.test) as test").GroupBy("$.test").Having("max($.age)>30"). Having("max($.age)<32").Limit(3).Offset(2) .Execute(); - Assert.AreEqual(3, result.FetchAll().Count); + Assert.That(result.FetchAll().Count, Is.EqualTo(3)); Assert.Throws(() => collection.Find().Fields("max($.age) as age", "max($.profit) as Profit", "max($.test) as test").GroupBy("$.test").Having("date=21/11/2011").Execute()); } @@ -1028,7 +1028,7 @@ public void FindLimitOffset() }; Result r = collection.Add(docs1).Execute(); - Assert.AreEqual(8, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(8)); // GroupBy operation. // GroupBy returns 5 rows since age 45 and 24 is repeated. @@ -1040,52 +1040,52 @@ public void FindLimitOffset() k = result1.FetchAll().Count; var result = collection.Find().Fields("_id as ID", "name as Name", "age as Age").GroupBy("age").Execute(); - Assert.AreEqual(5, result.FetchAll().Count); + Assert.That(result.FetchAll().Count, Is.EqualTo(5)); result = collection.Find().Fields("_id as ID", "name as Name", "profit as Profit", "test as test").GroupBy("test").Having("test=1.92").Execute(); - Assert.AreEqual(1, result.FetchAll().Count); + Assert.That(result.FetchAll().Count, Is.EqualTo(1)); result = collection.Find().Fields("max($.age) as age", "max($.profit) as Profit", "max($.test) as test").GroupBy("$.test").Having("max($.age)>=31"). Sort("profit DESC").Execute(); - Assert.AreEqual(result.FetchAll().Count, result.FetchAll().Count); + Assert.That(result.FetchAll().Count, Is.EqualTo(result.FetchAll().Count)); result = collection.Find().Fields("max($.age) as age", "max($.profit) as Profit", "max($.test) as test").GroupBy("$.test").Having("max($.age)>30 && max($.age)<32") .Execute(); - Assert.AreEqual(2, result.FetchAll().Count); + Assert.That(result.FetchAll().Count, Is.EqualTo(2)); result = collection.Find().Fields("max($.age) as age", "max($.profit) as Profit", "max($.test) as test").GroupBy("$.test").Having("max($.age)>300000000") .Execute(); - Assert.AreEqual(0, result.FetchAll().Count); + Assert.That(result.FetchAll().Count, Is.EqualTo(0)); result = collection.Find().Fields("max($.age) as age", "max($.profit) as Profit", "max($.test) as test").GroupBy("$.test").Having("max($.age)>30"). Having("max($.age)<32") .Execute(); - Assert.AreEqual(5, result.FetchAll().Count); + Assert.That(result.FetchAll().Count, Is.EqualTo(5)); result = collection.Find().Fields("max($.age) as age", "max($.profit) as Profit", "max($.test) as test").GroupBy("$.test").Having("max($.age)>30"). Having("max($.age)<32").Limit(5) .Execute(); - Assert.AreEqual(5, result.FetchAll().Count); + Assert.That(result.FetchAll().Count, Is.EqualTo(5)); result = collection.Find().Fields("max($.age) as age", "max($.profit) as Profit", "max($.test) as test").GroupBy("$.test").Having("max($.age)>30"). Having("max($.age)<32").Limit(3) .Execute(); - Assert.AreEqual(3, result.FetchAll().Count); + Assert.That(result.FetchAll().Count, Is.EqualTo(3)); result = collection.Find().Fields("max($.age) as age", "max($.profit) as Profit", "max($.test) as test").GroupBy("$.test").Having("max($.age)>30"). Having("max($.age)<32").Limit(3).Offset(2) .Execute(); - Assert.AreEqual(3, result.FetchAll().Count); + Assert.That(result.FetchAll().Count, Is.EqualTo(3)); result = collection.Find().Fields("$._id as _id", "$.test as test").GroupBy("$.test").Limit(5).Offset(1).Execute(); - Assert.AreEqual(5, result.FetchAll().Count); + Assert.That(result.FetchAll().Count, Is.EqualTo(5)); result = collection.Find().Fields("$._id as _id", "$.test as test").GroupBy("$.test").Limit(5).Offset(-1).Execute(); - Assert.AreEqual(5, result.FetchAll().Count); + Assert.That(result.FetchAll().Count, Is.EqualTo(5)); result = collection.Find().Fields("$._id as _id", "$.test as test").GroupBy("$.test").Limit(8).Execute(); - Assert.AreEqual(8, result.FetchAll().Count); + Assert.That(result.FetchAll().Count, Is.EqualTo(8)); result = collection.Find().Fields("max($.age) as age", "max($.profit) as Profit", "max($.test) as test").GroupBy("$.test").Having("max($.age)>30"). Having("max($.age)<32").Limit(3).Offset(-1) .Execute(); - Assert.AreEqual(3, result.FetchAll().Count); + Assert.That(result.FetchAll().Count, Is.EqualTo(3)); Assert.Throws(() => collection.Find().Fields("max($.age) as age", "max($.profit) as Profit", "max($.test) as test").GroupBy("$.test").Having("max($.age)>30"). Having("max($.age)<32").Limit(-1).Offset(0) @@ -1105,10 +1105,10 @@ public void FindLimitOffset() var res = collection.Add(jsonlist).Execute(); result = collection.Find().Fields("$.F1 as F1", "$.F2 as F2").GroupBy("$.F1").Limit(3).Offset(1).Execute(); - Assert.AreEqual(3, result.FetchAll().Count); + Assert.That(result.FetchAll().Count, Is.EqualTo(3)); result = collection.Find().Fields("$.F1 as F1", "$.F2 as F2").GroupBy("$.F1").Limit(3).Offset(1844674407370955161).Execute(); - Assert.AreEqual(0, result.FetchAll().Count); + Assert.That(result.FetchAll().Count, Is.EqualTo(0)); } [Test, Description("Collection.Find().Limit(x,y)")] @@ -1129,7 +1129,7 @@ public void FindLimitOffsetDeprecated() }; Result r = collection.Add(docs1).Execute(); - Assert.AreEqual(8, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(8)); // GroupBy operation. var result1 = collection.Find().Limit(2).Offset(-2378723).Execute(); @@ -1168,17 +1168,17 @@ public void FindLimitOffsetDeprecated() var result = collection.Find().Fields("max($.age) as age", "max($.profit) as Profit", "max($.test) as test").GroupBy("$.test").Having("max($.age)>30"). Having("max($.age)<32").Limit(3).Offset(2) .Execute(); - Assert.AreEqual(3, result.FetchAll().Count); + Assert.That(result.FetchAll().Count, Is.EqualTo(3)); result = collection.Find().Fields("$._id as _id", "$.test as test").GroupBy("$.test").Limit(5).Offset(1).Execute(); - Assert.AreEqual(5, result.FetchAll().Count); + Assert.That(result.FetchAll().Count, Is.EqualTo(5)); result = collection.Find().Fields("$._id as _id", "$.test as test").GroupBy("$.test").Limit(5).Offset(-1).Execute(); - Assert.AreEqual(5, result.FetchAll().Count); + Assert.That(result.FetchAll().Count, Is.EqualTo(5)); result = collection.Find().Fields("max($.age) as age", "max($.profit) as Profit", "max($.test) as test").GroupBy("$.test").Having("max($.age)>30"). Having("max($.age)<32").Limit(3).Offset(-1) .Execute(); - Assert.AreEqual(3, result.FetchAll().Count); + Assert.That(result.FetchAll().Count, Is.EqualTo(3)); Assert.Throws(() => collection.Find().Fields("max($.age) as age", "max($.profit) as Profit", "max($.test) as test").GroupBy("$.test").Having("max($.age)>30"). Having("max($.age)<32").Limit(-1).Offset(0) @@ -1226,14 +1226,14 @@ public void CollectionDbdoc() string[] test1 = new string[] { "_id=1" }; string[] test2 = new string[] { "_id=2" }; var res = col.Find("$._id = 1").Execute().FetchAll(); - Assert.AreEqual(1, res.Count, "Matching the find count"); - Assert.AreEqual(d1.ToString(), res[0].ToString(), "Matching the string"); + Assert.That(res.Count, Is.EqualTo(1), "Matching the find count"); + Assert.That(res[0].ToString(), Is.EqualTo(d1.ToString()), "Matching the string"); res = col.Find("$._id = 2").Execute().FetchAll(); - Assert.AreEqual(1, res.Count, "Matching the find count"); - Assert.AreEqual(d2.ToString(), res[0].ToString(), "Matching the string"); + Assert.That(res.Count, Is.EqualTo(1), "Matching the find count"); + Assert.That(res[0].ToString(), Is.EqualTo(d2.ToString()), "Matching the string"); res = col.Find("$._id = 3").Execute().FetchAll(); - Assert.AreEqual(1, res.Count, "Matching the find count"); - Assert.AreEqual(d3.ToString(), res[0].ToString(), "Matching the string"); + Assert.That(res.Count, Is.EqualTo(1), "Matching the find count"); + Assert.That(res[0].ToString(), Is.EqualTo(d3.ToString()), "Matching the string"); } @@ -1262,14 +1262,14 @@ public void CollectionIDPresentDbdocBlank() string[] test1 = new string[] { "_id=1" }; string[] test2 = new string[] { "_id=2" }; var res = col.Find("$._id = 1").Execute().FetchAll(); - Assert.AreEqual(1, res.Count, "Matching the find count"); - Assert.AreEqual(d1.ToString(), res[0].ToString(), "Matching the string"); + Assert.That(res.Count, Is.EqualTo(1), "Matching the find count"); + Assert.That(res[0].ToString(), Is.EqualTo(d1.ToString()), "Matching the string"); res = col.Find("$._id = 2").Execute().FetchAll(); - Assert.AreEqual(1, res.Count, "Matching the find count"); - Assert.AreEqual(d2.ToString(), res[0].ToString(), "Matching the string"); + Assert.That(res.Count, Is.EqualTo(1), "Matching the find count"); + Assert.That(res[0].ToString(), Is.EqualTo(d2.ToString()), "Matching the string"); res = col.Find("$._id = 3").Execute().FetchAll(); - Assert.AreEqual(1, res.Count, "Matching the find count"); - Assert.AreEqual(d3.ToString(), res[0].ToString(), "Matching the string"); + Assert.That(res.Count, Is.EqualTo(1), "Matching the find count"); + Assert.That(res[0].ToString(), Is.EqualTo(d3.ToString()), "Matching the string"); } /// @@ -1344,12 +1344,12 @@ public void ExclusiveLocksAndCommit(int scenario) var coll2 = session2.GetSchema("test").GetCollection("test"); session.SQL("START TRANSACTION").Execute(); var docResult = coll.Find("_id = 1").LockExclusive().Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID"); session2.SQL("START TRANSACTION").Execute(); // Should return immediately since document isn't locked. docResult = coll2.Find("_id = 2").LockExclusive().Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID"); // Session2 blocks due to to LockExclusive() not allowing to read locked documents. session2.SQL("SET SESSION innodb_lock_wait_timeout=1").Execute(); @@ -1359,7 +1359,7 @@ public void ExclusiveLocksAndCommit(int scenario) session.Commit(); var result = coll2.Modify("a = 1").Set("a", 12).Execute(); - Assert.AreEqual(1, result.AffectedItemsCount); + Assert.That(result.AffectedItemsCount, Is.EqualTo(1)); session.SQL("ROLLBACK").Execute(); session2.SQL("ROLLBACK").Execute(); } @@ -1390,7 +1390,7 @@ public void SharedLockAndCommit(LockMode? lockMode) session.SQL("START TRANSACTION").Execute(); var docResult = coll.Find("_id = 1").LockShared().Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID"); session2.SQL("START TRANSACTION").Execute(); // Should return immediately since document isn't locked. @@ -1406,7 +1406,7 @@ public void SharedLockAndCommit(LockMode? lockMode) docResult = coll2.Find("_id = 2").Execute(); break; } - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID"); // Session2 returns immediately. session2.SQL("SET SESSION innodb_lock_wait_timeout=1").Execute(); @@ -1419,7 +1419,7 @@ public void SharedLockAndCommit(LockMode? lockMode) // Session2 returns immediately as session is committed. session.Commit(); var result = coll2.Modify("a = 1").Set("a", 12).Execute(); - Assert.AreEqual(1, result.AffectedItemsCount); + Assert.That(result.AffectedItemsCount, Is.EqualTo(1)); session.SQL("ROLLBACK").Execute(); session2.SQL("ROLLBACK").Execute(); @@ -1468,7 +1468,7 @@ public void SharedAndExclusiveLockWithSkipAndNoWait(LockMode lockMode) docResult = coll2.Find("_id = :id").LockShared(LockContention.SkipLocked).Bind("id", 1).Execute(); break; } - Assert.AreEqual(0, docResult.FetchAll().Count, "Matching the document ID"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(0), "Matching the document ID"); session.SQL("ROLLBACK").Execute(); session2.SQL("ROLLBACK").Execute(); @@ -1497,7 +1497,7 @@ public void MultipleLocksWithNowaitAndSkiplock() session.SQL("START TRANSACTION").Execute(); var docResult = coll.Find("_id = 1").LockShared().Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID"); session2.SQL("START TRANSACTION").Execute(); @@ -1505,13 +1505,13 @@ public void MultipleLocksWithNowaitAndSkiplock() Assert.Throws(() => ExecuteFindStatement(coll2.Find("_id = :id").LockExclusive(LockContention.SkipLocked).LockExclusive(LockContention.NoWait).Bind("id", 1))); docResult = coll2.Find("_id = :id").LockExclusive(LockContention.SkipLocked).LockShared(LockContention.NoWait).Bind("id", 1).Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID"); docResult = coll2.Find("_id = :id").LockExclusive(LockContention.SkipLocked).LockShared(LockContention.SkipLocked).Bind("id", 1).Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID"); docResult = coll2.Find("_id = :id").LockShared(LockContention.SkipLocked).LockExclusive(LockContention.SkipLocked).Bind("id", 1).Execute(); - Assert.AreEqual(0, docResult.FetchAll().Count, "Matching the document ID"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(0), "Matching the document ID"); session.SQL("ROLLBACK").Execute(); session2.SQL("ROLLBACK").Execute(); @@ -1540,19 +1540,19 @@ public void LockSharedMultipleReads() session.SQL("START TRANSACTION").Execute(); var docResult = coll.Find("_id >1").LockShared().Execute(); - Assert.AreEqual(2, docResult.FetchAll().Count, "Matching the document ID"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(2), "Matching the document ID"); session2.SQL("START TRANSACTION").Execute(); session2.SQL("SET SESSION innodb_lock_wait_timeout=1").Execute(); docResult = coll2.Find("_id < 3").LockShared(LockContention.SkipLocked).Execute(); - Assert.AreEqual(2, docResult.FetchAll().Count, "Matching the document ID"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(2), "Matching the document ID"); docResult = coll2.Find("_id < 3").LockShared(LockContention.NoWait).Execute(); - Assert.AreEqual(2, docResult.FetchAll().Count, "Matching the document ID"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(2), "Matching the document ID"); docResult = coll2.Find("_id < 3").LockExclusive(LockContention.SkipLocked).Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID"); session.SQL("ROLLBACK").Execute(); session2.SQL("ROLLBACK").Execute(); @@ -1581,16 +1581,16 @@ public void LockExclusiveMultipleReads() session.SQL("START TRANSACTION").Execute(); var docResult = coll.Find("_id >1").LockExclusive().Execute(); - Assert.AreEqual(2, docResult.FetchAll().Count, "Matching the document ID"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(2), "Matching the document ID"); session2.SQL("START TRANSACTION").Execute(); session2.SQL("SET SESSION innodb_lock_wait_timeout=1").Execute(); docResult = coll2.Find("_id < 3").LockShared(LockContention.SkipLocked).Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID"); docResult = coll2.Find("_id < 3").LockExclusive(LockContention.SkipLocked).Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID"); session.SQL("ROLLBACK").Execute(); session2.SQL("ROLLBACK").Execute(); @@ -1619,15 +1619,15 @@ public void LockSharedAndModify() session.SQL("START TRANSACTION").Execute(); var docResult = coll.Find("_id = 1").LockShared().Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID"); session2.SQL("START TRANSACTION").Execute(); // Should return immediately since document isn't locked. docResult = coll2.Find("_id = 1").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID"); session2.SQL("SET SESSION innodb_lock_wait_timeout=1").Execute(); // Should allow to modify immediately since document isn't locked. var result = coll2.Modify("_id = 2").Set("a", 10).Execute(); - Assert.AreEqual(1, (int)result.AffectedItemsCount, "Match being done"); + Assert.That((int)result.AffectedItemsCount, Is.EqualTo(1), "Match being done"); Assert.Throws(() => ExecuteModifyStatement(coll2.Modify("_id = 1").Change("a", 10))); session.SQL("ROLLBACK").Execute(); @@ -1659,14 +1659,14 @@ public void LockSharedTwoSessions() session.SQL("START TRANSACTION").Execute(); var docResult = coll.Find("_id = 1").LockShared().Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID"); session2.SQL("START TRANSACTION").Execute(); // Should return immediately since document isn't locked. docResult = coll2.Find("_id = 2").LockShared().Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID"); // Should return immediately due to LockShared() allows reading by other sessions. docResult = coll2.Find("_id = 1").LockShared().Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID"); session.SQL("ROLLBACK").Execute(); session2.SQL("ROLLBACK").Execute(); } @@ -1696,20 +1696,20 @@ public void LockExclusiveFindAndLockSharedFind() session.SQL("START TRANSACTION").Execute(); var docResult = coll.Find("_id = 1").LockExclusive().Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID"); session2.SQL("START TRANSACTION").Execute(); // Should return immediately since document isn't locked. docResult = coll2.Find("_id = 2").LockShared().Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID"); session2.SQL("SET SESSION innodb_lock_wait_timeout=1").Execute(); // Session2 blocks due to LockExclusive() not allowing to read locked documents. Assert.Throws(() => ExecuteFindStatement(coll2.Find("_id = 1").LockShared())); // Session unlocks documents. session.SQL("ROLLBACK").Execute(); docResult = coll2.Find("_id = 1").LockShared().Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID"); docResult = coll.Find("_id = 1").LockShared().Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID"); session2.SQL("ROLLBACK").Execute(); } @@ -1738,21 +1738,21 @@ public void LockSharedFindAndExclusiveLocks() session.SQL("START TRANSACTION").Execute(); var docResult = coll.Find("_id = 1").LockShared().Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document IDs"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document IDs"); docResult = coll.Find("_id = 3").LockShared().Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document IDs"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document IDs"); session2.SQL("START TRANSACTION").Execute(); // Should return immediately since document isn't locked. docResult = coll2.Find("_id = 2").LockExclusive().Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID"); // Should return immediately due to LockShared() allows reading by other sessions. docResult = coll2.Find("_id = 2").LockShared().Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID"); session2.SQL("SET SESSION innodb_lock_wait_timeout=1").Execute(); // Session1 blocks due to LockExclusive() not allowing to read locked documents. coll2.Find("_id = 2").LockExclusive().Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID"); Assert.Throws(() => ExecuteFindStatement(coll2.Find("_id = 1").LockExclusive())); Assert.Throws(() => ExecuteModifyStatement(coll2.Modify("_id = 1").Set("a", 100))); // Session unlocks documents. @@ -1785,11 +1785,11 @@ public void LockExclusiveWithRollback() session.SQL("START TRANSACTION").Execute(); var docResult = coll.Find("_id = 1").LockExclusive().Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document IDs"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document IDs"); session2.SQL("START TRANSACTION").Execute(); // Should return immediately due to LockShared() allows reading by other sessions. docResult = coll2.Find("_id = 2").LockExclusive().Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID"); session.SQL("SET SESSION innodb_lock_wait_timeout=1").Execute(); Assert.Throws(() => ExecuteFindStatement(coll.Find("_id = 2").LockExclusive())); session2.SQL("SET SESSION innodb_lock_wait_timeout=1").Execute(); @@ -1798,10 +1798,10 @@ public void LockExclusiveWithRollback() // Session unlocks documents. session2.SQL("ROLLBACK").Execute(); docResult = coll.Find("_id = 2").LockExclusive().Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID"); session.SQL("ROLLBACK").Execute(); docResult = coll2.Find("_id = 1").LockExclusive().Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID"); } ExecuteSQLStatement(session.SQL("SET autocommit = 1")); @@ -1828,18 +1828,18 @@ public void LockExclusiveWithINSelection() var coll2 = session2.GetSchema("test").GetCollection("test"); session.SQL("START TRANSACTION").Execute(); var docResult = coll.Find("_id in (1,3)").LockExclusive().Execute(); - Assert.AreEqual(2, docResult.FetchAll().Count, "Matching the document ID"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(2), "Matching the document ID"); session2.SQL("START TRANSACTION").Execute(); // Should return immediately since document isn't locked. docResult = coll2.Find("_id = 2").LockExclusive().Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID"); // Should return immediately due to LockShared() allows reading by other sessions. docResult = coll2.Find("_id = 2").LockShared().Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID"); session2.SQL("SET SESSION innodb_lock_wait_timeout=1").Execute(); // Session1 blocks due to LockExclusive() not allowing to read locked documents. coll2.Find("_id = 2").LockExclusive().Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID"); Assert.Throws(() => ExecuteFindStatement(coll2.Find("_id = 1").LockExclusive())); Assert.Throws(() => ExecuteModifyStatement(coll2.Modify("_id = 1").Set("a", 100))); // Session unlocks documents. @@ -1871,18 +1871,18 @@ public void LockSharedReadTwice() session.SQL("START TRANSACTION").Execute(); var docResult = coll.Find("_id = 1").LockShared().Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID"); session2.SQL("START TRANSACTION").Execute(); // Should return immediately since document isn't locked. docResult = coll2.Find("_id = 2").LockExclusive().Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID"); docResult = coll2.Find("_id = 2").LockExclusive().Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID"); docResult = coll2.Find("_id = 2").LockShared().Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID"); docResult = coll2.Find("_id = 2").LockShared().Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID"); // Session unlocks documents. session2.SQL("ROLLBACK").Execute(); session.SQL("ROLLBACK").Execute(); @@ -1899,16 +1899,16 @@ public void FindInJsonObjects() var col = CreateCollection("my_collection_1"); string json = @"{ ""_id"": 0, ""title"": ""Book 0"" ,""pages"": 10,""name"": ""Jeoff Archer""}"; Result r = col.Add(json).Execute(); - Assert.AreEqual(1, (int)r.AffectedItemsCount, "Matching Affected Records Count"); + Assert.That((int)r.AffectedItemsCount, Is.EqualTo(1), "Matching Affected Records Count"); var foundDocs = col.Find("1 in (1,2,3,6)").Execute(); - Assert.AreEqual(1, foundDocs.FetchAll().Count, "Matching Count"); + Assert.That(foundDocs.FetchAll().Count, Is.EqualTo(1), "Matching Count"); //var result = col.Find("0 in $._id").Fields("$.name as name, $.pages as pages, $.title as title").Execute(); foundDocs = col.Find("'Book 0' in $.title").Execute(); - Assert.AreEqual(1, foundDocs.FetchAll().Count, "Matching Count"); + Assert.That(foundDocs.FetchAll().Count, Is.EqualTo(1), "Matching Count"); foundDocs = col.Find("100 in _id").Execute(); - Assert.AreEqual(0, foundDocs.FetchAll().Count, "Matching Count"); + Assert.That(foundDocs.FetchAll().Count, Is.EqualTo(0), "Matching Count"); foundDocs = col.Find("100 not in _id").Execute(); - Assert.AreEqual(1, foundDocs.FetchAll().Count, "Matching Count"); + Assert.That(foundDocs.FetchAll().Count, Is.EqualTo(1), "Matching Count"); json = @"{ ""_id"" : 99950, ""city"" : ""KETCHIKAN"", ""loc"" : ""[ -133.18479, 55.942471 ]"", ""pop"" : 422, ""state"" : ""AK"" }"; r = col.Add(json).Execute(); @@ -1922,7 +1922,7 @@ public void FindInJsonObjects() d2.SetValue("pages", 20); d2.SetValue("person", new { name = "Fred", age = 45 }); - Assert.AreEqual(d.Equals(d2), true, "Matching"); + Assert.That(true, Is.EqualTo(d.Equals(d2)), "Matching"); col.Add(d).Execute(); @@ -1955,32 +1955,32 @@ public void FindInJsonObjects() var result = col.Find("0 in $._id").Fields("$._id as _id,$.name as name, $.pages as pages, $.title as title").Execute(); var res1 = result.FetchOne(); - Assert.AreEqual(0, res1["_id"]); - Assert.AreEqual("Jeoff Archer", res1["name"]); - Assert.AreEqual(10, res1["pages"]); - Assert.AreEqual("Book 0", res1["title"]); + Assert.That(res1["_id"], Is.EqualTo(0)); + Assert.That(res1["name"], Is.EqualTo("Jeoff Archer")); + Assert.That(res1["pages"], Is.EqualTo(10)); + Assert.That(res1["title"], Is.EqualTo("Book 0")); result = col.Find("0 in $._id OR 1 in $._id").Fields("$._id as _id,$.name as name, $.pages as pages, $.title as title").Execute(); res1 = result.FetchOne(); - Assert.AreEqual(0, res1["_id"]); - Assert.AreEqual("Jeoff Archer", res1["name"]); - Assert.AreEqual(10, res1["pages"]); - Assert.AreEqual("Book 0", res1["title"]); + Assert.That(res1["_id"], Is.EqualTo(0)); + Assert.That(res1["name"], Is.EqualTo("Jeoff Archer")); + Assert.That(res1["pages"], Is.EqualTo(10)); + Assert.That(res1["title"], Is.EqualTo("Book 0")); result = col.Find("0 not in $._id").Fields("$._id as _id,$.name as name, $.pages as pages, $.title as title").Execute(); var res2 = result.FetchAll(); - Assert.AreEqual(6, res2.Count, "Matching the find count"); + Assert.That(res2.Count, Is.EqualTo(6), "Matching the find count"); result = col.Find("'Jeoff Archer' in $.name").Execute(); res1 = result.FetchOne(); - Assert.AreEqual(0, res1["_id"]); - Assert.AreEqual("Jeoff Archer", res1["name"]); - Assert.AreEqual(10, res1["pages"]); - Assert.AreEqual("Book 0", res1["title"]); + Assert.That(res1["_id"], Is.EqualTo(0)); + Assert.That(res1["name"], Is.EqualTo("Jeoff Archer")); + Assert.That(res1["pages"], Is.EqualTo(10)); + Assert.That(res1["title"], Is.EqualTo("Book 0")); result = col.Find("0 not in $._id").Fields().Execute(); res2 = result.FetchAll(); - Assert.IsNotNull(res2[0]["_id"]); + Assert.That(res2[0]["_id"], Is.Not.Null); var test = new DbDoc(); test.SetValue("_id", 1); @@ -1995,10 +1995,10 @@ public void FindInJsonObjects() "'ABBBBBBBBBBBBBBXXXXXXXXXXXXXXXYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYTTTTTTYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYABBBBBBBBBBBBBBXXXXXXXXXXXXXXXYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYTTTTTTYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYABBBBBBBBBBBBBBXXXXXXXXXXXXXXXYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYTTTTTTYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYABBBBBBBBBBBBBBXXXXXXXXXXXXXXXYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYTTTTTTYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYABBBBBBBBBBBBBBXXXXXXXXXXXXXXXYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYTTTTTTYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY' in $.name") .Execute(); var docs1 = foundDocs2.FetchAll(); - Assert.AreEqual(1, docs1.Count); + Assert.That(docs1.Count, Is.EqualTo(1)); foundDocs2 = coll.Find("3488888888.9 in $.age").Execute(); docs1 = foundDocs2.FetchAll(); - Assert.AreEqual(1, docs1.Count); + Assert.That(docs1.Count, Is.EqualTo(1)); } [Test, Description("Test MySQLX plugin Collection Array or Object contains operator Scenarios-3")] @@ -2022,17 +2022,17 @@ public void FindAndCountJsonValues() .Execute(); var docs = col.Find().Execute(); var result1 = col.Find("\"10-15-2017\" in $.misc").Execute().FetchAll().Count; - Assert.AreEqual(1, result1); + Assert.That(result1, Is.EqualTo(1)); result1 = col.Find("\"10-15-2019\" in $.misc").Execute().FetchAll().Count; - Assert.AreEqual(0, result1); + Assert.That(result1, Is.EqualTo(0)); var doc = docs.FetchOne(); var result = col.Find("1 in $.age").Fields("$.name as name, $.age as age, $.misc as misc").Sort("name DESC").Execute(); - Assert.AreEqual(3, result.FetchAll().Count); + Assert.That(result.FetchAll().Count, Is.EqualTo(3)); var coll = CreateCollection("test"); coll.Add(new DbDoc("{ \"a\": 1, \"b\": [ 1, \"value\" ], \"d\":\"\", \"ARR1\":[\"Field-1-Data-0\"] }")).Execute(); result = coll.Find("JSON_TYPE($.ARR1) = 'ARRAY' AND \"Field-1-Data-0\" in $.ARR1").Execute(); var count = result.FetchAll().Count; - Assert.AreEqual(1, count); + Assert.That(count, Is.EqualTo(1)); } @@ -2048,9 +2048,9 @@ public void CheckCountAfterSort() coll.Add("{ \"name\": [\"name1\", \"name2\", \"name3\"], \"age\": 1 , \"misc\": 1.2}").Execute(); coll.Add("{ \"name\": {\"first\" : \"ABCDEF1\", \"middle\" : \"ABCDEF2\", \"last\" : \"ABCDEF3\"}, \"age\": 1 , \"misc\": 1.2}").Execute(); var docs = coll.Find("4 in $.age").Execute().FetchAll().Count; - Assert.True(docs > 0); + Assert.That(docs > 0); var res3 = coll.Find("4 in $.age").Sort("name ASC").Execute().FetchAll(); - Assert.AreEqual(docs, res3.Count); + Assert.That(res3.Count, Is.EqualTo(docs)); } [Test, Description("Test MySQLX plugin Find with overlap Bugs")] @@ -2067,11 +2067,11 @@ public void FindUsingOverLapsBug() coll.Add("{\"" + splName[i] + "\":\"data" + i + "\",\"ID\":" + i + "}").Execute(); var docs2 = coll.Find("$.ID OVERLAPS " + i).Fields("$.`" + splName[i] + "` as col1,$.ID as Id").Execute(); var res2 = docs2.FetchOne(); - Assert.AreEqual(i.ToString(), res2["Id"].ToString(), "Matching the ID"); + Assert.That(res2["Id"].ToString(), Is.EqualTo(i.ToString()), "Matching the ID"); if (i == 30) - Assert.AreEqual("data" + i, "data30", "Matching the String"); + Assert.That("data30", Is.EqualTo("data" + i), "Matching the String"); else - Assert.AreEqual("data" + i, res2["col1"].ToString(), "Matching the String"); + Assert.That(res2["col1"].ToString(), Is.EqualTo("data" + i), "Matching the String"); } coll = CreateCollection("test"); @@ -2109,25 +2109,25 @@ public void FindUsingOverLapsBug() var docs = coll.Find("$._id OVERLAPS 1100").Fields("$_id as _id,$.F1 as f1, $.F2 as f2, $.F3 as f3").Execute(); var res1 = docs.FetchOne(); - Assert.AreEqual("1100", res1["_id"].ToString()); - Assert.AreEqual("Field-1-Data-100", res1["f1"].ToString()); - Assert.AreEqual("Field-2-Data-100", res1["f2"].ToString()); - Assert.AreEqual("400", res1["f3"].ToString()); + Assert.That(res1["_id"].ToString(), Is.EqualTo("1100")); + Assert.That(res1["f1"].ToString(), Is.EqualTo("Field-1-Data-100")); + Assert.That(res1["f2"].ToString(), Is.EqualTo("Field-2-Data-100")); + Assert.That(res1["f3"].ToString(), Is.EqualTo("400")); Assert.Throws(() => ExecuteFindStatement(coll.Find("$.F2 OVERLAPS #").Fields("$_id as _id,$.F1 as f1, $.F2 as f2, $.F3 as f3"))); docs = coll.Find("$.F2 OVERLAPS 'ABCD'").Fields("$_id as _id,$.F1 as f1, $.F2 as f2, $.F3 as f3").Execute(); res1 = docs.FetchOne(); - Assert.AreEqual("1005", res1["_id"]); - Assert.AreEqual(123, res1["f1"]); - Assert.AreEqual("ABCD", res1["f2"]); + Assert.That(res1["_id"], Is.EqualTo("1005")); + Assert.That(res1["f1"], Is.EqualTo(123)); + Assert.That(res1["f2"], Is.EqualTo("ABCD")); Assert.Throws(() => ExecuteFindStatement(coll.Find("$.F2 OVERLAPS [1234").Fields("$_id as _id,$.F1 as f1, $.F2 as f2, $.F3 as f3"))); Assert.Throws(() => ExecuteFindStatement(coll.Find("$.F2 OVERLAPS S()R%^").Fields("$_id as _id,$.F1 as f1, $.F2 as f2, $.F3 as f3"))); docs = coll.Find("$.F2 OVERLAPS 'S()R%^'").Fields("$_id as _id,$.F1 as f1, $.F2 as f2, $.F3 as f3").Execute(); res1 = docs.FetchOne(); - Assert.AreEqual("1007", res1["_id"]); - Assert.AreEqual(123, res1["f1"]); - Assert.AreEqual("S()R%^", res1["f2"]); + Assert.That(res1["_id"], Is.EqualTo("1007")); + Assert.That(res1["f1"], Is.EqualTo(123)); + Assert.That(res1["f2"], Is.EqualTo("S()R%^")); } [Test, Description("Test MySQLX plugin Find with overlap and Many conditions")] @@ -2152,7 +2152,7 @@ public void FindUsingOverLapsManyConditions() j++; } var docs = coll.Find(query).Execute(); - Assert.True(docs.FetchAll().Count > 0); + Assert.That(docs.FetchAll().Count > 0); } [Test, Description("Deprecated Find Where")] @@ -2167,11 +2167,11 @@ public void FindWhere() new { _id = 4, title = "Book 4", pages = 50 }, }; var result1 = collection.Add(docs).Execute(); - Assert.AreEqual(4, result1.AffectedItemsCount); + Assert.That(result1.AffectedItemsCount, Is.EqualTo(4)); //Deprecated Find().Where() in 8.0.17 var result2 = collection.Find("$._id = 1").Where("true").Execute().FetchAll(); - Assert.AreEqual(4, result2.Count); + Assert.That(result2.Count, Is.EqualTo(4)); } [Test, Description("Test MySQLX plugin Collection match count")] @@ -2218,35 +2218,35 @@ public void CollectionFindFieldMatchingCount() var final = col.Add(d1, d2).Add(d3).Execute(); var res1 = col.Find().Fields("{\"_id\":\"1\",\"books\": \"test1\" }").Fields("{\"_id\":\"2\",\"books\": \"test2\" }").Fields("{\"_id\":\"3\",\"books\": \"test3\" }").Execute().FetchAll(); res1 = col.Find().Fields(new string[] { "_id", "books", "count" }).Execute().FetchAll(); - Assert.AreEqual(3, res1.Count, "Matching the find count"); - Assert.AreEqual(d1.ToString(), res1[0].ToString(), "Matching the doc string 1"); - Assert.AreEqual(d2.ToString(), res1[1].ToString(), "Matching the doc string 2"); - Assert.AreEqual(d3.ToString(), res1[2].ToString(), "Matching the doc string 3"); + Assert.That(res1.Count, Is.EqualTo(3), "Matching the find count"); + Assert.That(res1[0].ToString(), Is.EqualTo(d1.ToString()), "Matching the doc string 1"); + Assert.That(res1[1].ToString(), Is.EqualTo(d2.ToString()), "Matching the doc string 2"); + Assert.That(res1[2].ToString(), Is.EqualTo(d3.ToString()), "Matching the doc string 3"); final = col.Add(new DbDoc[] { d4, d5 }).Execute(); var res2 = col.Find().Fields("$._id as _id,$.books as books, $.count as count").Execute().FetchAll(); - Assert.AreEqual(5, res2.Count, "Matching the find count"); - Assert.AreEqual(d1.ToString(), res2[0].ToString(), "Matching the doc string 1"); - Assert.AreEqual(d2.ToString(), res2[1].ToString(), "Matching the doc string 2"); - Assert.AreEqual(d3.ToString(), res2[2].ToString(), "Matching the doc string 3"); - Assert.AreEqual(d4.ToString(), res2[3].ToString(), "Matching the doc string 4"); - Assert.AreEqual(d5.ToString(), res2[4].ToString(), "Matching the doc string 5"); + Assert.That(res2.Count, Is.EqualTo(5), "Matching the find count"); + Assert.That(res2[0].ToString(), Is.EqualTo(d1.ToString()), "Matching the doc string 1"); + Assert.That(res2[1].ToString(), Is.EqualTo(d2.ToString()), "Matching the doc string 2"); + Assert.That(res2[2].ToString(), Is.EqualTo(d3.ToString()), "Matching the doc string 3"); + Assert.That(res2[3].ToString(), Is.EqualTo(d4.ToString()), "Matching the doc string 4"); + Assert.That(res2[4].ToString(), Is.EqualTo(d5.ToString()), "Matching the doc string 5"); final = col.Add(d6, d7).Execute(); var res3 = col.Find().Sort("count ASC").Execute().FetchAll(); - Assert.AreEqual(d6.ToString(), res3[0].ToString(), "Matching the doc string 7"); - Assert.AreEqual(d1.ToString(), res3[1].ToString(), "Matching the doc string 1"); - Assert.AreEqual(d2.ToString(), res3[2].ToString(), "Matching the doc string 2"); - Assert.AreEqual(d3.ToString(), res3[3].ToString(), "Matching the doc string 3"); - Assert.AreEqual(d4.ToString(), res3[4].ToString(), "Matching the doc string 4"); - Assert.AreEqual(d5.ToString(), res3[5].ToString(), "Matching the doc string 5"); - Assert.AreEqual(d7.ToString(), res3[6].ToString(), "Matching the doc string 6"); + Assert.That(res3[0].ToString(), Is.EqualTo(d6.ToString()), "Matching the doc string 7"); + Assert.That(res3[1].ToString(), Is.EqualTo(d1.ToString()), "Matching the doc string 1"); + Assert.That(res3[2].ToString(), Is.EqualTo(d2.ToString()), "Matching the doc string 2"); + Assert.That(res3[3].ToString(), Is.EqualTo(d3.ToString()), "Matching the doc string 3"); + Assert.That(res3[4].ToString(), Is.EqualTo(d4.ToString()), "Matching the doc string 4"); + Assert.That(res3[5].ToString(), Is.EqualTo(d5.ToString()), "Matching the doc string 5"); + Assert.That(res3[6].ToString(), Is.EqualTo(d7.ToString()), "Matching the doc string 6"); var res4 = col.Find().Sort("count DESC").Execute().FetchAll(); - Assert.AreEqual(d7.ToString(), res4[0].ToString(), "Matching the doc string 6"); - Assert.AreEqual(d5.ToString(), res4[1].ToString(), "Matching the doc string 1"); - Assert.AreEqual(d4.ToString(), res4[2].ToString(), "Matching the doc string 2"); - Assert.AreEqual(d3.ToString(), res4[3].ToString(), "Matching the doc string 3"); - Assert.AreEqual(d2.ToString(), res4[4].ToString(), "Matching the doc string 4"); - Assert.AreEqual(d1.ToString(), res4[5].ToString(), "Matching the doc string 5"); - Assert.AreEqual(d6.ToString(), res4[6].ToString(), "Matching the doc string 7"); + Assert.That(res4[0].ToString(), Is.EqualTo(d7.ToString()), "Matching the doc string 6"); + Assert.That(res4[1].ToString(), Is.EqualTo(d5.ToString()), "Matching the doc string 1"); + Assert.That(res4[2].ToString(), Is.EqualTo(d4.ToString()), "Matching the doc string 2"); + Assert.That(res4[3].ToString(), Is.EqualTo(d3.ToString()), "Matching the doc string 3"); + Assert.That(res4[4].ToString(), Is.EqualTo(d2.ToString()), "Matching the doc string 4"); + Assert.That(res4[5].ToString(), Is.EqualTo(d1.ToString()), "Matching the doc string 5"); + Assert.That(res4[6].ToString(), Is.EqualTo(d6.ToString()), "Matching the doc string 7"); col.Modify("_id = 1").Unset("count").Unset("books").Execute(); col.Modify("_id = 1").Set("count", 10).Set("books", "test1").Execute(); @@ -2260,21 +2260,21 @@ public void CollectionGetNameSchemaCount() Result r = col.Add(@"{ ""_id"": 1, ""foo"": 1 }").Execute(); long count = col.Count(); - Assert.AreEqual(count, 1, "Matching the Collection Count"); + Assert.That(1, Is.EqualTo(count), "Matching the Collection Count"); var collectionName = col.Name; - Assert.AreEqual(collectionName, "my_collection_123456789", "Matching the collection Name"); + Assert.That("my_collection_123456789", Is.EqualTo(collectionName), "Matching the collection Name"); var schema = col.Schema.Name; - Assert.AreEqual(schema, schemaName, "Matching the Schema Name"); + Assert.That(schemaName, Is.EqualTo(schema), "Matching the Schema Name"); r = col.Add(@"{ ""_id"": 2, ""foo"": 2 }").Execute(); count = col.Count(); - Assert.AreEqual(count, 2, "Matching the Collection Count"); + Assert.That(2, Is.EqualTo(count), "Matching the Collection Count"); r = col.Remove("_id=2").Execute(); count = col.Count(); - Assert.AreEqual(count, 1, "Matching the Collection Count"); + Assert.That(1, Is.EqualTo(count), "Matching the Collection Count"); session.Schema.DropCollection("my_collection_123456789"); } diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/BasicSelectTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/BasicSelectTests.cs index 0037b7cb0..20b6a73c0 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/BasicSelectTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/BasicSelectTests.cs @@ -45,12 +45,12 @@ public void SimpleSelect() RowResult result = ExecuteSelectStatement(books.Select("name", "pages")); var rows = result.FetchAll(); - Assert.True(result.Columns.Count == 2); - Assert.True(rows.Count == 2); + Assert.That(result.Columns.Count == 2); + Assert.That(rows.Count == 2); var result2 = session.SQL("Select* from test.books").Execute(); var row2 = result2.FetchOne(); - Assert.True(result2.Columns.Count == 3); + Assert.That(result2.Columns.Count == 3); } [Test] @@ -61,7 +61,7 @@ public void SimpleSelectWithWhere() RowResult result = ExecuteSelectStatement(books.Select("name", "pages").Where("pages > 250")); var rows = result.FetchAll(); - Assert.True(result.Columns.Count == 2); + Assert.That(result.Columns.Count == 2); Assert.That(rows, Has.One.Items); } @@ -97,7 +97,7 @@ public void LockExclusiveAndSharedWithWaitingOptions(LockContention lockOption, RowResult r1 = ExecuteSelectStatement(t1.Select().Where("id = :id").Bind("id", 1).LockExclusive()); var rows1 = r1.FetchAll(); Assert.That(rows1, Has.One.Items); - Assert.AreEqual(1, rows1[0]["id"]); + Assert.That(rows1[0]["id"], Is.EqualTo(1)); // second session tries to read the locked row using (Session s2 = MySQLX.GetSession(ConnectionString)) @@ -115,7 +115,7 @@ public void LockExclusiveAndSharedWithWaitingOptions(LockContention lockOption, { case LockContention.Default: // error 1205 Lock wait timeout exceeded; try restarting transaction - Assert.AreEqual(1205u, Assert.Throws(() => ExecuteSelectStatement(stmt2).FetchAll()).Code); + Assert.That(Assert.Throws(() => ExecuteSelectStatement(stmt2).FetchAll()).Code, Is.EqualTo(1205u)); break; case LockContention.NoWait: // error 1205 Lock wait timeout exceeded; try restarting transaction @@ -123,18 +123,18 @@ public void LockExclusiveAndSharedWithWaitingOptions(LockContention lockOption, if (session.XSession.GetServerVersion().isAtLeast(8, 0, 5)) // error 3572 Statement aborted because lock(s) could not be acquired immediately and NOWAIT is set expectedError = 3572; - Assert.AreEqual(expectedError, Assert.Throws(() => ExecuteSelectStatement(stmt2).FetchAll()).Code); + Assert.That(Assert.Throws(() => ExecuteSelectStatement(stmt2).FetchAll()).Code, Is.EqualTo(expectedError)); break; case LockContention.SkipLocked: if (!session.XSession.GetServerVersion().isAtLeast(8, 0, 5)) { // error 1205 Lock wait timeout exceeded; try restarting transaction - Assert.AreEqual(1205u, Assert.Throws(() => ExecuteSelectStatement(stmt2).FetchAll()).Code); + Assert.That(Assert.Throws(() => ExecuteSelectStatement(stmt2).FetchAll()).Code, Is.EqualTo(1205u)); break; } var rows2 = ExecuteSelectStatement(stmt2).FetchAll(); Assert.That(rows2, Has.One.Items); - Assert.AreEqual(2, rows2[0]["id"]); + Assert.That(rows2[0]["id"], Is.EqualTo(2)); break; default: throw new NotImplementedException(lockOption.ToString()); diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/CharsetAndCollationTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/CharsetAndCollationTests.cs index d0d1090cf..be95bf4c2 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/CharsetAndCollationTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/CharsetAndCollationTests.cs @@ -61,7 +61,7 @@ public void DefaultCharSet() using (var session = MySQLX.GetSession(ConnectionString)) { - Assert.AreEqual("utf8mb4", session.Settings.CharacterSet); + Assert.That(session.Settings.CharacterSet, Is.EqualTo("utf8mb4")); } using (var connection = new MySqlConnection(ConnectionStringRoot)) @@ -70,26 +70,26 @@ public void DefaultCharSet() MySqlCommand cmd = new MySqlCommand("SHOW VARIABLES LIKE 'character_set_connection'", connection); MySqlDataReader reader = cmd.ExecuteReader(); reader.Read(); - Assert.AreEqual("utf8mb4", reader.GetString("Value")); + Assert.That(reader.GetString("Value"), Is.EqualTo("utf8mb4")); reader.Close(); cmd.CommandText = "SHOW VARIABLES LIKE 'character_set_database'"; reader = cmd.ExecuteReader(); reader.Read(); - Assert.AreEqual("utf8mb4", reader.GetString("Value")); + Assert.That(reader.GetString("Value"), Is.EqualTo("utf8mb4")); reader.Close(); cmd.CommandText = "SHOW VARIABLES LIKE 'character_set_server'"; reader = cmd.ExecuteReader(); reader.Read(); - Assert.AreEqual("utf8mb4", reader.GetString("Value")); + Assert.That(reader.GetString("Value"), Is.EqualTo("utf8mb4")); reader.Close(); cmd.CommandText = "SHOW VARIABLES LIKE 'collation_%'"; reader = cmd.ExecuteReader(); while (reader.Read()) { - Assert.AreEqual("utf8mb4_0900_ai_ci", reader.GetString("Value")); + Assert.That(reader.GetString("Value"), Is.EqualTo("utf8mb4_0900_ai_ci")); } reader.Close(); } @@ -105,7 +105,7 @@ public void ValidateCollationMapList() connection.Open(); var command = new MySqlCommand("SELECT id, collation_name FROM INFORMATION_SCHEMA.COLLATIONS", connection); var reader = command.ExecuteReader(); - Assert.True(reader.HasRows); + Assert.That(reader.HasRows); while (reader.Read()) { @@ -115,7 +115,7 @@ public void ValidateCollationMapList() if (!_serverVersion.isAtLeast(8, 0, 30) && collationName.Contains("utf8_")) collationName = collationName.Replace("utf8_", "utf8mb3_"); - Assert.AreEqual(CollationMap.GetCollationName(id), collationName); + Assert.That(collationName, Is.EqualTo(CollationMap.GetCollationName(id))); } } } @@ -132,12 +132,12 @@ public void Utf8mb4CharsetExists() { // Search utf8mb4 database. var result = ExecuteSQLStatement(session.SQL("SHOW COLLATION WHERE id = 255")); - Assert.True(result.HasData); + Assert.That(result.HasData); var data = result.FetchOne(); - Assert.AreEqual("utf8mb4_0900_ai_ci", data.GetString("Collation")); + Assert.That(data.GetString("Collation"), Is.EqualTo("utf8mb4_0900_ai_ci")); // Check in CollationMap. - Assert.AreEqual("utf8mb4_0900_ai_ci", CollationMap.GetCollationName(255)); + Assert.That(CollationMap.GetCollationName(255), Is.EqualTo("utf8mb4_0900_ai_ci")); } } @@ -150,25 +150,25 @@ public void IllegalMixCollations() using (Session session = MySQLX.GetSession(ConnectionString)) { var result = ExecuteSQLStatement(session.SQL("SHOW COLLATION WHERE `Default` ='Yes';")); - Assert.True(result.HasData); + Assert.That(result.HasData); } using (Session session = MySQLX.GetSession(ConnectionString + ";charset=latin1")) { var result = ExecuteSQLStatement(session.SQL("SHOW COLLATION WHERE `Default` ='Yes';")); - Assert.True(result.HasData); + Assert.That(result.HasData); } using (Session session = MySQLX.GetSession(ConnectionString + ";charset=utf8mb4")) { var result = ExecuteSQLStatement(session.SQL("SHOW COLLATION WHERE `Default` ='Yes';")); - Assert.True(result.HasData); + Assert.That(result.HasData); } using (Session session = MySQLX.GetSession(ConnectionString + ";charset=utf-8")) { var result = ExecuteSQLStatement(session.SQL("SHOW COLLATION WHERE `Default` ='Yes';")); - Assert.True(result.HasData); + Assert.That(result.HasData); } } @@ -196,29 +196,29 @@ public void NamesAreReturnedAsStrings() ExecuteSQL("SELECT * FROM view2"); List
tables = test.GetTables(); - Assert.AreEqual(4, tables.Count); - Assert.AreEqual(2, tables.FindAll(i => !i.IsView).Count); - Assert.AreEqual(2, tables.FindAll(i => i.IsView).Count); + Assert.That(tables.Count, Is.EqualTo(4)); + Assert.That(tables.FindAll(i => !i.IsView).Count, Is.EqualTo(2)); + Assert.That(tables.FindAll(i => i.IsView).Count, Is.EqualTo(2)); ExecuteSelectStatement(tables[0].Select()); ExecuteSelectStatement(tables[1].Select()); ExecuteSelectStatement(tables[2].Select()); ExecuteSelectStatement(tables[3].Select()); - Assert.AreEqual("test1", tables[0].Name); - Assert.AreEqual("test2", tables[1].Name); - Assert.AreEqual("view1", tables[2].Name); - Assert.AreEqual("view2", tables[3].Name); + Assert.That(tables[0].Name, Is.EqualTo("test1")); + Assert.That(tables[1].Name, Is.EqualTo("test2")); + Assert.That(tables[2].Name, Is.EqualTo("view1")); + Assert.That(tables[3].Name, Is.EqualTo("view2")); Table table = test.GetTable("test2"); - Assert.AreEqual("test2", table.Name); + Assert.That(table.Name, Is.EqualTo("test2")); Collection c = test.CreateCollection("coll"); List collections = test.GetCollections(); Assert.That(collections, Has.One.Items); - Assert.AreEqual("coll", collections[0].Name); + Assert.That(collections[0].Name, Is.EqualTo("coll")); Collection collection = test.GetCollection("coll"); - Assert.AreEqual("coll", collection.Name); + Assert.That(collection.Name, Is.EqualTo("coll")); } } @@ -288,39 +288,39 @@ public void ColumnDefaultDatatypes() for (int i = 0; i < columns.Length; i++) { var tableType = result.Columns[i].Type; - Assert.AreEqual(columnTypeMatch[i], tableType.ToString(), "Matching the table Type"); + Assert.That(tableType.ToString(), Is.EqualTo(columnTypeMatch[i]), "Matching the table Type"); string tableLabel = result.Columns[i].TableLabel; - Assert.AreEqual("address", tableLabel, "Matching the table label"); + Assert.That(tableLabel, Is.EqualTo("address"), "Matching the table label"); string columnName = result.Columns[i].ColumnName; - Assert.AreEqual(columns[i].ToString(), columnName, "Matching the Column Name"); + Assert.That(columnName, Is.EqualTo(columns[i].ToString()), "Matching the Column Name"); string columnLabel = result.Columns[i].ColumnLabel; - Assert.AreEqual(columns[i].ToString(), columnLabel, "Matching the Column Label"); + Assert.That(columnLabel, Is.EqualTo(columns[i].ToString()), "Matching the Column Label"); uint columnLength = result.Columns[i].Length; - Assert.AreEqual(columnLength, columnLength, "Matching the Column Length"); + Assert.That(columnLength, Is.EqualTo(columnLength), "Matching the Column Length"); var columnType = result.Columns[i].Type; - Assert.AreEqual(columnTypeMatch[i], columnType.ToString(), "Matching the Column Type"); + Assert.That(columnType.ToString(), Is.EqualTo(columnTypeMatch[i]), "Matching the Column Type"); var columnFD = result.Columns[i].FractionalDigits; - Assert.AreEqual(FDLength[i], columnFD, "Matching the Column FD"); + Assert.That(columnFD, Is.EqualTo(FDLength[i]), "Matching the Column FD"); var columnIsSigned = result.Columns[i].IsNumberSigned; - Assert.AreEqual(columnIsSignedMatch[i], columnIsSigned.ToString(), "Matching whether column is signed or not"); + Assert.That(columnIsSigned.ToString(), Is.EqualTo(columnIsSignedMatch[i]), "Matching whether column is signed or not"); string columnCollation = result.Columns[i].CollationName; if (i == 10 || i == 11 || i == 12 || i == 13 || i == 14 || i == 20 || i == 21) - Assert.AreEqual(columnCollation, columnCollation, "Matching the Collation Name for default characters"); + Assert.That(columnCollation, Is.EqualTo(columnCollation), "Matching the Collation Name for default characters"); else if (i == 15 || i == 16 || i == 17 || i == 18 || i == 19) - Assert.AreEqual("binary", columnCollation, "Matching the Collation Name for default characters"); + Assert.That(columnCollation, Is.EqualTo("binary"), "Matching the Collation Name for default characters"); else - Assert.AreEqual(null, columnCollation, "Matching the Collation Name as null for data types other than characters"); + Assert.That(columnCollation, Is.EqualTo(null), "Matching the Collation Name as null for data types other than characters"); string columnCharacterSet = result.Columns[i].CharacterSetName; if (i == 10 || i == 11 || i == 12 || i == 13 || i == 14 || i == 20 || i == 21) - Assert.AreEqual(columnCharacterSet, columnCharacterSet, "Matching the CharacterSet Name for default characters"); + Assert.That(columnCharacterSet, Is.EqualTo(columnCharacterSet), "Matching the CharacterSet Name for default characters"); else if (i == 15 || i == 16 || i == 17 || i == 18 || i == 19) - Assert.AreEqual("binary", columnCharacterSet, "Matching the Collation Name for default characters"); + Assert.That(columnCharacterSet, Is.EqualTo("binary"), "Matching the Collation Name for default characters"); else - Assert.AreEqual(null, columnCharacterSet, "Matching the Collation Name as null for data types other than characters"); + Assert.That(columnCharacterSet, Is.EqualTo(null), "Matching the Collation Name as null for data types other than characters"); var columnIsPadded = result.Columns[i].IsPadded; - Assert.AreEqual(columnIsPaddedMatch[i], columnIsPadded.ToString(), "Matching whether column is padded or not"); + Assert.That(columnIsPadded.ToString(), Is.EqualTo(columnIsPaddedMatch[i]), "Matching whether column is padded or not"); var columnClrType = result.Columns[i].ClrType; - Assert.AreEqual(clrTypeMatch[i], columnClrType.ToString(), "Matching whether column CLR Type"); + Assert.That(columnClrType.ToString(), Is.EqualTo(clrTypeMatch[i]), "Matching whether column CLR Type"); } } @@ -388,37 +388,37 @@ public void ColumnCustomDatatypes() for (int i = 0; i < columns.Length; i++) { string tableLabel = result.Columns[i].TableLabel; - Assert.AreEqual("address", tableLabel, "Matching the table label"); + Assert.That(tableLabel, Is.EqualTo("address"), "Matching the table label"); string columnName = result.Columns[i].ColumnName; - Assert.AreEqual(columns[i].ToString(), columnName, "Matching the Column Name"); + Assert.That(columnName, Is.EqualTo(columns[i].ToString()), "Matching the Column Name"); string columnLabel = result.Columns[i].ColumnLabel; - Assert.AreEqual(columns[i].ToString(), columnLabel, "Matching the Column Label"); + Assert.That(columnLabel, Is.EqualTo(columns[i].ToString()), "Matching the Column Label"); uint columnLength = result.Columns[i].Length; - Assert.AreEqual(Length[i], columnLength, "Matching the Column Length"); + Assert.That(columnLength, Is.EqualTo(Length[i]), "Matching the Column Length"); var columnType = result.Columns[i].Type; - Assert.AreEqual(columnTypeMatch[i], columnType.ToString(), "Matching the Column Type"); + Assert.That(columnType.ToString(), Is.EqualTo(columnTypeMatch[i]), "Matching the Column Type"); var columnFD = result.Columns[i].FractionalDigits; - Assert.AreEqual(FDLength[i], columnFD, "Matching the Column FD"); + Assert.That(columnFD, Is.EqualTo(FDLength[i]), "Matching the Column FD"); var columnIsSigned = result.Columns[i].IsNumberSigned; - Assert.AreEqual(columnIsSignedMatch[i], columnIsSigned.ToString(), "Matching whether column is signed or not"); + Assert.That(columnIsSigned.ToString(), Is.EqualTo(columnIsSignedMatch[i]), "Matching whether column is signed or not"); string columnCollation = result.Columns[i].CollationName; if (i == 10 || i == 11 || i == 12 || i == 13 || i == 14 || i == 20 || i == 21) - Assert.AreEqual(columnCollation, columnCollation, "Matching the Collation Name for default characters"); + Assert.That(columnCollation, Is.EqualTo(columnCollation), "Matching the Collation Name for default characters"); else if (i == 15 || i == 16 || i == 17 || i == 18 || i == 19) - Assert.AreEqual("binary", columnCollation, "Matching the Collation Name for default characters"); + Assert.That(columnCollation, Is.EqualTo("binary"), "Matching the Collation Name for default characters"); else - Assert.AreEqual(null, columnCollation, "Matching the Collation Name as null for data types other than characters"); + Assert.That(columnCollation, Is.EqualTo(null), "Matching the Collation Name as null for data types other than characters"); string columnCharacterSet = result.Columns[i].CharacterSetName; if (i == 10 || i == 11 || i == 12 || i == 13 || i == 14 || i == 20 || i == 21) - StringAssert.AreEqualIgnoringCase(defaultCharset, columnCharacterSet, "Matching the CharacterSet Name for default characters"); + Assert.That(columnCharacterSet, Is.EqualTo(defaultCharset).IgnoreCase, "Matching the CharacterSet Name for default characters"); else if (i == 15 || i == 16 || i == 17 || i == 18 || i == 19) - Assert.AreEqual("binary", columnCharacterSet, "Matching the Collation Name for default characters"); + Assert.That(columnCharacterSet, Is.EqualTo("binary"), "Matching the Collation Name for default characters"); else - Assert.AreEqual(null, columnCharacterSet, "Matching the Collation Name as null for data types other than characters"); + Assert.That(columnCharacterSet, Is.EqualTo(null), "Matching the Collation Name as null for data types other than characters"); var columnIsPadded = result.Columns[i].IsPadded; - Assert.AreEqual(columnIsPaddedMatch[i], columnIsPadded.ToString(), "Matching whether column is padded or not"); + Assert.That(columnIsPadded.ToString(), Is.EqualTo(columnIsPaddedMatch[i]), "Matching whether column is padded or not"); var columnClrType = result.Columns[i].ClrType; - Assert.AreEqual(clrTypeMatch[i], columnClrType.ToString(), "Matching whether column CLR Type"); + Assert.That(columnClrType.ToString(), Is.EqualTo(clrTypeMatch[i]), "Matching whether column CLR Type"); } session.SQL($"drop table if exists address").Execute(); } @@ -481,73 +481,73 @@ public void ColumnJoin() for (int i = 0; i < columns1.Length; i++) { string tableName = result1.Columns[i].TableName; - Assert.AreEqual("result1", tableName, "Matching the table name"); + Assert.That(tableName, Is.EqualTo("result1"), "Matching the table name"); string tableLabel = result1.Columns[i].TableLabel; - Assert.AreEqual("result1", tableLabel, "Matching the table label"); + Assert.That(tableLabel, Is.EqualTo("result1"), "Matching the table label"); string columnName = result1.Columns[i].ColumnName; - Assert.AreEqual(columns1[i].ToString(), columnName, "Matching the Column Name"); + Assert.That(columnName, Is.EqualTo(columns1[i].ToString()), "Matching the Column Name"); string columnLabel = result1.Columns[i].ColumnLabel; - Assert.AreEqual(columns1[i].ToString(), columnLabel, "Matching the Column Label"); + Assert.That(columnLabel, Is.EqualTo(columns1[i].ToString()), "Matching the Column Label"); uint columnLength = result1.Columns[i].Length; - Assert.AreEqual(Length1[i], Length1[i], "Matching the Column Length"); + Assert.That(Length1[i], Is.EqualTo(Length1[i]), "Matching the Column Length"); var columnType = result1.Columns[i].Type; - Assert.AreEqual(columnTypeMatch1[i], columnType.ToString(), "Matching the Column Type"); + Assert.That(columnType.ToString(), Is.EqualTo(columnTypeMatch1[i]), "Matching the Column Type"); var columnFD = result1.Columns[i].FractionalDigits; - Assert.AreEqual(FDLength1[i], columnFD, "Matching the Column FD"); + Assert.That(columnFD, Is.EqualTo(FDLength1[i]), "Matching the Column FD"); var columnIsSigned = result1.Columns[i].IsNumberSigned; - Assert.AreEqual(columnIsSignedMatch1[i], columnIsSigned.ToString(), "Matching whether column is signed or not"); + Assert.That(columnIsSigned.ToString(), Is.EqualTo(columnIsSignedMatch1[i]), "Matching whether column is signed or not"); string columnCollation = result1.Columns[i].CollationName; if (i == 2 || i == 5) { - StringAssert.Contains(defaultCharset, columnCollation, "Matching the Collation Name for default characters"); + Assert.That(columnCollation, Does.Contain(defaultCharset), "Matching the Collation Name for default characters"); } else { - Assert.AreEqual(null, columnCollation, "Matching the Collation Name as null for data types other than characters"); + Assert.That(columnCollation, Is.EqualTo(null), "Matching the Collation Name as null for data types other than characters"); } string columnCharacterSet = result1.Columns[i].CharacterSetName; if (i == 2 || i == 5) - StringAssert.AreEqualIgnoringCase(defaultCharset, columnCharacterSet, "Matching the CharacterSet Name for default characters"); + Assert.That(columnCharacterSet, Is.EqualTo(defaultCharset).IgnoreCase, "Matching the CharacterSet Name for default characters"); else - Assert.AreEqual(null, columnCharacterSet, "Matching the Collation Name as null for data types other than characters"); + Assert.That(columnCharacterSet, Is.EqualTo(null), "Matching the Collation Name as null for data types other than characters"); var columnIsPadded = result1.Columns[i].IsPadded; - Assert.AreEqual(columnIsPaddedMatch1[i], columnIsPadded.ToString(), "Matching whether column is padded or not"); + Assert.That(columnIsPadded.ToString(), Is.EqualTo(columnIsPaddedMatch1[i]), "Matching whether column is padded or not"); var columnClrType = result1.Columns[i].ClrType; - Assert.AreEqual(clrTypeMatch1[i], columnClrType.ToString(), "Matching whether column CLR Type"); + Assert.That(columnClrType.ToString(), Is.EqualTo(clrTypeMatch1[i]), "Matching whether column CLR Type"); } for (int i = 0; i < columns2.Length; i++) { string tableName = result2.Columns[i].TableName; - Assert.AreEqual("result2", tableName, "Matching the table name"); + Assert.That(tableName, Is.EqualTo("result2"), "Matching the table name"); string tableLabel = result2.Columns[i].TableLabel; - Assert.AreEqual("result2", tableLabel, "Matching the table label"); + Assert.That(tableLabel, Is.EqualTo("result2"), "Matching the table label"); string columnName = result2.Columns[i].ColumnName; - Assert.AreEqual(columns2[i].ToString(), columnName, "Matching the Column Name"); + Assert.That(columnName, Is.EqualTo(columns2[i].ToString()), "Matching the Column Name"); string columnLabel = result2.Columns[i].ColumnLabel; - Assert.AreEqual(columns2[i].ToString(), columnLabel, "Matching the Column Label"); + Assert.That(columnLabel, Is.EqualTo(columns2[i].ToString()), "Matching the Column Label"); uint columnLength = result2.Columns[i].Length; - Assert.AreEqual(Length2[i], columnLength, "Matching the Column Length"); + Assert.That(columnLength, Is.EqualTo(Length2[i]), "Matching the Column Length"); var columnType = result2.Columns[i].Type; - Assert.AreEqual(columnTypeMatch2[i], columnType.ToString(), "Matching the Column Type"); + Assert.That(columnType.ToString(), Is.EqualTo(columnTypeMatch2[i]), "Matching the Column Type"); var columnFD = result2.Columns[i].FractionalDigits; - Assert.AreEqual(FDLength2[i], columnFD, "Matching the Column FD"); + Assert.That(columnFD, Is.EqualTo(FDLength2[i]), "Matching the Column FD"); var columnIsSigned = result2.Columns[i].IsNumberSigned; - Assert.AreEqual(columnIsSignedMatch2[i], columnIsSigned.ToString(), "Matching whether column is signed or not"); + Assert.That(columnIsSigned.ToString(), Is.EqualTo(columnIsSignedMatch2[i]), "Matching whether column is signed or not"); string columnCollation = result2.Columns[i].CollationName; if (i == 2) - StringAssert.Contains(defaultCharset, columnCollation, "Matching the Collation Name for default characters"); + Assert.That(columnCollation, Does.Contain(defaultCharset), "Matching the Collation Name for default characters"); else - Assert.AreEqual(null, columnCollation, "Matching the Collation Name as null for data types other than characters"); + Assert.That(columnCollation, Is.EqualTo(null), "Matching the Collation Name as null for data types other than characters"); string columnCharacterSet = result2.Columns[i].CharacterSetName; if (i == 2) - StringAssert.AreEqualIgnoringCase(defaultCharset, columnCharacterSet, "Matching the CharacterSet Name for default characters"); + Assert.That(columnCharacterSet, Is.EqualTo(defaultCharset).IgnoreCase, "Matching the CharacterSet Name for default characters"); else - Assert.AreEqual(null, columnCharacterSet, "Matching the Collation Name as null for data types other than characters"); + Assert.That(columnCharacterSet, Is.EqualTo(null), "Matching the Collation Name as null for data types other than characters"); var columnIsPadded = result2.Columns[i].IsPadded; - Assert.AreEqual(columnIsPaddedMatch2[i], columnIsPadded.ToString(), "Matching whether column is padded or not"); + Assert.That(columnIsPadded.ToString(), Is.EqualTo(columnIsPaddedMatch2[i]), "Matching whether column is padded or not"); var columnClrType = result2.Columns[i].ClrType; - Assert.AreEqual(clrTypeMatch2[i], columnClrType.ToString(), "Matching whether column CLR Type"); + Assert.That(columnClrType.ToString(), Is.EqualTo(clrTypeMatch2[i]), "Matching whether column CLR Type"); } session.SQL("DROP TABLE if exists test").Execute(); @@ -555,95 +555,95 @@ public void ColumnJoin() session.SQL("INSERT INTO test VALUES('Bob')").Execute(); result2 = session.GetSchema(schemaName).GetTable("test").Select("1 + 1 as a", "b").Execute(); var rows = result2.FetchAll(); - Assert.AreEqual(2, result2.Columns.Count, "Matching Column Count"); - - Assert.AreEqual(null, result2.Columns[0].SchemaName, "Matching Column Schema Name"); - Assert.AreEqual(null, result2.Columns[0].TableName, "Matching Column Table Name"); - Assert.AreEqual(null, result2.Columns[0].TableLabel, "Matching Column Table Label"); - Assert.AreEqual(null, result2.Columns[0].ColumnName, "Matching Column Name"); - Assert.AreEqual("a", result2.Columns[0].ColumnLabel, "Matching Column Label"); - Assert.AreEqual("Tinyint", result2.Columns[0].Type.ToString(), "Matching Column Type"); - Assert.AreEqual(3u, result2.Columns[0].Length, "Matching Column Length"); - Assert.AreEqual(0u, result2.Columns[0].FractionalDigits, "Matching Column FD"); - Assert.AreEqual(true, result2.Columns[0].IsNumberSigned, "Matching Column Is Signed"); - Assert.AreEqual(null, result2.Columns[0].CharacterSetName, "Matching Character Set Name"); - Assert.AreEqual(null, result2.Columns[0].CollationName, "Matching Collation Name"); - Assert.AreEqual(false, result2.Columns[0].IsPadded, "Matching Column Padded"); - - Assert.AreEqual(schemaName, result2.Columns[1].SchemaName, "Matching Column Schema Name"); - Assert.AreEqual("test", result2.Columns[1].TableName, "Matching Column Table Name"); - Assert.AreEqual("test", result2.Columns[1].TableLabel, "Matching Column Table Label"); - Assert.AreEqual("b", result2.Columns[1].ColumnName, "Matching Column Name"); - Assert.AreEqual("b", result2.Columns[1].ColumnLabel, "Matching Column Label"); - Assert.AreEqual("String", result2.Columns[1].Type.ToString(), "Matching Column Type"); - Assert.AreEqual(1020u, result2.Columns[1].Length, "Matching Column Length"); - Assert.AreEqual(0u, result2.Columns[1].FractionalDigits, "Matching Column FD"); - Assert.AreEqual(false, result2.Columns[1].IsNumberSigned, "Matching Column Is Signed"); - Assert.AreEqual(defaultCharset, result2.Columns[1].CharacterSetName, "Matching Character Set Name"); - StringAssert.Contains(defaultCharset, result2.Columns[1].CollationName, "Matching Collation Name"); - Assert.AreEqual(false, result2.Columns[1].IsPadded, "Matching Column Padded"); + Assert.That(result2.Columns.Count, Is.EqualTo(2), "Matching Column Count"); + + Assert.That(result2.Columns[0].SchemaName, Is.EqualTo(null), "Matching Column Schema Name"); + Assert.That(result2.Columns[0].TableName, Is.EqualTo(null), "Matching Column Table Name"); + Assert.That(result2.Columns[0].TableLabel, Is.EqualTo(null), "Matching Column Table Label"); + Assert.That(result2.Columns[0].ColumnName, Is.EqualTo(null), "Matching Column Name"); + Assert.That(result2.Columns[0].ColumnLabel, Is.EqualTo("a"), "Matching Column Label"); + Assert.That(result2.Columns[0].Type.ToString(), Is.EqualTo("Tinyint"), "Matching Column Type"); + Assert.That(result2.Columns[0].Length, Is.EqualTo(3u), "Matching Column Length"); + Assert.That(result2.Columns[0].FractionalDigits, Is.EqualTo(0u), "Matching Column FD"); + Assert.That(result2.Columns[0].IsNumberSigned, Is.EqualTo(true), "Matching Column Is Signed"); + Assert.That(result2.Columns[0].CharacterSetName, Is.EqualTo(null), "Matching Character Set Name"); + Assert.That(result2.Columns[0].CollationName, Is.EqualTo(null), "Matching Collation Name"); + Assert.That(result2.Columns[0].IsPadded, Is.EqualTo(false), "Matching Column Padded"); + + Assert.That(result2.Columns[1].SchemaName, Is.EqualTo(schemaName), "Matching Column Schema Name"); + Assert.That(result2.Columns[1].TableName, Is.EqualTo("test"), "Matching Column Table Name"); + Assert.That(result2.Columns[1].TableLabel, Is.EqualTo("test"), "Matching Column Table Label"); + Assert.That(result2.Columns[1].ColumnName, Is.EqualTo("b"), "Matching Column Name"); + Assert.That(result2.Columns[1].ColumnLabel, Is.EqualTo("b"), "Matching Column Label"); + Assert.That(result2.Columns[1].Type.ToString(), Is.EqualTo("String"), "Matching Column Type"); + Assert.That(result2.Columns[1].Length, Is.EqualTo(1020u), "Matching Column Length"); + Assert.That(result2.Columns[1].FractionalDigits, Is.EqualTo(0u), "Matching Column FD"); + Assert.That(result2.Columns[1].IsNumberSigned, Is.EqualTo(false), "Matching Column Is Signed"); + Assert.That(result2.Columns[1].CharacterSetName, Is.EqualTo(defaultCharset), "Matching Character Set Name"); + Assert.That(result2.Columns[1].CollationName, Does.Contain(defaultCharset), "Matching Collation Name"); + Assert.That(result2.Columns[1].IsPadded, Is.EqualTo(false), "Matching Column Padded"); session.SQL("create table test1(c1 int,c2 double GENERATED ALWAYS AS (c1*101/102) Stored COMMENT 'First Gen Col',c3 Json GENERATED ALWAYS AS (concat('{\"F1\":',c1,'}')) VIRTUAL COMMENT 'Second Gen /**/Col', c4 bigint GENERATED ALWAYS as (c1*10000) VIRTUAL UNIQUE KEY Comment '3rd Col' NOT NULL)").Execute(); session.SQL("insert into test1(c1) values(1000)").Execute(); result2 = session.GetSchema(schemaName).GetTable("test1").Select("c1").Execute(); - Assert.AreEqual(schemaName, result2.Columns[0].SchemaName, "Matching Column Schema Name"); - Assert.AreEqual("test1", result2.Columns[0].TableName, "Matching Column Table Name"); - Assert.AreEqual("test1", result2.Columns[0].TableLabel, "Matching Column Table Label"); - Assert.AreEqual("c1", result2.Columns[0].ColumnName, "Matching Column Name"); - Assert.AreEqual("c1", result2.Columns[0].ColumnLabel, "Matching Column Label"); - Assert.AreEqual("Int", result2.Columns[0].Type.ToString(), "Matching Column Type"); - Assert.AreEqual(11, result2.Columns[0].Length, "Matching Column Length"); - Assert.AreEqual(0u, result2.Columns[0].FractionalDigits, "Matching Column FD"); - Assert.AreEqual(true, result2.Columns[0].IsNumberSigned, "Matching Column Is Signed"); - Assert.AreEqual(null, result2.Columns[0].CharacterSetName, "Matching Character Set Name"); - Assert.AreEqual(null, result2.Columns[0].CollationName, "Matching Collation Name"); - Assert.AreEqual(false, result2.Columns[0].IsPadded, "Matching Column Padded"); + Assert.That(result2.Columns[0].SchemaName, Is.EqualTo(schemaName), "Matching Column Schema Name"); + Assert.That(result2.Columns[0].TableName, Is.EqualTo("test1"), "Matching Column Table Name"); + Assert.That(result2.Columns[0].TableLabel, Is.EqualTo("test1"), "Matching Column Table Label"); + Assert.That(result2.Columns[0].ColumnName, Is.EqualTo("c1"), "Matching Column Name"); + Assert.That(result2.Columns[0].ColumnLabel, Is.EqualTo("c1"), "Matching Column Label"); + Assert.That(result2.Columns[0].Type.ToString(), Is.EqualTo("Int"), "Matching Column Type"); + Assert.That(result2.Columns[0].Length, Is.EqualTo(11), "Matching Column Length"); + Assert.That(result2.Columns[0].FractionalDigits, Is.EqualTo(0u), "Matching Column FD"); + Assert.That(result2.Columns[0].IsNumberSigned, Is.EqualTo(true), "Matching Column Is Signed"); + Assert.That(result2.Columns[0].CharacterSetName, Is.EqualTo(null), "Matching Character Set Name"); + Assert.That(result2.Columns[0].CollationName, Is.EqualTo(null), "Matching Collation Name"); + Assert.That(result2.Columns[0].IsPadded, Is.EqualTo(false), "Matching Column Padded"); result2 = session.GetSchema(schemaName).GetTable("test1").Select("c2").Execute(); - Assert.AreEqual(schemaName, result2.Columns[0].SchemaName, "Matching Column Schema Name"); - Assert.AreEqual("test1", result2.Columns[0].TableName, "Matching Column Table Name"); - Assert.AreEqual("test1", result2.Columns[0].TableLabel, "Matching Column Table Label"); - Assert.AreEqual("c2", result2.Columns[0].ColumnName, "Matching Column Name"); - Assert.AreEqual("c2", result2.Columns[0].ColumnLabel, "Matching Column Label"); - Assert.AreEqual("Double", result2.Columns[0].Type.ToString(), "Matching Column Type"); - Assert.AreEqual(22, result2.Columns[0].Length, "Matching Column Length"); - Assert.AreEqual(31, result2.Columns[0].FractionalDigits, "Matching Column FD"); - Assert.AreEqual(false, result2.Columns[0].IsNumberSigned, "Matching Column Is Signed"); - Assert.AreEqual(null, result2.Columns[0].CharacterSetName, "Matching Character Set Name"); - Assert.AreEqual(null, result2.Columns[0].CollationName, "Matching Collation Name"); - Assert.AreEqual(false, result2.Columns[0].IsPadded, "Matching Column Padded"); + Assert.That(result2.Columns[0].SchemaName, Is.EqualTo(schemaName), "Matching Column Schema Name"); + Assert.That(result2.Columns[0].TableName, Is.EqualTo("test1"), "Matching Column Table Name"); + Assert.That(result2.Columns[0].TableLabel, Is.EqualTo("test1"), "Matching Column Table Label"); + Assert.That(result2.Columns[0].ColumnName, Is.EqualTo("c2"), "Matching Column Name"); + Assert.That(result2.Columns[0].ColumnLabel, Is.EqualTo("c2"), "Matching Column Label"); + Assert.That(result2.Columns[0].Type.ToString(), Is.EqualTo("Double"), "Matching Column Type"); + Assert.That(result2.Columns[0].Length, Is.EqualTo(22), "Matching Column Length"); + Assert.That(result2.Columns[0].FractionalDigits, Is.EqualTo(31), "Matching Column FD"); + Assert.That(result2.Columns[0].IsNumberSigned, Is.EqualTo(false), "Matching Column Is Signed"); + Assert.That(result2.Columns[0].CharacterSetName, Is.EqualTo(null), "Matching Character Set Name"); + Assert.That(result2.Columns[0].CollationName, Is.EqualTo(null), "Matching Collation Name"); + Assert.That(result2.Columns[0].IsPadded, Is.EqualTo(false), "Matching Column Padded"); result2 = session.GetSchema(schemaName).GetTable("test1").Select("c3").Execute(); - Assert.AreEqual(schemaName, result2.Columns[0].SchemaName, "Matching Column Schema Name"); - Assert.AreEqual("test1", result2.Columns[0].TableName, "Matching Column Table Name"); - Assert.AreEqual("test1", result2.Columns[0].TableLabel, "Matching Column Table Label"); - Assert.AreEqual("c3", result2.Columns[0].ColumnName, "Matching Column Name"); - Assert.AreEqual("c3", result2.Columns[0].ColumnLabel, "Matching Column Label"); - Assert.AreEqual("Json", result2.Columns[0].Type.ToString(), "Matching Column Type"); - Assert.AreEqual(4294967295, result2.Columns[0].Length, "Matching Column Length"); - Assert.AreEqual(0u, result2.Columns[0].FractionalDigits, "Matching Column FD"); - Assert.AreEqual(false, result2.Columns[0].IsNumberSigned, "Matching Column Is Signed"); - Assert.AreEqual("binary", result2.Columns[0].CharacterSetName, "Matching Character Set Name"); - Assert.AreEqual("binary", result2.Columns[0].CollationName, "Matching Collation Name"); - Assert.AreEqual(false, result2.Columns[0].IsPadded, "Matching Column Padded"); + Assert.That(result2.Columns[0].SchemaName, Is.EqualTo(schemaName), "Matching Column Schema Name"); + Assert.That(result2.Columns[0].TableName, Is.EqualTo("test1"), "Matching Column Table Name"); + Assert.That(result2.Columns[0].TableLabel, Is.EqualTo("test1"), "Matching Column Table Label"); + Assert.That(result2.Columns[0].ColumnName, Is.EqualTo("c3"), "Matching Column Name"); + Assert.That(result2.Columns[0].ColumnLabel, Is.EqualTo("c3"), "Matching Column Label"); + Assert.That(result2.Columns[0].Type.ToString(), Is.EqualTo("Json"), "Matching Column Type"); + Assert.That(result2.Columns[0].Length, Is.EqualTo(4294967295), "Matching Column Length"); + Assert.That(result2.Columns[0].FractionalDigits, Is.EqualTo(0u), "Matching Column FD"); + Assert.That(result2.Columns[0].IsNumberSigned, Is.EqualTo(false), "Matching Column Is Signed"); + Assert.That(result2.Columns[0].CharacterSetName, Is.EqualTo("binary"), "Matching Character Set Name"); + Assert.That(result2.Columns[0].CollationName, Is.EqualTo("binary"), "Matching Collation Name"); + Assert.That(result2.Columns[0].IsPadded, Is.EqualTo(false), "Matching Column Padded"); result2 = session.GetSchema(schemaName).GetTable("test1").Select("c4").Execute(); - Assert.AreEqual(schemaName, result2.Columns[0].SchemaName, "Matching Column Schema Name"); - Assert.AreEqual("test1", result2.Columns[0].TableName, "Matching Column Table Name"); - Assert.AreEqual("test1", result2.Columns[0].TableLabel, "Matching Column Table Label"); - Assert.AreEqual("c4", result2.Columns[0].ColumnName, "Matching Column Name"); - Assert.AreEqual("c4", result2.Columns[0].ColumnLabel, "Matching Column Label"); - Assert.AreEqual("Bigint", result2.Columns[0].Type.ToString(), "Matching Column Type"); - Assert.AreEqual(20, result2.Columns[0].Length, "Matching Column Length"); - Assert.AreEqual(0u, result2.Columns[0].FractionalDigits, "Matching Column FD"); - Assert.AreEqual(true, result2.Columns[0].IsNumberSigned, "Matching Column Is Signed"); - Assert.AreEqual(null, result2.Columns[0].CharacterSetName, "Matching Character Set Name"); - Assert.AreEqual(null, result2.Columns[0].CollationName, "Matching Collation Name"); - Assert.AreEqual(false, result2.Columns[0].IsPadded, "Matching Column Padded"); + Assert.That(result2.Columns[0].SchemaName, Is.EqualTo(schemaName), "Matching Column Schema Name"); + Assert.That(result2.Columns[0].TableName, Is.EqualTo("test1"), "Matching Column Table Name"); + Assert.That(result2.Columns[0].TableLabel, Is.EqualTo("test1"), "Matching Column Table Label"); + Assert.That(result2.Columns[0].ColumnName, Is.EqualTo("c4"), "Matching Column Name"); + Assert.That(result2.Columns[0].ColumnLabel, Is.EqualTo("c4"), "Matching Column Label"); + Assert.That(result2.Columns[0].Type.ToString(), Is.EqualTo("Bigint"), "Matching Column Type"); + Assert.That(result2.Columns[0].Length, Is.EqualTo(20), "Matching Column Length"); + Assert.That(result2.Columns[0].FractionalDigits, Is.EqualTo(0u), "Matching Column FD"); + Assert.That(result2.Columns[0].IsNumberSigned, Is.EqualTo(true), "Matching Column Is Signed"); + Assert.That(result2.Columns[0].CharacterSetName, Is.EqualTo(null), "Matching Character Set Name"); + Assert.That(result2.Columns[0].CollationName, Is.EqualTo(null), "Matching Collation Name"); + Assert.That(result2.Columns[0].IsPadded, Is.EqualTo(false), "Matching Column Padded"); session.SQL("DROP TABLE if exists test").Execute(); session.SQL("DROP TABLE if exists test1").Execute(); @@ -684,33 +684,33 @@ public void ColumnCharacterDefaultDatatype() for (int i = 0; i < columns.Length; i++) { string tableLabel = result.Columns[i].TableLabel; - Assert.AreEqual("address", tableLabel, "Matching the table label"); + Assert.That(tableLabel, Is.EqualTo("address"), "Matching the table label"); string columnName = result.Columns[i].ColumnName; - Assert.AreEqual(columns[i].ToString(), columnName, "Matching the Column Name"); + Assert.That(columnName, Is.EqualTo(columns[i].ToString()), "Matching the Column Name"); string columnLabel = result.Columns[i].ColumnLabel; - Assert.AreEqual(columns[i].ToString(), columnLabel, "Matching the Column Label"); + Assert.That(columnLabel, Is.EqualTo(columns[i].ToString()), "Matching the Column Label"); uint columnLength = result.Columns[i].Length; - Assert.AreEqual(columnLength, columnLength, "Matching the Column Length"); + Assert.That(columnLength, Is.EqualTo(columnLength), "Matching the Column Length"); var columnType = result.Columns[i].Type; - Assert.AreEqual(columnTypeMatch[i], columnType.ToString(), "Matching the Column Type"); + Assert.That(columnType.ToString(), Is.EqualTo(columnTypeMatch[i]), "Matching the Column Type"); var columnFD = result.Columns[i].FractionalDigits; - Assert.AreEqual(FDLength[i], columnFD, "Matching the Column FD"); + Assert.That(columnFD, Is.EqualTo(FDLength[i]), "Matching the Column FD"); var columnIsSigned = result.Columns[i].IsNumberSigned; - Assert.AreEqual(columnIsSignedMatch[i], columnIsSigned.ToString(), "Matching whether column is signed or not"); + Assert.That(columnIsSigned.ToString(), Is.EqualTo(columnIsSignedMatch[i]), "Matching whether column is signed or not"); string columnCollation = result.Columns[i].CollationName; if (i == 1 || i == 2 || i == 3 || i == 4 || i == 5) - Assert.AreEqual(columnCollation, columnCollation, "Matching the Collation Name for default characters"); + Assert.That(columnCollation, Is.EqualTo(columnCollation), "Matching the Collation Name for default characters"); else - Assert.AreEqual(null, columnCollation, "Matching the Collation Name as null for data types other than characters"); + Assert.That(columnCollation, Is.EqualTo(null), "Matching the Collation Name as null for data types other than characters"); string columnCharacterSet = result.Columns[i].CharacterSetName; if (i == 1 || i == 2 || i == 3 || i == 4 || i == 5) - Assert.AreEqual(columnCharacterSet, columnCharacterSet, "Matching the CharacterSet Name for default characters"); + Assert.That(columnCharacterSet, Is.EqualTo(columnCharacterSet), "Matching the CharacterSet Name for default characters"); else - Assert.AreEqual(null, columnCharacterSet, "Matching the Collation Name as null for data types other than characters"); + Assert.That(columnCharacterSet, Is.EqualTo(null), "Matching the Collation Name as null for data types other than characters"); var columnIsPadded = result.Columns[i].IsPadded; - Assert.AreEqual(columnIsPaddedMatch[i], columnIsPadded.ToString(), "Matching whether column is padded or not"); + Assert.That(columnIsPadded.ToString(), Is.EqualTo(columnIsPaddedMatch[i]), "Matching whether column is padded or not"); var columnClrType = result.Columns[i].ClrType; - Assert.AreEqual(clrTypeMatch[i], columnClrType.ToString(), "Matching whether column CLR Type"); + Assert.That(columnClrType.ToString(), Is.EqualTo(clrTypeMatch[i]), "Matching whether column CLR Type"); } session.SQL("DROP TABLE if exists address").Execute(); } @@ -747,33 +747,33 @@ public void ColumnCharacterCustomDatatype() for (int i = 0; i < columns.Length; i++) { string tableLabel = result.Columns[i].TableLabel; - Assert.AreEqual("address", tableLabel, "Matching the table label"); + Assert.That(tableLabel, Is.EqualTo("address"), "Matching the table label"); string columnName = result.Columns[i].ColumnName; - Assert.AreEqual(columns[i].ToString(), columnName, "Matching the Column Name"); + Assert.That(columnName, Is.EqualTo(columns[i].ToString()), "Matching the Column Name"); string columnLabel = result.Columns[i].ColumnLabel; - Assert.AreEqual(columns[i].ToString(), columnLabel, "Matching the Column Label"); + Assert.That(columnLabel, Is.EqualTo(columns[i].ToString()), "Matching the Column Label"); uint columnLength = result.Columns[i].Length; - Assert.AreEqual(Length[i], columnLength, "Matching the Column Length"); + Assert.That(columnLength, Is.EqualTo(Length[i]), "Matching the Column Length"); var columnType = result.Columns[i].Type; - Assert.AreEqual(columnTypeMatch[i], columnType.ToString(), "Matching the Column Type"); + Assert.That(columnType.ToString(), Is.EqualTo(columnTypeMatch[i]), "Matching the Column Type"); var columnFD = result.Columns[i].FractionalDigits; - Assert.AreEqual(FDLength[i], columnFD, "Matching the Column FD"); + Assert.That(columnFD, Is.EqualTo(FDLength[i]), "Matching the Column FD"); var columnIsSigned = result.Columns[i].IsNumberSigned; - Assert.AreEqual(columnIsSignedMatch[i], columnIsSigned.ToString(), "Matching whether column is signed or not"); + Assert.That(columnIsSigned.ToString(), Is.EqualTo(columnIsSignedMatch[i]), "Matching whether column is signed or not"); string columnCollation = result.Columns[i].CollationName; if (i == 1 || i == 2 || i == 3 || i == 4 || i == 5) - StringAssert.Contains(defaultCharset, columnCollation, "Matching the Collation Name for big5_chinese_ci characters"); + Assert.That(columnCollation, Does.Contain(defaultCharset), "Matching the Collation Name for big5_chinese_ci characters"); else - Assert.AreEqual(null, columnCollation, "Matching the Collation Name as null for data types other than characters"); + Assert.That(columnCollation, Is.EqualTo(null), "Matching the Collation Name as null for data types other than characters"); string columnCharacterSet = result.Columns[i].CharacterSetName; if (i == 1 || i == 2 || i == 3 || i == 4 || i == 5) - StringAssert.AreEqualIgnoringCase(defaultCharset, columnCharacterSet, "Matching the CharacterSet Name for big5 characters"); + Assert.That(columnCharacterSet, Is.EqualTo(defaultCharset).IgnoreCase, "Matching the CharacterSet Name for big5 characters"); else - Assert.AreEqual(null, columnCharacterSet, "Matching the Collation Name as null for data types other than characters"); + Assert.That(columnCharacterSet, Is.EqualTo(null), "Matching the Collation Name as null for data types other than characters"); var columnIsPadded = result.Columns[i].IsPadded; - Assert.AreEqual(columnIsPaddedMatch[i], columnIsPadded.ToString(), "Matching whether column is padded or not"); + Assert.That(columnIsPadded.ToString(), Is.EqualTo(columnIsPaddedMatch[i]), "Matching whether column is padded or not"); var columnClrType = result.Columns[i].ClrType; - Assert.AreEqual(clrTypeMatch[i], columnClrType.ToString(), "Matching whether column CLR Type"); + Assert.That(columnClrType.ToString(), Is.EqualTo(clrTypeMatch[i]), "Matching whether column CLR Type"); } session.SQL("Drop table if exists address").Execute(); } @@ -790,29 +790,29 @@ public void ColumnCharacterGeometricDatatype() for (int i = 0; i < columns.Length; i++) { string tableName = result.Columns[i].TableName; - Assert.AreEqual("geotest", tableName, "Matching the table name"); + Assert.That(tableName, Is.EqualTo("geotest"), "Matching the table name"); string tableLabel = result.Columns[i].TableLabel; - Assert.AreEqual("geotest", tableLabel, "Matching the table label"); + Assert.That(tableLabel, Is.EqualTo("geotest"), "Matching the table label"); string columnName = result.Columns[i].ColumnName; - Assert.AreEqual(columns[i].ToString(), columnName, "Matching the Column Name"); + Assert.That(columnName, Is.EqualTo(columns[i].ToString()), "Matching the Column Name"); string columnLabel = result.Columns[i].ColumnLabel; - Assert.AreEqual(columns[i].ToString(), columnLabel, "Matching the Column Label"); + Assert.That(columnLabel, Is.EqualTo(columns[i].ToString()), "Matching the Column Label"); uint columnLength = result.Columns[i].Length; - Assert.AreEqual(0, columnLength, "Matching the Column Length"); + Assert.That(columnLength, Is.EqualTo(0), "Matching the Column Length"); var columnType = result.Columns[i].Type; - Assert.AreEqual("Geometry", columnType.ToString(), "Matching the Column Type"); + Assert.That(columnType.ToString(), Is.EqualTo("Geometry"), "Matching the Column Type"); var columnFD = result.Columns[i].FractionalDigits; - Assert.AreEqual(0, columnFD, "Matching the Column FD"); + Assert.That(columnFD, Is.EqualTo(0), "Matching the Column FD"); var columnIsSigned = result.Columns[i].IsNumberSigned; - Assert.AreEqual(false, columnIsSigned, "Matching whether column is signed or not"); + Assert.That(columnIsSigned, Is.EqualTo(false), "Matching whether column is signed or not"); string columnCollation = result.Columns[i].CollationName; - Assert.AreEqual(null, columnCollation, "Matching the Collation Name for default characters"); + Assert.That(columnCollation, Is.EqualTo(null), "Matching the Collation Name for default characters"); string columnCharacterSet = result.Columns[i].CharacterSetName; - Assert.AreEqual(null, columnCharacterSet, "Matching the Collation Name as null for data types other than characters"); + Assert.That(columnCharacterSet, Is.EqualTo(null), "Matching the Collation Name as null for data types other than characters"); var columnIsPadded = result.Columns[i].IsPadded; - Assert.AreEqual(false, columnIsPadded, "Matching whether column is padded or not"); + Assert.That(columnIsPadded, Is.EqualTo(false), "Matching whether column is padded or not"); var columnClrType = result.Columns[i].ClrType; - Assert.AreEqual("System.Byte[]", columnClrType.ToString(), "Matching whether column CLR Type"); + Assert.That(columnClrType.ToString(), Is.EqualTo("System.Byte[]"), "Matching whether column CLR Type"); } } @@ -832,30 +832,30 @@ public void ColumnCharacterBlobDatatype() for (int i = 0; i < columns.Length; i++) { string tableName = result.Columns[i].TableName; - Assert.AreEqual("geotest", tableName, "Matching the table name"); + Assert.That(tableName, Is.EqualTo("geotest"), "Matching the table name"); string tableLabel = result.Columns[i].TableLabel; - Assert.AreEqual("geotest", tableLabel, "Matching the table label"); + Assert.That(tableLabel, Is.EqualTo("geotest"), "Matching the table label"); string columnName = result.Columns[i].ColumnName; - Assert.AreEqual(columns[i].ToString(), columnName, "Matching the Column Name"); + Assert.That(columnName, Is.EqualTo(columns[i].ToString()), "Matching the Column Name"); string columnLabel = result.Columns[i].ColumnLabel; - Assert.AreEqual(columns[i].ToString(), columnLabel, "Matching the Column Label"); + Assert.That(columnLabel, Is.EqualTo(columns[i].ToString()), "Matching the Column Label"); uint columnLength = result.Columns[i].Length; - Assert.AreEqual(ColumnLength[i], columnLength, "Matching the Column Length"); + Assert.That(columnLength, Is.EqualTo(ColumnLength[i]), "Matching the Column Length"); var columnType = result.Columns[i].Type; - Assert.AreEqual(columnTypeMatch[i], columnType.ToString(), "Matching the Column Type"); + Assert.That(columnType.ToString(), Is.EqualTo(columnTypeMatch[i]), "Matching the Column Type"); var columnFD = result.Columns[i].FractionalDigits; - Assert.AreEqual(0, columnFD, "Matching the Column FD"); + Assert.That(columnFD, Is.EqualTo(0), "Matching the Column FD"); var columnIsSigned = result.Columns[i].IsNumberSigned; - Assert.AreEqual("False", columnIsSigned.ToString(), "Matching whether column is signed or not"); + Assert.That(columnIsSigned.ToString(), Is.EqualTo("False"), "Matching whether column is signed or not"); string columnCollation = result.Columns[i].CollationName; - Assert.AreEqual("binary", columnCollation, "Matching the Collation Name for default characters"); + Assert.That(columnCollation, Is.EqualTo("binary"), "Matching the Collation Name for default characters"); string columnCharacterSet = result.Columns[i].CharacterSetName; //Character name returns binary for blob - Assert.AreEqual("binary", columnCharacterSet, "Matching the Collation Name as null for data types other than characters"); + Assert.That(columnCharacterSet, Is.EqualTo("binary"), "Matching the Collation Name as null for data types other than characters"); var columnIsPadded = result.Columns[i].IsPadded; - Assert.AreEqual("False", columnIsPadded.ToString(), "Matching whether column is padded or not"); + Assert.That(columnIsPadded.ToString(), Is.EqualTo("False"), "Matching whether column is padded or not"); var columnClrType = result.Columns[i].ClrType; - Assert.AreEqual("System.Byte[]", columnClrType.ToString(), "Matching whether column CLR Type"); + Assert.That(columnClrType.ToString(), Is.EqualTo("System.Byte[]"), "Matching whether column CLR Type"); } } @@ -876,7 +876,7 @@ public void LanguageSpecificCollations() var database_name = "collation_test"; session.DropSchema(database_name); var CommandText1 = "SHOW VARIABLES LIKE 'collation_%';"; - Assert.AreEqual(charset, session.Settings.CharacterSet, "Matching the character set of the session"); + Assert.That(session.Settings.CharacterSet, Is.EqualTo(charset), "Matching the character set of the session"); for (var i = 0; i < collationname.Length; i++) { @@ -886,18 +886,18 @@ public void LanguageSpecificCollations() session.SQL("USE " + database_name).Execute(); session.SQL("create table x(id int,name char(25));").Execute(); var res = session.SQL("insert into x values(10,'AXTREF');").Execute(); - Assert.AreEqual(1, res.AffectedItemsCount); + Assert.That(res.AffectedItemsCount, Is.EqualTo(1)); session.SQL("insert into x values(20,'Trädgårdsvägen');").Execute(); - Assert.AreEqual(1, res.AffectedItemsCount); + Assert.That(res.AffectedItemsCount, Is.EqualTo(1)); session.SQL("insert into x values(30,'foo𝌆bar');").Execute(); - Assert.AreEqual(1, res.AffectedItemsCount); + Assert.That(res.AffectedItemsCount, Is.EqualTo(1)); session.SQL("insert into x values(40,'Dolphin:🐬');").Execute(); - Assert.AreEqual(1, res.AffectedItemsCount); + Assert.That(res.AffectedItemsCount, Is.EqualTo(1)); var dbCharset = session.SQL("select @@character_set_database;").Execute().FirstOrDefault(); var dbCollation = session.SQL("select @@collation_database").Execute().FirstOrDefault(); - Assert.AreEqual(dbCharset[0], charset); - Assert.AreEqual(dbCollation[0], collationname[i]); + Assert.That(charset, Is.EqualTo(dbCharset[0])); + Assert.That(collationname[i], Is.EqualTo(dbCollation[0])); session.DropSchema(database_name); } } @@ -926,7 +926,7 @@ public void VerifyRenamedCollations() var database_name = "collation_test"; session.DropSchema(database_name); - Assert.AreEqual(charset, sessionX.Settings.CharacterSet, "Matching the character set of the session"); + Assert.That(sessionX.Settings.CharacterSet, Is.EqualTo(charset), "Matching the character set of the session"); for (var i = 0; i < collationname.Length; i++) { @@ -935,18 +935,18 @@ public void VerifyRenamedCollations() sessionX.SQL("USE " + database_name).Execute(); sessionX.SQL("CREATE TABLE x(id int,name char(25));").Execute(); var res = sessionX.SQL("insert into x values(10,'AXTREF');").Execute(); - Assert.AreEqual(1, res.AffectedItemsCount); + Assert.That(res.AffectedItemsCount, Is.EqualTo(1)); sessionX.SQL("insert into x values(20,'Trädgårdsvägen');").Execute(); - Assert.AreEqual(1, res.AffectedItemsCount); + Assert.That(res.AffectedItemsCount, Is.EqualTo(1)); sessionX.SQL("insert into x values(30,'foo𝌆bar');").Execute(); - Assert.AreEqual(1, res.AffectedItemsCount); + Assert.That(res.AffectedItemsCount, Is.EqualTo(1)); sessionX.SQL("insert into x values(40,'Dolphin:🐬');").Execute(); - Assert.AreEqual(1, res.AffectedItemsCount); + Assert.That(res.AffectedItemsCount, Is.EqualTo(1)); var dbCharset = sessionX.SQL("select @@character_set_database;").Execute().FirstOrDefault(); var dbCollation = sessionX.SQL("select @@collation_database").Execute().FirstOrDefault(); - Assert.AreEqual(dbCharset[0], charset); - Assert.AreEqual(dbCollation[0], collationname[i]); + Assert.That(charset, Is.EqualTo(dbCharset[0])); + Assert.That(collationname[i], Is.EqualTo(dbCollation[0])); sessionX.DropSchema(database_name); } } @@ -962,7 +962,7 @@ public void VerifyLatinCharsetAndCollation() var charset = "latin1"; var collationname = "latin1_danish_ci"; var defaultCharset = "utf8mb4"; - Assert.AreEqual(defaultCharset, session.Settings.CharacterSet, "Matching the character set of the session"); + Assert.That(session.Settings.CharacterSet, Is.EqualTo(defaultCharset), "Matching the character set of the session"); session.DropSchema(database_name); var CommandText1 = $"CREATE DATABASE {database_name} CHARACTER SET {charset} COLLATE {collationname}"; session.SQL(CommandText1).Execute(); @@ -970,11 +970,11 @@ public void VerifyLatinCharsetAndCollation() session.SQL("create table x(id int,name char(25));").Execute(); session.SQL("insert into x values(10,'AXTREF');").Execute(); RowResult result1 = session.GetSchema(database_name).GetTable("x").Select("id").Execute(); - Assert.AreEqual(null, result1.Columns[0].CharacterSetName, "id-charset"); - Assert.AreEqual(null, result1.Columns[0].CollationName, "id-collation"); + Assert.That(result1.Columns[0].CharacterSetName, Is.EqualTo(null), "id-charset"); + Assert.That(result1.Columns[0].CollationName, Is.EqualTo(null), "id-collation"); result1 = session.GetSchema(database_name).GetTable("x").Select("name").Execute(); - StringAssert.AreEqualIgnoringCase(defaultCharset, result1.Columns[0].CharacterSetName, "name-charset"); - StringAssert.Contains(defaultCharset, result1.Columns[0].CollationName, "name-collation"); + Assert.That(result1.Columns[0].CharacterSetName, Is.EqualTo(defaultCharset).IgnoreCase, "name-charset"); + Assert.That(result1.Columns[0].CollationName, Does.Contain(defaultCharset), "name-collation"); session.DropSchema(database_name); } @@ -997,7 +997,7 @@ public void Utf8mb4BinaryNopadCollationTable() var database_name = "collation_test"; - Assert.AreEqual(charset, session.Settings.CharacterSet, "Matching the character set of the session"); + Assert.That(session.Settings.CharacterSet, Is.EqualTo(charset), "Matching the character set of the session"); session.DropSchema(database_name); CommandText1 = "CREATE DATABASE " + database_name; var sqlRes = session.SQL(CommandText1).Execute(); @@ -1006,13 +1006,13 @@ public void Utf8mb4BinaryNopadCollationTable() Table t = session.GetSchema(database_name).GetTable("t"); t.Insert().Values(foo).Execute(); Row r = t.Select().Limit(1).Execute().FetchOne(); - Assert.AreEqual(foo, r[0].ToString(), "Compare extracted string"); + Assert.That(r[0].ToString(), Is.EqualTo(foo), "Compare extracted string"); session.DropSchema(database_name); CommandText1 = "SHOW VARIABLES LIKE 'collation_%';"; sqlRes = session.SQL(CommandText1).Execute(); while (sqlRes.Next()) ; - Assert.AreEqual(collation, sqlRes.Rows.ToArray()[0][1].ToString(), "Matching the collation"); + Assert.That(sqlRes.Rows.ToArray()[0][1].ToString(), Is.EqualTo(collation), "Matching the collation"); for (var i = 0; i < collationname.Count; i++) { @@ -1026,15 +1026,15 @@ public void Utf8mb4BinaryNopadCollationTable() session.SQL("insert into x values(40,'Dolphin:🐬');").Execute(); t = session.GetSchema(database_name).GetTable("x"); var res = t.Select().Execute().FetchAll(); - Assert.AreEqual("AXTREF", res[0][1].ToString(), "Matching the data"); - Assert.AreEqual("Trädgårdsvägen", res[1][1].ToString(), "Matching the data"); - Assert.AreEqual("foo𝌆bar", res[2][1].ToString(), "Matching the data"); - Assert.AreEqual("Dolphin:🐬", res[3][1].ToString(), "Matching the data"); + Assert.That(res[0][1].ToString(), Is.EqualTo("AXTREF"), "Matching the data"); + Assert.That(res[1][1].ToString(), Is.EqualTo("Trädgårdsvägen"), "Matching the data"); + Assert.That(res[2][1].ToString(), Is.EqualTo("foo𝌆bar"), "Matching the data"); + Assert.That(res[3][1].ToString(), Is.EqualTo("Dolphin:🐬"), "Matching the data"); RowResult result_collation = t.Select("name").Execute(); var collationName = result_collation.Columns[0].CollationName; - Assert.AreEqual(collationname[i], collationName, "Matching the collation"); + Assert.That(collationName, Is.EqualTo(collationname[i]), "Matching the collation"); var characterName = result_collation.Columns[0].CharacterSetName; - Assert.AreEqual(charset, characterName, "Matching the charset"); + Assert.That(characterName, Is.EqualTo(charset), "Matching the charset"); session.DropSchema(database_name); } @@ -1050,15 +1050,15 @@ public void Utf8mb4BinaryNopadCollationTable() session.SQL("insert into x values(40,'Dolphin:🐬');").Execute(); t = session.GetSchema(database_name).GetTable("x"); var res = t.Select().Execute().FetchAll(); - Assert.AreEqual("AXTREF", res[0][1].ToString(), "Matching the data"); - Assert.AreEqual("Trädgårdsvägen", res[1][1].ToString(), "Matching the data"); - Assert.AreEqual("foo𝌆bar", res[2][1].ToString(), "Matching the data"); - Assert.AreEqual("Dolphin:🐬", res[3][1].ToString(), "Matching the data"); + Assert.That(res[0][1].ToString(), Is.EqualTo("AXTREF"), "Matching the data"); + Assert.That(res[1][1].ToString(), Is.EqualTo("Trädgårdsvägen"), "Matching the data"); + Assert.That(res[2][1].ToString(), Is.EqualTo("foo𝌆bar"), "Matching the data"); + Assert.That(res[3][1].ToString(), Is.EqualTo("Dolphin:🐬"), "Matching the data"); RowResult result_collation = t.Select("name").Execute(); var collationName = result_collation.Columns[0].CollationName; - Assert.AreEqual(collationname[i], collationName, "Matching the collation"); + Assert.That(collationName, Is.EqualTo(collationname[i]), "Matching the collation"); var characterName = result_collation.Columns[0].CharacterSetName; - Assert.AreEqual(charset, characterName, "Matching the charset"); + Assert.That(characterName, Is.EqualTo(charset), "Matching the charset"); session.DropSchema(database_name); //ALTER CommandText1 = "CREATE DATABASE " + database_name; @@ -1072,15 +1072,15 @@ public void Utf8mb4BinaryNopadCollationTable() session.SQL("insert into x values(40,'Dolphin:🐬');").Execute(); t = session.GetSchema(database_name).GetTable("x"); res = t.Select().Execute().FetchAll(); - Assert.AreEqual("AXTREF", res[0][1].ToString(), "Matching the data"); - Assert.AreEqual("Trädgårdsvägen", res[1][1].ToString(), "Matching the data"); - Assert.AreEqual("foo𝌆bar", res[2][1].ToString(), "Matching the data"); - Assert.AreEqual("Dolphin:🐬", res[3][1].ToString(), "Matching the data"); + Assert.That(res[0][1].ToString(), Is.EqualTo("AXTREF"), "Matching the data"); + Assert.That(res[1][1].ToString(), Is.EqualTo("Trädgårdsvägen"), "Matching the data"); + Assert.That(res[2][1].ToString(), Is.EqualTo("foo𝌆bar"), "Matching the data"); + Assert.That(res[3][1].ToString(), Is.EqualTo("Dolphin:🐬"), "Matching the data"); result_collation = t.Select("name").Execute(); collationName = result_collation.Columns[0].CollationName; - Assert.AreEqual(collationname[i], collationName, "Matching the collation"); + Assert.That(collationName, Is.EqualTo(collationname[i]), "Matching the collation"); characterName = result_collation.Columns[0].CharacterSetName; - Assert.AreEqual(charset, characterName, "Matching the charset"); + Assert.That(characterName, Is.EqualTo(charset), "Matching the charset"); session.DropSchema(database_name); } @@ -1098,7 +1098,7 @@ public void Utf8mb4BinaryNopadCollationTable() session.SQL($"insert into x values({k},'{t_char}')").Execute(); t = session.GetSchema(database_name).GetTable("x"); r = t.Select().Limit(1).Execute().FetchOne(); - Assert.AreEqual(t_char.ToString(), r[1].ToString(), "Compare extracted string"); + Assert.That(r[1].ToString(), Is.EqualTo(t_char.ToString()), "Compare extracted string"); } session.DropSchema(database_name); @@ -1112,7 +1112,7 @@ public void Utf8mb4BinaryNopadCollationTable() session.SQL($"insert into x values({k},'{t_char}')").Execute(); t = session.GetSchema(database_name).GetTable("x"); r = t.Select().Limit(1).Execute().FetchOne(); - Assert.AreEqual(t_char.ToString(), r[1].ToString(), "Compare extracted string"); + Assert.That(r[1].ToString(), Is.EqualTo(t_char.ToString()), "Compare extracted string"); } session.DropSchema(database_name); } @@ -1136,7 +1136,7 @@ public void Utf8mb4BinaryNopadCollationTable() using (var sessiontest = MySQLX.GetSession(mysqlx0.ConnectionString)) { - Assert.AreEqual(charset, sessiontest.Settings.CharacterSet, "Matching the character set of the session"); + Assert.That(sessiontest.Settings.CharacterSet, Is.EqualTo(charset), "Matching the character set of the session"); sessiontest.DropSchema(database_name); CommandText1 = "CREATE DATABASE " + database_name; sqlRes = sessiontest.SQL(CommandText1).Execute(); @@ -1145,7 +1145,7 @@ public void Utf8mb4BinaryNopadCollationTable() t = sessiontest.GetSchema(database_name).GetTable("t"); t.Insert().Values(foo).Execute(); r = t.Select().Limit(1).Execute().FetchOne(); - Assert.AreEqual(foo, r[0].ToString(), "Compare extracted string"); + Assert.That(r[0].ToString(), Is.EqualTo(foo), "Compare extracted string"); sessiontest.DropSchema(database_name); } } diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/ClientSideFailoverTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/ClientSideFailoverTests.cs index 1a8ac5077..d3c8d0ceb 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/ClientSideFailoverTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/ClientSideFailoverTests.cs @@ -56,13 +56,13 @@ public void RandomMethodWithBasicFormatConnectionString() // Single host. using (var session = MySQLX.GetSession(ConnectionString)) { - Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); + Assert.That(session.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); } // Multiple hosts. using (var session = MySQLX.GetSession($"server=10.10.10.10, {Host}, 20.20.20.20, 30.30.30.30;port={XPort};uid=test;password=test;connecttimeout={connectionTimeout}")) { - Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); + Assert.That(session.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); } // Multiple hosts with IPv6 @@ -70,23 +70,23 @@ public void RandomMethodWithBasicFormatConnectionString() { using (var session = MySQLX.GetSession($"server=10.10.10.10, {localServerIpv6}, 20.20.20.20, 30.30.30.30;port={XPort};uid=test;password=test;connecttimeout={connectionTimeout}")) { - Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); + Assert.That(session.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); } } // Multiple hosts using synonyms for "server" connection option. using (var session = MySQLX.GetSession($"host=10.10.10.10, {Host};port={XPort};uid=test;password=test;connecttimeout=" + connectionTimeout)) { - Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); + Assert.That(session.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); } // Multiple hosts. All attempts fail. Exception ex = Assert.Throws(() => MySQLX.GetSession($"server= 10.10.10.10, 20.20.20.20 ;port={XPort};uid=test;password=test;connecttimeout={connectionTimeout}")); - Assert.AreEqual("Unable to connect to any of the specified MySQL hosts.", ex.Message); + Assert.That(ex.Message, Is.EqualTo("Unable to connect to any of the specified MySQL hosts.")); // Providing port number as part of the host name. ex = Assert.Throws(() => MySQLX.GetSession($"server= 10.10.10.10:33050, 20.20.20.20:33060, {Host}:{XPort} ;port={XPort};uid=test;password=test;connecttimeout={connectionTimeout}")); - Assert.AreEqual("Providing a port number as part of the host address isn't supported when using connection strings in basic format or anonymous objects. Use URI format instead.", ex.Message); + Assert.That(ex.Message, Is.EqualTo("Providing a port number as part of the host address isn't supported when using connection strings in basic format or anonymous objects. Use URI format instead.")); } [Test] @@ -97,13 +97,13 @@ public void RandomMethodWithUriFormatConnectionString() // Single host. using (var session = MySQLX.GetSession($"mysqlx://test:test@{Host}:{XPort}?connecttimeout={connectionTimeout}")) { - Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); + Assert.That(session.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); } // Single host and port as an array. Successful connection. using (var session = MySQLX.GetSession($"mysqlx://test:test@[{Host}:" + XPort + "]?connecttimeout=" + connectionTimeout)) { - Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); + Assert.That(session.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); } // Single host as an array. Failed connection. @@ -112,13 +112,13 @@ public void RandomMethodWithUriFormatConnectionString() // Multiple hosts. using (var session = MySQLX.GetSession($"mysqlx://test:test@[192.1.10.10,{Host}:" + XPort + "]?connecttimeout=" + connectionTimeout)) { - Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); + Assert.That(session.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); } // Multiple hosts and a schema. using (var session = MySQLX.GetSession($"mysqlx://test:test@[192.1.10.10,{Host}:" + XPort + "]/test?connecttimeout=" + connectionTimeout)) { - Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); + Assert.That(session.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); } // Multiple hosts which may or may not contain a port number. @@ -126,7 +126,7 @@ public void RandomMethodWithUriFormatConnectionString() { using (var session = MySQLX.GetSession($"mysqlx://test:test@[192.1.10.10,120.0.0.2:22000,[{localServerIpv6}]:{XPort}]/test?connecttimeout={connectionTimeout}")) { - Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); + Assert.That(session.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); } } } @@ -141,13 +141,13 @@ public void RandomMethodWithAnonymousTypes() // Single host. using (var session = MySQLX.GetSession(new { server = Host, port = XPort, uid = uid, password = password, connecttimeout = connectionTimeout })) { - Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); + Assert.That(session.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); } // Multiple hosts. using (var session = MySQLX.GetSession(new { server = $"10.10.10.10, {Host}", port = XPort, uid = uid, password = password, connecttimeout = connectionTimeout })) { - Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); + Assert.That(session.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); } // Multiple hosts with IPv6 @@ -155,23 +155,23 @@ public void RandomMethodWithAnonymousTypes() { using (var session = MySQLX.GetSession(new { server = $"10.10.10.10, {localServerIpv6}", port = XPort, uid = uid, password = password, connecttimeout = connectionTimeout })) { - Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); + Assert.That(session.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); } } // Multiple hosts using synonyms for "server" connection option. First attempt fails, second is succesful. using (var session = MySQLX.GetSession(new { datasource = $"10.10.10.10, {Host}", port = XPort, uid = uid, password = password, connecttimeout = connectionTimeout })) { - Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); + Assert.That(session.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); } // Multiple hosts. All attempts fail. Exception ex = Assert.Throws(() => MySQLX.GetSession(new { server = "10.10.10.10, 20.20.20.20", port = XPort, uid = uid, password = password, connecttimeout = connectionTimeout })); - Assert.AreEqual("Unable to connect to any of the specified MySQL hosts.", ex.Message); + Assert.That(ex.Message, Is.EqualTo("Unable to connect to any of the specified MySQL hosts.")); // Providing port number as part of the host name. ex = Assert.Throws(() => MySQLX.GetSession(new { server = "10.10.10.10:33060, 20.20.20.20:33060", port = XPort, uid = uid, password = password, connecttimeout = connectionTimeout })); - Assert.AreEqual("Providing a port number as part of the host address isn't supported when using connection strings in basic format or anonymous objects. Use URI format instead.", ex.Message); + Assert.That(ex.Message, Is.EqualTo("Providing a port number as part of the host address isn't supported when using connection strings in basic format or anonymous objects. Use URI format instead.")); } [Test] @@ -189,11 +189,11 @@ public void PriorityMethodWithBasicFormatConnectionString() Session newSession = MySQLX.GetSession($"server=(address={Host},priority=100);port=" + XPort + ";uid=test;password=test;"); sessions.Add(newSession); } - Assert.False(true, "MySqlException should be thrown"); + Assert.That(true, Is.False, "MySqlException should be thrown"); } catch (MySqlException exception) { - Assert.AreEqual(ResourcesX.UnableToOpenSession, exception.Message); + Assert.That(exception.Message, Is.EqualTo(ResourcesX.UnableToOpenSession)); } finally { @@ -202,20 +202,20 @@ public void PriorityMethodWithBasicFormatConnectionString() using (var session = MySQLX.GetSession($"server=(address={Host},priority=100);port=" + XPort + ";uid=test;password=test;connecttimeout=" + connectionTimeout)) { - Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); - Assert.AreEqual(Host, session.Settings.Server); + Assert.That(session.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); + Assert.That(session.Settings.Server, Is.EqualTo(Host)); } using (var session = MySQLX.GetSession($"server=(address=server.example,priority=50),(address={Host},priority=100);port=" + XPort + ";uid=test;password=test;connecttimeout=" + connectionTimeout)) { - Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); - Assert.AreEqual(Host, session.Settings.Server); + Assert.That(session.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); + Assert.That(session.Settings.Server, Is.EqualTo(Host)); } using (var session = MySQLX.GetSession($"server=(address=server.example,priority=100),(address={Host},priority=25),(address=192.0.10.56,priority=75);port=" + XPort + ";uid=test;password=test;connecttimeout=" + connectionTimeout)) { - Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); - Assert.AreEqual(Host, session.Settings.Server); + Assert.That(session.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); + Assert.That(session.Settings.Server, Is.EqualTo(Host)); } using (var session = MySQLX.GetSession(new @@ -227,33 +227,33 @@ public void PriorityMethodWithBasicFormatConnectionString() sslmode = MySqlSslMode.Disabled })) { - Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); - Assert.AreEqual(Host, session.Settings.Server); + Assert.That(session.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); + Assert.That(session.Settings.Server, Is.EqualTo(Host)); } using (var session = MySQLX.GetSession($"server=(address=server.example,priority=100),(address={Host},priority=25),(address=192.0.10.56,priority=75);port=" + XPort + ";uid=test;password=test;connecttimeout=" + connectionTimeout)) { - Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); - Assert.AreEqual(Host, session.Settings.Server); - Assert.AreEqual("server.example", FailoverManager.FailoverGroup.Hosts[0].Host); - Assert.AreEqual("192.0.10.56", FailoverManager.FailoverGroup.Hosts[1].Host); - Assert.AreEqual(Host, FailoverManager.FailoverGroup.Hosts[2].Host); + Assert.That(session.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); + Assert.That(session.Settings.Server, Is.EqualTo(Host)); + Assert.That(FailoverManager.FailoverGroup.Hosts[0].Host, Is.EqualTo("server.example")); + Assert.That(FailoverManager.FailoverGroup.Hosts[1].Host, Is.EqualTo("192.0.10.56")); + Assert.That(FailoverManager.FailoverGroup.Hosts[2].Host, Is.EqualTo(Host)); } // Priority outside the 0-100 allowed range. Exception ex = Assert.Throws(() => MySQLX.GetSession($"server=(address=server.example,priority=-20),(address={Host},priority=100);port=" + XPort + ";uid=test;password=test;connecttimeout=" + connectionTimeout)); - Assert.AreEqual("The priority must be between 0 and 100.", ex.Message); + Assert.That(ex.Message, Is.EqualTo("The priority must be between 0 and 100.")); ex = Assert.Throws(() => MySQLX.GetSession($"server=(address=server.example,priority=-50),(address={Host},priority=101);port=" + XPort + ";uid=test;password=test;connecttimeout=" + connectionTimeout)); - Assert.AreEqual("The priority must be between 0 and 100.", ex.Message); + Assert.That(ex.Message, Is.EqualTo("The priority must be between 0 and 100.")); // Set priority for a subset of the hosts. ex = Assert.Throws(() => MySQLX.GetSession($"server=(address=server.example),(address={Host},priority=100);port=" + XPort + ";uid=test;password=test;connecttimeout=" + connectionTimeout)); - Assert.AreEqual("You must either assign no priority to any of the hosts or give a priority for every host.", ex.Message); + Assert.That(ex.Message, Is.EqualTo("You must either assign no priority to any of the hosts or give a priority for every host.")); ex = Assert.Throws(() => MySQLX.GetSession($"server=(address=server.example,priority=50),(address={Host});port=" + XPort + ";uid=test;password=test;connecttimeout=" + connectionTimeout)); - Assert.AreEqual("You must either assign no priority to any of the hosts or give a priority for every host.", ex.Message); + Assert.That(ex.Message, Is.EqualTo("You must either assign no priority to any of the hosts or give a priority for every host.")); ex = Assert.Throws(() => MySQLX.GetSession($"server=(address=server.example,priority=50),(address={Host},priority=100),(address=server.example);port=" + XPort + ";uid=test;password=test;connecttimeout=" + connectionTimeout)); - Assert.AreEqual("You must either assign no priority to any of the hosts or give a priority for every host.", ex.Message); + Assert.That(ex.Message, Is.EqualTo("You must either assign no priority to any of the hosts or give a priority for every host.")); // Automatically set priority if no priority is given. string hostList = string.Empty; @@ -266,11 +266,11 @@ public void PriorityMethodWithBasicFormatConnectionString() using (var session = MySQLX.GetSession($"server={hostList};port={XPort};uid=test;password=test;connecttimeout={connectionTimeout}")) { - Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); + Assert.That(session.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); priority = 100; foreach (var host in FailoverManager.FailoverGroup.Hosts) { - Assert.AreEqual(priority != 0 ? priority-- : 0, host.Priority); + Assert.That(host.Priority, Is.EqualTo(priority != 0 ? priority-- : 0)); } } } @@ -290,11 +290,11 @@ public void PriorityMethodWithUriFormatConnectonString() Session newSession = MySQLX.GetSession($"mysqlx://test:test@[(address={Host}:" + XPort + ",priority=50)]?connecttimeout=" + connectionTimeout); sessions.Add(newSession); } - Assert.False(true, "MySqlException should be thrown"); + Assert.That(true, Is.False, "MySqlException should be thrown"); } catch (MySqlException exception) { - Assert.AreEqual(ResourcesX.UnableToOpenSession, exception.Message); + Assert.That(exception.Message, Is.EqualTo(ResourcesX.UnableToOpenSession)); } finally { @@ -303,39 +303,39 @@ public void PriorityMethodWithUriFormatConnectonString() using (var session = MySQLX.GetSession($"mysqlx://test:test@[(address=server.example,priority=50),(address={Host}:{XPort},priority=100)]?connecttimeout=" + connectionTimeout)) { - Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); - Assert.AreEqual(Host, session.Settings.Server); + Assert.That(session.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); + Assert.That(session.Settings.Server, Is.EqualTo(Host)); } using (var session = MySQLX.GetSession($"mysqlx://test:test@[(address=server.example,priority=50),(address={Host}:{XPort},priority=100)]?connecttimeout=" + connectionTimeout)) { - Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); - Assert.AreEqual(Host, session.Settings.Server); + Assert.That(session.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); + Assert.That(session.Settings.Server, Is.EqualTo(Host)); } using (var session = MySQLX.GetSession($"mysqlx://test:test@[(address=server.example,priority=100),(address={Host}:{XPort},priority=25),(address=192.0.10.56,priority=75)]?connecttimeout=" + connectionTimeout)) { - Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); - Assert.AreEqual(Host, session.Settings.Server); - Assert.AreEqual("server.example", FailoverManager.FailoverGroup.Hosts[0].Host); - Assert.AreEqual("192.0.10.56", FailoverManager.FailoverGroup.Hosts[1].Host); - Assert.AreEqual(Host, FailoverManager.FailoverGroup.Hosts[2].Host); + Assert.That(session.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); + Assert.That(session.Settings.Server, Is.EqualTo(Host)); + Assert.That(FailoverManager.FailoverGroup.Hosts[0].Host, Is.EqualTo("server.example")); + Assert.That(FailoverManager.FailoverGroup.Hosts[1].Host, Is.EqualTo("192.0.10.56")); + Assert.That(FailoverManager.FailoverGroup.Hosts[2].Host, Is.EqualTo(Host)); } // Priority outside the 0-100 allowed range. Exception ex = Assert.Throws(() => MySQLX.GetSession($"mysqlx://test:test@[(address=server.example,priority=-20),(address={Host}:{XPort},priority=100)]?connecttimeout=" + connectionTimeout)); - Assert.AreEqual("The priority must be between 0 and 100.", ex.Message); + Assert.That(ex.Message, Is.EqualTo("The priority must be between 0 and 100.")); ex = Assert.Throws(() => MySQLX.GetSession($"mysqlx://test:test@[(address=server.example,priority=50),(address={Host}:{XPort},priority=101)]?connecttimeout=" + connectionTimeout)); - Assert.AreEqual("The priority must be between 0 and 100.", ex.Message); + Assert.That(ex.Message, Is.EqualTo("The priority must be between 0 and 100.")); // Set priority for a subset of the hosts. ex = Assert.Throws(() => MySQLX.GetSession($"mysqlx://test:test@[(address=server.example),(address={Host}:{XPort},priority=100)]?connecttimeout=" + connectionTimeout)); - Assert.AreEqual("You must either assign no priority to any of the hosts or give a priority for every host.", ex.Message); + Assert.That(ex.Message, Is.EqualTo("You must either assign no priority to any of the hosts or give a priority for every host.")); ex = Assert.Throws(() => MySQLX.GetSession($"mysqlx://test:test@[(address=server.example,priority=100),(address={Host}:{XPort})]?connecttimeout=" + connectionTimeout)); - Assert.AreEqual("You must either assign no priority to any of the hosts or give a priority for every host.", ex.Message); + Assert.That(ex.Message, Is.EqualTo("You must either assign no priority to any of the hosts or give a priority for every host.")); ex = Assert.Throws(() => MySQLX.GetSession($"mysqlx://test:test@[(address=server.example),(address={Host}:{XPort}),(address=server2.example,priority=100)]?connecttimeout=" + connectionTimeout)); - Assert.AreEqual("You must either assign no priority to any of the hosts or give a priority for every host.", ex.Message); + Assert.That(ex.Message, Is.EqualTo("You must either assign no priority to any of the hosts or give a priority for every host.")); // Automatically set priority if no priority is given. string hostList = string.Empty; @@ -348,11 +348,11 @@ public void PriorityMethodWithUriFormatConnectonString() using (var session = MySQLX.GetSession($"mysqlx://test:test@[{hostList}]?connecttimeout=" + connectionTimeout)) { - Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); + Assert.That(session.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); priority = 100; foreach (var host in FailoverManager.FailoverGroup.Hosts) { - Assert.AreEqual(priority != 0 ? priority-- : 0, host.Priority); + Assert.That(host.Priority, Is.EqualTo(priority != 0 ? priority-- : 0)); } } } @@ -375,11 +375,11 @@ public void PriorityMethodWithAnonymousTypes() sessions.Add(newSession); } - Assert.False(true, "MySqlException should be thrown"); + Assert.That(true, Is.False, "MySqlException should be thrown"); } catch (MySqlException exception) { - Assert.AreEqual(ResourcesX.UnableToOpenSession, exception.Message); + Assert.That(exception.Message, Is.EqualTo(ResourcesX.UnableToOpenSession)); } finally { @@ -388,44 +388,44 @@ public void PriorityMethodWithAnonymousTypes() using (var session = MySQLX.GetSession(new { server = $"(address={Host},priority=100)", port = XPort, uid = uid, password = password, connecttimeout = connectionTimeout })) { - Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); - Assert.AreEqual(Host, session.Settings.Server); + Assert.That(session.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); + Assert.That(session.Settings.Server, Is.EqualTo(Host)); } using (var session = MySQLX.GetSession(new { server = $"(address=server.example,priority=50),(address={Host},priority=100)", port = XPort, uid = uid, password = password, connecttimeout = connectionTimeout })) { - Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); - Assert.AreEqual(Host, session.Settings.Server); + Assert.That(session.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); + Assert.That(session.Settings.Server, Is.EqualTo(Host)); } using (var session = MySQLX.GetSession(new { server = $"(address=server.example,priority=100),(address={Host},priority=25),(address=192.0.10.56,priority=75)", port = XPort, uid = uid, password = password, connecttimeout = connectionTimeout })) { - Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); - Assert.AreEqual(Host, session.Settings.Server); - Assert.AreEqual("server.example", FailoverManager.FailoverGroup.Hosts[0].Host); - Assert.AreEqual("192.0.10.56", FailoverManager.FailoverGroup.Hosts[1].Host); - Assert.AreEqual(Host, FailoverManager.FailoverGroup.Hosts[2].Host); + Assert.That(session.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); + Assert.That(session.Settings.Server, Is.EqualTo(Host)); + Assert.That(FailoverManager.FailoverGroup.Hosts[0].Host, Is.EqualTo("server.example")); + Assert.That(FailoverManager.FailoverGroup.Hosts[1].Host, Is.EqualTo("192.0.10.56")); + Assert.That(FailoverManager.FailoverGroup.Hosts[2].Host, Is.EqualTo(Host)); } using (var session = MySQLX.GetSession(new { host = $"(address={Host},priority=2),(address={Host},priority=3)", port = XPort, uid = uid, password = password, connecttimeout = connectionTimeout })) { - Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); + Assert.That(session.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); } // Priority outside the 0-100 allowed range. Exception ex = Assert.Throws(() => MySQLX.GetSession(new { server = $"(address=server.example,priority=-20),(address={Host},priority=100)", port = XPort, uid = uid, password = password, connecttimeout = connectionTimeout })); - Assert.AreEqual("The priority must be between 0 and 100.", ex.Message); + Assert.That(ex.Message, Is.EqualTo("The priority must be between 0 and 100.")); ex = Assert.Throws(() => MySQLX.GetSession(new { server = $"(address=server.example,priority=-50),(address={Host},priority=101)", port = XPort, uid = uid, password = password, connecttimeout = connectionTimeout })); - Assert.AreEqual("The priority must be between 0 and 100.", ex.Message); + Assert.That(ex.Message, Is.EqualTo("The priority must be between 0 and 100.")); // Set priority for a subset of the hosts. ex = Assert.Throws(() => MySQLX.GetSession(new { server = $"(address=server.example),(address={Host},priority=100)", port = XPort, uid = uid, password = password, connecttimeout = connectionTimeout })); - Assert.AreEqual("You must either assign no priority to any of the hosts or give a priority for every host.", ex.Message); + Assert.That(ex.Message, Is.EqualTo("You must either assign no priority to any of the hosts or give a priority for every host.")); ex = Assert.Throws(() => MySQLX.GetSession(new { server = $"(address=server.example,priority=50),(address={Host})", port = XPort, uid = uid, password = password, connecttimeout = connectionTimeout })); - Assert.AreEqual("You must either assign no priority to any of the hosts or give a priority for every host.", ex.Message); + Assert.That(ex.Message, Is.EqualTo("You must either assign no priority to any of the hosts or give a priority for every host.")); ex = Assert.Throws(() => MySQLX.GetSession(new { server = $"(address=server.example,priority=50),(address={Host},priority=100),(address=server.example)", port = XPort, uid = uid, password = password, connecttimeout = connectionTimeout })); - Assert.AreEqual("You must either assign no priority to any of the hosts or give a priority for every host.", ex.Message); + Assert.That(ex.Message, Is.EqualTo("You must either assign no priority to any of the hosts or give a priority for every host.")); // Automatically set priority if no priority is given. string hostList = string.Empty; @@ -438,11 +438,11 @@ public void PriorityMethodWithAnonymousTypes() using (var session = MySQLX.GetSession(new { server = hostList, port = XPort, uid = uid, password = password, connecttimeout = connectionTimeout })) { - Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); + Assert.That(session.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); priority = 100; foreach (var host in FailoverManager.FailoverGroup.Hosts) { - Assert.AreEqual(priority != 0 ? priority-- : 0, host.Priority); + Assert.That(host.Priority, Is.EqualTo(priority != 0 ? priority-- : 0)); } } } @@ -482,12 +482,12 @@ public void ManyInvalidHost() sb.UserID + ";password=" + sb.Password + ";connect-timeout=" + connectionTimeout + ";ssl-mode=Required")) { - Assert.AreEqual(SessionState.Open, session1.InternalSession.SessionState); + Assert.That(session1.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); var schema = session1.GetSchema("test"); - Assert.IsNotNull(schema); + Assert.That(schema, Is.Not.Null); schema.DropCollection("test123"); var testColl = schema.CreateCollection("test123"); - Assert.IsNotNull(testColl); + Assert.That(testColl, Is.Not.Null); schema.DropCollection("test123"); } @@ -501,12 +501,12 @@ public void ManyInvalidHost() var connStr = "mysqlx://test:test@[" + hostList + "]" + "?ssl-mode=Required"; using (var session1 = MySQLX.GetSession(connStr)) { - Assert.AreEqual(SessionState.Open, session1.InternalSession.SessionState); + Assert.That(session1.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); var schema = session1.GetSchema("test"); - Assert.IsNotNull(schema); + Assert.That(schema, Is.Not.Null); schema.DropCollection("test123"); var testColl = schema.CreateCollection("test123"); - Assert.IsNotNull(testColl); + Assert.That(testColl, Is.Not.Null); schema.DropCollection("test123"); } @@ -527,12 +527,12 @@ public void ManyInvalidHost() sslmode = MySqlSslMode.Disabled })) { - Assert.AreEqual(SessionState.Open, session1.InternalSession.SessionState); + Assert.That(session1.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); var schema = session.GetSchema("test"); - Assert.IsNotNull(schema); + Assert.That(schema, Is.Not.Null); schema.DropCollection("test123"); var testColl = schema.CreateCollection("test123"); - Assert.IsNotNull(testColl); + Assert.That(testColl, Is.Not.Null); schema.DropCollection("test123"); } } @@ -546,7 +546,7 @@ public void TwoValidHost() var connStr = $"mysqlx://test:test@[ (address={Host}:{XPort}, priority=0,address={Host}:{XPort}, priority=100)]?ssl-mode=Required"; using (var sessionTest = MySQLX.GetSession(connStr)) { - Assert.AreEqual(SessionState.Open, sessionTest.InternalSession.SessionState); + Assert.That(sessionTest.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); } var address_priority = $"(address = {Host}, priority = 0),(address={Host}, priority=100)"; @@ -555,7 +555,7 @@ public void TwoValidHost() ";password=" + sb.Password + ";ssl-mode=Required"; using (var sessionTest = MySQLX.GetSession(connStr)) { - Assert.AreEqual(SessionState.Open, sessionTest.InternalSession.SessionState); + Assert.That(sessionTest.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); } using (var sessionTest = MySQLX.GetSession(new @@ -567,7 +567,7 @@ public void TwoValidHost() sslmode = MySqlSslMode.Disabled })) { - Assert.AreEqual(SessionState.Open, sessionTest.InternalSession.SessionState); + Assert.That(sessionTest.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); } } @@ -583,7 +583,7 @@ public void TwoValidHostWithDefaultPort() using (var sessionTest = MySQLX.GetSession(connStr)) { - Assert.AreEqual(SessionState.Open, sessionTest.InternalSession.SessionState); + Assert.That(sessionTest.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); } var address_priority = $"(address={Host}, priority=0),(address={Host}, priority=100)"; @@ -591,7 +591,7 @@ public void TwoValidHostWithDefaultPort() ";ssl-mode=Required;" + "port=" + sb.Port; using (var sessionTest = MySQLX.GetSession(connStr)) { - Assert.AreEqual(SessionState.Open, sessionTest.InternalSession.SessionState); + Assert.That(sessionTest.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); } using (var sessionTest = MySQLX.GetSession(new { @@ -602,7 +602,7 @@ public void TwoValidHostWithDefaultPort() port = sb.Port })) { - Assert.AreEqual(SessionState.Open, sessionTest.InternalSession.SessionState); + Assert.That(sessionTest.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); } } @@ -622,26 +622,26 @@ public void IteratedPriority() var test = "server=" + hostList[i] + ";uid=test;password=test;connect-timeout=" + connectionTimeout + ";ssl-mode=required;" + "port=" + XPort; using (var session1 = MySQLX.GetSession(test)) { - Assert.AreEqual(SessionState.Open, session1.InternalSession.SessionState); + Assert.That(session1.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); } using (var session1 = MySQLX.GetSession("server=" + hostList[i] + ";port=" + XPort + ";uid=test;password=test;connect-timeout=" + connectionTimeout + ";ssl-mode=Required")) { - Assert.AreEqual(SessionState.Open, session1.InternalSession.SessionState); + Assert.That(session1.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); } hostList[i] = "(address=" + Host + ":" + XPort + ",priority=" + (priority != 0 ? priority-- : 0) + ")"; var connStr = "mysqlx://test:test@[" + hostList[i] + "]?ssl-mode=Required"; using (var session1 = MySQLX.GetSession(connStr)) { - Assert.AreEqual(SessionState.Open, session1.InternalSession.SessionState); + Assert.That(session1.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); } hostListPort[i] = $"(address={Host}:{XPort},priority={(priority != 0 ? priority-- : 0)})"; connStr = "mysqlx://test:test@[" + hostList[i] + "]?ssl-mode=Required"; using (var session1 = MySQLX.GetSession(connStr)) { - Assert.AreEqual(SessionState.Open, session1.InternalSession.SessionState); + Assert.That(session1.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); } hostList[i] = "(address=" + Host + ",priority=" + (priority != 0 ? priority-- : 0) + ")"; @@ -654,7 +654,7 @@ public void IteratedPriority() sslmode = MySqlSslMode.Required })) { - Assert.AreEqual(SessionState.Open, session1.InternalSession.SessionState); + Assert.That(session1.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); } } } @@ -671,14 +671,14 @@ public void PriorityWithSsl() using (var session1 = MySQLX.GetSession(connStr)) { - Assert.AreEqual(SessionState.Open, session1.InternalSession.SessionState); + Assert.That(session1.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); } connStr = $"mysqlx://test:test@[ (address={Host}:{XPort}, priority=100)]" + $"/?ssl-mode=Required&ssl-ca-pwd={certificatePassword}&ssl-ca={sslCa}"; using (var session1 = MySQLX.GetSession(connStr)) { - Assert.AreEqual(SessionState.Open, session1.InternalSession.SessionState); + Assert.That(session1.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); } connStr = $"mysqlx://test:test@[ (address={Host}" + ":" + XPort + ", priority=100)]" + @@ -689,14 +689,14 @@ public void PriorityWithSsl() connStr = "server=" + address_priority + ";port=" + XPort + ";uid=test;password=test;ssl-mode=VerifyCA;ssl-ca-pwd=pass;ssl-ca=" + sslCa; using (var session1 = MySQLX.GetSession(connStr)) { - Assert.AreEqual(SessionState.Open, session1.InternalSession.SessionState); + Assert.That(session1.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); } address_priority = $"(address = {Host}, priority = 25)"; connStr = "server=" + address_priority + ";port=" + XPort + ";uid=test;password=test;ssl-mode=Required;ssl-ca-pwd=" + certificatePassword + ";ssl-ca=" + sslCa; using (var session1 = MySQLX.GetSession(connStr)) { - Assert.AreEqual(SessionState.Open, session1.InternalSession.SessionState); + Assert.That(session1.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); } connStr = "server=" + address_priority + ";port=" + XPort + ";uid=test;password=test;ssl-mode=VerifyFull;ssl-ca-pwd=" + @@ -714,7 +714,7 @@ public void PriorityWithSsl() CertificatePassword = certificatePassword })) { - Assert.AreEqual(SessionState.Open, session1.InternalSession.SessionState); + Assert.That(session1.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); } using (var session1 = MySQLX.GetSession(new @@ -728,7 +728,7 @@ public void PriorityWithSsl() CertificatePassword = certificatePassword })) { - Assert.AreEqual(SessionState.Open, session1.InternalSession.SessionState); + Assert.That(session1.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); } Assert.Catch(() => MySQLX.GetSession(new @@ -765,7 +765,7 @@ public void SingleHostWithPriorityVerifyFull() CertificatePassword = certificatePassword })) { - Assert.AreEqual(SessionState.Open, session1.InternalSession.SessionState); + Assert.That(session1.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); } } #endregion diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/ClientTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/ClientTests.cs index 3b981419d..895fc3c1c 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/ClientTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/ClientTests.cs @@ -84,7 +84,7 @@ public void ParseConnectionOptionsTest(ClientOptions clientOptions) { Client.ConnectionOptions poolingOptions = (Client.ConnectionOptions)clientOptions.Options; Client.ConnectionOptions connectionOptionsResult = Client.ParseConnectionOptions(clientOptions.ConnectionOptions); - Assert.True(poolingOptions.Equals(connectionOptionsResult)); + Assert.That(poolingOptions.Equals(connectionOptionsResult)); } public struct InvalidOptions @@ -253,7 +253,7 @@ public void PoolingTest(PoolingTestData poolingTestData) Session session = client.GetSession(); string host = session.SQL("SELECT host FROM information_schema.PROCESSLIST where id=CONNECTION_ID()").Execute().FetchOne().GetString("host"); sessions.Add(session); - Assert.Contains(host, hosts); + Assert.That(hosts, Does.Contain(host)); } closeSessions.Invoke(); } @@ -273,8 +273,8 @@ public void QueueTimeoutTest() Stopwatch stopwatch = Stopwatch.StartNew(); TimeoutException ex = Assert.Throws(() => { Session session2 = client.GetSession(); }); stopwatch.Stop(); - Assert.AreEqual(ResourcesX.PoolingQueueTimeout, ex.Message); - Assert.True(stopwatch.ElapsedMilliseconds >= timeout); + Assert.That(ex.Message, Is.EqualTo(ResourcesX.PoolingQueueTimeout)); + Assert.That(stopwatch.ElapsedMilliseconds >= timeout); } } } @@ -288,10 +288,10 @@ public void ReuseSessions() using (Client client = MySQLX.GetClient(ConnectionString, new { pooling = new { maxSize = size, queueTimeout = timeout } })) { Session session = client.GetSession(); - Assert.AreEqual((sbyte)5, session.SQL("SELECT 5").Execute().FetchOne()[0]); + Assert.That(session.SQL("SELECT 5").Execute().FetchOne()[0], Is.EqualTo((sbyte)5)); session.Close(); MySqlException ex = Assert.Throws(() => { session.SQL("SELECT 5").Execute(); }); - Assert.AreEqual(ResourcesX.InvalidSession, ex.Message); + Assert.That(ex.Message, Is.EqualTo(ResourcesX.InvalidSession)); } } @@ -323,7 +323,7 @@ public void MultiHostTest(MultiHostData multiHostData) { using (Session session = client.GetSession()) { - Assert.AreEqual((sbyte)8, session.SQL("SELECT 8").Execute().FetchOne()[0]); + Assert.That(session.SQL("SELECT 8").Execute().FetchOne()[0], Is.EqualTo((sbyte)8)); } } } @@ -354,9 +354,9 @@ public void CloseTests(CloseData closeData) session.DropSchema(schemaName); session.CreateSchema(schemaName); client.Close(); - Assert.AreEqual(SessionState.Closed, session.XSession.SessionState); + Assert.That(session.XSession.SessionState, Is.EqualTo(SessionState.Closed)); MySqlException ex = Assert.Throws(() => { closeData.Action.Invoke(session); }); - Assert.AreEqual(ResourcesX.InvalidSession, ex.Message); + Assert.That(ex.Message, Is.EqualTo(ResourcesX.InvalidSession)); } } } @@ -402,22 +402,22 @@ private void ResetTestBeforeClose(Session session, int id) session.SQL(string.Format("SET @a='session{0}'", id)).Execute(); SqlResult res = session.SQL("SELECT @a AS a").Execute(); - Assert.AreEqual("session" + id, res.FetchAll()[0][0]); + Assert.That(res.FetchAll()[0][0], Is.EqualTo("session" + id)); res = session.SQL("SHOW CREATE TABLE testResetSession" + id).Execute(); - Assert.AreEqual("testResetSession" + id, res.FetchAll()[0][0]); + Assert.That(res.FetchAll()[0][0], Is.EqualTo("testResetSession" + id)); } private void ResetTestAfterClose(Session session, int threadId, int id) { - Assert.AreEqual(threadId, session.ThreadId); + Assert.That(session.ThreadId, Is.EqualTo(threadId)); SqlResult res = session.SQL("SELECT @a IS NULL").Execute(); - Assert.AreEqual((sbyte)1, res.FetchOne()[0]); + Assert.That(res.FetchOne()[0], Is.EqualTo((sbyte)1)); var ex = Assert.Throws(() => session.SQL("SHOW CREATE TABLE testResetSession" + id).Execute()); - StringAssert.AreEqualIgnoringCase(string.Format("Table 'test.testresetsession{0}' doesn't exist", id), ex.Message); + Assert.That(ex.Message, Is.EqualTo(string.Format("Table 'test.testresetsession{0}' doesn't exist", id)).IgnoreCase); session.SQL(string.Format("SET @a='session{0}'", id)).Execute(); res = session.SQL("SELECT @a AS a").Execute(); - Assert.AreEqual("session" + id, res.FetchAll()[0][0]); + Assert.That(res.FetchAll()[0][0], Is.EqualTo("session" + id)); } /// @@ -453,13 +453,13 @@ public void ConnectionAttributes() // Errors var ex = Assert.Throws(() => MySQLX.GetSession(ConnectionString + ";connection-attributes=[_key=value]")); - Assert.AreEqual(ResourcesX.InvalidUserDefinedAttribute, ex.Message); + Assert.That(ex.Message, Is.EqualTo(ResourcesX.InvalidUserDefinedAttribute)); ex = Assert.Throws(() => MySQLX.GetSession(ConnectionString + ";connection-attributes=123")); - Assert.AreEqual(ResourcesX.InvalidConnectionAttributes, ex.Message); + Assert.That(ex.Message, Is.EqualTo(ResourcesX.InvalidConnectionAttributes)); ex = Assert.Throws(() => MySQLX.GetSession(ConnectionString + ";connection-attributes=[key=value,key=value2]")); - Assert.AreEqual(string.Format(ResourcesX.DuplicateUserDefinedAttribute, "key"), ex.Message); + Assert.That(ex.Message, Is.EqualTo(string.Format(ResourcesX.DuplicateUserDefinedAttribute, "key"))); MySqlXConnectionStringBuilder builder = new MySqlXConnectionStringBuilder(); builder.Server = Host; @@ -467,7 +467,7 @@ public void ConnectionAttributes() builder.UserID = RootUser; builder.ConnectionAttributes = ";"; ex = Assert.Throws(() => MySQLX.GetClient(builder.ConnectionString, "{ \"pooling\": { \"enabled\": true } }")); - Assert.AreEqual("The requested value ';' is invalid for the given keyword 'connection-attributes'.", ex.Message); + Assert.That(ex.Message, Is.EqualTo("The requested value ';' is invalid for the given keyword 'connection-attributes'.")); } private void TestConnectionAttributes(string connString, Dictionary userAttrs = null) @@ -477,31 +477,31 @@ private void TestConnectionAttributes(string connString, Dictionary client2.GetSession()); @@ -743,31 +743,31 @@ public void MaxSizeOptionTests(string inputType) using (var client1 = MySQLX.GetClient(ConnectionString, (inputType == "string" ? connectionpooling : connectionpoolingObject)[i])) { var session1 = client1.GetSession(); - Assert.AreEqual(SessionState.Open, session1.InternalSession.SessionState); + Assert.That(session1.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); } //Uri using (var client1 = MySQLX.GetClient(ConnectionStringUri, (inputType == "string" ? connectionpooling : connectionpoolingObject)[i])) { var session1 = client1.GetSession(); - Assert.AreEqual(SessionState.Open, session1.InternalSession.SessionState); + Assert.That(session1.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); } //Connectin Object using (var client1 = MySQLX.GetClient(connObject, (inputType == "string" ? connectionpooling : connectionpoolingObject)[i])) { var session1 = client1.GetSession(); - Assert.AreEqual(SessionState.Open, session1.InternalSession.SessionState); + Assert.That(session1.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); } } else { Exception ex = Assert.Catch(() => MySQLX.GetClient(ConnectionString, (inputType == "string" ? connectionpooling : connectionpoolingObject)[i])); - Assert.True(ex.Message.Contains("'pooling.maxSize' does not support value"), "Expected Exception"); + Assert.That(ex.Message.Contains("'pooling.maxSize' does not support value"), "Expected Exception"); ex = Assert.Catch(() => MySQLX.GetClient(ConnectionStringUri, (inputType == "string" ? connectionpooling : connectionpoolingObject)[i])); - Assert.True(ex.Message.Contains("'pooling.maxSize' does not support value"), "Expected Exception"); + Assert.That(ex.Message.Contains("'pooling.maxSize' does not support value"), "Expected Exception"); ex = Assert.Catch(() => MySQLX.GetClient(connObject, (inputType == "string" ? connectionpooling : connectionpoolingObject)[i])); - Assert.True(ex.Message.Contains("'pooling.maxSize' does not support value"), "Expected Exception"); + Assert.That(ex.Message.Contains("'pooling.maxSize' does not support value"), "Expected Exception"); } } } @@ -834,7 +834,7 @@ public void QueueTimeoutOptionTests(string inputType) Stopwatch stopwatch = Stopwatch.StartNew(); Assert.Catch(() => client1.GetSession()); stopwatch.Stop(); - Assert.True(stopwatch.ElapsedMilliseconds >= timeoutMS); + Assert.That(stopwatch.ElapsedMilliseconds >= timeoutMS); } //Uri @@ -845,7 +845,7 @@ public void QueueTimeoutOptionTests(string inputType) Stopwatch stopwatch = Stopwatch.StartNew(); Assert.Catch(() => client1.GetSession()); stopwatch.Stop(); - Assert.True(stopwatch.ElapsedMilliseconds >= timeoutMS); + Assert.That(stopwatch.ElapsedMilliseconds >= timeoutMS); } //Anonymous Object @@ -856,7 +856,7 @@ public void QueueTimeoutOptionTests(string inputType) Stopwatch stopwatch = Stopwatch.StartNew(); Assert.Catch(() => client1.GetSession()); stopwatch.Stop(); - Assert.True(stopwatch.ElapsedMilliseconds >= timeoutMS); + Assert.That(stopwatch.ElapsedMilliseconds >= timeoutMS); } } else @@ -899,13 +899,13 @@ public void InvalidConnectionOptions(string inputType) { //Connection string Exception ex = Assert.Catch(() => MySQLX.GetClient(ConnectionString, (inputType == "string" ? connectionpooling : connectionpoolingObject)[i])); - Assert.True(ex is ArgumentNullException || ex is ArgumentException); + Assert.That(ex is ArgumentNullException || ex is ArgumentException); //Uri ex = Assert.Catch(() => MySQLX.GetClient(ConnectionStringUri, (inputType == "string" ? connectionpooling : connectionpoolingObject)[i])); - Assert.True(ex is ArgumentNullException || ex is ArgumentException); + Assert.That(ex is ArgumentNullException || ex is ArgumentException); //Anonymous object ex = Assert.Catch(() => MySQLX.GetClient(connObject, (inputType == "string" ? connectionpooling : connectionpoolingObject)[i])); - Assert.True(ex is ArgumentNullException || ex is ArgumentException); + Assert.That(ex is ArgumentNullException || ex is ArgumentException); } } @@ -942,10 +942,10 @@ public void MultipleHostsAndPriorityTests(string inputType, int hostNameOrIP) using (var localSession = client1.GetSession()) { var schema = localSession.GetSchema("test"); - Assert.IsNotNull(schema); + Assert.That(schema, Is.Not.Null); schema.DropCollection("test123"); var testColl = schema.CreateCollection("test123"); - Assert.IsNotNull(testColl); + Assert.That(testColl, Is.Not.Null); schema.DropCollection("test123"); } } @@ -973,10 +973,10 @@ public void MultipleHostsAndPriorityTests(string inputType, int hostNameOrIP) using (var localSession = client1.GetSession()) { var schema = localSession.GetSchema("test"); - Assert.IsNotNull(schema); + Assert.That(schema, Is.Not.Null); schema.DropCollection("test123"); var testColl = schema.CreateCollection("test123"); - Assert.IsNotNull(testColl); + Assert.That(testColl, Is.Not.Null); schema.DropCollection("test123"); } } @@ -998,10 +998,10 @@ public void MultipleHostsAndPriorityTests(string inputType, int hostNameOrIP) using (var localSession = client1.GetSession()) { var schema = localSession.GetSchema("test"); - Assert.IsNotNull(schema); + Assert.That(schema, Is.Not.Null); schema.DropCollection("test123"); var testColl = schema.CreateCollection("test123"); - Assert.IsNotNull(testColl); + Assert.That(testColl, Is.Not.Null); schema.DropCollection("test123"); } } @@ -1036,41 +1036,41 @@ public void SessionCreatedByClient() using (var client1 = MySQLX.GetClient(ConnectionString, connectionpoolingObject)) { var rs1 = client1.GetSession(); - Assert.AreEqual(SessionState.Open, rs1.InternalSession.SessionState); + Assert.That(rs1.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); } using (var client1 = MySQLX.GetClient(ConnectionStringUri, connectionpoolingObject)) { client1.GetSession(); var rs1 = client1.GetSession(); - Assert.AreEqual(SessionState.Open, rs1.InternalSession.SessionState); + Assert.That(rs1.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); } using (var client1 = MySQLX.GetClient(connObject, connectionpoolingObject)) { client1.GetSession(); var rs1 = client1.GetSession(); - Assert.AreEqual(SessionState.Open, rs1.InternalSession.SessionState); + Assert.That(rs1.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); } using (var client1 = MySQLX.GetClient(ConnectionString, connectionpooling)) { var rs1 = client1.GetSession(); - Assert.AreEqual(SessionState.Open, rs1.InternalSession.SessionState); + Assert.That(rs1.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); } using (var client1 = MySQLX.GetClient(ConnectionStringUri, connectionpooling)) { client1.GetSession(); var rs1 = client1.GetSession(); - Assert.AreEqual(SessionState.Open, rs1.InternalSession.SessionState); + Assert.That(rs1.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); } using (var client1 = MySQLX.GetClient(connObject, connectionpooling)) { client1.GetSession(); var rs1 = client1.GetSession(); - Assert.AreEqual(SessionState.Open, rs1.InternalSession.SessionState); + Assert.That(rs1.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); } } @@ -1372,7 +1372,7 @@ public void SessionResetConnectionState() } else { col1 = db1.CreateCollection("my_collection1"); } col1 = db1.GetCollection("my_collection1", true); - Assert.IsNotNull(col1); + Assert.That(col1, Is.Not.Null); var db2 = session2.GetSchema("test2"); if (db2.ExistsInDatabase()) @@ -1389,7 +1389,7 @@ public void SessionResetConnectionState() } else { col2 = db2.CreateCollection("my_collection2"); } col2 = db2.GetCollection("my_collection2", true); - Assert.IsNotNull(col2); + Assert.That(col2, Is.Not.Null); session1.Close(); DbDoc DbDocs1 = new DbDoc(); @@ -1398,21 +1398,21 @@ public void SessionResetConnectionState() db1 = session1.GetSchema("test1"); Exception ex = Assert.Throws(() => db1.ExistsInDatabase()); - StringAssert.Contains("Session state is not valid", ex.Message); + Assert.That(ex.Message, Does.Contain("Session state is not valid")); var result = col2.Add(DbDocs1).Execute(); - Assert.IsNotNull(result); + Assert.That(result, Is.Not.Null); session1 = client1.GetSession(); db1 = session1.GetSchema("test1"); col1 = db1.GetCollection("my_collection1", true); result = col1.Add(DbDocs1).Execute(); - Assert.IsNotNull(result); + Assert.That(result, Is.Not.Null); session1.Close(); db1 = session1.GetSchema("test1"); ex = Assert.Throws(() => db1.ExistsInDatabase()); - StringAssert.Contains("Session state is not valid", ex.Message); + Assert.That(ex.Message, Does.Contain("Session state is not valid")); session2.DropSchema("test1"); session2.DropSchema("test2"); @@ -1442,16 +1442,16 @@ public void ConnectionAttributesLongValue() //Connection String using (var s1 = MySQLX.GetSession($"{ConnectionString};connectionattributes={maxCombi}")) { - Assert.AreEqual(SessionState.Open, s1.InternalSession.SessionState); + Assert.That(s1.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); var truncatedValues = (int)session.SQL("SHOW STATUS LIKE 'Performance_schema_session_connect_attrs_lost'").Execute().First()[0]; - Assert.True(truncatedValues > connectAttributesLost); + Assert.That(truncatedValues > connectAttributesLost); } //Uri using (var s1 = MySQLX.GetSession($"{ConnectionStringUri}?connectionattributes={maxCombi}")) { - Assert.AreEqual(SessionState.Open, s1.InternalSession.SessionState); + Assert.That(s1.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); var truncatedValues = (int)session.SQL("SHOW STATUS LIKE 'Performance_schema_session_connect_attrs_lost'").Execute().First()[0]; - Assert.True(truncatedValues > connectAttributesLost); + Assert.That(truncatedValues > connectAttributesLost); } //Anonymous Object using (var s1 = MySQLX.GetSession(new @@ -1463,9 +1463,9 @@ public void ConnectionAttributesLongValue() ConnectionAttributes = maxCombi })) { - Assert.AreEqual(SessionState.Open, s1.InternalSession.SessionState); + Assert.That(s1.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); var truncatedValues = (int)session.SQL("SHOW STATUS LIKE 'Performance_schema_session_connect_attrs_lost'").Execute().First()[0]; - Assert.True(truncatedValues > connectAttributesLost); + Assert.That(truncatedValues > connectAttributesLost); } } } @@ -1479,7 +1479,7 @@ public void GetSessionExceptionWithConnetionAttribute() , "{ \"pooling\": { \"enabled\": true } }")) { Exception ex = Assert.Throws(() => client.GetSession()); - Assert.AreEqual("The requested value '=' is invalid for the given keyword 'connection-attributes'.", ex.Message); + Assert.That(ex.Message, Is.EqualTo("The requested value '=' is invalid for the given keyword 'connection-attributes'.")); } } @@ -1497,7 +1497,7 @@ public void ConnectionAttributesWithArrays() { using (Session session1 = client.GetSession()) { - Assert.AreEqual(SessionState.Open, session1.InternalSession.SessionState); + Assert.That(session1.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); } } //Uri @@ -1505,7 +1505,7 @@ public void ConnectionAttributesWithArrays() { using (Session session1 = client.GetSession()) { - Assert.AreEqual(SessionState.Open, session1.InternalSession.SessionState); + Assert.That(session1.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); } } //Anonymous Object @@ -1514,7 +1514,7 @@ public void ConnectionAttributesWithArrays() { using (Session session1 = client.GetSession()) { - Assert.AreEqual(SessionState.Open, session1.InternalSession.SessionState); + Assert.That(session1.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); } } //MySqlXConnectionStringBuilder @@ -1534,24 +1534,24 @@ public void ConnectionAttributesWithArrays() { using (Session session1 = client.GetSession()) { - Assert.AreEqual(SessionState.Open, session1.InternalSession.SessionState); + Assert.That(session1.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); } } //Connection string using (Session session1 = MySQLX.GetSession(ConnectionString + ";connection-attributes=" + arrayCases[i])) { - Assert.AreEqual(SessionState.Open, session1.InternalSession.SessionState); + Assert.That(session1.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); } //Uri using (Session session1 = MySQLX.GetSession(ConnectionStringUri + "?connection-attributes=" + arrayCases[i])) { - Assert.AreEqual(SessionState.Open, session1.InternalSession.SessionState); + Assert.That(session1.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); } //Anonymous Object sb = new MySqlXConnectionStringBuilder(ConnectionString); using (Session session1 = MySQLX.GetSession(new { server = sb.Server, port = XPort, user = sb.UserID, password = sb.Password, ConnectionAttributes = arrayCases[i] })) { - Assert.AreEqual(SessionState.Open, session1.InternalSession.SessionState); + Assert.That(session1.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); } //MySqlXConnectionStringBuilder mysqlx0 = new MySqlXConnectionStringBuilder(ConnectionString); @@ -1568,7 +1568,7 @@ public void ConnectionAttributesWithArrays() mysqlx0.ConnectionAttributes = arrayCases[i].ToString(); using (Session session1 = MySQLX.GetSession(mysqlx0.ConnectionString)) { - Assert.AreEqual(SessionState.Open, session1.InternalSession.SessionState); + Assert.That(session1.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); } } } @@ -1582,7 +1582,7 @@ public void NormalConnectionWithUri() { using (Session session1 = client.GetSession()) { - Assert.AreEqual(SessionState.Open, session1.InternalSession.SessionState); + Assert.That(session1.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); } } } @@ -1609,20 +1609,20 @@ public void ConnectionAttributesKeyRepeatedChars() using (Client client = MySQLX.GetClient(ConnectionString + ";connection-attributes=[quua=bar,quua=qux,key]", "{ \"pooling\": { \"enabled\": true } }")) { Exception ex = Assert.Throws(() => client.GetSession()); - Assert.AreEqual(expectedMsg, ex.Message); + Assert.That(ex.Message, Is.EqualTo(expectedMsg)); } //Uri using (Client client = MySQLX.GetClient(ConnectionStringUri + "?connection-attributes=[quua=bar,quua=qux,key];", "{ \"pooling\": { \"enabled\": true } }")) { Exception ex = Assert.Throws(() => client.GetSession()); - Assert.AreEqual(expectedMsg, ex.Message); + Assert.That(ex.Message, Is.EqualTo(expectedMsg)); } //Anonymous Object MySqlXConnectionStringBuilder sb = new MySqlXConnectionStringBuilder(ConnectionString); using (Client client = MySQLX.GetClient(new { server = sb.Server, port = XPort, user = sb.UserID, password = sb.Password, ConnectionAttributes = "[quua=bar,quua=qux,key=]" }, "{ \"pooling\": { \"enabled\": true } }")) { Exception ex = Assert.Throws(() => client.GetSession()); - Assert.AreEqual(expectedMsg, ex.Message); + Assert.That(ex.Message, Is.EqualTo(expectedMsg)); } if (Platform.IsWindows()) @@ -1642,18 +1642,18 @@ public void ConnectionAttributesKeyRepeatedChars() using (Client client = MySQLX.GetClient(mysqlx0.ConnectionString, "{ \"pooling\": { \"enabled\": true } }")) { Exception ex = Assert.Throws(() => client.GetSession()); - Assert.AreEqual(expectedMsg, ex.Message); + Assert.That(ex.Message, Is.EqualTo(expectedMsg)); } //Connection String Exception ex1 = Assert.Throws(() => MySQLX.GetSession(ConnectionString + ";connection-attributes=[quua=bar,quua=qux,key]")); - Assert.AreEqual(expectedMsg, ex1.Message); + Assert.That(ex1.Message, Is.EqualTo(expectedMsg)); //Uri ex1 = Assert.Throws(() => MySQLX.GetSession(ConnectionStringUri + "?connection-attributes=[quua=bar,quua=qux,key];")); - Assert.AreEqual(expectedMsg, ex1.Message); + Assert.That(ex1.Message, Is.EqualTo(expectedMsg)); //Anonymous Object sb = new MySqlXConnectionStringBuilder(ConnectionString); ex1 = Assert.Throws(() => MySQLX.GetSession(new { server = sb.Server, port = XPort, user = sb.UserID, password = sb.Password, ConnectionAttributes = "[quua=bar,quua=qux,key=]" })); - Assert.AreEqual(expectedMsg, ex1.Message); + Assert.That(ex1.Message, Is.EqualTo(expectedMsg)); //MySqlXConnectionStringBuilder mysqlx0 = new MySqlXConnectionStringBuilder(ConnectionString); mysqlx0.Database = schemaName; @@ -1667,7 +1667,7 @@ public void ConnectionAttributesKeyRepeatedChars() mysqlx0.CertificateThumbprint = ""; mysqlx0.ConnectionAttributes = "[quua=bar,quua=qux,key=]"; ex1 = Assert.Throws(() => MySQLX.GetSession(mysqlx0.ConnectionString)); - Assert.AreEqual(expectedMsg, ex1.Message); + Assert.That(ex1.Message, Is.EqualTo(expectedMsg)); } } @@ -1679,20 +1679,20 @@ public void ConnectionAttributesWithKey33Chars() using (Client client = MySQLX.GetClient(ConnectionString + ";connection-attributes=[foo32foo32foo32foo32foo32foo32323=bar,quua=qux,key]", "{ \"pooling\": { \"enabled\": true } }")) { Exception ex = Assert.Throws(() => client.GetSession()); - Assert.AreEqual(errorMsg, ex.Message); + Assert.That(ex.Message, Is.EqualTo(errorMsg)); } using (Client client = MySQLX.GetClient(ConnectionStringUri + "?connection-attributes=[foo32foo32foo32foo32foo32foo32323=bar,quua=qux,key];", "{ \"pooling\": { \"enabled\": true } }")) { Exception ex = Assert.Throws(() => client.GetSession()); - Assert.AreEqual(errorMsg, ex.Message); + Assert.That(ex.Message, Is.EqualTo(errorMsg)); } MySqlXConnectionStringBuilder sb = new MySqlXConnectionStringBuilder(ConnectionString); using (Client client = MySQLX.GetClient(new { server = sb.Server, port = XPort, user = sb.UserID, password = sb.Password, ConnectionAttributes = "[foo32foo32foo32foo32foo32foo32323=bar,quua=qux,key=]" }, "{ \"pooling\": { \"enabled\": true } }")) { Exception ex = Assert.Throws(() => client.GetSession()); - Assert.AreEqual(errorMsg, ex.Message); + Assert.That(ex.Message, Is.EqualTo(errorMsg)); } if (Platform.IsWindows()) @@ -1710,18 +1710,18 @@ public void ConnectionAttributesWithKey33Chars() using (Client client = MySQLX.GetClient(mysqlx0.ConnectionString, "{ \"pooling\": { \"enabled\": true } }")) { Exception ex = Assert.Throws(() => client.GetSession()); - Assert.AreEqual(errorMsg, ex.Message); + Assert.That(ex.Message, Is.EqualTo(errorMsg)); } Exception ex1 = Assert.Throws(() => MySQLX.GetSession(ConnectionString + ";connection-attributes=[foo32foo32foo32foo32foo32foo32323=bar,quua=qux,key]")); - Assert.AreEqual(errorMsg, ex1.Message); + Assert.That(ex1.Message, Is.EqualTo(errorMsg)); ex1 = Assert.Throws(() => MySQLX.GetSession(ConnectionStringUri + "?connection-attributes=[foo32foo32foo32foo32foo32foo32323=bar,quua=qux,key];")); - Assert.AreEqual(errorMsg, ex1.Message); + Assert.That(ex1.Message, Is.EqualTo(errorMsg)); sb = new MySqlXConnectionStringBuilder(ConnectionString); ex1 = Assert.Throws(() => MySQLX.GetSession(new { server = sb.Server, port = XPort, user = sb.UserID, password = sb.Password, ConnectionAttributes = "[foo32foo32foo32foo32foo32foo32323=bar,quua=qux,key=]" })); - Assert.AreEqual(errorMsg, ex1.Message); + Assert.That(ex1.Message, Is.EqualTo(errorMsg)); mysqlx0 = new MySqlXConnectionStringBuilder(ConnectionString); mysqlx0.CharacterSet = "utf8mb4"; @@ -1734,7 +1734,7 @@ public void ConnectionAttributesWithKey33Chars() mysqlx0.CertificateThumbprint = ""; mysqlx0.ConnectionAttributes = "[foo32foo32foo32foo32foo32foo32323=bar,quua=qux,key=]"; ex1 = Assert.Throws(() => MySQLX.GetSession(mysqlx0.ConnectionString)); - Assert.AreEqual(errorMsg, ex1.Message); + Assert.That(ex1.Message, Is.EqualTo(errorMsg)); } } @@ -1750,20 +1750,20 @@ public void ConnectionAttributesInvalidCombinations() using (Client client = MySQLX.GetClient(ConnectionString + ";connection-attributes=" + invalid[i], "{ \"pooling\": { \"enabled\": true } }")) { Exception ex = Assert.Throws(() => client.GetSession()); - Assert.True(errorMsgs.Contains(ex.Message)); + Assert.That(errorMsgs.Contains(ex.Message)); } //Uri using (Client client = MySQLX.GetClient(ConnectionStringUri + "?connection-attributes=" + invalid[i], "{ \"pooling\": { \"enabled\": true } }")) { Exception ex = Assert.Throws(() => client.GetSession()); - Assert.True(errorMsgs.Contains(ex.Message)); + Assert.That(errorMsgs.Contains(ex.Message)); } //Anonymous object MySqlXConnectionStringBuilder sb = new MySqlXConnectionStringBuilder(ConnectionString); using (Client client = MySQLX.GetClient(new { server = sb.Server, port = XPort, user = sb.UserID, password = sb.Password, ConnectionAttributes = invalid[i] }, "{ \"pooling\": { \"enabled\": true } }")) { Exception ex = Assert.Throws(() => client.GetSession()); - Assert.True(errorMsgs.Contains(ex.Message)); + Assert.That(errorMsgs.Contains(ex.Message)); } if (Platform.IsWindows()) @@ -1783,19 +1783,19 @@ public void ConnectionAttributesInvalidCombinations() using (Client client = MySQLX.GetClient(mysqlx0.ConnectionString, "{ \"pooling\": { \"enabled\": true } }")) { Exception ex = Assert.Throws(() => client.GetSession()); - Assert.True(errorMsgs.Contains(ex.Message)); + Assert.That(errorMsgs.Contains(ex.Message)); } //Connection String Exception ex1 = Assert.Throws(() => MySQLX.GetSession(ConnectionString + ";connection-attributes=" + invalid[i])); - Assert.True(errorMsgs.Contains(ex1.Message)); + Assert.That(errorMsgs.Contains(ex1.Message)); //Uri ex1 = Assert.Throws(() => MySQLX.GetSession(ConnectionStringUri + "?connection-attributes=" + invalid[i])); - Assert.True(errorMsgs.Contains(ex1.Message)); + Assert.That(errorMsgs.Contains(ex1.Message)); //Anonymous object sb = new MySqlXConnectionStringBuilder(ConnectionString); ex1 = Assert.Throws(() => MySQLX.GetSession(new { server = sb.Server, port = XPort, user = sb.UserID, password = sb.Password, ConnectionAttributes = invalid[i] })); - Assert.True(errorMsgs.Contains(ex1.Message)); + Assert.That(errorMsgs.Contains(ex1.Message)); //MySqlXConnectionStringBuilder mysqlx0 = new MySqlXConnectionStringBuilder(ConnectionString); mysqlx0.Database = schemaName; @@ -1809,7 +1809,7 @@ public void ConnectionAttributesInvalidCombinations() mysqlx0.CertificateThumbprint = ""; mysqlx0.ConnectionAttributes = invalid[i].ToString(); ex1 = Assert.Throws(() => MySQLX.GetSession(mysqlx0.ConnectionString)); - Assert.True(errorMsgs.Contains(ex1.Message)); + Assert.That(errorMsgs.Contains(ex1.Message)); } } } @@ -1827,7 +1827,7 @@ public void ConnectionAttributesValidCombinations() { using (Session session = client.GetSession()) { - Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); + Assert.That(session.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); } } @@ -1835,7 +1835,7 @@ public void ConnectionAttributesValidCombinations() { using (Session session = client.GetSession()) { - Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); + Assert.That(session.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); } } @@ -1844,7 +1844,7 @@ public void ConnectionAttributesValidCombinations() { using (Session session = client.GetSession()) { - Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); + Assert.That(session.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); } } @@ -1863,24 +1863,24 @@ public void ConnectionAttributesValidCombinations() { using (Session session = client.GetSession()) { - Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); + Assert.That(session.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); } } using (Session session = MySQLX.GetSession(ConnectionString + ";connection-attributes=" + invalid[i])) { - Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); + Assert.That(session.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); } using (Session session = MySQLX.GetSession(ConnectionStringUri + "?connection-attributes=" + invalid[i])) { - Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); + Assert.That(session.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); } sb = new MySqlXConnectionStringBuilder(ConnectionString); using (Session session = MySQLX.GetSession(new { server = sb.Server, port = XPort, user = sb.UserID, password = sb.Password, ConnectionAttributes = invalid[i] })) { - Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); + Assert.That(session.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); } mysqlx0 = new MySqlXConnectionStringBuilder(ConnectionString); @@ -1897,7 +1897,7 @@ public void ConnectionAttributesValidCombinations() using (Session session = MySQLX.GetSession(mysqlx0.ConnectionString)) { - Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); + Assert.That(session.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); } } } @@ -1912,7 +1912,7 @@ public void ConnectionAttributesKeySpecialChars() { using (Session session = client.GetSession()) { - Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); + Assert.That(session.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); } } @@ -1920,7 +1920,7 @@ public void ConnectionAttributesKeySpecialChars() { using (Session session = client.GetSession()) { - Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); + Assert.That(session.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); } } @@ -1935,7 +1935,7 @@ public void ConnectionAttributesKeySpecialChars() { using (Session session = client.GetSession()) { - Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); + Assert.That(session.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); } } @@ -1954,18 +1954,18 @@ public void ConnectionAttributesKeySpecialChars() { using (Session session = client.GetSession()) { - Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); + Assert.That(session.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); } } using (Session session = MySQLX.GetSession(ConnectionString + ";connection-attributes=[@#$%^&*()=bar,quua=*(&^&#$%,key]")) { - Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); + Assert.That(session.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); } using (Session session = MySQLX.GetSession(new { server = sb.Server, port = XPort, user = sb.UserID, password = sb.Password, ConnectionAttributes = "[@#$%^&*()=bar,quua=*(&^&#$%,key=]" })) { - Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); + Assert.That(session.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); } mysqlx0 = new MySqlXConnectionStringBuilder(ConnectionString); @@ -1981,7 +1981,7 @@ public void ConnectionAttributesKeySpecialChars() mysqlx0.ConnectionAttributes = "[@#$%^&*()=bar,quua=*(&^&#$%,key=]"; using (Session session = MySQLX.GetSession(mysqlx0.ConnectionString)) { - Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); + Assert.That(session.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); } } @@ -1997,19 +1997,19 @@ public void ConnectionAttributesKeyWithUnderLineChars() using (Client client = MySQLX.GetClient(ConnectionString + ";connection-attributes=[_foo32=bar,quua=qux,key]", "{ \"pooling\": { \"enabled\": true } }")) { Exception ex = Assert.Throws(() => client.GetSession()); - Assert.AreEqual(expectedMsg, ex.Message); + Assert.That(ex.Message, Is.EqualTo(expectedMsg)); } //Uri using (Client client = MySQLX.GetClient(ConnectionStringUri + "?connection-attributes=[_foo32=bar,quua=qux,key];", "{ \"pooling\": { \"enabled\": true } }")) { Exception ex = Assert.Throws(() => client.GetSession()); - Assert.AreEqual(expectedMsg, ex.Message); + Assert.That(ex.Message, Is.EqualTo(expectedMsg)); } //Anonymous object using (Client client = MySQLX.GetClient(new { server = sb.Server, port = XPort, user = sb.UserID, password = sb.Password, ConnectionAttributes = "[_foo32=bar,quua=qux,key=]" }, "{ \"pooling\": { \"enabled\": true } }")) { Exception ex = Assert.Throws(() => client.GetSession()); - Assert.AreEqual(expectedMsg, ex.Message); + Assert.That(ex.Message, Is.EqualTo(expectedMsg)); } MySqlXConnectionStringBuilder mysqlx0 = new MySqlXConnectionStringBuilder(ConnectionString); @@ -2026,18 +2026,18 @@ public void ConnectionAttributesKeyWithUnderLineChars() using (Client client = MySQLX.GetClient(mysqlx0.ConnectionString, "{ \"pooling\": { \"enabled\": true } }")) { Exception ex = Assert.Throws(() => client.GetSession()); - Assert.AreEqual(expectedMsg, ex.Message); + Assert.That(ex.Message, Is.EqualTo(expectedMsg)); } //Connection string Exception ex1 = Assert.Throws(() => MySQLX.GetSession(ConnectionString + ";connection-attributes=[_foo32=bar,quua=qux,key]")); - Assert.AreEqual(expectedMsg, ex1.Message); + Assert.That(ex1.Message, Is.EqualTo(expectedMsg)); //Uri ex1 = Assert.Throws(() => MySQLX.GetSession(ConnectionStringUri + "?connection-attributes=[_foo32=bar,quua=qux,key];")); - Assert.AreEqual(expectedMsg, ex1.Message); + Assert.That(ex1.Message, Is.EqualTo(expectedMsg)); //Anonymous object ex1 = Assert.Throws(() => MySQLX.GetSession(new { server = sb.Server, port = XPort, user = sb.UserID, password = sb.Password, ConnectionAttributes = "[_foo32=bar,quua=qux,key=]" })); - Assert.AreEqual(expectedMsg, ex1.Message); + Assert.That(ex1.Message, Is.EqualTo(expectedMsg)); //MySqlXConnectionStringBuilder mysqlx0 = new MySqlXConnectionStringBuilder(ConnectionString); mysqlx0.Database = schemaName; @@ -2051,7 +2051,7 @@ public void ConnectionAttributesKeyWithUnderLineChars() mysqlx0.CertificateThumbprint = ""; mysqlx0.ConnectionAttributes = "[_foo32=bar,quua=qux,key=]"; ex1 = Assert.Throws(() => MySQLX.GetSession(mysqlx0.ConnectionString)); - Assert.AreEqual(expectedMsg, ex1.Message); + Assert.That(ex1.Message, Is.EqualTo(expectedMsg)); } @@ -2066,21 +2066,21 @@ public void ConnectionAttributesKeyBlankChars() using (Client client = MySQLX.GetClient(ConnectionString + ";connection-attributes=[=bar,quua=qux,key]", "{ \"pooling\": { \"enabled\": true } }")) { Exception ex = Assert.Throws(() => client.GetSession()); - Assert.AreEqual(expectedMsg, ex.Message); + Assert.That(ex.Message, Is.EqualTo(expectedMsg)); } //Uri using (Client client = MySQLX.GetClient(ConnectionStringUri + "?connection-attributes=[=bar,quua=qux,key];", "{ \"pooling\": { \"enabled\": true } }")) { Exception ex = Assert.Throws(() => client.GetSession()); - Assert.AreEqual(expectedMsg, ex.Message); + Assert.That(ex.Message, Is.EqualTo(expectedMsg)); } //Anonymous object using (Client client = MySQLX.GetClient(new { server = sb.Server, port = XPort, user = sb.UserID, password = sb.Password, ConnectionAttributes = "[=bar,quua=qux,key=]" }, "{ \"pooling\": { \"enabled\": true } }")) { Exception ex = Assert.Throws(() => client.GetSession()); - Assert.AreEqual(expectedMsg, ex.Message); + Assert.That(ex.Message, Is.EqualTo(expectedMsg)); } //MySqlXConnectionStringBuilder @@ -2098,18 +2098,18 @@ public void ConnectionAttributesKeyBlankChars() using (Client client = MySQLX.GetClient(mysqlx0.ConnectionString, "{ \"pooling\": { \"enabled\": true } }")) { Exception ex = Assert.Throws(() => client.GetSession()); - Assert.AreEqual(expectedMsg, ex.Message); + Assert.That(ex.Message, Is.EqualTo(expectedMsg)); } //Connection String Exception ex1 = Assert.Throws(() => MySQLX.GetSession(ConnectionString + ";connection-attributes=[=bar,quua=qux,key]")); - Assert.AreEqual(expectedMsg, ex1.Message); + Assert.That(ex1.Message, Is.EqualTo(expectedMsg)); //Uri ex1 = Assert.Throws(() => MySQLX.GetSession(ConnectionStringUri + "?connection-attributes=[=bar,quua=qux,key];")); - Assert.AreEqual(expectedMsg, ex1.Message); + Assert.That(ex1.Message, Is.EqualTo(expectedMsg)); //Anonymous object ex1 = Assert.Throws(() => MySQLX.GetSession(new { server = sb.Server, port = XPort, user = sb.UserID, password = sb.Password, ConnectionAttributes = "[=bar,quua=qux,key=]" })); - Assert.AreEqual(expectedMsg, ex1.Message); + Assert.That(ex1.Message, Is.EqualTo(expectedMsg)); //MySqlXConnectionStringBuilder mysqlx0 = new MySqlXConnectionStringBuilder(ConnectionString); mysqlx0.Database = schemaName; @@ -2123,7 +2123,7 @@ public void ConnectionAttributesKeyBlankChars() mysqlx0.CertificateThumbprint = ""; mysqlx0.ConnectionAttributes = "[=bar,quua=qux,key=]"; ex1 = Assert.Throws(() => MySQLX.GetSession(mysqlx0.ConnectionString)); - Assert.AreEqual(expectedMsg, ex1.Message); + Assert.That(ex1.Message, Is.EqualTo(expectedMsg)); } @@ -2139,19 +2139,19 @@ public void ConnectionAttributesValue1025Chars() using (Client client = MySQLX.GetClient(ConnectionString + $";connection-attributes={strValue}", "{ \"pooling\": { \"enabled\": true } }")) { Exception ex = Assert.Catch(() => client.GetSession()); - Assert.AreEqual(expectedMsg, ex.Message); + Assert.That(ex.Message, Is.EqualTo(expectedMsg)); } //Uri using (Client client = MySQLX.GetClient(ConnectionStringUri + $"?connection-attributes={strValue};", "{ \"pooling\": { \"enabled\": true } }")) { Exception ex = Assert.Catch(() => client.GetSession()); - Assert.AreEqual(expectedMsg, ex.Message); + Assert.That(ex.Message, Is.EqualTo(expectedMsg)); } //Anonymous object using (Client client = MySQLX.GetClient(new { server = sb.Server, port = XPort, user = sb.UserID, password = sb.Password, ConnectionAttributes = strValue }, "{ \"pooling\": { \"enabled\": true } }")) { Exception ex = Assert.Catch(() => client.GetSession()); - Assert.AreEqual(expectedMsg, ex.Message); + Assert.That(ex.Message, Is.EqualTo(expectedMsg)); } //MySqlXConnectionStringBuilder @@ -2169,17 +2169,17 @@ public void ConnectionAttributesValue1025Chars() using (Client client = MySQLX.GetClient(mysqlx0.ConnectionString, "{ \"pooling\": { \"enabled\": true } }")) { Exception ex = Assert.Catch(() => client.GetSession()); - Assert.AreEqual(expectedMsg, ex.Message); + Assert.That(ex.Message, Is.EqualTo(expectedMsg)); } //Connection String Exception ex2 = Assert.Catch(() => MySQLX.GetSession(ConnectionString + $";connection-attributes={strValue}")); - Assert.AreEqual(expectedMsg, ex2.Message); + Assert.That(ex2.Message, Is.EqualTo(expectedMsg)); //Uri ex2 = Assert.Catch(() => MySQLX.GetSession(ConnectionStringUri + $"?connection-attributes={strValue};")); - Assert.AreEqual(expectedMsg, ex2.Message); + Assert.That(ex2.Message, Is.EqualTo(expectedMsg)); //Anonymous object ex2 = Assert.Catch(() => MySQLX.GetSession(new { server = sb.Server, port = XPort, user = sb.UserID, password = sb.Password, ConnectionAttributes = strValue })); - Assert.AreEqual(expectedMsg, ex2.Message); + Assert.That(ex2.Message, Is.EqualTo(expectedMsg)); //MySqlXConnectionStringBuilder mysqlx0 = new MySqlXConnectionStringBuilder(ConnectionString); mysqlx0.Database = schemaName; @@ -2193,7 +2193,7 @@ public void ConnectionAttributesValue1025Chars() mysqlx0.CertificateThumbprint = ""; mysqlx0.ConnectionAttributes = strValue; ex2 = Assert.Catch(() => MySQLX.GetSession(mysqlx0.ConnectionString)); - Assert.AreEqual(expectedMsg, ex2.Message); + Assert.That(ex2.Message, Is.EqualTo(expectedMsg)); } @@ -2212,12 +2212,12 @@ public void SessionRestore() if (res0.HasData) { var row = res0.FetchOne(); - Assert.AreEqual("big5", row[1].ToString()); + Assert.That(row[1].ToString(), Is.EqualTo("big5")); } session1.Close(); Session session2 = client.GetSession(); string threadId2 = session2.SQL("SELECT THREAD_ID FROM performance_schema.threads WHERE PROCESSLIST_ID=CONNECTION_ID()").Execute().FetchOne()[0].ToString(); - Assert.True(threadId1.Equals(threadId2)); + Assert.That(threadId1.Equals(threadId2)); session2.Close(); } } @@ -2283,8 +2283,8 @@ public void MultiSessionAuthentication() Session session4_1 = client.GetSession(); string threadId5 = session3_1.SQL("SELECT THREAD_ID FROM performance_schema.threads WHERE PROCESSLIST_ID=CONNECTION_ID()").Execute().FetchOne()[0].ToString(); string threadId6 = session4_1.SQL("SELECT THREAD_ID FROM performance_schema.threads WHERE PROCESSLIST_ID=CONNECTION_ID()").Execute().FetchOne()[0].ToString(); - Assert.False(threadId3.Equals(threadId5)); - Assert.False(threadId4.Equals(threadId6)); + Assert.That(threadId3.Equals(threadId5), Is.False); + Assert.That(threadId4.Equals(threadId6), Is.False); } } @@ -2312,7 +2312,7 @@ public void VerifyDataCleanupAfterClientClose(Client _client1, int iteration, st if (res0.HasData) { var row = res0.FetchOne(); - Assert.AreEqual("big5", row[1].ToString()); + Assert.That(row[1].ToString(), Is.EqualTo("big5")); } _client1.Close(); _client1 = MySQLX.GetClient(connectionString, clientOptions); @@ -2321,7 +2321,7 @@ public void VerifyDataCleanupAfterClientClose(Client _client1, int iteration, st if (res0.HasData) { var row = res0.FetchOne(); - Assert.AreEqual("utf8mb4", row[1].ToString()); + Assert.That(row[1].ToString(), Is.EqualTo("utf8mb4")); } } @@ -2342,7 +2342,7 @@ public void VerifyDataCleanupOneSession(Client client1, int iteration) if (res0.HasData) { var row = res0.FetchOne(); - Assert.AreEqual("big5", row[1].ToString()); + Assert.That(row[1].ToString(), Is.EqualTo("big5")); } sess0.Close(); Session sess4 = client1.GetSession(); @@ -2350,7 +2350,7 @@ public void VerifyDataCleanupOneSession(Client client1, int iteration) if (res0.HasData) { var row = res0.FetchOne(); - Assert.AreEqual("utf8mb4", row[1].ToString()); + Assert.That(row[1].ToString(), Is.EqualTo("utf8mb4")); } } @@ -2370,7 +2370,7 @@ public void CompareConnectionIDs(Client client1, int maxTimeout, bool maxTimeout if (res0.HasData) { var row = res0.FetchOne(); - Assert.AreEqual("big5", row[1].ToString()); + Assert.That(row[1].ToString(), Is.EqualTo("big5")); } res0 = sess0.SQL("SELECT CONNECTION_ID()").Execute(); if (res0.HasData) @@ -2386,7 +2386,7 @@ public void CompareConnectionIDs(Client client1, int maxTimeout, bool maxTimeout if (res0.HasData) { var row = res0.FetchOne(); - Assert.AreEqual("utf8mb4", row[1].ToString()); + Assert.That(row[1].ToString(), Is.EqualTo("utf8mb4")); } res0 = sess0.SQL("SELECT CONNECTION_ID()").Execute(); if (res0.HasData) @@ -2403,7 +2403,7 @@ public void CompareConnectionIDs(Client client1, int maxTimeout, bool maxTimeout if (res0.HasData) { var row = res0.FetchOne(); - Assert.AreEqual("big5", row[1].ToString()); + Assert.That(row[1].ToString(), Is.EqualTo("big5")); } res0 = sess0.SQL("SELECT CONNECTION_ID()").Execute(); if (res0.HasData) @@ -2420,7 +2420,7 @@ public void CompareConnectionIDs(Client client1, int maxTimeout, bool maxTimeout if (res0.HasData) { var row = res0.FetchOne(); - Assert.AreEqual("utf8mb4", row[1].ToString()); + Assert.That(row[1].ToString(), Is.EqualTo("utf8mb4")); } res0 = sess0.SQL("SELECT CONNECTION_ID()").Execute(); if (res0.HasData) @@ -2432,15 +2432,15 @@ public void CompareConnectionIDs(Client client1, int maxTimeout, bool maxTimeout sess0.Close(); if (maxTimeoutGreater) { - Assert.False(connectionID1.Equals(connectionID2)); + Assert.That(connectionID1.Equals(connectionID2), Is.False); } if (maxTimeoutGreater) { - Assert.AreNotEqual(cID3, cID2); + Assert.That(cID2, Is.Not.EqualTo(cID3)); } else { - Assert.True(cID3 == cID2); + Assert.That(cID3 == cID2); } } @@ -2459,7 +2459,7 @@ public void CompareConnectionIDs(Client client1, Client client2, Client client3) if (res0.HasData) { var row = res0.FetchOne(); - Assert.AreEqual("big5", row[1].ToString()); + Assert.That(row[1].ToString(), Is.EqualTo("big5")); } res0 = sess0.SQL("SELECT CONNECTION_ID()").Execute(); if (res0.HasData) @@ -2473,7 +2473,7 @@ public void CompareConnectionIDs(Client client1, Client client2, Client client3) if (res0.HasData) { var row = res0.FetchOne(); - Assert.AreEqual("utf8mb4", row[1].ToString()); + Assert.That(row[1].ToString(), Is.EqualTo("utf8mb4")); } res0 = sess0.SQL("SELECT CONNECTION_ID()").Execute(); if (res0.HasData) @@ -2493,7 +2493,7 @@ public void CompareConnectionIDs(Client client1, Client client2, Client client3) if (res.HasData) { var row = res.FetchOne(); - Assert.AreEqual("big5", row[1].ToString()); + Assert.That(row[1].ToString(), Is.EqualTo("big5")); } res = sess.SQL("SELECT CONNECTION_ID()").Execute(); if (res.HasData) @@ -2507,7 +2507,7 @@ public void CompareConnectionIDs(Client client1, Client client2, Client client3) if (res.HasData) { var row = res.FetchOne(); - Assert.AreEqual("utf8mb4", row[1].ToString()); + Assert.That(row[1].ToString(), Is.EqualTo("utf8mb4")); } res = sess.SQL("SELECT CONNECTION_ID()").Execute(); if (res.HasData) @@ -2516,7 +2516,7 @@ public void CompareConnectionIDs(Client client1, Client client2, Client client3) connectionID2 = row[0].ToString(); } sess.Close(); - Assert.False(connectionID1.Equals(connectionID2)); + Assert.That(connectionID1.Equals(connectionID2), Is.False); } /// @@ -2534,7 +2534,7 @@ public void CompareConnectionIDs(Client client1, int maxTimeout, bool maxTimeout if (res0.HasData) { var row = res0.FetchOne(); - Assert.AreEqual("big5", row[1].ToString()); + Assert.That(row[1].ToString(), Is.EqualTo("big5")); } res0 = sess0.SQL("SELECT CONNECTION_ID()").Execute(); if (res0.HasData) @@ -2550,7 +2550,7 @@ public void CompareConnectionIDs(Client client1, int maxTimeout, bool maxTimeout if (res0.HasData) { var row = res0.FetchOne(); - Assert.AreEqual("utf8mb4", row[1].ToString()); + Assert.That(row[1].ToString(), Is.EqualTo("utf8mb4")); } res0 = sess0.SQL("SELECT CONNECTION_ID()").Execute(); if (res0.HasData) @@ -2567,7 +2567,7 @@ public void CompareConnectionIDs(Client client1, int maxTimeout, bool maxTimeout if (res0.HasData) { var row = res0.FetchOne(); - Assert.AreEqual("big5", row[1].ToString()); + Assert.That(row[1].ToString(), Is.EqualTo("big5")); } res0 = sess0.SQL("SELECT CONNECTION_ID()").Execute(); if (res0.HasData) @@ -2584,7 +2584,7 @@ public void CompareConnectionIDs(Client client1, int maxTimeout, bool maxTimeout if (res0.HasData) { var row = res0.FetchOne(); - Assert.AreEqual("utf8mb4", row[1].ToString()); + Assert.That(row[1].ToString(), Is.EqualTo("utf8mb4")); } res0 = sess0.SQL("SELECT CONNECTION_ID()").Execute(); if (res0.HasData) @@ -2596,19 +2596,19 @@ public void CompareConnectionIDs(Client client1, int maxTimeout, bool maxTimeout sess0.Close(); if (maxTimeoutGreater) { - Assert.False(connectionID1.Equals(connectionID2), "Connection ID Matches when a session is closed and opened again"); + Assert.That(connectionID1.Equals(connectionID2), Is.False, "Connection ID Matches when a session is closed and opened again"); } if (maxTimeout.CompareTo(sleepTimeout) > 0) { - Assert.True(cID3 != cID2); + Assert.That(cID3 != cID2); } else if (maxTimeout.CompareTo(sleepTimeout) == 0) { - Assert.True(cID1 == cID2); + Assert.That(cID1 == cID2); } else { - Assert.True(cID1 == cID2); + Assert.That(cID1 == cID2); } } @@ -2623,9 +2623,9 @@ public void TestClientQueueTimeout(Client client, int minTime, int maxTime) { Stopwatch stopwatch = Stopwatch.StartNew(); Exception ex = Assert.Throws(() => client.GetSession()); - StringAssert.Contains("timeout", ex.Message); + Assert.That(ex.Message, Does.Contain("timeout")); stopwatch.Stop(); - Assert.True(stopwatch.ElapsedMilliseconds > minTime && stopwatch.ElapsedMilliseconds < maxTime); + Assert.That(stopwatch.ElapsedMilliseconds > minTime && stopwatch.ElapsedMilliseconds < maxTime); } /// diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/CloseConnectionTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/CloseConnectionTests.cs index 46afde1da..98f85067e 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/CloseConnectionTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/CloseConnectionTests.cs @@ -55,7 +55,7 @@ public void NotificationKill() using (Session session1 = MySQLX.GetSession(ConnectionString)) { Schema test = session1.GetSchema("test"); - Assert.AreEqual(SessionState.Open, session1.XSession.SessionState); + Assert.That(session1.XSession.SessionState, Is.EqualTo(SessionState.Open)); var threadId1 = (UInt64)session1.ThreadId; // Kill connection @@ -63,9 +63,9 @@ public void NotificationKill() Thread.Sleep(5000); Exception ex = Assert.Throws(() => session1.SQL("select 1").Execute()); - StringAssert.Contains(ResourcesX.NoticeKilledConnection, ex.Message); + Assert.That(ex.Message, Does.Contain(ResourcesX.NoticeKilledConnection)); - Assert.AreEqual(SessionState.Closed, session1.XSession.SessionState); + Assert.That(session1.XSession.SessionState, Is.EqualTo(SessionState.Closed)); } } @@ -79,14 +79,14 @@ public void NotificationIdle() ExecuteSqlAsRoot("SET GLOBAL mysqlx_wait_timeout = 5"); using (Session localsession = MySQLX.GetSession(ConnectionString)) { - Assert.AreEqual(SessionState.Open, localsession.XSession.SessionState); + Assert.That(localsession.XSession.SessionState, Is.EqualTo(SessionState.Open)); //wait for server to kill idle connection Thread.Sleep(7000); Exception ex = Assert.Throws(() => localsession.SQL("select 1").Execute()); - StringAssert.Contains(ResourcesX.NoticeIdleConnection, ex.Message); + Assert.That(ex.Message, Does.Contain(ResourcesX.NoticeIdleConnection)); - Assert.AreEqual(SessionState.Closed, localsession.XSession.SessionState); + Assert.That(localsession.XSession.SessionState, Is.EqualTo(SessionState.Closed)); } ExecuteSqlAsRoot("SET GLOBAL mysqlx_read_timeout = 28800"); ExecuteSqlAsRoot("SET GLOBAL mysqlx_wait_timeout = 28800"); @@ -122,8 +122,8 @@ public void CloseWarningsWithCollections(CloseData closeData) Thread.Sleep(5000); MySqlException ex = Assert.Throws(() => { closeData.Action.Invoke(sessionCol); }); - Assert.AreEqual(ResourcesX.NoticeKilledConnection, ex.Message); - Assert.AreEqual(SessionState.Closed, sessionCol.XSession.SessionState); + Assert.That(ex.Message, Is.EqualTo(ResourcesX.NoticeKilledConnection)); + Assert.That(sessionCol.XSession.SessionState, Is.EqualTo(SessionState.Closed)); } //Shutdown server Notice, exception expected @@ -135,16 +135,16 @@ public void NotificationShutdown() using (Session localsession = MySQLX.GetSession(BaseTest.ConnectionString)) { - Assert.AreEqual(SessionState.Open, localsession.XSession.SessionState); + Assert.That(localsession.XSession.SessionState, Is.EqualTo(SessionState.Open)); // Shutdown local MySQL Server ShutdownServer(); Thread.Sleep(2000); Exception ex = Assert.Throws(() => localsession.SQL("select 1").Execute()); - StringAssert.Contains(ResourcesX.NoticeServerShutdown, ex.Message); + Assert.That(ex.Message, Does.Contain(ResourcesX.NoticeServerShutdown)); - Assert.AreEqual(SessionState.Closed, localsession.XSession.SessionState); + Assert.That(localsession.XSession.SessionState, Is.EqualTo(SessionState.Closed)); } } @@ -176,24 +176,24 @@ public void PoolTestCloseOneConnection() //verify session 1 open var result1 = session1.SQL("select sqrt(9) as raiz;").Execute().FetchOne().GetString("raiz"); - StringAssert.Contains("3", result1); + Assert.That(result1, Does.Contain("3")); //try to use session 2 Exception ex1 = Assert.Throws(() => session2.SQL("select sqrt(9) as raiz;").Execute()); - StringAssert.Contains(ResourcesX.NoticeKilledConnection, ex1.Message); + Assert.That(ex1.Message, Does.Contain(ResourcesX.NoticeKilledConnection)); //verify session 3 open var result2 = session3.SQL("select sqrt(9) as raiz;").Execute().FetchOne().GetString("raiz"); - StringAssert.Contains("3", result2); + Assert.That(result2, Does.Contain("3")); //try to use session 2 once it is Invalid Exception ex2 = Assert.Throws(() => session2.SQL("SELECT 5").Execute()); - Assert.AreEqual(ResourcesX.InvalidSession, ex2.Message); + Assert.That(ex2.Message, Is.EqualTo(ResourcesX.InvalidSession)); //reuse session2 session2 = client.GetSession(); var result3 = session2.SQL("select sqrt(9) as raiz;").Execute().FetchOne().GetString("raiz"); - StringAssert.Contains("3", result3); + Assert.That(result3, Does.Contain("3")); } } @@ -216,13 +216,13 @@ public void PoolTestShutdown() // All connections should receive a close notification and become closed and invalid Exception ex1 = Assert.Throws(() => session1.SQL("select sqrt(9) as raiz;").Execute()); - StringAssert.Contains(ResourcesX.NoticeServerShutdown, ex1.Message); + Assert.That(ex1.Message, Does.Contain(ResourcesX.NoticeServerShutdown)); Exception ex2 = Assert.Throws(() => session2.SQL("select sqrt(9) as raiz;").Execute()); - StringAssert.Contains(ResourcesX.NoticeServerShutdown, ex2.Message); + Assert.That(ex2.Message, Does.Contain(ResourcesX.NoticeServerShutdown)); Exception ex3 = Assert.Throws(() => session3.SQL("select sqrt(9) as raiz;").Execute()); - StringAssert.Contains(ResourcesX.NoticeServerShutdown, ex3.Message); + Assert.That(ex3.Message, Does.Contain(ResourcesX.NoticeServerShutdown)); } } @@ -243,10 +243,10 @@ public void PoolWithIdleConnections() Thread.Sleep(8000); Exception ex1 = Assert.Throws(() => session1.SQL("select sqrt(9) as raiz;").Execute()); - StringAssert.Contains(ResourcesX.NoticeIdleConnection, ex1.Message); + Assert.That(ex1.Message, Does.Contain(ResourcesX.NoticeIdleConnection)); Exception ex2 = Assert.Throws(() => session2.SQL("select sqrt(9) as raiz;").Execute()); - StringAssert.Contains(ResourcesX.NoticeIdleConnection, ex2.Message); + Assert.That(ex2.Message, Does.Contain(ResourcesX.NoticeIdleConnection)); } ExecuteSqlAsRoot("SET GLOBAL mysqlx_read_timeout = 28800"); diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/CollectionAsyncTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/CollectionAsyncTests.cs index 6c9c393df..4e8fec078 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/CollectionAsyncTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/CollectionAsyncTests.cs @@ -54,7 +54,7 @@ public void CollectionInsert() Task.WaitAll(tasksList.ToArray(), TimeSpan.FromMinutes(1)); var count = session.SQL("SELECT COUNT(*) FROM test.test").Execute().FetchOne()[0]; - Assert.AreEqual(count, coll.Count()); + Assert.That(coll.Count(), Is.EqualTo(count)); } [Test] @@ -78,15 +78,15 @@ public void MultipleFindAsync() tasksList.Add(coll.Find("age = :age").Bind("AgE", i).ExecuteAsync()); } - Assert.True(Task.WaitAll(tasksList.ToArray(), TimeSpan.FromMinutes(2)), "WaitAll timeout"); + Assert.That(Task.WaitAll(tasksList.ToArray(), TimeSpan.FromMinutes(2)), "WaitAll timeout"); foreach (Task> task in tasksList) { var doc = task.Result.FetchOne(); string value = task.Result.Current["age"].ToString(); - Assert.False(validator.Contains(value), value + " value exists"); + Assert.That(validator.Contains(value), Is.False, value + " value exists"); validator.Add(value); } - Assert.AreEqual(docs, validator.Count); + Assert.That(validator.Count, Is.EqualTo(docs)); } [Test, Description("Create valid index using a document field type of array and setting array to true/with single key on all possible datatypes concurrently)")] @@ -102,7 +102,7 @@ public async Task IndexArrayMultiThreading() int v1 = await IndexArrayMultiThreading_T1(); int v2 = await IndexArrayMultiThreading_T2(); - Assert.AreEqual(2, v1 + v2); + Assert.That(v1 + v2, Is.EqualTo(2)); } private async Task IndexArrayMultiThreading_T1() diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/CollectionIndexTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/CollectionIndexTests.cs index df880847c..3da6ab3cb 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/CollectionIndexTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/CollectionIndexTests.cs @@ -48,37 +48,37 @@ public void IncorrectlyFormatedIndexDefinition() var collection = CreateCollection("test"); Exception ex = Assert.Throws(() => collection.CreateIndex("myIndex", "{\"type\": \"INDEX\" }")); - Assert.AreEqual("Field 'fields' is mandatory.", ex.Message); + Assert.That(ex.Message, Is.EqualTo("Field 'fields' is mandatory.")); ex = Assert.Throws(() => collection.CreateIndex("myIndex", "{\"fields\": [ { \"field\":$.myField, \"type\":\"TEXT\" } ], \"unexpectedField\" : false }")); - Assert.AreEqual("Field name 'unexpectedField' is not allowed.", ex.Message); + Assert.That(ex.Message, Is.EqualTo("Field name 'unexpectedField' is not allowed.")); ex = Assert.Throws(() => collection.CreateIndex("myIndex", "{\"fields\": [ { \"fields\":$.myField, \"types\":\"TEXT\" } ] }")); - Assert.AreEqual("Field 'field' is mandatory.", ex.Message); + Assert.That(ex.Message, Is.EqualTo("Field 'field' is mandatory.")); ex = Assert.Throws(() => collection.CreateIndex("myIndex", "{\"fields\": [ { \"field\":$.myField, \"types\":\"TEXT\" } ] }")); - Assert.AreEqual("Field 'type' is mandatory.", ex.Message); + Assert.That(ex.Message, Is.EqualTo("Field 'type' is mandatory.")); ex = Assert.Throws(() => collection.CreateIndex("myIndex", "{\"fields\": [ { \"field\":$.myField, \"type\":\"TEXT\", \"unexpectedField\" : false } ] }")); - Assert.AreEqual("Field name 'unexpectedField' is not allowed.", ex.Message); + Assert.That(ex.Message, Is.EqualTo("Field name 'unexpectedField' is not allowed.")); if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher."); collection = CreateCollection("test"); ex = Assert.Throws(() => collection.CreateIndex("myIndex", "{\"fields\": [ { \"field\":$.myField, \"type\":\"INT\" } ], \"type\":\"indexa\" }")); - Assert.AreEqual("Argument value 'indexa' for index type is invalid", ex.Message); + Assert.That(ex.Message, Is.EqualTo("Argument value 'indexa' for index type is invalid")); ex = Assert.Throws(() => collection.CreateIndex("myIndex", "{\"fields\": [ { \"field\":$.myField, \"type\":\"INT\" } ], \"type\":\"OTheR\" }")); - Assert.AreEqual("Argument value 'OTheR' for index type is invalid", ex.Message); + Assert.That(ex.Message, Is.EqualTo("Argument value 'OTheR' for index type is invalid")); ex = Assert.Throws(() => collection.CreateIndex("myIndex1", "{\"fields\": [ { \"field\":$.myGeoJsonField, \"type\":\"GEOJSON\" } ], \"type\":\"Spatial\" }")); - Assert.AreEqual("GEOJSON index requires 'constraint.required: TRUE", ex.Message); + Assert.That(ex.Message, Is.EqualTo("GEOJSON index requires 'constraint.required: TRUE")); ex = Assert.Throws(() => collection.CreateIndex("myIndex2", "{\"fields\": [ { \"field\":$.myGeoJsonField, \"type\":\"GEOJSON\" } ], \"type\":\"spatial\" }")); - Assert.AreEqual("GEOJSON index requires 'constraint.required: TRUE", ex.Message); + Assert.That(ex.Message, Is.EqualTo("GEOJSON index requires 'constraint.required: TRUE")); ex = Assert.Throws(() => collection.CreateIndex("myIndex3", "{\"fields\": [ { \"field\":$.myGeoJsonField, \"type\":\"GEOJSON\" } ], \"type\":\"sPaTiAl\" }")); - Assert.AreEqual("GEOJSON index requires 'constraint.required: TRUE", ex.Message); + Assert.That(ex.Message, Is.EqualTo("GEOJSON index requires 'constraint.required: TRUE")); } [Test] @@ -215,11 +215,11 @@ public void DropIndex() collection.DropIndex("myIndex"); Exception ex = Assert.Throws(() => ValidateIndex("myIndex", "test", "t10", false, false, false, 1, 10)); - Assert.AreEqual("Index not found.", ex.Message); + Assert.That(ex.Message, Is.EqualTo("Index not found.")); ex = Assert.Throws(() => ValidateIndex("myIndex", "test", "t10", false, true, false, 2, 10)); - Assert.AreEqual("Index not found.", ex.Message); + Assert.That(ex.Message, Is.EqualTo("Index not found.")); ex = Assert.Throws(() => ValidateIndex("myIndex", "test", "i_u", false, false, true, 3)); - Assert.AreEqual("Index not found.", ex.Message); + Assert.That(ex.Message, Is.EqualTo("Index not found.")); } [Test] @@ -229,7 +229,7 @@ public void CreateIndexWithDuplicateName() collection.CreateIndex("myUniqueIndex", "{\"fields\": [ { \"field\":$.myField, \"type\":\"INT\" } ] }"); Exception ex = Assert.Throws(() => collection.CreateIndex("myUniqueIndex", "{\"fields\": [ { \"field\":$.myField, \"type\":\"INT\" } ] }")); - Assert.AreEqual("Duplicate key name 'myUniqueIndex'", ex.Message); + Assert.That(ex.Message, Is.EqualTo("Duplicate key name 'myUniqueIndex'")); } [Test] @@ -238,11 +238,11 @@ public void CreateIndexWithInvalidJsonDocumentDefinition() var collection = CreateCollection("test"); Exception ex = Assert.Throws(() => collection.CreateIndex("myIndex", "{\"fields\": [ { \"field\" = $.myField, \"type\" = \"TEXT\" } ] }")); - Assert.AreEqual("The value provided is not a valid JSON document. Expected token ':'", ex.Message); + Assert.That(ex.Message, Is.EqualTo("The value provided is not a valid JSON document. Expected token ':'")); ex = Assert.Throws(() => collection.CreateIndex("myIndex", "{\"fields\": [ { \"field\":$.myField, \"type\":\"TEXT\" ] }")); - Assert.AreEqual("The value provided is not a valid JSON document. Expected token ','", ex.Message); + Assert.That(ex.Message, Is.EqualTo("The value provided is not a valid JSON document. Expected token ','")); ex = Assert.Throws(() => collection.CreateIndex("myIndex", "{\"fields\": [ { \"field\":$.myField, type:\"TEXT\" } }")); - Assert.AreEqual("The value provided is not a valid JSON document. Expected token '\"'", ex.Message); + Assert.That(ex.Message, Is.EqualTo("The value provided is not a valid JSON document. Expected token '\"'")); } [Test] @@ -251,15 +251,15 @@ public void CreateIndexWithInvalidJsonDocumentStructure() var collection = CreateCollection("test"); Exception ex = Assert.Throws(() => collection.CreateIndex("myIndex", "{\"fields\": [ { \"field\":$.myField, \"type\":\"INT\", \"myCustomField\":\"myCustomValue\" } ] }")); - Assert.AreEqual("Field name 'myCustomField' is not allowed.", ex.Message); + Assert.That(ex.Message, Is.EqualTo("Field name 'myCustomField' is not allowed.")); ex = Assert.Throws(() => collection.CreateIndex("myIndex", "{\"fields\": [ { \"field\":$.myField, \"mytype\":\"INT\" } ] }")); - Assert.AreEqual("Field 'type' is mandatory.", ex.Message); + Assert.That(ex.Message, Is.EqualTo("Field 'type' is mandatory.")); ex = Assert.Throws(() => collection.CreateIndex("myIndex", "{\"fields\": [ { \"myfield\":$.myField, \"type\":\"INT\" } ] }")); - Assert.AreEqual("Field 'field' is mandatory.", ex.Message); + Assert.That(ex.Message, Is.EqualTo("Field 'field' is mandatory.")); ex = Assert.Throws(() => collection.CreateIndex("myIndex", "{\"fields\": [ { \"field\":$.name, \"type\":\"TEXT\" , \"myCustomField\":\"myCustomValue\"} ] }")); - Assert.AreEqual("Field name 'myCustomField' is not allowed.", ex.Message); + Assert.That(ex.Message, Is.EqualTo("Field name 'myCustomField' is not allowed.")); ex = Assert.Throws(() => collection.CreateIndex("myIndex", "")); - Assert.AreEqual("The value provided is not a valid JSON document. Index was outside the bounds of the array.", ex.Message); + Assert.That(ex.Message, Is.EqualTo("The value provided is not a valid JSON document. Index was outside the bounds of the array.")); } [Test] @@ -268,9 +268,9 @@ public void CreateIndexWithTypeNotIndexOrSpatial() var collection = CreateCollection("test"); Exception ex = Assert.Throws(() => collection.CreateIndex("myIndex", "{\"fields\": [ { \"field\":$.myField, \"type\":\"INT\" } ], \"type\":\"indexa\" }")); - Assert.AreEqual("Argument value 'indexa' for index type is invalid", ex.Message); + Assert.That(ex.Message, Is.EqualTo("Argument value 'indexa' for index type is invalid")); ex = Assert.Throws(() => collection.CreateIndex("myIndex", "{\"fields\": [ { \"field\":$.myField, \"type\":\"INT\" } ], \"type\":\"OTheR\" }")); - Assert.AreEqual("Argument value 'OTheR' for index type is invalid", ex.Message); + Assert.That(ex.Message, Is.EqualTo("Argument value 'OTheR' for index type is invalid")); } [Test] @@ -279,7 +279,7 @@ public void CreateSpatialIndexWithRequiredSetToFalse() var collection = CreateCollection("test"); Exception ex = Assert.Throws(() => collection.CreateIndex("myIndex", "{\"fields\": [ { \"field\":$.myField, \"type\":\"GEOJSON\", \"required\":false, \"options\":2, \"srid\":4326 } ], \"type\":\"SPATIAL\" }")); - Assert.AreEqual("GEOJSON index requires 'constraint.required: TRUE", ex.Message); + Assert.That(ex.Message, Is.EqualTo("GEOJSON index requires 'constraint.required: TRUE")); } [Test] @@ -289,13 +289,13 @@ public void CreateIndexWithInvalidType() // Missing key length for text type. Exception ex = Assert.Throws(() => collection.CreateIndex("myIndex", "{ \"fields\": [ { \"field\":\"$.myField\", \"type\":\"Text\" } ] }")); - StringAssert.EndsWith("used in key specification without a key length", ex.Message); + Assert.That(ex.Message, Does.EndWith("used in key specification without a key length")); // Invalid index types. ex = Assert.Throws(() => collection.CreateIndex("myIndex", "{ \"fields\": [ { \"field\":\"$.myField\", \"type\":\"Texta\" } ] }")); - StringAssert.EndsWith("Invalid or unsupported type specification 'Texta'", ex.Message); + Assert.That(ex.Message, Does.EndWith("Invalid or unsupported type specification 'Texta'")); ex = Assert.Throws(() => collection.CreateIndex("myIndex", "{ \"fields\": [ { \"field\":\"$.myField\", \"type\":\"INTO\" } ] }")); - StringAssert.EndsWith("Invalid or unsupported type specification 'INTO'", ex.Message); + Assert.That(ex.Message, Does.EndWith("Invalid or unsupported type specification 'INTO'")); try { collection.CreateIndex("myIndex", "{\"fields\": [ { \"field\":$.name, \"type\":\"Datetime\"} ] }"); @@ -317,10 +317,10 @@ public void CreateIndexWithInvalidGeojsonOptions() var collection = CreateCollection("test"); Exception ex = Assert.Throws(() => collection.CreateIndex("myIndex", "{ \"fields\": [ { \"field\":\"$.myField\", \"type\":\"INT\", \"options\":2, \"srid\":4326 } ] }")); - Assert.AreEqual("Unsupported argument specification for '$.myField'", ex.Message); + Assert.That(ex.Message, Is.EqualTo("Unsupported argument specification for '$.myField'")); ex = Assert.Throws(() => collection.CreateIndex("myIndex", "{\"fields\": [ { \"field\":$.myField, \"type\":\"GEOJSON\", \"options\":2, \"srid\":4326 } ], \"type\":\"SPATIAL\" }")); - Assert.AreEqual("GEOJSON index requires 'constraint.required: TRUE", ex.Message); + Assert.That(ex.Message, Is.EqualTo("GEOJSON index requires 'constraint.required: TRUE")); } [Test] @@ -341,9 +341,9 @@ public void ValidIndexNames() collection.DropIndex("-myIndex"); Exception ex = Assert.Throws(() => collection.CreateIndex(null, "{\"fields\": [ { \"field\":$.name, \"type\":\"TEXT(64)\" , \"required\":true} ] }")); - Assert.AreEqual("Invalid value for argument 'name'", ex.Message); + Assert.That(ex.Message, Is.EqualTo("Invalid value for argument 'name'")); ex = Assert.Throws(() => collection.CreateIndex("myIndex1243536464r4urgfu4rgh43urvbnu4rgh4u3rive39irgf9r4fri3jgnfi", "{\"fields\": [ { \"field\":$.name, \"type\":\"TEXT(64)\" , \"required\":true} ] }")); - Assert.AreEqual("Identifier name 'myIndex1243536464r4urgfu4rgh43urvbnu4rgh4u3rive39irgf9r4fri3jgnfi' is too long", ex.Message); + Assert.That(ex.Message, Is.EqualTo("Identifier name 'myIndex1243536464r4urgfu4rgh43urvbnu4rgh4u3rive39irgf9r4fri3jgnfi' is too long")); } [Test] @@ -395,15 +395,15 @@ public void AddIndexAndInsertRecords() { if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher."); Collection testColl = CreateCollection("test1"); - Assert.IsTrue(testColl.ExistsInDatabase()); + Assert.That(testColl.ExistsInDatabase()); testColl.CreateIndex("testIndex", "{\"fields\": [ { \"field\":$.myId, \"type\":\"INTEGER UNSIGNED\" , \"required\":true} ] }"); testColl.CreateIndex("testIndex1", "{\"fields\": [ { \"field\":$.myAge, \"type\":\"FLOAT UNSIGNED\" , \"required\":true} ] }"); var result = testColl.Add(new { myId = 1, myAge = 35.1, _id = 1 }).Add(new { myId = 2, myAge = 41.9, _id = 2 }).Execute(); - Assert.True(result.AffectedItemsCount > 0); + Assert.That(result.AffectedItemsCount > 0); Collection testCol2 = CreateCollection("test2"); testCol2.CreateIndex("testIndex2", "{\"fields\": [ { \"field\":$.myId, \"type\":\"INT\" , \"required\":true} ] }"); result = testCol2.Add(new { myId = 1 }).Execute(); - Assert.True(result.AffectedItemsCount > 0); + Assert.That(result.AffectedItemsCount > 0); } [Test, Description("Create valid index on a single key with all options")] @@ -416,7 +416,7 @@ public void InsertWithValidIndexAndNoIndex() Assert.Throws(() => ExecuteAddStatement(col.Add(new { age = 10 }))); col.DropIndex("myIndex"); result = col.Add(new { age = 10 }).Execute(); - Assert.AreEqual(1, result.AffectedItemsCount); + Assert.That(result.AffectedItemsCount, Is.EqualTo(1)); } [Test, Description("Create a valid index on a single key of all DATATYPES.Datatypes supported: INT [UNSIGNED] TINYINT [UNSIGNED] SMALLINT [UNSIGNED] MEDIUMINT [UNSIGNED] INTEGER [UNSIGNED] BIGINT [UNSIGNED] REAL [UNSIGNED] FLOAT [UNSIGNED] DOUBLE [UNSIGNED] DECIMAL [UNSIGNED] NUMERIC [UNSIGNED] DATE TIME TIMESTAMP DATETIME TEXT[(length)]")] @@ -482,7 +482,7 @@ public void IndexWithMismatchedDatatypes() Result result = col.Add(new { name = "Sakila", age = 15 }).Execute(); Thread.Sleep(2000); Exception ex = Assert.Throws(() => col.CreateIndex("myIndex", "{\"fields\": [ { \"field\":$.name, \"type\":\"DATETIME\"} ] }")); - StringAssert.Contains("Incorrect datetime value", ex.Message); + Assert.That(ex.Message, Does.Contain("Incorrect datetime value")); } [Test, Description("Create an index specifiying SPATIAL as the index type for a non spatial data type and vice versa")] @@ -583,7 +583,7 @@ public void CountRecordsInsertedWithValidIndex() result = col.Add(new { name = "Maria", age = 20 }).Execute(); result = col.Add(new { name = "Maria", age = 21 }).Execute(); var Removing = col.Remove("name='Maria'").Execute(); - Assert.AreEqual(2, (int)Removing.AffectedItemsCount, "Matches"); + Assert.That((int)Removing.AffectedItemsCount, Is.EqualTo(2), "Matches"); } [Test, Description("Create invalid index with non-existent key")] @@ -633,14 +633,14 @@ public void IndexWithArrayOptionSingleKeyAfterInsertData() collection.Add(doc11).Execute(); collection.CreateIndex("myIndex", "{\"fields\": [{\"field\": $.myField, \"type\":\"" + "Time" + "\", \"array\": true}]}"); var docResult = collection.Find("'23:59:59.15' in myField").Execute(); - Assert.AreEqual(2, docResult.FetchAll().Count, "Matching the document ID"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(2), "Matching the document ID"); docResult = collection.Find("'1' in $.myField").Execute(); - Assert.AreEqual(3, docResult.FetchAll().Count, "Matching the document ID"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(3), "Matching the document ID"); docResult = collection.Find("1 in $.myField").Execute(); - Assert.AreEqual(3, docResult.FetchAll().Count, "Matching the document ID"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(3), "Matching the document ID"); docResult = collection.Find(":myField IN $.myField").Bind("myField", "23:59:59.15").Execute(); docResult = collection.Find(":myField IN $._id").Bind("myField", true).Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID"); collection = CreateCollection("test"); collection.Add(doc).Execute(); @@ -839,13 +839,13 @@ public void IndexWithArrayOptionSingleKeyBeforeInsertData() doc = new[] { new { _id = 1, name = "Char", myField = new[] { "foo@mail.com" } } }; collection.CreateIndex("myIndex", "{\"fields\": [{\"field\": $.myField, \"type\":\"" + "CHAR(11)" + "\", \"array\": true}]}"); Exception ex = Assert.Throws(() => collection.Add(doc).Execute()); - Assert.AreEqual("Data too long for functional index 'myIndex'.", ex.Message); + Assert.That(ex.Message, Is.EqualTo("Data too long for functional index 'myIndex'.")); collection = CreateCollection("test"); var doc1 = new[] { new { _id = 1, name = "Char", myField = "foo@mail.com" } }; collection.CreateIndex("myIndex", "{\"fields\": [{\"field\": $.myField, \"type\":\"" + "CHAR(11)" + "\", \"array\": true}]}"); ex = Assert.Throws(() => collection.Add(doc1).Execute()); - Assert.AreEqual("Data too long for functional index 'myIndex'.", ex.Message); + Assert.That(ex.Message, Is.EqualTo("Data too long for functional index 'myIndex'.")); collection = CreateCollection("test"); doc = new[] { new { _id = 1, name = "Binary", myField = new[] { "foo@mail.com", "bar@mail.com", "qux@mail.com" } } }; @@ -997,34 +997,34 @@ public void IndexArrayCombinations() Assert.Throws(() => coll.CreateIndex("charArrayIndex1", "{\"fields\": [{\"field\": \"$.charField1\", \"array\": true}]}")); Exception e = Assert.Throws(() => coll.CreateIndex("intArrayIndex1", "{\"fields\": [{\"field\": \"$.intField1\", \"type\": \"SIGNED INTEGER\", \"array\": null}]}")); - Assert.AreEqual(expectedException, e.Message, "Matching the expected exception"); + Assert.That(e.Message, Is.EqualTo(expectedException), "Matching the expected exception"); e = Assert.Throws(() => coll.CreateIndex("intArrayIndex1", "{\"fields\": [{\"field\": \"$.intField1\", \"type\": \"SIGNED INTEGER\", \"array\": NULL}]}")); - Assert.AreEqual(expectedException, e.Message, "Matching the expected exception"); + Assert.That(e.Message, Is.EqualTo(expectedException), "Matching the expected exception"); e = Assert.Throws(() => coll.CreateIndex("uintArrayIndex1", "{\"fields\": [{\"field\": \"$.uintField\", \"type\": \"UNSIGNED INTEGER\", \"array\": null}]}")); - Assert.AreEqual(expectedException, e.Message, "Matching the expected exception"); + Assert.That(e.Message, Is.EqualTo(expectedException), "Matching the expected exception"); e = Assert.Throws(() => coll.CreateIndex("floatArrayIndex1", "{\"fields\": [{\"field\": \"$.floatField\", \"type\": \"DECIMAL(10,2)\", \"array\": null}]}")); - Assert.AreEqual(expectedException, e.Message, "Matching the expected exception"); + Assert.That(e.Message, Is.EqualTo(expectedException), "Matching the expected exception"); e = Assert.Throws(() => coll.CreateIndex("floatArrayIndex1", "{\"fields\": [{\"field\": \"$.floatField\", \"type\": \"DECIMAL(10,2)\", \"array\": NULL}]}")); - Assert.AreEqual(expectedException, e.Message, "Matching the expected exception"); + Assert.That(e.Message, Is.EqualTo(expectedException), "Matching the expected exception"); e = Assert.Throws(() => coll.CreateIndex("dateArrayIndex1", "{\"fields\": [{\"field\": \"$.dateField\", \"type\": \"DATE\", \"array\": null}]}")); - Assert.AreEqual(expectedException, e.Message, "Matching the expected exception"); + Assert.That(e.Message, Is.EqualTo(expectedException), "Matching the expected exception"); e = Assert.Throws(() => coll.CreateIndex("datetimeArrayIndex1", "{\"fields\": [{\"field\": \"$.datetimeField\", \"type\": \"DATETIME\", \"array\": null}]}")); - Assert.AreEqual(expectedException, e.Message, "Matching the expected exception"); + Assert.That(e.Message, Is.EqualTo(expectedException), "Matching the expected exception"); e = Assert.Throws(() => coll.CreateIndex("timeArrayIndex1", "{\"fields\": [{\"field\": \"$.timeField\", \"type\": \"TIME\", \"array\": null}]}")); - Assert.AreEqual(expectedException, e.Message, "Matching the expected exception"); + Assert.That(e.Message, Is.EqualTo(expectedException), "Matching the expected exception"); e = Assert.Throws(() => coll.CreateIndex("charArrayIndex1", "{\"fields\": [{\"field\": \"$.charField\", \"type\": \"CHAR(256)\", \"array\": null}]}")); - Assert.AreEqual(expectedException, e.Message, "Matching the expected exception"); + Assert.That(e.Message, Is.EqualTo(expectedException), "Matching the expected exception"); e = Assert.Throws(() => coll.CreateIndex("binaryArrayIndex1", "{\"fields\": [{\"field\": \"$.binaryField\", \"type\": \"BINARY(256)\", \"array\": null}]}")); - Assert.AreEqual(expectedException, e.Message, "Matching the expected exception"); + Assert.That(e.Message, Is.EqualTo(expectedException), "Matching the expected exception"); Assert.Throws(() => ExecuteAddStatement(coll.Add("{\"intField\" : [1,[2, 3],4], \"uintField\" : [51,[52, 53],54], \"dateField\" : [\"2019-1-1\", [\"2019-2-1\", \"2019-3-1\"], \"2019-4-1\"], " + "\"datetimeField\" : [\"9999-12-30 23:59:59\", [\"9999-12-31 23:59:59\"], \"9999-12-31 23:59:59\"], \"charField\" : [\"abcd1\", \"abcd1\", \"abcd2\", \"abcd4\"], " + @@ -1041,7 +1041,7 @@ public void IndexArrayCombinations() for (int i = 0; i < fields.Length; i++) { var res = coll.Add(fields[i]).Execute(); - Assert.AreEqual(1, res.AffectedItemsCount); + Assert.That(res.AffectedItemsCount, Is.EqualTo(1)); } fields = new string[] {"{\"intField\" : []}", "{\"uintField\" : []}", "{\"charField\" : []}", @@ -1049,7 +1049,7 @@ public void IndexArrayCombinations() for (int i = 0; i < fields.Length; i++) { var res = coll.Add(fields[i]).Execute(); - Assert.AreEqual(1, res.AffectedItemsCount); + Assert.That(res.AffectedItemsCount, Is.EqualTo(1)); } fields = new string[] { "[]", "[]", "[]", "[]", "[]", "[]", "[]", "[]" }; @@ -1153,7 +1153,7 @@ public void IndexArrayCombinations() DbDoc doc = docs.FetchOne(); var findStatement = coll.Find("57.6"); var res1 = findStatement.Execute().FetchAll(); - Assert.AreEqual(5, res1.Count, "Matching the find count"); + Assert.That(res1.Count, Is.EqualTo(5), "Matching the find count"); coll = CreateCollection("test"); @@ -1244,17 +1244,17 @@ public void IndexArrayBugWorkAround() coll.Add(doc22).Execute(); coll.CreateIndex("myIndex", "{\"fields\": [{\"field\": $.myField, \"type\":\"" + "Time" + "\", \"array\": true}]}"); var docResult = coll.Find("CAST(CAST('12:00:00' as TIME) as JSON) in $.myField").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-Time"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-Time"); docResult = coll.Find("CAST(CAST('9:00:00' as TIME) as JSON) in $.myField").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-Time"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-Time"); docResult = coll.Find("CAST(CAST(:dt as TIME) as JSON) in $.myField").Bind("dt", "9:00:00").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-Time-With Bind"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-Time-With Bind"); docResult = coll.Find("CAST(CAST(:dt as TIME) as JSON) in $.myField").Bind("dt", "12:00:00").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-Time-With Bind"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-Time-With Bind"); docResult = coll.Find(":dt IN $.myField").Bind("dt", "9:00:00").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-Time-With Bind-Bug"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-Time-With Bind-Bug"); docResult = coll.Find(":dt IN $.myField").Bind("dt", "01:01:01.001").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-Time-With Bind-Bug"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-Time-With Bind-Bug"); coll = CreateCollection("test"); doc = new[] { new { _id = 1, name = "Decimal", myField = "5" } }; @@ -1263,19 +1263,19 @@ public void IndexArrayBugWorkAround() coll.Add(doc22).Execute(); coll.CreateIndex("myIndex", "{\"fields\": [{\"field\": $.myField, \"type\":\"" + "Decimal" + "\", \"array\": true}]}"); docResult = coll.Find("CAST(CAST('3.0' as DECIMAL) as JSON) in $.myField").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-Decimal"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-Decimal"); docResult = coll.Find("CAST(CAST('5' as DECIMAL) as JSON) in $.myField").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-Decimal"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-Decimal"); docResult = coll.Find("CAST(CAST(:dt as DECIMAL) as JSON) in $.myField").Bind("dt", "5").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-Decimal-With Bind"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-Decimal-With Bind"); docResult = coll.Find("CAST(CAST(:dt as DECIMAL) as JSON) in $.myField").Bind("dt", "3.0").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-Decimal-With Bind"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-Decimal-With Bind"); docResult = coll.Find(":dt IN $.myField").Bind("dt", "5").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-Decimal-With Bind-Bug"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-Decimal-With Bind-Bug"); docResult = coll.Find(":dt IN $.myField").Bind("dt", 5).Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-Decimal-With Bind-Bug"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-Decimal-With Bind-Bug"); docResult = coll.Find(":dt IN $.myField").Bind("dt", 3.0).Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-Decimal-With Bind-Bug"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-Decimal-With Bind-Bug"); coll = CreateCollection("test"); doc = new[] { new { _id = 1, name = "Date", myField = "2019-01-04" } }; @@ -1284,19 +1284,19 @@ public void IndexArrayBugWorkAround() coll.Add(doc22).Execute(); coll.CreateIndex("myIndex", "{\"fields\": [{\"field\": $.myField, \"type\":\"" + "Date" + "\", \"array\": true}]}"); docResult = coll.Find("CAST(CAST('2019-01-04' as DATE) as JSON) in $.myField").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-Date"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-Date"); docResult = coll.Find("CAST(CAST('2019-01-01' as DATE) as JSON) in $.myField").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-Date"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-Date"); docResult = coll.Find("CAST(CAST(:dt as DATE) as JSON) in $.myField").Bind("dt", "2019-01-04").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-Date-With Bind"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-Date-With Bind"); docResult = coll.Find("CAST(CAST(:dt as DATE) as JSON) in $.myField").Bind("dt", "2019-01-01").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-Date-With Bind"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-Date-With Bind"); docResult = coll.Find(":dt IN $.myField").Bind("dt", 2019 - 01 - 04).Execute(); - Assert.AreEqual(0, docResult.FetchAll().Count, "Matching the document ID-Date-With Bind-Bug"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(0), "Matching the document ID-Date-With Bind-Bug"); docResult = coll.Find(":dt IN $.myField").Bind("dt", "2019-01-04").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-Date-With Bind-Bug"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-Date-With Bind-Bug"); docResult = coll.Find(":dt IN $.myField").Bind("dt", "2019-01-01").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-Date-With Bind-Bug"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-Date-With Bind-Bug"); coll = CreateCollection("test"); doc = new[] { new { _id = 1, name = "DateTime", myField = "9999-02-02 01:20:33" } }; @@ -1305,17 +1305,17 @@ public void IndexArrayBugWorkAround() coll.Add(doc22).Execute(); coll.CreateIndex("myIndex", "{\"fields\": [{\"field\": $.myField, \"type\":\"" + "DateTime" + "\", \"array\": true}]}"); docResult = coll.Find("CAST(CAST('1000-01-01 00:00:00' as DATETIME) as JSON) in $.myField").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-DateTime"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-DateTime"); docResult = coll.Find("CAST(CAST('9999-02-02 01:20:33' as DATETIME) as JSON) in $.myField").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-DateTime"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-DateTime"); docResult = coll.Find("CAST(CAST(:dt as DATETIME) as JSON) in $.myField").Bind("dt", "9999-02-02 01:20:33").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-Date-With Bind"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-Date-With Bind"); docResult = coll.Find("CAST(CAST(:dt as DATETIME) as JSON) in $.myField").Bind("dt", "9999-12-31 23:59:59").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-Date-With Bind"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-Date-With Bind"); docResult = coll.Find(":dt IN $.myField").Bind("dt", "9999-02-02 01:20:33").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-DateTime-With Bind-Bug"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-DateTime-With Bind-Bug"); docResult = coll.Find(":dt IN $.myField").Bind("dt", "1000-01-01 00:00:00").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-DateTime-With Bind-Bug"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-DateTime-With Bind-Bug"); coll = CreateCollection("test"); doc = new[] { new { _id = 1, name = "Signed", myField = "100" } }; @@ -1324,19 +1324,19 @@ public void IndexArrayBugWorkAround() coll.Add(doc22).Execute(); coll.CreateIndex("myIndex", "{\"fields\": [{\"field\": $.myField, \"type\":\"" + "Signed" + "\", \"array\": true}]}"); docResult = coll.Find("CAST(CAST('100' as SIGNED) as JSON) in $.myField").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-SIGNED"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-SIGNED"); docResult = coll.Find("CAST(CAST('3' as SIGNED) as JSON) in $.myField").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-SIGNED"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-SIGNED"); docResult = coll.Find("CAST(CAST(:dt as SIGNED) as JSON) in $.myField").Bind("dt", "100").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-SIGNED-With Bind"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-SIGNED-With Bind"); docResult = coll.Find("CAST(CAST(:dt as SIGNED) as JSON) in $.myField").Bind("dt", "19").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-SIGNED-With Bind"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-SIGNED-With Bind"); docResult = coll.Find(":dt IN $.myField").Bind("dt", 100).Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-Signed-With Bind"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-Signed-With Bind"); docResult = coll.Find(":dt IN $.myField").Bind("dt", "100").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-Signed-With Bind"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-Signed-With Bind"); docResult = coll.Find(":dt IN $.myField").Bind("dt", "3").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-Signed-With Bind"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-Signed-With Bind"); coll = CreateCollection("test"); doc = new[] { new { _id = 1, name = "SIGNED INTEGER", myField = "100" } }; @@ -1345,21 +1345,21 @@ public void IndexArrayBugWorkAround() coll.Add(doc22).Execute(); coll.CreateIndex("myIndex", "{\"fields\": [{\"field\": $.myField, \"type\":\"" + "SIGNED INTEGER" + "\", \"array\": true}]}"); docResult = coll.Find("CAST(CAST('100' as SIGNED INTEGER) as JSON) in $.myField").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-SIGNED INTEGER"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-SIGNED INTEGER"); docResult = coll.Find("CAST(CAST('3' as SIGNED INTEGER) as JSON) in $.myField").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-SIGNED INTEGER"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-SIGNED INTEGER"); docResult = coll.Find("CAST(CAST(:dt as SIGNED INTEGER) as JSON) in $.myField").Bind("dt", "100").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-SIGNED INTEGER-With Bind"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-SIGNED INTEGER-With Bind"); docResult = coll.Find("CAST(CAST(:dt as SIGNED INTEGER) as JSON) in $.myField").Bind("dt", "19").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-SIGNED INTEGER-With Bind"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-SIGNED INTEGER-With Bind"); docResult = coll.Find(":dt IN $.myField").Bind("dt", 100).Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-SIGNED INTEGER-With Bind-Bug"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-SIGNED INTEGER-With Bind-Bug"); docResult = coll.Find(":dt IN $.myField").Bind("dt", "100").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-SIGNED INTEGER-With Bind-Bug"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-SIGNED INTEGER-With Bind-Bug"); docResult = coll.Find(":dt IN $.myField").Bind("dt", 3).Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-SIGNED INTEGER-With Bind-Bug"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-SIGNED INTEGER-With Bind-Bug"); docResult = coll.Find(":dt IN $.myField").Bind("dt", "3").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-SIGNED INTEGER-With Bind-Bug"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-SIGNED INTEGER-With Bind-Bug"); coll = CreateCollection("test"); doc = new[] { new { _id = 1, name = "Unsigned", myField = "100" } }; @@ -1368,21 +1368,21 @@ public void IndexArrayBugWorkAround() coll.Add(doc22).Execute(); coll.CreateIndex("myIndex", "{\"fields\": [{\"field\": $.myField, \"type\":\"" + "Unsigned" + "\", \"array\": true}]}"); docResult = coll.Find("CAST(CAST('100' as UNSIGNED) as JSON) in $.myField").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-Unsigned"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-Unsigned"); docResult = coll.Find("CAST(CAST('3' as UNSIGNED) as JSON) in $.myField").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-Unsigned"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-Unsigned"); docResult = coll.Find("CAST(CAST(:dt as UNSIGNED) as JSON) in $.myField").Bind("dt", "100").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-Unsigned-With Bind"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-Unsigned-With Bind"); docResult = coll.Find("CAST(CAST(:dt as UNSIGNED) as JSON) in $.myField").Bind("dt", "19").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-Unsigned-With Bind"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-Unsigned-With Bind"); docResult = coll.Find(":dt IN $.myField").Bind("dt", 100).Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-Unsigned-With Bind-Bug"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-Unsigned-With Bind-Bug"); docResult = coll.Find(":dt IN $.myField").Bind("dt", "100").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-Unsigned-With Bind-Bug"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-Unsigned-With Bind-Bug"); docResult = coll.Find(":dt IN $.myField").Bind("dt", 3).Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-Unsigned-With Bind-Bug"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-Unsigned-With Bind-Bug"); docResult = coll.Find(":dt IN $.myField").Bind("dt", "3").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-Unsigned-With Bind-Bug"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-Unsigned-With Bind-Bug"); coll = CreateCollection("test"); doc = new[] { new { _id = 1, name = "Char", myField = "too@mail.com" } }; @@ -1391,9 +1391,9 @@ public void IndexArrayBugWorkAround() coll.Add(doc22).Execute(); coll.CreateIndex("myIndex", "{\"fields\": [{\"field\": $.myField, \"type\":\"" + "CHAR(128)" + "\", \"array\": true}]}"); docResult = coll.Find(":dt IN $.myField").Bind("dt", "too@mail.com").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-CHAR(128)-With Bind"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-CHAR(128)-With Bind"); docResult = coll.Find(":dt IN $.myField").Bind("dt", "foo@mail.com").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-CHAR(128)-With Bind"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-CHAR(128)-With Bind"); } /// @@ -1409,34 +1409,34 @@ public void IndexArrayWorkAroundOverlaps() coll.Add(doc).Execute(); coll.Add(doc22).Execute(); var docResult = coll.Find(":dt overlaps $.myField").Bind("dt", "9:00:00").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-Time-With Bind-Bug before index creation"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-Time-With Bind-Bug before index creation"); docResult = coll.Find(":dt not overlaps $.myField").Bind("dt", "9:00:00").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-Time-With Bind-Bug before index creation"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-Time-With Bind-Bug before index creation"); docResult = coll.Find("CAST(CAST('01:01:01.001' as TIME) as JSON) overlaps $.myField").Execute(); - Assert.AreEqual(0, docResult.FetchAll().Count, "Matching the document ID-Time before index creation"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(0), "Matching the document ID-Time before index creation"); docResult = coll.Find("CAST(CAST('01:01:01.001' as TIME) as JSON) not overlaps $.myField").Execute(); - Assert.AreEqual(2, docResult.FetchAll().Count, "Matching the document ID-Time before index creation"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(2), "Matching the document ID-Time before index creation"); coll.CreateIndex("myIndex", "{\"fields\": [{\"field\": $.myField, \"type\":\"" + "Time" + "\", \"array\": true}]}"); docResult = coll.Find("CAST(CAST('12:00:00' as TIME) as JSON) overlaps $.myField").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-Time"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-Time"); docResult = coll.Find("CAST(CAST('9:00:00' as TIME) as JSON) overlaps $.myField").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-Time"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-Time"); docResult = coll.Find("CAST(CAST(:dt as TIME) as JSON) overlaps $.myField").Bind("dt", "9:00:00").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-Time-With Bind"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-Time-With Bind"); docResult = coll.Find("CAST(CAST(:dt as TIME) as JSON) overlaps $.myField").Bind("dt", "12:00:00").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-Time-With Bind"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-Time-With Bind"); docResult = coll.Find(":dt overlaps $.myField").Bind("dt", "9:00:00").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-Time-With Bind-Bug"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-Time-With Bind-Bug"); docResult = coll.Find(":dt overlaps $.myField").Bind("dt", "01:01:01.001").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-Time-With Bind-Bug"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-Time-With Bind-Bug"); docResult = coll.Find(":dt not overlaps $.myField").Bind("dt", "01:01:01.001").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-Time-With Bind-Bug"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-Time-With Bind-Bug"); docResult = coll.Find(":dt not IN $.myField").Bind("dt", "01:01:01.001").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-Time-With Bind-Bug"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-Time-With Bind-Bug"); docResult = coll.Find("CAST(CAST(:dt as TIME) as JSON) not overlaps $.myField").Bind("dt", "12:00:00").Execute(); - Assert.AreEqual(2, docResult.FetchAll().Count, "Matching the document ID-Time-With Bind"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(2), "Matching the document ID-Time-With Bind"); coll = CreateCollection("test"); @@ -1445,35 +1445,35 @@ public void IndexArrayWorkAroundOverlaps() coll.Add(doc).Execute(); coll.Add(doc22).Execute(); docResult = coll.Find(":dt overlaps $.myField").Bind("dt", "5").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-DECIMAL-With Bind-Bug before index creation"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-DECIMAL-With Bind-Bug before index creation"); docResult = coll.Find(":dt not overlaps $.myField").Bind("dt", "5").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-DECIMAL-With Bind-Bug before index creation"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-DECIMAL-With Bind-Bug before index creation"); docResult = coll.Find("CAST(CAST('5' as DECIMAL) as JSON) overlaps $.myField").Execute(); - Assert.AreEqual(0, docResult.FetchAll().Count, "Matching the document ID-DECIMAL before index creation"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(0), "Matching the document ID-DECIMAL before index creation"); docResult = coll.Find("CAST(CAST('5' as DECIMAL) as JSON) not overlaps $.myField").Execute(); - Assert.AreEqual(2, docResult.FetchAll().Count, "Matching the document ID-DECIMAL before index creation"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(2), "Matching the document ID-DECIMAL before index creation"); coll.CreateIndex("myIndex", "{\"fields\": [{\"field\": $.myField, \"type\":\"" + "Decimal" + "\", \"array\": true}]}"); docResult = coll.Find("CAST(CAST('3.0' as DECIMAL) as JSON) overlaps $.myField").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-Decimal"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-Decimal"); docResult = coll.Find("CAST(CAST('5' as DECIMAL) as JSON) overlaps $.myField").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-Decimal"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-Decimal"); docResult = coll.Find("CAST(CAST(:dt as DECIMAL) as JSON) overlaps $.myField").Bind("dt", "5").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-Decimal-With Bind"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-Decimal-With Bind"); docResult = coll.Find("CAST(CAST(:dt as DECIMAL) as JSON) overlaps $.myField").Bind("dt", "3.0").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-Decimal-With Bind"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-Decimal-With Bind"); docResult = coll.Find(":dt overlaps $.myField").Bind("dt", "5").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-Decimal-With Bind-Bug"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-Decimal-With Bind-Bug"); docResult = coll.Find(":dt overlaps $.myField").Bind("dt", 5).Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-Decimal-With Bind-Bug"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-Decimal-With Bind-Bug"); docResult = coll.Find(":dt overlaps $.myField").Bind("dt", 3.0).Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-Decimal-With Bind-Bug"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-Decimal-With Bind-Bug"); docResult = coll.Find(":dt not overlaps $.myField").Bind("dt", "5").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-Decimal-With Bind-Bug"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-Decimal-With Bind-Bug"); docResult = coll.Find(":dt not overlaps $.myField").Bind("dt", 3.0).Execute(); - Assert.AreEqual(2, docResult.FetchAll().Count, "Matching the document ID-Decimal-With Bind-Bug"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(2), "Matching the document ID-Decimal-With Bind-Bug"); docResult = coll.Find("CAST(CAST(:dt as DECIMAL) as JSON) not overlaps $.myField").Bind("dt", "3.0").Execute(); - Assert.AreEqual(2, docResult.FetchAll().Count, "Matching the document ID-Decimal-With Bind"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(2), "Matching the document ID-Decimal-With Bind"); coll = CreateCollection("test"); @@ -1483,23 +1483,23 @@ public void IndexArrayWorkAroundOverlaps() coll.Add(doc22).Execute(); coll.CreateIndex("myIndex", "{\"fields\": [{\"field\": $.myField, \"type\":\"" + "Date" + "\", \"array\": true}]}"); docResult = coll.Find("CAST(CAST('2019-01-04' as DATE) as JSON) overlaps $.myField").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-Date"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-Date"); docResult = coll.Find("CAST(CAST('2019-01-01' as DATE) as JSON) overlaps $.myField").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-Date"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-Date"); docResult = coll.Find("CAST(CAST(:dt as DATE) as JSON) overlaps $.myField").Bind("dt", "2019-01-04").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-Date-With Bind"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-Date-With Bind"); docResult = coll.Find("CAST(CAST(:dt as DATE) as JSON) overlaps $.myField").Bind("dt", "2019-01-01").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-Date-With Bind"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-Date-With Bind"); docResult = coll.Find(":dt overlaps $.myField").Bind("dt", 2019 - 01 - 04).Execute(); - Assert.AreEqual(0, docResult.FetchAll().Count, "Matching the document ID-Date-With Bind-Bug"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(0), "Matching the document ID-Date-With Bind-Bug"); docResult = coll.Find(":dt overlaps $.myField").Bind("dt", "2019-01-04").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-Date-With Bind-Bug"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-Date-With Bind-Bug"); docResult = coll.Find(":dt overlaps $.myField").Bind("dt", "2019-01-01").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-Date-With Bind-Bug"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-Date-With Bind-Bug"); docResult = coll.Find(":dt not overlaps $.myField").Bind("dt", "2019-01-01").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-Date-With Bind-Bug"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-Date-With Bind-Bug"); docResult = coll.Find("CAST(CAST(:dt as DATE) as JSON) not overlaps $.myField").Bind("dt", "2019-01-04").Execute(); - Assert.AreEqual(2, docResult.FetchAll().Count, "Matching the document ID-Date-With Bind"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(2), "Matching the document ID-Date-With Bind"); coll = CreateCollection("test"); @@ -1509,21 +1509,21 @@ public void IndexArrayWorkAroundOverlaps() coll.Add(doc22).Execute(); coll.CreateIndex("myIndex", "{\"fields\": [{\"field\": $.myField, \"type\":\"" + "DateTime" + "\", \"array\": true}]}"); docResult = coll.Find("CAST(CAST('1000-01-01 00:00:00' as DATETIME) as JSON) overlaps $.myField").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-DateTime"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-DateTime"); docResult = coll.Find("CAST(CAST('9999-02-02 01:20:33' as DATETIME) as JSON) overlaps $.myField").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-DateTime"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-DateTime"); docResult = coll.Find("CAST(CAST(:dt as DATETIME) as JSON) overlaps $.myField").Bind("dt", "9999-02-02 01:20:33").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-Date-With Bind"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-Date-With Bind"); docResult = coll.Find("CAST(CAST(:dt as DATETIME) as JSON) overlaps $.myField").Bind("dt", "9999-12-31 23:59:59").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-Date-With Bind"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-Date-With Bind"); docResult = coll.Find(":dt overlaps $.myField").Bind("dt", "9999-02-02 01:20:33").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-DateTime-With Bind-Bug"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-DateTime-With Bind-Bug"); docResult = coll.Find(":dt overlaps $.myField").Bind("dt", "1000-01-01 00:00:00").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-DateTime-With Bind-Bug"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-DateTime-With Bind-Bug"); docResult = coll.Find(":dt not overlaps $.myField").Bind("dt", "1000-01-01 00:00:00").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-DateTime-With Bind-Bug"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-DateTime-With Bind-Bug"); docResult = coll.Find("CAST(CAST(:dt as DATETIME) as JSON) not overlaps $.myField").Bind("dt", "9999-12-31 23:59:59").Execute(); - Assert.AreEqual(2, docResult.FetchAll().Count, "Matching the document ID-Date-With Bind"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(2), "Matching the document ID-Date-With Bind"); coll = CreateCollection("test"); @@ -1533,23 +1533,23 @@ public void IndexArrayWorkAroundOverlaps() coll.Add(doc22).Execute(); coll.CreateIndex("myIndex", "{\"fields\": [{\"field\": $.myField, \"type\":\"" + "Signed" + "\", \"array\": true}]}"); docResult = coll.Find("CAST(CAST('100' as SIGNED) as JSON) overlaps $.myField").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-SIGNED"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-SIGNED"); docResult = coll.Find("CAST(CAST('3' as SIGNED) as JSON) overlaps $.myField").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-SIGNED"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-SIGNED"); docResult = coll.Find("CAST(CAST(:dt as SIGNED) as JSON) overlaps $.myField").Bind("dt", "100").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-SIGNED-With Bind"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-SIGNED-With Bind"); docResult = coll.Find("CAST(CAST(:dt as SIGNED) as JSON) overlaps $.myField").Bind("dt", "19").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-SIGNED-With Bind"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-SIGNED-With Bind"); docResult = coll.Find(":dt overlaps $.myField").Bind("dt", 100).Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-Signed-With Bind"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-Signed-With Bind"); docResult = coll.Find(":dt overlaps $.myField").Bind("dt", "100").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-Signed-With Bind"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-Signed-With Bind"); docResult = coll.Find(":dt overlaps $.myField").Bind("dt", "3").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-Signed-With Bind"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-Signed-With Bind"); docResult = coll.Find(":dt not overlaps $.myField").Bind("dt", "100").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-Signed-With Bind"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-Signed-With Bind"); docResult = coll.Find("CAST(CAST(:dt as SIGNED) as JSON) not overlaps $.myField").Bind("dt", "19").Execute(); - Assert.AreEqual(2, docResult.FetchAll().Count, "Matching the document ID-SIGNED-With Bind"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(2), "Matching the document ID-SIGNED-With Bind"); coll = CreateCollection("test"); doc = new[] { new { _id = 1, name = "SIGNED INTEGER", myField = "100" } }; @@ -1558,25 +1558,25 @@ public void IndexArrayWorkAroundOverlaps() coll.Add(doc22).Execute(); coll.CreateIndex("myIndex", "{\"fields\": [{\"field\": $.myField, \"type\":\"" + "SIGNED INTEGER" + "\", \"array\": true}]}"); docResult = coll.Find("CAST(CAST('100' as SIGNED INTEGER) as JSON) overlaps $.myField").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-SIGNED INTEGER"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-SIGNED INTEGER"); docResult = coll.Find("CAST(CAST('3' as SIGNED INTEGER) as JSON) overlaps $.myField").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-SIGNED INTEGER"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-SIGNED INTEGER"); docResult = coll.Find("CAST(CAST(:dt as SIGNED INTEGER) as JSON) overlaps $.myField").Bind("dt", "100").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-SIGNED INTEGER-With Bind"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-SIGNED INTEGER-With Bind"); docResult = coll.Find("CAST(CAST(:dt as SIGNED INTEGER) as JSON) overlaps $.myField").Bind("dt", "19").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-SIGNED INTEGER-With Bind"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-SIGNED INTEGER-With Bind"); docResult = coll.Find(":dt overlaps $.myField").Bind("dt", 100).Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-SIGNED INTEGER-With Bind-Bug"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-SIGNED INTEGER-With Bind-Bug"); docResult = coll.Find(":dt overlaps $.myField").Bind("dt", "100").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-SIGNED INTEGER-With Bind-Bug"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-SIGNED INTEGER-With Bind-Bug"); docResult = coll.Find(":dt overlaps $.myField").Bind("dt", 3).Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-SIGNED INTEGER-With Bind-Bug"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-SIGNED INTEGER-With Bind-Bug"); docResult = coll.Find(":dt overlaps $.myField").Bind("dt", "3").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-SIGNED INTEGER-With Bind-Bug"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-SIGNED INTEGER-With Bind-Bug"); docResult = coll.Find(":dt not overlaps $.myField").Bind("dt", "3").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-SIGNED INTEGER-With Bind-Bug"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-SIGNED INTEGER-With Bind-Bug"); docResult = coll.Find("CAST(CAST(:dt as SIGNED INTEGER) as JSON) overlaps $.myField").Bind("dt", "19").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-SIGNED INTEGER-With Bind"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-SIGNED INTEGER-With Bind"); coll = CreateCollection("test"); doc = new[] { new { _id = 1, name = "Unsigned", myField = "100" } }; @@ -1585,25 +1585,25 @@ public void IndexArrayWorkAroundOverlaps() coll.Add(doc22).Execute(); coll.CreateIndex("myIndex", "{\"fields\": [{\"field\": $.myField, \"type\":\"" + "Unsigned" + "\", \"array\": true}]}"); docResult = coll.Find("CAST(CAST('100' as UNSIGNED) as JSON) overlaps $.myField").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-Unsigned"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-Unsigned"); docResult = coll.Find("CAST(CAST('3' as UNSIGNED) as JSON) overlaps $.myField").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-Unsigned"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-Unsigned"); docResult = coll.Find("CAST(CAST(:dt as UNSIGNED) as JSON) overlaps $.myField").Bind("dt", "100").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-Unsigned-With Bind"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-Unsigned-With Bind"); docResult = coll.Find("CAST(CAST(:dt as UNSIGNED) as JSON) overlaps $.myField").Bind("dt", "19").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-Unsigned-With Bind"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-Unsigned-With Bind"); docResult = coll.Find(":dt overlaps $.myField").Bind("dt", 100).Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-Unsigned-With Bind-Bug"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-Unsigned-With Bind-Bug"); docResult = coll.Find(":dt overlaps $.myField").Bind("dt", "100").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-Unsigned-With Bind-Bug"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-Unsigned-With Bind-Bug"); docResult = coll.Find(":dt overlaps $.myField").Bind("dt", 3).Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-Unsigned-With Bind-Bug"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-Unsigned-With Bind-Bug"); docResult = coll.Find(":dt overlaps $.myField").Bind("dt", "3").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-Unsigned-With Bind-Bug"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-Unsigned-With Bind-Bug"); docResult = coll.Find(":dt not overlaps $.myField").Bind("dt", "3").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-Unsigned-With Bind-Bug"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-Unsigned-With Bind-Bug"); docResult = coll.Find("CAST(CAST(:dt as UNSIGNED) as JSON) overlaps $.myField").Bind("dt", "19").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-Unsigned-With Bind"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-Unsigned-With Bind"); coll = CreateCollection("test"); doc = new[] { new { _id = 1, name = "Char", myField = "too@mail.com" } }; @@ -1612,11 +1612,11 @@ public void IndexArrayWorkAroundOverlaps() coll.Add(doc22).Execute(); coll.CreateIndex("myIndex", "{\"fields\": [{\"field\": $.myField, \"type\":\"" + "CHAR(128)" + "\", \"array\": true}]}"); docResult = coll.Find(":dt overlaps $.myField").Bind("dt", "too@mail.com").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-CHAR(128)-With Bind"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-CHAR(128)-With Bind"); docResult = coll.Find(":dt overlaps $.myField").Bind("dt", "foo@mail.com").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-CHAR(128)-With Bind"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-CHAR(128)-With Bind"); docResult = coll.Find(":dt not overlaps $.myField").Bind("dt", "foo@mail.com").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-CHAR(128)-With Bind"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-CHAR(128)-With Bind"); } [Test, Description("Index using overlaps")] @@ -1635,34 +1635,34 @@ public void IndexArrayWithOverlaps() coll.Add(doc34).Execute(); var docResult = coll.Find(":dt overlaps $.myField1").Bind("dt", "9:00:00").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the document ID-Time-With Bind-Bug before index creation"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID-Time-With Bind-Bug before index creation"); coll.CreateIndex("myIndex1", "{\"fields\": [{\"field\": $.myField1, \"type\":\"" + "Time" + "\", \"array\": true}]}"); coll.CreateIndex("myIndex2", "{\"fields\": [{\"field\": $.myField2, \"type\":\"" + "Time" + "\", \"array\": true}]}"); coll.CreateIndex("myIndex3", "{\"fields\": [{\"field\": $.myField3, \"type\":\"" + "Time" + "\", \"array\": true}]}"); coll.CreateIndex("myIndex4", "{\"fields\": [{\"field\": $.myField1, \"type\":\"" + "Time" + "\", \"array\": true}]}"); coll.CreateIndex("myIndex5", "{\"fields\": [{\"field\": $.myField3, \"type\":\"" + "Time" + "\", \"array\": true}]}"); docResult = coll.Find("myIndex1 overlaps myIndex2").Execute(); - Assert.AreEqual(0, docResult.FetchAll().Count, "Matching the indexes using overlaps"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(0), "Matching the indexes using overlaps"); docResult = coll.Find("myIndex2 overlaps myIndex3").Execute(); - Assert.AreEqual(0, docResult.FetchAll().Count, "Matching the indexes using overlaps"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(0), "Matching the indexes using overlaps"); docResult = coll.Find("myIndex2 not overlaps myIndex3").Execute(); - Assert.AreEqual(0, docResult.FetchAll().Count, "Matching the indexes using not overlaps"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(0), "Matching the indexes using not overlaps"); docResult = coll.Find("myIndex1 overlaps myIndex4").Execute(); - Assert.AreEqual(0, docResult.FetchAll().Count, "Matching the indexes using overlaps"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(0), "Matching the indexes using overlaps"); docResult = coll.Find("'myIndex3' overlaps 'myIndex5'").Execute(); - Assert.AreEqual(0, docResult.FetchAll().Count, "Matching the indexes using overlaps"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(0), "Matching the indexes using overlaps"); docResult = coll.Find("$.myField3 overlaps $.myField2").Execute(); - Assert.AreEqual(0, docResult.FetchAll().Count, "Matching the indexes using overlaps"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(0), "Matching the indexes using overlaps"); docResult = coll.Find("$.myField1 overlaps $.myField3").Execute(); - Assert.AreEqual(0, docResult.FetchAll().Count, "Matching the indexes using overlaps"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(0), "Matching the indexes using overlaps"); docResult = coll.Find("$.myField2 overlaps $.myField4").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the indexes using overlaps"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the indexes using overlaps"); docResult = coll.Find("$.myField2 not overlaps $.myField4").Execute(); - Assert.AreEqual(0, docResult.FetchAll().Count, "Matching the indexes using not overlaps"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(0), "Matching the indexes using not overlaps"); docResult = coll.Find("$.myField5 overlaps $.myField3").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the indexes using overlaps"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the indexes using overlaps"); docResult = coll.Find("$.myField5 not overlaps $.myField3").Execute(); - Assert.AreEqual(1, docResult.FetchAll().Count, "Matching the indexes using not overlaps"); + Assert.That(docResult.FetchAll().Count, Is.EqualTo(1), "Matching the indexes using not overlaps"); } [Test, Description("multikey scenarios with observations")] @@ -1733,7 +1733,7 @@ public void CreateCollectionMultipleIndexDataType() { if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher."); Collection testColl = CreateCollection("test"); - Assert.AreEqual(true, testColl.ExistsInDatabase(), "ExistsInDatabase failed"); + Assert.That(testColl.ExistsInDatabase(), Is.EqualTo(true), "ExistsInDatabase failed"); testColl.CreateIndex("testIndex12", "{\"fields\": [ { \"field\":$.myId, \"type\":\"DOUBLE\" , \"required\":true} ] }"); testColl.CreateIndex("testIndex", "{\"fields\": [ { \"field\":$.myId, \"type\":\"DOUBLE UNSIGNED\" , \"required\":true} ] }"); @@ -1745,11 +1745,11 @@ public void CreateCollectionMultipleIndexDataType() testColl.Add(new { myId = 990.196078431, myAge = 10000000 }).Execute(); testColl.DropIndex("testIndex"); var result = testColl.Add(new { myId = 990.196078431, myAge = 10000000 }).Execute(); - Assert.AreEqual(1, result.AffectedItemsCount); + Assert.That(result.AffectedItemsCount, Is.EqualTo(1)); testColl.DropIndex("testIndex1"); result = testColl.Add(new { myId = 990.196078431, myAge = 10000000 }).Execute(); - Assert.AreEqual(1, result.AffectedItemsCount); + Assert.That(result.AffectedItemsCount, Is.EqualTo(1)); Assert.Throws(() => testColl.CreateIndex("testIndex2", "{\"fields\": [ { \"field\":$.myName, \"type\":\"TEXT\" , \"required\":true} ] }")); } @@ -1758,7 +1758,7 @@ public void CreateCollectionMultipleIndexStress() { if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher."); Collection testColl = CreateCollection("test"); - Assert.AreEqual(true, testColl.ExistsInDatabase(), "ExistsInDatabase failed"); + Assert.That(testColl.ExistsInDatabase(), Is.EqualTo(true), "ExistsInDatabase failed"); testColl.CreateIndex("testIndex", "{\"fields\": [ { \"field\":$.myId, \"type\":\"TINYINT UNSIGNED\" , \"required\":true} ] }"); testColl.CreateIndex("testIndex1", "{\"fields\": [ { \"field\":$.myAge, \"type\":\"SMALLINT UNSIGNED\" , \"required\":true} ] }"); @@ -1822,27 +1822,27 @@ private void ValidateIndex(string fieldName, string collectionName, string dataT continue; indexFound = true; - Assert.AreEqual(collectionName, reader["Table"]); - Assert.AreEqual(unique ? 0 : 1, Convert.ToInt16(reader["Non_unique"])); + Assert.That(reader["Table"], Is.EqualTo(collectionName)); + Assert.That(Convert.ToInt16(reader["Non_unique"]), Is.EqualTo(unique ? 0 : 1)); if (!array && !string.IsNullOrEmpty(reader["Column_name"].ToString())) { var columnNameTokens = reader["Column_name"].ToString().Split('_'); - Assert.AreEqual(dataType, isUnsigned ? string.Format("{0}_{1}", columnNameTokens[1], columnNameTokens[2]) : columnNameTokens[1]); + Assert.That(isUnsigned ? string.Format("{0}_{1}", columnNameTokens[1], columnNameTokens[2]) : columnNameTokens[1], Is.EqualTo(dataType)); } else if (array && !string.IsNullOrEmpty(reader["Expression"].ToString())) { string expression = reader["Expression"].ToString(); int pos = reader["Expression"].ToString().IndexOf(" as "); expression = expression.Substring(pos + 4); - StringAssert.Contains("array", expression); + Assert.That(expression, Does.Contain("array")); expression = expression.Substring(0, expression.IndexOf(" array")); Assert.That(dataType, Is.EqualTo(expression.Replace(" ", string.Empty)).IgnoreCase); } - Assert.AreEqual(required ? "" : "YES", reader["Null"]); + Assert.That(reader["Null"], Is.EqualTo(required ? "" : "YES")); if (length != null) - Assert.AreEqual(length, Convert.ToInt32(reader["Sub_part"])); + Assert.That(Convert.ToInt32(reader["Sub_part"]), Is.EqualTo(length)); break; } } diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/CollectionTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/CollectionTests.cs index 00d73b3d8..e2e1ac3a0 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/CollectionTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/CollectionTests.cs @@ -63,7 +63,7 @@ public void GetAllCollections() Collection book = CreateCollection("book"); List collections = book.Schema.GetCollections(); Assert.That(collections, Has.One.Items); - Assert.True(collections[0].Name == "book"); + Assert.That(collections[0].Name == "book"); book.Schema.DropCollection("book"); } @@ -73,15 +73,15 @@ public void CreateAndDropCollection() Session s = GetSession(); Schema test = s.GetSchema("test"); Collection testColl = test.CreateCollection("test"); - Assert.True(CollectionExistsInDatabase(testColl)); + Assert.That(CollectionExistsInDatabase(testColl)); // Drop existing collection. test.DropCollection("test"); - Assert.False(CollectionExistsInDatabase(testColl)); + Assert.That(CollectionExistsInDatabase(testColl), Is.False); // Drop non-existing collection. test.DropCollection("test"); - Assert.False(CollectionExistsInDatabase(testColl)); + Assert.That(CollectionExistsInDatabase(testColl), Is.False); //dropCollection when the object to drop contains invalid characters test.DropCollection("%^&!@~*(&*(*&:>(() => schema.GetCollection("nonExistentCollection", true)); - Assert.AreEqual("Collection 'nonExistentCollection' does not exist.", ex.Message); + Assert.That(ex.Message, Is.EqualTo("Collection 'nonExistentCollection' does not exist.")); } [Test] @@ -164,9 +164,9 @@ public void CountCollection() // Zero records var collection = schema.GetCollection("testCount"); - Assert.AreEqual(count, collection.Count()); + Assert.That(collection.Count(), Is.EqualTo(count)); var table = schema.GetTable("testCount"); - Assert.AreEqual(count, table.Count()); + Assert.That(table.Count(), Is.EqualTo(count)); // Insert some records var stm = collection.Add(@"{ ""_id"": 1, ""foo"": 1 }") @@ -174,22 +174,22 @@ public void CountCollection() .Add(@"{ ""_id"": 3, ""foo"": 3 }"); stm.Execute(); count = session.SQL("SELECT COUNT(*) FROM test.testCount").Execute().FetchOne()[0]; - Assert.AreEqual(count, collection.Count()); + Assert.That(collection.Count(), Is.EqualTo(count)); table.Insert("doc").Values(@"{ ""_id"": 4, ""foo"": 4 }").Execute(); count = session.SQL("SELECT COUNT(*) FROM test.testCount").Execute().FetchOne()[0]; - Assert.AreEqual(count, table.Count()); + Assert.That(table.Count(), Is.EqualTo(count)); collection.RemoveOne(2); count = session.SQL("SELECT COUNT(*) FROM test.testCount").Execute().FetchOne()[0]; - Assert.AreEqual(count, collection.Count()); - Assert.AreEqual(count, table.Count()); + Assert.That(collection.Count(), Is.EqualTo(count)); + Assert.That(table.Count(), Is.EqualTo(count)); // Collection/Table does not exist var ex = Assert.Throws(() => schema.GetCollection("testCount_").Count()); - Assert.AreEqual("Collection 'testCount_' does not exist in schema 'test'.", ex.Message); + Assert.That(ex.Message, Is.EqualTo("Collection 'testCount_' does not exist in schema 'test'.")); ex = Assert.Throws(() => schema.GetTable("testCount_").Count()); - Assert.AreEqual("Table 'testCount_' does not exist in schema 'test'.", ex.Message); + Assert.That(ex.Message, Is.EqualTo("Table 'testCount_' does not exist in schema 'test'.")); } [Test] @@ -235,7 +235,7 @@ public void CreateCollectionWithOptions() options.ReuseExisting = false; options.Validation = val; Collection testColl = test.CreateCollection("testWithSchemaValidation", options); - Assert.True(CollectionExistsInDatabase(testColl)); + Assert.That(CollectionExistsInDatabase(testColl)); //Bug #30830962 options = new CreateCollectionOptions(); @@ -245,7 +245,7 @@ public void CreateCollectionWithOptions() testbug1.Add(@"{ ""latitude"": 20, ""longitude"": 30 }").Execute(); testbug1.Add(@"{ ""sexo"": 1, ""edad"": 20 }").Execute(); int.TryParse(session.SQL("SELECT COUNT(*) FROM test.bug_0962").Execute().FetchOne()[0].ToString(), out int expected_count); - Assert.AreEqual(2, expected_count); //Collection is created as STRICT with empty json schema,both records were inserted + Assert.That(expected_count, Is.EqualTo(2)); //Collection is created as STRICT with empty json schema,both records were inserted options = new CreateCollectionOptions(); val = new Validation() { Schema = str }; @@ -253,90 +253,90 @@ public void CreateCollectionWithOptions() testbug1 = test.CreateCollection("bug_0962b", options);// adding an schema from testbug1.Add(@"{ ""latitude"": 20, ""longitude"": 30 }").Execute(); var invalidEx = Assert.Throws(() => testbug1.Add(@"{ ""sexo"": 1, ""edad"": 20 }").Execute()); - StringAssert.Contains("Document is not valid according to the schema assigned to collection", invalidEx.Message); + Assert.That(invalidEx.Message, Does.Contain("Document is not valid according to the schema assigned to collection")); // Create a Collection passing a reuse_existing parameter to server CreateCollectionOptions options_reuse = new CreateCollectionOptions(); options_reuse.ReuseExisting = false; options_reuse.Validation = val; Collection testCol2 = test.CreateCollection("testReuseExisting_1", options_reuse); - Assert.True(CollectionExistsInDatabase(testCol2)); + Assert.That(CollectionExistsInDatabase(testCol2)); //Insert Valid record with Level Strict var insert_statement = testColl.Add(@"{ ""latitude"": 20, ""longitude"": 30 }"); insert_statement.Execute(); var count = session.SQL("SELECT COUNT(*) FROM test.testWithSchemaValidation").Execute().FetchOne()[0]; - Assert.AreEqual(count, testColl.Count()); + Assert.That(testColl.Count(), Is.EqualTo(count)); //Insert invalid record with Level Strict insert_statement = testColl.Add(@"{ ""OtherField"": ""value"", ""Age"": 30 }"); var invalidInsertEx = Assert.Throws(() => insert_statement.Execute()); - StringAssert.Contains("Document is not valid according to the schema assigned to collection", invalidInsertEx.Message); + Assert.That(invalidInsertEx.Message, Does.Contain("Document is not valid according to the schema assigned to collection")); //Test: Old MySQL Server Version exceptions if (!(session.Version.isAtLeast(8, 0, 19))) { //FR6.2 var ex1 = Assert.Throws(() => test.CreateCollection("testInvalid", options)); - StringAssert.Contains("Invalid number of arguments, expected 2 but got 3, " + - "The server doesn't support the requested operation. Please update the MySQL Server and/or Client library", ex1.Message); + Assert.That(ex1.Message, Does.Contain("Invalid number of arguments, expected 2 but got 3, " + + "The server doesn't support the requested operation. Please update the MySQL Server and/or Client library")); //FR6.3 test.CreateCollection("testInvalid"); ModifyCollectionOptions modifyOptions = new ModifyCollectionOptions(); modifyOptions.Validation = val; var ex2 = Assert.Throws(() => test.ModifyCollection("testInvalid", modifyOptions)); - StringAssert.Contains("Invalid mysqlx command modify_collection_options, " + - "The server doesn't support the requested operation. Please update the MySQL Server and/or Client library", ex2.Message); + Assert.That(ex2.Message, Does.Contain("Invalid mysqlx command modify_collection_options, " + + "The server doesn't support the requested operation. Please update the MySQL Server and/or Client library")); } //Create collection with json schema and level OFF. Try to insert document matches this schema options = new CreateCollectionOptions(); options.Validation = new Validation() { Level = ValidationLevel.OFF, Schema = str }; Collection col_test = test.CreateCollection("Test_2b_1", options); - Assert.True(CollectionExistsInDatabase(col_test)); + Assert.That(CollectionExistsInDatabase(col_test)); insert_statement = col_test.Add(@"{ ""latitude"": 120, ""longitude"": 78 }"); insert_statement.Execute(); count = session.SQL("SELECT COUNT(*) FROM test.Test_2b_1").Execute().FetchOne()[0]; - Assert.AreEqual(count, col_test.Count()); + Assert.That(col_test.Count(), Is.EqualTo(count)); //Create collection with json schema and level OFF,ReuseExisting set to true, Try to insert options = new CreateCollectionOptions(); options.Validation = new Validation() { Level = ValidationLevel.OFF, Schema = str }; options.ReuseExisting = true; col_test = test.CreateCollection("Test_2b_2", options); - Assert.True(CollectionExistsInDatabase(col_test)); + Assert.That(CollectionExistsInDatabase(col_test)); insert_statement = col_test.Add(@"{ ""latitude"": 20, ""longitude"": 42 }"); insert_statement.Execute(); count = session.SQL("SELECT COUNT(*) FROM test.Test_2b_2").Execute().FetchOne()[0]; - Assert.AreEqual(count, col_test.Count()); + Assert.That(col_test.Count(), Is.EqualTo(count)); //Create collection with only schema option, Try to insert options = new CreateCollectionOptions(); options.Validation = new Validation() { Schema = str }; col_test = test.CreateCollection("Test_2b_3", options); - Assert.True(CollectionExistsInDatabase(col_test)); + Assert.That(CollectionExistsInDatabase(col_test)); insert_statement = col_test.Add(@"{ ""latitude"": 5, ""longitude"": 10 }"); insert_statement.Execute(); count = session.SQL("SELECT COUNT(*) FROM test.Test_2b_3").Execute().FetchOne()[0]; - Assert.AreEqual(count, col_test.Count()); + Assert.That(col_test.Count(), Is.EqualTo(count)); //Create collection with only schema option,ReuseExisting set to true, Try to insert options = new CreateCollectionOptions(); options.Validation = new Validation() { Schema = str }; options.ReuseExisting = true; col_test = test.CreateCollection("Test_2b_4", options); - Assert.True(CollectionExistsInDatabase(col_test)); + Assert.That(CollectionExistsInDatabase(col_test)); insert_statement = col_test.Add(@"{ ""latitude"": 25, ""longitude"": 52 }"); insert_statement.Execute(); count = session.SQL("SELECT COUNT(*) FROM test.Test_2b_4").Execute().FetchOne()[0]; - Assert.AreEqual(count, col_test.Count()); + Assert.That(col_test.Count(), Is.EqualTo(count)); //Create collection with only level option options = new CreateCollectionOptions(); options.Validation = new Validation() { Level = ValidationLevel.OFF }; col_test = test.CreateCollection("Test_2b_5", options); - Assert.True(CollectionExistsInDatabase(col_test)); + Assert.That(CollectionExistsInDatabase(col_test)); //ResuseExisting = false should throw exception for an existing collection CreateCollectionOptions testReuseOptions = new CreateCollectionOptions(); @@ -344,12 +344,12 @@ public void CreateCollectionWithOptions() testReuseOptions.Validation = new Validation() { Level = ValidationLevel.OFF }; test.CreateCollection("testReuse"); var exreuse = Assert.Throws(() => test.CreateCollection("testReuse", testReuseOptions)); - StringAssert.AreEqualIgnoringCase("Table 'testReuse' already exists", exreuse.Message); + Assert.That(exreuse.Message, Is.EqualTo("Table 'testReuse' already exists").IgnoreCase); //Test: Resuse Existing = True should return existing collection testReuseOptions.ReuseExisting = true; var existing = test.CreateCollection("testReuse", testReuseOptions); - Assert.True(CollectionExistsInDatabase(existing)); + Assert.That(CollectionExistsInDatabase(existing)); //Create collection and prepare test data with json schema and level STRICT CreateCollectionOptions prepareOptions = new CreateCollectionOptions(); @@ -358,13 +358,13 @@ public void CreateCollectionWithOptions() res_stm.Execute(); var num = session.SQL("SELECT COUNT(*) FROM test.TestCreateInsert").Execute().FetchOne()[0]; var collection_test = test.GetCollection("TestCreateInsert"); - Assert.AreEqual(num, collection_test.Count()); + Assert.That(collection_test.Count(), Is.EqualTo(num)); //Passing invalid Schema options = new CreateCollectionOptions(); options.Validation = new Validation() { Level = ValidationLevel.STRICT, Schema = "Not Valid JSON Schema" }; Exception ex_schema = Assert.Throws(() => test.CreateCollection("testInvalidSchema", options)); - StringAssert.Contains(@"The value provided is not a valid JSON document.", ex_schema.Message); + Assert.That(ex_schema.Message, Does.Contain(@"The value provided is not a valid JSON document.")); //Testing an schema with different data types str = "{\"id\": \"http://json-schema.org/geo\"," @@ -385,20 +385,20 @@ public void CreateCollectionWithOptions() options = new CreateCollectionOptions(); options.Validation = new Validation() { Level = ValidationLevel.STRICT, Schema = str }; Collection person_col = test.CreateCollection("testWithPersonSchema", options); - Assert.True(CollectionExistsInDatabase(person_col)); + Assert.That(CollectionExistsInDatabase(person_col)); person_col.Add(@"{ ""name"": ""John"", ""age"": 52 }").Execute(); var rows = session.SQL("SELECT COUNT(*) FROM test.testWithPersonSchema").Execute().FetchOne()[0]; - Assert.AreEqual(rows, person_col.Count()); + Assert.That(person_col.Count(), Is.EqualTo(rows)); // Create an existing collection with different schema options = new CreateCollectionOptions(); options.ReuseExisting = true; options.Validation = new Validation() { Level = ValidationLevel.STRICT, Schema = str }; Collection col_schema1 = test.CreateCollection("testSchema1", options); - Assert.True(CollectionExistsInDatabase(col_schema1)); + Assert.That(CollectionExistsInDatabase(col_schema1)); col_schema1.Add(@"{ ""name"": ""John"", ""age"": 52 }").Execute(); - Assert.AreEqual(1, col_schema1.Count()); + Assert.That(col_schema1.Count(), Is.EqualTo(1)); var sqlDefinition1 = session.SQL("SHOW CREATE TABLE test.testSchema1").Execute().FetchOne()[1]; @@ -420,31 +420,31 @@ public void CreateCollectionWithOptions() options.Validation = new Validation() { Level = ValidationLevel.STRICT, Schema = schema2 }; Collection col_schema2 = test.CreateCollection("testSchema1", options); var sqlDefinition2 = session.SQL("SHOW CREATE TABLE test.testSchema1").Execute().FetchOne()[1]; - Assert.AreEqual(sqlDefinition1, sqlDefinition2); + Assert.That(sqlDefinition2, Is.EqualTo(sqlDefinition1)); //Create a collection without sending reuseExisting parameter and insert record Collection original_col1 = test.CreateCollection("testOriginal1"); - Assert.True(CollectionExistsInDatabase(original_col1)); + Assert.That(CollectionExistsInDatabase(original_col1)); original_col1.Add(@"{ ""name"": ""John"", ""age"": 52 }").Execute(); rows = session.SQL("SELECT COUNT(*) FROM test.testOriginal1").Execute().FetchOne()[0]; - Assert.AreEqual(rows, original_col1.Count()); + Assert.That(original_col1.Count(), Is.EqualTo(rows)); //Create a new collection sending reuseExisting as true, insert record Collection original_col2 = test.CreateCollection("testOriginal2", true); - Assert.True(CollectionExistsInDatabase(original_col2)); + Assert.That(CollectionExistsInDatabase(original_col2)); original_col2.Add(@"{ ""name"": ""John"", ""age"": 52 }").Execute(); rows = session.SQL("SELECT COUNT(*) FROM test.testOriginal2").Execute().FetchOne()[0]; - Assert.AreEqual(rows, original_col2.Count()); + Assert.That(original_col2.Count(), Is.EqualTo(rows)); //Create an existing collection sending reuseExisting as true, insert record Collection original_col3 = test.CreateCollection("testOriginal2", true); - Assert.True(CollectionExistsInDatabase(original_col3)); + Assert.That(CollectionExistsInDatabase(original_col3)); original_col3.Add(@"{ ""name"": ""John2"", ""age"": 12 }").Execute(); - Assert.AreEqual(2, original_col3.Count()); + Assert.That(original_col3.Count(), Is.EqualTo(2)); //Create an existing collection sending reuseExisting as false,exception expected var ex_existing = Assert.Throws(() => test.CreateCollection("testOriginal2", false)); - StringAssert.AreEqualIgnoringCase(@"Table 'testOriginal2' already exists", ex_existing.Message); + Assert.That(ex_existing.Message, Is.EqualTo(@"Table 'testOriginal2' already exists").IgnoreCase); //Modify collection with only level option ModifyCollectionOptions Test_Options = new ModifyCollectionOptions(); @@ -456,20 +456,20 @@ public void CreateCollectionWithOptions() .Add(@"{ ""OtherField"": ""value"", ""Age"": 30 }"); insert_statement.Execute(); count = session.SQL("SELECT COUNT(*) FROM test.testWithSchemaValidation").Execute().FetchOne()[0]; - Assert.AreEqual(count, col_Test_2a_1.Count()); + Assert.That(col_Test_2a_1.Count(), Is.EqualTo(count)); //Modify collection with only schema option Test_Options.Validation = new Validation() { Schema = "{ }" }; test.ModifyCollection("testWithSchemaValidation", Test_Options); var sqlCreate = session.SQL("SHOW CREATE TABLE test.testWithSchemaValidation").Execute().FetchOne()[1]; - Assert.True(sqlCreate.ToString().Contains(@"'{\r\n}'") || sqlCreate.ToString().Contains("{}")); + Assert.That(sqlCreate.ToString().Contains(@"'{\r\n}'") || sqlCreate.ToString().Contains("{}")); //Passing null as parameter to ModifyCollection var emptyOptions = new ModifyCollectionOptions(); emptyOptions.Validation = new Validation() { }; test.CreateCollection("testnull"); exreuse = Assert.Throws(() => test.ModifyCollection("testnull", null)); - Assert.AreEqual(@"Arguments value used under ""validation"" must be an object with at least one field", exreuse.Message); + Assert.That(exreuse.Message, Is.EqualTo(@"Arguments value used under ""validation"" must be an object with at least one field")); test.DropCollection("testWithSchemaValidation"); test.DropCollection("bug_0962"); @@ -508,13 +508,13 @@ public void PreparedStatementWithNumericStrings() var stmt = coll.Find("_id=:v").Bind("v", "1"); var res = stmt.Execute(); var values = res.FetchOne(); - Assert.AreEqual(1, Convert.ToInt32(values.values["_id"])); - StringAssert.AreEqualIgnoringCase("foo", values.values["title"].ToString()); + Assert.That(Convert.ToInt32(values.values["_id"]), Is.EqualTo(1)); + Assert.That(values.values["title"].ToString(), Is.EqualTo("foo").IgnoreCase); res = coll.Find("_id=:v").Bind("v", "2").Execute(); values = res.FetchOne(); - Assert.AreEqual(2, Convert.ToInt32(values.values["_id"])); - StringAssert.AreEqualIgnoringCase("bar", values.values["title"].ToString()); + Assert.That(Convert.ToInt32(values.values["_id"]), Is.EqualTo(2)); + Assert.That(values.values["title"].ToString(), Is.EqualTo("bar").IgnoreCase); } [Test, Description("Verify Count method for Tables,Collections,Collection As Table,Views with different combinations")] @@ -526,14 +526,14 @@ public void AdditionalCountTests() var count = session.SQL("SELECT COUNT(*) FROM test.testCount").Execute().FetchOne()[0]; var collection = schema.GetCollection("testCount"); var collectionAsTable = schema.GetCollectionAsTable("testCount"); - Assert.AreEqual(count, collection.Count()); - Assert.AreEqual(count, collectionAsTable.Count()); + Assert.That(collection.Count(), Is.EqualTo(count)); + Assert.That(collectionAsTable.Count(), Is.EqualTo(count)); session.SQL($"USE {schemaName}").Execute(); session.SQL("create table test1(name VARCHAR(40), age INT)").Execute(); count = session.SQL($"SELECT COUNT(*) FROM {schemaName}.test1").Execute().FetchOne()[0]; Table table = session.GetSchema(schemaName).GetTable("test1"); - Assert.AreEqual(count, collectionAsTable.Count()); + Assert.That(collectionAsTable.Count(), Is.EqualTo(count)); var result = table.Insert("name", "age") .Values("MARK", "34") @@ -541,13 +541,13 @@ public void AdditionalCountTests() .Values("TEST", "50") .Execute(); - Assert.AreEqual((ulong)3, result.AffectedItemsCount); + Assert.That(result.AffectedItemsCount, Is.EqualTo((ulong)3)); var selectResult = table.Select().Execute(); while (selectResult.Next()) ; - Assert.AreEqual(3, selectResult.Rows.Count); - Assert.AreEqual("MARK", selectResult.Rows.ToArray()[0][0].ToString()); + Assert.That(selectResult.Rows.Count, Is.EqualTo(3)); + Assert.That(selectResult.Rows.ToArray()[0][0].ToString(), Is.EqualTo("MARK")); count = session.SQL($"SELECT COUNT(*) FROM {schemaName}.test1").Execute().FetchOne()[0]; - Assert.AreEqual(count, table.Count()); + Assert.That(table.Count(), Is.EqualTo(count)); // Insert some records var stm = collection.Add(@"{ ""_id"": 1, ""foo"": 1 }") @@ -555,19 +555,19 @@ public void AdditionalCountTests() .Add(@"{ ""_id"": 3, ""foo"": 3 }"); stm.Execute(); count = session.SQL("SELECT COUNT(*) FROM test.testCount").Execute().FetchOne()[0]; - Assert.AreEqual(count, collection.Count()); + Assert.That(collection.Count(), Is.EqualTo(count)); collectionAsTable = schema.GetCollectionAsTable("testCount"); - Assert.AreEqual(count, collectionAsTable.Count()); + Assert.That(collectionAsTable.Count(), Is.EqualTo(count)); table = schema.GetTable("testCount"); table.Insert("doc").Values(@"{ ""_id"": 4, ""foo"": 4 }").Execute(); count = session.SQL($"SELECT COUNT(*) FROM {schemaName}.testCount").Execute().FetchOne()[0]; - Assert.AreEqual(count, table.Count()); + Assert.That(table.Count(), Is.EqualTo(count)); collection.RemoveOne(2); count = session.SQL($"SELECT COUNT(*) FROM {schemaName}.testCount").Execute().FetchOne()[0]; - Assert.AreEqual(count, collection.Count()); - Assert.AreEqual(count, table.Count()); + Assert.That(collection.Count(), Is.EqualTo(count)); + Assert.That(table.Count(), Is.EqualTo(count)); // Collection/Table does not exist Assert.Throws(() => schema.GetCollection("testCount_").Count()); @@ -585,7 +585,7 @@ public void AdditionalCountTests() session.SQL("CREATE VIEW view2 AS select * from test2").Execute(); session.SQL("SELECT * FROM view2").Execute(); count = session.SQL("SELECT COUNT(*) FROM view1").Execute().FetchOne()[0]; - Assert.AreEqual(count, schema.GetTable("view1").Count()); + Assert.That(schema.GetTable("view1").Count(), Is.EqualTo(count)); schema.DropCollection("testCount"); session.SQL("DROP TABLE IF EXISTS test1").Execute(); session.SQL("DROP TABLE IF EXISTS test2").Execute(); @@ -607,16 +607,16 @@ public void ExceptionsInCount() var count = session.SQL("SELECT COUNT(*) FROM test.testCount").Execute().FetchOne()[0]; Schema schema = session.GetSchema(schemaName); var collection = schema.GetCollection("testCount"); - Assert.AreEqual(4, collection.Count()); + Assert.That(collection.Count(), Is.EqualTo(4)); coll.Add(new { _id = 5, title = "Book 5", pages = 60 }).Execute(); count = session.SQL("SELECT COUNT(*) FROM test.testCount").Execute().FetchOne()[0]; schema = session.GetSchema(schemaName); collection = schema.GetCollection("testCount"); - Assert.AreEqual(5, collection.Count()); + Assert.That(collection.Count(), Is.EqualTo(5)); Table table = session.GetSchema("test").GetTable("testCount"); - Assert.AreEqual(5, table.Count()); + Assert.That(table.Count(), Is.EqualTo(5)); // Expected exceptions. Assert.Throws(() => coll.RemoveOne(null)); @@ -625,47 +625,47 @@ public void ExceptionsInCount() Assert.Throws(() => coll.RemoveOne(" ")); // Remove sending numeric parameter. - Assert.AreEqual(1, coll.RemoveOne(1).AffectedItemsCount); - Assert.AreEqual(4, collection.Count()); - Assert.AreEqual(4, table.Count()); + Assert.That(coll.RemoveOne(1).AffectedItemsCount, Is.EqualTo(1)); + Assert.That(collection.Count(), Is.EqualTo(4)); + Assert.That(table.Count(), Is.EqualTo(4)); // Remove sending string parameter. - Assert.AreEqual(1, coll.RemoveOne("3").AffectedItemsCount); - Assert.AreEqual(3, collection.Count()); - Assert.AreEqual(3, table.Count()); + Assert.That(coll.RemoveOne("3").AffectedItemsCount, Is.EqualTo(1)); + Assert.That(collection.Count(), Is.EqualTo(3)); + Assert.That(table.Count(), Is.EqualTo(3)); // Remove an auto-generated id. var document = coll.Find("pages = 60").Execute().FetchOne(); - Assert.AreEqual(1, coll.RemoveOne(document.Id).AffectedItemsCount); - Assert.AreEqual(2, collection.Count()); - Assert.AreEqual(2, table.Count()); + Assert.That(coll.RemoveOne(document.Id).AffectedItemsCount, Is.EqualTo(1)); + Assert.That(collection.Count(), Is.EqualTo(2)); + Assert.That(table.Count(), Is.EqualTo(2)); // Remove a non-existing document. - Assert.AreEqual(0, coll.RemoveOne(5).AffectedItemsCount); - Assert.AreEqual(2, collection.Count()); - Assert.AreEqual(2, table.Count()); + Assert.That(coll.RemoveOne(5).AffectedItemsCount, Is.EqualTo(0)); + Assert.That(collection.Count(), Is.EqualTo(2)); + Assert.That(table.Count(), Is.EqualTo(2)); // Add or ReplaceOne - Assert.AreEqual(1, coll.AddOrReplaceOne(5, new { _id = 5, title = "Book 5", pages = 60 }). - AffectedItemsCount); - Assert.AreEqual(3, collection.Count()); - Assert.AreEqual(3, table.Count()); + Assert.That(coll.AddOrReplaceOne(5, new { _id = 5, title = "Book 5", pages = 60 }). + AffectedItemsCount, Is.EqualTo(1)); + Assert.That(collection.Count(), Is.EqualTo(3)); + Assert.That(table.Count(), Is.EqualTo(3)); // Add or ReplaceOne - Assert.AreEqual(2, coll.AddOrReplaceOne(2, new { title = "Book 50", pages = 60 }). - AffectedItemsCount); - Assert.AreEqual(3, collection.Count()); - Assert.AreEqual(3, table.Count()); + Assert.That(coll.AddOrReplaceOne(2, new { title = "Book 50", pages = 60 }). + AffectedItemsCount, Is.EqualTo(2)); + Assert.That(collection.Count(), Is.EqualTo(3)); + Assert.That(table.Count(), Is.EqualTo(3)); // Add or ReplaceOne - Assert.AreEqual(1, coll.AddOrReplaceOne(6, new { _id = 6, title = "Book 6", pages = 70 }). - AffectedItemsCount); - Assert.AreEqual(4, collection.Count()); - Assert.AreEqual(4, table.Count()); + Assert.That(coll.AddOrReplaceOne(6, new { _id = 6, title = "Book 6", pages = 70 }). + AffectedItemsCount, Is.EqualTo(1)); + Assert.That(collection.Count(), Is.EqualTo(4)); + Assert.That(table.Count(), Is.EqualTo(4)); var result = coll.Modify("_id = 5").Set("title", "Book 5").Execute(); - Assert.AreEqual(4, collection.Count()); - Assert.AreEqual(4, table.Count()); + Assert.That(collection.Count(), Is.EqualTo(4)); + Assert.That(table.Count(), Is.EqualTo(4)); coll = CreateCollection("testCount"); @@ -696,10 +696,10 @@ public void ExceptionsInCount() count = session.SQL("SELECT COUNT(*) FROM test.testCount").Execute().FetchOne()[0]; schema = session.GetSchema(schemaName); collection = schema.GetCollection("testCount"); - Assert.AreEqual(2000, collection.Count()); + Assert.That(collection.Count(), Is.EqualTo(2000)); r = coll.Remove("_id = :_id").Bind("_id", 1000).Execute(); - Assert.AreEqual(1999, collection.Count()); + Assert.That(collection.Count(), Is.EqualTo(1999)); } [Test, Description("Verify MultiThreading with count")] @@ -729,10 +729,10 @@ private Task SubProcessA() var res = coll.Add(jsonlist).Execute(); var count = sessionA.SQL("SELECT COUNT(*) FROM test.testCount").Execute().FetchOne()[0]; var collection = schema.GetCollection("testCount"); - Assert.AreEqual(1000, collection.Count()); + Assert.That(collection.Count(), Is.EqualTo(1000)); var r = coll.Remove("_id = :_id").Bind("_id", 1001).Execute(); - Assert.AreEqual(999, collection.Count()); + Assert.That(collection.Count(), Is.EqualTo(999)); } return Task.FromResult(0); } @@ -752,14 +752,14 @@ private Task SubProcessB() { if (collection.Count() > 5) { - Assert.AreEqual(999, collection.Count()); + Assert.That(collection.Count(), Is.EqualTo(999)); break; } } while (true); var r = coll.Remove("_id = :_id").Bind("_id", 1100).Execute(); - Assert.AreEqual(998, collection.Count()); + Assert.That(collection.Count(), Is.EqualTo(998)); } return Task.FromResult(0); } @@ -796,7 +796,7 @@ public void DropObjectsUnderStress() { session.CreateSchema("validSchema"); session.DropSchema("validSchema"); - Assert.False(session.GetSchema("validSchema").ExistsInDatabase()); + Assert.That(session.GetSchema("validSchema").ExistsInDatabase(), Is.False); } } @@ -856,7 +856,7 @@ public void SchemaValidation_S1() var collection = schema.CreateCollection("coll1", options); collection.Add(@"{ ""name"": ""John"", ""age"": 52 }").Execute(); var count = session.SQL("select count(*) from coll1").Execute().FetchOne()[0]; - Assert.AreEqual(count, collection.Count()); + Assert.That(collection.Count(), Is.EqualTo(count)); val.Level = ValidationLevel.OFF; val.Schema = doc1; @@ -865,7 +865,7 @@ public void SchemaValidation_S1() collection = schema.CreateCollection("coll1", options); collection.Add(@"{ ""name"": ""John"", ""age"": 52 }").Execute(); count = session.SQL("select count(*) from coll1").Execute().FetchOne()[0]; - Assert.AreEqual(count, collection.Count()); + Assert.That(collection.Count(), Is.EqualTo(count)); val.Level = ValidationLevel.OFF; val.Schema = doc1; @@ -874,21 +874,21 @@ public void SchemaValidation_S1() collection = schema.CreateCollection("coll2", options); collection.Add(@"{ ""name"": ""John"", ""age"": 52 }").Execute(); count = session.SQL("select count(*) from coll2").Execute().FetchOne()[0]; - Assert.AreEqual(count, collection.Count()); + Assert.That(collection.Count(), Is.EqualTo(count)); options.Validation = new Validation() { Level = ValidationLevel.OFF, Schema = doc1 }; options.ReuseExisting = false; collection = schema.CreateCollection("coll3", options); collection.Add(@"{ ""name"": ""Ram"" , ""age"": 22 }").Execute(); count = session.SQL("select count(*) from coll3").Execute().FetchOne()[0]; - Assert.AreEqual(count, collection.Count()); + Assert.That(collection.Count(), Is.EqualTo(count)); options.Validation = new Validation() { Level = ValidationLevel.OFF, Schema = doc1 }; options.ReuseExisting = true; collection = schema.CreateCollection("coll3", options); collection.Add(@"{ ""name"": ""John"", ""age"": 52 }").Execute(); count = session.SQL("select count(*) from coll3").Execute().FetchOne()[0]; - Assert.AreEqual(count, collection.Count()); + Assert.That(collection.Count(), Is.EqualTo(count)); var doc3 = "{\"id\": \"http://json-schema.org/geo\"," + "\"$schema\": \"http://json-schema.org/draft-06/schema#\"," @@ -911,7 +911,7 @@ public void SchemaValidation_S1() collection = schema.ModifyCollection("coll1", options1); collection.Add(@"{ ""latitude"": 20, ""longitude"": 30 }"); count = session.SQL("select count(*) from coll1").Execute().FetchOne()[0]; - Assert.AreEqual(count, collection.Count()); + Assert.That(collection.Count(), Is.EqualTo(count)); var doc4 = "{\"id\": \"http://json-schema.org/geo\"," + "\"$schema\": \"http://json-schema.org/draft-06/schema#\"," @@ -931,13 +931,13 @@ public void SchemaValidation_S1() collection = schema.ModifyCollection("coll3", options1); collection.Add(@"{ ""name"": ""Samar"" }"); count = session.SQL("select count(*) from coll3").Execute().FetchOne()[0]; - Assert.AreEqual(count, collection.Count()); + Assert.That(collection.Count(), Is.EqualTo(count)); options1.Validation = new Validation() { Level = ValidationLevel.OFF, Schema = doc1 }; collection = schema.ModifyCollection("coll2", options1); collection.Add(@"{ ""name"": ""Ram"" , ""age"": 22 }").Execute(); count = session.SQL("select count(*) from coll2").Execute().FetchOne()[0]; - Assert.AreEqual(count, collection.Count()); + Assert.That(collection.Count(), Is.EqualTo(count)); val.Level = ValidationLevel.STRICT; val.Schema = doc1; @@ -945,7 +945,7 @@ public void SchemaValidation_S1() collection = schema.ModifyCollection("coll2", options1); collection.Add(@"{ ""name"": ""Ram"" , ""age"": 22 }").Execute(); count = session.SQL("select count(*) from coll2").Execute().FetchOne()[0]; - Assert.AreEqual(count, collection.Count()); + Assert.That(collection.Count(), Is.EqualTo(count)); } [Test, Description("Checking the createcollection() and ModifyCollection() with either the level or the schema")] @@ -977,9 +977,9 @@ public void SchemaValidation_S2() collection.Add(@"{ ""name"": ""John"", ""age"": 52 }").Execute(); var result = session.SQL("select * from coll4").Execute().FetchAll(); foreach (Row res in result) - Assert.IsNotNull(res[0]); + Assert.That(res[0], Is.Not.Null); var count = session.SQL("select count(*) from coll4").Execute().FetchOne()[0]; - Assert.AreEqual(count, collection.Count()); + Assert.That(collection.Count(), Is.EqualTo(count)); options.Validation = new Validation { Schema = doc1 }; options.ReuseExisting = true; @@ -987,16 +987,16 @@ public void SchemaValidation_S2() collection.Add(@"{ ""name"": ""John"", ""age"": 52 }").Execute(); result = session.SQL("select * from coll4").Execute().FetchAll(); foreach (Row res in result) - Assert.IsNotNull(res[0]); + Assert.That(res[0], Is.Not.Null); count = session.SQL("select count(*) from coll4").Execute().FetchOne()[0]; - Assert.AreEqual(count, collection.Count()); + Assert.That(collection.Count(), Is.EqualTo(count)); options.Validation = new Validation { Schema = doc1 }; options.ReuseExisting = true; collection = schema.CreateCollection("colltesting", options); Assert.Throws(() => ExecuteAddStatement(collection.Add(@"{ ""name"": ""John"", ""age"": ""52"" }"))); count = session.SQL("select count(*) from colltesting").Execute().FetchOne()[0]; - Assert.AreEqual(count, collection.Count()); + Assert.That(collection.Count(), Is.EqualTo(count)); var doc2 = "{\"id\":\"http://json-schema.org/geo\"," + "\"$schema\": \"http://json-schema.org/draft-06/schema#\"," @@ -1033,9 +1033,9 @@ public void SchemaValidation_S2() collection.Add(@"{ ""name"": ""John"", ""age"": 52 }").Execute(); result = session.SQL("select * from coll5").Execute().FetchAll(); foreach (Row res in result) - Assert.IsNotNull(res[0]); + Assert.That(res[0], Is.Not.Null); count = session.SQL("select count(*) from coll5").Execute().FetchOne()[0]; - Assert.AreEqual(count, collection.Count()); + Assert.That(collection.Count(), Is.EqualTo(count)); options.Validation = new Validation { Level = ValidationLevel.STRICT }; options.ReuseExisting = false; @@ -1043,18 +1043,18 @@ public void SchemaValidation_S2() collection.Add(@"{ ""name"": ""John"", ""age"": 52 }").Execute(); result = session.SQL("select * from coll6").Execute().FetchAll(); foreach (Row res in result) - Assert.IsNotNull(res[0]); + Assert.That(res[0], Is.Not.Null); count = session.SQL("select count(*) from coll6").Execute().FetchOne()[0]; - Assert.AreEqual(count, collection.Count()); + Assert.That(collection.Count(), Is.EqualTo(count)); options1.Validation = new Validation() { Schema = doc1 }; collection = schema.ModifyCollection("coll6", options1); collection.Add(@"{ ""name"": ""Ram"" , ""age"": 22 }").Execute(); result = session.SQL("select * from coll6").Execute().FetchAll(); foreach (Row res in result) - Assert.IsNotNull(res[0]); + Assert.That(res[0], Is.Not.Null); count = session.SQL("select count(*) from coll6").Execute().FetchOne()[0]; - Assert.AreEqual(count, collection.Count()); + Assert.That(collection.Count(), Is.EqualTo(count)); options1.Validation = new Validation() { Schema = doc1 }; collection = schema.ModifyCollection("colltesting", options1); @@ -1068,18 +1068,18 @@ public void SchemaValidation_S2() collection.Add(@"{ ""name"": ""Ram"" , ""age"": 22 }").Execute(); result = session.SQL("select * from coll4").Execute().FetchAll(); foreach (Row res in result) - Assert.IsNotNull(res[0]); + Assert.That(res[0], Is.Not.Null); count = session.SQL("select count(*) from coll4").Execute().FetchOne()[0]; - Assert.AreEqual(count, collection.Count()); + Assert.That(collection.Count(), Is.EqualTo(count)); options1.Validation = new Validation() { Level = ValidationLevel.STRICT }; collection = schema.ModifyCollection("coll5", options1); collection.Add(@"{ ""name"": ""Ram"" , ""age"": 22 }").Execute(); result = session.SQL("select * from coll5").Execute().FetchAll(); foreach (Row res in result) - Assert.IsNotNull(res[0]); + Assert.That(res[0], Is.Not.Null); count = session.SQL("select count(*) from coll5").Execute().FetchOne()[0]; - Assert.AreEqual(count, collection.Count()); + Assert.That(collection.Count(), Is.EqualTo(count)); options1.Validation = new Validation() { }; Assert.Throws(() => schema.ModifyCollection("coll2", options1)); @@ -1126,7 +1126,7 @@ public void SchemaValidation_S2() foreach (Row res in result) Console.WriteLine("test with enum: " + res[0]); count = session.SQL("select count(*) from collEnum").Execute().FetchOne()[0]; - Assert.AreEqual(count, collection.Count()); + Assert.That(collection.Count(), Is.EqualTo(count)); } [Test, Description("Checking the error messages with different level")] @@ -1158,9 +1158,9 @@ public void SchemaValidation_S3() collection.Add(@"{ ""name"": ""John"", ""age"": 52 }").Execute(); var result = session.SQL("select * from coll7").Execute().FetchAll(); foreach (Row res in result) - Assert.IsNotNull(res[0]); + Assert.That(res[0], Is.Not.Null); var count = session.SQL("select count(*) from coll7").Execute().FetchOne()[0]; - Assert.AreEqual(count, collection.Count()); + Assert.That(collection.Count(), Is.EqualTo(count)); options.Validation = new Validation { Schema = doc1, Level = ValidationLevel.STRICT }; options.ReuseExisting = false; @@ -1168,9 +1168,9 @@ public void SchemaValidation_S3() collection.Add(@"{ ""name"": ""John"", ""age"": 52 }").Execute(); result = session.SQL("select * from collext").Execute().FetchAll(); foreach (Row res in result) - Assert.IsNotNull(res[0]); ; + Assert.That(res[0], Is.Not.Null); ; count = session.SQL("select count(*) from collext").Execute().FetchOne()[0]; - Assert.AreEqual(count, collection.Count()); + Assert.That(collection.Count(), Is.EqualTo(count)); var doc2 = "{\"id\":\"http://json-schema.org/geo\"," + "\"$schema\": \"http://json-schema.org/draft-06/schema#\"," @@ -1207,9 +1207,9 @@ public void SchemaValidation_S3() collection.Add(@"{ ""name"": ""John"", ""age"": 52 }").Execute(); result = session.SQL("select * from coll8").Execute().FetchAll(); foreach (Row res in result) - Assert.IsNotNull(res[0]); ; + Assert.That(res[0], Is.Not.Null); ; count = session.SQL("select count(*) from coll8").Execute().FetchOne()[0]; - Assert.AreEqual(count, collection.Count()); + Assert.That(collection.Count(), Is.EqualTo(count)); options.Validation = new Validation { Schema = doc1, Level = ValidationLevel.STRICT }; options.ReuseExisting = false; @@ -1226,18 +1226,18 @@ public void SchemaValidation_S3() collection.Add(@"{""longitude"":""99""}").Execute(); result = session.SQL("select * from coll10").Execute().FetchAll(); foreach (Row res in result) - Assert.IsNotNull(res[0]); ; + Assert.That(res[0], Is.Not.Null); ; count = session.SQL("select count(*) from coll10").Execute().FetchOne()[0]; - Assert.AreEqual(count, collection.Count()); + Assert.That(collection.Count(), Is.EqualTo(count)); options1.Validation = new Validation { Schema = doc1, Level = ValidationLevel.OFF }; collection = schema.ModifyCollection("coll10", options1); collection.Add(@"{ ""name"": 67 }").Execute(); result = session.SQL("select * from coll10").Execute().FetchAll(); foreach (Row res in result) - Assert.IsNotNull(res[0]); ; + Assert.That(res[0], Is.Not.Null); ; count = session.SQL("select count(*) from coll10").Execute().FetchOne()[0]; - Assert.AreEqual(count, collection.Count()); + Assert.That(collection.Count(), Is.EqualTo(count)); options.Validation = new Validation { Schema = doc1, Level = ValidationLevel.STRICT }; options.ReuseExisting = false; @@ -1245,9 +1245,9 @@ public void SchemaValidation_S3() collection.Add(@"{""_id"":1,""name"": ""John"", ""age"": 52}").Execute(); result = session.SQL("select * from coll").Execute().FetchAll(); foreach (Row res in result) - Assert.IsNotNull(res[0]); ; + Assert.That(res[0], Is.Not.Null); ; count = session.SQL("select count(*) from coll").Execute().FetchOne()[0]; - Assert.AreEqual(count, collection.Count()); + Assert.That(collection.Count(), Is.EqualTo(count)); } /// @@ -1304,9 +1304,9 @@ public void ModifyCollectionSchemaValidation() collection.Add(@"{""fruits"": [ ""apple"", ""orange"", ""pear"" ],""vegetables"": [{""veggieName"": ""potato"",""veggieLike"": true},{""veggieName"": ""broccoli"",""veggieLike"": false}]}").Execute(); var result = session.SQL("select * from coll20").Execute().FetchAll(); foreach (Row res in result) - Assert.IsNotNull(res[0]); + Assert.That(res[0], Is.Not.Null); var count = session.SQL("select count(*) from coll20").Execute().FetchOne()[0]; - Assert.AreEqual(count, collection.Count()); + Assert.That(collection.Count(), Is.EqualTo(count)); options.Validation = new Validation { Level = ValidationLevel.STRICT, Schema = doc1 }; options.ReuseExisting = false; @@ -1314,9 +1314,9 @@ public void ModifyCollectionSchemaValidation() collection.Add(@"{""fruits"": [ ""apple"", ""orange"", ""pear"" ],""vegetables"": [{""veggieName"": ""potato"",""veggieLike"": true},{""veggieName"": ""broccoli"",""veggieLike"": false}]}").Execute(); result = session.SQL("select * from coll21").Execute().FetchAll(); foreach (Row res in result) - Assert.IsNotNull(res[0]); + Assert.That(res[0], Is.Not.Null); count = session.SQL("select count(*) from coll21").Execute().FetchOne()[0]; - Assert.AreEqual(count, collection.Count()); + Assert.That(collection.Count(), Is.EqualTo(count)); val.Level = ValidationLevel.STRICT; val.Schema = doc1; @@ -1326,9 +1326,9 @@ public void ModifyCollectionSchemaValidation() collection.Add(@"{""fruits"": [ ""apple"", ""orange"", ""pear"" ],""vegetables"": [{""veggieName"": ""potato"",""veggieLike"": true},{""veggieName"": ""broccoli"",""veggieLike"": false}]}").Execute(); result = session.SQL("select * from coll20").Execute().FetchAll(); foreach (Row res in result) - Assert.IsNotNull(res[0]); + Assert.That(res[0], Is.Not.Null); count = session.SQL("select count(*) from coll20").Execute().FetchOne()[0]; - Assert.AreEqual(count, collection.Count()); + Assert.That(collection.Count(), Is.EqualTo(count)); options.Validation = new Validation { Level = ValidationLevel.STRICT, Schema = doc1 }; options.ReuseExisting = true; @@ -1336,9 +1336,9 @@ public void ModifyCollectionSchemaValidation() collection.Add(@"{""fruits"": [ ""apple"", ""orange"", ""pear"" ],""vegetables"": [{""veggieName"": ""potato"",""veggieLike"": true},{""veggieName"": ""broccoli"",""veggieLike"": false}]}").Execute(); result = session.SQL("select * from coll21").Execute().FetchAll(); foreach (Row res in result) - Assert.IsNotNull(res[0]); + Assert.That(res[0], Is.Not.Null); count = session.SQL("select count(*) from coll21").Execute().FetchOne()[0]; - Assert.AreEqual(count, collection.Count()); + Assert.That(collection.Count(), Is.EqualTo(count)); val.Level = ValidationLevel.OFF; val.Schema = doc1; @@ -1348,9 +1348,9 @@ public void ModifyCollectionSchemaValidation() collection.Add(@"{""fruits"": [ 78, ""orange"", ""pear"" ],""vegetables"": [{""veggieName"": ""potato"",""veggieLike"": true},{""veggieName"": ""broccoli"",""veggieLike"": false}]}").Execute(); result = session.SQL("select * from coll22").Execute().FetchAll(); foreach (Row res in result) - Assert.IsNotNull(res[0]); + Assert.That(res[0], Is.Not.Null); count = session.SQL("select count(*) from coll22").Execute().FetchOne()[0]; - Assert.AreEqual(count, collection.Count()); + Assert.That(collection.Count(), Is.EqualTo(count)); } [Test, Description("Verify ModifyCollection with level OFF and JSON schema")] @@ -1422,9 +1422,9 @@ public void SchemaValidationDeleteRecords() collection.Add(@"{ ""name"": 52 }").Execute(); var result = session.SQL("select * from collectiontest").Execute().FetchAll(); foreach (Row res1 in result) - Assert.IsNotNull(res1[0]); + Assert.That(res1[0], Is.Not.Null); var count = session.SQL("select count(*) from collectiontest").Execute().FetchOne()[0]; - Assert.AreEqual(count, collection.Count()); + Assert.That(collection.Count(), Is.EqualTo(count)); options1.Validation = new Validation { Level = ValidationLevel.STRICT, Schema = doc1 }; session.SQL("delete from collectiontest").Execute(); @@ -1435,16 +1435,16 @@ public void SchemaValidationDeleteRecords() foreach (Row res2 in result2) Console.WriteLine(res2[0]); count = session.SQL("select count(*) from collectiontest").Execute().FetchOne()[0]; - Assert.AreEqual(count, collection.Count()); + Assert.That(collection.Count(), Is.EqualTo(count)); options1.Validation = new Validation { Level = ValidationLevel.OFF, Schema = doc1 }; collection = schema.ModifyCollection("collectiontest", options1); collection.Add(@"{ ""name"": 78 }").Execute(); result = session.SQL("select * from collectiontest").Execute().FetchAll(); foreach (Row res2 in result) - Assert.IsNotNull(res2[0]); + Assert.That(res2[0], Is.Not.Null); count = session.SQL("select count(*) from collectiontest").Execute().FetchOne()[0]; - Assert.AreEqual(count, collection.Count()); + Assert.That(collection.Count(), Is.EqualTo(count)); options1.Validation = new Validation { Level = ValidationLevel.STRICT, Schema = doc3 }; session.SQL("delete from collectiontest").Execute(); @@ -1452,9 +1452,9 @@ public void SchemaValidationDeleteRecords() collection.Add(@"{""latitude"": 253, ""longitude"": 525}").Execute(); result = session.SQL("select * from collectiontest").Execute().FetchAll(); foreach (Row res2 in result) - Assert.IsNotNull(res2[0]); + Assert.That(res2[0], Is.Not.Null); count = session.SQL("select count(*) from collectiontest").Execute().FetchOne()[0]; - Assert.AreEqual(count, collection.Count()); + Assert.That(collection.Count(), Is.EqualTo(count)); options1.Validation = new Validation { Level = ValidationLevel.STRICT, Schema = doc4 }; session.SQL("delete from collectiontest").Execute(); @@ -1463,9 +1463,9 @@ public void SchemaValidationDeleteRecords() collection.Add(@"{ ""name"": ""Johnny"" }").Execute(); result = session.SQL("select * from collectiontest").Execute().FetchAll(); foreach (Row res2 in result) - Assert.IsNotNull(res2[0]); + Assert.That(res2[0], Is.Not.Null); count = session.SQL("select count(*) from collectiontest").Execute().FetchOne()[0]; - Assert.AreEqual(count, collection.Count()); + Assert.That(collection.Count(), Is.EqualTo(count)); } @@ -1499,10 +1499,10 @@ public void RemoveBindStress() } Result r = coll.Add(jsonlist).Add(jsonlist1).Execute(); - Assert.AreEqual(20, r.AffectedItemsCount, "Matching"); + Assert.That(r.AffectedItemsCount, Is.EqualTo(20), "Matching"); r = coll.Remove("_id = :_id").Bind("_id", 1000).Execute(); - Assert.AreEqual(1, r.AffectedItemsCount, "Matching"); + Assert.That(r.AffectedItemsCount, Is.EqualTo(1), "Matching"); } [Test, Description("Test MySQLX plugin Get Collection as Table")] @@ -1523,17 +1523,17 @@ public void GetCollectionAsTableStress() newDoc2 = null; } Result r = testCollection.Add(jsonlist).Execute(); - Assert.AreEqual(1000, r.AffectedItemsCount, "Matching"); + Assert.That(r.AffectedItemsCount, Is.EqualTo(1000), "Matching"); Table test = testSchema.GetCollectionAsTable("test"); - Assert.IsTrue(test.ExistsInDatabase()); + Assert.That(test.ExistsInDatabase()); var rows = test.Select("_id").Execute().FetchAll(); for (int j = 0; j < rows.Count; j++) { var doc = testCollection.Find("_id like :param").Bind("param", (j + 1000)).Execute(); var docs = doc.FetchAll().Count(); - Assert.AreEqual(1, docs, "Matches"); + Assert.That(docs, Is.EqualTo(1), "Matches"); } } @@ -1582,9 +1582,9 @@ public void GetDocumentIDSStress() newDoc2 = null; } Result r = coll.Add(jsonlist).Execute(); - Assert.AreEqual(1000, r.AffectedItemsCount, "Matching"); + Assert.That(r.AffectedItemsCount, Is.EqualTo(1000), "Matching"); var documentIds = r.GeneratedIds; - Assert.False(documentIds != null && documentIds.Count > 0); + Assert.That(documentIds != null && documentIds.Count > 0, Is.False); } [Test, Description("Session Performance Test")] @@ -1671,8 +1671,8 @@ public void SessionPerformanceTest() json = "CAST(" + query + " as SIGNED)= " + maxDepth; var docs = collection.Find(json).Fields("$._id as _id," + query + " as Arr").Execute(); var res = docs.FetchAll(); - Assert.AreEqual("1001", res[0]["_id"].ToString(), "Matching the id"); - Assert.AreEqual("1002", res[1]["_id"].ToString(), "Matching the id"); + Assert.That(res[0]["_id"].ToString(), Is.EqualTo("1001"), "Matching the id"); + Assert.That(res[1]["_id"].ToString(), Is.EqualTo("1002"), "Matching the id"); query = "$.DATAX" + (maxField - 1); for (i = 0; i < maxDepth; i++) @@ -1682,8 +1682,8 @@ public void SessionPerformanceTest() json = "CAST(" + query + " as SIGNED)"; docs = collection.Find(json + " =" + maxDepth).Fields("$._id as _id ").Execute(); res = docs.FetchAll(); - Assert.AreEqual("1001", res[0]["_id"].ToString(), "Matching the id"); - Assert.AreEqual("1003", res[1]["_id"].ToString(), "Matching the id"); + Assert.That(res[0]["_id"].ToString(), Is.EqualTo("1001"), "Matching the id"); + Assert.That(res[1]["_id"].ToString(), Is.EqualTo("1003"), "Matching the id"); } /// @@ -1698,42 +1698,42 @@ public void EmptyStringInModifyMethods() coll.Add(_doc).Execute(); var result = coll.Find("_id == 1").Execute().FetchOne(); - Assert.NotNull(result); - Assert.AreEqual(1, result.Id); + Assert.That(result, Is.Not.Null); + Assert.That(result.Id, Is.EqualTo(1)); // empty string var ex = Assert.Throws(() => coll.Modify("_id == 1").Set("", new { title = "bar" }).Execute()); - StringAssert.AreEqualIgnoringCase(ResourcesX.DocPathNullOrEmpty, ex.Message); + Assert.That(ex.Message, Is.EqualTo(ResourcesX.DocPathNullOrEmpty).IgnoreCase); ex = Assert.Throws(() => coll.Modify("_id == 1").Unset("").Execute()); - StringAssert.AreEqualIgnoringCase(ResourcesX.DocPathNullOrEmpty, ex.Message); + Assert.That(ex.Message, Is.EqualTo(ResourcesX.DocPathNullOrEmpty).IgnoreCase); ex = Assert.Throws(() => coll.Modify("_id == 1").Change("", new { title = "bar" }).Execute()); - StringAssert.AreEqualIgnoringCase(ResourcesX.DocPathNullOrEmpty, ex.Message); + Assert.That(ex.Message, Is.EqualTo(ResourcesX.DocPathNullOrEmpty).IgnoreCase); ex = Assert.Throws(() => coll.Modify("_id == 1").ArrayInsert("", new { title = "bar" }).Execute()); - StringAssert.AreEqualIgnoringCase(ResourcesX.DocPathNullOrEmpty, ex.Message); + Assert.That(ex.Message, Is.EqualTo(ResourcesX.DocPathNullOrEmpty).IgnoreCase); ex = Assert.Throws(() => coll.Modify("_id == 1").ArrayAppend("", new { title = "bar" }).Execute()); - StringAssert.AreEqualIgnoringCase(ResourcesX.DocPathNullOrEmpty, ex.Message); + Assert.That(ex.Message, Is.EqualTo(ResourcesX.DocPathNullOrEmpty).IgnoreCase); // white space ex = Assert.Throws(() => coll.Modify("_id == 1").Set(" ", new { title = "bar" }).Execute()); - StringAssert.AreEqualIgnoringCase(ResourcesX.DocPathNullOrEmpty, ex.Message); + Assert.That(ex.Message, Is.EqualTo(ResourcesX.DocPathNullOrEmpty).IgnoreCase); ex = Assert.Throws(() => coll.Modify("_id == 1").Unset(" ").Execute()); - StringAssert.AreEqualIgnoringCase(ResourcesX.DocPathNullOrEmpty, ex.Message); + Assert.That(ex.Message, Is.EqualTo(ResourcesX.DocPathNullOrEmpty).IgnoreCase); ex = Assert.Throws(() => coll.Modify("_id == 1").Change(" ", new { title = "bar" }).Execute()); - StringAssert.AreEqualIgnoringCase(ResourcesX.DocPathNullOrEmpty, ex.Message); + Assert.That(ex.Message, Is.EqualTo(ResourcesX.DocPathNullOrEmpty).IgnoreCase); ex = Assert.Throws(() => coll.Modify("_id == 1").ArrayInsert(" ", new { title = "bar" }).Execute()); - StringAssert.AreEqualIgnoringCase(ResourcesX.DocPathNullOrEmpty, ex.Message); + Assert.That(ex.Message, Is.EqualTo(ResourcesX.DocPathNullOrEmpty).IgnoreCase); ex = Assert.Throws(() => coll.Modify("_id == 1").ArrayAppend(" ", new { title = "bar" }).Execute()); - StringAssert.AreEqualIgnoringCase(ResourcesX.DocPathNullOrEmpty, ex.Message); + Assert.That(ex.Message, Is.EqualTo(ResourcesX.DocPathNullOrEmpty).IgnoreCase); // null ex = Assert.Throws(() => coll.Modify("_id == 1").Set(null, new { title = "bar" }).Execute()); - StringAssert.AreEqualIgnoringCase(ResourcesX.DocPathNullOrEmpty, ex.Message); + Assert.That(ex.Message, Is.EqualTo(ResourcesX.DocPathNullOrEmpty).IgnoreCase); ex = Assert.Throws(() => coll.Modify("_id == 1").Change(null, new { title = "bar" }).Execute()); - StringAssert.AreEqualIgnoringCase(ResourcesX.DocPathNullOrEmpty, ex.Message); + Assert.That(ex.Message, Is.EqualTo(ResourcesX.DocPathNullOrEmpty).IgnoreCase); ex = Assert.Throws(() => coll.Modify("_id == 1").ArrayInsert(null, new { title = "bar" }).Execute()); - StringAssert.AreEqualIgnoringCase(ResourcesX.DocPathNullOrEmpty, ex.Message); + Assert.That(ex.Message, Is.EqualTo(ResourcesX.DocPathNullOrEmpty).IgnoreCase); ex = Assert.Throws(() => coll.Modify("_id == 1").ArrayAppend(null, new { title = "bar" }).Execute()); - StringAssert.AreEqualIgnoringCase(ResourcesX.DocPathNullOrEmpty, ex.Message); + Assert.That(ex.Message, Is.EqualTo(ResourcesX.DocPathNullOrEmpty).IgnoreCase); var ex2 = Assert.Throws(() => coll.Modify("_id == 1").Unset(null).Execute()); } } diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/CompressionTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/CompressionTests.cs index 16a94cfd2..8629fd5ac 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/CompressionTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/CompressionTests.cs @@ -59,13 +59,13 @@ public void ConnectionOptionIsValidUsingBuilder() { var builder = new MySqlXConnectionStringBuilder(ConnectionString); builder.Compression = CompressionType.Preferred; - StringAssert.Contains("compression=Preferred", builder.ToString()); + Assert.That(builder.ToString(), Does.Contain("compression=Preferred")); builder.Compression = CompressionType.Required; - StringAssert.Contains("compression=Required", builder.ToString()); + Assert.That(builder.ToString(), Does.Contain("compression=Required")); builder.Compression = CompressionType.Disabled; - StringAssert.Contains("compression=Disabled", builder.ToString()); + Assert.That(builder.ToString(), Does.Contain("compression=Disabled")); } [Test] @@ -73,32 +73,32 @@ public void ConnectionOptionIsValidUsingConnectionUri() { using (var session = MySQLX.GetSession($"{ConnectionStringUri}?compression=PreFerRed")) { - Assert.AreEqual(CompressionType.Preferred, session.Settings.Compression); + Assert.That(session.Settings.Compression, Is.EqualTo(CompressionType.Preferred)); session.Close(); } using (var session = MySQLX.GetSession($"{ConnectionStringUri}?compression=required")) { - Assert.AreEqual(CompressionType.Required, session.Settings.Compression); + Assert.That(session.Settings.Compression, Is.EqualTo(CompressionType.Required)); session.Close(); } using (var session = MySQLX.GetSession($"{ConnectionStringUri}?compression=DISABLED")) { - Assert.AreEqual(CompressionType.Disabled, session.Settings.Compression); + Assert.That(session.Settings.Compression, Is.EqualTo(CompressionType.Disabled)); session.Close(); } // Test whitespace using (var session = MySQLX.GetSession($"{ConnectionStringUri}?compression= DISABLED")) { - Assert.AreEqual(CompressionType.Disabled, session.Settings.Compression); + Assert.That(session.Settings.Compression, Is.EqualTo(CompressionType.Disabled)); session.Close(); } using (var session = MySQLX.GetSession($"{ConnectionStringUri}?compression= DISABLED ")) { - Assert.AreEqual(CompressionType.Disabled, session.Settings.Compression); + Assert.That(session.Settings.Compression, Is.EqualTo(CompressionType.Disabled)); session.Close(); } } @@ -117,7 +117,7 @@ public void ConnectionOptionIsValidUsingAnonymousObject() using (var session = MySQLX.GetSession(connectionData)) { - Assert.AreEqual(CompressionType.Required, session.Settings.Compression); + Assert.That(session.Settings.Compression, Is.EqualTo(CompressionType.Required)); session.Close(); } } @@ -126,36 +126,36 @@ public void ConnectionOptionIsValidUsingAnonymousObject() public void ConnectionOptionIsValidUsingConnectionString() { var builder = new MySqlXConnectionStringBuilder($"server={Host};port={XPort};compression=PreFerRed"); - Assert.AreEqual(CompressionType.Preferred, builder.Compression); + Assert.That(builder.Compression, Is.EqualTo(CompressionType.Preferred)); builder = new MySqlXConnectionStringBuilder($"server={Host};port={XPort};compression=required"); - Assert.AreEqual(CompressionType.Required, builder.Compression); + Assert.That(builder.Compression, Is.EqualTo(CompressionType.Required)); builder = new MySqlXConnectionStringBuilder($"server={Host};port={XPort};compression=DISABLED"); - Assert.AreEqual(CompressionType.Disabled, builder.Compression); + Assert.That(builder.Compression, Is.EqualTo(CompressionType.Disabled)); // Test whitespace builder = new MySqlXConnectionStringBuilder($"server={Host};port={XPort};compression= required"); - Assert.AreEqual(CompressionType.Required, builder.Compression); + Assert.That(builder.Compression, Is.EqualTo(CompressionType.Required)); builder = new MySqlXConnectionStringBuilder($"server={Host};port={XPort};compression= required"); - Assert.AreEqual(CompressionType.Required, builder.Compression); + Assert.That(builder.Compression, Is.EqualTo(CompressionType.Required)); builder = new MySqlXConnectionStringBuilder($"server={Host};port={XPort};compression= required "); - Assert.AreEqual(CompressionType.Required, builder.Compression); + Assert.That(builder.Compression, Is.EqualTo(CompressionType.Required)); } [Test] public void PreferredIsTheDefaultValue() { var builder = new MySqlXConnectionStringBuilder(); - Assert.AreEqual(CompressionType.Preferred, builder.Compression); + Assert.That(builder.Compression, Is.EqualTo(CompressionType.Preferred)); // Empty value is ignored. var updatedConnectionStringUri = ConnectionStringUri + "?compression="; using (var session = MySQLX.GetSession(updatedConnectionStringUri)) { - Assert.AreEqual(CompressionType.Preferred, session.Settings.Compression); + Assert.That(session.Settings.Compression, Is.EqualTo(CompressionType.Preferred)); session.Close(); } @@ -163,7 +163,7 @@ public void PreferredIsTheDefaultValue() updatedConnectionStringUri = ConnectionStringUri + "?compression= "; using (var session = MySQLX.GetSession(updatedConnectionStringUri)) { - Assert.AreEqual(CompressionType.Preferred, session.Settings.Compression); + Assert.That(session.Settings.Compression, Is.EqualTo(CompressionType.Preferred)); session.Close(); } } @@ -175,10 +175,10 @@ public void SettingAnInvalidCompressionTypeRaisesException() foreach (var invalidValue in invalidValues) { var exception = Assert.Throws(() => new MySqlXConnectionStringBuilder($"server={Host};port={XPort};compression={invalidValue}")); - Assert.AreEqual($"The connection property 'compression' acceptable values are: 'preferred', 'required' or 'disabled'. The value '{invalidValue}' is not acceptable.", exception.Message); + Assert.That(exception.Message, Is.EqualTo($"The connection property 'compression' acceptable values are: 'preferred', 'required' or 'disabled'. The value '{invalidValue}' is not acceptable.")); exception = Assert.Throws(() => MySQLX.GetSession($"server={Host};port={XPort};user=root;compression={invalidValue}")); - Assert.AreEqual($"The connection property 'compression' acceptable values are: 'preferred', 'required' or 'disabled'. The value '{invalidValue}' is not acceptable.", exception.Message); + Assert.That(exception.Message, Is.EqualTo($"The connection property 'compression' acceptable values are: 'preferred', 'required' or 'disabled'. The value '{invalidValue}' is not acceptable.")); } } @@ -187,14 +187,14 @@ public void SessionRetainsTheSpecifiedCompressionType() { using (var session = MySQLX.GetSession(ConnectionStringUri)) { - Assert.AreEqual(CompressionType.Preferred, session.Settings.Compression); + Assert.That(session.Settings.Compression, Is.EqualTo(CompressionType.Preferred)); session.Close(); } var updatedConnectionStringUri = ConnectionStringUri + "?compression=Disabled"; using (var session = MySQLX.GetSession(updatedConnectionStringUri)) { - Assert.AreEqual(CompressionType.Disabled, session.Settings.Compression); + Assert.That(session.Settings.Compression, Is.EqualTo(CompressionType.Disabled)); session.Close(); } } @@ -206,12 +206,12 @@ public void ValidateRequiredCompressionType() if (!session.InternalSession.GetServerVersion().isAtLeast(8, 0, 19)) { var exception = Assert.Throws(() => MySQLX.GetSession($"{ConnectionStringUri}?compression=Required")); - Assert.AreEqual("Compression requested but the server does not support it.", exception.Message); + Assert.That(exception.Message, Is.EqualTo("Compression requested but the server does not support it.")); } else { using var session = MySQLX.GetSession($"{ConnectionStringUri}?compression=Required"); - Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); + Assert.That(session.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); } } @@ -224,26 +224,26 @@ public void NegotiationSucceedsWithExpectedCompressionAlgorithm() using (var session = MySQLX.GetSession(ConnectionStringUri)) { var compressionAlgorithm = session.XSession.GetCompressionAlgorithm(true); - Assert.AreEqual(CompressionAlgorithms.zstd_stream.ToString(), compressionAlgorithm); + Assert.That(compressionAlgorithm, Is.EqualTo(CompressionAlgorithms.zstd_stream.ToString())); compressionAlgorithm = session.XSession.GetCompressionAlgorithm(false); - Assert.AreEqual(CompressionAlgorithms.zstd_stream.ToString(), compressionAlgorithm); + Assert.That(compressionAlgorithm, Is.EqualTo(CompressionAlgorithms.zstd_stream.ToString())); } using (var session = MySQLX.GetSession(ConnectionStringUri + "?compression-algorithms=lz4_message")) { var compressionAlgorithm = session.XSession.GetCompressionAlgorithm(true); - Assert.AreEqual(CompressionAlgorithms.lz4_message.ToString(), compressionAlgorithm); + Assert.That(compressionAlgorithm, Is.EqualTo(CompressionAlgorithms.lz4_message.ToString())); compressionAlgorithm = session.XSession.GetCompressionAlgorithm(false); - Assert.AreEqual(CompressionAlgorithms.lz4_message.ToString(), compressionAlgorithm); + Assert.That(compressionAlgorithm, Is.EqualTo(CompressionAlgorithms.lz4_message.ToString())); } #if !NETFRAMEWORK using (var session = MySQLX.GetSession(ConnectionStringUri + "?compression-algorithms=deflate_stream")) { var compressionAlgorithm = session.XSession.GetCompressionAlgorithm(true); - Assert.AreEqual(CompressionAlgorithms.deflate_stream.ToString(), compressionAlgorithm); + Assert.That(compressionAlgorithm, Is.EqualTo(CompressionAlgorithms.deflate_stream.ToString())); compressionAlgorithm = session.XSession.GetCompressionAlgorithm(false); - Assert.AreEqual(CompressionAlgorithms.deflate_stream.ToString(), compressionAlgorithm); + Assert.That(compressionAlgorithm, Is.EqualTo(CompressionAlgorithms.deflate_stream.ToString())); } #endif } @@ -260,7 +260,7 @@ public void NegotiationWithSpecificCompressionAlgorithm() using (var session = MySQLX.GetSession(updatedConnectionStringUri)) { var compressionAlgorithm = session.XSession.GetCompressionAlgorithm(true); - Assert.AreEqual(CompressionAlgorithms.zstd_stream.ToString(), compressionAlgorithm); + Assert.That(compressionAlgorithm, Is.EqualTo(CompressionAlgorithms.zstd_stream.ToString())); } } @@ -268,18 +268,18 @@ public void NegotiationWithSpecificCompressionAlgorithm() using (var session = MySQLX.GetSession(updatedConnectionStringUri)) { var compressionAlgorithm = session.XSession.GetCompressionAlgorithm(true); - Assert.AreEqual(CompressionAlgorithms.lz4_message.ToString(), compressionAlgorithm); + Assert.That(compressionAlgorithm, Is.EqualTo(CompressionAlgorithms.lz4_message.ToString())); } ExecuteSqlAsRoot($"SET GLOBAL mysqlx_compression_algorithms ={DEFLATE_STREAM}"); #if NETFRAMEWORK var exception = Assert.Throws(() => MySQLX.GetSession(updatedConnectionStringUri)); - Assert.AreEqual("Compression requested but the compression algorithm negotiation failed.", exception.Message); + Assert.That(exception.Message, Is.EqualTo("Compression requested but the compression algorithm negotiation failed.")); #else using (var session = MySQLX.GetSession(updatedConnectionStringUri)) { var compressionAlgorithm = session.XSession.GetCompressionAlgorithm(true); - Assert.AreEqual(CompressionAlgorithms.deflate_stream.ToString(), compressionAlgorithm); + Assert.That(compressionAlgorithm, Is.EqualTo(CompressionAlgorithms.deflate_stream.ToString())); } #endif @@ -288,8 +288,8 @@ public void NegotiationWithSpecificCompressionAlgorithm() using (var session = MySQLX.GetSession(updatedConnectionStringUri)) { var compressionAlgorithm = session.XSession.GetCompressionAlgorithm(true); - Assert.True(Enum.TryParse(compressionAlgorithm, out var algorithm)); - Assert.True(algorithm == CompressionAlgorithms.lz4_message || algorithm == CompressionAlgorithms.zstd_stream); + Assert.That(Enum.TryParse(compressionAlgorithm, out var algorithm)); + Assert.That(algorithm == CompressionAlgorithms.lz4_message || algorithm == CompressionAlgorithms.zstd_stream); } } @@ -322,13 +322,13 @@ public void ConfigurableCompressionAlgorithms() using (var session = MySQLX.GetSession(ConnectionStringUri + "?compression-algorithms=lz4_message;")) { var compressionAlgorithm = session.XSession.GetCompressionAlgorithm(true); - Assert.AreEqual(CompressionAlgorithms.lz4_message.ToString(), compressionAlgorithm); + Assert.That(compressionAlgorithm, Is.EqualTo(CompressionAlgorithms.lz4_message.ToString())); } using (var session = MySQLX.GetSession(ConnectionString + ";compression-algorithms=lz4_message;")) { var compressionAlgorithm = session.XSession.GetCompressionAlgorithm(true); - Assert.AreEqual(CompressionAlgorithms.lz4_message.ToString(), compressionAlgorithm); + Assert.That(compressionAlgorithm, Is.EqualTo(CompressionAlgorithms.lz4_message.ToString())); } #if NETFRAMEWORK @@ -336,13 +336,13 @@ public void ConfigurableCompressionAlgorithms() using (var session = MySQLX.GetSession(new { server = Host, port = XPort, uid = "test", password = "test", compressionalgorithms = "deflate_stream" })) { var compressionAlgorithm = session.XSession.GetCompressionAlgorithm(true); - Assert.IsNull(compressionAlgorithm); + Assert.That(compressionAlgorithm, Is.Null); } #else using (var session = MySQLX.GetSession(new { server = Host, port = XPort, uid = "test", password = "test", compressionalgorithms = "deflate_stream" })) { var compressionAlgorithm = session.XSession.GetCompressionAlgorithm(true); - StringAssert.AreEqualIgnoringCase(CompressionAlgorithms.deflate_stream.ToString(), compressionAlgorithm); + Assert.That(compressionAlgorithm, Is.EqualTo(CompressionAlgorithms.deflate_stream.ToString()).IgnoreCase); } #endif @@ -350,7 +350,7 @@ public void ConfigurableCompressionAlgorithms() using (var session = MySQLX.GetSession(sb.GetConnectionString(true))) { var compressionAlgorithm = session.XSession.GetCompressionAlgorithm(true); - Assert.AreEqual(CompressionAlgorithms.lz4_message.ToString(), compressionAlgorithm); + Assert.That(compressionAlgorithm, Is.EqualTo(CompressionAlgorithms.lz4_message.ToString())); } // FR1_2 Create session with option compression-algorithms and set the option with no value either by not including the property in the connection string @@ -358,13 +358,13 @@ public void ConfigurableCompressionAlgorithms() using (var session = MySQLX.GetSession($"server={Host};port={XPort};uid=test;password=test;")) { var compressionAlgorithm = session.XSession.GetCompressionAlgorithm(true); - Assert.True(Enum.TryParse(compressionAlgorithm, out var result)); + Assert.That(Enum.TryParse(compressionAlgorithm, out var result)); } using (var session = MySQLX.GetSession(ConnectionString + ";compression-algorithms=")) { var compressionAlgorithm = session.XSession.GetCompressionAlgorithm(true); - Assert.True(Enum.TryParse(compressionAlgorithm, out var result)); + Assert.That(Enum.TryParse(compressionAlgorithm, out var result)); } // FR2_1,FR2_2 Create session with option compression-algorithms and set the value with multiple compression algorithms for @@ -372,13 +372,13 @@ public void ConfigurableCompressionAlgorithms() using (var session = MySQLX.GetSession(ConnectionStringUri + "?compression-algorithms=lz4_message,zstd_stream,deflate_stream;")) { var compressionAlgorithm = session.XSession.GetCompressionAlgorithm(true); - Assert.AreEqual(CompressionAlgorithms.lz4_message.ToString(), compressionAlgorithm); + Assert.That(compressionAlgorithm, Is.EqualTo(CompressionAlgorithms.lz4_message.ToString())); } using (var session = MySQLX.GetSession(ConnectionString + ";compression-algorithms=lz4_message,zstd_stream,deflate_stream;")) { var compressionAlgorithm = session.XSession.GetCompressionAlgorithm(true); - Assert.AreEqual(CompressionAlgorithms.lz4_message.ToString(), compressionAlgorithm); + Assert.That(compressionAlgorithm, Is.EqualTo(CompressionAlgorithms.lz4_message.ToString())); } #if NETFRAMEWORK @@ -386,13 +386,13 @@ public void ConfigurableCompressionAlgorithms() using (var session = MySQLX.GetSession(new { server = Host, port = XPort, uid = "test", password = "test", compressionalgorithms = "deflate_stream,lz4_message,zstd_stream" })) { var compressionAlgorithm = session.XSession.GetCompressionAlgorithm(true); - Assert.AreEqual(CompressionAlgorithms.lz4_message.ToString(), compressionAlgorithm); + Assert.That(compressionAlgorithm, Is.EqualTo(CompressionAlgorithms.lz4_message.ToString())); } #else using (var session = MySQLX.GetSession(new { server = Host, port = XPort, uid = "test", password = "test", compressionalgorithms = "deflate_stream,lz4_message,zstd_stream" })) { var compressionAlgorithm = session.XSession.GetCompressionAlgorithm(true); - StringAssert.AreEqualIgnoringCase(CompressionAlgorithms.deflate_stream.ToString(), compressionAlgorithm); + Assert.That(compressionAlgorithm, Is.EqualTo(CompressionAlgorithms.deflate_stream.ToString()).IgnoreCase); } #endif @@ -400,40 +400,40 @@ public void ConfigurableCompressionAlgorithms() using (var session = MySQLX.GetSession(sb.GetConnectionString(true))) { var compressionAlgorithm = session.XSession.GetCompressionAlgorithm(true); - Assert.AreEqual(CompressionAlgorithms.lz4_message.ToString(), compressionAlgorithm); + Assert.That(compressionAlgorithm, Is.EqualTo(CompressionAlgorithms.lz4_message.ToString())); } // FR3 Create session with option compression-algorithms and set the option with Algorithm aliases lz4, zstd, and deflate. using (var session = MySQLX.GetSession(ConnectionString + ";compression-algorithms=lz4,zstd,deflate;")) { var compressionAlgorithm = session.XSession.GetCompressionAlgorithm(true); - Assert.AreEqual(CompressionAlgorithms.lz4_message.ToString(), compressionAlgorithm); + Assert.That(compressionAlgorithm, Is.EqualTo(CompressionAlgorithms.lz4_message.ToString())); } using (var session = MySQLX.GetSession(ConnectionStringUri + "?compression-algorithms=lz4,deflate_stream")) { var compressionAlgorithm = session.XSession.GetCompressionAlgorithm(true); - Assert.AreEqual(CompressionAlgorithms.lz4_message.ToString(), compressionAlgorithm); + Assert.That(compressionAlgorithm, Is.EqualTo(CompressionAlgorithms.lz4_message.ToString())); } // FR4_1 Create session with option compression-algorithms.Set the option with unsupported and supported algorithms by client. using (var session = MySQLX.GetSession(ConnectionString + ";compression=required;compression-algorithms=NotSupported,lz4,SomethingElse;")) { var compressionAlgorithm = session.XSession.GetCompressionAlgorithm(true); - Assert.AreEqual(CompressionAlgorithms.lz4_message.ToString(), compressionAlgorithm); + Assert.That(compressionAlgorithm, Is.EqualTo(CompressionAlgorithms.lz4_message.ToString())); } using (var session = MySQLX.GetSession(ConnectionStringUri + "?compression-algorithms=lz4,NotSupported")) { var compressionAlgorithm = session.XSession.GetCompressionAlgorithm(true); - Assert.AreEqual(CompressionAlgorithms.lz4_message.ToString(), compressionAlgorithm); + Assert.That(compressionAlgorithm, Is.EqualTo(CompressionAlgorithms.lz4_message.ToString())); } sb = new MySqlXConnectionStringBuilder($"server={Host};port={XPort};uid=test;password=test;compression-algorithms=[NotValid,INVALID,NOTSUPPORTED,lz4]"); using (var session = MySQLX.GetSession(sb.GetConnectionString(true))) { var compressionAlgorithm = session.XSession.GetCompressionAlgorithm(true); - Assert.AreEqual(CompressionAlgorithms.lz4_message.ToString(), compressionAlgorithm); + Assert.That(compressionAlgorithm, Is.EqualTo(CompressionAlgorithms.lz4_message.ToString())); } // FR4_2 Create session and set invalid values to the compression-algorithm option to check if the connection is uncompressed when @@ -441,26 +441,26 @@ public void ConfigurableCompressionAlgorithms() using (var session = MySQLX.GetSession(ConnectionString + ";compression-algorithms=NotSupported,SomethingElse;")) { var compressionAlgorithm = session.XSession.GetCompressionAlgorithm(true); - Assert.IsNull(compressionAlgorithm); + Assert.That(compressionAlgorithm, Is.Null); } using (var session = MySQLX.GetSession(ConnectionString + ";compression=disabled;compression-algorithms=lz4,NotSupported,SomethingElse;")) { var compressionAlgorithm = session.XSession.GetCompressionAlgorithm(true); - Assert.IsNull(compressionAlgorithm); + Assert.That(compressionAlgorithm, Is.Null); } using (var session = MySQLX.GetSession(ConnectionString + ";compression=preferred;compression-algorithms=[NotSupported,SomethingElse];")) { var compressionAlgorithm = session.XSession.GetCompressionAlgorithm(true); - Assert.IsNull(compressionAlgorithm); + Assert.That(compressionAlgorithm, Is.Null); } // FR4_3 Create session and set invalid values to the compression-algorithm option. // The connection should terminate with an error when compression option is set to required. Exception ex = Assert.Throws(() => MySQLX.GetSession(ConnectionString + ";compression=required;compression-algorithms=NotSupported,SomethingElse;")); - Assert.AreEqual("Compression requested but the compression algorithm negotiation failed.", ex.Message); + Assert.That(ex.Message, Is.EqualTo("Compression requested but the compression algorithm negotiation failed.")); // FR4_4 Start server with specific compression algorithm and create session with option // compression-algorithms.Set the option with multiple compression algorithms. @@ -468,7 +468,7 @@ public void ConfigurableCompressionAlgorithms() using (var session = MySQLX.GetSession(ConnectionString + ";compression=preferred;compression-algorithms=[lz4_message,deflate,zstd];")) { var compressionAlgorithm = session.XSession.GetCompressionAlgorithm(true); - Assert.AreEqual(CompressionAlgorithms.lz4_message.ToString(), compressionAlgorithm); + Assert.That(compressionAlgorithm, Is.EqualTo(CompressionAlgorithms.lz4_message.ToString())); } // FR4_5 Start the server with a specific compression algorithm and use some other in the client and when compression option is either @@ -477,19 +477,19 @@ public void ConfigurableCompressionAlgorithms() using (var session = MySQLX.GetSession(ConnectionString + ";compression-algorithms=[lz4_message]")) { var compressionAlgorithm = session.XSession.GetCompressionAlgorithm(true); - Assert.IsNull(compressionAlgorithm); + Assert.That(compressionAlgorithm, Is.Null); } using (var session = MySQLX.GetSession(ConnectionString + ";compression=preferred;compression-algorithms=[lz4_message]")) { var compressionAlgorithm = session.XSession.GetCompressionAlgorithm(true); - Assert.IsNull(compressionAlgorithm); + Assert.That(compressionAlgorithm, Is.Null); } using (var session = MySQLX.GetSession(ConnectionString + ";compression=disabled;compression-algorithms=[lz4_message]")) { var compressionAlgorithm = session.XSession.GetCompressionAlgorithm(true); - Assert.IsNull(compressionAlgorithm); + Assert.That(compressionAlgorithm, Is.Null); } //FR4_6,FR_5 Start the server with a specific compression algorithm and use some other in the client and when compression option is set to required.Verify the behaviour @@ -497,7 +497,7 @@ public void ConfigurableCompressionAlgorithms() using (var session = MySQLX.GetSession(ConnectionString + ";compression=required;")) { var compressionAlgorithm = session.XSession.GetCompressionAlgorithm(true); - Assert.AreEqual(CompressionAlgorithms.lz4_message.ToString(), compressionAlgorithm); + Assert.That(compressionAlgorithm, Is.EqualTo(CompressionAlgorithms.lz4_message.ToString())); var ele = new List(); for (int i = 0; i < 1000; i++) { @@ -508,23 +508,23 @@ public void ConfigurableCompressionAlgorithms() var result = ExecuteAddStatement(coll.Add(ele.ToArray())); var result1 = session.SQL("select * from performance_schema.session_status where variable_name='Mysqlx_bytes_sent_uncompressed_frame' ").Execute().FetchOne()[1]; var result2 = session.SQL("select * from performance_schema.session_status where variable_name='Mysqlx_bytes_received_uncompressed_frame' ").Execute().FetchOne()[1]; - Assert.Greater(int.Parse(result1.ToString()), int.Parse(result2.ToString())); + Assert.That(int.Parse(result1.ToString()), Is.GreaterThan(int.Parse(result2.ToString()))); var result3 = session.SQL("select * from performance_schema.session_status where variable_name='Mysqlx_bytes_sent_compressed_payload' ").Execute().FetchOne()[1]; var result4 = session.SQL("select * from performance_schema.session_status where variable_name='Mysqlx_bytes_received_compressed_payload' ").Execute().FetchOne()[1]; - Assert.Greater(int.Parse(result3.ToString()), int.Parse(result4.ToString())); + Assert.That(int.Parse(result3.ToString()), Is.GreaterThan(int.Parse(result4.ToString()))); } using (var session = MySQLX.GetSession(ConnectionString + ";compression=required;compression-algorithms=[lz4_message]")) { var compressionAlgorithm = session.XSession.GetCompressionAlgorithm(true); - Assert.AreEqual(CompressionAlgorithms.lz4_message.ToString(), compressionAlgorithm); + Assert.That(compressionAlgorithm, Is.EqualTo(CompressionAlgorithms.lz4_message.ToString())); } // Server algorithm not contain user defined algorithm, with compression preferred using (var session = MySQLX.GetSession(ConnectionStringUri + "?compression-algorithms=[zstd];")) { var compressionAlgorithm = session.XSession.GetCompressionAlgorithm(true); - Assert.IsNull(compressionAlgorithm); + Assert.That(compressionAlgorithm, Is.Null); var ele = new List(); for (int i = 0; i < 1000; i++) @@ -536,14 +536,14 @@ public void ConfigurableCompressionAlgorithms() var result = ExecuteAddStatement(coll.Add(ele.ToArray())); var result1 = session.SQL("select * from performance_schema.session_status where variable_name='Mysqlx_bytes_sent_uncompressed_frame' ").Execute().FetchOne()[1]; var result2 = session.SQL("select * from performance_schema.session_status where variable_name='Mysqlx_bytes_received_uncompressed_frame' ").Execute().FetchOne()[1]; - Assert.AreEqual(result1, result2); + Assert.That(result2, Is.EqualTo(result1)); var result3 = session.SQL("select * from performance_schema.session_status where variable_name='Mysqlx_bytes_sent_compressed_payload' ").Execute().FetchOne()[1]; var result4 = session.SQL("select * from performance_schema.session_status where variable_name='Mysqlx_bytes_received_compressed_payload' ").Execute().FetchOne()[1]; - Assert.AreEqual(result3, result4); + Assert.That(result4, Is.EqualTo(result3)); } Exception ex_args = Assert.Throws(() => MySQLX.GetSession(ConnectionString + ";compression=required;compression_algorithms=[lz4_message]")); - StringAssert.Contains("Option not supported", ex_args.Message); + Assert.That(ex_args.Message, Does.Contain("Option not supported")); } [Test] @@ -558,24 +558,24 @@ public void CompressionAlgorithms_Bugs() using (var session = MySQLX.GetSession(ConnectionString + ";compression=required;compression-algorithms=[];")) { var compressionAlgorithm = session.XSession.GetCompressionAlgorithm(true); - Assert.IsNotNull(compressionAlgorithm); + Assert.That(compressionAlgorithm, Is.Not.Null); } // With only deflate available,Exeption expected ExecuteSqlAsRoot(@"SET GLOBAL mysqlx_compression_algorithms = ""DEFLATE_STREAM"" "); Exception ex_bug1 = Assert.Throws(() => MySQLX.GetSession(ConnectionString + ";compression=required;compression-algorithms=[];")); - StringAssert.Contains("Compression requested but the compression algorithm negotiation failed", ex_bug1.Message); + Assert.That(ex_bug1.Message, Does.Contain("Compression requested but the compression algorithm negotiation failed")); #else using (var session = MySQLX.GetSession(ConnectionString + ";compression=required;compression-algorithms=[];")) { var compressionAlgorithm = session.XSession.GetCompressionAlgorithm(true); - Assert.IsNotNull(compressionAlgorithm); + Assert.That(compressionAlgorithm, Is.Not.Null); } // With only deflate available,compression is expected ExecuteSqlAsRoot(@"SET GLOBAL mysqlx_compression_algorithms = ""DEFLATE_STREAM"" "); using (var session = MySQLX.GetSession(ConnectionString + ";compression=required;compression-algorithms=[];")) { var compressionAlgorithm = session.XSession.GetCompressionAlgorithm(true); - Assert.AreEqual(CompressionAlgorithms.deflate_stream.ToString(), compressionAlgorithm); + Assert.That(compressionAlgorithm, Is.EqualTo(CompressionAlgorithms.deflate_stream.ToString())); } #endif @@ -584,12 +584,12 @@ public void CompressionAlgorithms_Bugs() #if NETFRAMEWORK // Exeption expected due to compression=required Exception ex_bug2 = Assert.Throws(() => MySQLX.GetSession(ConnectionString + ";compression=required;compression-algorithms=deflate_stream;")); - StringAssert.Contains("is not supported in .NET Framework", ex_bug2.Message); + Assert.That(ex_bug2.Message, Does.Contain("is not supported in .NET Framework")); #else using (var session = MySQLX.GetSession(ConnectionString + ";compression=required;compression-algorithms=deflate_stream;")) { var compressionAlgorithm = session.XSession.GetCompressionAlgorithm(true); - Assert.AreEqual(CompressionAlgorithms.deflate_stream.ToString(), compressionAlgorithm); + Assert.That(compressionAlgorithm, Is.EqualTo(CompressionAlgorithms.deflate_stream.ToString())); } #endif } @@ -601,7 +601,7 @@ public void CompressionAlgorithms_Bugs() { // This line ensures that the list of supported compression algorithms is set to its default value. ExecuteSqlAsRoot(@"SET GLOBAL mysqlx_compression_algorithms = ""ZSTD_STREAM,LZ4_MESSAGE,DEFLATE_STREAM"" "); - Assert.True(success); + Assert.That(success); } } @@ -630,17 +630,17 @@ public void ConnectionStringCombinations() { //ConnectionString session1 = MySQLX.GetSession(ConnectionStringUserWithSSLPEM + " ;Auth=AUTO;sslmode=" + modes[j] + ";compression=" + compressValue[i]); - Assert.AreEqual(SessionState.Open, session1.XSession.SessionState); + Assert.That(session1.XSession.SessionState, Is.EqualTo(SessionState.Open)); session1.Close(); //Uri session2 = MySQLX.GetSession(connSSLURI + "&sslmode=" + modes[j] + "&compression=" + compressValue[i]); - Assert.AreEqual(SessionState.Open, session2.XSession.SessionState); + Assert.That(session2.XSession.SessionState, Is.EqualTo(SessionState.Open)); session2.Close(); //Anonymous Object session3 = MySQLX.GetSession(new { server = sb.Server, user = sb.UserID, port = sb.Port, password = sb.Password, SslCa = sslCa, SslCert = sslCert, SslKey = sslKey, Auth = MySqlAuthenticationMode.AUTO, sslmode = modes[j], compression = compressValue[i] }); - Assert.AreEqual(SessionState.Open, session3.XSession.SessionState); + Assert.That(session3.XSession.SessionState, Is.EqualTo(SessionState.Open)); session3.Close(); //MySqlXConnectionStringBuilder @@ -648,7 +648,7 @@ public void ConnectionStringCombinations() sb.Auth = MySqlAuthenticationMode.AUTO; sb.Compression = compressValue[i]; session4 = MySQLX.GetSession(sb.ConnectionString); - Assert.AreEqual(SessionState.Open, session4.XSession.SessionState); + Assert.That(session4.XSession.SessionState, Is.EqualTo(SessionState.Open)); session4.Close(); } } @@ -657,20 +657,20 @@ public void ConnectionStringCombinations() for (int i = 0; i < 3; i++) { session1 = MySQLX.GetSession(ConnectionString + ";auth=AUTO;compression=" + compressValue[i]); - Assert.AreEqual(SessionState.Open, session1.XSession.SessionState); + Assert.That(session1.XSession.SessionState, Is.EqualTo(SessionState.Open)); session1.Close(); session2 = MySQLX.GetSession(ConnectionStringUri + "?compression=" + compressValue[i]); - Assert.AreEqual(SessionState.Open, session2.XSession.SessionState); + Assert.That(session2.XSession.SessionState, Is.EqualTo(SessionState.Open)); session2.Close(); session3 = MySQLX.GetSession(new { server = sb.Server, user = sb.UserID, port = sb.Port, password = sb.Password, compression = compressValue[i] }); - Assert.AreEqual(SessionState.Open, session3.XSession.SessionState); + Assert.That(session3.XSession.SessionState, Is.EqualTo(SessionState.Open)); session3.Close(); sb.Compression = compressValue[i]; session4 = MySQLX.GetSession(sb.ConnectionString); - Assert.AreEqual(SessionState.Open, session4.XSession.SessionState); + Assert.That(session4.XSession.SessionState, Is.EqualTo(SessionState.Open)); session4.Close(); } } @@ -685,17 +685,17 @@ public void CompressionWithPolling() client = MySQLX.GetClient(ConnectionString + ";compression=" + compressValue[i], new { pooling = new { maxSize = 2, queueTimeout = 2000 } }); session1 = client.GetSession(); - Assert.AreEqual(SessionState.Open, session1.XSession.SessionState); + Assert.That(session1.XSession.SessionState, Is.EqualTo(SessionState.Open)); session1.Close(); session2 = client.GetSession(); - Assert.AreEqual(SessionState.Open, session2.XSession.SessionState); + Assert.That(session2.XSession.SessionState, Is.EqualTo(SessionState.Open)); session2.Close(); session1 = client.GetSession(); - Assert.AreEqual(SessionState.Open, session1.XSession.SessionState); + Assert.That(session1.XSession.SessionState, Is.EqualTo(SessionState.Open)); session2 = client.GetSession(); - Assert.AreEqual(SessionState.Open, session2.XSession.SessionState); + Assert.That(session2.XSession.SessionState, Is.EqualTo(SessionState.Open)); Assert.Throws(() => client.GetSession()); session1.Close(); @@ -731,17 +731,17 @@ public void VerifyDataSentCompression() schema.GetCollection("compressed"); var reader = session2.SQL("Select count(*) from compressed").Execute().FetchOne()[0]; var reader2 = session2.SQL("Select * from compressed").Execute().FetchAll(); - Assert.AreEqual("1", reader.ToString()); + Assert.That(reader.ToString(), Is.EqualTo("1")); // Results of compression when its value for session1 is: compressValue1[i] and for session2 is: compressValue2[i] var result1 = session1.SQL("select * from performance_schema.session_status where variable_name='Mysqlx_bytes_sent_uncompressed_frame' ").Execute().FetchOne()[1]; - Assert.IsNotNull(result1); + Assert.That(result1, Is.Not.Null); var result2 = session1.SQL("select * from performance_schema.session_status where variable_name='Mysqlx_bytes_received_uncompressed_frame' ").Execute().FetchOne()[1]; - Assert.IsNotNull(result2); + Assert.That(result2, Is.Not.Null); var result3 = session1.SQL("select * from performance_schema.session_status where variable_name='Mysqlx_bytes_sent_compressed_payload' ").Execute().FetchOne()[1]; - Assert.IsNotNull(result3); + Assert.That(result3, Is.Not.Null); var result4 = session1.SQL("select * from performance_schema.session_status where variable_name='Mysqlx_bytes_received_compressed_payload' ").Execute().FetchOne()[1]; - Assert.IsNotNull(result4); + Assert.That(result4, Is.Not.Null); if (Convert.ToInt32(result4) == 0 || Convert.ToInt32(result2) == 0) { Assert.Fail("Compression failed"); @@ -749,13 +749,13 @@ public void VerifyDataSentCompression() // Results of compression when its value for session2 is: compressValue1[i] and for session2 is: compressValue2[i] var result21 = session2.SQL("select * from performance_schema.session_status where variable_name='Mysqlx_bytes_sent_uncompressed_frame' ").Execute().FetchOne()[1]; - Assert.IsNotNull(result21); + Assert.That(result21, Is.Not.Null); var result22 = session2.SQL("select * from performance_schema.session_status where variable_name='Mysqlx_bytes_received_uncompressed_frame' ").Execute().FetchOne()[1]; - Assert.IsNotNull(result22); + Assert.That(result22, Is.Not.Null); var result23 = session2.SQL("select * from performance_schema.session_status where variable_name='Mysqlx_bytes_sent_compressed_payload' ").Execute().FetchOne()[1]; - Assert.IsNotNull(result23); + Assert.That(result23, Is.Not.Null); var result24 = session2.SQL("select * from performance_schema.session_status where variable_name='Mysqlx_bytes_received_compressed_payload' ").Execute().FetchOne()[1]; - Assert.IsNotNull(result24); + Assert.That(result24, Is.Not.Null); session1.Close(); session2.Close(); } @@ -787,25 +787,25 @@ public void VerifyDataReadCompression() schema.GetCollection("compressed"); var reader = session2.SQL("Select count(*) from compressed").Execute().FetchOne()[0]; var reader2 = session2.SQL("Select * from compressed").Execute().FetchAll(); - Assert.AreEqual("1", reader.ToString()); + Assert.That(reader.ToString(), Is.EqualTo("1")); var result1 = session1.SQL("select * from performance_schema.session_status where variable_name='Mysqlx_bytes_sent_uncompressed_frame' ").Execute().FetchOne()[1]; - Assert.IsNotNull(result1); + Assert.That(result1, Is.Not.Null); var result2 = session1.SQL("select * from performance_schema.session_status where variable_name='Mysqlx_bytes_received_uncompressed_frame' ").Execute().FetchOne()[1]; - Assert.IsNotNull(result2); + Assert.That(result2, Is.Not.Null); var result3 = session1.SQL("select * from performance_schema.session_status where variable_name='Mysqlx_bytes_sent_compressed_payload' ").Execute().FetchOne()[1]; - Assert.IsNotNull(result3); + Assert.That(result3, Is.Not.Null); var result4 = session1.SQL("select * from performance_schema.session_status where variable_name='Mysqlx_bytes_received_compressed_payload' ").Execute().FetchOne()[1]; - Assert.IsNotNull(result4); + Assert.That(result4, Is.Not.Null); var result21 = session2.SQL("select * from performance_schema.session_status where variable_name='Mysqlx_bytes_sent_uncompressed_frame' ").Execute().FetchOne()[1]; - Assert.IsNotNull(result21); + Assert.That(result21, Is.Not.Null); var result22 = session2.SQL("select * from performance_schema.session_status where variable_name='Mysqlx_bytes_received_uncompressed_frame' ").Execute().FetchOne()[1]; - Assert.IsNotNull(result22); + Assert.That(result22, Is.Not.Null); var result23 = session2.SQL("select * from performance_schema.session_status where variable_name='Mysqlx_bytes_sent_compressed_payload' ").Execute().FetchOne()[1]; - Assert.IsNotNull(result23); + Assert.That(result23, Is.Not.Null); var result24 = session2.SQL("select * from performance_schema.session_status where variable_name='Mysqlx_bytes_received_compressed_payload' ").Execute().FetchOne()[1]; - Assert.IsNotNull(result24); + Assert.That(result24, Is.Not.Null); session1.Close(); session2.Close(); } @@ -828,13 +828,13 @@ public void CompressionThreshold() collection.Add(doc1).Execute(); var result1 = session1.SQL("select * from performance_schema.session_status where variable_name='Mysqlx_bytes_sent_uncompressed_frame' ").Execute().FetchOne()[1]; - Assert.IsNotNull(result1); + Assert.That(result1, Is.Not.Null); var result2 = session1.SQL("select * from performance_schema.session_status where variable_name='Mysqlx_bytes_received_uncompressed_frame' ").Execute().FetchOne()[1]; - Assert.IsNotNull(result2); + Assert.That(result2, Is.Not.Null); var result3 = session1.SQL("select * from performance_schema.session_status where variable_name='Mysqlx_bytes_sent_compressed_payload' ").Execute().FetchOne()[1]; - Assert.IsNotNull(result3); + Assert.That(result3, Is.Not.Null); var result4 = session1.SQL("select * from performance_schema.session_status where variable_name='Mysqlx_bytes_received_compressed_payload' ").Execute().FetchOne()[1]; - Assert.IsNotNull(result4); + Assert.That(result4, Is.Not.Null); if (!Platform.IsWindows()) if (Convert.ToInt32(result2) != 0 || Convert.ToInt32(result4) != 0) @@ -846,13 +846,13 @@ public void CompressionThreshold() collection2.Add(doc2).Execute(); var result1b = session1.SQL("select * from performance_schema.session_status where variable_name='Mysqlx_bytes_sent_uncompressed_frame' ").Execute().FetchOne()[1]; - Assert.IsNotNull(result1b); + Assert.That(result1b, Is.Not.Null); var result2b = session1.SQL("select * from performance_schema.session_status where variable_name='Mysqlx_bytes_received_uncompressed_frame' ").Execute().FetchOne()[1]; - Assert.IsNotNull(result2b); + Assert.That(result2b, Is.Not.Null); var result3b = session1.SQL("select * from performance_schema.session_status where variable_name='Mysqlx_bytes_sent_compressed_payload' ").Execute().FetchOne()[1]; - Assert.IsNotNull(result3b); + Assert.That(result3b, Is.Not.Null); var result4b = session1.SQL("select * from performance_schema.session_status where variable_name='Mysqlx_bytes_received_compressed_payload' ").Execute().FetchOne()[1]; - Assert.IsNotNull(result4b); + Assert.That(result4b, Is.Not.Null); if (Convert.ToInt32(result4b) == 0 || Convert.ToInt32(result2b) == 0) Assert.Fail("Compression failed"); @@ -863,13 +863,13 @@ public void CompressionThreshold() collection3.Add(doc3).Execute(); var result1c = session1.SQL("select * from performance_schema.session_status where variable_name='Mysqlx_bytes_sent_uncompressed_frame' ").Execute().FetchOne()[1]; - Assert.IsNotNull(result1c); + Assert.That(result1c, Is.Not.Null); var result2c = session1.SQL("select * from performance_schema.session_status where variable_name='Mysqlx_bytes_received_uncompressed_frame' ").Execute().FetchOne()[1]; - Assert.IsNotNull(result2c); + Assert.That(result2c, Is.Not.Null); var result3c = session1.SQL("select * from performance_schema.session_status where variable_name='Mysqlx_bytes_sent_compressed_payload' ").Execute().FetchOne()[1]; - Assert.IsNotNull(result3c); + Assert.That(result3c, Is.Not.Null); var result4c = session1.SQL("select * from performance_schema.session_status where variable_name='Mysqlx_bytes_received_compressed_payload' ").Execute().FetchOne()[1]; - Assert.IsNotNull(result4c); + Assert.That(result4c, Is.Not.Null); if (Convert.ToInt32(result4c) == 0 || Convert.ToInt32(result2c) == 0) Assert.Fail("Compression failed"); @@ -912,7 +912,7 @@ public void NetworkLatency() watch2.Stop(); } - Assert.True(watch1.ElapsedTicks != watch2.ElapsedTicks, + Assert.That(watch1.ElapsedTicks != watch2.ElapsedTicks, $"Watch1: {watch1.ElapsedMilliseconds}, Watch2: {watch2.ElapsedMilliseconds}"); } #endregion diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/CrudInsertTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/CrudInsertTests.cs index aa5bcd253..d21fe9c36 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/CrudInsertTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/CrudInsertTests.cs @@ -51,8 +51,8 @@ public void InsertSingleDbDocWithId() { Collection coll = CreateCollection("test"); Result r = ExecuteAddStatement(coll.Add(@"{ ""_id"": 1, ""foo"": 1 }")); - Assert.AreEqual(1, r.AffectedItemsCount); - Assert.AreEqual(1, coll.Count()); + Assert.That(r.AffectedItemsCount, Is.EqualTo(1)); + Assert.That(coll.Count(), Is.EqualTo(1)); } [Test] @@ -63,14 +63,14 @@ public void InsertSingleDbDocWithoutId() if (!session.Version.isAtLeast(8, 0, 5)) { // Code 5115 Document is missing a required field - Assert.AreEqual(5115u, Assert.Throws(() => ExecuteAddStatement(stmt)).Code); + Assert.That(Assert.Throws(() => ExecuteAddStatement(stmt)).Code, Is.EqualTo(5115u)); return; } Result r = ExecuteAddStatement(stmt); - Assert.AreEqual(1, r.AffectedItemsCount); - Assert.AreEqual(1, coll.Count()); + Assert.That(r.AffectedItemsCount, Is.EqualTo(1)); + Assert.That(coll.Count(), Is.EqualTo(1)); Assert.That(r.GeneratedIds, Has.One.Items); - Assert.False(string.IsNullOrWhiteSpace(r.GeneratedIds[0])); + Assert.That(string.IsNullOrWhiteSpace(r.GeneratedIds[0]), Is.False); } [Test] @@ -83,13 +83,13 @@ public void InsertMultipleDbDocWithoutId() if (!session.Version.isAtLeast(8, 0, 5)) { // Code 5115 Document is missing a required field - Assert.AreEqual(5115u, Assert.Throws(() => ExecuteAddStatement(stmt)).Code); + Assert.That(Assert.Throws(() => ExecuteAddStatement(stmt)).Code, Is.EqualTo(5115u)); return; } Result r = ExecuteAddStatement(stmt); - Assert.AreEqual(3, r.AffectedItemsCount); - Assert.AreEqual(3, coll.Count()); - Assert.AreEqual(3, r.GeneratedIds.Count); + Assert.That(r.AffectedItemsCount, Is.EqualTo(3)); + Assert.That(coll.Count(), Is.EqualTo(3)); + Assert.That(r.GeneratedIds.Count, Is.EqualTo(3)); } [Test] @@ -99,9 +99,9 @@ public void InsertAnonymousObjectWithId() Collection coll = CreateCollection("test"); Result r = ExecuteAddStatement(coll.Add(obj)); - Assert.AreEqual(1, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(1)); //TODO: pull object and verify data - Assert.AreEqual(1, coll.Count()); + Assert.That(coll.Count(), Is.EqualTo(1)); } [Test] @@ -114,15 +114,15 @@ public void InsertAnonymousObjectWithNoId() if (!session.Version.isAtLeast(8, 0, 5)) { // Code 5115 Document is missing a required field - Assert.AreEqual(5115u, Assert.Throws(() => ExecuteAddStatement(stmt)).Code); + Assert.That(Assert.Throws(() => ExecuteAddStatement(stmt)).Code, Is.EqualTo(5115u)); return; } Result r = ExecuteAddStatement(stmt); - Assert.AreEqual(1, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(1)); //TODO: pull object and verify data - Assert.AreEqual(1, coll.Count()); + Assert.That(coll.Count(), Is.EqualTo(1)); Assert.That(r.GeneratedIds, Has.One.Items); - Assert.False(string.IsNullOrWhiteSpace(r.GeneratedIds[0])); + Assert.That(string.IsNullOrWhiteSpace(r.GeneratedIds[0]), Is.False); } [Test] @@ -137,8 +137,8 @@ public void InsertMultipleAnonymousObjectsWithId() new { _id = 4, title = "Book 4", pages = 50 }, }; Result r = ExecuteAddStatement(coll.Add(docs)); - Assert.AreEqual(4, r.AffectedItemsCount); - Assert.AreEqual(4, coll.Count()); + Assert.That(r.AffectedItemsCount, Is.EqualTo(4)); + Assert.That(coll.Count(), Is.EqualTo(4)); } [Test] @@ -149,15 +149,15 @@ public void ValidatesDocumentIds() if (!session.Version.isAtLeast(8, 0, 5)) { // Code 5115 Document is missing a required field - Assert.AreEqual(5115u, Assert.Throws(() => ExecuteAddStatement(stmt)).Code); + Assert.That(Assert.Throws(() => ExecuteAddStatement(stmt)).Code, Is.EqualTo(5115u)); return; } Result result = ExecuteAddStatement(stmt); - Assert.AreEqual(1, result.AffectedItemsCount); + Assert.That(result.AffectedItemsCount, Is.EqualTo(1)); result = ExecuteModifyStatement(coll.Modify($"_id = '{result.GeneratedIds[0]}'").Set("pages", "20")); - Assert.AreEqual(1, result.AffectedItemsCount); - CollectionAssert.IsEmpty(result.GeneratedIds); + Assert.That(result.AffectedItemsCount, Is.EqualTo(1)); + Assert.That(result.GeneratedIds, Is.Empty); } [Test] @@ -177,8 +177,8 @@ public void ReuseStatement() stmt.Add(doc); } Result r = ExecuteAddStatement(stmt); - Assert.AreEqual((ulong)docs.Length + 1, r.AffectedItemsCount); - Assert.AreEqual(5, coll.Count()); + Assert.That(r.AffectedItemsCount, Is.EqualTo((ulong)docs.Length + 1)); + Assert.That(coll.Count(), Is.EqualTo(5)); } [Test] @@ -187,10 +187,10 @@ public void EmptyDocArray() Collection coll = CreateCollection("test"); var insertResult = ExecuteAddStatement(coll.Add(new DbDoc[] { })); - Assert.AreEqual(0ul, insertResult.AffectedItemsCount); + Assert.That(insertResult.AffectedItemsCount, Is.EqualTo(0ul)); var result = ExecuteFindStatement(coll.Find()).FetchAll(); - CollectionAssert.IsEmpty(result); + Assert.That(result, Is.Empty); } [Test] @@ -218,7 +218,7 @@ public void InsertingArray() ExecuteAddStatement(coll.Add(d2)); var result = ExecuteFindStatement(coll.Find()).FetchAll(); Assert.That(result, Has.One.Items); - Assert.AreEqual(d2.ToString(), result[0].ToString()); + Assert.That(result[0].ToString(), Is.EqualTo(d2.ToString())); } [Test] @@ -226,13 +226,13 @@ public void CompareGuids() { Guid guid1 = new Guid(); Guid guid2 = new Guid(); - Assert.AreEqual(0, Tools.CompareGuids(guid1, guid2)); - Assert.AreEqual(0, Tools.CompareGuids(guid1.ToString(), guid2.ToString())); + Assert.That(Tools.CompareGuids(guid1, guid2), Is.EqualTo(0)); + Assert.That(Tools.CompareGuids(guid1.ToString(), guid2.ToString()), Is.EqualTo(0)); guid1 = Guid.NewGuid(); guid2 = Guid.NewGuid(); - Assert.True(Tools.CompareGuids(guid1, guid2) != 0); - Assert.True(Tools.CompareGuids(guid1.ToString(), guid2.ToString()) != 0); + Assert.That(Tools.CompareGuids(guid1, guid2) != 0); + Assert.That(Tools.CompareGuids(guid1.ToString(), guid2.ToString()) != 0); } [Test] @@ -251,10 +251,10 @@ public void InsertNullValuesAsDbDoc() ExecuteAddStatement(collection.Add(docs)); var result = ExecuteFindStatement(collection.Find()).FetchAll(); - Assert.AreEqual(docs.Length, result.Count); + Assert.That(result.Count, Is.EqualTo(docs.Length)); for (int i = 0; i < docs.Length; i++) - Assert.AreEqual(docs[i].ToString(), result[i].ToString()); + Assert.That(result[i].ToString(), Is.EqualTo(docs[i].ToString())); } [Test] @@ -271,13 +271,13 @@ public void InsertNullValuesAsJson() Collection collection = CreateCollection("test"); ExecuteAddStatement(collection.Add(docs)); var result = ExecuteFindStatement(collection.Find()).FetchAll(); - Assert.AreEqual(docs.Length, result.Count); + Assert.That(result.Count, Is.EqualTo(docs.Length)); for (int i = 0; i < docs.Length; i++) { var currentDoc = new DbDoc(docs[i]); var resultingDoc = new DbDoc(result[i]); - Assert.AreEqual(currentDoc.Id, resultingDoc.Id); - Assert.AreEqual(currentDoc["foo"], resultingDoc["foo"]); + Assert.That(resultingDoc.Id, Is.EqualTo(currentDoc.Id)); + Assert.That(resultingDoc["foo"], Is.EqualTo(currentDoc["foo"])); } } @@ -295,29 +295,29 @@ public void AddOrReplaceOne() new { _id = 4, title = "Book 4", pages = 50 }, }; Result result = ExecuteAddStatement(collection.Add(docs)); - Assert.AreEqual(4, result.AffectedItemsCount); + Assert.That(result.AffectedItemsCount, Is.EqualTo(4)); // Add a document. - Assert.AreEqual(1, collection.AddOrReplaceOne(5, new { _id = 5, title = "Book 5", pages = 60 }).AffectedItemsCount); - Assert.True(collection.GetOne(5) != null); + Assert.That(collection.AddOrReplaceOne(5, new { _id = 5, title = "Book 5", pages = 60 }).AffectedItemsCount, Is.EqualTo(1)); + Assert.That(collection.GetOne(5) != null); - Assert.AreEqual(1, collection.AddOrReplaceOne("6", new { title = "Book 6", pages = 70 }).AffectedItemsCount); - Assert.True(collection.GetOne(6) != null); - Assert.True(collection.GetOne("6") != null); + Assert.That(collection.AddOrReplaceOne("6", new { title = "Book 6", pages = 70 }).AffectedItemsCount, Is.EqualTo(1)); + Assert.That(collection.GetOne(6) != null); + Assert.That(collection.GetOne("6") != null); // Replace a document. - Assert.AreEqual(2, collection.AddOrReplaceOne(1, new { _id = 1, title = "Book X", pages = 10 }).AffectedItemsCount); + Assert.That(collection.AddOrReplaceOne(1, new { _id = 1, title = "Book X", pages = 10 }).AffectedItemsCount, Is.EqualTo(2)); DbDoc document = collection.GetOne(1); - Assert.AreEqual(1, Convert.ToInt32(document.Id)); - Assert.AreEqual("Book X", document["title"]); - Assert.AreEqual(10, Convert.ToInt32(document["pages"])); + Assert.That(Convert.ToInt32(document.Id), Is.EqualTo(1)); + Assert.That(document["title"], Is.EqualTo("Book X")); + Assert.That(Convert.ToInt32(document["pages"]), Is.EqualTo(10)); - Assert.AreEqual(2, collection.AddOrReplaceOne(1, new { title = "Book Y", pages = 9, other = "value" }).AffectedItemsCount); + Assert.That(collection.AddOrReplaceOne(1, new { title = "Book Y", pages = 9, other = "value" }).AffectedItemsCount, Is.EqualTo(2)); document = collection.GetOne(1); - Assert.AreEqual(1, Convert.ToInt32(document.Id)); - Assert.AreEqual("Book Y", document["title"]); - Assert.AreEqual(9, Convert.ToInt32(document["pages"])); - Assert.AreEqual("value", document["other"]); + Assert.That(Convert.ToInt32(document.Id), Is.EqualTo(1)); + Assert.That(document["title"], Is.EqualTo("Book Y")); + Assert.That(Convert.ToInt32(document["pages"]), Is.EqualTo(9)); + Assert.That(document["other"], Is.EqualTo("value")); // Expected exceptions. Assert.Throws(() => collection.AddOrReplaceOne(null, docs[1])); @@ -346,13 +346,13 @@ public void CreateCollectionAndReuseObject() }; Result result = col.Add(data).Execute(); var data1 = col.Remove("_id = 1").Execute(); - Assert.AreEqual(1, (int)data1.AffectedItemsCount, "Matching the deleted record count"); + Assert.That((int)data1.AffectedItemsCount, Is.EqualTo(1), "Matching the deleted record count"); data1 = col.Remove("_id = 2").Execute(); - Assert.AreEqual(1, (int)data1.AffectedItemsCount, "Matching the deleted record count"); + Assert.That((int)data1.AffectedItemsCount, Is.EqualTo(1), "Matching the deleted record count"); data1 = col.Remove("_id = 3").Execute(); - Assert.AreEqual(1, (int)data1.AffectedItemsCount, "Matching the deleted record count"); + Assert.That((int)data1.AffectedItemsCount, Is.EqualTo(1), "Matching the deleted record count"); data1 = col.Remove("_id = 4").Execute(); - Assert.AreEqual(1, (int)data1.AffectedItemsCount, "Matching the deleted record count"); + Assert.That((int)data1.AffectedItemsCount, Is.EqualTo(1), "Matching the deleted record count"); sessionPlain.Close(); } } @@ -370,7 +370,7 @@ public void CreateCollectionWithoutReuseExistingObject() Schema db = session.GetSchema(schemaName); var col = CreateCollection("my_collection_123456789"); col = db.GetCollection("my_collection_123456789", true); - Assert.IsNotNull(col); + Assert.That(col, Is.Not.Null); Assert.Throws(() => db.CreateCollection("my_collection_123456789", false)); } @@ -388,15 +388,15 @@ public void CollectionAddObjectsFindCondition() }; Result result = col.Add(docs).Execute(); - Assert.AreEqual(4, (int)result.AffectedItemsCount, "Matching the updated record count"); + Assert.That((int)result.AffectedItemsCount, Is.EqualTo(4), "Matching the updated record count"); var foundDocs = col.Find("pages > 20").Execute(); - Assert.AreEqual(true, foundDocs.Next(), "Next Node Exist"); - Assert.AreEqual("Book 2", foundDocs.Current["title"], "Matching the Node Value"); - Assert.AreEqual(true, foundDocs.Next(), "Next Node Exist"); - Assert.AreEqual("Book 3", foundDocs.Current["title"], "Matching the Node Value"); - Assert.AreEqual(true, foundDocs.Next(), "Next Node Exist"); - Assert.AreEqual("Book 4", foundDocs.Current["title"], "Matching the Node Value"); - Assert.AreEqual(false, foundDocs.Next(), "Next Node doesnot Exist"); + Assert.That(foundDocs.Next(), Is.EqualTo(true), "Next Node Exist"); + Assert.That(foundDocs.Current["title"], Is.EqualTo("Book 2"), "Matching the Node Value"); + Assert.That(foundDocs.Next(), Is.EqualTo(true), "Next Node Exist"); + Assert.That(foundDocs.Current["title"], Is.EqualTo("Book 3"), "Matching the Node Value"); + Assert.That(foundDocs.Next(), Is.EqualTo(true), "Next Node Exist"); + Assert.That(foundDocs.Current["title"], Is.EqualTo("Book 4"), "Matching the Node Value"); + Assert.That(foundDocs.Next(), Is.EqualTo(false), "Next Node doesnot Exist"); db.DropCollection("my_collection_1"); } @@ -414,17 +414,17 @@ public void CollectionAddFindNoParams() }; var result = col.Add(docs).Execute(); - Assert.AreEqual(4, (int)result.AffectedItemsCount, "Matching the updated record count"); + Assert.That((int)result.AffectedItemsCount, Is.EqualTo(4), "Matching the updated record count"); var foundDocs = col.Find().Execute(); - Assert.AreEqual(true, foundDocs.Next(), "Next Node Exist"); - Assert.AreEqual("Book 1", foundDocs.Current["title"], "Matching the Node Value"); - Assert.AreEqual(true, foundDocs.Next(), "Next Node Exist"); - Assert.AreEqual("Book 2", foundDocs.Current["title"], "Matching the Node Value"); - Assert.AreEqual(true, foundDocs.Next(), "Next Node Exist"); - Assert.AreEqual("Book 3", foundDocs.Current["title"], "Matching the Node Value"); - Assert.AreEqual(true, foundDocs.Next(), "Next Node Exist"); - Assert.AreEqual("Book 4", foundDocs.Current["title"], "Matching the Node Value"); - Assert.AreEqual(false, foundDocs.Next(), "Next Node doesnot Exist"); + Assert.That(foundDocs.Next(), Is.EqualTo(true), "Next Node Exist"); + Assert.That(foundDocs.Current["title"], Is.EqualTo("Book 1"), "Matching the Node Value"); + Assert.That(foundDocs.Next(), Is.EqualTo(true), "Next Node Exist"); + Assert.That(foundDocs.Current["title"], Is.EqualTo("Book 2"), "Matching the Node Value"); + Assert.That(foundDocs.Next(), Is.EqualTo(true), "Next Node Exist"); + Assert.That(foundDocs.Current["title"], Is.EqualTo("Book 3"), "Matching the Node Value"); + Assert.That(foundDocs.Next(), Is.EqualTo(true), "Next Node Exist"); + Assert.That(foundDocs.Current["title"], Is.EqualTo("Book 4"), "Matching the Node Value"); + Assert.That(foundDocs.Next(), Is.EqualTo(false), "Next Node doesnot Exist"); } [Test, Description("Test MySQLX plugin Collection Scenarios - Add/Remove JSON Object with id")] @@ -440,11 +440,11 @@ public void CollectionAddRemoveJSONObjectID() DbDocs.SetValue("title", "Book 0"); DbDocs.SetValue("pages", "10"); var result = col.Add(DbDocs).Execute(); - Assert.AreEqual(1, (int)result.AffectedItemsCount, "Matching the updated record count"); + Assert.That((int)result.AffectedItemsCount, Is.EqualTo(1), "Matching the updated record count"); DbDoc jsonremovedoc = new DbDoc(); jsonremovedoc.SetValue("_id", "0"); var foundDocs = col.Remove("_id='0'").Execute(); - Assert.AreEqual(1, (int)foundDocs.AffectedItemsCount, "Matching the deleted record count"); + Assert.That((int)foundDocs.AffectedItemsCount, Is.EqualTo(1), "Matching the deleted record count"); db.DropCollection("my_collection_1"); sessionPlain.Close(); } @@ -461,9 +461,9 @@ public void CollectionAddRemoveJSONObjectCondition() DbDocs.SetValue("title", "Book 0"); DbDocs.SetValue("pages", "10"); var result = col.Add(DbDocs).Execute(); - Assert.AreEqual(1, (int)result.AffectedItemsCount, "Matching the updated record count"); + Assert.That((int)result.AffectedItemsCount, Is.EqualTo(1), "Matching the updated record count"); var foundDocs = col.Remove("pages > 0").Execute(); - Assert.AreEqual(1, (int)foundDocs.AffectedItemsCount, "Matching the deleted record count"); + Assert.That((int)foundDocs.AffectedItemsCount, Is.EqualTo(1), "Matching the deleted record count"); db.DropCollection("my_collection_1"); } @@ -482,19 +482,19 @@ public void CollectionAddRemoveObjectConditionLimit() new { _id = 4, title = "Book 4", pages = 50 }, }; var result = col.Add(docs).Execute(); - Assert.AreEqual(5, (int)result.AffectedItemsCount, "Matching the updated record count"); + Assert.That((int)result.AffectedItemsCount, Is.EqualTo(5), "Matching the updated record count"); var foundDocs = col.Remove("_id=1").Execute(); - Assert.AreEqual(1, (int)foundDocs.AffectedItemsCount, "Matching the deleted record count"); + Assert.That((int)foundDocs.AffectedItemsCount, Is.EqualTo(1), "Matching the deleted record count"); docs = new[] { new { _id = 1, title = "Book 1", pages = 20 }, }; result = col.Add(docs).Execute(); - Assert.AreEqual(1, (int)result.AffectedItemsCount, "Matching the updated record count"); + Assert.That((int)result.AffectedItemsCount, Is.EqualTo(1), "Matching the updated record count"); result = col.Remove("pages > 10").Limit(1).Execute(); - Assert.AreEqual(1, (int)result.AffectedItemsCount, "Matching the updated record count"); + Assert.That((int)result.AffectedItemsCount, Is.EqualTo(1), "Matching the updated record count"); result = col.Remove("pages > 10").Limit(3).Execute(); - Assert.AreEqual(3, (int)result.AffectedItemsCount, "Matching the updated record count"); + Assert.That((int)result.AffectedItemsCount, Is.EqualTo(3), "Matching the updated record count"); Assert.Throws(() => col.Remove("pages > 10").Limit(0).Execute()); db.DropCollection("my_collection_1"); } @@ -519,11 +519,11 @@ public void CollectionAddRemove200JSONRecords() } var res = col.Add(jsonlist).Execute(); - Assert.AreEqual(jsonlist[0].ToString(), jsonlist[0].ToString(), "String Match being done"); + Assert.That(jsonlist[0].ToString(), Is.EqualTo(jsonlist[0].ToString()), "String Match being done"); for (int i = 0; i < numOfRecords; i++) { var data1 = col.Remove($"_id = '{i + 1000}'").Execute(); - Assert.AreEqual(1, (int)data1.AffectedItemsCount, "Matching the deleted record count"); + Assert.That((int)data1.AffectedItemsCount, Is.EqualTo(1), "Matching the deleted record count"); } } @@ -546,25 +546,25 @@ public void CollectionAddRemoveJSONRecordsLimitOrderBy() newDoc2 = null; } col.Add(jsonlist).Execute(); - Assert.AreEqual(jsonlist[0].ToString(), jsonlist[0].ToString(), "String Match being done"); + Assert.That(jsonlist[0].ToString(), Is.EqualTo(jsonlist[0].ToString()), "String Match being done"); Result result = col.Remove("F3 > 305").Limit(1).Execute(); - Assert.AreEqual(1, (int)result.AffectedItemsCount, "Match being done"); + Assert.That((int)result.AffectedItemsCount, Is.EqualTo(1), "Match being done"); result = col.Remove("F3 > 303").Sort("F3 DESC").Execute(); - Assert.AreEqual(5, (int)result.AffectedItemsCount, "Match being done"); + Assert.That((int)result.AffectedItemsCount, Is.EqualTo(5), "Match being done"); result = col.Remove("F3 > 303").Sort("F3 DESC").Execute(); - Assert.AreEqual(0, (int)result.AffectedItemsCount, "Match being done"); + Assert.That((int)result.AffectedItemsCount, Is.EqualTo(0), "Match being done"); result = col.Remove("F3 = 303").Sort("F2 DESC").Execute(); - Assert.AreEqual(1, (int)result.AffectedItemsCount, "Match being done"); + Assert.That((int)result.AffectedItemsCount, Is.EqualTo(1), "Match being done"); result = col.Remove("F3 < 301").Sort("F2 DESC").Execute(); - Assert.AreEqual(1, (int)result.AffectedItemsCount, "Match being done"); + Assert.That((int)result.AffectedItemsCount, Is.EqualTo(1), "Match being done"); result = col.Remove("F3 < 301").Sort("F2 DESC").Execute(); - Assert.AreEqual(0, (int)result.AffectedItemsCount, "Match being done"); + Assert.That((int)result.AffectedItemsCount, Is.EqualTo(0), "Match being done"); db.DropCollection("my_collection_1"); @@ -580,23 +580,23 @@ public void CollectionAddRemoveDocsLimitOrderByBind() DbDocs.SetValue("title", "Book 0"); DbDocs.SetValue("pages", 10); var result = col.Add(DbDocs).Execute(); - Assert.AreEqual(1, (int)result.AffectedItemsCount, "Matching the updated record count"); + Assert.That((int)result.AffectedItemsCount, Is.EqualTo(1), "Matching the updated record count"); var foundDocs = col.Remove("pages > 0").Execute(); - Assert.AreEqual(1, (int)foundDocs.AffectedItemsCount, "Matching the deleted record count"); + Assert.That((int)foundDocs.AffectedItemsCount, Is.EqualTo(1), "Matching the deleted record count"); var docs = new { _id = 100001, title = "Book 1", pages = 20 }; result = col.Add(docs).Execute(); - Assert.AreEqual(1, (int)result.AffectedItemsCount, "Matching the updated record count"); + Assert.That((int)result.AffectedItemsCount, Is.EqualTo(1), "Matching the updated record count"); foundDocs = col.Remove("pages=20").Execute(); - Assert.AreEqual(1, (int)foundDocs.AffectedItemsCount, "Matching the deleted record count"); + Assert.That((int)foundDocs.AffectedItemsCount, Is.EqualTo(1), "Matching the deleted record count"); docs = new { _id = -100001, title = "Book 1", pages = 20 }; result = col.Add(docs).Execute(); - Assert.AreEqual(1, (int)result.AffectedItemsCount, "Matching the updated record count"); + Assert.That((int)result.AffectedItemsCount, Is.EqualTo(1), "Matching the updated record count"); foundDocs = col.Remove("pages=20").Execute(); - Assert.AreEqual(1, (int)foundDocs.AffectedItemsCount, "Matching the deleted record count"); + Assert.That((int)foundDocs.AffectedItemsCount, Is.EqualTo(1), "Matching the deleted record count"); var docs1 = new[] { new { _id = -100001, title = "Book 0", pages = 10 }, @@ -605,13 +605,13 @@ public void CollectionAddRemoveDocsLimitOrderByBind() new { _id = 10000001, title = "Book 3", pages = 40 } }; result = col.Add(docs1).Execute(); - Assert.AreEqual(4, (int)result.AffectedItemsCount, "Matching the updated record count"); + Assert.That((int)result.AffectedItemsCount, Is.EqualTo(4), "Matching the updated record count"); foundDocs = col.Remove("pages > 10").Execute(); - Assert.AreEqual(3, (int)foundDocs.AffectedItemsCount, "Matching the deleted record count"); + Assert.That((int)foundDocs.AffectedItemsCount, Is.EqualTo(3), "Matching the deleted record count"); foundDocs = col.Remove("pages=10").Execute(); - Assert.AreEqual(1, (int)foundDocs.AffectedItemsCount, "Matching the deleted record count"); + Assert.That((int)foundDocs.AffectedItemsCount, Is.EqualTo(1), "Matching the deleted record count"); docs1 = new[] { new { _id = -100001, title = "Book 0", pages = 10 }, @@ -621,27 +621,27 @@ public void CollectionAddRemoveDocsLimitOrderByBind() new { _id = 10000009, title = "Book 4", pages = 50 } }; result = col.Add(docs1).Execute(); - Assert.AreEqual(5, (int)result.AffectedItemsCount, "Matching the updated record count"); + Assert.That((int)result.AffectedItemsCount, Is.EqualTo(5), "Matching the updated record count"); foundDocs = col.Remove("pages = 40").Execute(); - Assert.AreEqual(1, (int)foundDocs.AffectedItemsCount, "Matching the deleted record count"); + Assert.That((int)foundDocs.AffectedItemsCount, Is.EqualTo(1), "Matching the deleted record count"); foundDocs = col.Remove("pages >= 10").Execute(); - Assert.AreEqual(4, (int)foundDocs.AffectedItemsCount, "Matching the deleted record count"); + Assert.That((int)foundDocs.AffectedItemsCount, Is.EqualTo(4), "Matching the deleted record count"); result = col.Add(docs1).Execute(); - Assert.AreEqual(5, (int)result.AffectedItemsCount, "Matching the updated record count"); + Assert.That((int)result.AffectedItemsCount, Is.EqualTo(5), "Matching the updated record count"); foundDocs = col.Remove("pages = 40").Limit(1).Execute(); - Assert.AreEqual(1, (int)foundDocs.AffectedItemsCount, "Matching the deleted record count"); + Assert.That((int)foundDocs.AffectedItemsCount, Is.EqualTo(1), "Matching the deleted record count"); foundDocs = col.Remove("pages <= 50").Execute(); - Assert.AreEqual(4, (int)foundDocs.AffectedItemsCount, "Matching the deleted record count"); + Assert.That((int)foundDocs.AffectedItemsCount, Is.EqualTo(4), "Matching the deleted record count"); result = col.Add(docs1).Execute(); - Assert.AreEqual(5, (int)result.AffectedItemsCount, "Matching the updated record count"); + Assert.That((int)result.AffectedItemsCount, Is.EqualTo(5), "Matching the updated record count"); foundDocs = col.Remove("pages = 40").Limit(1).Sort("title").Execute(); - Assert.AreEqual(1, (int)foundDocs.AffectedItemsCount, "Matching the deleted record count"); + Assert.That((int)foundDocs.AffectedItemsCount, Is.EqualTo(1), "Matching the deleted record count"); foundDocs = col.Remove("pages <= 50").Execute(); - Assert.AreEqual(4, (int)foundDocs.AffectedItemsCount, "Matching the deleted record count"); + Assert.That((int)foundDocs.AffectedItemsCount, Is.EqualTo(4), "Matching the deleted record count"); docs1 = new[] { @@ -652,9 +652,9 @@ public void CollectionAddRemoveDocsLimitOrderByBind() }; result = col.Add(docs1).Execute(); - Assert.AreEqual(4, (int)result.AffectedItemsCount, "Matching the updated record count"); + Assert.That((int)result.AffectedItemsCount, Is.EqualTo(4), "Matching the updated record count"); foundDocs = col.Remove("pages = :Pages").Bind("pAges", 50).Execute(); - Assert.AreEqual(1, (int)foundDocs.AffectedItemsCount, "Matching the deleted record count"); + Assert.That((int)foundDocs.AffectedItemsCount, Is.EqualTo(1), "Matching the deleted record count"); } [Test, Description("Test MySQLX plugin Collection Scenarios - Add Single/Multiple Docs - Remove Condition/ID/Condition-Limit/Condition-Limit-OrderBy/Bind using invalid conditions")] @@ -670,23 +670,23 @@ public void CollectionRemoveDocsLimitOrderByBindNegative() DbDocs.SetValue("pages", 10); var result = col.Add(DbDocs).Execute(); - Assert.AreEqual(1, (int)result.AffectedItemsCount, "Matching the updated record count"); + Assert.That((int)result.AffectedItemsCount, Is.EqualTo(1), "Matching the updated record count"); var foundDocs = col.Remove("pages > 10").Execute(); - Assert.AreEqual(0, (int)foundDocs.AffectedItemsCount, "Matching the deleted record count"); + Assert.That((int)foundDocs.AffectedItemsCount, Is.EqualTo(0), "Matching the deleted record count"); var docs = new { _id = 100001, title = "Book 1", pages = 20 }; result = col.Add(docs).Execute(); - Assert.AreEqual(1, (int)result.AffectedItemsCount, "Matching the updated record count"); + Assert.That((int)result.AffectedItemsCount, Is.EqualTo(1), "Matching the updated record count"); foundDocs = col.Remove("pages >= 10").Execute(); - Assert.AreEqual(2, (int)foundDocs.AffectedItemsCount, "Matching the deleted record count"); + Assert.That((int)foundDocs.AffectedItemsCount, Is.EqualTo(2), "Matching the deleted record count"); docs = new { _id = -100001, title = "Book 1", pages = 20 }; result = col.Add(docs).Execute(); - Assert.AreEqual(1, (int)result.AffectedItemsCount, "Matching the updated record count"); + Assert.That((int)result.AffectedItemsCount, Is.EqualTo(1), "Matching the updated record count"); foundDocs = col.Remove("pages > 10").Execute(); - Assert.AreEqual(1, (int)foundDocs.AffectedItemsCount, "Matching the deleted record count"); + Assert.That((int)foundDocs.AffectedItemsCount, Is.EqualTo(1), "Matching the deleted record count"); var docs1 = new[] @@ -697,13 +697,13 @@ public void CollectionRemoveDocsLimitOrderByBindNegative() new { _id = 10000001, title = "Book 3", pages = 40 } }; result = col.Add(docs1).Execute(); - Assert.AreEqual(4, (int)result.AffectedItemsCount, "Matching the updated record count"); + Assert.That((int)result.AffectedItemsCount, Is.EqualTo(4), "Matching the updated record count"); foundDocs = col.Remove("pages > 50").Execute(); - Assert.AreEqual(0, (int)foundDocs.AffectedItemsCount, "Matching the deleted record count"); + Assert.That((int)foundDocs.AffectedItemsCount, Is.EqualTo(0), "Matching the deleted record count"); foundDocs = col.Remove("pages < 50").Execute(); - Assert.AreEqual(4, (int)foundDocs.AffectedItemsCount, "Matching the deleted record count"); + Assert.That((int)foundDocs.AffectedItemsCount, Is.EqualTo(4), "Matching the deleted record count"); docs1 = new[] { @@ -714,28 +714,28 @@ public void CollectionRemoveDocsLimitOrderByBindNegative() new { _id = 10000009, title = "Book 4", pages = 50 } }; result = col.Add(docs1).Execute(); - Assert.AreEqual(5, (int)result.AffectedItemsCount, "Matching the updated record count"); + Assert.That((int)result.AffectedItemsCount, Is.EqualTo(5), "Matching the updated record count"); foundDocs = col.Remove("pages = 0").Execute(); - Assert.AreEqual(0, (int)foundDocs.AffectedItemsCount, "Matching the deleted record count"); + Assert.That((int)foundDocs.AffectedItemsCount, Is.EqualTo(0), "Matching the deleted record count"); foundDocs = col.Remove("pages <= 50").Execute(); - Assert.AreEqual(5, (int)foundDocs.AffectedItemsCount, "Matching the deleted record count"); + Assert.That((int)foundDocs.AffectedItemsCount, Is.EqualTo(5), "Matching the deleted record count"); result = col.Add(docs1).Execute(); - Assert.AreEqual(5, (int)result.AffectedItemsCount, "Matching the updated record count"); + Assert.That((int)result.AffectedItemsCount, Is.EqualTo(5), "Matching the updated record count"); foundDocs = col.Remove("pages = 60").Limit(1).Execute(); - Assert.AreEqual(0, (int)foundDocs.AffectedItemsCount, "Matching the deleted record count"); + Assert.That((int)foundDocs.AffectedItemsCount, Is.EqualTo(0), "Matching the deleted record count"); foundDocs = col.Remove("pages <= 50").Execute(); - Assert.AreEqual(5, (int)foundDocs.AffectedItemsCount, "Matching the deleted record count"); + Assert.That((int)foundDocs.AffectedItemsCount, Is.EqualTo(5), "Matching the deleted record count"); result = col.Add(docs1).Execute(); - Assert.AreEqual(5, (int)result.AffectedItemsCount, "Matching the updated record count"); + Assert.That((int)result.AffectedItemsCount, Is.EqualTo(5), "Matching the updated record count"); foundDocs = col.Remove("pages = 04").Limit(1).Sort("title").Execute(); - Assert.AreEqual(0, (int)foundDocs.AffectedItemsCount, "Matching the deleted record count"); + Assert.That((int)foundDocs.AffectedItemsCount, Is.EqualTo(0), "Matching the deleted record count"); foundDocs = col.Remove("pages <= 50").Execute(); - Assert.AreEqual(5, (int)foundDocs.AffectedItemsCount, "Matching the deleted record count"); + Assert.That((int)foundDocs.AffectedItemsCount, Is.EqualTo(5), "Matching the deleted record count"); docs1 = new[] { @@ -746,13 +746,13 @@ public void CollectionRemoveDocsLimitOrderByBindNegative() }; result = col.Add(docs1).Execute(); - Assert.AreEqual(4, (int)result.AffectedItemsCount, "Matching the updated record count"); + Assert.That((int)result.AffectedItemsCount, Is.EqualTo(4), "Matching the updated record count"); foundDocs = col.Remove("pages1 = :Pages").Bind("pAges", 50).Execute(); - Assert.AreEqual(0, (int)foundDocs.AffectedItemsCount, "Matching the deleted record count"); + Assert.That((int)foundDocs.AffectedItemsCount, Is.EqualTo(0), "Matching the deleted record count"); foundDocs = col.Remove("pages = :Pages").Bind("pAges", 51).Execute(); - Assert.AreEqual(0, (int)foundDocs.AffectedItemsCount, "Matching the deleted record count"); + Assert.That((int)foundDocs.AffectedItemsCount, Is.EqualTo(0), "Matching the deleted record count"); foundDocs = col.Remove("pages = :Pages").Bind("pAges", 50).Execute(); - Assert.AreEqual(1, (int)foundDocs.AffectedItemsCount, "Matching the deleted record count"); + Assert.That((int)foundDocs.AffectedItemsCount, Is.EqualTo(1), "Matching the deleted record count"); db.DropCollection("my_collection_1"); } @@ -775,18 +775,18 @@ public void AllowReuseStatementAfterExecutePositive1() new { _id = 8, title = "Book 8", pages = 80 }, }; Result result = col.Add(data).Execute(); - Assert.AreEqual(8, (int)result.AffectedItemsCount, "Matching the added record count"); + Assert.That((int)result.AffectedItemsCount, Is.EqualTo(8), "Matching the added record count"); var data1 = col.Remove("_id=1").Execute(); - Assert.AreEqual(1, (int)data1.AffectedItemsCount, "Matching the deleted record count"); + Assert.That((int)data1.AffectedItemsCount, Is.EqualTo(1), "Matching the deleted record count"); data1 = col.Remove("pages = :Pages").Bind("pAges", 80).Execute(); - Assert.AreEqual(1, (int)data1.AffectedItemsCount, "Matching the deleted record count"); + Assert.That((int)data1.AffectedItemsCount, Is.EqualTo(1), "Matching the deleted record count"); data1 = col.Remove("pages = :Pages").Bind("pAges", 70).Execute(); - Assert.AreEqual(1, (int)data1.AffectedItemsCount, "Matching the deleted record count"); + Assert.That((int)data1.AffectedItemsCount, Is.EqualTo(1), "Matching the deleted record count"); var remData = col.Remove("_id = :param1 AND title = :param2"); data1 = remData.Bind("param1", 5).Bind("param2", "Book 5").Execute(); - Assert.AreEqual(1, (int)data1.AffectedItemsCount, "Matching the deleted record count"); + Assert.That((int)data1.AffectedItemsCount, Is.EqualTo(1), "Matching the deleted record count"); data1 = remData.Bind("param1", 6).Bind("param2", "Book 6").Execute(); - Assert.AreEqual(1, (int)data1.AffectedItemsCount, "Matching the deleted record count"); + Assert.That((int)data1.AffectedItemsCount, Is.EqualTo(1), "Matching the deleted record count"); db.DropCollection("my_collection_123456789"); } @@ -806,20 +806,20 @@ public void AllowReuseStatementAfterExecutePositive2() new { _id = 8, title = "Book 8", pages = 80 }, }; Result result = col.Add(data).Execute(); - Assert.AreEqual(8, (int)result.AffectedItemsCount, "Matching the added record count"); + Assert.That((int)result.AffectedItemsCount, Is.EqualTo(8), "Matching the added record count"); var data1 = col.Remove("_id=1").Execute(); - Assert.AreEqual(1, (int)data1.AffectedItemsCount, "Matching the deleted record count"); + Assert.That((int)data1.AffectedItemsCount, Is.EqualTo(1), "Matching the deleted record count"); data1 = col.Remove("pages = :Pages").Bind("pAges", 80).Execute(); - Assert.AreEqual(1, (int)data1.AffectedItemsCount, "Matching the deleted record count"); + Assert.That((int)data1.AffectedItemsCount, Is.EqualTo(1), "Matching the deleted record count"); data1 = col.Remove("pages = :Pages").Bind("pAges", 70).Execute(); - Assert.AreEqual(1, (int)data1.AffectedItemsCount, "Matching the deleted record count"); + Assert.That((int)data1.AffectedItemsCount, Is.EqualTo(1), "Matching the deleted record count"); var remData = col.Remove("_id = :param1 AND title = :param2"); data1 = remData.Bind("param1", 35).Bind("param2", "Book 33").Execute(); - Assert.AreEqual(0, (int)data1.AffectedItemsCount, "Matching the deleted record count"); + Assert.That((int)data1.AffectedItemsCount, Is.EqualTo(0), "Matching the deleted record count"); data1 = remData.Bind("param1", 6).Bind("param2", "Book 6").Execute(); - Assert.AreEqual(1, (int)data1.AffectedItemsCount, "Matching the deleted record count"); + Assert.That((int)data1.AffectedItemsCount, Is.EqualTo(1), "Matching the deleted record count"); testSchema.DropCollection("my_collection_123456789"); } @@ -834,7 +834,7 @@ public void CollectionGetDocumentID() }; Result result = coll.Add(docs).Execute(); var documentIds = result.GeneratedIds; - Assert.False(documentIds != null && documentIds.Count > 0); + Assert.That(documentIds != null && documentIds.Count > 0, Is.False); coll = CreateCollection("test"); var docs1 = new[] @@ -849,7 +849,7 @@ public void CollectionGetDocumentID() { if (documentIds1 != null) { - Assert.AreEqual(documentIds1[i].ToString(), documentIds1[i].ToString(), "Matching the document ID with unique id"); + Assert.That(documentIds1[i].ToString(), Is.EqualTo(documentIds1[i].ToString()), "Matching the document ID with unique id"); } if (!firstset.Add(documentIds1[i])) { @@ -868,7 +868,7 @@ public void CollectionGetDocumentID() var r1 = coll.Add(docs).Execute(); documentIds = r1.GeneratedIds; - Assert.False(documentIds != null && documentIds.Count > 0); + Assert.That(documentIds != null && documentIds.Count > 0, Is.False); coll = CreateCollection("test"); docs1 = new[] @@ -887,7 +887,7 @@ public void CollectionGetDocumentID() { if (documentIds != null) { - Assert.AreEqual(documentIds1[i].ToString(), documentIds1[i].ToString(), "Matching the document ID with unique id"); + Assert.That(documentIds1[i].ToString(), Is.EqualTo(documentIds1[i].ToString()), "Matching the document ID with unique id"); } if (!firstset.Add(documentIds1[i])) @@ -910,7 +910,7 @@ public void CheckDocUUIDScenario1() }; Result result = col.Add(data).Execute(); var documentIds = result.GeneratedIds; - Assert.False(documentIds != null && documentIds.Count > 0); + Assert.That(documentIds != null && documentIds.Count > 0, Is.False); } [Test, Description("Test MySQLX UUID Scenario-2(Check UUID generated when multiple JSON docs are added using collection.add().add()..without _id fields)")] @@ -941,7 +941,7 @@ public void CheckDocUUIDScenario2() { if (documentIds != null) { - Assert.AreEqual(documentIds[i].ToString(), documentIds[i].ToString(), "Matching the document ID with unique id"); + Assert.That(documentIds[i].ToString(), Is.EqualTo(documentIds[i].ToString()), "Matching the document ID with unique id"); } if (!firstset.Add(documentIds[i])) { @@ -959,19 +959,19 @@ public void CheckDocUUIDScenario3() var stmt = col.Add(@"{ ""foo"": 1 }", @"{""foo"": 2 }", @"{ ""foo"": 3 }", @"{ ""foo"": 4 }"); Result r = col.Add(@"{ ""foo"": 1 }", @"{""foo"": 2 }", @"{ ""foo"": 3 }", @"{ ""foo"": 4 }").Execute(); long count = col.Count(); - Assert.AreEqual(count, 4, "Matching the Collection Count"); + Assert.That(4, Is.EqualTo(count), "Matching the Collection Count"); var documentIds = r.GeneratedIds; if (documentIds != null) { - Assert.AreEqual(documentIds[0].ToString(), documentIds[0].ToString(), "Matching the document ID without unique id"); - Assert.AreEqual(documentIds[1].ToString(), documentIds[1].ToString(), "Matching the document ID without unique id"); - Assert.AreEqual(documentIds[2].ToString(), documentIds[2].ToString(), "Matching the document ID without unique id"); - Assert.AreEqual(documentIds[3].ToString(), documentIds[3].ToString(), "Matching the document ID without unique id"); + Assert.That(documentIds[0].ToString(), Is.EqualTo(documentIds[0].ToString()), "Matching the document ID without unique id"); + Assert.That(documentIds[1].ToString(), Is.EqualTo(documentIds[1].ToString()), "Matching the document ID without unique id"); + Assert.That(documentIds[2].ToString(), Is.EqualTo(documentIds[2].ToString()), "Matching the document ID without unique id"); + Assert.That(documentIds[3].ToString(), Is.EqualTo(documentIds[3].ToString()), "Matching the document ID without unique id"); } var collectionName = col.Name; - Assert.AreEqual(collectionName, "my_collection_123456789", "Matching the collection Name"); - Assert.AreEqual(schemaName, col.Schema.Name, "Matching the Schema Name"); + Assert.That("my_collection_123456789", Is.EqualTo(collectionName), "Matching the collection Name"); + Assert.That(col.Schema.Name, Is.EqualTo(schemaName), "Matching the Schema Name"); } [Test, Description("Test MySQLX UUID Scenario-4(Check UUID generated when multiple JSON docs are added using some containing and some not containing _id fields)")] @@ -999,13 +999,13 @@ public void CheckDocUUIDScenario4() Result result = stmt.Execute(); var documentIdsCount = result.GeneratedIds.Count; var documentIds = result.GeneratedIds; - Assert.AreEqual(4, documentIdsCount, "Matching the document ID count"); + Assert.That(documentIdsCount, Is.EqualTo(4), "Matching the document ID count"); if (documentIds != null) { - Assert.AreEqual(documentIds[0].ToString(), documentIds[0].ToString(), "Matching the document ID with unique id"); - Assert.AreEqual(documentIds[1].ToString(), documentIds[1].ToString(), "Matching the document ID with unique id"); - Assert.AreEqual(documentIds[2].ToString(), documentIds[2].ToString(), "Matching the document ID with unique id"); - Assert.AreEqual(documentIds[3].ToString(), documentIds[3].ToString(), "Matching the document ID without unique id"); + Assert.That(documentIds[0].ToString(), Is.EqualTo(documentIds[0].ToString()), "Matching the document ID with unique id"); + Assert.That(documentIds[1].ToString(), Is.EqualTo(documentIds[1].ToString()), "Matching the document ID with unique id"); + Assert.That(documentIds[2].ToString(), Is.EqualTo(documentIds[2].ToString()), "Matching the document ID with unique id"); + Assert.That(documentIds[3].ToString(), Is.EqualTo(documentIds[3].ToString()), "Matching the document ID without unique id"); } } @@ -1025,13 +1025,13 @@ public void CheckDocUUIDScenario5() newDoc2 = null; } Result r = testCollection.Add(jsonlist).Execute(); - Assert.AreEqual(1000, r.AffectedItemsCount, "Matching"); + Assert.That(r.AffectedItemsCount, Is.EqualTo(1000), "Matching"); var documentIds = r.GeneratedIds; - Assert.False(documentIds != null && documentIds.Count > 0); + Assert.That(documentIds != null && documentIds.Count > 0, Is.False); Schema testSchema = session.GetSchema(schemaName); Table test = testSchema.GetCollectionAsTable("test"); - Assert.AreEqual(true, test.ExistsInDatabase(), "Matching"); + Assert.That(test.ExistsInDatabase(), Is.EqualTo(true), "Matching"); } [Test, Description("Test MySQLX UUID Scenario-6(Check that no duplicate UUID is generated by adding multiple doc from the same collection in a session when there are no _id fields)")] @@ -1053,16 +1053,16 @@ public void CheckDocUUIDScenario6() var r = testCollection.Add(jsonlist); var result = r.Execute(); var countgenerateIDs = result.GeneratedIds.Count; - Assert.AreEqual(1000, countgenerateIDs, "Count of the ID generated by the server"); + Assert.That(countgenerateIDs, Is.EqualTo(1000), "Count of the ID generated by the server"); for (int i = 0; i < countgenerateIDs; i++) { var generatedIDs1 = result.GeneratedIds[i]; - Assert.AreEqual(generatedIDs1, generatedIDs1, "ID generated by the server"); + Assert.That(generatedIDs1, Is.EqualTo(generatedIDs1), "ID generated by the server"); } Schema testSchema = session.GetSchema(schemaName); Table test = testSchema.GetCollectionAsTable("test"); - Assert.AreEqual(true, test.ExistsInDatabase(), "Matching"); + Assert.That(test.ExistsInDatabase(), Is.EqualTo(true), "Matching"); } [Test, Description("Test MySQLX UUID Scenario-7(Check UUID generated when multiple JSON docs are added using collection.add(doc, doc, doc... ) when docs contains _id fields with negative numbers,big positive numbers)")] @@ -1088,11 +1088,11 @@ public void CheckDocUUIDScenario7() var r = col.Add(data1).Add(data2); var result = r.Execute(); var countgenerateIDs = result.GeneratedIds.Count; - Assert.AreEqual(4, countgenerateIDs, "Count of the ID generated by the server"); + Assert.That(countgenerateIDs, Is.EqualTo(4), "Count of the ID generated by the server"); for (int i = 0; i < countgenerateIDs; i++) { var generatedIDs1 = result.GeneratedIds[i]; - Assert.AreEqual(generatedIDs1, generatedIDs1, "ID generated by the server"); + Assert.That(generatedIDs1, Is.EqualTo(generatedIDs1), "ID generated by the server"); } } @@ -1121,11 +1121,11 @@ public void CheckDocUUIDScenario8() var r = col.Add(data1).Add(data2); var result = r.Execute(); var countgenerateIDs = result.GeneratedIds.Count; - Assert.AreEqual(4, countgenerateIDs, "Count of the ID generated by the server"); + Assert.That(countgenerateIDs, Is.EqualTo(4), "Count of the ID generated by the server"); for (int i = 0; i < countgenerateIDs; i++) { var generatedIDs1 = result.GeneratedIds[i]; - Assert.AreEqual(generatedIDs1, generatedIDs1, "ID generated by the server"); + Assert.That(generatedIDs1, Is.EqualTo(generatedIDs1), "ID generated by the server"); } } @@ -1147,11 +1147,11 @@ public void CheckDocUUIDScenario9() Result result = testCollection.Add(jsonlist).Execute(); //ID with blank could be added as per bug#27627861 as client will not do any validation and server will do" - Assert.IsNotNull(result); + Assert.That(result, Is.Not.Null); Schema testSchema = session.GetSchema("test"); Table test = testSchema.GetCollectionAsTable("test"); - Assert.AreEqual(true, test.ExistsInDatabase(), "Matching"); + Assert.That(test.ExistsInDatabase(), Is.EqualTo(true), "Matching"); } [Test, Description("Test MySQLX plugin Collection JSON Depth Scenarios")] @@ -1170,7 +1170,7 @@ public void CollectionAddJSONDepth() } var result = col1.Add(d1).Execute(); - Assert.Greater(result.AffectedItemsCount, 0); + Assert.That(result.AffectedItemsCount, Is.GreaterThan(0)); var data1 = new DbDoc(@"{ ""_id"": 1, ""pages"": 20, ""person"": { ""name"": ""Fred"", ""age"": 45 } @@ -1188,12 +1188,12 @@ public void CollectionAddJSONDepth() d2.SetValue("taker2", data2); result = col.Add(d2).Execute(); - Assert.Greater(result.AffectedItemsCount, 0); + Assert.That(result.AffectedItemsCount, Is.GreaterThan(0)); var result1 = col1.Find().Execute().FetchAll(); - Assert.AreEqual(1, result1.Count); + Assert.That(result1.Count, Is.EqualTo(1)); var result2 = col.Find().Execute().FetchAll(); - Assert.AreEqual(1, result2.Count); + Assert.That(result2.Count, Is.EqualTo(1)); } [Test, Description("Test MySQLX plugin Collection Add function with null")] @@ -1204,12 +1204,12 @@ public void CollectionAddNullFind() Collection col = CreateCollection("my_collection_1"); var d1 = new DbDoc(); d1.SetValue("id" + "_" + i.ToString(), "test"); - Assert.AreEqual(1, col.Add(d1).Execute().AffectedItemsCount); + Assert.That(col.Add(d1).Execute().AffectedItemsCount, Is.EqualTo(1)); var result1 = col.Find(null).Execute(); - Assert.AreEqual(0, result1.AffectedItemsCount); + Assert.That(result1.AffectedItemsCount, Is.EqualTo(0)); Assert.Throws(() => col.Add(null).Execute()); var result2 = col.Add().Execute(); - Assert.AreEqual(0, result2.AffectedItemsCount); + Assert.That(result2.AffectedItemsCount, Is.EqualTo(0)); } [Test, Description("Test MySQLX plugin Invalid JSON String")] @@ -1219,7 +1219,7 @@ public void InvalidJSONString() String json = ""; json = "{'_id':'1004','F1': [] }"; Exception ex = Assert.Throws(() => col.Add(json).Execute()); - StringAssert.Contains("The value provided is not a valid JSON document", ex.Message); + Assert.That(ex.Message, Does.Contain("The value provided is not a valid JSON document")); } [Test, Description("Test MySQLX plugin JSON String long expression")] @@ -1246,7 +1246,7 @@ public void JSONStringLongExpression() var docs = col.Find().Fields(("{'X':" + query2 + "}")).Execute(); var res = col.Modify("$.F1 = 1234").Set("F1", query2).Limit(1).Execute(); - Assert.AreEqual(1, res.AffectedItemsCount); + Assert.That(res.AffectedItemsCount, Is.EqualTo(1)); } [Test, Description("Test MySQLX plugin Binary Expression")] @@ -1260,18 +1260,18 @@ public void BinaryExpression() var docs1 = col.Find().Fields("$._id as _id", "1 << 4 as tmp").Execute(); var res = docs1.FetchAll(); - StringAssert.AreEqualIgnoringCase("1004", res[0].Id.ToString()); + Assert.That(res[0].Id.ToString(), Is.EqualTo("1004").IgnoreCase); docs1 = col.Find().Fields("$._id as _id", "$.F2 ^ 1 as tmp").Execute(); res = docs1.FetchAll(); - StringAssert.AreEqualIgnoringCase("1004", res[0].Id.ToString()); + Assert.That(res[0].Id.ToString(), Is.EqualTo("1004").IgnoreCase); col.Add("{\"_id\":\"100001\",\"x1\":\"31\", \"x2\":\"13\", \"x3\":\"8\", \"x4\":\"18446744073709551614\"}").Execute(); docs1 = col.Find("CAST($.x1 as SIGNED) | pow(2,$.x1) = $.x1").Fields("$._id as _id, $.x1 as x1, $.x2 as x2, $.x3 as x3 , $.x2 | pow(2,$.x1) as tmp").Execute(); res = docs1.FetchAll(); - Assert.IsNotNull(res); + Assert.That(res, Is.Not.Null); docs1 = col.Find("~16 = ~CAST($.F2 as SIGNED)").Fields("$._id as _id,$.F2 as f2, ~1 as tmp").Execute(); res = docs1.FetchAll(); - Assert.IsNotNull(res); + Assert.That(res, Is.Not.Null); int maxrec = 100; DbDoc newDoc = new DbDoc(); newDoc.SetValue("_id", maxrec + 1000); @@ -1283,17 +1283,17 @@ public void BinaryExpression() json = "{'_id':'" + (maxrec + 1000 + 1) + "','F1':'Field-1-Data-" + (maxrec + 1) + "','F2':'Field-2-Data-" + (maxrec + 1) + "','F3':" + (300 + maxrec + 1) + "}"; json = json.Replace("'", "\""); var res1 = col1.Add(json).Execute(); - Assert.AreEqual(1, res1.AffectedItemsCount); + Assert.That(res1.AffectedItemsCount, Is.EqualTo(1)); json = "{'F1': 'Field-1-Data-9999','F2': 'Field-2-Data-9999','F3': 'Field-3-Data-9999'}".Replace("'", "\""); col1.Add(json).Add(json.Replace("9", "8")).Execute(); - Assert.AreEqual(1, res1.AffectedItemsCount); + Assert.That(res1.AffectedItemsCount, Is.EqualTo(1)); var docs = col1.Find("$._id = 1100").Fields("$_id as _id,$.F1 as f1, $.F2 as f2, $.F3 as f3").Execute(); var res2 = docs.FetchOne(); - Assert.AreEqual("1100", res2["_id"].ToString()); - Assert.AreEqual("Field-1-Data-100", res2["f1"].ToString()); - Assert.AreEqual("Field-2-Data-100", res2["f2"].ToString()); - Assert.AreEqual("400", res2["f3"].ToString()); + Assert.That(res2["_id"].ToString(), Is.EqualTo("1100")); + Assert.That(res2["f1"].ToString(), Is.EqualTo("Field-1-Data-100")); + Assert.That(res2["f2"].ToString(), Is.EqualTo("Field-2-Data-100")); + Assert.That(res2["f3"].ToString(), Is.EqualTo("400")); } @@ -1310,11 +1310,11 @@ public void JSONStringSpecialCharacters() col.Add("{\"" + splName[i] + "\":\"data" + i + "\",\"ID\":" + i + "}").Execute(); var docs = col.Find("$.ID = " + i).Fields("$.`" + splName[i] + "` as col1,$.ID as Id").Execute(); var res = docs.FetchOne(); - Assert.AreEqual(i.ToString(), res["Id"].ToString(), "Matching the ID"); + Assert.That(res["Id"].ToString(), Is.EqualTo(i.ToString()), "Matching the ID"); if (i == 30) - Assert.AreEqual("data" + i, "data30", "Matching the String"); + Assert.That("data30", Is.EqualTo("data" + i), "Matching the String"); else - Assert.AreEqual("data" + i, res["col1"].ToString(), "Matching the String"); + Assert.That(res["col1"].ToString(), Is.EqualTo("data" + i), "Matching the String"); } } @@ -1360,13 +1360,13 @@ public void CollectionsChainedInsert() } var tabRes = col.Add(newDoc).Add(newDoc1).Execute(); - Assert.AreEqual(2, tabRes.AffectedItemsCount, "Matching the affected records"); + Assert.That(tabRes.AffectedItemsCount, Is.EqualTo(2), "Matching the affected records"); tabRes = col.Add(jsonlist).Add(newDoc2).Execute(); - Assert.AreEqual(6, tabRes.AffectedItemsCount, "Matching the affected records"); + Assert.That(tabRes.AffectedItemsCount, Is.EqualTo(6), "Matching the affected records"); tabRes = col.Add(jsonlist1).Add(jsonlist2).Execute(); - Assert.AreEqual(10, tabRes.AffectedItemsCount, "Matching the affected records"); + Assert.That(tabRes.AffectedItemsCount, Is.EqualTo(10), "Matching the affected records"); } [Test, Description("Test MySQLX plugin Collection Add Array")] @@ -1393,7 +1393,7 @@ public void CollectionAddArray() jsonlist = null; var res = col.Find().Execute().FetchAll(); - Assert.AreEqual(5, res.Count, "Matching the find count"); + Assert.That(res.Count, Is.EqualTo(5), "Matching the find count"); } [Test, Description("Test MySQLX plugin Collection JSON Scenarios")] @@ -1406,9 +1406,9 @@ public void CollectionAddJSONDocs() string json = @"{ ""_id"": 0, ""title"": ""Book 0"" ,""pages"": 10,""name"": ""Jeoff Archer""}"; Result r = col.Add(json).Execute(); - Assert.AreEqual(1, (int)r.AffectedItemsCount, "Matching Affected Records Count"); + Assert.That((int)r.AffectedItemsCount, Is.EqualTo(1), "Matching Affected Records Count"); var foundDocs = col.Find("pages > 5").Execute(); - Assert.AreEqual(1, foundDocs.Count(), "Matching Count"); + Assert.That(foundDocs.Count(), Is.EqualTo(1), "Matching Count"); json = @"{ ""_id"" : 99950, ""city"" : ""KETCHIKAN"", ""loc"" : ""[ -133.18479, 55.942471 ]"", ""pop"" : 422, ""state"" : ""AK"" }"; r = col.Add(json).Execute(); @@ -1421,7 +1421,7 @@ public void CollectionAddJSONDocs() d2.SetValue("pages", 20); d2.SetValue("person", new { name = "Fred", age = 45 }); - Assert.AreEqual(d.Equals(d2), true, "Matching"); + Assert.That(true, Is.EqualTo(d.Equals(d2)), "Matching"); col.Add(d).Execute(); d = new DbDoc(@"{""id"":100,""FirstName"":""xyz"",""lastname"":""pqr"", @@ -1453,14 +1453,14 @@ public void CollectionAddJSONDocs() var result = col.Find("$._id = 0").Fields("$._id as _id,$.name as name, $.pages as pages, $.title as title").Execute(); var res1 = result.FetchOne(); - Assert.AreEqual(0, res1["_id"]); - Assert.AreEqual("Jeoff Archer", res1["name"]); - Assert.AreEqual(10, res1["pages"]); - Assert.AreEqual("Book 0", res1["title"]); + Assert.That(res1["_id"], Is.EqualTo(0)); + Assert.That(res1["name"], Is.EqualTo("Jeoff Archer")); + Assert.That(res1["pages"], Is.EqualTo(10)); + Assert.That(res1["title"], Is.EqualTo("Book 0")); result = col.Find("$._id > 0").Fields().Execute(); var res2 = result.FetchAll(); - Assert.AreEqual(6, res2.Count()); + Assert.That(res2.Count(), Is.EqualTo(6)); DbDoc test = new DbDoc(); test.SetValue("_id", 1); @@ -1469,7 +1469,7 @@ public void CollectionAddJSONDocs() var res = coll.Add(test).Execute(); foundDocs = coll.Find().Execute(); var docs1 = foundDocs.FetchAll(); - Assert.AreEqual(1, docs1.Count); + Assert.That(docs1.Count, Is.EqualTo(1)); } [Test, Description("Verify that the field and column _id has a value when it's not given to a document-Scenario-1(single document add)")] @@ -1486,10 +1486,10 @@ public void VerifyIDField() var stmt = col.Add(data); result = stmt.Execute(); generatedIDs1 = result.GeneratedIds[0]; - Assert.AreEqual(generatedIDs1, generatedIDs1, "ID generated by the server"); + Assert.That(generatedIDs1, Is.EqualTo(generatedIDs1), "ID generated by the server"); VerifyGeneratedID(generatedIDs1); countgenerateIDs = result.GeneratedIds.Count; - Assert.AreEqual(1, countgenerateIDs, "Count of the ID generated by the server"); + Assert.That(countgenerateIDs, Is.EqualTo(1), "Count of the ID generated by the server"); for (int i = 0; i < countgenerateIDs; i++) { idStringList.Add(result.GeneratedIds[i]); @@ -1502,10 +1502,10 @@ public void VerifyIDField() stmt = col.Add(DbDocs); result = stmt.Execute(); generatedIDs2 = result.GeneratedIds[0]; - Assert.AreEqual(generatedIDs2, generatedIDs2, "ID generated by the server"); + Assert.That(generatedIDs2, Is.EqualTo(generatedIDs2), "ID generated by the server"); VerifyGeneratedID(generatedIDs2); countgenerateIDs = result.GeneratedIds.Count; - Assert.AreEqual(1, countgenerateIDs, "Count of the ID generated by the server"); + Assert.That(countgenerateIDs, Is.EqualTo(1), "Count of the ID generated by the server"); for (int i = 0; i < countgenerateIDs; i++) { idStringList.Add(result.GeneratedIds[i]); @@ -1516,10 +1516,10 @@ public void VerifyIDField() stmt = col.Add(docs); result = stmt.Execute(); generatedIDs1 = result.GeneratedIds[0]; - Assert.AreEqual(generatedIDs1, generatedIDs1, "ID generated by the server"); + Assert.That(generatedIDs1, Is.EqualTo(generatedIDs1), "ID generated by the server"); VerifyGeneratedID(generatedIDs1); countgenerateIDs = result.GeneratedIds.Count; - Assert.AreEqual(1, countgenerateIDs, "Count of the ID generated by the server"); + Assert.That(countgenerateIDs, Is.EqualTo(1), "Count of the ID generated by the server"); for (int i = 0; i < countgenerateIDs; i++) { idStringList.Add(result.GeneratedIds[i]); @@ -1529,10 +1529,10 @@ public void VerifyIDField() stmt = col.Add("{ \"foo\": 100 }"); result = stmt.Execute(); generatedIDs2 = result.GeneratedIds[0]; - Assert.AreEqual(generatedIDs2, generatedIDs2, "ID generated by the server"); + Assert.That(generatedIDs2, Is.EqualTo(generatedIDs2), "ID generated by the server"); VerifyGeneratedID(generatedIDs2); countgenerateIDs = result.GeneratedIds.Count; - Assert.AreEqual(1, countgenerateIDs, "Count of the ID generated by the server"); + Assert.That(countgenerateIDs, Is.EqualTo(1), "Count of the ID generated by the server"); for (int i = 0; i < countgenerateIDs; i++) { idStringList.Add(result.GeneratedIds[i]); @@ -1572,13 +1572,13 @@ public void VerifyIDFieldScenario3() var stmt = col.Add(data1); result = stmt.Execute(); countgenerateIDs = result.GeneratedIds.Count; - Assert.AreEqual(4, countgenerateIDs, "Count of the ID generated by the server"); + Assert.That(countgenerateIDs, Is.EqualTo(4), "Count of the ID generated by the server"); for (int i = 0; i < countgenerateIDs; i++) { generatedIDs1 = result.GeneratedIds[i]; - Assert.AreEqual(generatedIDs1, generatedIDs1, "ID generated by the server"); + Assert.That(generatedIDs1, Is.EqualTo(generatedIDs1), "ID generated by the server"); VerifyGeneratedID(generatedIDs1); - Assert.False(!firstset.Add(generatedIDs1)); + Assert.That(!firstset.Add(generatedIDs1), Is.False); } for (int i = 0; i < countgenerateIDs; i++) @@ -1589,13 +1589,13 @@ public void VerifyIDFieldScenario3() stmt = col.Add(@"{ ""foo"": 1 }", @"{""foo"": 2 }", @"{ ""foo"": 3 }", @"{ ""foo"": 4 }"); result = stmt.Execute(); countgenerateIDs = result.GeneratedIds.Count; - Assert.AreEqual(4, countgenerateIDs, "Count of the ID generated by the server"); + Assert.That(countgenerateIDs, Is.EqualTo(4), "Count of the ID generated by the server"); for (int i = 0; i < countgenerateIDs; i++) { generatedIDs1 = result.GeneratedIds[i]; - Assert.AreEqual(generatedIDs1, generatedIDs1, "ID generated by the server"); + Assert.That(generatedIDs1, Is.EqualTo(generatedIDs1), "ID generated by the server"); VerifyGeneratedID(generatedIDs1); - Assert.False(!firstset.Add(generatedIDs1)); + Assert.That(!firstset.Add(generatedIDs1), Is.False); } for (int i = 0; i < countgenerateIDs; i++) @@ -1633,7 +1633,7 @@ public void VerifyIDFieldScenario4() result = col.Add(data).Execute(); countgenerateIDs = result.GeneratedIds.Count; generatedIDs1 = result.GeneratedIds[0]; - Assert.AreEqual(1, countgenerateIDs, "Count of the ID generated by the server"); + Assert.That(countgenerateIDs, Is.EqualTo(1), "Count of the ID generated by the server"); for (int i = 0; i < countgenerateIDs; i++) { idStringList.Add(result.GeneratedIds[i]); @@ -1644,10 +1644,10 @@ public void VerifyIDFieldScenario4() var stmt = col.Add(data); result = stmt.Execute(); generatedIDs1 = result.GeneratedIds[0]; - Assert.AreEqual(generatedIDs1, generatedIDs1, "ID generated by the server"); + Assert.That(generatedIDs1, Is.EqualTo(generatedIDs1), "ID generated by the server"); VerifyGeneratedID(generatedIDs1); countgenerateIDs = result.GeneratedIds.Count; - Assert.AreEqual(1, countgenerateIDs, "Count of the ID generated by the server"); + Assert.That(countgenerateIDs, Is.EqualTo(1), "Count of the ID generated by the server"); for (int i = 0; i < countgenerateIDs; i++) { idStringList.Add(result.GeneratedIds[i]); @@ -1663,7 +1663,7 @@ public void VerifyIDFieldScenario4() result = col.Add(data).Execute(); countgenerateIDs = result.GeneratedIds.Count; generatedIDs1 = result.GeneratedIds[0]; - Assert.AreEqual(1, countgenerateIDs, "Count of the ID generated by the server"); + Assert.That(countgenerateIDs, Is.EqualTo(1), "Count of the ID generated by the server"); for (int i = 0; i < countgenerateIDs; i++) { idStringList.Add(result.GeneratedIds[i]); @@ -1676,10 +1676,10 @@ public void VerifyIDFieldScenario4() stmt = col.Add(DbDocs); result = stmt.Execute(); generatedIDs2 = result.GeneratedIds[0]; - Assert.AreEqual(generatedIDs2, generatedIDs2, "ID generated by the server"); + Assert.That(generatedIDs2, Is.EqualTo(generatedIDs2), "ID generated by the server"); VerifyGeneratedID(generatedIDs2); countgenerateIDs = result.GeneratedIds.Count; - Assert.AreEqual(1, countgenerateIDs, "Count of the ID generated by the server"); + Assert.That(countgenerateIDs, Is.EqualTo(1), "Count of the ID generated by the server"); for (int i = 0; i < countgenerateIDs; i++) { idStringList.Add(result.GeneratedIds[i]); @@ -1695,7 +1695,7 @@ public void VerifyIDFieldScenario4() result = col.Add(data).Execute(); countgenerateIDs = result.GeneratedIds.Count; generatedIDs1 = result.GeneratedIds[0]; - Assert.AreEqual(1, countgenerateIDs, "Count of the ID generated by the server"); + Assert.That(countgenerateIDs, Is.EqualTo(1), "Count of the ID generated by the server"); for (int i = 0; i < countgenerateIDs; i++) { idStringList.Add(result.GeneratedIds[i]); @@ -1706,10 +1706,10 @@ public void VerifyIDFieldScenario4() stmt = col.Add(docs); result = stmt.Execute(); generatedIDs1 = result.GeneratedIds[0]; - Assert.AreEqual(generatedIDs1, generatedIDs1, "ID generated by the server"); + Assert.That(generatedIDs1, Is.EqualTo(generatedIDs1), "ID generated by the server"); VerifyGeneratedID(generatedIDs1); countgenerateIDs = result.GeneratedIds.Count; - Assert.AreEqual(1, countgenerateIDs, "Count of the ID generated by the server"); + Assert.That(countgenerateIDs, Is.EqualTo(1), "Count of the ID generated by the server"); for (int i = 0; i < countgenerateIDs; i++) { idStringList.Add(result.GeneratedIds[i]); @@ -1725,7 +1725,7 @@ public void VerifyIDFieldScenario4() result = col.Add(data).Execute(); countgenerateIDs = result.GeneratedIds.Count; generatedIDs1 = result.GeneratedIds[0]; - Assert.AreEqual(1, countgenerateIDs, "Count of the ID generated by the server"); + Assert.That(countgenerateIDs, Is.EqualTo(1), "Count of the ID generated by the server"); for (int i = 0; i < countgenerateIDs; i++) { idStringList.Add(result.GeneratedIds[i]); @@ -1735,10 +1735,10 @@ public void VerifyIDFieldScenario4() stmt = col.Add("{ \"foo\": 100 }"); result = stmt.Execute(); generatedIDs2 = result.GeneratedIds[0]; - Assert.AreEqual(generatedIDs2, generatedIDs2, "ID generated by the server"); + Assert.That(generatedIDs2, Is.EqualTo(generatedIDs2), "ID generated by the server"); VerifyGeneratedID(generatedIDs2); countgenerateIDs = result.GeneratedIds.Count; - Assert.AreEqual(1, countgenerateIDs, "Count of the ID generated by the server"); + Assert.That(countgenerateIDs, Is.EqualTo(1), "Count of the ID generated by the server"); for (int i = 0; i < countgenerateIDs; i++) { idStringList.Add(result.GeneratedIds[i]); @@ -1775,7 +1775,7 @@ public void VerifyIDFieldScenario5() result = col.Add(data).Execute(); countgenerateIDs = result.GeneratedIds.Count; generatedIDs1 = result.GeneratedIds[0]; - Assert.AreEqual(1, countgenerateIDs, "Count of the ID generated by the server"); + Assert.That(countgenerateIDs, Is.EqualTo(1), "Count of the ID generated by the server"); for (int i = 0; i < countgenerateIDs; i++) { idStringList.Add(result.GeneratedIds[i]); @@ -1790,13 +1790,13 @@ public void VerifyIDFieldScenario5() var stmt = col.Add(data1).Add(data2); result = stmt.Execute(); countgenerateIDs = result.GeneratedIds.Count; - Assert.AreEqual(2, countgenerateIDs, "Count of the ID generated by the server"); + Assert.That(countgenerateIDs, Is.EqualTo(2), "Count of the ID generated by the server"); for (int i = 0; i < countgenerateIDs; i++) { generatedIDs1 = result.GeneratedIds[i]; - Assert.AreEqual(generatedIDs1, generatedIDs1, "ID generated by the server"); + Assert.That(generatedIDs1, Is.EqualTo(generatedIDs1), "ID generated by the server"); VerifyGeneratedID(generatedIDs1); - Assert.False(!firstset.Add(generatedIDs1)); + Assert.That(!firstset.Add(generatedIDs1), Is.False); } for (int i = 0; i < countgenerateIDs; i++) { @@ -1812,7 +1812,7 @@ public void VerifyIDFieldScenario5() result = col.Add(data).Execute(); countgenerateIDs = result.GeneratedIds.Count; generatedIDs1 = result.GeneratedIds[0]; - Assert.AreEqual(1, countgenerateIDs, "Count of the ID generated by the server"); + Assert.That(countgenerateIDs, Is.EqualTo(1), "Count of the ID generated by the server"); for (int i = 0; i < countgenerateIDs; i++) { idStringList.Add(result.GeneratedIds[i]); @@ -1828,13 +1828,13 @@ public void VerifyIDFieldScenario5() stmt = col.Add(DbDocs1).Add(DbDocs2); result = stmt.Execute(); countgenerateIDs = result.GeneratedIds.Count; - Assert.AreEqual(2, countgenerateIDs, "Count of the ID generated by the server"); + Assert.That(countgenerateIDs, Is.EqualTo(2), "Count of the ID generated by the server"); for (int i = 0; i < countgenerateIDs; i++) { generatedIDs1 = result.GeneratedIds[i]; - Assert.AreEqual(generatedIDs1, generatedIDs1, "ID generated by the server"); + Assert.That(generatedIDs1, Is.EqualTo(generatedIDs1), "ID generated by the server"); VerifyGeneratedID(generatedIDs1); - Assert.False(!firstset.Add(generatedIDs1)); + Assert.That(!firstset.Add(generatedIDs1), Is.False); } for (int i = 0; i < countgenerateIDs; i++) { @@ -1851,7 +1851,7 @@ public void VerifyIDFieldScenario5() result = col.Add(data).Execute(); countgenerateIDs = result.GeneratedIds.Count; generatedIDs1 = result.GeneratedIds[0]; - Assert.AreEqual(1, countgenerateIDs, "Count of the ID generated by the server"); + Assert.That(countgenerateIDs, Is.EqualTo(1), "Count of the ID generated by the server"); for (int i = 0; i < countgenerateIDs; i++) { idStringList.Add(result.GeneratedIds[i]); @@ -1864,13 +1864,13 @@ public void VerifyIDFieldScenario5() result = stmt.Execute(); countgenerateIDs = result.GeneratedIds.Count; - Assert.AreEqual(2, countgenerateIDs, "Count of the ID generated by the server"); + Assert.That(countgenerateIDs, Is.EqualTo(2), "Count of the ID generated by the server"); for (int i = 0; i < countgenerateIDs; i++) { generatedIDs1 = result.GeneratedIds[i]; - Assert.AreEqual(generatedIDs1, generatedIDs1, "ID generated by the server"); + Assert.That(generatedIDs1, Is.EqualTo(generatedIDs1), "ID generated by the server"); VerifyGeneratedID(generatedIDs1); - Assert.False(!firstset.Add(generatedIDs1)); + Assert.That(!firstset.Add(generatedIDs1), Is.False); } for (int i = 0; i < countgenerateIDs; i++) { @@ -1886,7 +1886,7 @@ public void VerifyIDFieldScenario5() result = col.Add(data).Execute(); countgenerateIDs = result.GeneratedIds.Count; generatedIDs1 = result.GeneratedIds[0]; - Assert.AreEqual(1, countgenerateIDs, "Count of the ID generated by the server"); + Assert.That(countgenerateIDs, Is.EqualTo(1), "Count of the ID generated by the server"); for (int i = 0; i < countgenerateIDs; i++) { idStringList.Add(result.GeneratedIds[i]); @@ -1896,11 +1896,11 @@ public void VerifyIDFieldScenario5() stmt = col.Add("{ \"foo1\": 100 }").Add("{ \"foo2\": 200 }"); result = stmt.Execute(); countgenerateIDs = result.GeneratedIds.Count; - Assert.AreEqual(2, countgenerateIDs, "Count of the ID generated by the server"); + Assert.That(countgenerateIDs, Is.EqualTo(2), "Count of the ID generated by the server"); for (int i = 0; i < countgenerateIDs; i++) { generatedIDs1 = result.GeneratedIds[i]; - Assert.AreEqual(generatedIDs1, generatedIDs1, "ID generated by the server"); + Assert.That(generatedIDs1, Is.EqualTo(generatedIDs1), "ID generated by the server"); VerifyGeneratedID(generatedIDs1); if (!firstset.Add(generatedIDs1)) { @@ -1943,7 +1943,7 @@ public void VerifyIDFieldScenario6() result = col.Add(data).Execute(); countgenerateIDs = result.GeneratedIds.Count; generatedIDs1 = result.GeneratedIds[0]; - Assert.AreEqual(1, countgenerateIDs, "Count of the ID generated by the server"); + Assert.That(countgenerateIDs, Is.EqualTo(1), "Count of the ID generated by the server"); for (int i = 0; i < countgenerateIDs; i++) { idStringList.Add(result.GeneratedIds[i]); @@ -1962,13 +1962,13 @@ public void VerifyIDFieldScenario6() var stmt = col.Add(data1); result = stmt.Execute(); countgenerateIDs = result.GeneratedIds.Count; - Assert.AreEqual(4, countgenerateIDs, "Count of the ID generated by the server"); + Assert.That(countgenerateIDs, Is.EqualTo(4), "Count of the ID generated by the server"); for (int i = 0; i < countgenerateIDs; i++) { generatedIDs1 = result.GeneratedIds[i]; - Assert.AreEqual(generatedIDs1, generatedIDs1, "ID generated by the server"); + Assert.That(generatedIDs1, Is.EqualTo(generatedIDs1), "ID generated by the server"); VerifyGeneratedID(generatedIDs1); - Assert.False(!firstset.Add(generatedIDs1)); + Assert.That(!firstset.Add(generatedIDs1), Is.False); } for (int i = 0; i < countgenerateIDs; i++) { @@ -1979,7 +1979,7 @@ public void VerifyIDFieldScenario6() result = col.Add(@"{ ""foo"": 0, ""_id"":0 }", @"{""foo"": 5 }").Execute(); countgenerateIDs = result.GeneratedIds.Count; generatedIDs1 = result.GeneratedIds[0]; - Assert.AreEqual(1, countgenerateIDs, "Count of the ID generated by the server"); + Assert.That(countgenerateIDs, Is.EqualTo(1), "Count of the ID generated by the server"); for (int i = 0; i < countgenerateIDs; i++) { idStringList.Add(result.GeneratedIds[i]); @@ -1989,13 +1989,13 @@ public void VerifyIDFieldScenario6() stmt = col.Add(@"{ ""foo"": 1 }", @"{""foo"": 2 }", @"{ ""foo"": 3 }", @"{ ""foo"": 4 }"); result = stmt.Execute(); countgenerateIDs = result.GeneratedIds.Count; - Assert.AreEqual(4, countgenerateIDs, "Count of the ID generated by the server"); + Assert.That(countgenerateIDs, Is.EqualTo(4), "Count of the ID generated by the server"); for (int i = 0; i < countgenerateIDs; i++) { generatedIDs1 = result.GeneratedIds[i]; - Assert.AreEqual(generatedIDs1, generatedIDs1, "ID generated by the server"); + Assert.That(generatedIDs1, Is.EqualTo(generatedIDs1), "ID generated by the server"); VerifyGeneratedID(generatedIDs1); - Assert.False(!firstset.Add(generatedIDs1)); + Assert.That(!firstset.Add(generatedIDs1), Is.False); } for (int i = 0; i < countgenerateIDs; i++) { @@ -2024,20 +2024,20 @@ public void VerifyIDFieldScenario7() }; Result result = col.Add(data).Execute(); var generatedIDs = result.GeneratedIds; - Assert.AreEqual(0, generatedIDs.Count, "Matches"); + Assert.That(generatedIDs.Count, Is.EqualTo(0), "Matches"); var doc = col.Find("_id like :param").Bind("param", "1e9c92fda74ed311944e00059a3c7a00").Execute(); var docs = doc.FetchAll().Count(); - Assert.AreEqual(1, docs, "Matches"); + Assert.That(docs, Is.EqualTo(1), "Matches"); //Anonymous Object var data1 = new { _id = "1e9c92fda74ed311944e00059a3c7a01", title = "Book 0", pages = 10 }; result = col.Add(data1).Execute(); generatedIDs = result.GeneratedIds; - Assert.AreEqual(0, generatedIDs.Count, "Matches"); + Assert.That(generatedIDs.Count, Is.EqualTo(0), "Matches"); doc = col.Find("_id like :param").Bind("param", "1e9c92fda74ed311944e00059a3c7a01").Execute(); docs = doc.FetchAll().Count(); - Assert.AreEqual(1, docs, "Matches"); + Assert.That(docs, Is.EqualTo(1), "Matches"); // DbDoc DbDoc DbDocs = new DbDoc(); @@ -2047,18 +2047,18 @@ public void VerifyIDFieldScenario7() result = col.Add(DbDocs).Execute(); generatedIDs = result.GeneratedIds; - Assert.AreEqual(0, generatedIDs.Count, "Matches"); + Assert.That(generatedIDs.Count, Is.EqualTo(0), "Matches"); doc = col.Find("_id like :param").Bind("param", "1e9c92fda74ed311944e00059a3c7a02").Execute(); docs = doc.FetchAll().Count(); - Assert.AreEqual(1, docs, "Matches"); + Assert.That(docs, Is.EqualTo(1), "Matches"); //JSON result = col.Add("{\"_id\":\"1e9c92fda74ed311944e00059a3c7a03\",\"title\": \"Book 0\",\"pages\": 10}").Execute(); generatedIDs = result.GeneratedIds; - Assert.AreEqual(0, generatedIDs.Count, "Matches"); + Assert.That(generatedIDs.Count, Is.EqualTo(0), "Matches"); doc = col.Find("_id like :param").Bind("param", "1e9c92fda74ed311944e00059a3c7a03").Execute(); docs = doc.FetchAll().Count(); - Assert.AreEqual(1, docs, "Matches"); + Assert.That(docs, Is.EqualTo(1), "Matches"); } [Test, Description("Client provided _id shouldnt be discarded and generatedids() should give empty list for anonymous object array -multiple documents multiple add with negative number")] @@ -2075,26 +2075,26 @@ public void VerifyIDFieldScenario8() }; Result result = col.Add(data1).Add(data2).Execute(); var generatedIDs = result.GeneratedIds; - Assert.AreEqual(0, generatedIDs.Count, "Matches"); + Assert.That(generatedIDs.Count, Is.EqualTo(0), "Matches"); var doc = col.Find("_id like :param").Bind("param", "1e9c92fda74ed311944e00059a3c7a00").Execute(); var docs = doc.FetchAll().Count(); - Assert.AreEqual(1, docs, "Matches"); + Assert.That(docs, Is.EqualTo(1), "Matches"); doc = col.Find("_id like :param").Bind("param", -1).Execute(); docs = doc.FetchAll().Count(); - Assert.AreEqual(1, docs, "Matches"); + Assert.That(docs, Is.EqualTo(1), "Matches"); // Anonymous Object var data3 = new { _id = "1e9c92fda74ed311944e00059a3c7a01", title = "Book 0", pages = 10 }; var data4 = new { _id = -2, title = "Book 0", pages = 10 }; result = col.Add(data3).Add(data4).Execute(); generatedIDs = result.GeneratedIds; - Assert.AreEqual(0, generatedIDs.Count, "Matches"); + Assert.That(generatedIDs.Count, Is.EqualTo(0), "Matches"); doc = col.Find("_id like :param").Bind("param", "1e9c92fda74ed311944e00059a3c7a01").Execute(); docs = doc.FetchAll().Count(); - Assert.AreEqual(1, docs, "Matches"); + Assert.That(docs, Is.EqualTo(1), "Matches"); doc = col.Find("_id like :param").Bind("param", -2).Execute(); docs = doc.FetchAll().Count(); - Assert.AreEqual(1, docs, "Matches"); + Assert.That(docs, Is.EqualTo(1), "Matches"); //DbDoc DbDoc DbDocs1 = new DbDoc(); @@ -2107,26 +2107,26 @@ public void VerifyIDFieldScenario8() DbDocs2.SetValue("_id", -3); result = col.Add(DbDocs1).Add(DbDocs2).Execute(); generatedIDs = result.GeneratedIds; - Assert.AreEqual(0, generatedIDs.Count, "Matches"); + Assert.That(generatedIDs.Count, Is.EqualTo(0), "Matches"); doc = col.Find("_id like :param").Bind("param", "1e9c92fda74ed311944e00059a3c7a02").Execute(); docs = doc.FetchAll().Count(); - Assert.AreEqual(1, docs, "Matches"); + Assert.That(docs, Is.EqualTo(1), "Matches"); doc = col.Find("_id like :param").Bind("param", -3).Execute(); docs = doc.FetchAll().Count(); - Assert.AreEqual(1, docs, "Matches"); + Assert.That(docs, Is.EqualTo(1), "Matches"); // JSON result = col.Add("{\"_id\":\"1e9c92fda74ed311944e00059a3c7a03\",\"title\": \"Book 0\",\"pages\": 10}"). Add("{\"_id\":-4,\"title\": \"Book 0\",\"pages\": 10}"). Execute(); generatedIDs = result.GeneratedIds; - Assert.AreEqual(0, generatedIDs.Count, "Matches"); + Assert.That(generatedIDs.Count, Is.EqualTo(0), "Matches"); doc = col.Find("_id like :param").Bind("param", "1e9c92fda74ed311944e00059a3c7a03").Execute(); docs = doc.FetchAll().Count(); - Assert.AreEqual(1, docs, "Matches"); + Assert.That(docs, Is.EqualTo(1), "Matches"); doc = col.Find("_id like :param").Bind("param", -4).Execute(); docs = doc.FetchAll().Count(); - Assert.AreEqual(1, docs, "Matches"); + Assert.That(docs, Is.EqualTo(1), "Matches"); } [Test, Description("Client provided _id shouldnt be discarded and generatedids() should give empty list for anonymous object array -multiple documents single add with negative number,zero and big positive numbers")] @@ -2145,12 +2145,12 @@ public void VerifyIDFieldScenario9() }; Result result = col.Add(data1).Execute(); var generatedIDs = result.GeneratedIds; - Assert.AreEqual(0, generatedIDs.Count, "Matches"); + Assert.That(generatedIDs.Count, Is.EqualTo(0), "Matches"); for (int i = 0; i < idList.Length; i++) { var doc = col.Find("_id like :param").Bind("param", idList[i]).Execute(); var docs = doc.FetchAll().Count(); - Assert.AreEqual(1, docs, "Matches the Document ID"); + Assert.That(docs, Is.EqualTo(1), "Matches the Document ID"); } } @@ -2169,12 +2169,12 @@ public void CollectionAddBlankId() new { _id = idList[1], title = "Book 0", pages = 10 } }; Result result1 = col.Add(data1).Execute(); - Assert.AreEqual(1, result1.AffectedItemsCount); + Assert.That(result1.AffectedItemsCount, Is.EqualTo(1)); result1 = null; col = CreateCollection("my_collection"); result1 = col.Add(data2).Execute(); - Assert.AreEqual(1, result1.AffectedItemsCount); + Assert.That(result1.AffectedItemsCount, Is.EqualTo(1)); result1 = null; col = CreateCollection("my_collection"); @@ -2184,7 +2184,7 @@ public void CollectionAddBlankId() DbDocs1.SetValue("pages", 10); DbDocs1.SetValue("_id", ""); result1 = col.Add(DbDocs1).Execute(); - Assert.AreEqual(1, result1.AffectedItemsCount); + Assert.That(result1.AffectedItemsCount, Is.EqualTo(1)); result1 = null; col = CreateCollection("my_collection"); @@ -2193,18 +2193,18 @@ public void CollectionAddBlankId() DbDocs2.SetValue("pages", 20); DbDocs2.SetValue("_id", " "); result1 = col.Add(DbDocs2).Execute(); - Assert.AreEqual(1, result1.AffectedItemsCount); + Assert.That(result1.AffectedItemsCount, Is.EqualTo(1)); result1 = null; // JSON col = CreateCollection("my_collection"); result1 = col.Add("{\"_id\":\"\",\"title\": \"Book 0\",\"pages\": 10}").Execute(); - Assert.AreEqual(1, result1.AffectedItemsCount); + Assert.That(result1.AffectedItemsCount, Is.EqualTo(1)); result1 = null; col = CreateCollection("my_collection"); result1 = col.Add("{\"_id\":\" \",\"title\": \"Book 0\",\"pages\": 10}").Execute(); - Assert.AreEqual(1, result1.AffectedItemsCount); + Assert.That(result1.AffectedItemsCount, Is.EqualTo(1)); result1 = null; } @@ -2224,12 +2224,12 @@ public void CollectionAddMultipleDocsSameId() DbDocs2.SetValue("pages", 20); DbDocs2.SetValue("_id", 1); var ex = Assert.Throws(() => col.Add(DbDocs1).Add(DbDocs2).Execute()); - Assert.AreEqual(exception, ex.Message, "Checking the exception"); + Assert.That(ex.Message, Is.EqualTo(exception), "Checking the exception"); // JSON ex = Assert.Throws(() => col.Add("{\"_id\":1,\"title\": \"Book 0\",\"pages\": 10}"). Add("{\"_id\":1,\"title\": \"Book 1\",\"pages\": 20}").Execute()); - Assert.AreEqual(exception, ex.Message, "Checking the exception"); + Assert.That(ex.Message, Is.EqualTo(exception), "Checking the exception"); // Anonymous Object Array object[] data1 = new object[] @@ -2241,7 +2241,7 @@ public void CollectionAddMultipleDocsSameId() new { _id = 1, title = "Book 1", pages = 20 } }; ex = Assert.Throws(() => col.Add(data1).Add(data2).Execute()); - Assert.AreEqual(exception, ex.Message, "Checking the exception"); + Assert.That(ex.Message, Is.EqualTo(exception), "Checking the exception"); } [Test, Description("Verify the behaviour if a sequence is incremented by the user and added as _id for the document")] @@ -2259,10 +2259,10 @@ public void VerifySequenceAndIdAdded() result = stmt.Execute(); generatedIDs1 = result.GeneratedIds[0]; - Assert.AreEqual(generatedIDs1, generatedIDs1, "ID generated by the server"); + Assert.That(generatedIDs1, Is.EqualTo(generatedIDs1), "ID generated by the server"); VerifyGeneratedID(generatedIDs1); countgenerateIDs = result.GeneratedIds.Count; - Assert.AreEqual(1, countgenerateIDs, "Count of the ID generated by the server"); + Assert.That(countgenerateIDs, Is.EqualTo(1), "Count of the ID generated by the server"); generatedString = generatedIDs1; incrementedString = Increment(generatedIDs1, Mode.AlphaNumeric); @@ -2270,17 +2270,17 @@ public void VerifySequenceAndIdAdded() stmt = col.Add(data); string exception = "Document contains a field value that is not unique but required to be"; Exception ex = Assert.Throws(() => stmt.Execute()); - Assert.AreEqual(exception, ex.Message, "Matching the exception"); + Assert.That(ex.Message, Is.EqualTo(exception), "Matching the exception"); data = new object[] { new { title = "Book 3", pages = 50, _id = incrementedString } }; stmt = col.Add(data); result = stmt.Execute(); - Assert.IsNotNull(result); + Assert.That(result, Is.Not.Null); data = new object[] { new { title = "Book 4", pages = 60 } }; stmt = col.Add(data); ex = Assert.Throws(() => stmt.Execute()); - Assert.AreEqual(exception, ex.Message, "Matching the exception"); + Assert.That(ex.Message, Is.EqualTo(exception), "Matching the exception"); } @@ -2292,7 +2292,7 @@ public async Task CollectionConcurrentAdd() CreateCollection("my_collection"); var r1 = await CollectionAddThread1(); _ = await CollectionAddThread2(); - Assert.AreEqual(1000, r1); + Assert.That(r1, Is.EqualTo(1000)); } public Task CollectionAddThread1() { @@ -2309,7 +2309,7 @@ public Task CollectionAddThread1() newDoc2 = null; } Result r = col.Add(jsonlist).Execute(); - Assert.AreEqual(1000, r.AffectedItemsCount, "Matching"); + Assert.That(r.AffectedItemsCount, Is.EqualTo(1000), "Matching"); int countgenerateIDs = r.GeneratedIds.Count; for (int i = 0; i < countgenerateIDs; i++) { @@ -2344,7 +2344,7 @@ public Task CollectionAddThread2() newDoc2 = null; } Result r = col.Add(jsonlist).Execute(); - Assert.AreEqual(1000, r.AffectedItemsCount, "Matching"); + Assert.That(r.AffectedItemsCount, Is.EqualTo(1000), "Matching"); int countgenerateIDs = r.GeneratedIds.Count; for (int i = 0; i < countgenerateIDs; i++) { @@ -2381,7 +2381,7 @@ public void DbDocAsObjectConvertToBlank() d2.SetValue("pages", 20); d2.SetValue("taker1", data1); string expected = $"{{{newLine} \"id\": 1, {newLine} \"pages\": 20, {newLine} \"taker1\": {{{newLine} \"id\": 1, {newLine} \"pages\": 20, {newLine} \"person\": {{{newLine} \"name\": \"Fred\", {newLine} \"age\": 45{newLine} }}{newLine} }}{newLine}}}"; - Assert.AreEqual(expected, d2.ToString()); + Assert.That(d2.ToString(), Is.EqualTo(expected)); } [Test, Description("ADDITION OF OBJ FAILS AFTER CREATE INDEX IN 5.7.12 SERVER(WORKS WITH 5.7.9)")] @@ -2391,7 +2391,7 @@ public void AdditionOfObject() testColl.CreateIndex("testIndex", "{\"fields\": [ { \"field\":$.myId, \"type\":\"INT\" , \"required\":true} ] }"); testColl.CreateIndex("testIndex1", "{\"fields\": [ { \"field\":$.myAge, \"type\":\"FLOAT\" , \"required\":true} ] }"); var result = testColl.Add(new { myId = 1, myAge = 35.1, _id = 1 }).Execute(); - Assert.AreEqual(1, result.AffectedItemsCount); + Assert.That(result.AffectedItemsCount, Is.EqualTo(1)); } [Test, Description("Test valid insert at Depth n for multiple arrays))")] @@ -2420,7 +2420,7 @@ public void InsertAtNDepth() json = json + "}"; var res = collection.Add(json).Execute(); - Assert.AreEqual(1, res.AffectedItemsCount); + Assert.That(res.AffectedItemsCount, Is.EqualTo(1)); } #endregion WL14389 @@ -2430,32 +2430,32 @@ public void InsertAtNDepth() public void VerifyGeneratedID(string input) { byte[] array = Encoding.ASCII.GetBytes(input); - Assert.False(array.Length < 28); + Assert.That(array.Length < 28, Is.False); byte[] uniquePrefix = new byte[4]; Array.Copy(array, 0, uniquePrefix, 0, 4); - Assert.AreEqual(System.Text.Encoding.UTF8.GetString(uniquePrefix), System.Text.Encoding.UTF8.GetString(uniquePrefix), + Assert.That(System.Text.Encoding.UTF8.GetString(uniquePrefix), Is.EqualTo(System.Text.Encoding.UTF8.GetString(uniquePrefix)), "Unique Prefix of the Generated ID"); byte[] startTimeStamp = new byte[8]; Array.Copy(array, 4, startTimeStamp, 0, 8); - Assert.AreEqual(System.Text.Encoding.UTF8.GetString(startTimeStamp), System.Text.Encoding.UTF8.GetString(startTimeStamp), + Assert.That(System.Text.Encoding.UTF8.GetString(startTimeStamp), Is.EqualTo(System.Text.Encoding.UTF8.GetString(startTimeStamp)), "StartTimeStamp of the Generated ID"); byte[] serial = new byte[16]; Array.Copy(array, 12, serial, 0, 16); - Assert.AreEqual(System.Text.Encoding.UTF8.GetString(serial), System.Text.Encoding.UTF8.GetString(serial), + Assert.That(System.Text.Encoding.UTF8.GetString(serial), Is.EqualTo(System.Text.Encoding.UTF8.GetString(serial)), "Serial Number of the Generated ID"); } public bool VerifySequence(string input1, string input2) { byte[] array1 = Encoding.ASCII.GetBytes(input1); - Assert.False(array1.Length < 28); + Assert.That(array1.Length < 28, Is.False); byte[] array2 = Encoding.ASCII.GetBytes(input2); - Assert.False(array2.Length < 28); - Assert.AreNotEqual(input1, input2); + Assert.That(array2.Length < 28, Is.False); + Assert.That(input2, Is.Not.EqualTo(input1)); string incrementedString = Increment(input1, Mode.AlphaNumeric); if (incrementedString.Equals(input2)) { diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/CrudRemoveTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/CrudRemoveTests.cs index d6dc7081e..e14e77037 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/CrudRemoveTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/CrudRemoveTests.cs @@ -47,21 +47,21 @@ public void RemoveSingleDocumentById() new { _id = 56, title = "Book 3", pages = 40 }, }; Result r = ExecuteAddStatement(coll.Add(docs)); - Assert.AreEqual(3, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(3)); // Remove with condition. r = ExecuteRemoveStatement(coll.Remove("_id = 12")); - Assert.AreEqual(1, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(1)); // Remove by ID. r = coll.RemoveOne(34); - Assert.AreEqual(1, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(1)); var ex = Assert.Throws(() => coll.Remove("")); #if !NETFRAMEWORK - Assert.AreEqual("Parameter can't be null or empty. (Parameter 'condition')", ex.Message); + Assert.That(ex.Message, Is.EqualTo("Parameter can't be null or empty. (Parameter 'condition')")); #else - Assert.AreEqual("Parameter can't be null or empty.\r\nParameter name: condition", ex.Message); + Assert.That(ex.Message, Is.EqualTo("Parameter can't be null or empty.\r\nParameter name: condition")); #endif } @@ -77,10 +77,10 @@ public void RemoveMultipleDocuments() new { _id = 4, title = "Book 4", pages = 50 }, }; Result r = ExecuteAddStatement(coll.Add(docs)); - Assert.AreEqual(4, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(4)); r = ExecuteRemoveStatement(coll.Remove("pages > 20")); - Assert.AreEqual(3, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(3)); } [Test] @@ -95,10 +95,10 @@ public void RemoveMultipleDocumentsWithLimit() new { _id = 4, title = "Book 4", pages = 50 }, }; Result r = ExecuteAddStatement(coll.Add(docs)); - Assert.AreEqual(4, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(4)); r = ExecuteRemoveStatement(coll.Remove("pages > 20").Limit(1)); - Assert.AreEqual(1, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(1)); // Limit out of range. Assert.Throws(() => ExecuteRemoveStatement(coll.Remove("True").Limit(0))); @@ -119,10 +119,10 @@ public void RemoveMultipleDocumentsWithLimitAndOrder() new { _id = 4, title = "Book 4", pages = 50 }, }; Result r = ExecuteAddStatement(coll.Add(docs)); - Assert.AreEqual(4, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(4)); r = ExecuteRemoveStatement(coll.Remove("pages > 20").Limit(1)); - Assert.AreEqual(1, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(1)); } [Test] @@ -145,18 +145,18 @@ public void RemoveBind() new { _id = 4, title = "Book 4", pages = 50 }, }; Result r = ExecuteAddStatement(coll.Add(docs)); - Assert.AreEqual(4, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(4)); r = ExecuteRemoveStatement(coll.Remove("pages = :Pages").Bind("pAges", 50)); - Assert.AreEqual(1, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(1)); var jsonParams = new { pages1 = 30, pages2 = 40 }; var res = coll.Remove("pages = :Pages1 || pages = :Pages2").Bind(jsonParams).Execute(); - Assert.AreEqual(2, res.AffectedItemsCount); + Assert.That(res.AffectedItemsCount, Is.EqualTo(2)); DbDoc docParams = new DbDoc(new { pages1 = 10, pages2 = 20 }); coll.Remove("pages = :Pages1 || pages = :Pages2").Bind(docParams).Execute(); - Assert.True(res.AffectedItemsCount > 0); + Assert.That(res.AffectedItemsCount > 0); } [Test] @@ -171,7 +171,7 @@ public void RemoveAll() new { _id = 4, title = "Book 4", pages = 50 }, }; Result result = ExecuteAddStatement(collection.Add(docs)); - Assert.AreEqual(4, result.AffectedItemsCount); + Assert.That(result.AffectedItemsCount, Is.EqualTo(4)); // Condition can't be null or empty. string errorMessage = string.Empty; @@ -181,17 +181,17 @@ public void RemoveAll() errorMessage = "Parameter can't be null or empty.\r\nParameter name: condition"; #endif Exception ex = Assert.Throws(() => ExecuteRemoveStatement(collection.Remove(string.Empty))); - Assert.AreEqual(errorMessage, ex.Message); + Assert.That(ex.Message, Is.EqualTo(errorMessage)); ex = Assert.Throws(() => ExecuteRemoveStatement(collection.Remove(""))); - Assert.AreEqual(errorMessage, ex.Message); + Assert.That(ex.Message, Is.EqualTo(errorMessage)); ex = Assert.Throws(() => ExecuteRemoveStatement(collection.Remove(" "))); - Assert.AreEqual(errorMessage, ex.Message); + Assert.That(ex.Message, Is.EqualTo(errorMessage)); ex = Assert.Throws(() => ExecuteRemoveStatement(collection.Remove(" "))); - Assert.AreEqual(errorMessage, ex.Message); + Assert.That(ex.Message, Is.EqualTo(errorMessage)); // Sending an expression that evaluates to true applies changes on all documents. result = ExecuteRemoveStatement(collection.Remove("true")); - Assert.AreEqual(4, result.AffectedItemsCount); + Assert.That(result.AffectedItemsCount, Is.EqualTo(4)); } [Test] @@ -207,16 +207,16 @@ public void RemoveWithInOperator() new DbDoc("{ \"a\": 1, \"b\": \"foo3\", \"c\": { \"d\": true, \"e\": [1,4,3] }, \"f\": [ {\"x\":6}, {\"x\":9 } ] }"), }; Result result = ExecuteAddStatement(collection.Add(docs)); - Assert.AreEqual(3, result.AffectedItemsCount); + Assert.That(result.AffectedItemsCount, Is.EqualTo(3)); - Assert.AreEqual(1, ExecuteRemoveStatement(collection.Remove("a IN (2,3)")).AffectedItemsCount); - Assert.AreEqual(2, ExecuteFindStatement(collection.Find()).FetchAll().Count); + Assert.That(ExecuteRemoveStatement(collection.Remove("a IN (2,3)")).AffectedItemsCount, Is.EqualTo(1)); + Assert.That(ExecuteFindStatement(collection.Find()).FetchAll().Count, Is.EqualTo(2)); - Assert.AreEqual(0, ExecuteRemoveStatement(collection.Remove("a IN [3]")).AffectedItemsCount); - Assert.AreEqual(2, ExecuteFindStatement(collection.Find()).FetchAll().Count); + Assert.That(ExecuteRemoveStatement(collection.Remove("a IN [3]")).AffectedItemsCount, Is.EqualTo(0)); + Assert.That(ExecuteFindStatement(collection.Find()).FetchAll().Count, Is.EqualTo(2)); - Assert.AreEqual(2, ExecuteRemoveStatement(collection.Remove("1 IN c.e")).AffectedItemsCount); - CollectionAssert.IsEmpty(ExecuteFindStatement(collection.Find()).FetchAll()); + Assert.That(ExecuteRemoveStatement(collection.Remove("1 IN c.e")).AffectedItemsCount, Is.EqualTo(2)); + Assert.That(ExecuteFindStatement(collection.Find()).FetchAll(), Is.Empty); } [Test] @@ -231,27 +231,27 @@ public void RemoveOne() new { _id = 4, title = "Book 4", pages = 50 }, }; Result result = ExecuteAddStatement(collection.Add(docs)); - Assert.AreEqual(4, result.AffectedItemsCount); + Assert.That(result.AffectedItemsCount, Is.EqualTo(4)); ExecuteAddStatement(collection.Add(new { _id = 5, title = "Book 5", pages = 60 })); - Assert.AreEqual(5, ExecuteFindStatement(collection.Find()).FetchAll().Count); + Assert.That(ExecuteFindStatement(collection.Find()).FetchAll().Count, Is.EqualTo(5)); // Remove sending numeric parameter. - Assert.AreEqual(1, collection.RemoveOne(1).AffectedItemsCount); - Assert.AreEqual(4, ExecuteFindStatement(collection.Find()).FetchAll().Count); + Assert.That(collection.RemoveOne(1).AffectedItemsCount, Is.EqualTo(1)); + Assert.That(ExecuteFindStatement(collection.Find()).FetchAll().Count, Is.EqualTo(4)); // Remove sending string parameter. - Assert.AreEqual(1, collection.RemoveOne("3").AffectedItemsCount); - Assert.AreEqual(3, ExecuteFindStatement(collection.Find()).FetchAll().Count); + Assert.That(collection.RemoveOne("3").AffectedItemsCount, Is.EqualTo(1)); + Assert.That(ExecuteFindStatement(collection.Find()).FetchAll().Count, Is.EqualTo(3)); // Remove an auto-generated id. DbDoc document = ExecuteFindStatement(collection.Find("pages = 60")).FetchOne(); - Assert.AreEqual(1, collection.RemoveOne(document.Id).AffectedItemsCount); - Assert.AreEqual(2, ExecuteFindStatement(collection.Find()).FetchAll().Count); + Assert.That(collection.RemoveOne(document.Id).AffectedItemsCount, Is.EqualTo(1)); + Assert.That(ExecuteFindStatement(collection.Find()).FetchAll().Count, Is.EqualTo(2)); // Remove a non-existing document. - Assert.AreEqual(0, collection.RemoveOne(5).AffectedItemsCount); - Assert.AreEqual(2, ExecuteFindStatement(collection.Find()).FetchAll().Count); + Assert.That(collection.RemoveOne(5).AffectedItemsCount, Is.EqualTo(0)); + Assert.That(ExecuteFindStatement(collection.Find()).FetchAll().Count, Is.EqualTo(2)); // Expected exceptions. Assert.Throws(() => collection.RemoveOne(null)); @@ -273,16 +273,16 @@ public void ForbidRemoveWithNoCondition() new { _id = 4, title = "Book 4", pages = 50 }, }; Result result = collection.Add(docs).Execute(); - Assert.AreEqual(4, result.AffectedItemsCount); + Assert.That(result.AffectedItemsCount, Is.EqualTo(4)); result = collection.Remove("_id = 1").Execute(); - Assert.AreEqual(1, result.AffectedItemsCount); + Assert.That(result.AffectedItemsCount, Is.EqualTo(1)); result = collection.Remove("_id = 10").Execute(); - Assert.AreEqual(0, result.AffectedItemsCount); + Assert.That(result.AffectedItemsCount, Is.EqualTo(0)); result = collection.Remove("_id = 2").Execute(); - Assert.AreEqual(1, result.AffectedItemsCount); + Assert.That(result.AffectedItemsCount, Is.EqualTo(1)); result = collection.Remove("_id = 10").Execute(); - Assert.AreEqual(0, result.AffectedItemsCount); + Assert.That(result.AffectedItemsCount, Is.EqualTo(0)); Assert.Throws(() => collection.Remove("")); } @@ -330,35 +330,35 @@ public void CollectionUnsetMultiple() var res1 = col.Find().Fields("{\"_id\":\"1\",\"books\": \"test1\" }").Fields("{\"_id\":\"2\",\"books\": \"test2\" }").Fields("{\"_id\":\"3\",\"books\": \"test3\" }").Execute().FetchAll(); res1 = col.Find().Fields(new string[] { "_id", "books", "count" }).Execute().FetchAll(); - Assert.AreEqual(3, res1.Count, "Matching the find count"); - Assert.AreEqual(d1.ToString(), res1[0].ToString(), "Matching the doc string 1"); - Assert.AreEqual(d2.ToString(), res1[1].ToString(), "Matching the doc string 2"); - Assert.AreEqual(d3.ToString(), res1[2].ToString(), "Matching the doc string 3"); + Assert.That(res1.Count, Is.EqualTo(3), "Matching the find count"); + Assert.That(res1[0].ToString(), Is.EqualTo(d1.ToString()), "Matching the doc string 1"); + Assert.That(res1[1].ToString(), Is.EqualTo(d2.ToString()), "Matching the doc string 2"); + Assert.That(res1[2].ToString(), Is.EqualTo(d3.ToString()), "Matching the doc string 3"); final = col.Add(new DbDoc[] { d4, d5 }).Execute(); var res2 = col.Find().Fields("$._id as _id,$.books as books, $.count as count").Execute().FetchAll(); - Assert.AreEqual(5, res2.Count, "Matching the find count"); - Assert.AreEqual(d1.ToString(), res2[0].ToString(), "Matching the doc string 1"); - Assert.AreEqual(d2.ToString(), res2[1].ToString(), "Matching the doc string 2"); - Assert.AreEqual(d3.ToString(), res2[2].ToString(), "Matching the doc string 3"); - Assert.AreEqual(d4.ToString(), res2[3].ToString(), "Matching the doc string 4"); - Assert.AreEqual(d5.ToString(), res2[4].ToString(), "Matching the doc string 5"); + Assert.That(res2.Count, Is.EqualTo(5), "Matching the find count"); + Assert.That(res2[0].ToString(), Is.EqualTo(d1.ToString()), "Matching the doc string 1"); + Assert.That(res2[1].ToString(), Is.EqualTo(d2.ToString()), "Matching the doc string 2"); + Assert.That(res2[2].ToString(), Is.EqualTo(d3.ToString()), "Matching the doc string 3"); + Assert.That(res2[3].ToString(), Is.EqualTo(d4.ToString()), "Matching the doc string 4"); + Assert.That(res2[4].ToString(), Is.EqualTo(d5.ToString()), "Matching the doc string 5"); final = col.Add(d6, d7).Execute(); var res3 = col.Find().Sort("count ASC").Execute().FetchAll(); - Assert.AreEqual(d6.ToString(), res3[0].ToString(), "Matching the doc string 7"); - Assert.AreEqual(d1.ToString(), res3[1].ToString(), "Matching the doc string 1"); - Assert.AreEqual(d2.ToString(), res3[2].ToString(), "Matching the doc string 2"); - Assert.AreEqual(d3.ToString(), res3[3].ToString(), "Matching the doc string 3"); - Assert.AreEqual(d4.ToString(), res3[4].ToString(), "Matching the doc string 4"); - Assert.AreEqual(d5.ToString(), res3[5].ToString(), "Matching the doc string 5"); - Assert.AreEqual(d7.ToString(), res3[6].ToString(), "Matching the doc string 6"); + Assert.That(res3[0].ToString(), Is.EqualTo(d6.ToString()), "Matching the doc string 7"); + Assert.That(res3[1].ToString(), Is.EqualTo(d1.ToString()), "Matching the doc string 1"); + Assert.That(res3[2].ToString(), Is.EqualTo(d2.ToString()), "Matching the doc string 2"); + Assert.That(res3[3].ToString(), Is.EqualTo(d3.ToString()), "Matching the doc string 3"); + Assert.That(res3[4].ToString(), Is.EqualTo(d4.ToString()), "Matching the doc string 4"); + Assert.That(res3[5].ToString(), Is.EqualTo(d5.ToString()), "Matching the doc string 5"); + Assert.That(res3[6].ToString(), Is.EqualTo(d7.ToString()), "Matching the doc string 6"); var res4 = col.Find().Sort("count DESC").Execute().FetchAll(); - Assert.AreEqual(d7.ToString(), res4[0].ToString(), "Matching the doc string 6"); - Assert.AreEqual(d5.ToString(), res4[1].ToString(), "Matching the doc string 1"); - Assert.AreEqual(d4.ToString(), res4[2].ToString(), "Matching the doc string 2"); - Assert.AreEqual(d3.ToString(), res4[3].ToString(), "Matching the doc string 3"); - Assert.AreEqual(d2.ToString(), res4[4].ToString(), "Matching the doc string 4"); - Assert.AreEqual(d1.ToString(), res4[5].ToString(), "Matching the doc string 5"); - Assert.AreEqual(d6.ToString(), res4[6].ToString(), "Matching the doc string 7"); + Assert.That(res4[0].ToString(), Is.EqualTo(d7.ToString()), "Matching the doc string 6"); + Assert.That(res4[1].ToString(), Is.EqualTo(d5.ToString()), "Matching the doc string 1"); + Assert.That(res4[2].ToString(), Is.EqualTo(d4.ToString()), "Matching the doc string 2"); + Assert.That(res4[3].ToString(), Is.EqualTo(d3.ToString()), "Matching the doc string 3"); + Assert.That(res4[4].ToString(), Is.EqualTo(d2.ToString()), "Matching the doc string 4"); + Assert.That(res4[5].ToString(), Is.EqualTo(d1.ToString()), "Matching the doc string 5"); + Assert.That(res4[6].ToString(), Is.EqualTo(d6.ToString()), "Matching the doc string 7"); //Unset with multiple variables not supported col.Modify("_id = 1").Unset(new string[] { "count", "books" }).Execute(); col.Modify("_id = 1").Set("count", 10).Set("books", "test1").Execute(); @@ -371,9 +371,9 @@ public void RemovingItemUsingDbDoc() Collection coll = CreateCollection("test"); DbDoc doc = new DbDoc(new { _id = 1, title = "Book 1", pages = 20 }); Result r = coll.Add(doc).Execute(); - Assert.AreEqual(1, (int)r.AffectedItemsCount, "Match being done"); + Assert.That((int)r.AffectedItemsCount, Is.EqualTo(1), "Match being done"); r = coll.Remove("_id=1").Execute(); - Assert.AreEqual(1, (int)r.AffectedItemsCount, "Match being done"); + Assert.That((int)r.AffectedItemsCount, Is.EqualTo(1), "Match being done"); } #endregion WL14389 diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/CrudTests/CrudGCTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/CrudTests/CrudGCTests.cs index 5b181c9bb..96aa89cd5 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/CrudTests/CrudGCTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/CrudTests/CrudGCTests.cs @@ -46,15 +46,15 @@ public void FetchAllNoReference() stmt.Add(@"{ ""_id"": 3, ""foo"": 3 }"); stmt.Add(@"{ ""_id"": 4, ""foo"": 4 }"); Result result = ExecuteAddStatement(stmt); - Assert.AreEqual(4, (int)result.AffectedItemsCount); + Assert.That((int)result.AffectedItemsCount, Is.EqualTo(4)); var docResult = ExecuteFindStatement(testColl.Find()); var docs = docResult.FetchAll(); WeakReference wr = new WeakReference(docResult); docResult = null; GC.Collect(); - Assert.False(wr.IsAlive); - Assert.AreEqual(4, docs.Count); + Assert.That(wr.IsAlive, Is.False); + Assert.That(docs.Count, Is.EqualTo(4)); } #endif } diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/CrudTests/DocBufferingTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/CrudTests/DocBufferingTests.cs index 968fb8b8b..b9d5b74d9 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/CrudTests/DocBufferingTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/CrudTests/DocBufferingTests.cs @@ -49,13 +49,13 @@ public void SmartBuffering() new { _id = 4, title = "Book 4", pages = 50 }, }; Result r = ExecuteAddStatement(test.Add(docs)); - Assert.AreEqual(r.Warnings.Count, r.WarningsCount); + Assert.That(r.WarningsCount, Is.EqualTo(r.Warnings.Count)); var docResult = ExecuteFindStatement(test.Find()); foreach (var doc in docResult) { var result = ExecuteAddStatement(test2.Add(doc)); - Assert.AreEqual(1, result.AffectedItemsCount); + Assert.That(result.AffectedItemsCount, Is.EqualTo(1)); } } } diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/CrudUpdateTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/CrudUpdateTests.cs index b5abd79a6..19216f6a5 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/CrudUpdateTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/CrudUpdateTests.cs @@ -43,29 +43,29 @@ public void SetItemInSingleDocument() { Collection coll = CreateCollection("test"); Result result = ExecuteAddStatement(coll.Add(new { _id = 1, name = "Book 1" })); - Assert.AreEqual(1, result.AffectedItemsCount); + Assert.That(result.AffectedItemsCount, Is.EqualTo(1)); // Set integer value. result = ExecuteModifyStatement(coll.Modify("_id = 1").Set("pages", "20")); - Assert.AreEqual(1, result.AffectedItemsCount); - Assert.AreEqual("20", coll.GetOne(1)["pages"]); + Assert.That(result.AffectedItemsCount, Is.EqualTo(1)); + Assert.That(coll.GetOne(1)["pages"], Is.EqualTo("20")); // Set null value. result = ExecuteModifyStatement(coll.Modify("_id = 1").Set("pages", null)); - Assert.AreEqual(1, result.AffectedItemsCount); - Assert.Null(coll.GetOne(1)["pages"]); + Assert.That(result.AffectedItemsCount, Is.EqualTo(1)); + Assert.That(coll.GetOne(1)["pages"], Is.Null); // Set existing field. result = ExecuteModifyStatement(coll.Modify("_id = 1").Set("name", "Book 2")); - Assert.AreEqual(1, result.AffectedItemsCount); - Assert.AreEqual("Book 2", coll.GetOne(1)["name"]); + Assert.That(result.AffectedItemsCount, Is.EqualTo(1)); + Assert.That(coll.GetOne(1)["name"], Is.EqualTo("Book 2")); // Set alphanumeric field. var document = new DbDoc(); document.SetValue("_id", 2); document.SetValue("1a", "other"); result = ExecuteAddStatement(coll.Add(document)); - Assert.AreEqual(1, result.AffectedItemsCount); + Assert.That(result.AffectedItemsCount, Is.EqualTo(1)); var insertedDocument = coll.GetOne(2); //result = coll.Modify("_id = 1").Set("1a", "other")); @@ -76,10 +76,10 @@ public void ChangeItemInSingleDocument() { Collection coll = CreateCollection("test"); Result result = ExecuteAddStatement(coll.Add(new { _id = 1, name = "Book 1", pages = 20 })); - Assert.AreEqual(1, result.AffectedItemsCount); + Assert.That(result.AffectedItemsCount, Is.EqualTo(1)); result = ExecuteModifyStatement(coll.Modify("_id = 1").Change("name", "Book 2")); - Assert.AreEqual(1, result.AffectedItemsCount); + Assert.That(result.AffectedItemsCount, Is.EqualTo(1)); } [Test] @@ -91,42 +91,42 @@ public void RemoveItemInSingleDocumentUsingUnset() .Add(new { _id = 2, name = "Book 2", pages = 30 }) .Add(new { _id = 3, name = "Book 3", pages = 40, author = "John", author2 = "Mary" }) ); - Assert.AreEqual(3, result.AffectedItemsCount); + Assert.That(result.AffectedItemsCount, Is.EqualTo(3)); // Unset 1 field. result = ExecuteModifyStatement(coll.Modify("_id = 1").Unset("pages")); - Assert.AreEqual(1, result.AffectedItemsCount); + Assert.That(result.AffectedItemsCount, Is.EqualTo(1)); var document = ExecuteFindStatement(coll.Find("_id = 1")).FetchOne(); - Assert.AreEqual(2, document.values.Count); + Assert.That(document.values.Count, Is.EqualTo(2)); // Unset multiple fields. result = ExecuteModifyStatement(coll.Modify("_id = 2").Unset("name", "pages")); - Assert.AreEqual(1, result.AffectedItemsCount); + Assert.That(result.AffectedItemsCount, Is.EqualTo(1)); document = ExecuteFindStatement(coll.Find("_id = 2")).FetchOne(); Assert.That(document.values, Has.One.Items); result = ExecuteModifyStatement(coll.Modify("_id = 3").Unset(null, "author", "author2")); document = ExecuteFindStatement(coll.Find("_id = 3")).FetchOne(); - Assert.AreEqual(3, document.values.Count); + Assert.That(document.values.Count, Is.EqualTo(3)); // Unsetting nonexistent fields doesn't raise an error. result = ExecuteModifyStatement(coll.Modify("_id = 2").Unset("otherfield")); - Assert.AreEqual(0ul, result.AffectedItemsCount); + Assert.That(result.AffectedItemsCount, Is.EqualTo(0ul)); // Unsetting null items combined with valid values are ignored. result = ExecuteModifyStatement(coll.Modify("_id = 3").Unset(null).Unset("name")); - Assert.AreEqual(1ul, result.AffectedItemsCount); + Assert.That(result.AffectedItemsCount, Is.EqualTo(1ul)); document = ExecuteFindStatement(coll.Find("_id = 3")).FetchOne(); - Assert.AreEqual(2, document.values.Count); + Assert.That(document.values.Count, Is.EqualTo(2)); // Unsetting single null items raises an error var ex = Assert.Throws(() => ExecuteModifyStatement(coll.Modify("_id = 3").Unset(null))); - Assert.AreEqual("Invalid update expression list", ex.Message); + Assert.That(ex.Message, Is.EqualTo("Invalid update expression list")); // Unsetting empty strings raises an error. var ex2 = Assert.Throws(() => ExecuteModifyStatement(coll.Modify("_id = 2").Unset(""))); - Assert.AreEqual(ResourcesX.DocPathNullOrEmpty, ex2.Message); + Assert.That(ex2.Message, Is.EqualTo(ResourcesX.DocPathNullOrEmpty)); ex2 = Assert.Throws(() => ExecuteModifyStatement(coll.Modify("_id = 2").Unset(string.Empty))); - Assert.AreEqual(ResourcesX.DocPathNullOrEmpty, ex2.Message); + Assert.That(ex2.Message, Is.EqualTo(ResourcesX.DocPathNullOrEmpty)); // Unset with special chars. Assert.Throws(() => ExecuteModifyStatement(coll.Modify("_id = 3").Unset(null).Unset("@*%#�"))); @@ -139,16 +139,16 @@ public void SetItemAndBind() Collection coll = CreateCollection("test"); Result result = ExecuteAddStatement(coll.Add(new { _id = 1, name = "Book 1" }) .Add(new { _id = 2, name = "Book 2" })); - Assert.AreEqual(2, result.AffectedItemsCount); + Assert.That(result.AffectedItemsCount, Is.EqualTo(2)); var stmt = coll.Modify("_id = :ID"); result = ExecuteModifyStatement(stmt.Bind("Id", 2).Set("pages", "20")); - Assert.AreEqual(1, result.AffectedItemsCount); - result = ExecuteModifyStatement(stmt.Bind("Id", 1).Set("pages", 10)); Assert.AreEqual(1, result.AffectedItemsCount); + Assert.That(result.AffectedItemsCount, Is.EqualTo(1)); + result = ExecuteModifyStatement(stmt.Bind("Id", 1).Set("pages", 10)); Assert.That(result.AffectedItemsCount, Is.EqualTo(1)); var docs = ExecuteFindStatement(coll.Find()).FetchAll(); - Assert.AreEqual(new DbDoc("{ \"_id\": 1, \"name\": \"Book 1\", \"pages\": 10 }").ToString(), docs[0].ToString()); - Assert.AreEqual(new DbDoc("{ \"_id\": 2, \"name\": \"Book 2\", \"pages\": \"20\" }").ToString(), docs[1].ToString()); + Assert.That(docs[0].ToString(), Is.EqualTo(new DbDoc("{ \"_id\": 1, \"name\": \"Book 1\", \"pages\": 10 }").ToString())); + Assert.That(docs[1].ToString(), Is.EqualTo(new DbDoc("{ \"_id\": 2, \"name\": \"Book 2\", \"pages\": \"20\" }").ToString())); } [Test] @@ -161,7 +161,7 @@ public void ModifyAll() new { _id = 2, title = "Book 2", pages = 30 }, }; Result result = ExecuteAddStatement(collection.Add(docs)); - Assert.AreEqual(2, result.AffectedItemsCount); + Assert.That(result.AffectedItemsCount, Is.EqualTo(2)); // Condition can't be null or empty. string errorMessage = string.Empty; @@ -171,19 +171,19 @@ public void ModifyAll() errorMessage = "Parameter can't be null or empty.\r\nParameter name: condition"; #endif Exception ex = Assert.Throws(() => ExecuteModifyStatement(collection.Modify(string.Empty))); - Assert.AreEqual(ex.Message, errorMessage); + Assert.That(errorMessage, Is.EqualTo(ex.Message)); ex = Assert.Throws(() => ExecuteModifyStatement(collection.Modify(""))); - Assert.AreEqual(ex.Message, errorMessage); + Assert.That(errorMessage, Is.EqualTo(ex.Message)); ex = Assert.Throws(() => ExecuteModifyStatement(collection.Modify(" "))); - Assert.AreEqual(ex.Message, errorMessage); + Assert.That(errorMessage, Is.EqualTo(ex.Message)); ex = Assert.Throws(() => ExecuteModifyStatement(collection.Modify(" "))); - Assert.AreEqual(ex.Message, errorMessage); + Assert.That(errorMessage, Is.EqualTo(ex.Message)); ex = Assert.Throws(() => ExecuteModifyStatement(collection.Modify(null))); - Assert.AreEqual(ex.Message, errorMessage); + Assert.That(errorMessage, Is.EqualTo(ex.Message)); // Sending an expression that evaluates to true applies changes on all documents. result = ExecuteModifyStatement(collection.Modify("true").Set("pages", "10")); - Assert.AreEqual(2, result.AffectedItemsCount); + Assert.That(result.AffectedItemsCount, Is.EqualTo(2)); } [Test] @@ -196,7 +196,7 @@ public void ModifyWithLimit() new { _id = 2, title = "Book 2", pages = 30 }, }; Result result = ExecuteAddStatement(collection.Add(docs)); - Assert.AreEqual(2, result.AffectedItemsCount); + Assert.That(result.AffectedItemsCount, Is.EqualTo(2)); ExecuteModifyStatement(collection.Modify("true").Set("title", "Book X").Limit(1)); Assert.That(ExecuteFindStatement(collection.Find("title = \"Book X\"")).FetchAll(), Has.One.Items); @@ -219,16 +219,16 @@ public void ModifyWithInOperator() new DbDoc("{ \"a\": 1, \"b\": \"foo3\", \"c\": { \"d\": true, \"e\": [1,4,3] }, \"f\": [ {\"x\":6}, {\"x\":9 } ] }"), }; Result result = ExecuteAddStatement(collection.Add(docs)); - Assert.AreEqual(3, result.AffectedItemsCount); + Assert.That(result.AffectedItemsCount, Is.EqualTo(3)); - Assert.AreEqual(3, ExecuteModifyStatement(collection.Modify("a IN (1,2)").Set("a", 3)).AffectedItemsCount); - Assert.AreEqual(3, ExecuteFindStatement(collection.Find().Where("a = 3")).FetchAll().Count); + Assert.That(ExecuteModifyStatement(collection.Modify("a IN (1,2)").Set("a", 3)).AffectedItemsCount, Is.EqualTo(3)); + Assert.That(ExecuteFindStatement(collection.Find().Where("a = 3")).FetchAll().Count, Is.EqualTo(3)); - Assert.AreEqual(3, ExecuteModifyStatement(collection.Modify("a IN [3]").Set("a", 1)).AffectedItemsCount); - Assert.AreEqual(3, ExecuteFindStatement(collection.Find().Where("a = 1")).FetchAll().Count); + Assert.That(ExecuteModifyStatement(collection.Modify("a IN [3]").Set("a", 1)).AffectedItemsCount, Is.EqualTo(3)); + Assert.That(ExecuteFindStatement(collection.Find().Where("a = 1")).FetchAll().Count, Is.EqualTo(3)); - Assert.AreEqual(2, ExecuteModifyStatement(collection.Modify("1 IN c.e").Set("c.e", "newValue")).AffectedItemsCount); - Assert.AreEqual(2, ExecuteFindStatement(collection.Find().Where("c.e = \"newValue\"")).FetchAll().Count); + Assert.That(ExecuteModifyStatement(collection.Modify("1 IN c.e").Set("c.e", "newValue")).AffectedItemsCount, Is.EqualTo(2)); + Assert.That(ExecuteFindStatement(collection.Find().Where("c.e = \"newValue\"")).FetchAll().Count, Is.EqualTo(2)); } [Test] @@ -243,7 +243,7 @@ public void ReplaceOne() new { _id = 4, title = "Book 4", pages = 50 }, }; Result result = ExecuteAddStatement(collection.Add(docs)); - Assert.AreEqual(4, result.AffectedItemsCount); + Assert.That(result.AffectedItemsCount, Is.EqualTo(4)); // Expected exceptions. Assert.Throws(() => collection.ReplaceOne(null, docs[1])); @@ -257,22 +257,22 @@ public void ReplaceOne() var newDoc = new { _id = 1, title = "Book 11", pages = 311 }; // Replace using a numeric identifier. - Assert.AreEqual(1, collection.ReplaceOne(1, newDoc).AffectedItemsCount); + Assert.That(collection.ReplaceOne(1, newDoc).AffectedItemsCount, Is.EqualTo(1)); DbDoc document = collection.GetOne(1); - Assert.AreEqual(1, Convert.ToInt32(document.Id)); - Assert.AreEqual("Book 11", document["title"]); - Assert.AreEqual(311, Convert.ToInt32(document["pages"])); + Assert.That(Convert.ToInt32(document.Id), Is.EqualTo(1)); + Assert.That(document["title"], Is.EqualTo("Book 11")); + Assert.That(Convert.ToInt32(document["pages"]), Is.EqualTo(311)); // Replace using a string identifier. - Assert.AreEqual(1, collection.ReplaceOne("2", new DbDoc("{ \"name\": \"John\", \"lastName\": \"Smith\" }")).AffectedItemsCount); + Assert.That(collection.ReplaceOne("2", new DbDoc("{ \"name\": \"John\", \"lastName\": \"Smith\" }")).AffectedItemsCount, Is.EqualTo(1)); document = collection.GetOne(2); - Assert.AreEqual(2, Convert.ToInt32(document.Id)); - Assert.AreEqual("John", document["name"]); - Assert.AreEqual("Smith", document["lastName"]); + Assert.That(Convert.ToInt32(document.Id), Is.EqualTo(2)); + Assert.That(document["name"], Is.EqualTo("John")); + Assert.That(document["lastName"], Is.EqualTo("Smith")); // Replace a non-existing document. - Assert.AreEqual(0, collection.ReplaceOne(5, docs[1]).AffectedItemsCount); - Assert.True(collection.GetOne(5) == null); + Assert.That(collection.ReplaceOne(5, docs[1]).AffectedItemsCount, Is.EqualTo(0)); + Assert.That(collection.GetOne(5) == null); } [Test] @@ -286,17 +286,17 @@ public void ReplaceNestedDocument() new DbDoc(@"{ ""_id"": 3, ""pages"": 40,""title"" : ""Book 3"", ""person"": { ""name"": ""Andy"", ""age"": 25 } }"), new DbDoc(@"{ ""_id"": 4, ""pages"": 50,""title"" : ""Book 4"", ""person"": { ""name"": ""John"", ""age"": 34 } }") }; - Assert.AreEqual(4, ExecuteAddStatement(collection.Add(docs)).AffectedItemsCount); + Assert.That(ExecuteAddStatement(collection.Add(docs)).AffectedItemsCount, Is.EqualTo(4)); DbDoc d_new = new DbDoc(@"{ ""_id"": 1, ""pages"": 20,""title"" : ""Book 1"", ""person"": { ""name"": ""Fred"", ""age"": 45 ,""State"" : ""Ohio""} }"); - Assert.AreEqual(1, collection.ReplaceOne(1, d_new).AffectedItemsCount); + Assert.That(collection.ReplaceOne(1, d_new).AffectedItemsCount, Is.EqualTo(1)); DbDoc document = collection.GetOne(1); - Assert.AreEqual("Ohio", (document.values["person"] as Dictionary)["State"]); + Assert.That((document.values["person"] as Dictionary)["State"], Is.EqualTo("Ohio")); d_new = new DbDoc(@"{ ""_id"": 1, ""pages"": 20,""title"" : ""Book 1"", ""person"": { ""name"": ""Fred"", ""age"": 45 ,""State"" : ""Ohio"", ""newProp"": { ""a"":33 } } }"); - Assert.AreEqual(1, collection.ReplaceOne(1, d_new).AffectedItemsCount); + Assert.That(collection.ReplaceOne(1, d_new).AffectedItemsCount, Is.EqualTo(1)); document = collection.GetOne(1); - Assert.AreEqual(33, ((document.values["person"] as Dictionary)["newProp"] as Dictionary)["a"]); + Assert.That(((document.values["person"] as Dictionary)["newProp"] as Dictionary)["a"], Is.EqualTo(33)); } [Test] @@ -322,22 +322,22 @@ public void ArrayInsert() var document = result.FetchOne(); var x = (object[])document.values["x"]; - Assert.AreEqual(8, x.Length); - Assert.AreEqual(1, (int)x[0]); - Assert.AreEqual(43, (int)x[1]); - Assert.AreEqual(2, (int)x[2]); - Assert.AreEqual(44, (int)x[3]); - Assert.AreEqual(46, (int)x[4]); - Assert.AreEqual(50, (int)x[5]); - Assert.AreEqual("string", x[6]); - Assert.True(new DbDoc(x[7]) is DbDoc); + Assert.That(x.Length, Is.EqualTo(8)); + Assert.That((int)x[0], Is.EqualTo(1)); + Assert.That((int)x[1], Is.EqualTo(43)); + Assert.That((int)x[2], Is.EqualTo(2)); + Assert.That((int)x[3], Is.EqualTo(44)); + Assert.That((int)x[4], Is.EqualTo(46)); + Assert.That((int)x[5], Is.EqualTo(50)); + Assert.That(x[6], Is.EqualTo("string")); + Assert.That(new DbDoc(x[7]) is DbDoc); // No value is inserted if the array doesn't exist. ExecuteModifyStatement(collection.Modify("true").ArrayInsert("y[0]", 1)); result = ExecuteFindStatement(collection.Find()); document = result.FetchOne(); - Assert.False(document.values.ContainsKey("y")); + Assert.That(document.values.ContainsKey("y"), Is.False); ExecuteModifyStatement(collection.Modify("true").ArrayInsert("x[0]", null)); ExecuteModifyStatement(collection.Modify("true").ArrayInsert("x[1]", " ")); @@ -345,18 +345,18 @@ public void ArrayInsert() result = ExecuteFindStatement(collection.Find()); document = result.FetchOne(); x = (object[])document.values["x"]; - Assert.Null(x[0]); - Assert.AreEqual(" ", x[1]); + Assert.That(x[0], Is.Null); + Assert.That(x[1], Is.EqualTo(" ")); // Insert an empty string fails. var ex = Assert.Throws(() => ExecuteModifyStatement(collection.Modify("true").ArrayInsert("x[0]", ""))); - StringAssert.Contains("String can't be empty.", ex.Message); + Assert.That(ex.Message, Does.Contain("String can't be empty.")); ex = Assert.Throws(() => ExecuteModifyStatement(collection.Modify("true").ArrayInsert("x[0]", string.Empty))); - StringAssert.Contains("String can't be empty.", ex.Message); + Assert.That(ex.Message, Does.Contain("String can't be empty.")); // Not specifying an index raises an error. var ex2 = Assert.Throws(() => ExecuteModifyStatement(collection.Modify("true").ArrayInsert("dates", "5/1/2018"))); - Assert.AreEqual("A path expression is not a path to a cell in an array.", ex2.Message); + Assert.That(ex2.Message, Is.EqualTo("A path expression is not a path to a cell in an array.")); var col = CreateCollection("my_collection"); var t1 = "{\"_id\": \"1001\", \"ARR\":[1,2,3], \"ARR1\":[\"name1\",\"name2\", \"name3\"]}"; @@ -372,11 +372,11 @@ public void ArrayInsert() result = ExecuteFindStatement(col.Find()); document = result.FetchOne(); var x2 = (object[])document.values["ARR"]; - Assert.AreEqual(8, x2.Length); - Assert.AreEqual(8, (int)x2[0]); + Assert.That(x2.Length, Is.EqualTo(8)); + Assert.That((int)x2[0], Is.EqualTo(8)); x2 = (object[])document.values["ARR1"]; - Assert.AreEqual("****", x2[0]); - Assert.AreEqual("name3", x2[8]); + Assert.That(x2[0], Is.EqualTo("****")); + Assert.That(x2[8], Is.EqualTo("name3")); } [Test] @@ -388,27 +388,27 @@ public void ArrayAppendWithMySqlExpression() ExecuteAddStatement(collection.Add("{ \"_id\":\"123\", \"name\":\"alice\", \"email\":[ \"alice@ora.com\" ], \"dates\":\"4/1/2017\" }")); ExecuteModifyStatement(collection.Modify("true").ArrayAppend("email", "UPPER($.name)")); var document = collection.GetOne("123"); - Assert.AreEqual("UPPER($.name)", (document["email"] as object[])[1]); + Assert.That((document["email"] as object[])[1], Is.EqualTo("UPPER($.name)")); // Use MySqlExpression. ExecuteAddStatement(collection.Add("{ \"_id\":\"124\", \"name\":\"alice\", \"value\":[ \"alice@ora.com\" ], \"dates\":\"4/1/2017\" }")); ExecuteModifyStatement(collection.Modify("_id = \"124\"").ArrayAppend("value", new MySqlExpression("UPPER($.name)"))); document = collection.GetOne("124"); - Assert.AreEqual("ALICE", (document["value"] as object[])[1]); + Assert.That((document["value"] as object[])[1], Is.EqualTo("ALICE")); // Use embedded MySqlExpression. ExecuteAddStatement(collection.Add("{ \"_id\":\"125\", \"name\":\"alice\", \"value\":[ \"alice@ora.com\" ], \"dates\":\"4/1/2017\" }")); ExecuteModifyStatement(collection.Modify("_id = \"125\"").ArrayAppend("value", new { expression = new MySqlExpression("UPPER($.name)") })); document = collection.GetOne("125"); var item = ((document["value"] as object[])[1] as Dictionary); - Assert.AreEqual("ALICE", item["expression"]); + Assert.That(item["expression"], Is.EqualTo("ALICE")); ExecuteAddStatement(collection.Add("{ \"_id\":\"126\", \"name\":\"alice\", \"value\":[ \"alice@ora.com\" ], \"dates\":\"4/1/2017\" }")); ExecuteModifyStatement(collection.Modify("_id = \"126\"").ArrayAppend("value", new { expression = new MySqlExpression("UPPER($.name)"), literal = "UPPER($.name)" })); document = collection.GetOne("126"); item = ((document["value"] as object[])[1] as Dictionary); - Assert.AreEqual("ALICE", item["expression"]); - Assert.AreEqual("UPPER($.name)", item["literal"]); + Assert.That(item["expression"], Is.EqualTo("ALICE")); + Assert.That(item["literal"], Is.EqualTo("UPPER($.name)")); } [Test] @@ -420,8 +420,8 @@ public void ArrayAppendUsesCorrectDataTypes() ExecuteModifyStatement(collection.Modify("true").ArrayAppend("dates", 1)); var document = collection.GetOne("123"); var dates = document["dates"] as object[]; - Assert.True(dates[1] is string); - Assert.True(dates[2] is int); + Assert.That(dates[1] is string); + Assert.That(dates[2] is int); } [Test] @@ -440,26 +440,26 @@ public void ArrayAppend() DbDoc document = result.FetchOne(); var x = (object[])document.values["x"]; - Assert.AreEqual(7, x.Length); - Assert.AreEqual(1, (int)x[0]); - Assert.AreEqual(2, (int)x[1]); - Assert.AreEqual(43, (int)x[2]); - Assert.AreEqual("string", x[3]); - Assert.AreEqual(true, x[4]); - Assert.Null(x[5]); - Assert.AreEqual(" ", x[6]); + Assert.That(x.Length, Is.EqualTo(7)); + Assert.That((int)x[0], Is.EqualTo(1)); + Assert.That((int)x[1], Is.EqualTo(2)); + Assert.That((int)x[2], Is.EqualTo(43)); + Assert.That(x[3], Is.EqualTo("string")); + Assert.That(x[4], Is.EqualTo(true)); + Assert.That(x[5], Is.Null); + Assert.That(x[6], Is.EqualTo(" ")); // No value is appended if the array doesn't exist. ExecuteModifyStatement(collection.Modify("true").ArrayAppend("y", 45)); result = ExecuteFindStatement(collection.Find()); document = result.FetchOne(); - Assert.False(document.values.ContainsKey("y")); + Assert.That(document.values.ContainsKey("y"), Is.False); var ex = Assert.Throws(() => ExecuteModifyStatement(collection.Modify("true").ArrayAppend("x", ""))); - StringAssert.Contains("String can't be empty.", ex.Message); + Assert.That(ex.Message, Does.Contain("String can't be empty.")); ex = Assert.Throws(() => ExecuteModifyStatement(collection.Modify("true").ArrayAppend("x", string.Empty))); - StringAssert.Contains("String can't be empty.", ex.Message); + Assert.That(ex.Message, Does.Contain("String can't be empty.")); var col = CreateCollection("my_collection"); var t1 = "{\"_id\": \"1001\", \"ARR\":[1,2,3], \"ARR1\":[\"name1\",\"name2\", \"name3\"]}"; @@ -483,27 +483,27 @@ public void ArrayInsertWithMySqlExpression() ExecuteAddStatement(collection.Add("{ \"_id\":\"123\", \"name\":\"alice\", \"email\":[ \"alice@ora.com\" ], \"dates\":\"4/1/2017\" }")); ExecuteModifyStatement(collection.Modify("true").ArrayInsert("email[0]", "UPPER($.name)")); var document = collection.GetOne("123"); - Assert.AreEqual("UPPER($.name)", (document["email"] as object[])[0]); + Assert.That((document["email"] as object[])[0], Is.EqualTo("UPPER($.name)")); // Use MySqlExpression. ExecuteAddStatement(collection.Add("{ \"_id\":\"124\", \"name\":\"alice\", \"email\":[ \"alice@ora.com\" ], \"dates\":\"4/1/2017\" }")); ExecuteModifyStatement(collection.Modify("_id = \"124\"").ArrayInsert("email[0]", new MySqlExpression("UPPER($.name)"))); document = collection.GetOne("124"); - Assert.AreEqual("ALICE", (document["email"] as object[])[0]); + Assert.That((document["email"] as object[])[0], Is.EqualTo("ALICE")); // Use embedded MySqlExpression. ExecuteAddStatement(collection.Add("{ \"_id\":\"125\", \"name\":\"alice\", \"email\":[ \"alice@ora.com\" ], \"dates\":\"4/1/2017\" }")); ExecuteModifyStatement(collection.Modify("_id = \"125\"").ArrayInsert("email[0]", new { other = new MySqlExpression("UPPER($.name)") })); document = collection.GetOne("125"); var item = ((document["email"] as object[])[0] as Dictionary); - Assert.AreEqual("ALICE", item["other"]); + Assert.That(item["other"], Is.EqualTo("ALICE")); ExecuteAddStatement(collection.Add("{ \"_id\":\"126\", \"name\":\"alice\", \"email\":[ \"alice@ora.com\" ], \"dates\":\"4/1/2017\" }")); ExecuteModifyStatement(collection.Modify("_id = \"126\"").ArrayInsert("email[0]", new { other = new MySqlExpression("UPPER($.name)"), literal = "UPPER($.name)" })); document = collection.GetOne("126"); item = ((document["email"] as object[])[0] as Dictionary); - Assert.AreEqual("ALICE", item["other"]); - Assert.AreEqual("UPPER($.name)", item["literal"]); + Assert.That(item["other"], Is.EqualTo("ALICE")); + Assert.That(item["literal"], Is.EqualTo("UPPER($.name)")); } [Test] @@ -511,11 +511,11 @@ public void ArrayOperationsKeepDateValue() { Collection collection = CreateCollection("test"); Result r = ExecuteAddStatement(collection.Add("{ \"_id\": \"123\", \"email\":[\"alice@ora.com\"], \"dates\": \"5/1/2018\" }")); - Assert.AreEqual(1ul, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(1ul)); // No items are affected since dates isn't an array. r = ExecuteModifyStatement(collection.Modify("true").ArrayInsert("dates[0]", "4/1/2018")); - Assert.AreEqual(0ul, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(0ul)); // Converts a non array to an array by appending a value. ExecuteModifyStatement(collection.Modify("true").ArrayAppend("dates", "6/1/2018")); @@ -525,10 +525,10 @@ public void ArrayOperationsKeepDateValue() DbDoc document = collection.GetOne("123"); object[] dates = document["dates"] as object[]; - Assert.AreEqual(3, dates.Length); - Assert.AreEqual("4/1/2018", dates[0]); - Assert.AreEqual("5/1/2018", dates[1]); - Assert.AreEqual("6/1/2018", dates[2]); + Assert.That(dates.Length, Is.EqualTo(3)); + Assert.That(dates[0], Is.EqualTo("4/1/2018")); + Assert.That(dates[1], Is.EqualTo("5/1/2018")); + Assert.That(dates[2], Is.EqualTo("6/1/2018")); } [Test] @@ -553,16 +553,16 @@ public void Alphanumeric() } var crudresult = collection.Find("pages=10").Execute().FetchAll(); - Assert.AreEqual(1, crudresult.Count, "Count should be 1 before Unset of pages for _id=0."); + Assert.That(crudresult.Count, Is.EqualTo(1), "Count should be 1 before Unset of pages for _id=0."); var result = collection.Modify("_id = 0").Unset("pages").Execute(); - Assert.AreEqual(1, result.AffectedItemsCount, "Affected Items Count when modify unset is used"); + Assert.That(result.AffectedItemsCount, Is.EqualTo(1), "Affected Items Count when modify unset is used"); crudresult = collection.Find("pages=10").Execute().FetchAll(); - Assert.AreEqual(0, crudresult.Count, "Count should be 0 after Unset of pages for _id=0"); + Assert.That(crudresult.Count, Is.EqualTo(0), "Count should be 0 after Unset of pages for _id=0"); crudresult = collection.Find("books='test0'").Execute().FetchAll(); - Assert.AreEqual(1, crudresult.Count, "Count should be 0 after Unset of pages for _id=0"); + Assert.That(crudresult.Count, Is.EqualTo(1), "Count should be 0 after Unset of pages for _id=0"); result = collection.Modify("_id = 21").Unset("1address").Execute(); - Assert.AreEqual(1, result.AffectedItemsCount, "Affected Items Count when modify unset(multiple docs) is used"); + Assert.That(result.AffectedItemsCount, Is.EqualTo(1), "Affected Items Count when modify unset(multiple docs) is used"); } [Test] @@ -574,22 +574,22 @@ public void UnsetVariations() // Whitespace is ignored. ExecuteModifyStatement(collection.Modify("_id = 1").Unset("pages ")); - Assert.False(collection.GetOne(1).values.ContainsKey("pages")); + Assert.That(collection.GetOne(1).values.ContainsKey("pages"), Is.False); ExecuteModifyStatement(collection.Modify("_id = 1").Unset(" pages2 ")); - Assert.False(collection.GetOne(1).values.ContainsKey("pages2")); + Assert.That(collection.GetOne(1).values.ContainsKey("pages2"), Is.False); ExecuteModifyStatement(collection.Modify("_id = 1").Unset(" pages3")); - Assert.False(collection.GetOne(1).values.ContainsKey("pages3")); + Assert.That(collection.GetOne(1).values.ContainsKey("pages3"), Is.False); ExecuteModifyStatement(collection.Modify("_id = 1").Unset(" pages4.internalPages ")); - Assert.True(collection.GetOne(1).values.ContainsKey("pages4")); - Assert.False(collection.GetOne(1).values.ContainsKey("pages4.internalPages")); + Assert.That(collection.GetOne(1).values.ContainsKey("pages4")); + Assert.That(collection.GetOne(1).values.ContainsKey("pages4.internalPages"), Is.False); // Error is raised with incorrect document path. var ex = Assert.Throws(() => ExecuteModifyStatement(collection.Modify("_id = 1").Unset("pages*"))); - Assert.AreEqual("Invalid document path.", ex.Message); + Assert.That(ex.Message, Is.EqualTo("Invalid document path.")); ex = Assert.Throws(() => ExecuteModifyStatement(collection.Modify("_id = 1").Unset("pages!"))); - Assert.AreEqual("Invalid document path.", ex.Message); + Assert.That(ex.Message, Is.EqualTo("Invalid document path.")); ex = Assert.Throws(() => ExecuteModifyStatement(collection.Modify("_id = 1").Unset("pages*data"))); - Assert.AreEqual("Invalid document path.", ex.Message); + Assert.That(ex.Message, Is.EqualTo("Invalid document path.")); } #region WL14389 @@ -612,43 +612,43 @@ public void CollectionModifyUnset() } var crudresult = col.Find("pages=10").Execute().FetchAll(); - Assert.AreEqual(1, crudresult.Count, "Count should be 1 before Unset of pages for _id=0."); + Assert.That(crudresult.Count, Is.EqualTo(1), "Count should be 1 before Unset of pages for _id=0."); var result = col.Modify("_id = 0").Unset("pages").Execute(); - Assert.AreEqual(1, result.AffectedItemsCount, "Affected Items Count when modify unset is used"); + Assert.That(result.AffectedItemsCount, Is.EqualTo(1), "Affected Items Count when modify unset is used"); crudresult = col.Find("pages=10").Execute().FetchAll(); - Assert.AreEqual(0, crudresult.Count, "Count should be 0 after Unset of pages for _id=0"); + Assert.That(crudresult.Count, Is.EqualTo(0), "Count should be 0 after Unset of pages for _id=0"); crudresult = col.Find("books='test0'").Execute().FetchAll(); - Assert.AreEqual(1, crudresult.Count, "Count should be 0 after Unset of pages for _id=0"); + Assert.That(crudresult.Count, Is.EqualTo(1), "Count should be 0 after Unset of pages for _id=0"); crudresult = col.Find("pages=11").Execute().FetchAll(); - Assert.AreEqual(1, crudresult.Count, "Count of pages=11 should be 1 before Unset of pages for _id=1."); + Assert.That(crudresult.Count, Is.EqualTo(1), "Count of pages=11 should be 1 before Unset of pages for _id=1."); crudresult = col.Find("reviewers='reviewers1'").Execute().FetchAll(); - Assert.AreEqual(1, crudresult.Count, "Count of reviewers1 should be 1 before Unset of pages for _id=1."); + Assert.That(crudresult.Count, Is.EqualTo(1), "Count of reviewers1 should be 1 before Unset of pages for _id=1."); result = col.Modify("_id = 1").Unset("pages").Unset("reviewers").Execute(); - Assert.AreEqual(1, result.AffectedItemsCount, "Affected Items Count when modify multiple unset is used"); + Assert.That(result.AffectedItemsCount, Is.EqualTo(1), "Affected Items Count when modify multiple unset is used"); crudresult = col.Find("pages=11").Execute().FetchAll(); - Assert.AreEqual(0, crudresult.Count, "Count should be 0 after Unset of pages for _id=1"); + Assert.That(crudresult.Count, Is.EqualTo(0), "Count should be 0 after Unset of pages for _id=1"); crudresult = col.Find("reviewers='reviewers1'").Execute().FetchAll(); - Assert.AreEqual(0, crudresult.Count, "Count should be 0 after Unset of pages for _id=1"); + Assert.That(crudresult.Count, Is.EqualTo(0), "Count should be 0 after Unset of pages for _id=1"); crudresult = col.Find("pages=21").Execute().FetchAll(); - Assert.AreEqual(1, crudresult.Count, "Count of pages=21 should be 1 before Unset of pages for _id=11."); + Assert.That(crudresult.Count, Is.EqualTo(1), "Count of pages=21 should be 1 before Unset of pages for _id=11."); crudresult = col.Find("reviewers='reviewers11'").Execute().FetchAll(); - Assert.AreEqual(1, crudresult.Count, "Count of reviewers11 should be 1 before Unset of pages for _id=11."); + Assert.That(crudresult.Count, Is.EqualTo(1), "Count of reviewers11 should be 1 before Unset of pages for _id=11."); result = col.Modify("_id = 11").Unset(new string[] { "pages", "reviewers" }).Execute(); - Assert.AreEqual(1, result.AffectedItemsCount, "Affected Items Count when modify unset(multiple docs) is used"); + Assert.That(result.AffectedItemsCount, Is.EqualTo(1), "Affected Items Count when modify unset(multiple docs) is used"); crudresult = col.Find("pages=21").Execute().FetchAll(); - Assert.AreEqual(0, crudresult.Count, "Count should be 0 after Unset of pages for _id=11"); + Assert.That(crudresult.Count, Is.EqualTo(0), "Count should be 0 after Unset of pages for _id=11"); crudresult = col.Find("reviewers='reviewers11'").Execute().FetchAll(); - Assert.AreEqual(0, crudresult.Count, "Count should be 0 after Unset of pages for _id=11"); + Assert.That(crudresult.Count, Is.EqualTo(0), "Count should be 0 after Unset of pages for _id=11"); crudresult = col.Find("pages=31").Execute().FetchAll(); - Assert.AreEqual(1, crudresult.Count, "Count of pages=31 should be 1 before Unset of pages for _id=21."); + Assert.That(crudresult.Count, Is.EqualTo(1), "Count of pages=31 should be 1 before Unset of pages for _id=21."); crudresult = col.Find("reviewers='reviewers21'").Execute().FetchAll(); - Assert.AreEqual(1, crudresult.Count, "Count of reviewers21 should be 1 before Unset of pages for _id=21."); + Assert.That(crudresult.Count, Is.EqualTo(1), "Count of reviewers21 should be 1 before Unset of pages for _id=21."); result = col.Modify("_id = 21").Unset(" pages ").Execute(); - Assert.AreEqual(1, result.AffectedItemsCount, "Affected Items Count when modify unset(multiple docs) is used"); + Assert.That(result.AffectedItemsCount, Is.EqualTo(1), "Affected Items Count when modify unset(multiple docs) is used"); //Should have failed when unset is used for fields with special characters Assert.Throws(() => ExecuteModifyStatement(col.Modify("_id = 22").Unset("pages*"))); //Should have failed when unset is used for non-existent fields @@ -659,41 +659,41 @@ public void CollectionModifyUnset() Assert.Throws(() => ExecuteModifyStatement(col.Modify("_id = 21").Unset("*******"))); crudresult = col.Find("pages=31").Execute().FetchAll(); - Assert.AreEqual(0, crudresult.Count, "Count should be 0 after Unset of pages for _id=21"); + Assert.That(crudresult.Count, Is.EqualTo(0), "Count should be 0 after Unset of pages for _id=21"); result = col.Modify("_id = 12").Unset(new string[] { " pages1", "reviewers1" }).Execute(); - Assert.AreEqual(0, result.AffectedItemsCount, "Affected Items Count when modify unset(invalid docs) is used"); + Assert.That(result.AffectedItemsCount, Is.EqualTo(0), "Affected Items Count when modify unset(invalid docs) is used"); crudresult = col.Find("pages=22").Execute().FetchAll(); - Assert.AreEqual(1, crudresult.Count, "Count should be 1 after Unset with invalid of pages for _id=12"); + Assert.That(crudresult.Count, Is.EqualTo(1), "Count should be 1 after Unset with invalid of pages for _id=12"); crudresult = col.Find("reviewers='reviewers12'").Execute().FetchAll(); - Assert.AreEqual(1, crudresult.Count, "Count should be 1 after Unset with invalid of pages for _id=12"); + Assert.That(crudresult.Count, Is.EqualTo(1), "Count should be 1 after Unset with invalid of pages for _id=12"); //Testcase should have failed when unset is used with null Assert.Throws(() => ExecuteModifyStatement(col.Modify("_id = 12").Unset(null))); crudresult = col.Find("pages=22").Execute().FetchAll(); - Assert.AreEqual(1, crudresult.Count, "Count should be 1 after Unset with null of pages for _id=12"); + Assert.That(crudresult.Count, Is.EqualTo(1), "Count should be 1 after Unset with null of pages for _id=12"); crudresult = col.Find("reviewers='reviewers12'").Execute().FetchAll(); - Assert.AreEqual(1, crudresult.Count, "Count should be 1 after Unset with null of pages for _id=12"); + Assert.That(crudresult.Count, Is.EqualTo(1), "Count should be 1 after Unset with null of pages for _id=12"); Assert.Throws(() => ExecuteModifyStatement(col.Modify("_id = 12").Unset(""))); crudresult = col.Find("pages=22").Execute().FetchAll(); - Assert.AreEqual(1, crudresult.Count, "Count should be 1 after Unset with blank of pages for _id=12"); + Assert.That(crudresult.Count, Is.EqualTo(1), "Count should be 1 after Unset with blank of pages for _id=12"); crudresult = col.Find("reviewers='reviewers12'").Execute().FetchAll(); - Assert.AreEqual(1, crudresult.Count, "Count should be 1 after Unset with blank of pages for _id=12"); + Assert.That(crudresult.Count, Is.EqualTo(1), "Count should be 1 after Unset with blank of pages for _id=12"); crudresult = col.Find("pages=22").Execute().FetchAll(); - Assert.AreEqual(1, crudresult.Count, "Count should be 1 after Unset with blank with space of pages for _id=12"); + Assert.That(crudresult.Count, Is.EqualTo(1), "Count should be 1 after Unset with blank with space of pages for _id=12"); crudresult = col.Find("reviewers='reviewers12'").Execute().FetchAll(); - Assert.AreEqual(1, crudresult.Count, "Count should be 1 after Unset with blank with space of pages for _id=12"); + Assert.That(crudresult.Count, Is.EqualTo(1), "Count should be 1 after Unset with blank with space of pages for _id=12"); //Testcase should have failed when unset is used with blank and space Assert.Throws(() => ExecuteModifyStatement(col.Modify("_id = 12").Unset(new string[] { "", " ", "pages" }))); crudresult = col.Find("pages=22").Execute().FetchAll(); - Assert.AreEqual(1, crudresult.Count); + Assert.That(crudresult.Count, Is.EqualTo(1)); crudresult = col.Find("reviewers='reviewers12'").Execute().FetchAll(); - Assert.AreEqual(1, crudresult.Count); + Assert.That(crudresult.Count, Is.EqualTo(1)); } [Test, Description("All Bug Fixes")] @@ -703,40 +703,40 @@ public void ValidateValuesAfterAppendAndInserts() Collection collection = CreateCollection("test"); Result r = collection.Add("{ \"_id\": \"123\", \"email\": [\"alice@ora.com\"], " + "\"dates\": \"4/1/2017\" }").Execute(); - Assert.AreEqual(1, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(1)); collection.Modify("true").ArrayAppend("dates", "5/1/2018").Execute(); document = collection.GetOne("123"); object[] dates = document["dates"] as object[]; - Assert.AreEqual(2, dates.Length); - Assert.AreEqual("4/1/2017", dates[0], "Existing Date"); - Assert.AreEqual("5/1/2018", dates[1], "Appended Date"); + Assert.That(dates.Length, Is.EqualTo(2)); + Assert.That(dates[0], Is.EqualTo("4/1/2017"), "Existing Date"); + Assert.That(dates[1], Is.EqualTo("5/1/2018"), "Appended Date"); collection.Modify("true").ArrayInsert("dates[0]", "5/1/2059").Execute(); document = collection.GetOne("123"); dates = document["dates"] as object[]; - Assert.AreEqual("5/1/2059", dates[0], "Inserted Date"); + Assert.That(dates[0], Is.EqualTo("5/1/2059"), "Inserted Date"); collection = CreateCollection("test"); r = collection.Add("{ \"_id\": \"123\", \"email\": [\"alice@ora.com\"], " + "\"dates\": [\"4/1/2017\"] }").Execute(); - Assert.AreEqual(1, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(1)); collection = CreateCollection("test"); r = collection.Add("{ \"_id\": \"123\", \"email\": [\"alice@ora.com\"], " + "\"dates\": \"4/1/2017\" }").Execute(); - Assert.AreEqual(1, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(1)); collection.Modify("true").ArrayAppend("dates", "1").Execute(); collection.Modify("true").ArrayAppend("dates", 1).Execute(); collection.Modify("true").ArrayAppend("dates", "3.1").Execute(); collection.Modify("true").ArrayAppend("dates", 3.1).Execute(); document = collection.GetOne("123"); dates = document["dates"] as object[]; - Assert.AreEqual(5, dates.Length); - Assert.AreEqual("4/1/2017", dates[0], "Existing Date"); - Assert.AreEqual("1", dates[1], "Appended Date"); - Assert.AreEqual(1, dates[2], "Appended Date"); - Assert.AreEqual("3.1", dates[3], "Appended Date"); - Assert.AreEqual(3.1, dates[4], "Appended Date"); + Assert.That(dates.Length, Is.EqualTo(5)); + Assert.That(dates[0], Is.EqualTo("4/1/2017"), "Existing Date"); + Assert.That(dates[1], Is.EqualTo("1"), "Appended Date"); + Assert.That(dates[2], Is.EqualTo(1), "Appended Date"); + Assert.That(dates[3], Is.EqualTo("3.1"), "Appended Date"); + Assert.That(dates[4], Is.EqualTo(3.1), "Appended Date"); collection.Modify("true").ArrayInsert("dates[0]", "10").Execute(); collection.Modify("true").ArrayInsert("dates[0]", 1000).Execute(); @@ -744,10 +744,10 @@ public void ValidateValuesAfterAppendAndInserts() collection.Modify("true").ArrayInsert("dates[0]", 22.7).Execute(); document = collection.GetOne("123"); dates = document["dates"] as object[]; - Assert.AreEqual("10", dates[3], "Inserted Date"); - Assert.AreEqual(1000, dates[2], "Inserted Date"); - Assert.AreEqual("3.1", dates[1], "Inserted Date"); - Assert.AreEqual(22.7, dates[0], "Inserted Date"); + Assert.That(dates[3], Is.EqualTo("10"), "Inserted Date"); + Assert.That(dates[2], Is.EqualTo(1000), "Inserted Date"); + Assert.That(dates[1], Is.EqualTo("3.1"), "Inserted Date"); + Assert.That(dates[0], Is.EqualTo(22.7), "Inserted Date"); var d1 = new DbDoc(); for (int i = 0; i < 30; i++) @@ -774,9 +774,9 @@ public void ValidateValuesAfterAppendAndInserts() new { _id = 400, title = "Book 4", pages = 50 }, }; r = collection.Add(docs).Execute(); - Assert.AreEqual(4, r.AffectedItemsCount, "Matching the records affected"); + Assert.That(r.AffectedItemsCount, Is.EqualTo(4), "Matching the records affected"); var test1 = collection.Find("pages = :Pages").Bind("pAges", 90).Fields("{\"_id\":100,\"pages\": 20 }").Execute(); - Assert.IsNotNull(test1); + Assert.That(test1, Is.Not.Null); } [Test, Description("Collection.modify(condition).arrayAppend(CollectionField, ExprOrLiteral)")] @@ -788,7 +788,7 @@ public void CollectionModifyArrayAppend() string t1 = "{\"_id\": \"1\", \"name\": \"Alice\" }"; var collection = CreateCollection("test"); Result r = collection.Add(t1).Execute(); - Assert.AreEqual(1, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(1)); object[] expressions1 = new object[] { "YEAR('2000-01-01')", "MONTH('2008-02-03')", "WEEK('2008-02-20')", "DAY('2008-02-20')", "HOUR('10:05:03')", "MINUTE('2008-02-03 10:05:03')","SECOND('10:05:03')","MICROSECOND('12:00:00.123456')","QUARTER('2008-04-01')","TIME('2003-12-31 01:02:03')","DATE('2003-12-31 01:02:03')", "Year(CURDATE())"}; @@ -817,7 +817,7 @@ public void CollectionModifyArrayAppend() actors = document["name"] as object[]; actor0 = actors[l] as Dictionary; test = actor0["dateAndTimeValue"]; - Assert.AreEqual(compare_expressions1[k].ToString(), test.ToString()); + Assert.That(test.ToString(), Is.EqualTo(compare_expressions1[k].ToString())); l++; } for (int k = 0; k < compare_expressions2.Length; k++) @@ -827,14 +827,14 @@ public void CollectionModifyArrayAppend() actors = document["name"] as object[]; actor0 = actors[l] as Dictionary; test = actor0["dateAndTimeValue"]; - Assert.AreEqual(compare_expressions2[k].ToString(), test.ToString()); + Assert.That(test.ToString(), Is.EqualTo(compare_expressions2[k].ToString())); l++; } collection = CreateCollection("test"); r = collection.Add("{ \"_id\": \"123\", \"email\": [\"alice@ora.com\"], " + "\"dates\": [\"4/1/2017\"] }").Execute(); - Assert.AreEqual(1, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(1)); var reg_expression = new { test1 = new MySqlExpression("UPPER($.email)"), @@ -885,7 +885,7 @@ public void CollectionModifyArrayAppend() { } else { - Assert.AreEqual(actors[m], compare_expressions[n]); + Assert.That(compare_expressions[n], Is.EqualTo(actors[m])); } m++; n++; @@ -914,11 +914,11 @@ public void CollectionModifyArrayAppend() collection.Add(json).Execute(); r = collection.Modify("true").ArrayAppend("ARR10", 1).ArrayAppend("ARR20", 2).ArrayAppend("ARR30", 3).Execute(); - Assert.AreEqual(1, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(1)); r = collection.Modify("true").ArrayAppend("ARR0", null).Execute(); - Assert.AreEqual(1, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(1)); r = collection.Modify("true").ArrayAppend("ARR39", null).Execute(); - Assert.AreEqual(1, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(1)); } @@ -935,7 +935,7 @@ public void ForbidModifyWithNoCondition_S1() new { _id = 4, title = "Book 4", pages = 50 }, }; Result result = collection.Add(docs).Execute(); - Assert.AreEqual(4, result.AffectedItemsCount); + Assert.That(result.AffectedItemsCount, Is.EqualTo(4)); // Condition can't be null or empty. Assert.Throws(() => ExecuteModifyStatement(collection.Modify(string.Empty))); @@ -944,7 +944,7 @@ public void ForbidModifyWithNoCondition_S1() // Sending an expression that evaluates to true applies changes on all documents. result = collection.Modify("true").Set("pages", "10").Execute(); - Assert.AreEqual(4, result.AffectedItemsCount); + Assert.That(result.AffectedItemsCount, Is.EqualTo(4)); } @@ -961,19 +961,19 @@ public void ForbidModifyWithNoCondition_S2() new { _id = 4, title = "Book 4", pages = 50 }, }; Result result = collection.Add(docs).Execute(); - Assert.AreEqual(4, result.AffectedItemsCount); + Assert.That(result.AffectedItemsCount, Is.EqualTo(4)); // Sending an expression that evaluates to true applies changes on all documents. //Deprecated Modify().Where() in 8.0.17 result = collection.Modify("true").Where("false").Set("pages", "10").Execute(); - Assert.AreEqual(0, result.AffectedItemsCount); + Assert.That(result.AffectedItemsCount, Is.EqualTo(0)); result = collection.Modify("true").Where("true").Set("pages", "10").Execute(); - Assert.AreEqual(4, result.AffectedItemsCount); + Assert.That(result.AffectedItemsCount, Is.EqualTo(4)); result = collection.Modify("false").Where("true").Set("pages", "40").Execute(); - Assert.AreEqual(4, result.AffectedItemsCount); + Assert.That(result.AffectedItemsCount, Is.EqualTo(4)); result = collection.Modify("false").Where("false").Set("pages", "40").Execute(); - Assert.AreEqual(0, result.AffectedItemsCount); + Assert.That(result.AffectedItemsCount, Is.EqualTo(0)); // Condition can't be null or empty. Assert.Throws(() => ExecuteModifyStatement(collection.Modify(" "))); @@ -1006,7 +1006,7 @@ public void ModifyPatchNDepth() var r = collection.Modify("age = :age").Patch(json). Bind("age", "18").Execute(); - Assert.IsNotNull(r); + Assert.That(r, Is.Not.Null); } [Test, Description("Test valid modify.patch with condition/limit/OrderBy")] @@ -1022,25 +1022,25 @@ public void ModifyPatch() new {_id = 4, title = "Book 4", pages = 50,age = 15} }; var r = collection.Add(docs).Execute(); - Assert.AreEqual(4, (int)r.AffectedItemsCount, "Matching the updated record count"); + Assert.That((int)r.AffectedItemsCount, Is.EqualTo(4), "Matching the updated record count"); var jsonParams = new { title = "Book 100" }; var foundDocs = collection.Modify("age==18").Patch(jsonParams).Execute(); - Assert.AreEqual(1, (int)foundDocs.AffectedItemsCount, "Matching the record count"); + Assert.That((int)foundDocs.AffectedItemsCount, Is.EqualTo(1), "Matching the record count"); var document = collection.GetOne("2"); - Assert.AreEqual("Book 100", document["title"]); + Assert.That(document["title"], Is.EqualTo("Book 100")); jsonParams = new { title = "Book 300" }; r = collection.Modify("age<18").Patch(jsonParams).Limit(1).Execute(); - Assert.AreEqual(1, (int)r.AffectedItemsCount, "Matching the record count"); + Assert.That((int)r.AffectedItemsCount, Is.EqualTo(1), "Matching the record count"); document = collection.GetOne(1); - Assert.AreEqual("Book 300", document["title"]); + Assert.That(document["title"], Is.EqualTo("Book 300")); var jsonParams1 = new { title = "Book 10", pages = 1000 }; r = collection.Modify("age>30").Patch(jsonParams1).Sort("age ASC").Execute(); - Assert.AreEqual(1, (int)r.AffectedItemsCount, "Matching the record count"); + Assert.That((int)r.AffectedItemsCount, Is.EqualTo(1), "Matching the record count"); } [Test, Description("Test valid modify.patch with set/unset")] @@ -1056,25 +1056,25 @@ public void ModifyPatchWithSetUnset() new {_id = 4, title = "Book 4", pages = 50,age = "12"} }; Result r = collection.Add(docs).Execute(); - Assert.AreEqual(4, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(4)); var jsonParams = new { title = "Book 500" }; r = collection.Modify("age = :age").Patch(jsonParams).Bind("age", "18"). Set("pages", "5000").Execute(); - Assert.AreEqual(1, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(1)); var document = collection.GetOne("2"); - Assert.AreEqual("5000", document["pages"].ToString()); - Assert.AreEqual("Book 500", document["title"].ToString()); + Assert.That(document["pages"].ToString(), Is.EqualTo("5000")); + Assert.That(document["title"].ToString(), Is.EqualTo("Book 500")); var jsonParams1 = new { title = "Book 50000", pages = 5000 }; r = collection.Modify("age = :age").Patch(jsonParams1).Bind("age", "18"). Unset("pages").Execute(); - Assert.AreEqual(1, r.AffectedItemsCount, "Match being done"); + Assert.That(r.AffectedItemsCount, Is.EqualTo(1), "Match being done"); document = collection.GetOne("2"); DbDoc test = null; Assert.Throws(() => test = (DbDoc)document["pages"]); - Assert.AreEqual("Book 50000", document["title"]); + Assert.That(document["title"], Is.EqualTo("Book 50000")); } [Test, Description("Test invalid modify.patch to attempt to change _id using modify.patch")] @@ -1090,29 +1090,29 @@ public void ModifyPatchChangeId() new {_id = 4, title = "Book 4", pages = 50,age = 12} }; Result r = collection.Add(docs).Execute(); - Assert.AreEqual(4, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(4)); var document = collection.GetOne("1"); var jsonParams = new { _id = 123 }; r = collection.Modify("age = :age").Patch(jsonParams). Bind("age", 18).Execute(); - Assert.AreEqual(0, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(0)); var jsonParams2 = new { _id = 123, title = "Book 4000" }; r = collection.Modify("age = :age").Patch(jsonParams2). Bind("age", 18).Execute(); - Assert.AreEqual(1, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(1)); string jsonParams1 = "{ \"_id\": \"123\"}"; r = collection.Modify("age = :age").Patch(jsonParams1). Bind("age", 18).Execute(); - Assert.AreEqual(0, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(0)); jsonParams1 = "{ \"_id\": \"123\",\"title\": \"Book 400\"}"; r = collection.Modify("age = :age").Patch(jsonParams1). Bind("age", 18).Execute(); - Assert.AreEqual(1, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(1)); } [Test, Description("Test modify.patch where the key to be modified has array, dbDoc and normal constant value and condition is matched for all.")] @@ -1130,14 +1130,14 @@ public void ModifyPatchKeyWithArray() var docs3 = "{\"_id\": \"3\", \"age\": 12,\"name\":[\"Cynthia\"], \"ARR1\":[\"name1\",\"name2\", \"name3\"]}"; Result r = collection.Add(docs1).Execute(); - Assert.AreEqual(1, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(1)); r = collection.Add(docs2).Execute(); - Assert.AreEqual(1, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(1)); r = collection.Add(docs3).Execute(); - Assert.AreEqual(1, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(1)); var jsonParams = new { name = "Changed" }; r = collection.Modify("age = :age").Patch(jsonParams).Bind("age", 12).Execute(); - Assert.AreEqual(3, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(3)); } [Test, Description("Test that documents not matching conditions are not modified.")] @@ -1153,17 +1153,17 @@ public void ModifyPatchNotMatchingConditions() new {_id = 4, title = "Book 4", pages = 50,age = 12} }; Result r = collection.Add(docs).Execute(); - Assert.AreEqual(4, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(4)); var document = collection.GetOne("1"); var jsonParams = new { title = "Book 100" }; r = collection.Modify("age = :age").Patch(jsonParams).Bind("age", "19").Execute(); - Assert.AreEqual(0, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(0)); string jsonParams1 = "{ \"title\": \"Book 100\"}"; r = collection.Modify("age = :age").Patch(jsonParams1).Bind("age", "28").Execute(); - Assert.AreEqual(0, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(0)); jsonParams1 = "{ \"unknownvalues\": null}"; r = collection.Modify("age = :age").Patch(jsonParams1).Bind("age", "28").Execute(); - Assert.AreEqual(0, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(0)); } [Test, Description("Test modify.patch with different types of records(anonymous object,Json String,DbDoc) with same key and try to replace using a patch")] @@ -1186,15 +1186,15 @@ public void ModifyPatchDifferentTypesSameKey() ] }"); Result r = collection.Add(docs1).Execute(); - Assert.AreEqual(1, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(1)); r = collection.Add(docs2).Execute(); - Assert.AreEqual(1, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(1)); r = collection.Add(docs3).Execute(); - Assert.AreEqual(1, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(1)); var jsonParams = new { name = "Changed" }; r = collection.Modify("age = :age").Patch(jsonParams). Bind("age", 12).Execute(); - Assert.AreEqual(2, r.AffectedItemsCount);//docs2 age is the string + Assert.That(r.AffectedItemsCount, Is.EqualTo(2));//docs2 age is the string } [Test, Description("GetOne with ExistingID and NewID with doc(Verify the Immutable feature also))")] @@ -1210,7 +1210,7 @@ public void GetOneAndRemoveOne() new {_id = 4, title = "Book 4", pages = 50} }; var r = coll.Add(docs).Execute(); - Assert.AreEqual(4, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(4)); // Expected exceptions. Assert.Throws(() => coll.GetOne(null)); @@ -1220,39 +1220,39 @@ public void GetOneAndRemoveOne() // Get document using numeric parameter. var document = coll.GetOne(1); - Assert.AreEqual(1, document.Id); - Assert.AreEqual("Book 1", document["title"]); - Assert.AreEqual(20, Convert.ToInt32(document["pages"])); + Assert.That(document.Id, Is.EqualTo(1)); + Assert.That(document["title"], Is.EqualTo("Book 1")); + Assert.That(Convert.ToInt32(document["pages"]), Is.EqualTo(20)); // Get document using string parameter. document = coll.GetOne("3"); - Assert.AreEqual(3, document.Id); - Assert.AreEqual("Book 3", document["title"]); - Assert.AreEqual(40, Convert.ToInt32(document["pages"])); + Assert.That(document.Id, Is.EqualTo(3)); + Assert.That(document["title"], Is.EqualTo("Book 3")); + Assert.That(Convert.ToInt32(document["pages"]), Is.EqualTo(40)); // Get a non-existing document. document = coll.GetOne(5); - Assert.AreEqual(null, document); + Assert.That(document, Is.EqualTo(null)); coll.Add(new { _id = 5, title = "Book 5", pages = 60 }).Execute(); - Assert.AreEqual(5, coll.Find().Execute().FetchAll().Count); + Assert.That(coll.Find().Execute().FetchAll().Count, Is.EqualTo(5)); // Remove sending numeric parameter. //WL11843-Core API v1 alignment Changes - Assert.AreEqual(1, coll.RemoveOne(1).AffectedItemsCount); - Assert.AreEqual(4, coll.Find().Execute().FetchAll().Count); + Assert.That(coll.RemoveOne(1).AffectedItemsCount, Is.EqualTo(1)); + Assert.That(coll.Find().Execute().FetchAll().Count, Is.EqualTo(4)); // Remove sending string parameter. - Assert.AreEqual(1, coll.RemoveOne("3").AffectedItemsCount); - Assert.AreEqual(3, coll.Find().Execute().FetchAll().Count); + Assert.That(coll.RemoveOne("3").AffectedItemsCount, Is.EqualTo(1)); + Assert.That(coll.Find().Execute().FetchAll().Count, Is.EqualTo(3)); // Remove an auto-generated id. document = coll.Find("pages = 60").Execute().FetchOne(); - Assert.AreEqual(1, coll.RemoveOne(document.Id).AffectedItemsCount); - Assert.AreEqual(2, coll.Find().Execute().FetchAll().Count); + Assert.That(coll.RemoveOne(document.Id).AffectedItemsCount, Is.EqualTo(1)); + Assert.That(coll.Find().Execute().FetchAll().Count, Is.EqualTo(2)); // Remove a non-existing document. - Assert.AreEqual(0, coll.RemoveOne(5).AffectedItemsCount); - Assert.AreEqual(2, coll.Find().Execute().FetchAll().Count); + Assert.That(coll.RemoveOne(5).AffectedItemsCount, Is.EqualTo(0)); + Assert.That(coll.Find().Execute().FetchAll().Count, Is.EqualTo(2)); } @@ -1267,7 +1267,7 @@ public void AddReplaceOneUniqueId() new {_id = 2, name = "bar"} }; var result = collection.Add(docs).Execute(); - Assert.AreEqual(2, result.AffectedItemsCount); + Assert.That(result.AffectedItemsCount, Is.EqualTo(2)); // Add unique index. session.SQL( diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/CustomTypeTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/CustomTypeTests.cs index ba9a17c37..90cc1ee73 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/CustomTypeTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/CustomTypeTests.cs @@ -86,7 +86,7 @@ private void InitCollection() Collection.Add(Data).Execute(); var count = session.SQL("SELECT COUNT(*) FROM test.test").Execute().FetchOne()[0]; - Assert.AreEqual(count, Collection.Count()); + Assert.That(Collection.Count(), Is.EqualTo(count)); } [Test] @@ -95,9 +95,9 @@ public void Find() InitCollection(); var result = Collection.Find("_id = :id").Bind("id", 1).Execute().FetchOne(); - Assert.NotNull(result); - Assert.True(typeof(CustomType).Equals(result.GetType())); - Assert.AreEqual(result.DictData["DictData1_1"].Meta, Data[1].DictData["DictData1_1"].Meta); + Assert.That(result, Is.Not.Null); + Assert.That(typeof(CustomType).Equals(result.GetType())); + Assert.That(Data[1].DictData["DictData1_1"].Meta, Is.EqualTo(result.DictData["DictData1_1"].Meta)); } [Test] @@ -106,8 +106,8 @@ public void RemoveOne() InitCollection(); var removeStmt = Collection.RemoveOne(1); - Assert.AreEqual(1, removeStmt.AffectedItemsCount); - Assert.AreEqual(19, Collection.Count()); + Assert.That(removeStmt.AffectedItemsCount, Is.EqualTo(1)); + Assert.That(Collection.Count(), Is.EqualTo(19)); } [TestCase("_id = :id","id",3)] @@ -117,8 +117,8 @@ public void Remove(string condition, string bind,object value) InitCollection(); var removeStmt = Collection.Remove(condition).Bind(bind,value).Execute(); - Assert.AreEqual(1, removeStmt.AffectedItemsCount); - Assert.AreEqual(19, Collection.Count()); + Assert.That(removeStmt.AffectedItemsCount, Is.EqualTo(1)); + Assert.That(Collection.Count(), Is.EqualTo(19)); } [Test] @@ -128,8 +128,8 @@ public void Modify() CustomType customTypeNew = new() { Date = DateTime.Now, Name = "NewDoc" }; var modifyStmt = Collection.Modify("_id = :id").Bind("id", 7).Patch(customTypeNew).Execute(); - Assert.AreEqual(1, modifyStmt.AffectedItemsCount); - Assert.AreEqual("NewDoc", Collection.GetOne(7).Name); + Assert.That(modifyStmt.AffectedItemsCount, Is.EqualTo(1)); + Assert.That(Collection.GetOne(7).Name, Is.EqualTo("NewDoc")); } [Test] @@ -139,14 +139,14 @@ public void PrepareStatement() var findStmt = Collection.Find("_id = :id and Name = :name").Bind("id", 15).Bind("name", "Name_15"); var doc = findStmt.Execute(); - Assert.AreEqual("Name_15", doc.FetchOne().Name); - Assert.False(findStmt._isPrepared); + Assert.That(doc.FetchOne().Name, Is.EqualTo("Name_15")); + Assert.That(findStmt._isPrepared, Is.False); for (int i = 0; i < Data.Length; i++) { doc = findStmt.Bind("id", i).Bind("name", $"Name_{i}").Limit(1).Execute(); - Assert.AreEqual($"Name_{i}", doc.FetchOne().Name); - Assert.True(findStmt._isPrepared || !findStmt.Session.SupportsPreparedStatements); + Assert.That(doc.FetchOne().Name, Is.EqualTo($"Name_{i}")); + Assert.That(findStmt._isPrepared || !findStmt.Session.SupportsPreparedStatements); } } @@ -182,7 +182,7 @@ public void InsertAsync() Task.WaitAll(tasksList.ToArray(), TimeSpan.FromMinutes(1)); var count = session.SQL("SELECT COUNT(*) FROM test.test").Execute().FetchOne()[0]; - Assert.AreEqual(count, Collection.Count()); + Assert.That(Collection.Count(), Is.EqualTo(count)); } } } diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/DbDocTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/DbDocTests.cs index e2acbd9fa..27f54b1d7 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/DbDocTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/DbDocTests.cs @@ -51,7 +51,7 @@ public void SimpleConverstionToJson() ""_id"": 1, ""pages"": 20 }"; - StringAssert.AreEqualIgnoringCase(RemoveLineEndings(json), RemoveLineEndings(s)); + Assert.That(RemoveLineEndings(s), Is.EqualTo(RemoveLineEndings(json)).IgnoreCase); } [Test] @@ -61,7 +61,7 @@ public void SimpleParse() DbDoc d2 = new DbDoc(); d2.SetValue("id", 1); d2.SetValue("pages", 20); - Assert.True(d.Equals(d2)); + Assert.That(d.Equals(d2)); } [Test] @@ -74,7 +74,7 @@ public void NestedParse() d2.SetValue("id", 1); d2.SetValue("pages", 20); d2.SetValue("person", new { name = "Fred", age = 45 }); - Assert.True(d.Equals(d2)); + Assert.That(d.Equals(d2)); } [Test] @@ -112,8 +112,8 @@ public void ParseWithArray() d2.SetValue("id", 1); d2.SetValue("pages", 20); d2.SetValue("books", docs); - StringAssert.AreEqualIgnoringCase(d.ToString(), d2.ToString()); - StringAssert.AreEqualIgnoringCase(RemoveLineEndings(json), RemoveLineEndings(d2.ToString())); + Assert.That(d2.ToString(), Is.EqualTo(d.ToString()).IgnoreCase); + Assert.That(RemoveLineEndings(d2.ToString()), Is.EqualTo(RemoveLineEndings(json)).IgnoreCase); } [Test] @@ -123,7 +123,7 @@ public void ParseLongValues() DbDoc d2 = new DbDoc(); d2.SetValue("id", 1); d2.SetValue("pages", (long)int.MaxValue + 1); - Assert.True(d.Equals(d2)); + Assert.That(d.Equals(d2)); } [Test] @@ -133,7 +133,7 @@ public void ParseFloatValues() DbDoc d2 = new DbDoc(); d2.SetValue("id", 1); d2.SetValue("pi", 3.14159); - Assert.True(d.Equals(d2)); + Assert.That(d.Equals(d2)); } } } diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/DnsSrvTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/DnsSrvTests.cs index 301471910..ff82ee248 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/DnsSrvTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/DnsSrvTests.cs @@ -50,7 +50,7 @@ public void DnsSrvConnectionStringInvalidConfiguration(string connString, string { connString = connString.Replace("localhost", Host).Replace("33060", XPort); var exception = Assert.Throws(() => MySQLX.GetSession(connString)); - Assert.AreEqual(exceptionMessage, exception.Message); + Assert.That(exception.Message, Is.EqualTo(exceptionMessage)); } [TestCase("server=localhost;port=33060;dns-srv=false;uid=test;password=test;")] @@ -62,7 +62,7 @@ public void DnsSrvConnectionStringValidConfiguration(string connString) { connString = connString.Replace("localhost", Host).Replace("33060", XPort); using (var session = MySQLX.GetSession(connString)) - Assert.NotNull(session); + Assert.That(session, Is.Not.Null); } [Test] @@ -73,35 +73,35 @@ public void DnsSrvConnectionAnonymousTypeInvalidConfiguration() sb.Port = UInt32.Parse(XPort); sb.Server = Host; var exception = Assert.Throws(() => MySQLX.GetSession(sb.ConnectionString)); - Assert.AreEqual(MySql.Data.Resources.DnsSrvInvalidConnOptionPort, exception.Message); + Assert.That(exception.Message, Is.EqualTo(MySql.Data.Resources.DnsSrvInvalidConnOptionPort)); exception = Assert.Throws(() => MySQLX.GetClient(sb.ConnectionString, new { pooling = new { enabled = true } })); - Assert.AreEqual(MySql.Data.Resources.DnsSrvInvalidConnOptionPort, exception.Message); + Assert.That(exception.Message, Is.EqualTo(MySql.Data.Resources.DnsSrvInvalidConnOptionPort)); sb = new MySqlXConnectionStringBuilder(); sb.DnsSrv = true; sb.Server = $"{Host}, 10.10.10.10"; exception = Assert.Throws(() => MySQLX.GetSession(sb.ConnectionString)); - Assert.AreEqual(MySql.Data.Resources.DnsSrvInvalidConnOptionMultihost, exception.Message); + Assert.That(exception.Message, Is.EqualTo(MySql.Data.Resources.DnsSrvInvalidConnOptionMultihost)); exception = Assert.Throws(() => MySQLX.GetClient(sb.ConnectionString, new { pooling = new { enabled = true } })); - Assert.AreEqual(MySql.Data.Resources.DnsSrvInvalidConnOptionMultihost, exception.Message); + Assert.That(exception.Message, Is.EqualTo(MySql.Data.Resources.DnsSrvInvalidConnOptionMultihost)); sb = new MySqlXConnectionStringBuilder(); sb.DnsSrv = true; sb.Server = $"(address={Host},priority=100), (address=10.10.10.10,priority=90)"; exception = Assert.Throws(() => MySQLX.GetSession(sb.ConnectionString)); - Assert.AreEqual(MySql.Data.Resources.DnsSrvInvalidConnOptionMultihost, exception.Message); + Assert.That(exception.Message, Is.EqualTo(MySql.Data.Resources.DnsSrvInvalidConnOptionMultihost)); var connDataHost = new { server = $"(address={Host},priority=100), (address=10.10.10.10,priority=90)", dnssrv = true }; exception = Assert.Throws(() => MySQLX.GetClient(connDataHost, new { pooling = new { enabled = true } })); - Assert.AreEqual(MySql.Data.Resources.DnsSrvInvalidConnOptionMultihost, exception.Message); + Assert.That(exception.Message, Is.EqualTo(MySql.Data.Resources.DnsSrvInvalidConnOptionMultihost)); var connDataPort = new { server = Host, port = XPort, dnssrv = true }; exception = Assert.Throws(() => MySQLX.GetClient(connDataPort, new { pooling = new { enabled = true } })); - Assert.AreEqual(MySql.Data.Resources.DnsSrvInvalidConnOptionPort, exception.Message); + Assert.That(exception.Message, Is.EqualTo(MySql.Data.Resources.DnsSrvInvalidConnOptionPort)); var connDataUnix = new { server = Host, protocol = "unix", dnssrv = true }; exception = Assert.Throws(() => MySQLX.GetClient(connDataUnix, new { pooling = new { enabled = true } })); - Assert.AreEqual(MySql.Data.Resources.DnsSrvInvalidConnOptionUnixSocket, exception.Message); + Assert.That(exception.Message, Is.EqualTo(MySql.Data.Resources.DnsSrvInvalidConnOptionUnixSocket)); } [TestCase("mysqlx+srv://test:test@localhost:33060", "Specifying a port number with DNS SRV lookup is not permitted.")] @@ -114,10 +114,10 @@ public void DnsSrvConnectionStringUriInvalidConfiguration(string connStringUri, { connStringUri = connStringUri.Replace("localhost", Host).Replace("33060", XPort); var exception = Assert.Throws(() => MySQLX.GetSession(connStringUri)); - Assert.AreEqual(exceptionMessage, exception.Message); + Assert.That(exception.Message, Is.EqualTo(exceptionMessage)); exception = Assert.Throws(() => MySQLX.GetClient(connStringUri, new { pooling = new { enabled = true } })); - Assert.AreEqual(exceptionMessage, exception.Message); + Assert.That(exception.Message, Is.EqualTo(exceptionMessage)); } [TestCase("mysqlx+srv://test:test@localhost")] @@ -129,7 +129,7 @@ public void DnsResolverNoHosts(string connString) { connString = connString.Replace("localhost", Host); var ex = Assert.Throws(() => MySQLX.GetSession(connString)); - Assert.AreEqual(string.Format(MySql.Data.Resources.DnsSrvNoHostsAvailable, Host), ex.Message); + Assert.That(ex.Message, Is.EqualTo(string.Format(MySql.Data.Resources.DnsSrvNoHostsAvailable, Host))); } [Test] @@ -138,7 +138,7 @@ public void DnsResolverNoHostsPooling() using (var client = MySQLX.GetClient($"mysqlx+srv://test:test@{Host}?dns-srv=true;", new { pooling = new { enabled = true } })) { var ex = Assert.Throws(() => client.GetSession()); - Assert.AreEqual(string.Format(MySql.Data.Resources.DnsSrvNoHostsAvailable, Host), ex.Message); + Assert.That(ex.Message, Is.EqualTo(string.Format(MySql.Data.Resources.DnsSrvNoHostsAvailable, Host))); } } } diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/ExprParserTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/ExprParserTests.cs index 89426bba8..d31c6bfcc 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/ExprParserTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/ExprParserTests.cs @@ -98,12 +98,12 @@ private void CheckParseRoundTrip(string input, string expected) } Expr expr = new ExprParser(input).Parse(); string canonicalized = ExprUnparser.ExprToString(expr); - Assert.AreEqual(expected, canonicalized); + Assert.That(canonicalized, Is.EqualTo(expected)); // System.err.println("Canonicalized: " + canonicalized); Expr expr2 = new ExprParser(canonicalized).Parse(); string recanonicalized = ExprUnparser.ExprToString(expr2); - Assert.AreEqual(expected, recanonicalized); + Assert.That(recanonicalized, Is.EqualTo(expected)); } /** @@ -210,104 +210,104 @@ public void TestRoundTrips() public void TestExprTree() { Expr expr = new ExprParser("a like 'xyz' and $.count > 10 + 1").Parse(); - Assert.AreEqual(Expr.Types.Type.Operator, expr.Type); - Assert.AreEqual("&&", expr.Operator.Name); - Assert.AreEqual(2, expr.Operator.Param.Count); + Assert.That(expr.Type, Is.EqualTo(Expr.Types.Type.Operator)); + Assert.That(expr.Operator.Name, Is.EqualTo("&&")); + Assert.That(expr.Operator.Param.Count, Is.EqualTo(2)); // check left side of AND: (a like 'xyz') Expr andLeft = expr.Operator.Param[0]; - Assert.AreEqual(Expr.Types.Type.Operator, andLeft.Type); - Assert.AreEqual("like", andLeft.Operator.Name); - Assert.AreEqual(2, andLeft.Operator.Param.Count); + Assert.That(andLeft.Type, Is.EqualTo(Expr.Types.Type.Operator)); + Assert.That(andLeft.Operator.Name, Is.EqualTo("like")); + Assert.That(andLeft.Operator.Param.Count, Is.EqualTo(2)); Expr identA = andLeft.Operator.Param[0]; - Assert.AreEqual(Expr.Types.Type.Ident, identA.Type); - Assert.AreEqual("a", identA.Identifier.Name); + Assert.That(identA.Type, Is.EqualTo(Expr.Types.Type.Ident)); + Assert.That(identA.Identifier.Name, Is.EqualTo("a")); Expr literalXyz = andLeft.Operator.Param[1]; - Assert.AreEqual(Expr.Types.Type.Literal, literalXyz.Type); + Assert.That(literalXyz.Type, Is.EqualTo(Expr.Types.Type.Literal)); Scalar scalarXyz = literalXyz.Literal; - Assert.AreEqual(Scalar.Types.Type.VString, scalarXyz.Type); - Assert.AreEqual("xyz", scalarXyz.VString.Value.ToStringUtf8()); + Assert.That(scalarXyz.Type, Is.EqualTo(Scalar.Types.Type.VString)); + Assert.That(scalarXyz.VString.Value.ToStringUtf8(), Is.EqualTo("xyz")); // check right side of AND: ($.count > 10 + 1) Expr andRight = expr.Operator.Param[1]; - Assert.AreEqual(Expr.Types.Type.Operator, andRight.Type); - Assert.AreEqual(">", andRight.Operator.Name); - Assert.AreEqual(2, andRight.Operator.Param.Count); + Assert.That(andRight.Type, Is.EqualTo(Expr.Types.Type.Operator)); + Assert.That(andRight.Operator.Name, Is.EqualTo(">")); + Assert.That(andRight.Operator.Param.Count, Is.EqualTo(2)); Expr countDocPath = andRight.Operator.Param[0]; - Assert.AreEqual(Expr.Types.Type.Ident, countDocPath.Type); + Assert.That(countDocPath.Type, Is.EqualTo(Expr.Types.Type.Ident)); ColumnIdentifier countId = countDocPath.Identifier; - Assert.AreEqual(string.Empty, countId.Name); - Assert.AreEqual(string.Empty, countId.TableName); - Assert.AreEqual(string.Empty, countId.SchemaName); + Assert.That(countId.Name, Is.EqualTo(string.Empty)); + Assert.That(countId.TableName, Is.EqualTo(string.Empty)); + Assert.That(countId.SchemaName, Is.EqualTo(string.Empty)); Assert.That(countId.DocumentPath.Count==1); - Assert.AreEqual(DocumentPathItem.Types.Type.Member, countId.DocumentPath[0].Type); - Assert.AreEqual("count", countId.DocumentPath[0].Value); + Assert.That(countId.DocumentPath[0].Type, Is.EqualTo(DocumentPathItem.Types.Type.Member)); + Assert.That(countId.DocumentPath[0].Value, Is.EqualTo("count")); Expr addition = andRight.Operator.Param[1]; Scalar addLeftScalar = addition.Operator.Param[0].Literal; Scalar addRightScalar = addition.Operator.Param[1].Literal; - Assert.AreEqual(Expr.Types.Type.Operator, addition.Type); - Assert.AreEqual("+", addition.Operator.Name); - Assert.AreEqual(2, addition.Operator.Param.Count); - Assert.AreEqual(Expr.Types.Type.Literal, addition.Operator.Param[0].Type); - Assert.AreEqual(Expr.Types.Type.Literal, addition.Operator.Param[1].Type); - Assert.AreEqual(Scalar.Types.Type.VSint, addLeftScalar.Type); - Assert.AreEqual(Scalar.Types.Type.VSint, addRightScalar.Type); - Assert.AreEqual(10, addLeftScalar.VSignedInt); - Assert.AreEqual(1, addRightScalar.VSignedInt); + Assert.That(addition.Type, Is.EqualTo(Expr.Types.Type.Operator)); + Assert.That(addition.Operator.Name, Is.EqualTo("+")); + Assert.That(addition.Operator.Param.Count, Is.EqualTo(2)); + Assert.That(addition.Operator.Param[0].Type, Is.EqualTo(Expr.Types.Type.Literal)); + Assert.That(addition.Operator.Param[1].Type, Is.EqualTo(Expr.Types.Type.Literal)); + Assert.That(addLeftScalar.Type, Is.EqualTo(Scalar.Types.Type.VSint)); + Assert.That(addRightScalar.Type, Is.EqualTo(Scalar.Types.Type.VSint)); + Assert.That(addLeftScalar.VSignedInt, Is.EqualTo(10)); + Assert.That(addRightScalar.VSignedInt, Is.EqualTo(1)); } [Test] public void TestOrderByParserBasic() { List orderSpec = new ExprParser("a, b desc").ParseOrderSpec(); - Assert.AreEqual(2, orderSpec.Count); + Assert.That(orderSpec.Count, Is.EqualTo(2)); Order o1 = orderSpec[0]; - Assert.False(o1.HasDirection); - Assert.AreEqual("a", ExprUnparser.ExprToString(o1.Expr)); + Assert.That(o1.HasDirection, Is.False); + Assert.That(ExprUnparser.ExprToString(o1.Expr), Is.EqualTo("a")); Order o2 = orderSpec[1]; - Assert.True(o2.HasDirection); - Assert.AreEqual(Order.Types.Direction.Desc, o2.Direction); - Assert.AreEqual("b", ExprUnparser.ExprToString(o2.Expr)); + Assert.That(o2.HasDirection); + Assert.That(o2.Direction, Is.EqualTo(Order.Types.Direction.Desc)); + Assert.That(ExprUnparser.ExprToString(o2.Expr), Is.EqualTo("b")); } [Test] public void TestOrderByParserComplexExpressions() { List orderSpec = new ExprParser("field not in ('a',func('b', 2.0),'c') desc, 1-a$**[0].*, now () + $.b + c > 2 asc").ParseOrderSpec(); - Assert.AreEqual(3, orderSpec.Count); + Assert.That(orderSpec.Count, Is.EqualTo(3)); Order o1 = orderSpec[0]; - Assert.True(o1.HasDirection); - Assert.AreEqual(Order.Types.Direction.Desc, o1.Direction); - Assert.AreEqual("field not in(\"a\", func(\"b\", 2), \"c\")", ExprUnparser.ExprToString(o1.Expr)); + Assert.That(o1.HasDirection); + Assert.That(o1.Direction, Is.EqualTo(Order.Types.Direction.Desc)); + Assert.That(ExprUnparser.ExprToString(o1.Expr), Is.EqualTo("field not in(\"a\", func(\"b\", 2), \"c\")")); Order o2 = orderSpec[1]; - Assert.False(o2.HasDirection); - Assert.AreEqual("(1 - a$**[0].*)", ExprUnparser.ExprToString(o2.Expr)); + Assert.That(o2.HasDirection, Is.False); + Assert.That(ExprUnparser.ExprToString(o2.Expr), Is.EqualTo("(1 - a$**[0].*)")); Order o3 = orderSpec[2]; - Assert.True(o3.HasDirection); - Assert.AreEqual(Order.Types.Direction.Asc, o3.Direction); - Assert.AreEqual("(((now() + $.b) + c) > 2)", ExprUnparser.ExprToString(o3.Expr)); + Assert.That(o3.HasDirection); + Assert.That(o3.Direction, Is.EqualTo(Order.Types.Direction.Asc)); + Assert.That(ExprUnparser.ExprToString(o3.Expr), Is.EqualTo("(((now() + $.b) + c) > 2)")); } [Test] public void TestNamedPlaceholders() { ExprParser parser = new ExprParser("a = :a and b = :b and (c = 'x' or d = :b)"); - Assert.AreEqual("IDENT(a)", parser.tokens[0].ToString()); - Assert.AreEqual("EQ", parser.tokens[1].ToString()); + Assert.That(parser.tokens[0].ToString(), Is.EqualTo("IDENT(a)")); + Assert.That(parser.tokens[1].ToString(), Is.EqualTo("EQ")); Expr e = parser.Parse(); - Assert.AreEqual(0, parser.placeholderNameToPosition["a"]); - Assert.AreEqual(1, parser.placeholderNameToPosition["b"]); - Assert.AreEqual(2, parser.positionalPlaceholderCount); + Assert.That(parser.placeholderNameToPosition["a"], Is.EqualTo(0)); + Assert.That(parser.placeholderNameToPosition["b"], Is.EqualTo(1)); + Assert.That(parser.positionalPlaceholderCount, Is.EqualTo(2)); Expr aEqualsPlaceholder = e.Operator.Param[0].Operator.Param[0].Operator.Param[1]; - Assert.AreEqual(Expr.Types.Type.Placeholder, aEqualsPlaceholder.Type); - Assert.AreEqual((uint)0, aEqualsPlaceholder.Position); + Assert.That(aEqualsPlaceholder.Type, Is.EqualTo(Expr.Types.Type.Placeholder)); + Assert.That(aEqualsPlaceholder.Position, Is.EqualTo((uint)0)); Expr bEqualsPlaceholder = e.Operator.Param[0].Operator.Param[1].Operator.Param[1]; - Assert.AreEqual(Expr.Types.Type.Placeholder, bEqualsPlaceholder.Type); - Assert.AreEqual((uint)1, bEqualsPlaceholder.Position); + Assert.That(bEqualsPlaceholder.Type, Is.EqualTo(Expr.Types.Type.Placeholder)); + Assert.That(bEqualsPlaceholder.Position, Is.EqualTo((uint)1)); Expr dEqualsPlaceholder = e.Operator.Param[1].Operator.Param[1].Operator.Param[1]; - Assert.AreEqual(Expr.Types.Type.Placeholder, dEqualsPlaceholder.Type); - Assert.AreEqual((uint)1, dEqualsPlaceholder.Position); + Assert.That(dEqualsPlaceholder.Type, Is.EqualTo(Expr.Types.Type.Placeholder)); + Assert.That(dEqualsPlaceholder.Position, Is.EqualTo((uint)1)); } [Test] @@ -315,23 +315,23 @@ public void TestNumberedPlaceholders() { ExprParser parser = new ExprParser("a == :1 and b == :3 and (c == :2 or d == :2)"); Expr e = parser.Parse(); - Assert.AreEqual(0, parser.placeholderNameToPosition["1"]); - Assert.AreEqual(1, parser.placeholderNameToPosition["3"]); - Assert.AreEqual(2, parser.placeholderNameToPosition["2"]); - Assert.AreEqual(3, parser.positionalPlaceholderCount); + Assert.That(parser.placeholderNameToPosition["1"], Is.EqualTo(0)); + Assert.That(parser.placeholderNameToPosition["3"], Is.EqualTo(1)); + Assert.That(parser.placeholderNameToPosition["2"], Is.EqualTo(2)); + Assert.That(parser.positionalPlaceholderCount, Is.EqualTo(3)); Expr aEqualsPlaceholder = e.Operator.Param[0].Operator.Param[0].Operator.Param[1]; - Assert.AreEqual(Expr.Types.Type.Placeholder, aEqualsPlaceholder.Type); - Assert.AreEqual((uint)0, aEqualsPlaceholder.Position); + Assert.That(aEqualsPlaceholder.Type, Is.EqualTo(Expr.Types.Type.Placeholder)); + Assert.That(aEqualsPlaceholder.Position, Is.EqualTo((uint)0)); Expr bEqualsPlaceholder = e.Operator.Param[0].Operator.Param[1].Operator.Param[1]; - Assert.AreEqual(Expr.Types.Type.Placeholder, bEqualsPlaceholder.Type); - Assert.AreEqual((uint)1, bEqualsPlaceholder.Position); + Assert.That(bEqualsPlaceholder.Type, Is.EqualTo(Expr.Types.Type.Placeholder)); + Assert.That(bEqualsPlaceholder.Position, Is.EqualTo((uint)1)); Expr cEqualsPlaceholder = e.Operator.Param[1].Operator.Param[0].Operator.Param[1]; - Assert.AreEqual(Expr.Types.Type.Placeholder, cEqualsPlaceholder.Type); - Assert.AreEqual((uint)2, cEqualsPlaceholder.Position); + Assert.That(cEqualsPlaceholder.Type, Is.EqualTo(Expr.Types.Type.Placeholder)); + Assert.That(cEqualsPlaceholder.Position, Is.EqualTo((uint)2)); Expr dEqualsPlaceholder = e.Operator.Param[1].Operator.Param[1].Operator.Param[1]; - Assert.AreEqual(Expr.Types.Type.Placeholder, dEqualsPlaceholder.Type); - Assert.AreEqual((uint)2, dEqualsPlaceholder.Position); + Assert.That(dEqualsPlaceholder.Type, Is.EqualTo(Expr.Types.Type.Placeholder)); + Assert.That(dEqualsPlaceholder.Position, Is.EqualTo((uint)2)); } [Test] @@ -339,20 +339,20 @@ public void TestUnnumberedPlaceholders() { ExprParser parser = new ExprParser("a = ? and b = ? and (c = 'x' or d = ?)"); Expr e = parser.Parse(); - Assert.AreEqual(0, parser.placeholderNameToPosition["0"]); - Assert.AreEqual(1, parser.placeholderNameToPosition["1"]); - Assert.AreEqual(2, parser.placeholderNameToPosition["2"]); - Assert.AreEqual(3, parser.positionalPlaceholderCount); + Assert.That(parser.placeholderNameToPosition["0"], Is.EqualTo(0)); + Assert.That(parser.placeholderNameToPosition["1"], Is.EqualTo(1)); + Assert.That(parser.placeholderNameToPosition["2"], Is.EqualTo(2)); + Assert.That(parser.positionalPlaceholderCount, Is.EqualTo(3)); Expr aEqualsPlaceholder = e.Operator.Param[0].Operator.Param[0].Operator.Param[1]; - Assert.AreEqual(Expr.Types.Type.Placeholder, aEqualsPlaceholder.Type); - Assert.AreEqual((uint)0, aEqualsPlaceholder.Position); + Assert.That(aEqualsPlaceholder.Type, Is.EqualTo(Expr.Types.Type.Placeholder)); + Assert.That(aEqualsPlaceholder.Position, Is.EqualTo((uint)0)); Expr bEqualsPlaceholder = e.Operator.Param[0].Operator.Param[1].Operator.Param[1]; - Assert.AreEqual(Expr.Types.Type.Placeholder, bEqualsPlaceholder.Type); - Assert.AreEqual((uint)1, bEqualsPlaceholder.Position); + Assert.That(bEqualsPlaceholder.Type, Is.EqualTo(Expr.Types.Type.Placeholder)); + Assert.That(bEqualsPlaceholder.Position, Is.EqualTo((uint)1)); Expr dEqualsPlaceholder = e.Operator.Param[1].Operator.Param[1].Operator.Param[1]; - Assert.AreEqual(Expr.Types.Type.Placeholder, dEqualsPlaceholder.Type); - Assert.AreEqual((uint)2, dEqualsPlaceholder.Position); + Assert.That(dEqualsPlaceholder.Type, Is.EqualTo(Expr.Types.Type.Placeholder)); + Assert.That(dEqualsPlaceholder.Position, Is.EqualTo((uint)2)); } [Test] @@ -360,24 +360,24 @@ public void TestJsonLiteral() { Expr e = new ExprParser("{'a':1, 'b':\"a string\"}").Parse(); - Assert.AreEqual("{'a':1, 'b':\"a string\"}", ExprUnparser.ExprToString(e)); + Assert.That(ExprUnparser.ExprToString(e), Is.EqualTo("{'a':1, 'b':\"a string\"}")); - Assert.AreEqual(Expr.Types.Type.Object, e.Type); + Assert.That(e.Type, Is.EqualTo(Expr.Types.Type.Object)); Mysqlx.Expr.Object o = e.Object; - Assert.AreEqual(2, o.Fld.Count); + Assert.That(o.Fld.Count, Is.EqualTo(2)); Mysqlx.Expr.Object.Types.ObjectField of; of = o.Fld[0]; - Assert.AreEqual("a", of.Key); + Assert.That(of.Key, Is.EqualTo("a")); e = of.Value; - Assert.AreEqual(Expr.Types.Type.Literal, e.Type); - Assert.AreEqual(1, e.Literal.VSignedInt); + Assert.That(e.Type, Is.EqualTo(Expr.Types.Type.Literal)); + Assert.That(e.Literal.VSignedInt, Is.EqualTo(1)); of = o.Fld[1]; - Assert.AreEqual("b", of.Key); + Assert.That(of.Key, Is.EqualTo("b")); e = of.Value; - Assert.AreEqual(Expr.Types.Type.Literal, e.Type); - Assert.AreEqual("a string", e.Literal.VString.Value.ToStringUtf8()); + Assert.That(e.Type, Is.EqualTo(Expr.Types.Type.Literal)); + Assert.That(e.Literal.VString.Value.ToStringUtf8(), Is.EqualTo("a string")); } [Test] @@ -387,8 +387,8 @@ public void TestTrivialDocumentProjection() proj = new ExprParser("$.a as a").ParseDocumentProjection(); Assert.That(proj, Has.One.Items); - Assert.AreNotEqual(string.Empty, proj[0].Alias); - Assert.AreEqual("a", proj[0].Alias); + Assert.That(proj[0].Alias, Is.Not.EqualTo(string.Empty)); + Assert.That(proj[0].Alias, Is.EqualTo("a")); proj = new ExprParser("$.a as a, $.b as b, $.c as c").ParseDocumentProjection(); } @@ -398,26 +398,26 @@ public void TestExprAsPathDocumentProjection() { List projList = new ExprParser("$.a as b, (1 + 1) * 100 as x, 2 as j42").ParseDocumentProjection(); - Assert.AreEqual(3, projList.Count); + Assert.That(projList.Count, Is.EqualTo(3)); // check $.a as b Projection proj = projList[0]; IList paths = proj.Source.Identifier.DocumentPath; - Assert.AreEqual(1, paths.Count); - Assert.AreEqual(DocumentPathItem.Types.Type.Member, paths[0].Type); - Assert.AreEqual("a", paths[0].Value); + Assert.That(paths.Count, Is.EqualTo(1)); + Assert.That(paths[0].Type, Is.EqualTo(DocumentPathItem.Types.Type.Member)); + Assert.That(paths[0].Value, Is.EqualTo("a")); - Assert.AreEqual("b", proj.Alias); + Assert.That(proj.Alias, Is.EqualTo("b")); // check (1 + 1) * 100 as x proj = projList[1]; - Assert.AreEqual("((1 + 1) * 100)", ExprUnparser.ExprToString(proj.Source)); - Assert.AreEqual("x", proj.Alias); + Assert.That(ExprUnparser.ExprToString(proj.Source), Is.EqualTo("((1 + 1) * 100)")); + Assert.That(proj.Alias, Is.EqualTo("x")); // check 2 as j42 proj = projList[2]; - Assert.AreEqual("2", ExprUnparser.ExprToString(proj.Source)); - Assert.AreEqual("j42", proj.Alias); + Assert.That(ExprUnparser.ExprToString(proj.Source), Is.EqualTo("2")); + Assert.That(proj.Alias, Is.EqualTo("j42")); } [Test] @@ -427,7 +427,7 @@ public void TestJsonConstructorAsDocumentProjection() string projString = "{'a':'value for a', 'b':1+1, 'c'::bindvar, 'd':$.member[22], 'e':{'nested':'doc'}}"; Projection proj = new Projection(); proj.Source = new ExprParser(projString, false).Parse(); - Assert.AreEqual(Expr.Types.Type.Object, proj.Source.Type); + Assert.That(proj.Source.Type, Is.EqualTo(Expr.Types.Type.Object)); IEnumerator fields = proj.Source.Object.Fld.GetEnumerator(); string[][] array = new string[][] { @@ -440,10 +440,10 @@ public void TestJsonConstructorAsDocumentProjection() { fields.MoveNext(); Mysqlx.Expr.Object.Types.ObjectField f = fields.Current; - Assert.AreEqual(pair[0], f.Key); - Assert.AreEqual(pair[1], ExprUnparser.ExprToString(f.Value)); + Assert.That(f.Key, Is.EqualTo(pair[0])); + Assert.That(ExprUnparser.ExprToString(f.Value), Is.EqualTo(pair[1])); }); - Assert.False(fields.MoveNext()); + Assert.That(fields.MoveNext(), Is.False); } [Test] @@ -452,7 +452,7 @@ public void TestJsonExprsInDocumentProjection() // this is not a single doc as the project but multiple docs as embedded fields string projString = "{'a':1} as a, {'b':2} as b"; List projList = new ExprParser(projString).ParseDocumentProjection(); - Assert.AreEqual(2, projList.Count); + Assert.That(projList.Count, Is.EqualTo(2)); // TODO: verification of remaining elements } @@ -460,10 +460,10 @@ public void TestJsonExprsInDocumentProjection() public void TestTableInsertProjection() { Column col = new ExprParser("a").ParseTableInsertField(); - Assert.AreEqual("a", col.Name); + Assert.That(col.Name, Is.EqualTo("a")); col = new ExprParser("`double weird `` string`").ParseTableInsertField(); - Assert.AreEqual("double weird ` string", col.Name); + Assert.That(col.Name, Is.EqualTo("double weird ` string")); } [Test] @@ -471,45 +471,45 @@ public void TestTableUpdateField() { ColumnIdentifier col; col = new ExprParser("a").ParseTableUpdateField(); - Assert.AreEqual("a", col.Name); + Assert.That(col.Name, Is.EqualTo("a")); col = new ExprParser("b.c").ParseTableUpdateField(); - Assert.AreEqual("b", col.TableName); - Assert.AreEqual("c", col.Name); + Assert.That(col.TableName, Is.EqualTo("b")); + Assert.That(col.Name, Is.EqualTo("c")); col = new ExprParser("d.e$.the_path[2]").ParseTableUpdateField(); - Assert.AreEqual("d", col.TableName); - Assert.AreEqual("e", col.Name); - Assert.AreEqual(2, col.DocumentPath.Count); - Assert.AreEqual("the_path", col.DocumentPath[0].Value); - Assert.AreEqual((uint)2, col.DocumentPath[1].Index); + Assert.That(col.TableName, Is.EqualTo("d")); + Assert.That(col.Name, Is.EqualTo("e")); + Assert.That(col.DocumentPath.Count, Is.EqualTo(2)); + Assert.That(col.DocumentPath[0].Value, Is.EqualTo("the_path")); + Assert.That(col.DocumentPath[1].Index, Is.EqualTo((uint)2)); col = new ExprParser("`zzz\\``").ParseTableUpdateField(); - Assert.AreEqual("zzz`", col.Name); + Assert.That(col.Name, Is.EqualTo("zzz`")); } [Test] public void TestTrivialTableSelectProjection() { List proj = new ExprParser("a, b as c").ParseTableSelectProjection(); - Assert.AreEqual(2, proj.Count); - Assert.AreEqual("a", ExprUnparser.ExprToString(proj[0].Source)); - Assert.AreEqual(string.Empty, proj[0].Alias); - Assert.AreEqual("b", ExprUnparser.ExprToString(proj[1].Source)); - Assert.AreNotEqual(string.Empty, proj[1].Alias); - Assert.AreEqual("c", proj[1].Alias); + Assert.That(proj.Count, Is.EqualTo(2)); + Assert.That(ExprUnparser.ExprToString(proj[0].Source), Is.EqualTo("a")); + Assert.That(proj[0].Alias, Is.EqualTo(string.Empty)); + Assert.That(ExprUnparser.ExprToString(proj[1].Source), Is.EqualTo("b")); + Assert.That(proj[1].Alias, Is.Not.EqualTo(string.Empty)); + Assert.That(proj[1].Alias, Is.EqualTo("c")); } [Test] public void TestStarTableSelectProjection() { List proj = new ExprParser("*, b as c").ParseTableSelectProjection(); - Assert.AreEqual(2, proj.Count); - Assert.AreEqual("*", ExprUnparser.ExprToString(proj[0].Source)); - Assert.AreEqual(string.Empty, proj[0].Alias); - Assert.AreEqual("b", ExprUnparser.ExprToString(proj[1].Source)); - Assert.AreNotEqual(string.Empty, proj[1].Alias); - Assert.AreEqual("c", proj[1].Alias); + Assert.That(proj.Count, Is.EqualTo(2)); + Assert.That(ExprUnparser.ExprToString(proj[0].Source), Is.EqualTo("*")); + Assert.That(proj[0].Alias, Is.EqualTo(string.Empty)); + Assert.That(ExprUnparser.ExprToString(proj[1].Source), Is.EqualTo("b")); + Assert.That(proj[1].Alias, Is.Not.EqualTo(string.Empty)); + Assert.That(proj[1].Alias, Is.EqualTo("c")); } [Test] @@ -517,13 +517,13 @@ public void TestComplexTableSelectProjection() { string projectionString = "(1 + 1) * 100 as `one-o-two`, 'a is \\'a\\'' as `what is 'a'`"; List proj = new ExprParser(projectionString).ParseTableSelectProjection(); - Assert.AreEqual(2, proj.Count); + Assert.That(proj.Count, Is.EqualTo(2)); - Assert.AreEqual("((1 + 1) * 100)", ExprUnparser.ExprToString(proj[0].Source)); - Assert.AreEqual("one-o-two", proj[0].Alias); + Assert.That(ExprUnparser.ExprToString(proj[0].Source), Is.EqualTo("((1 + 1) * 100)")); + Assert.That(proj[0].Alias, Is.EqualTo("one-o-two")); - Assert.AreEqual("a is 'a'", proj[1].Source.Literal.VString.Value.ToStringUtf8()); - Assert.AreEqual("what is 'a'", proj[1].Alias); + Assert.That(proj[1].Source.Literal.VString.Value.ToStringUtf8(), Is.EqualTo("a is 'a'")); + Assert.That(proj[1].Alias, Is.EqualTo("what is 'a'")); } [Test] @@ -540,13 +540,13 @@ public void TestRandom() public void UnqualifiedDocPaths() { Expr expr = new ExprParser("1 + b[0]", false).Parse(); - Assert.AreEqual("(1 + $.b[0])", ExprUnparser.ExprToString(expr)); + Assert.That(ExprUnparser.ExprToString(expr), Is.EqualTo("(1 + $.b[0])")); expr = new ExprParser("a.*", false).Parse(); - Assert.AreEqual("$.a.*", ExprUnparser.ExprToString(expr)); + Assert.That(ExprUnparser.ExprToString(expr), Is.EqualTo("$.a.*")); expr = new ExprParser("bL . vT .*", false).Parse(); - Assert.AreEqual("$.bL.vT.*", ExprUnparser.ExprToString(expr)); + Assert.That(ExprUnparser.ExprToString(expr), Is.EqualTo("$.bL.vT.*")); expr = new ExprParser("dd ** .X", false).Parse(); - Assert.AreEqual("$.dd**.X", ExprUnparser.ExprToString(expr)); + Assert.That(ExprUnparser.ExprToString(expr), Is.EqualTo("$.dd**.X")); } [TestCase("info$.additionalinfo.hobbies", "info$.additionalinfo.hobbies", true)] @@ -560,13 +560,12 @@ public void JsonColumnPath(string exprString, string unparserString, bool isRela { if(unparserString == null) { - Assert.AreEqual($"Unable to parse query '{exprString}'", - Assert.Throws(() => new ExprParser(exprString, isRelational).Parse()).Message); + Assert.That(Assert.Throws(() => new ExprParser(exprString, isRelational).Parse()).Message, Is.EqualTo($"Unable to parse query '{exprString}'")); } else { Expr expr = new ExprParser(exprString, isRelational).Parse(); - Assert.AreEqual(unparserString, ExprUnparser.ExprToString(expr)); + Assert.That(ExprUnparser.ExprToString(expr), Is.EqualTo(unparserString)); } } } diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/GlobalUsings.cs b/MySQL.Data/tests/MySqlX.Data.Tests/GlobalUsings.cs deleted file mode 100644 index 575c7cfd0..000000000 --- a/MySQL.Data/tests/MySqlX.Data.Tests/GlobalUsings.cs +++ /dev/null @@ -1,5 +0,0 @@ -global using Assert = NUnit.Framework.Legacy.ClassicAssert; -global using CollectionAssert = NUnit.Framework.Legacy.CollectionAssert; -global using StringAssert = NUnit.Framework.Legacy.StringAssert; -global using DirectoryAssert = NUnit.Framework.Legacy.DirectoryAssert; -global using FileAssert = NUnit.Framework.Legacy.FileAssert; diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/JsonParserTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/JsonParserTests.cs index e12dee9f7..07fb51ff3 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/JsonParserTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/JsonParserTests.cs @@ -44,21 +44,21 @@ public void ParseBooleanValue() DbDoc document = new DbDoc(@"{ ""_id"": 1, ""isDocument"": true }"); Result result = ExecuteAddStatement(collection.Add(document)); - Assert.AreEqual(1, result.AffectedItemsCount); + Assert.That(result.AffectedItemsCount, Is.EqualTo(1)); document = collection.GetOne(1); - Assert.True(document.values.ContainsKey("isDocument")); - Assert.True((bool) document.values["isDocument"]); + Assert.That(document.values.ContainsKey("isDocument")); + Assert.That((bool) document.values["isDocument"]); document = new DbDoc(new { _id=2, isDocument=false }); result = ExecuteAddStatement(collection.Add(document)); - Assert.AreEqual(1, result.AffectedItemsCount); + Assert.That(result.AffectedItemsCount, Is.EqualTo(1)); document = collection.GetOne(2); - Assert.True(document.values.ContainsKey("isDocument")); - Assert.False((bool) document.values["isDocument"]); + Assert.That(document.values.ContainsKey("isDocument")); + Assert.That((bool) document.values["isDocument"], Is.False); - Assert.True(ExecuteFindStatement(collection.Find("isDocument = false")).FetchAll().Count > 0); + Assert.That(ExecuteFindStatement(collection.Find("isDocument = false")).FetchAll().Count > 0); } [Test] @@ -68,11 +68,11 @@ public void ParseNullValue() DbDoc document = new DbDoc(@"{ ""isDocument"": null }"); Result result = ExecuteAddStatement(collection.Add(document)); - Assert.AreEqual(1, result.AffectedItemsCount); + Assert.That(result.AffectedItemsCount, Is.EqualTo(1)); document = ExecuteFindStatement(collection.Find()).FetchOne(); - Assert.True(document.values.ContainsKey("isDocument")); - Assert.Null(document.values["isDocument"]); + Assert.That(document.values.ContainsKey("isDocument")); + Assert.That(document.values["isDocument"], Is.Null); } [Test] @@ -82,11 +82,11 @@ public void ParseNumberArray() DbDoc document = new DbDoc(@"{ ""id"": 1, ""list"": [1,2,3] }"); Result result = ExecuteAddStatement(collection.Add(document)); - Assert.AreEqual(1, result.AffectedItemsCount); + Assert.That(result.AffectedItemsCount, Is.EqualTo(1)); document = ExecuteFindStatement(collection.Find()).FetchOne(); - Assert.True(document.values.ContainsKey("list")); - Assert.AreEqual(new object[] { 1, 2, 3 }, document.values["list"]); + Assert.That(document.values.ContainsKey("list")); + Assert.That(document.values["list"], Is.EqualTo(new object[] { 1, 2, 3 })); } [Test] @@ -97,11 +97,11 @@ public void ParsObjectArray() DbDoc document = new DbDoc(@"{ ""id"": 1, ""list"": [1,""a""] }"); //DbDoc document = new DbDoc(@"{ ""id"": 1, ""list"": [1,""a"",true,null] }"); Result result = ExecuteAddStatement(collection.Add(document)); - Assert.AreEqual(1, result.AffectedItemsCount); + Assert.That(result.AffectedItemsCount, Is.EqualTo(1)); document = ExecuteFindStatement(collection.Find()).FetchOne(); - Assert.True(document.values.ContainsKey("list")); - Assert.AreEqual(new object[] { 1, "a" }, document.values["list"]); + Assert.That(document.values.ContainsKey("list")); + Assert.That(document.values["list"], Is.EqualTo(new object[] { 1, "a" })); //Assert.AreEqual(new object[] { 1, "a", true, null }, document.values["list"]); } @@ -112,13 +112,13 @@ public void ParseGroupsEmbededInArrays() //DbDoc document = new DbDoc(@"{ ""id"": 1, ""list"": [1,""a"",true,null] }"); Collection collection = CreateCollection("test"); Result result = ExecuteAddStatement(collection.Add(document)); - Assert.AreEqual(1, result.AffectedItemsCount); + Assert.That(result.AffectedItemsCount, Is.EqualTo(1)); document = ExecuteFindStatement(collection.Find()).FetchOne(); - Assert.True(document.values.ContainsKey("list")); + Assert.That(document.values.ContainsKey("list")); var dictionary = new Dictionary(); dictionary.Add("b",1); - Assert.AreEqual(new object[] { 1, "a", dictionary }, document.values["list"]); + Assert.That(document.values["list"], Is.EqualTo(new object[] { 1, "a", dictionary })); //Assert.AreEqual(new object[] { 1, "a", true, null, dictionary }, document.values["list"]); } @@ -140,19 +140,19 @@ public void ParseWithEscapedQuotes() var document = collection.GetOne("123"); var innerEmail = ((document["email"] as object[])[1]) as Dictionary; - Assert.AreEqual("[\\\"ALICE@ORA.COM\\\"]", innerEmail["email"]); + Assert.That(innerEmail["email"], Is.EqualTo("[\\\"ALICE@ORA.COM\\\"]")); innerEmail = ((document["email"] as object[])[2]) as Dictionary; - Assert.AreEqual("ALICE@ORA.COM", innerEmail["email"]); + Assert.That(innerEmail["email"], Is.EqualTo("ALICE@ORA.COM")); ExecuteAddStatement(collection.Add("{ \"_id\": \"124\", \"email\": \"\\\"\" }")); document = collection.GetOne("124"); - Assert.AreEqual("\\\"", document["email"]); + Assert.That(document["email"], Is.EqualTo("\\\"")); var ex = Assert.Throws(() => ExecuteAddStatement(collection.Add("{ \"_id\": \"124\", \"email\": \"\"\" }"))); - Assert.AreEqual("The value provided is not a valid JSON document. Expected token ','", ex.Message); + Assert.That(ex.Message, Is.EqualTo("The value provided is not a valid JSON document. Expected token ','")); ex = Assert.Throws(() => ExecuteAddStatement(collection.Add("{ \"_id\": \"124\", \"email\": \"\\\" }"))); - Assert.AreEqual("The value provided is not a valid JSON document. Failed to find ending '\"' while reading stream.", ex.Message); + Assert.That(ex.Message, Is.EqualTo("The value provided is not a valid JSON document. Failed to find ending '\"' while reading stream.")); } } } diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/MergePatch.cs b/MySQL.Data/tests/MySqlX.Data.Tests/MergePatch.cs index c0097e85b..be931efa9 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/MergePatch.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/MergePatch.cs @@ -138,21 +138,21 @@ public void SimplePatch() Collection collection = CreateCollection("test"); Result r = ExecuteAddStatement(collection.Add("{ \"_id\": \"123\", \"email\": \"alice@ora.com\", \"startDate\": \"4/1/2017\" }")); - Assert.AreEqual(1, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(1)); r = ExecuteAddStatement(collection.Add("{ \"_id\": \"124\", \"email\": \"jose@ora.com\", \"startDate\": \"4/1/2017\" }")); - Assert.AreEqual(1, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(1)); ExecuteModifyStatement(collection.Modify("email = \"alice@ora.com\"").Patch("{ \"_id\": \"123\", \"email\":\"bob@ora.com\", \"startDate\":null }")); DbDoc document = collection.GetOne("123"); - Assert.AreEqual("123", document.Id); - Assert.AreEqual("bob@ora.com", document.values["email"]); - Assert.True(!document.values.ContainsKey("startDate")); + Assert.That(document.Id, Is.EqualTo("123")); + Assert.That(document.values["email"], Is.EqualTo("bob@ora.com")); + Assert.That(!document.values.ContainsKey("startDate")); document = collection.GetOne("124"); - Assert.AreEqual("124", document.Id); - Assert.AreEqual("jose@ora.com", document.values["email"]); - Assert.True(document.values.ContainsKey("startDate")); + Assert.That(document.Id, Is.EqualTo("124")); + Assert.That(document.values["email"], Is.EqualTo("jose@ora.com")); + Assert.That(document.values.ContainsKey("startDate")); } [Test] @@ -162,7 +162,7 @@ public void SimplePatchUsingMySqlExpressionClass() Collection collection = CreateCollection("test"); Result r = ExecuteAddStatement(collection.Add("{ \"_id\": \"123\", \"email\": \"alice@ora.com\", \"startDate\": \"4/1/2017\" }")); - Assert.AreEqual(1, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(1)); var patch = new { @@ -171,7 +171,7 @@ public void SimplePatchUsingMySqlExpressionClass() ExecuteModifyStatement(collection.Modify("true").Patch(patch)); DbDoc document = collection.GetOne("123"); - Assert.AreEqual("ALICE@ORA.COM", document.values["email"]); + Assert.That(document.values["email"], Is.EqualTo("ALICE@ORA.COM")); } [Test] @@ -181,59 +181,59 @@ public void CRUD() Collection collection = CreateCollection("test"); Result r = ExecuteAddStatement(collection.Add(documentsAsJsonStrings)); - Assert.AreEqual(1, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(1)); // Add field. ExecuteModifyStatement(collection.Modify("language = :lang").Patch("{ \"translations\": [\"Spanish\"] }").Bind("lang", "English")); var document = ExecuteFindStatement(collection.Find("language = :lang").Bind("lang", "English")).FetchOne(); - Assert.True(document.values.ContainsKey("translations")); + Assert.That(document.values.ContainsKey("translations")); // Update field. ExecuteModifyStatement(collection.Modify("language = :lang").Patch("{ \"translations\": [\"Spanish\", \"Italian\"] }").Bind("lang", "English")); document = ExecuteFindStatement(collection.Find("language = :lang").Bind("lang", "English")).FetchOne(); - Assert.True(document.values.ContainsKey("translations")); + Assert.That(document.values.ContainsKey("translations")); var translations = (object[])document.values["translations"]; - Assert.AreEqual("Spanish", (string)translations[0]); - Assert.AreEqual("Italian", (string)translations[1]); + Assert.That((string)translations[0], Is.EqualTo("Spanish")); + Assert.That((string)translations[1], Is.EqualTo("Italian")); // Remove field. ExecuteModifyStatement(collection.Modify("language = :lang").Patch("{ \"translations\": null }").Bind("lang", "English")); document = ExecuteFindStatement(collection.Find("language = :lang").Bind("lang", "English")).FetchOne(); - Assert.False(document.values.ContainsKey("translations")); + Assert.That(document.values.ContainsKey("translations"), Is.False); // Add field. - Assert.False(((Dictionary)document.values["additionalinfo"]).ContainsKey("musicby")); + Assert.That(((Dictionary)document.values["additionalinfo"]).ContainsKey("musicby"), Is.False); ExecuteModifyStatement(collection.Modify("additionalinfo.director.name = :director").Patch("{ \"additionalinfo\": { \"musicby\": \"Sakila D\" } }").Bind("director", "Sharice Legaspi")); document = ExecuteFindStatement(collection.Find("language = :lang").Bind("lang", "English")).FetchOne(); - Assert.True(((Dictionary)document.values["additionalinfo"]).ContainsKey("musicby")); + Assert.That(((Dictionary)document.values["additionalinfo"]).ContainsKey("musicby")); // Update field. ExecuteModifyStatement(collection.Modify("additionalinfo.director.name = :director").Patch("{ \"additionalinfo\": { \"musicby\": \"The Sakila\" } }").Bind("director", "Sharice Legaspi")); document = ExecuteFindStatement(collection.Find("language = :lang").Bind("lang", "English")).FetchOne(); - Assert.True(((Dictionary)document.values["additionalinfo"]).ContainsKey("musicby")); - Assert.AreEqual("The Sakila", ((Dictionary)document.values["additionalinfo"])["musicby"]); + Assert.That(((Dictionary)document.values["additionalinfo"]).ContainsKey("musicby")); + Assert.That(((Dictionary)document.values["additionalinfo"])["musicby"], Is.EqualTo("The Sakila")); // Remove field. ExecuteModifyStatement(collection.Modify("additionalinfo.director.name = :director").Patch("{ \"additionalinfo\": { \"musicby\": null } }").Bind("director", "Sharice Legaspi")); document = ExecuteFindStatement(collection.Find("additionalinfo.director.name = :director").Bind("director", "Sharice Legaspi")).FetchOne(); - Assert.False(((Dictionary)document.values["additionalinfo"]).ContainsKey("musicby")); + Assert.That(((Dictionary)document.values["additionalinfo"]).ContainsKey("musicby"), Is.False); // Add field. - Assert.False(((Dictionary)((Dictionary)document.values["additionalinfo"])["director"]).ContainsKey("country")); + Assert.That(((Dictionary)((Dictionary)document.values["additionalinfo"])["director"]).ContainsKey("country"), Is.False); ExecuteModifyStatement(collection.Modify("additionalinfo.director.name = :director").Patch("{ \"additionalinfo\": { \"director\": { \"country\": \"France\" } } }").Bind("director", "Sharice Legaspi")); document = ExecuteFindStatement(collection.Find("language = :lang").Bind("lang", "English")).FetchOne(); - Assert.True(((Dictionary)((Dictionary)document.values["additionalinfo"])["director"]).ContainsKey("country")); + Assert.That(((Dictionary)((Dictionary)document.values["additionalinfo"])["director"]).ContainsKey("country")); // Update field. ExecuteModifyStatement(collection.Modify("additionalinfo.director.name = :director").Patch("{ \"additionalinfo\": { \"director\": { \"country\": \"Canada\" } } }").Bind("director", "Sharice Legaspi")); document = ExecuteFindStatement(collection.Find("language = :lang").Bind("lang", "English")).FetchOne(); - Assert.True(((Dictionary)((Dictionary)document.values["additionalinfo"])["director"]).ContainsKey("country")); - Assert.AreEqual("Canada", ((Dictionary)((Dictionary)document.values["additionalinfo"])["director"])["country"]); + Assert.That(((Dictionary)((Dictionary)document.values["additionalinfo"])["director"]).ContainsKey("country")); + Assert.That(((Dictionary)((Dictionary)document.values["additionalinfo"])["director"])["country"], Is.EqualTo("Canada")); // Remove field. ExecuteModifyStatement(collection.Modify("additionalinfo.director.name = :director").Patch("{ \"additionalinfo\": { \"director\": { \"country\": null } } }").Bind("director", "Sharice Legaspi")); document = ExecuteFindStatement(collection.Find("additionalinfo.director.name = :director").Bind("director", "Sharice Legaspi")).FetchOne(); - Assert.False(((Dictionary)((Dictionary)document.values["additionalinfo"])["director"]).ContainsKey("country")); + Assert.That(((Dictionary)((Dictionary)document.values["additionalinfo"])["director"]).ContainsKey("country"), Is.False); } #endregion @@ -247,30 +247,30 @@ public void ReplaceUpdateInDifferentNestingLevels() Collection collection = CreateCollection("test"); Result r = ExecuteAddStatement(collection.Add(documentsAsDbDocs)); - Assert.AreEqual(1, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(1)); DbDoc document = collection.GetOne("a6f4b93e1a264a108393524f29546a8c"); - Assert.AreEqual("AFRICAN EGG", document["title"]); + Assert.That(document["title"], Is.EqualTo("AFRICAN EGG")); ExecuteModifyStatement(collection.Modify("_id = :id").Patch("{ \"title\": \"The African Egg\" }").Bind("id", "a6f4b93e1a264a108393524f29546a8c")); document = collection.GetOne("a6f4b93e1a264a108393524f29546a8c"); - Assert.AreEqual("The African Egg", document["title"]); + Assert.That(document["title"], Is.EqualTo("The African Egg")); - Assert.AreEqual(57, ((Dictionary)((Dictionary)document.values["additionalinfo"])["director"])["age"]); + Assert.That(((Dictionary)((Dictionary)document.values["additionalinfo"])["director"])["age"], Is.EqualTo(57)); ExecuteModifyStatement(collection.Modify("additionalinfo.director.name = :director").Patch("{ \"additionalinfo\": { \"director\": { \"age\": 67 } } }").Bind("director", "Sharice Legaspi")); document = collection.GetOne("a6f4b93e1a264a108393524f29546a8c"); - Assert.AreEqual(67, ((Dictionary)((Dictionary)document.values["additionalinfo"])["director"])["age"]); + Assert.That(((Dictionary)((Dictionary)document.values["additionalinfo"])["director"])["age"], Is.EqualTo(67)); ExecuteModifyStatement(collection.Modify("_id = :id").Patch("{ \"additionalinfo\": { \"director\": { \"age\": 77 } } }").Bind("id", "a6f4b93e1a264a108393524f29546a8c")); document = collection.GetOne("a6f4b93e1a264a108393524f29546a8c"); - Assert.AreEqual(77, ((Dictionary)((Dictionary)document.values["additionalinfo"])["director"])["age"]); + Assert.That(((Dictionary)((Dictionary)document.values["additionalinfo"])["director"])["age"], Is.EqualTo(77)); ExecuteModifyStatement(collection.Modify("_id = :id").Patch("{ \"title\": { \"movie\": \"The African Egg\"} }").Bind("id", "a6f4b93e1a264a108393524f29546a8c")); document = collection.GetOne("a6f4b93e1a264a108393524f29546a8c"); - Assert.AreEqual("The African Egg", ((Dictionary)document.values["title"])["movie"]); + Assert.That(((Dictionary)document.values["title"])["movie"], Is.EqualTo("The African Egg")); ExecuteModifyStatement(collection.Modify("_id = :id").Patch("{ \"additionalinfo\": \"No data available\" }").Bind("id", "a6f4b93e1a264a108393524f29546a8c")); document = collection.GetOne("a6f4b93e1a264a108393524f29546a8c"); - Assert.AreEqual("No data available", document.values["additionalinfo"]); + Assert.That(document.values["additionalinfo"], Is.EqualTo("No data available")); } [Test] @@ -280,32 +280,32 @@ public void AddRemoveFieldInDifferentNestingLevels() Collection collection = CreateCollection("test"); Result r = ExecuteAddStatement(collection.Add(documentsAsDbDocs)); - Assert.AreEqual(1, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(1)); DbDoc document = collection.GetOne("a6f4b93e1a264a108393524f29546a8c"); - Assert.False(document.values.ContainsKey("translations")); + Assert.That(document.values.ContainsKey("translations"), Is.False); ExecuteModifyStatement(collection.Modify("_id = :id").Patch("{ \"translations\": [\"Spanish\"] }").Bind("id", "a6f4b93e1a264a108393524f29546a8c")); document = collection.GetOne("a6f4b93e1a264a108393524f29546a8c"); - Assert.True(document.values.ContainsKey("translations")); + Assert.That(document.values.ContainsKey("translations")); ExecuteModifyStatement(collection.Modify("_id = :id").Patch("{ \"translations\": null }").Bind("id", "a6f4b93e1a264a108393524f29546a8c")); document = collection.GetOne("a6f4b93e1a264a108393524f29546a8c"); - Assert.False(document.values.ContainsKey("translations")); + Assert.That(document.values.ContainsKey("translations"), Is.False); - Assert.False(((Dictionary)((Dictionary)document.values["additionalinfo"])["director"]).ContainsKey("country")); + Assert.That(((Dictionary)((Dictionary)document.values["additionalinfo"])["director"]).ContainsKey("country"), Is.False); ExecuteModifyStatement(collection.Modify("additionalinfo.director.name = :director").Patch("{ \"additionalinfo\": { \"director\": { \"country\": \"France\" } } }").Bind("director", "Sharice Legaspi")); document = collection.GetOne("a6f4b93e1a264a108393524f29546a8c"); - Assert.True(((Dictionary)((Dictionary)document.values["additionalinfo"])["director"]).ContainsKey("country")); + Assert.That(((Dictionary)((Dictionary)document.values["additionalinfo"])["director"]).ContainsKey("country")); ExecuteModifyStatement(collection.Modify("additionalinfo.director.name = :director").Patch("{ \"additionalinfo\": { \"director\": { \"country\": null } } }").Bind("director", "Sharice Legaspi")); document = collection.GetOne("a6f4b93e1a264a108393524f29546a8c"); - Assert.False(((Dictionary)((Dictionary)document.values["additionalinfo"])["director"]).ContainsKey("country")); + Assert.That(((Dictionary)((Dictionary)document.values["additionalinfo"])["director"]).ContainsKey("country"), Is.False); - Assert.False(((Dictionary)document.values["additionalinfo"]).ContainsKey("musicby")); + Assert.That(((Dictionary)document.values["additionalinfo"]).ContainsKey("musicby"), Is.False); ExecuteModifyStatement(collection.Modify("_id = :id").Patch("{ \"additionalinfo\": { \"musicby\": \"The Sakila\" } }").Bind("id", "a6f4b93e1a264a108393524f29546a8c")); document = collection.GetOne("a6f4b93e1a264a108393524f29546a8c"); - Assert.True(((Dictionary)document.values["additionalinfo"]).ContainsKey("musicby")); + Assert.That(((Dictionary)document.values["additionalinfo"]).ContainsKey("musicby")); ExecuteModifyStatement(collection.Modify("_id = :id").Patch("{ \"additionalinfo\": { \"musicby\": null } }").Bind("id", "a6f4b93e1a264a108393524f29546a8c")); document = collection.GetOne("a6f4b93e1a264a108393524f29546a8c"); - Assert.False(((Dictionary)document.values["additionalinfo"]).ContainsKey("musicby")); + Assert.That(((Dictionary)document.values["additionalinfo"]).ContainsKey("musicby"), Is.False); } #endregion @@ -319,7 +319,7 @@ public void CRUDMultipleFields() Collection collection = CreateCollection("test"); Result r = ExecuteAddStatement(collection.Add(documentsAsDbDocs)); - Assert.AreEqual(1, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(1)); DbDoc document = collection.GetOne("a6f4b93e1a264a108393524f29546a8c"); @@ -327,34 +327,34 @@ public void CRUDMultipleFields() ExecuteModifyStatement(collection.Modify("_id = :id").Patch("{ \"field 1\": \"one\", \"field 2\": \"two\", \"field 3\": \"three\" }").Bind("id", "a6f4b93e1a264a108393524f29546a8c")); ExecuteModifyStatement(collection.Modify("additionalinfo.director.name = :director").Patch("{ \"additionalinfo\": { \"director\": { \"field 1\": \"one\", \"field 2\": \"two\", \"field 3\": \"three\" } } }").Bind("director", "Sharice Legaspi")); document = collection.GetOne("a6f4b93e1a264a108393524f29546a8c"); - Assert.AreEqual("one", document.values["field 1"]); - Assert.AreEqual("two", document.values["field 2"]); - Assert.AreEqual("three", document.values["field 3"]); - Assert.AreEqual("one", (((Dictionary)((Dictionary)document.values["additionalinfo"])["director"]))["field 1"]); - Assert.AreEqual("two", (((Dictionary)((Dictionary)document.values["additionalinfo"])["director"]))["field 2"]); - Assert.AreEqual("three", (((Dictionary)((Dictionary)document.values["additionalinfo"])["director"]))["field 3"]); + Assert.That(document.values["field 1"], Is.EqualTo("one")); + Assert.That(document.values["field 2"], Is.EqualTo("two")); + Assert.That(document.values["field 3"], Is.EqualTo("three")); + Assert.That((((Dictionary)((Dictionary)document.values["additionalinfo"])["director"]))["field 1"], Is.EqualTo("one")); + Assert.That((((Dictionary)((Dictionary)document.values["additionalinfo"])["director"]))["field 2"], Is.EqualTo("two")); + Assert.That((((Dictionary)((Dictionary)document.values["additionalinfo"])["director"]))["field 3"], Is.EqualTo("three")); // Update/Replace fields. ExecuteModifyStatement(collection.Modify("_id = :id").Patch("{ \"field 1\": \"ONE\", \"field 2\": \"TWO\", \"field 3\": \"THREE\" }").Bind("id", "a6f4b93e1a264a108393524f29546a8c")); ExecuteModifyStatement(collection.Modify("additionalinfo.director.name = :director").Patch("{ \"additionalinfo\": { \"director\": { \"field 1\": \"ONE\", \"field 2\": \"TWO\", \"field 3\": \"THREE\" } } }").Bind("director", "Sharice Legaspi")); document = collection.GetOne("a6f4b93e1a264a108393524f29546a8c"); - Assert.AreEqual("ONE", document.values["field 1"]); - Assert.AreEqual("TWO", document.values["field 2"]); - Assert.AreEqual("THREE", document.values["field 3"]); - Assert.AreEqual("ONE", (((Dictionary)((Dictionary)document.values["additionalinfo"])["director"]))["field 1"]); - Assert.AreEqual("TWO", (((Dictionary)((Dictionary)document.values["additionalinfo"])["director"]))["field 2"]); - Assert.AreEqual("THREE", (((Dictionary)((Dictionary)document.values["additionalinfo"])["director"]))["field 3"]); + Assert.That(document.values["field 1"], Is.EqualTo("ONE")); + Assert.That(document.values["field 2"], Is.EqualTo("TWO")); + Assert.That(document.values["field 3"], Is.EqualTo("THREE")); + Assert.That((((Dictionary)((Dictionary)document.values["additionalinfo"])["director"]))["field 1"], Is.EqualTo("ONE")); + Assert.That((((Dictionary)((Dictionary)document.values["additionalinfo"])["director"]))["field 2"], Is.EqualTo("TWO")); + Assert.That((((Dictionary)((Dictionary)document.values["additionalinfo"])["director"]))["field 3"], Is.EqualTo("THREE")); // Remove fields. ExecuteModifyStatement(collection.Modify("_id = :id").Patch("{ \"field 1\": null, \"field 2\": null, \"field 3\": null }").Bind("id", "a6f4b93e1a264a108393524f29546a8c")); ExecuteModifyStatement(collection.Modify("additionalinfo.director.name = :director").Patch("{ \"additionalinfo\": { \"director\": { \"field 1\": null, \"field 2\": null, \"field 3\": null } } }").Bind("director", "Sharice Legaspi")); document = collection.GetOne("a6f4b93e1a264a108393524f29546a8c"); - Assert.False(document.values.ContainsKey("field 1")); - Assert.False(document.values.ContainsKey("field 2")); - Assert.False(document.values.ContainsKey("field 3")); - Assert.False((((Dictionary)((Dictionary)document.values["additionalinfo"])["director"])).ContainsKey("field 1")); - Assert.False((((Dictionary)((Dictionary)document.values["additionalinfo"])["director"])).ContainsKey("field 2")); - Assert.False((((Dictionary)((Dictionary)document.values["additionalinfo"])["director"])).ContainsKey("field 3")); + Assert.That(document.values.ContainsKey("field 1"), Is.False); + Assert.That(document.values.ContainsKey("field 2"), Is.False); + Assert.That(document.values.ContainsKey("field 3"), Is.False); + Assert.That((((Dictionary)((Dictionary)document.values["additionalinfo"])["director"])).ContainsKey("field 1"), Is.False); + Assert.That((((Dictionary)((Dictionary)document.values["additionalinfo"])["director"])).ContainsKey("field 2"), Is.False); + Assert.That((((Dictionary)((Dictionary)document.values["additionalinfo"])["director"])).ContainsKey("field 3"), Is.False); } #endregion @@ -368,17 +368,17 @@ public void AddNewFieldUsingExpressions() Collection collection = CreateCollection("test"); Result r = ExecuteAddStatement(collection.Add(documentsAsDbDocs)); - Assert.AreEqual(1, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(1)); DbDoc document = ExecuteFindStatement(collection.Find()).FetchOne(); - Assert.False(((Dictionary)((object[])document.values["actors"])[0]).ContainsKey("age")); + Assert.That(((Dictionary)((object[])document.values["actors"])[0]).ContainsKey("age"), Is.False); Assert.Throws(() => ExecuteModifyStatement(collection.Modify("true").Patch("{ \"actors\": { \"age\": Year(CURDATE()) - CAST(SUBSTRING_INDEX(actors.birthdate, ' ', - 1) AS DECIMAL)) } }"))); document = ExecuteFindStatement(collection.Find()).FetchOne(); - Assert.False(document.values.ContainsKey("audio")); + Assert.That(document.values.ContainsKey("audio"), Is.False); ExecuteModifyStatement(collection.Modify("true").Patch("{ \"audio\": CONCAT($.language, ', no subtitles') }")); document = ExecuteFindStatement(collection.Find()).FetchOne(); - Assert.AreEqual("English, no subtitles", document.values["audio"]); + Assert.That(document.values["audio"], Is.EqualTo("English, no subtitles")); } [Test] @@ -388,13 +388,13 @@ public void ReplaceUpdateUsingExpressions() Collection collection = CreateCollection("test"); Result r = ExecuteAddStatement(collection.Add(documentsAsDbDocs)); - Assert.AreEqual(1, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(1)); DbDoc document = collection.GetOne("a6f4b93e1a264a108393524f29546a8c"); - Assert.False(document.values.ContainsKey("audio")); + Assert.That(document.values.ContainsKey("audio"), Is.False); ExecuteModifyStatement(collection.Modify("true").Patch("{ \"audio\": CONCAT(UPPER($.language), ', No Subtitles') }")); document = collection.GetOne("a6f4b93e1a264a108393524f29546a8c"); - Assert.AreEqual("ENGLISH, No Subtitles", document.values["audio"]); + Assert.That(document.values["audio"], Is.EqualTo("ENGLISH, No Subtitles")); } [Test] @@ -404,12 +404,12 @@ public void ReplaceUpdateIdUsingExpressions() Collection collection = CreateCollection("test"); Result r = ExecuteAddStatement(collection.Add(documentsAsDbDocs)); - Assert.AreEqual(1, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(1)); // Changes to the _id field are ignored. ExecuteModifyStatement(collection.Modify("_id = :id").Patch("{ \"_id\": replace(UUID(), '-', '') }").Bind("id", "a6f4b93e1a264a108393524f29546a8c")); DbDoc document = ExecuteFindStatement(collection.Find()).FetchOne(); - Assert.AreEqual("a6f4b93e1a264a108393524f29546a8c", document.Id); + Assert.That(document.Id, Is.EqualTo("a6f4b93e1a264a108393524f29546a8c")); } [Test] @@ -419,13 +419,13 @@ public void AddIdToNestedDocumentUsingExpressions() Collection collection = CreateCollection("test"); Result r = ExecuteAddStatement(collection.Add(documentsAsDbDocs)); - Assert.AreEqual(1, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(1)); DbDoc document = collection.GetOne("a6f4b93e1a264a108393524f29546a8c"); - Assert.False(((Dictionary)document.values["additionalinfo"]).ContainsKey("_id")); + Assert.That(((Dictionary)document.values["additionalinfo"]).ContainsKey("_id"), Is.False); ExecuteModifyStatement(collection.Modify("_id = :id").Patch("{ \"additionalinfo\": { \"_id\": replace(UUID(), '-', '') } }").Bind("id", "a6f4b93e1a264a108393524f29546a8c")); document = collection.GetOne("a6f4b93e1a264a108393524f29546a8c"); - Assert.True(((Dictionary)document.values["additionalinfo"]).ContainsKey("_id")); + Assert.That(((Dictionary)document.values["additionalinfo"]).ContainsKey("_id")); } [Test] @@ -435,12 +435,12 @@ public void AddNullFieldUsingExpressions() Collection collection = CreateCollection("test"); Result r = ExecuteAddStatement(collection.Add(documentsAsDbDocs)); - Assert.AreEqual(1, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(1)); DbDoc document = collection.GetOne("a6f4b93e1a264a108393524f29546a8c"); - Assert.False(((Dictionary)document.values["additionalinfo"]).ContainsKey("releasedate")); + Assert.That(((Dictionary)document.values["additionalinfo"]).ContainsKey("releasedate"), Is.False); Exception ex = Assert.Throws(() => ExecuteModifyStatement(collection.Modify("_id = :id").Patch("{ \"releasedate\": DATE_ADD('2006-04-00',INTERVAL 1 DAY) }").Bind("id", "a6f4b93e1a264a108393524f29546a8c"))); - Assert.AreEqual("Invalid data for update operation on document collection table", ex.Message); + Assert.That(ex.Message, Is.EqualTo("Invalid data for update operation on document collection table")); } [Test] @@ -450,13 +450,13 @@ public void ReplaceUpdateNullFieldReturnedFromExpression() Collection collection = CreateCollection("test"); Result r = ExecuteAddStatement(collection.Add(documentsAsDbDocs)); - Assert.AreEqual(1, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(1)); DbDoc document = collection.GetOne("a6f4b93e1a264a108393524f29546a8c"); - Assert.AreEqual("AFRICAN EGG", document.values["title"]); + Assert.That(document.values["title"], Is.EqualTo("AFRICAN EGG")); ExecuteModifyStatement(collection.Modify("_id = :id").Patch("{ \"title\": concat('my ', NULL, ' title') }").Bind("id", "a6f4b93e1a264a108393524f29546a8c")); document = collection.GetOne("a6f4b93e1a264a108393524f29546a8c"); - Assert.False(document.values.ContainsKey("title")); + Assert.That(document.values.ContainsKey("title"), Is.False); } [Test] @@ -466,13 +466,13 @@ public void AddNewFieldReturnedFromExpression() Collection collection = CreateCollection("test"); Result r = ExecuteAddStatement(collection.Add(documentsAsDbDocs)); - Assert.AreEqual(1, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(1)); DbDoc document = collection.GetOne("a6f4b93e1a264a108393524f29546a8c"); - Assert.False(document.values.ContainsKey("docfield")); + Assert.That(document.values.ContainsKey("docfield"), Is.False); ExecuteModifyStatement(collection.Modify("_id = :id").Patch("{ \"docfield\": JSON_OBJECT('field 1', 1, 'field 2', 'two') }").Bind("id", "a6f4b93e1a264a108393524f29546a8c")); document = collection.GetOne("a6f4b93e1a264a108393524f29546a8c"); - Assert.True(document.values.ContainsKey("docfield")); + Assert.That(document.values.ContainsKey("docfield")); } [Test] @@ -482,13 +482,13 @@ public void ReplaceUpdateFieldWithDocumentReturnedFromExpression() Collection collection = CreateCollection("test"); Result r = ExecuteAddStatement(collection.Add(documentsAsDbDocs)); - Assert.AreEqual(1, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(1)); DbDoc document = collection.GetOne("a6f4b93e1a264a108393524f29546a8c"); - Assert.AreEqual("Science fiction", document.values["genre"]); + Assert.That(document.values["genre"], Is.EqualTo("Science fiction")); ExecuteModifyStatement(collection.Modify("_id = :id").Patch("{ \"genre\": JSON_OBJECT('name', 'Science Fiction') }").Bind("id", "a6f4b93e1a264a108393524f29546a8c")); document = collection.GetOne("a6f4b93e1a264a108393524f29546a8c"); - Assert.AreEqual("Science Fiction", ((Dictionary)document.values["genre"])["name"]); + Assert.That(((Dictionary)document.values["genre"])["name"], Is.EqualTo("Science Fiction")); } #endregion @@ -502,12 +502,12 @@ public void ReplaceUpdateId() Collection collection = CreateCollection("test"); Result r = ExecuteAddStatement(collection.Add(documentsAsDbDocs)); - Assert.AreEqual(1, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(1)); // Changes to the _id field are ignored. ExecuteModifyStatement(collection.Modify("_id = :id").Patch("{ \"_id\": \"b5f4b93e1a264a108393524f29546a9d\" }").Bind("id", "a6f4b93e1a264a108393524f29546a8c")); DbDoc document = ExecuteFindStatement(collection.Find()).FetchOne(); - Assert.AreEqual("a6f4b93e1a264a108393524f29546a8c", document.Id); + Assert.That(document.Id, Is.EqualTo("a6f4b93e1a264a108393524f29546a8c")); } [Test] @@ -517,19 +517,19 @@ public void AddIdToNestedDocument() Collection collection = CreateCollection("test"); Result r = ExecuteAddStatement(collection.Add(documentsAsDbDocs)); - Assert.AreEqual(1, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(1)); // Add id to nested document is allowed. DbDoc document = ExecuteFindStatement(collection.Find()).FetchOne(); var field = (Dictionary)document.values["additionalinfo"]; - Assert.AreEqual(3, field.Count); - Assert.False(field.ContainsKey("_id")); + Assert.That(field.Count, Is.EqualTo(3)); + Assert.That(field.ContainsKey("_id"), Is.False); ExecuteModifyStatement(collection.Modify("_id = :id").Patch("{ \"additionalinfo\": { \"_id\": \"b5f4b93e1a264a108393524f29546a9d\" } }").Bind("id", "a6f4b93e1a264a108393524f29546a8c")); document = ExecuteFindStatement(collection.Find()).FetchOne(); field = (Dictionary)document.values["additionalinfo"]; - Assert.AreEqual(4, field.Count); - Assert.True(field.ContainsKey("_id")); - Assert.AreEqual("b5f4b93e1a264a108393524f29546a9d", field["_id"]); + Assert.That(field.Count, Is.EqualTo(4)); + Assert.That(field.ContainsKey("_id")); + Assert.That(field["_id"], Is.EqualTo("b5f4b93e1a264a108393524f29546a9d")); } [Test] @@ -539,11 +539,11 @@ public void SetNullToId() Collection collection = CreateCollection("test"); Result r = ExecuteAddStatement(collection.Add(documentsAsJsonStrings)); - Assert.AreEqual(1, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(1)); // Changes to the _id field are ignored. ExecuteModifyStatement(collection.Modify("true").Patch("{ \"_id\": NULL }")); - Assert.AreEqual("a6f4b93e1a264a108393524f29546a8c", ExecuteFindStatement(collection.Find()).FetchOne().Id); + Assert.That(ExecuteFindStatement(collection.Find()).FetchOne().Id, Is.EqualTo("a6f4b93e1a264a108393524f29546a8c")); } [Test] @@ -553,28 +553,28 @@ public void AddNullFields() Collection collection = CreateCollection("test"); Result r = ExecuteAddStatement(collection.Add(documentsAsJsonStrings)); - Assert.AreEqual(1, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(1)); ExecuteModifyStatement(collection.Modify("true").Patch("{ \"nullfield\": NULL }")); - Assert.False(ExecuteFindStatement(collection.Find()).FetchOne().values.ContainsKey("nullfield")); + Assert.That(ExecuteFindStatement(collection.Find()).FetchOne().values.ContainsKey("nullfield"), Is.False); ExecuteModifyStatement(collection.Modify("true").Patch("{ \"nullfield\": [NULL, NULL] }")); DbDoc document = ExecuteFindStatement(collection.Find()).FetchOne(); - Assert.True(document.values.ContainsKey("nullfield")); + Assert.That(document.values.ContainsKey("nullfield")); var nullArray = (object[])document.values["nullfield"]; - Assert.Null(nullArray[0]); - Assert.Null(nullArray[1]); + Assert.That(nullArray[0], Is.Null); + Assert.That(nullArray[1], Is.Null); ExecuteModifyStatement(collection.Modify("true").Patch("{ \"nullfield\": { \"nested\": NULL } }")); document = ExecuteFindStatement(collection.Find()).FetchOne(); - Assert.True(ExecuteFindStatement(collection.Find()).FetchOne().values.ContainsKey("nullfield")); - Assert.True(((Dictionary)document.values["nullfield"]).Count == 0); + Assert.That(ExecuteFindStatement(collection.Find()).FetchOne().values.ContainsKey("nullfield")); + Assert.That(((Dictionary)document.values["nullfield"]).Count == 0); ExecuteModifyStatement(collection.Modify("true").Patch("{ \"nullfield\": { \"nested\": [NULL, NULL] } }")); document = ExecuteFindStatement(collection.Find()).FetchOne(); var nestedNullArray = (object[])((Dictionary)document.values["nullfield"])["nested"]; - Assert.Null(nestedNullArray[0]); - Assert.Null(nestedNullArray[1]); + Assert.That(nestedNullArray[0], Is.Null); + Assert.That(nestedNullArray[1], Is.Null); } [Test] @@ -584,31 +584,31 @@ public void AddNestedNullFields() Collection collection = CreateCollection("test"); Result r = ExecuteAddStatement(collection.Add(documentsAsJsonStrings)); - Assert.AreEqual(1, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(1)); ExecuteModifyStatement(collection.Modify("true").Patch("{ \"additionalinfo\": { \"nullfield\": NULL } }")); - Assert.False(((Dictionary)ExecuteFindStatement(collection.Find()).FetchOne().values["additionalinfo"]).ContainsKey("nullfield")); + Assert.That(((Dictionary)ExecuteFindStatement(collection.Find()).FetchOne().values["additionalinfo"]).ContainsKey("nullfield"), Is.False); ExecuteModifyStatement(collection.Modify("true").Patch("{ \"additionalinfo\": { \"nullfield\": [NULL, NULL] } }")); DbDoc document = collection.GetOne("a6f4b93e1a264a108393524f29546a8c"); var nestedNullArray = (object[])((Dictionary)document.values["additionalinfo"])["nullfield"]; - Assert.Null(nestedNullArray[0]); - Assert.Null(nestedNullArray[1]); + Assert.That(nestedNullArray[0], Is.Null); + Assert.That(nestedNullArray[1], Is.Null); ExecuteModifyStatement(collection.Modify("true").Patch("{ \"additionalinfo\": { \"nullfield\": { \"nested\": NULL } } }")); document = collection.GetOne("a6f4b93e1a264a108393524f29546a8c"); - Assert.False(((Dictionary)((Dictionary)document.values["additionalinfo"])["nullfield"]).ContainsKey("nullfield")); + Assert.That(((Dictionary)((Dictionary)document.values["additionalinfo"])["nullfield"]).ContainsKey("nullfield"), Is.False); ExecuteModifyStatement(collection.Modify("true").Patch("{ \"additionalinfo\": { \"nullfield\": { \"nested\": [NULL, NULL] } } }")); document = collection.GetOne("a6f4b93e1a264a108393524f29546a8c"); nestedNullArray = (object[])((Dictionary)((Dictionary)document.values["additionalinfo"])["nullfield"])["nested"]; - Assert.Null(nestedNullArray[0]); - Assert.Null(nestedNullArray[1]); + Assert.That(nestedNullArray[0], Is.Null); + Assert.That(nestedNullArray[1], Is.Null); ExecuteModifyStatement(collection.Modify("true").Patch("{ \"additionalinfo\": { \"nullfield\": { \"nested\": JSON_OBJECT('field', null) } } }")); document = collection.GetOne("a6f4b93e1a264a108393524f29546a8c"); var nestedObject = (Dictionary)((Dictionary)((Dictionary)document.values["additionalinfo"])["nullfield"])["nested"]; - CollectionAssert.IsEmpty(nestedObject); + Assert.That(nestedObject, Is.Empty); } #endregion @@ -618,32 +618,32 @@ public void GetDocumentProperties() { Collection collection = CreateCollection("test"); Result r = ExecuteAddStatement(collection.Add(documentsAsDbDocs)); - Assert.AreEqual(1, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(1)); // Get root string properties. DbDoc document = collection.GetOne("a6f4b93e1a264a108393524f29546a8c"); - Assert.AreEqual("a6f4b93e1a264a108393524f29546a8c", document.Id); - Assert.AreEqual("AFRICAN EGG", document["title"]); - Assert.AreEqual("G", document["rating"]); + Assert.That(document.Id, Is.EqualTo("a6f4b93e1a264a108393524f29546a8c")); + Assert.That(document["title"], Is.EqualTo("AFRICAN EGG")); + Assert.That(document["rating"], Is.EqualTo("G")); // Get root numeric properties. - Assert.AreEqual(2006, document["releaseyear"]); - Assert.AreEqual(130, document["duration"]); + Assert.That(document["releaseyear"], Is.EqualTo(2006)); + Assert.That(document["duration"], Is.EqualTo(130)); // Get root array. object[] actors = document["actors"] as object[]; - Assert.True(actors.Length == 3); + Assert.That(actors.Length == 3); Dictionary actor1 = actors[1] as Dictionary; - Assert.AreEqual("VAL BOLGER", actor1["name"]); + Assert.That(actor1["name"], Is.EqualTo("VAL BOLGER")); // Get nested string properies. - Assert.AreEqual("Sharice Legaspi", document["additionalinfo.director.name"]); - Assert.AreEqual(57, document["additionalinfo.director.age"]); - Assert.AreEqual("Italy", document["additionalinfo.director.birthplace.country"]); + Assert.That(document["additionalinfo.director.name"], Is.EqualTo("Sharice Legaspi")); + Assert.That(document["additionalinfo.director.age"], Is.EqualTo(57)); + Assert.That(document["additionalinfo.director.birthplace.country"], Is.EqualTo("Italy")); // Get nested array. object[] awards = document["additionalinfo.director.awards"] as object[]; - Assert.True(awards.Length == 2); + Assert.That(awards.Length == 2); } [Test] @@ -652,51 +652,51 @@ public void PatchUsingDateAndTimeFunctions() string t1 = "{\"_id\": \"1\", \"name\": \"Alice\" }"; Collection collection = CreateCollection("test"); Result r = ExecuteAddStatement(collection.Add(t1)); - Assert.AreEqual(1, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(1)); ExecuteModifyStatement(collection.Modify("_id = :id").Patch("{ \"dateAndTimeValue\": YEAR('2000-01-01') }").Bind("id", "1")); DbDoc document = collection.GetOne("1"); - Assert.AreEqual(2000, document["dateAndTimeValue"]); + Assert.That(document["dateAndTimeValue"], Is.EqualTo(2000)); ExecuteModifyStatement(collection.Modify("_id = :id").Patch("{ \"dateAndTimeValue\": MONTH('2008-02-03') }").Bind("id", "1")); document = collection.GetOne("1"); - Assert.AreEqual(2, document["dateAndTimeValue"]); + Assert.That(document["dateAndTimeValue"], Is.EqualTo(2)); ExecuteModifyStatement(collection.Modify("_id = :id").Patch("{ \"dateAndTimeValue\": WEEK('2008-02-20') }").Bind("id", "1")); document = collection.GetOne("1"); - Assert.AreEqual(7, document["dateAndTimeValue"]); + Assert.That(document["dateAndTimeValue"], Is.EqualTo(7)); ExecuteModifyStatement(collection.Modify("_id = :id").Patch("{ \"dateAndTimeValue\": DAY('2008-02-20') }").Bind("id", "1")); document = collection.GetOne("1"); - Assert.AreEqual(20, document["dateAndTimeValue"]); + Assert.That(document["dateAndTimeValue"], Is.EqualTo(20)); ExecuteModifyStatement(collection.Modify("_id = :id").Patch("{ \"dateAndTimeValue\": HOUR('10:05:03') }").Bind("id", "1")); document = collection.GetOne("1"); - Assert.AreEqual(10, document["dateAndTimeValue"]); + Assert.That(document["dateAndTimeValue"], Is.EqualTo(10)); ExecuteModifyStatement(collection.Modify("_id = :id").Patch("{ \"dateAndTimeValue\": MINUTE('2008-02-03 10:05:03') }").Bind("id", "1")); document = collection.GetOne("1"); - Assert.AreEqual(5, document["dateAndTimeValue"]); + Assert.That(document["dateAndTimeValue"], Is.EqualTo(5)); ExecuteModifyStatement(collection.Modify("_id = :id").Patch("{ \"dateAndTimeValue\": SECOND('10:05:03') }").Bind("id", "1")); document = collection.GetOne("1"); - Assert.AreEqual(3, document["dateAndTimeValue"]); + Assert.That(document["dateAndTimeValue"], Is.EqualTo(3)); ExecuteModifyStatement(collection.Modify("_id = :id").Patch("{ \"dateAndTimeValue\": MICROSECOND('12:00:00.123456') }").Bind("id", "1")); document = collection.GetOne("1"); - Assert.AreEqual(123456, document["dateAndTimeValue"]); + Assert.That(document["dateAndTimeValue"], Is.EqualTo(123456)); ExecuteModifyStatement(collection.Modify("_id = :id").Patch("{ \"dateAndTimeValue\": QUARTER('2008-04-01') }").Bind("id", "1")); document = collection.GetOne("1"); - Assert.AreEqual(2, document["dateAndTimeValue"]); + Assert.That(document["dateAndTimeValue"], Is.EqualTo(2)); ExecuteModifyStatement(collection.Modify("_id = :id").Patch("{ \"dateAndTimeValue\": TIME('2003-12-31 01:02:03') }").Bind("id", "1")); document = collection.GetOne("1"); - Assert.AreEqual("01:02:03.000000", document["dateAndTimeValue"]); + Assert.That(document["dateAndTimeValue"], Is.EqualTo("01:02:03.000000")); ExecuteModifyStatement(collection.Modify("_id = :id").Patch("{ \"dateAndTimeValue\": DATE('2003-12-31 01:02:03') }").Bind("id", "1")); document = collection.GetOne("1"); - Assert.AreEqual("2003-12-31", document["dateAndTimeValue"]); + Assert.That(document["dateAndTimeValue"], Is.EqualTo("2003-12-31")); } [Test] @@ -705,19 +705,19 @@ public void PatchUsingOtherKnownFunctions() string t1 = "{\"_id\": \"1\", \"name\": \"Alice\" }"; Collection collection = CreateCollection("test"); Result r = ExecuteAddStatement(collection.Add(t1)); - Assert.AreEqual(1, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(1)); ExecuteModifyStatement(collection.Modify("_id = :id").Patch("{ \"otherValue\": CHAR(77, 121, 83, 81, '76') }").Bind("id", "1")); DbDoc document = collection.GetOne("1"); - Assert.AreEqual("base64:type15:TXlTUUw=", document["otherValue"]); + Assert.That(document["otherValue"], Is.EqualTo("base64:type15:TXlTUUw=")); ExecuteModifyStatement(collection.Modify("_id = :id").Patch("{ \"otherValue\": HEX('abc') }").Bind("id", "1")); document = collection.GetOne("1"); - Assert.AreEqual("616263", document["otherValue"]); + Assert.That(document["otherValue"], Is.EqualTo("616263")); ExecuteModifyStatement(collection.Modify("_id = :id").Patch("{ \"otherValue\": BIN(12) }").Bind("id", "1")); document = collection.GetOne("1"); - Assert.AreEqual("1100", document["otherValue"]); + Assert.That(document["otherValue"], Is.EqualTo("1100")); } #region WL14389 @@ -736,61 +736,61 @@ public void ModifyPatchMultipleRecords_S1() new {_id = 4, title = "Book 4", pages = 50,age = "12"} }; Result r = collection.Add(docs).Execute(); - Assert.AreEqual(4, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(4)); var document = collection.GetOne("1"); var jsonParams = new { title = "Book 100" }; r = collection.Modify("age = :age").Patch(jsonParams). Bind("age", "12").Execute();//Multiple Records - Assert.AreEqual(2, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(2)); string jsonParams1 = "{ \"title\": \"Book 400\"}"; r = collection.Modify("age = :age").Patch(jsonParams1). Bind("age", "18").Execute(); - Assert.AreEqual(1, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(1)); document = collection.GetOne("1"); - Assert.AreEqual("Book 100", document["title"]); + Assert.That(document["title"], Is.EqualTo("Book 100")); document = collection.GetOne("4"); - Assert.AreEqual("Book 100", document["title"]); + Assert.That(document["title"], Is.EqualTo("Book 100")); document = collection.GetOne("2"); - Assert.AreEqual("Book 400", document["title"]); + Assert.That(document["title"], Is.EqualTo("Book 400")); string splName = "A*b"; jsonParams1 = "{\"data1\":\"" + splName + "\"}"; r = collection.Modify("age = :age").Patch(jsonParams1). Bind("age", "18").Execute(); - Assert.AreEqual(1, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(1)); document = collection.GetOne("2"); - Assert.AreEqual(splName, document["data1"]); + Assert.That(document["data1"], Is.EqualTo(splName)); splName = "A/b"; jsonParams1 = "{\"data1\":\"" + splName + "\"}"; r = collection.Modify("age = :age").Patch(jsonParams1). Bind("age", "18").Execute(); - Assert.AreEqual(1, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(1)); document = collection.GetOne("2"); - Assert.AreEqual(splName, document["data1"]); + Assert.That(document["data1"], Is.EqualTo(splName)); splName = "A&b!c@d#e$f%g^h&i(j)k-l+m=0_p~q`r}s{t][.,?/><"; jsonParams1 = "{\"data1\":\"" + splName + "\"}"; r = collection.Modify("age = :age").Patch(jsonParams1). Bind("age", "18").Execute(); - Assert.AreEqual(1, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(1)); document = collection.GetOne("2"); - Assert.AreEqual(splName, document["data1"]); + Assert.That(document["data1"], Is.EqualTo(splName)); //Large Key Length string myString = new string('*', 65535); jsonParams1 = "{\"data1\":\"" + myString + "\"}"; r = collection.Modify("age = :age").Patch(jsonParams1). Bind("age", "18").Execute(); - Assert.AreEqual(1, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(1)); document = collection.GetOne("2"); - Assert.AreEqual(myString, document["data1"]); + Assert.That(document["data1"], Is.EqualTo(myString)); collection = CreateCollection("test"); r = collection.Add(documentsAsJsonStrings).Execute(); - Assert.AreEqual(1, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(1)); r = collection.Add(documentAsJsonString2).Execute(); - Assert.AreEqual(1, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(1)); document = collection.GetOne("a6f4b93e1a264a108393524f29546a8c"); collection.Modify("_id = :id").Patch("{ \"field 1\": \"one\", \"field 2\": \"two\", \"field 3\": \"three\" }"). @@ -807,26 +807,20 @@ public void ModifyPatchMultipleRecords_S1() "\"one\", \"field2 12\": \"two\", \"field3 13\": \"three\" } } }"). Bind("director", "Steven Spielberg").Execute(); document = collection.GetOne("a6f4b93e1a264a108393524f29546a8c"); - Assert.AreEqual("one", document["field 1"]); - Assert.AreEqual("two", document["field 2"]); - Assert.AreEqual("three", document["field 3"]); - Assert.AreEqual("one", - (((Dictionary)((Dictionary)document["additionalinfo"])["director"]))["field1 11"]); - Assert.AreEqual("two", - (((Dictionary)((Dictionary)document["additionalinfo"])["director"]))["field2 12"]); - Assert.AreEqual("three", - (((Dictionary)((Dictionary)document["additionalinfo"])["director"]))["field3 13"]); + Assert.That(document["field 1"], Is.EqualTo("one")); + Assert.That(document["field 2"], Is.EqualTo("two")); + Assert.That(document["field 3"], Is.EqualTo("three")); + Assert.That((((Dictionary)((Dictionary)document["additionalinfo"])["director"]))["field1 11"], Is.EqualTo("one")); + Assert.That((((Dictionary)((Dictionary)document["additionalinfo"])["director"]))["field2 12"], Is.EqualTo("two")); + Assert.That((((Dictionary)((Dictionary)document["additionalinfo"])["director"]))["field3 13"], Is.EqualTo("three")); document = collection.GetOne("123456789asdferdfghhghjh12334"); - Assert.AreEqual("one", document["field 1"]); - Assert.AreEqual("two", document["field 2"]); - Assert.AreEqual("three", document["field 3"]); - Assert.AreEqual("one", - (((Dictionary)((Dictionary)document["additionalinfo"])["director"]))["field1 11"]); - Assert.AreEqual("two", - (((Dictionary)((Dictionary)document["additionalinfo"])["director"]))["field2 12"]); - Assert.AreEqual("three", - (((Dictionary)((Dictionary)document["additionalinfo"])["director"]))["field3 13"]); + Assert.That(document["field 1"], Is.EqualTo("one")); + Assert.That(document["field 2"], Is.EqualTo("two")); + Assert.That(document["field 3"], Is.EqualTo("three")); + Assert.That((((Dictionary)((Dictionary)document["additionalinfo"])["director"]))["field1 11"], Is.EqualTo("one")); + Assert.That((((Dictionary)((Dictionary)document["additionalinfo"])["director"]))["field2 12"], Is.EqualTo("two")); + Assert.That((((Dictionary)((Dictionary)document["additionalinfo"])["director"]))["field3 13"], Is.EqualTo("three")); collection.Modify("language = :language"). Patch("{ \"additionalinfo\": { \"director\": { \"test1\": " + @@ -837,25 +831,19 @@ public void ModifyPatchMultipleRecords_S1() Bind("language", "English").Execute(); //Multiple Records document = collection.GetOne("a6f4b93e1a264a108393524f29546a8c"); - Assert.AreEqual("check1", document["field 1"]); - Assert.AreEqual("check2", document["field 2"]); - Assert.AreEqual("check3", document["field 3"]); - Assert.AreEqual("one", - (((Dictionary)((Dictionary)document["additionalinfo"])["director"]))["test1"]); - Assert.AreEqual("two", - (((Dictionary)((Dictionary)document["additionalinfo"])["director"]))["test2"]); - Assert.AreEqual("three", - (((Dictionary)((Dictionary)document["additionalinfo"])["director"]))["test3"]); + Assert.That(document["field 1"], Is.EqualTo("check1")); + Assert.That(document["field 2"], Is.EqualTo("check2")); + Assert.That(document["field 3"], Is.EqualTo("check3")); + Assert.That((((Dictionary)((Dictionary)document["additionalinfo"])["director"]))["test1"], Is.EqualTo("one")); + Assert.That((((Dictionary)((Dictionary)document["additionalinfo"])["director"]))["test2"], Is.EqualTo("two")); + Assert.That((((Dictionary)((Dictionary)document["additionalinfo"])["director"]))["test3"], Is.EqualTo("three")); document = collection.GetOne("123456789asdferdfghhghjh12334"); - Assert.AreEqual("check1", document["field 1"]); - Assert.AreEqual("check2", document["field 2"]); - Assert.AreEqual("check3", document["field 3"]); - Assert.AreEqual("one", - (((Dictionary)((Dictionary)document["additionalinfo"])["director"]))["test1"]); - Assert.AreEqual("two", - (((Dictionary)((Dictionary)document["additionalinfo"])["director"]))["test2"]); - Assert.AreEqual("three", - (((Dictionary)((Dictionary)document["additionalinfo"])["director"]))["test3"]); + Assert.That(document["field 1"], Is.EqualTo("check1")); + Assert.That(document["field 2"], Is.EqualTo("check2")); + Assert.That(document["field 3"], Is.EqualTo("check3")); + Assert.That((((Dictionary)((Dictionary)document["additionalinfo"])["director"]))["test1"], Is.EqualTo("one")); + Assert.That((((Dictionary)((Dictionary)document["additionalinfo"])["director"]))["test2"], Is.EqualTo("two")); + Assert.That((((Dictionary)((Dictionary)document["additionalinfo"])["director"]))["test3"], Is.EqualTo("three")); collection = CreateCollection("test"); var data2 = new DbDoc(@"{ ""_id"": -1, ""pages"": 20, @@ -865,13 +853,13 @@ public void ModifyPatchMultipleRecords_S1() ] }"); r = collection.Add(data2).Execute(); - Assert.AreEqual(1, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(1)); document = collection.GetOne("-1"); - Assert.AreEqual("20", document["pages"].ToString()); + Assert.That(document["pages"].ToString(), Is.EqualTo("20")); collection.Modify("_id = :id").Patch("{ \"pages\": \"200\" }"). Bind("id", -1).Execute(); document = collection.GetOne("-1"); - Assert.AreEqual("200", document["pages"]); + Assert.That(document["pages"], Is.EqualTo("200")); data2 = new DbDoc(@"{ ""_id"": 1, ""pages"": 20, ""books"": [ {""_id"" : 10, ""title"" : ""Book 10""}, @@ -884,10 +872,10 @@ public void ModifyPatchMultipleRecords_S1() Bind("id", "1").Execute(); document = collection.GetOne("1"); object[] books = document["books"] as object[]; - Assert.AreEqual(1, books.Length); + Assert.That(books.Length, Is.EqualTo(1)); Dictionary book1 = books[0] as Dictionary; - Assert.AreEqual("11", book1["_id"]); - Assert.AreEqual("Ganges", book1["title"]); + Assert.That(book1["_id"], Is.EqualTo("11")); + Assert.That(book1["title"], Is.EqualTo("Ganges")); var t1 = "{\"_id\": \"1\", \"name\": \"Alice\", \"address\": [{\"zip\": \"12345\", \"city\": \"Los Angeles\", \"street\": \"32 Main str\"}]}"; var t2 = @@ -898,65 +886,65 @@ public void ModifyPatchMultipleRecords_S1() collection = CreateCollection("test"); r = collection.Add(t1).Execute(); - Assert.AreEqual(1, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(1)); r = collection.Add(t2).Execute(); //update the name and zip code of match collection.Modify("_id = :id").Patch("{\"name\": \"Joe\", \"address\": [{\"zip\":\"91234\"}]}").Bind("id", "1").Execute(); document = collection.GetOne("1"); - Assert.AreEqual("Joe", document["name"]); + Assert.That(document["name"], Is.EqualTo("Joe")); object[] address = document["address"] as object[]; - Assert.AreEqual(1, address.Length); + Assert.That(address.Length, Is.EqualTo(1)); Dictionary address1 = address[0] as Dictionary; - Assert.AreEqual("91234", address1["zip"]); + Assert.That(address1["zip"], Is.EqualTo("91234")); collection = CreateCollection("test"); r = collection.Add(t1).Execute(); - Assert.AreEqual(1, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(1)); r = collection.Add(t2).Execute(); - Assert.AreEqual(1, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(1)); r = collection.Add(t3).Execute(); - Assert.AreEqual(1, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(1)); collection.Modify("_id = :id").Patch("{\"name\": \"Joe\", \"address\": [{\"zip1\":\"91234\"},{\"zip2\":\"10000\"}]}"). Bind("id", "3").Execute(); document = collection.GetOne("3"); - Assert.AreEqual("Joe", document["name"]); + Assert.That(document["name"], Is.EqualTo("Joe")); address = document["address"] as object[]; - Assert.AreEqual(2, address.Length); + Assert.That(address.Length, Is.EqualTo(2)); address1 = address[0] as Dictionary; - Assert.AreEqual("91234", address1["zip1"]); + Assert.That(address1["zip1"], Is.EqualTo("91234")); address1 = address[1] as Dictionary; - Assert.AreEqual("10000", address1["zip2"]); + Assert.That(address1["zip2"], Is.EqualTo("10000")); collection = CreateCollection("test"); var t = "{\"_id\": \"id1004\", \"age\": 1, \"misc\": 1.2, \"name\": { \"last\": \"ABCDEF3\", \"first\": \"ABCDEF1\", \"middle\": { \"middle1\": \"ABCDEF21\", \"middle2\": \"ABCDEF22\"}}}"; r = collection.Add(t).Execute(); collection.Modify("_id = :id").Patch("{\"name\":{\"middle\":{\"middle1\": {\"middle11\" : \"ABCDEF211\", \"middle12\" : \"ABCDEF212\", \"middle13\" : \"ABCDEF213\"}}}}").Bind("id", "id1004").Execute(); document = collection.GetOne("id1004"); - Assert.AreEqual("ABCDEF211", document["name.middle.middle1.middle11"]); - Assert.AreEqual("ABCDEF212", document["name.middle.middle1.middle12"]); - Assert.AreEqual("ABCDEF213", document["name.middle.middle1.middle13"]); + Assert.That(document["name.middle.middle1.middle11"], Is.EqualTo("ABCDEF211")); + Assert.That(document["name.middle.middle1.middle12"], Is.EqualTo("ABCDEF212")); + Assert.That(document["name.middle.middle1.middle13"], Is.EqualTo("ABCDEF213")); t1 = "{\"_id\": \"1001\", \"ARR\":[1,2,3], \"ARR1\":[\"name1\",\"name2\", \"name3\"]}"; t2 = "{\"_id\": \"1002\", \"ARR\":[1,1,2], \"ARR1\":[\"name1\",\"name2\", \"name3\"]}"; t3 = "{\"_id\": \"1003\", \"ARR\":[1,4,5], \"ARR1\":[\"name1\",\"name2\", \"name3\"]}"; collection = CreateCollection("test"); r = collection.Add(t1).Execute(); - Assert.AreEqual(1, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(1)); r = collection.Add(t2).Execute(); - Assert.AreEqual(1, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(1)); r = collection.Add(t3).Execute(); - Assert.AreEqual(1, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(1)); collection.Modify("_id = :_id"). Patch("{\"ARR\":[6,8,3],\"ARR1\":[\"changed name1\",\"changed name2\", \"changed name3\"]}"). Bind("_id", "1001").Execute(); document = collection.GetOne("1001"); object[] arr = document["ARR1"] as object[]; - Assert.AreEqual(3, arr.Length); + Assert.That(arr.Length, Is.EqualTo(3)); int j = 1; for (int i = 0; i < arr.Length; i++) { - Assert.AreEqual("changed name" + j, arr[i]); + Assert.That(arr[i], Is.EqualTo("changed name" + j)); j++; } @@ -970,34 +958,34 @@ public void ModifyPatchMultipleRecords_S1() collection = CreateCollection("test"); r = collection.Add(t1).Execute(); - Assert.AreEqual(1, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(1)); r = collection.Add(t2).Execute(); - Assert.AreEqual(1, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(1)); r = collection.Add(t3).Execute(); - Assert.AreEqual(1, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(1)); collection.Modify("_id = :id"). Patch("{\"address\": null, \"zip\": $.address.zip, \"street\": $.address.street, \"city\": upper($.address.city)}").Bind("id", "1"). Execute(); document = collection.GetOne("1"); - Assert.AreEqual("Alice", document["name"]); - Assert.AreEqual("32 Main str", document["street"]); - Assert.AreEqual("LOS ANGELES", document["city"]); - Assert.AreEqual("12345", document["zip"]); + Assert.That(document["name"], Is.EqualTo("Alice")); + Assert.That(document["street"], Is.EqualTo("32 Main str")); + Assert.That(document["city"], Is.EqualTo("LOS ANGELES")); + Assert.That(document["zip"], Is.EqualTo("12345")); t1 = "{\"_id\": \"1\", \"name\": \"Alice\", \"address\": {\"test\":{\"zip\": \"12345\", " + "\"city\": \"Los Angeles\", \"street\": \"32 Main str\"}}}"; collection = CreateCollection("test"); r = collection.Add(t1).Execute(); - Assert.AreEqual(1, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(1)); collection.Modify("_id = :id"). Patch("{\"address\":{\"test\": null,\"zip\":$.address.test.zip,\"city\": lower($.address.test.city)}}").Bind("id", "1"). Execute(); document = collection.GetOne("1"); - Assert.AreEqual("Alice", document["name"]); - Assert.AreEqual("los angeles", document["address.city"]); - Assert.AreEqual("12345", document["address.zip"]); + Assert.That(document["name"], Is.EqualTo("Alice")); + Assert.That(document["address.city"], Is.EqualTo("los angeles")); + Assert.That(document["address.zip"], Is.EqualTo("12345")); } @@ -1088,7 +1076,7 @@ public void ModifyInNestedObjects() var document1 = collection.GetOne("1002"); var test = "ARR" + i; object[] arr1 = document1[test] as object[]; - Assert.AreEqual(3, arr1.Length); + Assert.That(arr1.Length, Is.EqualTo(3)); i = 0; j = 0; for (i = 0; i < arr1.Length; i++) @@ -1097,65 +1085,65 @@ public void ModifyInNestedObjects() if (i == 1) { object[] arr2 = arr1[1] as object[]; - Assert.AreEqual(3, arr2.Length); + Assert.That(arr2.Length, Is.EqualTo(3)); for (j = 0; j < arr2.Length; j++) { if (j == 1) { object[] arr3 = arr2[1] as object[]; - Assert.AreEqual(3, arr3.Length); + Assert.That(arr3.Length, Is.EqualTo(3)); for (k = 0; k < arr3.Length; k++) { if (k == 1) { object[] arr4 = arr3[1] as object[]; - Assert.AreEqual(3, arr4.Length); + Assert.That(arr4.Length, Is.EqualTo(3)); for (l = 0; l < arr4.Length; l++) { if (l == 1) { object[] arr5 = arr4[1] as object[]; - Assert.AreEqual(3, arr5.Length); + Assert.That(arr5.Length, Is.EqualTo(3)); for (m = 0; m < arr5.Length; m++) { if (m == 1) { object[] arr6 = arr5[1] as object[]; - Assert.AreEqual(1, arr6.Length); + Assert.That(arr6.Length, Is.EqualTo(1)); if (arr6.Length == 1) - Assert.AreEqual(4, arr6[0]); + Assert.That(arr6[0], Is.EqualTo(4)); } else - Assert.AreEqual(5, arr5[m]); + Assert.That(arr5[m], Is.EqualTo(5)); if (m == 2) break; } } else - Assert.AreEqual(6, arr4[l]); + Assert.That(arr4[l], Is.EqualTo(6)); if (l == 2) break; } } else - Assert.AreEqual(7, arr3[k]); + Assert.That(arr3[k], Is.EqualTo(7)); if (k == 2) break; } } if (j == 0 || j == 2) - Assert.AreEqual(8, arr2[j]); + Assert.That(arr2[j], Is.EqualTo(8)); if (j == 2) break; } } else - Assert.AreEqual(9, arr1[i]); + Assert.That(arr1[i], Is.EqualTo(9)); if (i == 2) break; } @@ -1180,7 +1168,7 @@ public void ModifyInNestedObjects() { var test = "ARR" + i; object[] arr1 = document[test] as object[]; - Assert.AreEqual(3, arr1.Length); + Assert.That(arr1.Length, Is.EqualTo(3)); i = 0; j = 0; for (i = 0; i < arr1.Length; i++) @@ -1189,65 +1177,65 @@ public void ModifyInNestedObjects() if (i == 1) { object[] arr2 = arr1[1] as object[]; - Assert.AreEqual(3, arr2.Length); + Assert.That(arr2.Length, Is.EqualTo(3)); for (j = 0; j < arr2.Length; j++) { if (j == 1) { object[] arr3 = arr2[1] as object[]; - Assert.AreEqual(3, arr3.Length); + Assert.That(arr3.Length, Is.EqualTo(3)); for (k = 0; k < arr3.Length; k++) { if (k == 1) { object[] arr4 = arr3[1] as object[]; - Assert.AreEqual(3, arr4.Length); + Assert.That(arr4.Length, Is.EqualTo(3)); for (l = 0; l < arr4.Length; l++) { if (l == 1) { object[] arr5 = arr4[1] as object[]; - Assert.AreEqual(3, arr5.Length); + Assert.That(arr5.Length, Is.EqualTo(3)); for (m = 0; m < arr5.Length; m++) { if (m == 1) { object[] arr6 = arr5[1] as object[]; - Assert.AreEqual(1, arr6.Length); + Assert.That(arr6.Length, Is.EqualTo(1)); if (arr6.Length == 1) - Assert.AreEqual(4, arr6[0]); + Assert.That(arr6[0], Is.EqualTo(4)); } else - Assert.AreEqual(5, arr5[m]); + Assert.That(arr5[m], Is.EqualTo(5)); if (m == 2) break; } } else - Assert.AreEqual(6, arr4[l]); + Assert.That(arr4[l], Is.EqualTo(6)); if (l == 2) break; } } else - Assert.AreEqual(7, arr3[k]); + Assert.That(arr3[k], Is.EqualTo(7)); if (k == 2) break; } } if (j == 0 || j == 2) - Assert.AreEqual(8, arr2[j]); + Assert.That(arr2[j], Is.EqualTo(8)); if (j == 2) break; } } else - Assert.AreEqual(9, arr1[i]); + Assert.That(arr1[i], Is.EqualTo(9)); if (i == 2) break; } @@ -1259,71 +1247,71 @@ public void ModifyInNestedObjects() listDocs.Add(new DbDoc(documentAsJsonString2)); collection = CreateCollection("test"); Result r = collection.Add(listDocs.ToArray()).Execute(); - Assert.AreEqual(2, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(2)); document = collection.GetOne("a6f4b93e1a264a108393524f29546a8c"); - Assert.AreEqual("AFRICAN EGG", document["title"]); + Assert.That(document["title"], Is.EqualTo("AFRICAN EGG")); // Modify Using ID and Patch Title collection.Modify("_id = :id").Patch("{ \"title\": \"The African Egg\" }"). Bind("id", "a6f4b93e1a264a108393524f29546a8c").Execute(); document = collection.GetOne("a6f4b93e1a264a108393524f29546a8c"); - Assert.AreEqual("The African Egg", document["title"]); + Assert.That(document["title"], Is.EqualTo("The African Egg")); - Assert.AreEqual(57, ((Dictionary)((Dictionary)document["additionalinfo"])["director"])["age"]); + Assert.That(((Dictionary)((Dictionary)document["additionalinfo"])["director"])["age"], Is.EqualTo(57)); // Modify Using additionalinfo.director.name = :director and Patch Age 67 collection.Modify("additionalinfo.director.name = :director"). Patch("{ \"additionalinfo\": { \"director\": { \"age\": 67 } } }"). Bind("director", "Sharice Legaspi").Execute(); document = collection.GetOne("a6f4b93e1a264a108393524f29546a8c"); - Assert.AreEqual(67, ((Dictionary)((Dictionary)document["additionalinfo"])["director"])["age"]); + Assert.That(((Dictionary)((Dictionary)document["additionalinfo"])["director"])["age"], Is.EqualTo(67)); // Modify Using _id=:id and Patch Age 77 collection.Modify("_id = :id"). Patch("{ \"additionalinfo\": { \"director\": { \"age\": 77 } } }"). Bind("id", "a6f4b93e1a264a108393524f29546a8c").Execute(); document = collection.GetOne("a6f4b93e1a264a108393524f29546a8c"); - Assert.AreEqual(77, ((Dictionary)((Dictionary)document["additionalinfo"])["director"])["age"]); + Assert.That(((Dictionary)((Dictionary)document["additionalinfo"])["director"])["age"], Is.EqualTo(77)); // Modify Using _id=:id and Patch contains movie title collection.Modify("_id = :id"). Patch("{ \"title\": { \"movie\": \"The African Egg\"} }"). Bind("id", "a6f4b93e1a264a108393524f29546a8c").Execute(); document = collection.GetOne("a6f4b93e1a264a108393524f29546a8c"); - Assert.AreEqual("The African Egg", ((Dictionary)document["title"])["movie"]); + Assert.That(((Dictionary)document["title"])["movie"], Is.EqualTo("The African Egg")); // Modify Using _id=:id and Patch additionalinfo Birthplace director country countryActual collection.Modify("_id = :id"). Patch("{ \"additionalinfo\": { \"director\": { \"birthplace\": { \"country\": { \"countryActual\": \"India\" } } } } }"). Bind("id", "123456789asdferdfghhghjh12334").Execute(); document = collection.GetOne("123456789asdferdfghhghjh12334"); - Assert.AreEqual("India", document["additionalinfo.director.birthplace.country.countryActual"]); + Assert.That(document["additionalinfo.director.birthplace.country.countryActual"], Is.EqualTo("India")); // Modify Using _id=:id and Patch additionalinfo Birthplace director country countryActual" collection.Modify("_id = :id"). Patch("{ \"additionalinfo\": { \"director\": { \"birthplace\": { \"country\": { \"city\": \"NewDelhi\",\"countryActual\": \"India\" } } } } }"). Bind("id", "123456789asdferdfghhghjh12334").Execute(); document = collection.GetOne("123456789asdferdfghhghjh12334"); - Assert.AreEqual("India", document["additionalinfo.director.birthplace.country.countryActual"]); - Assert.AreEqual("NewDelhi", document["additionalinfo.director.birthplace.country.city"]); + Assert.That(document["additionalinfo.director.birthplace.country.countryActual"], Is.EqualTo("India")); + Assert.That(document["additionalinfo.director.birthplace.country.city"], Is.EqualTo("NewDelhi")); // Modify Using _id=:id and Patch additionalinfo Birthplace director country to replace an array collection.Modify("_id = :id"). Patch("{ \"additionalinfo\": { \"director\": { \"birthplace\": { \"country\": \"India\" } } } }"). Bind("id", "123456789asdferdfghhghjh12334").Execute(); document = collection.GetOne("123456789asdferdfghhghjh12334"); - Assert.AreEqual("India", document["additionalinfo.director.birthplace.country"]); + Assert.That(document["additionalinfo.director.birthplace.country"], Is.EqualTo("India")); // Modify Using _id=:id and Patch additionalinfo writers to replace an array collection.Modify("_id = :id"). Patch("{ \"additionalinfo\": { \"writers\": \"Jeoff Archer\" } }"). Bind("id", "123456789asdferdfghhghjh12334").Execute(); document = collection.GetOne("123456789asdferdfghhghjh12334"); - Assert.AreEqual("Jeoff Archer", document["additionalinfo.writers"]); + Assert.That(document["additionalinfo.writers"], Is.EqualTo("Jeoff Archer")); //Reset the docs collection = CreateCollection("test"); r = collection.Add(listDocs.ToArray()).Execute(); - Assert.AreEqual(2, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(2)); // Modify Using _id=:id and Patch contains blank collection.Modify("_id = :id").Patch("{ \"additionalinfo\": \"\" }"). @@ -1342,7 +1330,7 @@ public void ModifyPatchAtDepthMultipleArrays_S1() listDocs.Add(documentsAsDbDocs[0]); listDocs.Add(new DbDoc(documentAsJsonString2)); Result r = collection.Add(listDocs.ToArray()).Execute(); - Assert.AreEqual(2, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(2)); object[] path = null; DbDoc document = collection.GetOne("a6f4b93e1a264a108393524f29546a8c"); Assert.Throws(() => path = document["translations"] as object[]); @@ -1352,7 +1340,7 @@ public void ModifyPatchAtDepthMultipleArrays_S1() Bind("id", "a6f4b93e1a264a108393524f29546a8c").Execute(); document = collection.GetOne("a6f4b93e1a264a108393524f29546a8c"); path = document["translations"] as object[]; - Assert.AreEqual("Spanish", path[0], + Assert.That(path[0], Is.EqualTo("Spanish"), "Verify transalations field is present or not"); collection.Modify("_id = :id"). Patch("{ \"translations\": null }"). @@ -1365,7 +1353,7 @@ public void ModifyPatchAtDepthMultipleArrays_S1() Patch("{ \"additionalinfo\": { \"director\": { \"mobile\": \"9876543210\" } } }"). Bind("age", 57).Execute(); document = collection.GetOne("a6f4b93e1a264a108393524f29546a8c"); - Assert.AreEqual("9876543210", document["additionalinfo.director.mobile"], + Assert.That(document["additionalinfo.director.mobile"], Is.EqualTo("9876543210"), "Verify mobile field is present or not"); collection.Modify("additionalinfo.director.name = :director"). Patch("{ \"additionalinfo\": { \"director\": { \"mobile\": null } } }"). @@ -1378,7 +1366,7 @@ public void ModifyPatchAtDepthMultipleArrays_S1() Patch("{ \"additionalinfo\": { \"musicby\": \"The Sakila\" } }"). Bind("id", "a6f4b93e1a264a108393524f29546a8c").Execute(); document = collection.GetOne("a6f4b93e1a264a108393524f29546a8c"); - Assert.AreEqual("The Sakila", document["additionalinfo.musicby"], + Assert.That(document["additionalinfo.musicby"], Is.EqualTo("The Sakila"), "Verify musicby field is present or not"); collection.Modify("_id = :id").Patch("{ \"additionalinfo\": { \"musicby\": null } }"). Bind("id", "a6f4b93e1a264a108393524f29546a8c").Execute(); @@ -1390,7 +1378,7 @@ public void ModifyPatchAtDepthMultipleArrays_S1() Patch("{\"additionalinfo\": { \"director\": { \"awards\": { \"genre\": \"Action\" } } } }"). Bind("id", "a6f4b93e1a264a108393524f29546a8c").Execute(); document = collection.GetOne("a6f4b93e1a264a108393524f29546a8c"); - Assert.AreEqual("Action", document["additionalinfo.director.awards.genre"], + Assert.That(document["additionalinfo.director.awards.genre"], Is.EqualTo("Action"), "Verify musicby field is present or not"); collection.Modify("_id = :id"). Patch("{\"additionalinfo\": { \"director\": { \"awards\": { \"genre\": null } } } }"). @@ -1408,7 +1396,7 @@ public void ModifyPatchAtDepthMultipleArrays_S2() Collection collection = CreateCollection("test"); Result r = collection.Add("{ \"_id\": \"123\", \"email\": \"alice@ora.com\", " + "\"startDate\": \"4/1/2017\" }").Execute(); - Assert.AreEqual(1, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(1)); var patch1 = new { email = new MySqlExpression("UPPER($.email)") @@ -1460,16 +1448,16 @@ public void ModifyPatchAtDepthMultipleArrays_S2() collection.Modify("true").Patch(patch1).Execute(); document = collection.GetOne("123"); - Assert.AreEqual("ALICE@ORA.COM", document["email"]); + Assert.That(document["email"], Is.EqualTo("ALICE@ORA.COM")); collection.Modify("true").Patch(patch2).Execute(); document = collection.GetOne("123"); - Assert.AreEqual("alice@ora.com", document["email"]); + Assert.That(document["email"], Is.EqualTo("alice@ora.com")); collection.Modify("true").Patch(patch3).Execute(); document = collection.GetOne("123"); - Assert.AreEqual("NoSQL", document["email"]); + Assert.That(document["email"], Is.EqualTo("NoSQL")); collection.Modify("true").Patch(patch4).Execute(); document = collection.GetOne("123"); - Assert.AreEqual("base64:type15:TXlTUUw=", document["email"]); + Assert.That(document["email"], Is.EqualTo("base64:type15:TXlTUUw=")); collection.Modify("true").Patch(patch5).Execute(); document = collection.GetOne("123"); DbDoc test = null; @@ -1480,84 +1468,84 @@ public void ModifyPatchAtDepthMultipleArrays_S2() "\"startDate\": \"4/1/2017\" }").Execute(); collection.Modify("true").Patch(patch6).Execute(); document = collection.GetOne("123"); - Assert.AreEqual("foo", document["email"]); + Assert.That(document["email"], Is.EqualTo("foo")); collection.Modify("true").Patch(patch7).Execute(); document = collection.GetOne("123"); - Assert.AreEqual("MySQLMySQLMySQL", document["email"]); + Assert.That(document["email"], Is.EqualTo("MySQLMySQLMySQL")); collection.Modify("true").Patch(patch8).Execute(); document = collection.GetOne("123"); - Assert.AreEqual("cba", document["email"]); + Assert.That(document["email"], Is.EqualTo("cba")); collection.Modify("true").Patch(patch9).Execute(); document = collection.GetOne("123"); - Assert.AreEqual("rbar", document["email"]); + Assert.That(document["email"], Is.EqualTo("rbar")); collection.Modify("true").Patch(patch10).Execute(); document = collection.GetOne("123"); - Assert.AreEqual("WwWwWw.mysql.com", document["email"]); + Assert.That(document["email"], Is.EqualTo("WwWwWw.mysql.com")); collection.Modify("true").Patch(patch11).Execute(); document = collection.GetOne("123"); - Assert.AreEqual("616263", document["email"]); + Assert.That(document["email"], Is.EqualTo("616263")); collection.Modify("true").Patch(patch12).Execute(); document = collection.GetOne("123"); - Assert.AreEqual("1100", document["email"]); + Assert.That(document["email"], Is.EqualTo("1100")); string t1 = "{\"_id\": \"1\", \"name\": \"Alice\" }"; collection = CreateCollection("test"); r = collection.Add(t1).Execute(); - Assert.AreEqual(1, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(1)); collection.Modify("_id = :id").Patch("{ \"dateAndTimeValue\": YEAR('2000-01-01') }").Bind("id", "1").Execute(); document = collection.GetOne("1"); - Assert.AreEqual(2000, document["dateAndTimeValue"]); + Assert.That(document["dateAndTimeValue"], Is.EqualTo(2000)); collection.Modify("_id = :id").Patch("{ \"dateAndTimeValue\": MONTH('2008-02-03') }").Bind("id", "1").Execute(); document = collection.GetOne("1"); - Assert.AreEqual(2, document["dateAndTimeValue"]); + Assert.That(document["dateAndTimeValue"], Is.EqualTo(2)); collection.Modify("_id = :id").Patch("{ \"dateAndTimeValue\": WEEK('2008-02-20') }").Bind("id", "1").Execute(); document = collection.GetOne("1"); - Assert.AreEqual(7, document["dateAndTimeValue"]); + Assert.That(document["dateAndTimeValue"], Is.EqualTo(7)); collection.Modify("_id = :id").Patch("{ \"dateAndTimeValue\": DAY('2008-02-20') }").Bind("id", "1").Execute(); document = collection.GetOne("1"); - Assert.AreEqual(20, document["dateAndTimeValue"]); + Assert.That(document["dateAndTimeValue"], Is.EqualTo(20)); collection.Modify("_id = :id").Patch("{ \"dateAndTimeValue\": HOUR('10:05:03') }").Bind("id", "1").Execute(); document = collection.GetOne("1"); - Assert.AreEqual(10, document["dateAndTimeValue"]); + Assert.That(document["dateAndTimeValue"], Is.EqualTo(10)); collection.Modify("_id = :id").Patch("{ \"dateAndTimeValue\": MINUTE('2008-02-03 10:05:03') }").Bind("id", "1").Execute(); document = collection.GetOne("1"); - Assert.AreEqual(5, document["dateAndTimeValue"]); + Assert.That(document["dateAndTimeValue"], Is.EqualTo(5)); collection.Modify("_id = :id").Patch("{ \"dateAndTimeValue\": SECOND('10:05:03') }").Bind("id", "1").Execute(); document = collection.GetOne("1"); - Assert.AreEqual(3, document["dateAndTimeValue"]); + Assert.That(document["dateAndTimeValue"], Is.EqualTo(3)); collection.Modify("_id = :id").Patch("{ \"dateAndTimeValue\": MICROSECOND('12:00:00.123456') }").Bind("id", "1").Execute(); document = collection.GetOne("1"); - Assert.AreEqual(123456, document["dateAndTimeValue"]); + Assert.That(document["dateAndTimeValue"], Is.EqualTo(123456)); collection.Modify("_id = :id").Patch("{ \"dateAndTimeValue\": QUARTER('2008-04-01') }").Bind("id", "1").Execute(); document = collection.GetOne("1"); - Assert.AreEqual(2, document["dateAndTimeValue"]); + Assert.That(document["dateAndTimeValue"], Is.EqualTo(2)); collection.Modify("_id = :id").Patch("{ \"dateAndTimeValue\": TIME('2003-12-31 01:02:03') }").Bind("id", "1").Execute(); document = collection.GetOne("1"); - Assert.AreEqual("01:02:03.000000", document["dateAndTimeValue"]); + Assert.That(document["dateAndTimeValue"], Is.EqualTo("01:02:03.000000")); collection.Modify("_id = :id").Patch("{ \"dateAndTimeValue\": DATE('2003-12-31 01:02:03') }").Bind("id", "1").Execute(); document = collection.GetOne("1"); - Assert.AreEqual("2003-12-31", document["dateAndTimeValue"]); + Assert.That(document["dateAndTimeValue"], Is.EqualTo("2003-12-31")); List listDocs = new List(); listDocs.Add(documentsAsDbDocs[0]); listDocs.Add(new DbDoc(documentAsJsonString2)); r = collection.Add(listDocs.ToArray()).Execute(); - Assert.AreEqual(2, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(2)); document = collection.GetOne("a6f4b93e1a264a108393524f29546a8c"); object[] actors = document["actors"] as object[]; - Assert.AreEqual(3, actors.Length); + Assert.That(actors.Length, Is.EqualTo(3)); Dictionary actor0 = actors[0] as Dictionary; Assert.Throws(() => test = (DbDoc)actor0["age"]); @@ -1567,52 +1555,52 @@ public void ModifyPatchAtDepthMultipleArrays_S2() "\"DOB\": \"19 Mar 1982\", \"citizen\": \"USA\"}}}"; collection = CreateCollection("test"); r = collection.Add(t1).Execute(); - Assert.AreEqual(1, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(1)); collection.Modify("_id = :id"). Patch("{\"details\":{\"personal\": null,\"mobile\":$.details.personal.mobile,\"yearofbirth\":" + "CAST(SUBSTRING_INDEX($.details.personal.DOB, ' ', -1) AS DECIMAL)}}").Bind("id", "1"). Execute(); document = collection.GetOne("1"); - Assert.AreEqual("Alice", document["name"]); - Assert.AreEqual("9876543210", document["details.mobile"]); - Assert.AreEqual("1982", document["details.yearofbirth"].ToString()); + Assert.That(document["name"], Is.EqualTo("Alice")); + Assert.That(document["details.mobile"], Is.EqualTo("9876543210")); + Assert.That(document["details.yearofbirth"].ToString(), Is.EqualTo("1982")); collection = CreateCollection("test"); r = collection.Add(t1).Execute(); - Assert.AreEqual(1, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(1)); collection.Modify("_id = :id"). Patch("{\"details\":{\"personal\": null,\"mobile\":$.details.personal.mobile,\"currentyear\":" + "CURDATE()}}").Bind("id", "1"). Execute(); document = collection.GetOne("1"); - Assert.AreEqual("Alice", document["name"]); - Assert.AreEqual("9876543210", document["details.mobile"]); - Assert.AreEqual(document["details.currentyear"].ToString(), document["details.currentyear"].ToString(), "Matching the current date"); + Assert.That(document["name"], Is.EqualTo("Alice")); + Assert.That(document["details.mobile"], Is.EqualTo("9876543210")); + Assert.That(document["details.currentyear"].ToString(), Is.EqualTo(document["details.currentyear"].ToString()), "Matching the current date"); collection = CreateCollection("test"); r = collection.Add(t1).Execute(); - Assert.AreEqual(1, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(1)); collection.Modify("_id = :id"). Patch("{\"details\":{\"personal\": null,\"mobile\":$.details.personal.mobile,\"currentyear\":" + "Year(CURDATE())}}").Bind("id", "1"). Execute(); document = collection.GetOne("1"); - Assert.AreEqual("Alice", document["name"]); - Assert.AreEqual("9876543210", document["details.mobile"]); - Assert.AreEqual(document["details.currentyear"].ToString(), document["details.currentyear"].ToString()); + Assert.That(document["name"], Is.EqualTo("Alice")); + Assert.That(document["details.mobile"], Is.EqualTo("9876543210")); + Assert.That(document["details.currentyear"].ToString(), Is.EqualTo(document["details.currentyear"].ToString())); collection = CreateCollection("test"); r = collection.Add(t1).Execute(); - Assert.AreEqual(1, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(1)); collection.Modify("_id = :id"). Patch("{\"details\":{\"personal\": null,\"mobile\":$.details.personal.mobile,\"currentage\":" + "Year(CURDATE()) - CAST(SUBSTRING_INDEX($.details.personal.DOB, ' ', -1) AS DECIMAL)}}").Bind("id", "1"). Execute(); document = collection.GetOne("1"); - Assert.AreEqual("Alice", document["name"]); - Assert.AreEqual("9876543210", document["details.mobile"]); - Assert.AreEqual(document["details.currentage"].ToString(), document["details.currentage"].ToString()); + Assert.That(document["name"], Is.EqualTo("Alice")); + Assert.That(document["details.mobile"], Is.EqualTo("9876543210")); + Assert.That(document["details.currentage"].ToString(), Is.EqualTo(document["details.currentage"].ToString())); collection = CreateCollection("test"); r = collection.Add(listDocs.ToArray()).Execute(); - Assert.AreEqual(2, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(2)); document = collection.GetOne("a6f4b93e1a264a108393524f29546a8c"); // Get root array. Assert.Throws(() => test = (DbDoc)document["audio"]); @@ -1620,41 +1608,41 @@ public void ModifyPatchAtDepthMultipleArrays_S2() collection.Modify("true"). Patch("{ \"audio\": CONCAT($.language, ', no subtitles') }").Execute(); document = collection.GetOne("a6f4b93e1a264a108393524f29546a8c"); - Assert.AreEqual("English, no subtitles", document["audio"]); + Assert.That(document["audio"], Is.EqualTo("English, no subtitles")); collection = CreateCollection("test"); r = collection.Add(listDocs.ToArray()).Execute(); - Assert.AreEqual(2, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(2)); document = collection.GetOne("a6f4b93e1a264a108393524f29546a8c"); Assert.Throws(() => test = (DbDoc)document["audio"]); collection.Modify("true").Patch("{ \"audio\": CONCAT(UPPER($.language), ', No Subtitles') }").Execute(); document = collection.GetOne("a6f4b93e1a264a108393524f29546a8c"); - Assert.AreEqual("ENGLISH, No Subtitles", document["audio"]); + Assert.That(document["audio"], Is.EqualTo("ENGLISH, No Subtitles")); collection = CreateCollection("test"); r = collection.Add(listDocs.ToArray()).Execute(); - Assert.AreEqual(2, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(2)); collection.Modify("_id = :id").Patch("{ \"_id\": replace(UUID(), '-', '') }"). Bind("id", "a6f4b93e1a264a108393524f29546a8c").Execute(); document = collection.GetOne("a6f4b93e1a264a108393524f29546a8c"); - Assert.AreEqual("a6f4b93e1a264a108393524f29546a8c", document.Id); + Assert.That(document.Id, Is.EqualTo("a6f4b93e1a264a108393524f29546a8c")); collection = CreateCollection("test"); r = collection.Add(listDocs.ToArray()).Execute(); - Assert.AreEqual(2, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(2)); Assert.Throws(() => test = (DbDoc)document["additionalinfo._id"]); document = collection.GetOne("a6f4b93e1a264a108393524f29546a8c"); collection.Modify("_id = :id").Patch("{ \"additionalinfo\": { \"_id\": replace(UUID(), '-', '') } }"). Bind("id", "a6f4b93e1a264a108393524f29546a8c").Execute(); document = collection.GetOne("a6f4b93e1a264a108393524f29546a8c"); - Assert.True(((Dictionary)document["additionalinfo"])["_id"] != null); + Assert.That(((Dictionary)document["additionalinfo"])["_id"] != null); collection = CreateCollection("test"); r = collection.Add(listDocs.ToArray()).Execute(); - Assert.AreEqual(2, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(2)); document = collection.GetOne("a6f4b93e1a264a108393524f29546a8c"); Assert.Throws(() => test = (DbDoc)document["additionalinfo.releasedate"]); @@ -1667,15 +1655,15 @@ public void ModifyPatchAtDepthMultipleArrays_S2() } catch (MySqlException ex) { - Assert.AreEqual("Invalid data for update operation on document collection table", ex.Message); + Assert.That(ex.Message, Is.EqualTo("Invalid data for update operation on document collection table")); } collection = CreateCollection("test"); r = collection.Add(listDocs.ToArray()).Execute(); - Assert.AreEqual(2, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(2)); document = collection.GetOne("a6f4b93e1a264a108393524f29546a8c"); - Assert.AreEqual("AFRICAN EGG", document["title"]); + Assert.That(document["title"], Is.EqualTo("AFRICAN EGG")); collection.Modify("_id = :id").Patch("{ \"title\": concat('my ', NULL, ' title') }"). Bind("id", "a6f4b93e1a264a108393524f29546a8c").Execute(); document = collection.GetOne("a6f4b93e1a264a108393524f29546a8c"); @@ -1683,7 +1671,7 @@ public void ModifyPatchAtDepthMultipleArrays_S2() collection = CreateCollection("test"); r = collection.Add(listDocs.ToArray()).Execute(); - Assert.AreEqual(2, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(2)); document = collection.GetOne("a6f4b93e1a264a108393524f29546a8c"); Assert.Throws(() => test = (DbDoc)document["docfield"]); @@ -1693,19 +1681,19 @@ public void ModifyPatchAtDepthMultipleArrays_S2() document = collection.GetOne("a6f4b93e1a264a108393524f29546a8c"); object docField = document["docfield"] as object; - Assert.True(docField != null); + Assert.That(docField != null); collection = CreateCollection("test"); r = collection.Add(listDocs.ToArray()).Execute(); - Assert.AreEqual(2, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(2)); document = collection.GetOne("a6f4b93e1a264a108393524f29546a8c"); - Assert.AreEqual("Science fiction", document["genre"]); + Assert.That(document["genre"], Is.EqualTo("Science fiction")); collection.Modify("_id = :id").Patch("{ \"genre\": JSON_OBJECT('name', 'Science Fiction') }"). Bind("id", "a6f4b93e1a264a108393524f29546a8c").Execute(); document = collection.GetOne("a6f4b93e1a264a108393524f29546a8c"); - Assert.AreEqual("Science Fiction", ((Dictionary)document["genre"])["name"]); + Assert.That(((Dictionary)document["genre"])["name"], Is.EqualTo("Science Fiction")); } @@ -1722,7 +1710,7 @@ public void ModifyPatchInvalidString() new {_id = 4, title = "Book 4", pages = 50,age = 12} }; Result r = collection.Add(docs).Execute(); - Assert.AreEqual(4, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(4)); var document = collection.GetOne("1"); var jsonParams = "invalidJsonString"; Assert.Throws(() => ExecuteModifyStatement(collection.Modify("age = :age").Patch(jsonParams).Bind("age", "12"))); @@ -1743,14 +1731,14 @@ public void ModifyPatchInvalidString() r = collection.Add(documentsAsJsonStrings).Execute(); - Assert.AreEqual(1, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(1)); collection.Modify("true").Patch("{ \"_id\": NULL }").Execute(); - Assert.AreEqual("1", collection.Find().Execute().FetchOne().Id.ToString()); + Assert.That(collection.Find().Execute().FetchOne().Id.ToString(), Is.EqualTo("1")); collection = CreateCollection("test"); r = collection.Add(documentsAsJsonStrings).Execute(); - Assert.AreEqual(1, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(1)); collection.Modify("true").Patch("{ \"nullfield\": NULL }").Execute(); DbDoc test = null; @@ -1759,18 +1747,18 @@ public void ModifyPatchInvalidString() collection.Modify("true").Patch("{ \"nullfield\": [NULL, NULL] }").Execute(); document = collection.Find().Execute().FetchOne(); var nullArray = (object[])document["nullfield"]; - Assert.AreEqual(null, nullArray[0]); - Assert.AreEqual(null, nullArray[1]); + Assert.That(nullArray[0], Is.EqualTo(null)); + Assert.That(nullArray[1], Is.EqualTo(null)); collection.Modify("true").Patch("{ \"nullfield\": { \"nested\": NULL } }").Execute(); document = collection.Find().Execute().FetchOne(); - Assert.AreEqual(true, ((Dictionary)document["nullfield"]).Count == 0); + Assert.That(((Dictionary)document["nullfield"]).Count == 0, Is.EqualTo(true)); collection.Modify("true").Patch("{ \"nullfield\": { \"nested\": [NULL, NULL] } }").Execute(); document = collection.Find().Execute().FetchOne(); var nestedNullArray = (object[])((Dictionary)document["nullfield"])["nested"]; - Assert.AreEqual(null, nestedNullArray[0]); - Assert.AreEqual(null, nestedNullArray[1]); + Assert.That(nestedNullArray[0], Is.EqualTo(null)); + Assert.That(nestedNullArray[1], Is.EqualTo(null)); collection.Modify("true").Patch("{ \"additionalinfo\": { \"nullfield\": NULL } }").Execute(); Dictionary test2 = null; @@ -1779,20 +1767,20 @@ public void ModifyPatchInvalidString() collection.Modify("true").Patch("{ \"additionalinfo\": { \"nullfield\": [NULL, NULL] } }").Execute(); document = collection.GetOne("a6f4b93e1a264a108393524f29546a8c"); nestedNullArray = (object[])((Dictionary)document["additionalinfo"])["nullfield"]; - Assert.AreEqual(null, nestedNullArray[0]); - Assert.AreEqual(null, nestedNullArray[1]); + Assert.That(nestedNullArray[0], Is.EqualTo(null)); + Assert.That(nestedNullArray[1], Is.EqualTo(null)); collection.Modify("true").Patch("{ \"additionalinfo\": { \"nullfield\": { \"nested\": [NULL, NULL] } } }").Execute(); document = collection.GetOne("a6f4b93e1a264a108393524f29546a8c"); nestedNullArray = (object[])((((Dictionary)((Dictionary)document["additionalinfo"])["nullfield"]))["nested"]); - Assert.AreEqual(null, nestedNullArray[0]); - Assert.AreEqual(null, nestedNullArray[1]); + Assert.That(nestedNullArray[0], Is.EqualTo(null)); + Assert.That(nestedNullArray[1], Is.EqualTo(null)); collection.Modify("true").Patch("{ \"additionalinfo\": { \"nullfield\": { \"nested\": JSON_OBJECT('field', null) } } }").Execute(); document = collection.GetOne("a6f4b93e1a264a108393524f29546a8c"); var nestedObject = (Dictionary)((Dictionary)((Dictionary)document["additionalinfo.nullfield.nested"])); - Assert.AreEqual(0, nestedObject.Count); + Assert.That(nestedObject.Count, Is.EqualTo(0)); } #endregion WL14389 diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/PreparedStatementsTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/PreparedStatementsTests.cs index e2af9b591..daf2f5f30 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/PreparedStatementsTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/PreparedStatementsTests.cs @@ -66,7 +66,7 @@ private void InitCollection() { Collection coll = CreateCollection(_collectionName); Result r = ExecuteAddStatement(coll.Add(_docs)); - Assert.AreEqual(4, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(4)); } public void InitTable() @@ -101,11 +101,11 @@ private void ValidatePreparedStatements(int count, ulong executions, string sqlT $"WHERE {condition}"; var preparedStatements = ExecuteSQL(sql).FetchAll(); - Assert.AreEqual(count, preparedStatements.Count); + Assert.That(preparedStatements.Count, Is.EqualTo(count)); if (count > 0) { - StringAssert.AreEqualIgnoringCase(sqlText, preparedStatements[0]["SQL_TEXT"].ToString()); - Assert.AreEqual(executions, preparedStatements[0]["COUNT_EXECUTE"]); + Assert.That(preparedStatements[0]["SQL_TEXT"].ToString(), Is.EqualTo(sqlText).IgnoreCase); + Assert.That(preparedStatements[0]["COUNT_EXECUTE"], Is.EqualTo(executions)); } } @@ -124,15 +124,15 @@ public void Find() Collection coll = GetCollection(); var findStmt = coll.Find("_id = :id and pages = :pages").Bind("id", 1).Bind("pages", 20); var doc = ExecuteFindStatement(findStmt); - Assert.AreEqual("Book 1", doc.FetchAll()[0]["title"].ToString()); - Assert.False(findStmt._isPrepared); + Assert.That(doc.FetchAll()[0]["title"].ToString(), Is.EqualTo("Book 1")); + Assert.That(findStmt._isPrepared, Is.False); ValidatePreparedStatements(0, 0, null); for (int i = 1; i <= _docs.Length; i++) { doc = ExecuteFindStatement(findStmt.Bind("id", i).Bind("pages", i * 10 + 10).Limit(1)); - Assert.AreEqual($"Book {i}", doc.FetchAll()[0]["title"].ToString()); - Assert.True(findStmt._isPrepared || !findStmt.Session.SupportsPreparedStatements); + Assert.That(doc.FetchAll()[0]["title"].ToString(), Is.EqualTo($"Book {i}")); + Assert.That(findStmt._isPrepared || !findStmt.Session.SupportsPreparedStatements); } ValidatePreparedStatements(1, 4, @@ -147,13 +147,13 @@ public void FindWithChanges() var findStmt = coll.Find("_id = 1"); var foundDoc = ExecuteFindStatement(findStmt); - Assert.AreEqual("Book 1", foundDoc.FetchAll()[0]["title"].ToString()); - Assert.False(findStmt._isPrepared); + Assert.That(foundDoc.FetchAll()[0]["title"].ToString(), Is.EqualTo("Book 1")); + Assert.That(findStmt._isPrepared, Is.False); ValidatePreparedStatements(0, 0, null); foundDoc = ExecuteFindStatement(findStmt.Limit(1)); - Assert.AreEqual("Book 1", foundDoc.FetchAll()[0]["title"].ToString()); - Assert.True(findStmt._isPrepared || !findStmt.Session.SupportsPreparedStatements); + Assert.That(foundDoc.FetchAll()[0]["title"].ToString(), Is.EqualTo("Book 1")); + Assert.That(findStmt._isPrepared || !findStmt.Session.SupportsPreparedStatements); ValidatePreparedStatements(1, 1, $"SELECT doc FROM `{schemaName}`.`{_collectionName}` WHERE (JSON_UNQUOTE(JSON_EXTRACT(doc,'$._id')) = 1) LIMIT ?, ?"); @@ -161,8 +161,8 @@ public void FindWithChanges() for (int i = 1; i <= _docs.Length; i++) { var foundDoc2 = ExecuteFindStatement(findStmt.Where($"_id = {i}")); - Assert.AreEqual($"Book {i}", foundDoc2.FetchAll()[0]["title"].ToString()); - Assert.False(findStmt._isPrepared); + Assert.That(foundDoc2.FetchAll()[0]["title"].ToString(), Is.EqualTo($"Book {i}")); + Assert.That(findStmt._isPrepared, Is.False); } ValidatePreparedStatements(0, 0, null); @@ -182,13 +182,13 @@ public void DeallocatePreparedStatmentsWhenClosingSession() var findStmt = coll.Find($"_id = 1"); var foundDoc = ExecuteFindStatement(findStmt); - Assert.AreEqual("Book 1", foundDoc.FetchAll()[0]["title"].ToString()); - Assert.False(findStmt._isPrepared); + Assert.That(foundDoc.FetchAll()[0]["title"].ToString(), Is.EqualTo("Book 1")); + Assert.That(findStmt._isPrepared, Is.False); ValidatePreparedStatements(0, 0, null, threadId); foundDoc = ExecuteFindStatement(findStmt.Limit(1)); - Assert.AreEqual("Book 1", foundDoc.FetchAll()[0]["title"].ToString()); - Assert.True(findStmt._isPrepared || !findStmt.Session.SupportsPreparedStatements); + Assert.That(foundDoc.FetchAll()[0]["title"].ToString(), Is.EqualTo("Book 1")); + Assert.That(findStmt._isPrepared || !findStmt.Session.SupportsPreparedStatements); if (findStmt.Session.SupportsPreparedStatements) { @@ -208,15 +208,15 @@ public void Select() Table table = GetTable(); var selectStmt = table.Select().Where("id = :id").Bind("id", 1); RowResult row = ExecuteSelectStatement(selectStmt); - Assert.AreEqual(_allRows[0][1], row.FetchAll()[0]["name"].ToString()); - Assert.False(selectStmt._isPrepared); + Assert.That(row.FetchAll()[0]["name"].ToString(), Is.EqualTo(_allRows[0][1])); + Assert.That(selectStmt._isPrepared, Is.False); ValidatePreparedStatements(0, 0, null); for (int i = 0; i < _allRows.Length; i++) { row = ExecuteSelectStatement(selectStmt.Bind("id", i + 1).Limit(1)); - Assert.AreEqual(_allRows[i][1], row.FetchAll()[0]["name"].ToString()); - Assert.True(selectStmt._isPrepared || !selectStmt.Session.SupportsPreparedStatements); + Assert.That(row.FetchAll()[0]["name"].ToString(), Is.EqualTo(_allRows[i][1])); + Assert.That(selectStmt._isPrepared || !selectStmt.Session.SupportsPreparedStatements); } ValidatePreparedStatements(1, 3, @@ -231,13 +231,13 @@ public void SelectWithChanges() var selectStmt = table.Select().Where("id = 1"); RowResult row = ExecuteSelectStatement(selectStmt); - Assert.AreEqual(_allRows[0][1], row.FetchAll()[0]["name"].ToString()); - Assert.False(selectStmt._isPrepared); + Assert.That(row.FetchAll()[0]["name"].ToString(), Is.EqualTo(_allRows[0][1])); + Assert.That(selectStmt._isPrepared, Is.False); ValidatePreparedStatements(0, 0, null); row = ExecuteSelectStatement(selectStmt.Limit(1)); - Assert.AreEqual(_allRows[0][1], row.FetchAll()[0]["name"].ToString()); - Assert.True(selectStmt._isPrepared || !selectStmt.Session.SupportsPreparedStatements); + Assert.That(row.FetchAll()[0]["name"].ToString(), Is.EqualTo(_allRows[0][1])); + Assert.That(selectStmt._isPrepared || !selectStmt.Session.SupportsPreparedStatements); ValidatePreparedStatements(1, 1, $"SELECT * FROM `{schemaName}`.`{_tableName}` WHERE (`id` = 1) LIMIT ?, ?"); @@ -245,8 +245,8 @@ public void SelectWithChanges() for (int i = 2; i <= _allRows.Length; i++) { row = ExecuteSelectStatement(selectStmt.Where($"id = {i}")); - Assert.AreEqual(_allRows[i - 1][1], row.FetchAll()[0]["name"].ToString()); - Assert.False(selectStmt._isPrepared); + Assert.That(row.FetchAll()[0]["name"].ToString(), Is.EqualTo(_allRows[i - 1][1])); + Assert.That(selectStmt._isPrepared, Is.False); } ValidatePreparedStatements(0, 0, null); @@ -259,15 +259,15 @@ public void Modify() Collection coll = GetCollection(); var modifyStmt = coll.Modify("_id = :id").Set("title", "Magazine 1").Bind("id", 1); Result result = ExecuteModifyStatement(modifyStmt); - Assert.AreEqual(1ul, result.AffectedItemsCount); - Assert.False(modifyStmt._isPrepared); + Assert.That(result.AffectedItemsCount, Is.EqualTo(1ul)); + Assert.That(modifyStmt._isPrepared, Is.False); ValidatePreparedStatements(0, 0, null); for (int i = 2; i <= _docs.Length; i++) { result = ExecuteModifyStatement(modifyStmt.Bind("id", i).Limit(1)); - Assert.AreEqual(1ul, result.AffectedItemsCount); - Assert.True(modifyStmt._isPrepared || !modifyStmt.Session.SupportsPreparedStatements); + Assert.That(result.AffectedItemsCount, Is.EqualTo(1ul)); + Assert.That(modifyStmt._isPrepared || !modifyStmt.Session.SupportsPreparedStatements); } ValidatePreparedStatements(1, 3, @@ -281,21 +281,21 @@ public void ModifyWithChanges() Collection coll = GetCollection(); var modifyStmt = coll.Modify("_id = :id").Set("title", "CONCAT('Magazine ', id)").Bind("id", 1); Result result = ExecuteModifyStatement(modifyStmt); - Assert.AreEqual(1ul, result.AffectedItemsCount); - Assert.False(modifyStmt._isPrepared); + Assert.That(result.AffectedItemsCount, Is.EqualTo(1ul)); + Assert.That(modifyStmt._isPrepared, Is.False); ValidatePreparedStatements(0, 0, null); result = ExecuteModifyStatement(modifyStmt.Bind("id", 2).Limit(1)); - Assert.AreEqual(1ul, result.AffectedItemsCount); - Assert.True(modifyStmt._isPrepared || !modifyStmt.Session.SupportsPreparedStatements); + Assert.That(result.AffectedItemsCount, Is.EqualTo(1ul)); + Assert.That(modifyStmt._isPrepared || !modifyStmt.Session.SupportsPreparedStatements); ValidatePreparedStatements(1, 1, $"UPDATE `{schemaName}`.`{_collectionName}` SET doc=JSON_SET(JSON_SET(doc,'$.title','CONCAT(\\'Magazine \\', id)'),'$._id',JSON_EXTRACT(`doc`,'$._id')) WHERE (JSON_EXTRACT(doc,'$._id') = ?) LIMIT ?"); for (int i = 3; i <= _docs.Length; i++) { result = ExecuteModifyStatement(modifyStmt.Set("title", $"Magazine {i}").Bind("id", i)); - Assert.AreEqual(1ul, result.AffectedItemsCount); - Assert.False(modifyStmt._isPrepared); + Assert.That(result.AffectedItemsCount, Is.EqualTo(1ul)); + Assert.That(modifyStmt._isPrepared, Is.False); } ValidatePreparedStatements(0, 0, null); @@ -308,15 +308,15 @@ public void Update() Table table = GetTable(); var updateStmt = table.Update().Where("id = :id").Set("name", "Magazine").Bind("id", 1); Result result = ExecuteUpdateStatement(updateStmt); - Assert.AreEqual(1ul, result.AffectedItemsCount); - Assert.False(updateStmt._isPrepared); + Assert.That(result.AffectedItemsCount, Is.EqualTo(1ul)); + Assert.That(updateStmt._isPrepared, Is.False); ValidatePreparedStatements(0, 0, null); for (int i = 2; i <= _allRows.Length; i++) { result = ExecuteUpdateStatement(updateStmt.Bind("id", i).Limit(1)); - Assert.AreEqual(1ul, result.AffectedItemsCount); - Assert.True(updateStmt._isPrepared || !updateStmt.Session.SupportsPreparedStatements); + Assert.That(result.AffectedItemsCount, Is.EqualTo(1ul)); + Assert.That(updateStmt._isPrepared || !updateStmt.Session.SupportsPreparedStatements); } ValidatePreparedStatements(1, 2, @@ -330,21 +330,21 @@ public void UpdateWithChanges() Table table = GetTable(); var updateStmt = table.Update().Where("id = :id").Set("name", "CONCAT('Magazine ', id)").Bind("id", 1); Result result = ExecuteUpdateStatement(updateStmt); - Assert.AreEqual(1ul, result.AffectedItemsCount); - Assert.False(updateStmt._isPrepared); + Assert.That(result.AffectedItemsCount, Is.EqualTo(1ul)); + Assert.That(updateStmt._isPrepared, Is.False); ValidatePreparedStatements(0, 0, null); result = ExecuteUpdateStatement(updateStmt.Bind("id", 2).Limit(1)); - Assert.AreEqual(1ul, result.AffectedItemsCount); - Assert.True(updateStmt._isPrepared || !updateStmt.Session.SupportsPreparedStatements); + Assert.That(result.AffectedItemsCount, Is.EqualTo(1ul)); + Assert.That(updateStmt._isPrepared || !updateStmt.Session.SupportsPreparedStatements); ValidatePreparedStatements(1, 1, $"UPDATE `{schemaName}`.`{_tableName}` SET `name`=CONCAT('Magazine ',`id`) WHERE (`id` = ?) LIMIT ?"); for (int i = 3; i <= _allRows.Length; i++) { result = ExecuteUpdateStatement(updateStmt.Set("name", $"Magazine {i}").Bind("id", i)); - Assert.AreEqual(1ul, result.AffectedItemsCount); - Assert.False(updateStmt._isPrepared); + Assert.That(result.AffectedItemsCount, Is.EqualTo(1ul)); + Assert.That(updateStmt._isPrepared, Is.False); } ValidatePreparedStatements(0, 0, null); @@ -357,15 +357,15 @@ public void Remove() Collection coll = GetCollection(); var removeStmt = coll.Remove("_id = :id").Bind("id", 1); Result result = ExecuteRemoveStatement(removeStmt); - Assert.AreEqual(1ul, result.AffectedItemsCount); - Assert.False(removeStmt._isPrepared); + Assert.That(result.AffectedItemsCount, Is.EqualTo(1ul)); + Assert.That(removeStmt._isPrepared, Is.False); ValidatePreparedStatements(0, 0, null); for (int i = 2; i <= _docs.Length; i++) { result = ExecuteRemoveStatement(removeStmt.Bind("id", i).Limit(1)); - Assert.AreEqual(1ul, result.AffectedItemsCount); - Assert.True(removeStmt._isPrepared || !removeStmt.Session.SupportsPreparedStatements); + Assert.That(result.AffectedItemsCount, Is.EqualTo(1ul)); + Assert.That(removeStmt._isPrepared || !removeStmt.Session.SupportsPreparedStatements); } ValidatePreparedStatements(1, 3, @@ -379,21 +379,21 @@ public void RemoveWithChanges() Collection coll = GetCollection(); var removeStmt = coll.Remove("_id = :id").Bind("id", 1); Result result = ExecuteRemoveStatement(removeStmt); - Assert.AreEqual(1ul, result.AffectedItemsCount); - Assert.False(removeStmt._isPrepared); + Assert.That(result.AffectedItemsCount, Is.EqualTo(1ul)); + Assert.That(removeStmt._isPrepared, Is.False); ValidatePreparedStatements(0, 0, null); result = ExecuteRemoveStatement(removeStmt.Bind("id", 2).Limit(1)); - Assert.AreEqual(1ul, result.AffectedItemsCount); - Assert.True(removeStmt._isPrepared || !removeStmt.Session.SupportsPreparedStatements); + Assert.That(result.AffectedItemsCount, Is.EqualTo(1ul)); + Assert.That(removeStmt._isPrepared || !removeStmt.Session.SupportsPreparedStatements); ValidatePreparedStatements(1, 1, $"DELETE FROM `{schemaName}`.`{_collectionName}` WHERE (JSON_EXTRACT(doc,'$._id') = ?) LIMIT ?"); for (int i = 3; i <= _docs.Length; i++) { result = ExecuteRemoveStatement(removeStmt.Where($"_id = {i}")); - Assert.AreEqual(1ul, result.AffectedItemsCount); - Assert.False(removeStmt._isPrepared); + Assert.That(result.AffectedItemsCount, Is.EqualTo(1ul)); + Assert.That(removeStmt._isPrepared, Is.False); } ValidatePreparedStatements(0, 0, null); @@ -406,15 +406,15 @@ public void Delete() Table table = GetTable(); var deleteStmt = table.Delete().Where("id = :id").Bind("id", 1); Result result = ExecuteDeleteStatement(deleteStmt); - Assert.AreEqual(1ul, result.AffectedItemsCount); - Assert.False(deleteStmt._isPrepared); + Assert.That(result.AffectedItemsCount, Is.EqualTo(1ul)); + Assert.That(deleteStmt._isPrepared, Is.False); ValidatePreparedStatements(0, 0, null); for (int i = 2; i <= _allRows.Length; i++) { result = ExecuteDeleteStatement(deleteStmt.Bind("id", i).Limit(1)); - Assert.AreEqual(1ul, result.AffectedItemsCount); - Assert.True(deleteStmt._isPrepared || !deleteStmt.Session.SupportsPreparedStatements); + Assert.That(result.AffectedItemsCount, Is.EqualTo(1ul)); + Assert.That(deleteStmt._isPrepared || !deleteStmt.Session.SupportsPreparedStatements); } ValidatePreparedStatements(1, 2, @@ -428,21 +428,21 @@ public void DeleteWithChanges() Table table = GetTable(); var deleteStmt = table.Delete().Where("id = :id").Bind("id", 1); Result result = ExecuteDeleteStatement(deleteStmt); - Assert.AreEqual(1ul, result.AffectedItemsCount); - Assert.False(deleteStmt._isPrepared); + Assert.That(result.AffectedItemsCount, Is.EqualTo(1ul)); + Assert.That(deleteStmt._isPrepared, Is.False); ValidatePreparedStatements(0, 0, null); result = ExecuteDeleteStatement(deleteStmt.Bind("id", 2).Limit(1)); - Assert.AreEqual(1ul, result.AffectedItemsCount); - Assert.True(deleteStmt._isPrepared || !deleteStmt.Session.SupportsPreparedStatements); + Assert.That(result.AffectedItemsCount, Is.EqualTo(1ul)); + Assert.That(deleteStmt._isPrepared || !deleteStmt.Session.SupportsPreparedStatements); ValidatePreparedStatements(1, 1, $"DELETE FROM `{schemaName}`.`{_tableName}` WHERE (`id` = ?) LIMIT ?"); for (int i = 3; i <= _allRows.Length; i++) { result = ExecuteDeleteStatement(deleteStmt.Where($"id = {i}")); - Assert.AreEqual(1ul, result.AffectedItemsCount); - Assert.False(deleteStmt._isPrepared); + Assert.That(result.AffectedItemsCount, Is.EqualTo(1ul)); + Assert.That(deleteStmt._isPrepared, Is.False); } ValidatePreparedStatements(0, 0, null); @@ -458,20 +458,20 @@ public void MaxPreparedStmtCount() ((Session)coll.Session).SQL("SET GLOBAL max_prepared_stmt_count=0").Execute(); var findStmt = coll.Find("_id = :id and pages = :pages").Bind("id", 1).Bind("pages", 20); var doc = ExecuteFindStatement(findStmt); - Assert.AreEqual("Book 1", doc.FetchAll()[0]["title"].ToString()); - Assert.False(findStmt._isPrepared); - Assert.True(findStmt.Session.SupportsPreparedStatements); + Assert.That(doc.FetchAll()[0]["title"].ToString(), Is.EqualTo("Book 1")); + Assert.That(findStmt._isPrepared, Is.False); + Assert.That(findStmt.Session.SupportsPreparedStatements); ValidatePreparedStatements(0, 0, null); doc = ExecuteFindStatement(findStmt.Bind("id", 2).Bind("pages", 30).Limit(1)); - Assert.AreEqual($"Book 2", doc.FetchAll()[0]["title"].ToString()); - Assert.False(findStmt._isPrepared); - Assert.False(findStmt.Session.SupportsPreparedStatements); + Assert.That(doc.FetchAll()[0]["title"].ToString(), Is.EqualTo($"Book 2")); + Assert.That(findStmt._isPrepared, Is.False); + Assert.That(findStmt.Session.SupportsPreparedStatements, Is.False); doc = ExecuteFindStatement(findStmt.Bind("id", 3).Bind("pages", 40).Limit(1)); - Assert.AreEqual($"Book 3", doc.FetchAll()[0]["title"].ToString()); - Assert.False(findStmt._isPrepared); - Assert.False(findStmt.Session.SupportsPreparedStatements); + Assert.That(doc.FetchAll()[0]["title"].ToString(), Is.EqualTo($"Book 3")); + Assert.That(findStmt._isPrepared, Is.False); + Assert.That(findStmt.Session.SupportsPreparedStatements, Is.False); } finally { @@ -489,34 +489,34 @@ public void LimitAndOffset() var findStmt = coll.Find("pages >= :lower AND pages <= :upper").Bind("lower", 20).Bind("upper", 20); var result = ExecuteFindStatement(findStmt).FetchAll(); Assert.That(result, Has.One.Items); - Assert.AreEqual("Book 1", result[0]["title"].ToString()); - Assert.False(findStmt._isPrepared); + Assert.That(result[0]["title"].ToString(), Is.EqualTo("Book 1")); + Assert.That(findStmt._isPrepared, Is.False); ValidatePreparedStatements(0, 0, null); // second execution adding limit (prepared statement) result = ExecuteFindStatement(findStmt.Bind("lower", 0).Bind("upper", 100).Limit(1)).FetchAll(); Assert.That(result, Has.One.Items); - Assert.AreEqual($"Book 1", result[0]["title"].ToString()); - Assert.True(findStmt._isPrepared); + Assert.That(result[0]["title"].ToString(), Is.EqualTo($"Book 1")); + Assert.That(findStmt._isPrepared); ValidatePreparedStatements(1, 1, $"SELECT doc FROM `{schemaName}`.`{_collectionName}` WHERE ((JSON_EXTRACT(doc,'$.pages') >= ?) AND (JSON_EXTRACT(doc,'$.pages') <= ?)) LIMIT ?, ?"); // new execution using a different limit and offset (prepared statement) result = ExecuteFindStatement(findStmt.Bind("lower", 0).Bind("upper", 100).Limit(2).Offset(1)).FetchAll(); - Assert.AreEqual(2, result.Count); - Assert.AreEqual($"Book 2", result[0]["title"].ToString()); - Assert.AreEqual($"Book 3", result[1]["title"].ToString()); - Assert.True(findStmt._isPrepared || !findStmt.Session.SupportsPreparedStatements); + Assert.That(result.Count, Is.EqualTo(2)); + Assert.That(result[0]["title"].ToString(), Is.EqualTo($"Book 2")); + Assert.That(result[1]["title"].ToString(), Is.EqualTo($"Book 3")); + Assert.That(findStmt._isPrepared || !findStmt.Session.SupportsPreparedStatements); ValidatePreparedStatements(1, 2, $"SELECT doc FROM `{schemaName}`.`{_collectionName}` WHERE ((JSON_EXTRACT(doc,'$.pages') >= ?) AND (JSON_EXTRACT(doc,'$.pages') <= ?)) LIMIT ?, ?"); // execution without limit and offset but persisting previous values (prepared statement) result = ExecuteFindStatement(findStmt.Bind("lower", 0).Bind("upper", 100)).FetchAll(); - Assert.AreEqual(2, result.Count); - Assert.True(findStmt._isPrepared); + Assert.That(result.Count, Is.EqualTo(2)); + Assert.That(findStmt._isPrepared); ValidatePreparedStatements(1, 3, $"SELECT doc FROM `{schemaName}`.`{_collectionName}` WHERE ((JSON_EXTRACT(doc,'$.pages') >= ?) AND (JSON_EXTRACT(doc,'$.pages') <= ?)) LIMIT ?, ?"); @@ -544,16 +544,16 @@ public void ConnectionPoolingTest() { var row = res0.FetchOne(); connectionID1 = row[0].ToString(); - Assert.IsNotEmpty(connectionID1); + Assert.That(connectionID1, Is.Not.Empty); } var findStmt = col.Find("_id = :id and pages = :pages").Bind("id", 1).Bind("pages", 20); var doc = ExecuteFindStatement(findStmt); - Assert.AreEqual("Book 1", doc.FetchAll()[0]["title"].ToString()); + Assert.That(doc.FetchAll()[0]["title"].ToString(), Is.EqualTo("Book 1")); ValidatePreparedStatements(0, 0, null); for (int i = 1; i < _docs.Length; i++) { doc = ExecuteFindStatement(findStmt.Bind("id", i).Bind("pages", i * 10 + 10).Limit(1)); - Assert.AreEqual($"Book {i}", doc.FetchAll()[0]["title"].ToString()); + Assert.That(doc.FetchAll()[0]["title"].ToString(), Is.EqualTo($"Book {i}")); } ValidatePreparedStatements(1, 3, $"SELECT doc FROM `{schemaName}`.`{_collectionName}` WHERE ((JSON_UNQUOTE(JSON_EXTRACT(doc,'$._id')) = ?) AND (JSON_EXTRACT(doc,'$.pages') = ?)) LIMIT ?, ?"); @@ -565,18 +565,18 @@ public void ConnectionPoolingTest() { var row = res0.FetchOne(); connectionID1 = row[0].ToString(); - Assert.IsNotEmpty(connectionID1); + Assert.That(connectionID1, Is.Not.Empty); } s = session2.GetSchema(schemaName); col = s.GetCollection(_collectionName); findStmt = col.Find("_id = :id and pages = :pages").Bind("id", 1).Bind("pages", 20); doc = ExecuteFindStatement(findStmt); - Assert.AreEqual("Book 1", doc.FetchAll()[0]["title"].ToString()); + Assert.That(doc.FetchAll()[0]["title"].ToString(), Is.EqualTo("Book 1")); ValidatePreparedStatements(0, 0, null, connectionID1); for (int i = 1; i < _docs.Length; i++) { doc = ExecuteFindStatement(findStmt.Bind("id", i).Bind("pages", i * 10 + 10).Limit(1)); - Assert.AreEqual($"Book {i}", doc.FetchAll()[0]["title"].ToString()); + Assert.That(doc.FetchAll()[0]["title"].ToString(), Is.EqualTo($"Book {i}")); } ValidatePreparedStatements(1, 3, $"SELECT doc FROM `{schemaName}`.`{_collectionName}` WHERE ((JSON_UNQUOTE(JSON_EXTRACT(doc,'$._id')) = ?) AND (JSON_EXTRACT(doc,'$.pages') = ?)) LIMIT ?, ?"); @@ -588,18 +588,18 @@ public void ConnectionPoolingTest() { var row = res0.FetchOne(); connectionID1 = row[0].ToString(); - Assert.IsNotEmpty(connectionID1); + Assert.That(connectionID1, Is.Not.Empty); } s = session2.GetSchema(schemaName); col = s.GetCollection(_collectionName); findStmt = col.Find("_id = :id and pages = :pages").Bind("id", 1).Bind("pages", 20); doc = ExecuteFindStatement(findStmt); - Assert.AreEqual("Book 1", doc.FetchAll()[0]["title"].ToString()); + Assert.That(doc.FetchAll()[0]["title"].ToString(), Is.EqualTo("Book 1")); ValidatePreparedStatements(0, 0, null, connectionID1); for (int i = 1; i < _docs.Length; i++) { doc = ExecuteFindStatement(findStmt.Bind("id", i).Bind("pages", i * 10 + 10).Limit(1)); - Assert.AreEqual($"Book {i}", doc.FetchAll()[0]["title"].ToString()); + Assert.That(doc.FetchAll()[0]["title"].ToString(), Is.EqualTo($"Book {i}")); } ValidatePreparedStatements(1, 3, $"SELECT doc FROM `{schemaName}`.`{_collectionName}` WHERE ((JSON_UNQUOTE(JSON_EXTRACT(doc,'$._id')) = ?) AND (JSON_EXTRACT(doc,'$.pages') = ?)) LIMIT ?, ?"); @@ -625,13 +625,13 @@ public void DeallocatePreparedStatmentsWhenClosingSessionLoad() Collection coll = mySession.GetSchema(schemaName).GetCollection(_collectionName); var findStmt = coll.Find("_id = :id and pages = :pages").Bind("id", 1).Bind("pages", 20); var doc = ExecuteFindStatement(findStmt); - Assert.AreEqual("Book 1", doc.FetchAll()[0]["title"].ToString()); + Assert.That(doc.FetchAll()[0]["title"].ToString(), Is.EqualTo("Book 1")); ValidatePreparedStatements(0, 0, null, threadId); for (int i = 1; i <= _docs.Length; i++) { doc = ExecuteFindStatement(findStmt.Bind("id", i).Bind("pages", i * 10 + 10).Limit(1)); - Assert.AreEqual($"Book {i}", doc.FetchAll()[0]["title"].ToString()); + Assert.That(doc.FetchAll()[0]["title"].ToString(), Is.EqualTo($"Book {i}")); } ValidatePreparedStatements(1, 4, $"SELECT doc FROM `{schemaName}`.`{_collectionName}` WHERE ((JSON_UNQUOTE(JSON_EXTRACT(doc,'$._id')) = ?) AND (JSON_EXTRACT(doc,'$.pages') = ?)) LIMIT ?, ?", threadId); @@ -659,23 +659,23 @@ public void DeallocatePreparedStatmentsWhenClosingSessionParallel() var findStmt1 = coll1.Find("_id = :id and pages = :pages").Bind("id", 1).Bind("pages", 20); var findStmt2 = coll2.Find("_id = :id and pages = :pages").Bind("id", 1).Bind("pages", 20); var doc1 = ExecuteFindStatement(findStmt1); - Assert.AreEqual("Book 1", doc1.FetchAll()[0]["title"].ToString()); + Assert.That(doc1.FetchAll()[0]["title"].ToString(), Is.EqualTo("Book 1")); ValidatePreparedStatements(0, 0, null, threadId1); var doc2 = ExecuteFindStatement(findStmt2); - Assert.AreEqual("Book 1", doc2.FetchAll()[0]["title"].ToString()); + Assert.That(doc2.FetchAll()[0]["title"].ToString(), Is.EqualTo("Book 1")); ValidatePreparedStatements(0, 0, null, threadId2); for (int i = 1; i <= _docs.Length; i++) { doc1 = ExecuteFindStatement(findStmt1.Bind("id", i).Bind("pages", i * 10 + 10).Limit(1)); - Assert.AreEqual($"Book {i}", doc1.FetchAll()[0]["title"].ToString()); + Assert.That(doc1.FetchAll()[0]["title"].ToString(), Is.EqualTo($"Book {i}")); } for (int i = 1; i <= _docs.Length; i++) { doc2 = ExecuteFindStatement(findStmt2.Bind("id", i).Bind("pages", i * 10 + 10).Limit(1)); - Assert.AreEqual($"Book {i}", doc2.FetchAll()[0]["title"].ToString()); + Assert.That(doc2.FetchAll()[0]["title"].ToString(), Is.EqualTo($"Book {i}")); } ValidatePreparedStatements(1, 4, @@ -694,21 +694,21 @@ public void MaxPreparedStmtCountAsOne() { Collection coll = CreateCollection("testGlobal"); Result r = ExecuteAddStatement(coll.Add(_docs)); - Assert.AreEqual(4, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(4)); try { ((Session)coll.Session).SQL("SET GLOBAL max_prepared_stmt_count=1").Execute(); var findStmt = coll.Find("_id = :id and pages = :pages").Bind("id", 1).Bind("pages", 20); var doc = ExecuteFindStatement(findStmt); - Assert.AreEqual("Book 1", doc.FetchAll()[0]["title"].ToString()); + Assert.That(doc.FetchAll()[0]["title"].ToString(), Is.EqualTo("Book 1")); ValidatePreparedStatements(0, 0, null); for (int i = 1; i <= _docs.Length; i++) { doc = ExecuteFindStatement(findStmt.Bind("id", i).Bind("pages", i * 10 + 10).Limit(1)); - Assert.AreEqual($"Book {i}", doc.FetchAll()[0]["title"].ToString()); + Assert.That(doc.FetchAll()[0]["title"].ToString(), Is.EqualTo($"Book {i}")); } ValidatePreparedStatements(1, 4, $"SELECT doc FROM `{schemaName}`.`testGlobal` WHERE ((JSON_EXTRACT(doc,'$._id') = ?) AND (JSON_EXTRACT(doc,'$.pages') = ?)) LIMIT ?, ?"); @@ -747,13 +747,13 @@ public void PSMultipleFindAsync() var findStmt = coll.Find("age = 1"); tasksList.Add(findStmt.ExecuteAsync().ContinueWith((findResult) => { - Assert.AreEqual(1, findResult.Result.FetchAll()[0]["age"]); + Assert.That(findResult.Result.FetchAll()[0]["age"], Is.EqualTo(1)); })); tasksList.Add(findStmt.ExecuteAsync().ContinueWith((findResult) => { - Assert.AreEqual(1, findResult.Result.FetchAll()[0]["age"]); + Assert.That(findResult.Result.FetchAll()[0]["age"], Is.EqualTo(1)); })); - Assert.AreEqual(true, Task.WaitAll(tasksList.ToArray(), TimeSpan.FromMinutes(2)), "WaitAll timeout"); + Assert.That(Task.WaitAll(tasksList.ToArray(), TimeSpan.FromMinutes(2)), Is.EqualTo(true), "WaitAll timeout"); ValidatePreparedStatements(1, 1, $"SELECT doc FROM `test`.`test` WHERE (JSON_EXTRACT(doc,'$.age') = 1)"); } @@ -766,7 +766,7 @@ public void FindRemoveWithString() { InitCollection(); Collection coll = GetCollection(); - Assert.AreEqual(4, coll.Count()); + Assert.That(coll.Count(), Is.EqualTo(4)); var findStmt = coll.Find("_id = :id and pages = :pages").Bind("id", "1").Bind("pages", 20); var doc = ExecuteFindStatement(findStmt); findStmt = coll.Find("_id = :id and pages = :pages").Bind("id", "2").Bind("pages", 30); @@ -778,11 +778,11 @@ public void FindRemoveWithString() } findStmt = coll.Find("_id = :id").Bind("id", "4"); var docCount = ExecuteFindStatement(findStmt).FetchAll(); - Assert.AreEqual(1, docCount.Count, "There should be a record"); - Assert.AreEqual("Book 4", docCount[0]["title"].ToString()); + Assert.That(docCount.Count, Is.EqualTo(1), "There should be a record"); + Assert.That(docCount[0]["title"].ToString(), Is.EqualTo("Book 4")); findStmt = coll.Find("_id = :id").Bind("id", "1"); docCount = ExecuteFindStatement(findStmt).FetchAll(); - Assert.AreEqual(0, docCount.Count, "There should not be any records"); + Assert.That(docCount.Count, Is.EqualTo(0), "There should not be any records"); } /// @@ -806,7 +806,7 @@ public void StatementWithOffset() new { _id = 8, name = "tommy h", age =31,profit = 3000} }; var r = coll.Add(docs1).Execute(); - Assert.AreEqual((ulong)8, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo((ulong)8)); var findStmt = coll.Find().Fields("_id as ID", "name as Name", "age as Age", "profit as Profit").GroupBy("age"). GroupBy("profit").Sort("profit ASC").Limit(3); diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/ColumnMetadataTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/ColumnMetadataTests.cs index fa37af35e..5d4a7b5eb 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/ColumnMetadataTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/ColumnMetadataTests.cs @@ -46,46 +46,46 @@ public void ColumnMetadata() RowResult r = ExecuteSelectStatement(GetSession().GetSchema(schemaName).GetTable("test").Select("1 + 1 as a", "b", "c")); var rows = r.FetchAll(); - Assert.AreEqual(3, r.Columns.Count); - Assert.AreEqual("def", r.Columns[0].DatabaseName); - Assert.Null(r.Columns[0].SchemaName); - Assert.Null(r.Columns[0].TableName); - Assert.Null(r.Columns[0].TableLabel); - Assert.Null(r.Columns[0].ColumnName); - Assert.AreEqual("a", r.Columns[0].ColumnLabel); - Assert.AreEqual(ColumnType.Tinyint, r.Columns[0].Type); - Assert.AreEqual(3u, r.Columns[0].Length); - Assert.AreEqual(0u, r.Columns[0].FractionalDigits); - Assert.True(r.Columns[0].IsNumberSigned); - Assert.Null(r.Columns[0].CharacterSetName); - Assert.Null(r.Columns[0].CollationName); - Assert.False(r.Columns[0].IsPadded); + Assert.That(r.Columns.Count, Is.EqualTo(3)); + Assert.That(r.Columns[0].DatabaseName, Is.EqualTo("def")); + Assert.That(r.Columns[0].SchemaName, Is.Null); + Assert.That(r.Columns[0].TableName, Is.Null); + Assert.That(r.Columns[0].TableLabel, Is.Null); + Assert.That(r.Columns[0].ColumnName, Is.Null); + Assert.That(r.Columns[0].ColumnLabel, Is.EqualTo("a")); + Assert.That(r.Columns[0].Type, Is.EqualTo(ColumnType.Tinyint)); + Assert.That(r.Columns[0].Length, Is.EqualTo(3u)); + Assert.That(r.Columns[0].FractionalDigits, Is.EqualTo(0u)); + Assert.That(r.Columns[0].IsNumberSigned); + Assert.That(r.Columns[0].CharacterSetName, Is.Null); + Assert.That(r.Columns[0].CollationName, Is.Null); + Assert.That(r.Columns[0].IsPadded, Is.False); - Assert.AreEqual(schemaName, r.Columns[1].SchemaName); - Assert.AreEqual("test", r.Columns[1].TableName); - Assert.AreEqual("test", r.Columns[1].TableLabel); - Assert.AreEqual("b", r.Columns[1].ColumnName); - Assert.AreEqual("b", r.Columns[1].ColumnLabel); - Assert.AreEqual(ColumnType.String, r.Columns[1].Type); - Assert.AreEqual(255u, r.Columns[1].Length); - Assert.AreEqual(0u, r.Columns[1].FractionalDigits); - Assert.False(r.Columns[1].IsNumberSigned); - Assert.AreEqual("utf8mb4", r.Columns[1].CharacterSetName); - Assert.AreEqual("utf8mb4_0900_ai_ci", r.Columns[1].CollationName); - Assert.False(r.Columns[1].IsPadded); + Assert.That(r.Columns[1].SchemaName, Is.EqualTo(schemaName)); + Assert.That(r.Columns[1].TableName, Is.EqualTo("test")); + Assert.That(r.Columns[1].TableLabel, Is.EqualTo("test")); + Assert.That(r.Columns[1].ColumnName, Is.EqualTo("b")); + Assert.That(r.Columns[1].ColumnLabel, Is.EqualTo("b")); + Assert.That(r.Columns[1].Type, Is.EqualTo(ColumnType.String)); + Assert.That(r.Columns[1].Length, Is.EqualTo(255u)); + Assert.That(r.Columns[1].FractionalDigits, Is.EqualTo(0u)); + Assert.That(r.Columns[1].IsNumberSigned, Is.False); + Assert.That(r.Columns[1].CharacterSetName, Is.EqualTo("utf8mb4")); + Assert.That(r.Columns[1].CollationName, Is.EqualTo("utf8mb4_0900_ai_ci")); + Assert.That(r.Columns[1].IsPadded, Is.False); - Assert.AreEqual(schemaName, r.Columns[2].SchemaName); - Assert.AreEqual("test", r.Columns[2].TableName); - Assert.AreEqual("test", r.Columns[2].TableLabel); - Assert.AreEqual("c", r.Columns[2].ColumnName); - Assert.AreEqual("c", r.Columns[2].ColumnLabel); - Assert.AreEqual(ColumnType.String, r.Columns[2].Type); - Assert.AreEqual(20u, r.Columns[2].Length); - Assert.AreEqual(0u, r.Columns[2].FractionalDigits); - Assert.False(r.Columns[2].IsNumberSigned); - Assert.AreEqual("utf8mb4", r.Columns[2].CharacterSetName); - Assert.AreEqual("utf8mb4_0900_ai_ci", r.Columns[2].CollationName); - Assert.False(r.Columns[2].IsPadded); + Assert.That(r.Columns[2].SchemaName, Is.EqualTo(schemaName)); + Assert.That(r.Columns[2].TableName, Is.EqualTo("test")); + Assert.That(r.Columns[2].TableLabel, Is.EqualTo("test")); + Assert.That(r.Columns[2].ColumnName, Is.EqualTo("c")); + Assert.That(r.Columns[2].ColumnLabel, Is.EqualTo("c")); + Assert.That(r.Columns[2].Type, Is.EqualTo(ColumnType.String)); + Assert.That(r.Columns[2].Length, Is.EqualTo(20u)); + Assert.That(r.Columns[2].FractionalDigits, Is.EqualTo(0u)); + Assert.That(r.Columns[2].IsNumberSigned, Is.False); + Assert.That(r.Columns[2].CharacterSetName, Is.EqualTo("utf8mb4")); + Assert.That(r.Columns[2].CollationName, Is.EqualTo("utf8mb4_0900_ai_ci")); + Assert.That(r.Columns[2].IsPadded, Is.False); //Assert.AreEqual("Δ", rows[0][2]); } @@ -101,26 +101,26 @@ public void SchemaDefaultCharset() RowResult r = ExecuteSelectStatement(GetSession().GetSchema(schemaName).GetTable("test").Select("b")); var rows = r.FetchAll(); - Assert.AreEqual(schemaName, r.Columns[0].SchemaName); - Assert.AreEqual("test", r.Columns[0].TableName); - Assert.AreEqual("test", r.Columns[0].TableLabel); - Assert.AreEqual("b", r.Columns[0].ColumnName); - Assert.AreEqual("b", r.Columns[0].ColumnLabel); - Assert.AreEqual(ColumnType.String, r.Columns[0].Type); - Assert.AreEqual(0u, r.Columns[0].FractionalDigits); - Assert.AreEqual(false, r.Columns[0].IsNumberSigned); - Assert.AreEqual(defaultValues[0][0], r.Columns[0].CharacterSetName); - Assert.AreEqual(defaultValues[0][1], r.Columns[0].CollationName); - Assert.AreEqual(false, r.Columns[0].IsPadded); - Assert.AreEqual("CAR", rows[0][0]); + Assert.That(r.Columns[0].SchemaName, Is.EqualTo(schemaName)); + Assert.That(r.Columns[0].TableName, Is.EqualTo("test")); + Assert.That(r.Columns[0].TableLabel, Is.EqualTo("test")); + Assert.That(r.Columns[0].ColumnName, Is.EqualTo("b")); + Assert.That(r.Columns[0].ColumnLabel, Is.EqualTo("b")); + Assert.That(r.Columns[0].Type, Is.EqualTo(ColumnType.String)); + Assert.That(r.Columns[0].FractionalDigits, Is.EqualTo(0u)); + Assert.That(r.Columns[0].IsNumberSigned, Is.EqualTo(false)); + Assert.That(r.Columns[0].CharacterSetName, Is.EqualTo(defaultValues[0][0])); + Assert.That(r.Columns[0].CollationName, Is.EqualTo(defaultValues[0][1])); + Assert.That(r.Columns[0].IsPadded, Is.EqualTo(false)); + Assert.That(rows[0][0], Is.EqualTo("CAR")); using (var connection = new MySqlConnection(ConnectionStringRoot)) { connection.Open(); if (connection.driver.Version.isAtLeast(8, 0, 1)) - Assert.AreEqual(1020u, r.Columns[0].Length); + Assert.That(r.Columns[0].Length, Is.EqualTo(1020u)); else - Assert.AreEqual(255u, r.Columns[0].Length); + Assert.That(r.Columns[0].Length, Is.EqualTo(255u)); } } @@ -130,11 +130,11 @@ public void ColumnNames() ExecuteSQL("CREATE TABLE test(columnA VARCHAR(255), columnB INT, columnX BIT)"); RowResult r = ExecuteSelectStatement(GetSession().GetSchema(schemaName).GetTable("test").Select()); - Assert.AreEqual(3, r.ColumnCount); - Assert.AreEqual(r.Columns.Count, r.ColumnCount); - Assert.AreEqual("columnA", r.ColumnNames[0]); - Assert.AreEqual("columnB", r.ColumnNames[1]); - Assert.AreEqual("columnX", r.ColumnNames[2]); + Assert.That(r.ColumnCount, Is.EqualTo(3)); + Assert.That(r.ColumnCount, Is.EqualTo(r.Columns.Count)); + Assert.That(r.ColumnNames[0], Is.EqualTo("columnA")); + Assert.That(r.ColumnNames[1], Is.EqualTo("columnB")); + Assert.That(r.ColumnNames[2], Is.EqualTo("columnX")); } [Test] @@ -147,19 +147,19 @@ public void TableDefaultCharset() RowResult r = ExecuteSelectStatement(GetSession().GetSchema(schemaName).GetTable("test").Select("b")); var rows = r.FetchAll(); - Assert.AreEqual(schemaName, r.Columns[0].SchemaName); - Assert.AreEqual("test", r.Columns[0].TableName); - Assert.AreEqual("test", r.Columns[0].TableLabel); - Assert.AreEqual("b", r.Columns[0].ColumnName); - Assert.AreEqual("b", r.Columns[0].ColumnLabel); - Assert.AreEqual(ColumnType.String, r.Columns[0].Type); - Assert.AreEqual(255u, r.Columns[0].Length); - Assert.AreEqual(0u, r.Columns[0].FractionalDigits); - Assert.False(r.Columns[0].IsNumberSigned); - Assert.AreEqual("utf8mb4", r.Columns[0].CharacterSetName); - Assert.AreEqual("utf8mb4_0900_ai_ci", r.Columns[0].CollationName); - Assert.False(r.Columns[0].IsPadded); - Assert.AreEqual("Δ", rows[0][0]); + Assert.That(r.Columns[0].SchemaName, Is.EqualTo(schemaName)); + Assert.That(r.Columns[0].TableName, Is.EqualTo("test")); + Assert.That(r.Columns[0].TableLabel, Is.EqualTo("test")); + Assert.That(r.Columns[0].ColumnName, Is.EqualTo("b")); + Assert.That(r.Columns[0].ColumnLabel, Is.EqualTo("b")); + Assert.That(r.Columns[0].Type, Is.EqualTo(ColumnType.String)); + Assert.That(r.Columns[0].Length, Is.EqualTo(255u)); + Assert.That(r.Columns[0].FractionalDigits, Is.EqualTo(0u)); + Assert.That(r.Columns[0].IsNumberSigned, Is.False); + Assert.That(r.Columns[0].CharacterSetName, Is.EqualTo("utf8mb4")); + Assert.That(r.Columns[0].CollationName, Is.EqualTo("utf8mb4_0900_ai_ci")); + Assert.That(r.Columns[0].IsPadded, Is.False); + Assert.That(rows[0][0], Is.EqualTo("Δ")); } } } diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/DataTypeTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/DataTypeTests.cs index 4e76036a7..81806cf7e 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/DataTypeTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/DataTypeTests.cs @@ -49,14 +49,14 @@ public void Float() RowResult r = ExecuteSelectStatement(GetSession().GetSchema("test").GetTable("test").Select("rvalue")); var rows = r.FetchAll(); Assert.That(r.Columns, Has.One.Items); - Assert.AreEqual(typeof(float), r.Columns[0].ClrType); - Assert.AreEqual(14, (int)r.Columns[0].Length); - Assert.AreEqual(8, (int)r.Columns[0].FractionalDigits); - Assert.AreEqual(ColumnType.Float, r.Columns[0].Type); - Assert.AreEqual(3, rows.Count); - Assert.AreEqual(23.4f, (float)rows[0][0]); - Assert.AreEqual(14.8f, rows[1][0]); - Assert.AreEqual(11.9f, rows[2][0]); + Assert.That(r.Columns[0].ClrType, Is.EqualTo(typeof(float))); + Assert.That((int)r.Columns[0].Length, Is.EqualTo(14)); + Assert.That((int)r.Columns[0].FractionalDigits, Is.EqualTo(8)); + Assert.That(r.Columns[0].Type, Is.EqualTo(ColumnType.Float)); + Assert.That(rows.Count, Is.EqualTo(3)); + Assert.That((float)rows[0][0], Is.EqualTo(23.4f)); + Assert.That(rows[1][0], Is.EqualTo(14.8f)); + Assert.That(rows[2][0], Is.EqualTo(11.9f)); } [Test] @@ -68,14 +68,14 @@ public void Double() RowResult r = ExecuteSelectStatement(GetSession().GetSchema("test").GetTable("test").Select("rvalue")); var rows = r.FetchAll(); Assert.That(r.Columns, Has.One.Items); - Assert.AreEqual(typeof(double), r.Columns[0].ClrType); - Assert.AreEqual(ColumnType.Double, r.Columns[0].Type); - Assert.AreEqual(12, (int)r.Columns[0].Length); - Assert.AreEqual(4, (int)r.Columns[0].FractionalDigits); - Assert.AreEqual(3, rows.Count); - Assert.AreEqual(23.4, rows[0][0]); - Assert.AreEqual(14.8, rows[1][0]); - Assert.AreEqual(11.9, rows[2][0]); + Assert.That(r.Columns[0].ClrType, Is.EqualTo(typeof(double))); + Assert.That(r.Columns[0].Type, Is.EqualTo(ColumnType.Double)); + Assert.That((int)r.Columns[0].Length, Is.EqualTo(12)); + Assert.That((int)r.Columns[0].FractionalDigits, Is.EqualTo(4)); + Assert.That(rows.Count, Is.EqualTo(3)); + Assert.That(rows[0][0], Is.EqualTo(23.4)); + Assert.That(rows[1][0], Is.EqualTo(14.8)); + Assert.That(rows[2][0], Is.EqualTo(11.9)); } [Test] @@ -87,12 +87,12 @@ public void Set() RowResult r = ExecuteSelectStatement(GetSession().GetSchema("test").GetTable("test").Select("rvalue")); var rows = r.FetchAll(); Assert.That(r.Columns, Has.One.Items); - Assert.AreEqual(typeof(string), r.Columns[0].ClrType); - Assert.AreEqual(ColumnType.Set, r.Columns[0].Type); - Assert.AreEqual(3, rows.Count); - Assert.AreEqual("A", rows[0][0]); - Assert.AreEqual("A,B", rows[1][0]); - Assert.AreEqual("B", rows[2][0]); + Assert.That(r.Columns[0].ClrType, Is.EqualTo(typeof(string))); + Assert.That(r.Columns[0].Type, Is.EqualTo(ColumnType.Set)); + Assert.That(rows.Count, Is.EqualTo(3)); + Assert.That(rows[0][0], Is.EqualTo("A")); + Assert.That(rows[1][0], Is.EqualTo("A,B")); + Assert.That(rows[2][0], Is.EqualTo("B")); } [Test] @@ -104,12 +104,12 @@ public void Enum() RowResult r = ExecuteSelectStatement(GetSession().GetSchema("test").GetTable("test").Select("rvalue")); var rows = r.FetchAll(); Assert.That(r.Columns, Has.One.Items); - Assert.AreEqual(typeof(string), r.Columns[0].ClrType); - Assert.AreEqual(ColumnType.Enum, r.Columns[0].Type); - Assert.AreEqual(3, rows.Count); - Assert.AreEqual("Alpha", rows[0][0]); - Assert.AreEqual("Beta", rows[1][0]); - Assert.AreEqual("C", rows[2][0]); + Assert.That(r.Columns[0].ClrType, Is.EqualTo(typeof(string))); + Assert.That(r.Columns[0].Type, Is.EqualTo(ColumnType.Enum)); + Assert.That(rows.Count, Is.EqualTo(3)); + Assert.That(rows[0][0], Is.EqualTo("Alpha")); + Assert.That(rows[1][0], Is.EqualTo("Beta")); + Assert.That(rows[2][0], Is.EqualTo("C")); } [Test] @@ -121,27 +121,27 @@ public void SignedIntegers() RowResult r = ExecuteSelectStatement(GetSession().GetSchema("test").GetTable("test").Select()); var rows = r.FetchAll(); - Assert.AreEqual(5, r.Columns.Count); - Assert.AreEqual(typeof(sbyte), r.Columns[0].ClrType); - Assert.AreEqual(ColumnType.Tinyint, r.Columns[0].Type); - Assert.AreEqual((sbyte)127, rows[0][0]); - Assert.AreEqual((sbyte)-128, rows[1][0]); - Assert.AreEqual(typeof(Int16), r.Columns[1].ClrType); - Assert.AreEqual(ColumnType.Smallint, r.Columns[1].Type); - Assert.AreEqual((short)32767, rows[0][1]); - Assert.AreEqual((short)-32768, rows[1][1]); - Assert.AreEqual(typeof(Int32), r.Columns[2].ClrType); - Assert.AreEqual(ColumnType.Mediumint, r.Columns[2].Type); - Assert.AreEqual(8388607, rows[0][2]); - Assert.AreEqual(-8388608, rows[1][2]); - Assert.AreEqual(typeof(Int32), r.Columns[3].ClrType); - Assert.AreEqual(ColumnType.Int, r.Columns[3].Type); - Assert.AreEqual(2147483647, rows[0][3]); - Assert.AreEqual(-2147483648, rows[1][3]); - Assert.AreEqual(typeof(Int64), r.Columns[4].ClrType); - Assert.AreEqual(ColumnType.Bigint, r.Columns[4].Type); - Assert.AreEqual((long)9223372036854775807, rows[0][4]); - Assert.AreEqual((long)-9223372036854775808, rows[1][4]); + Assert.That(r.Columns.Count, Is.EqualTo(5)); + Assert.That(r.Columns[0].ClrType, Is.EqualTo(typeof(sbyte))); + Assert.That(r.Columns[0].Type, Is.EqualTo(ColumnType.Tinyint)); + Assert.That(rows[0][0], Is.EqualTo((sbyte)127)); + Assert.That(rows[1][0], Is.EqualTo((sbyte)-128)); + Assert.That(r.Columns[1].ClrType, Is.EqualTo(typeof(Int16))); + Assert.That(r.Columns[1].Type, Is.EqualTo(ColumnType.Smallint)); + Assert.That(rows[0][1], Is.EqualTo((short)32767)); + Assert.That(rows[1][1], Is.EqualTo((short)-32768)); + Assert.That(r.Columns[2].ClrType, Is.EqualTo(typeof(Int32))); + Assert.That(r.Columns[2].Type, Is.EqualTo(ColumnType.Mediumint)); + Assert.That(rows[0][2], Is.EqualTo(8388607)); + Assert.That(rows[1][2], Is.EqualTo(-8388608)); + Assert.That(r.Columns[3].ClrType, Is.EqualTo(typeof(Int32))); + Assert.That(r.Columns[3].Type, Is.EqualTo(ColumnType.Int)); + Assert.That(rows[0][3], Is.EqualTo(2147483647)); + Assert.That(rows[1][3], Is.EqualTo(-2147483648)); + Assert.That(r.Columns[4].ClrType, Is.EqualTo(typeof(Int64))); + Assert.That(r.Columns[4].Type, Is.EqualTo(ColumnType.Bigint)); + Assert.That(rows[0][4], Is.EqualTo((long)9223372036854775807)); + Assert.That(rows[1][4], Is.EqualTo((long)-9223372036854775808)); } [Test] @@ -152,22 +152,22 @@ public void UnsignedIntegers() RowResult r = ExecuteSelectStatement(GetSession().GetSchema("test").GetTable("test").Select()); var rows = r.FetchAll(); - Assert.AreEqual(5, r.Columns.Count); - Assert.AreEqual(typeof(byte), r.Columns[0].ClrType); - Assert.AreEqual(ColumnType.Tinyint, r.Columns[0].Type); - Assert.AreEqual((byte)255, rows[0][0]); - Assert.AreEqual(typeof(UInt16), r.Columns[1].ClrType); - Assert.AreEqual(ColumnType.Smallint, r.Columns[1].Type); - Assert.AreEqual((ushort)65535, rows[0][1]); - Assert.AreEqual(typeof(UInt32), r.Columns[2].ClrType); - Assert.AreEqual(ColumnType.Mediumint, r.Columns[2].Type); - Assert.AreEqual((uint)16777215, rows[0][2]); - Assert.AreEqual(typeof(UInt32), r.Columns[3].ClrType); - Assert.AreEqual(ColumnType.Int, r.Columns[3].Type); - Assert.AreEqual((uint)4294967295, rows[0][3]); - Assert.AreEqual(typeof(UInt64), r.Columns[4].ClrType); - Assert.AreEqual(ColumnType.Bigint, r.Columns[4].Type); - Assert.AreEqual((ulong)18446744073709551615, rows[0][4]); + Assert.That(r.Columns.Count, Is.EqualTo(5)); + Assert.That(r.Columns[0].ClrType, Is.EqualTo(typeof(byte))); + Assert.That(r.Columns[0].Type, Is.EqualTo(ColumnType.Tinyint)); + Assert.That(rows[0][0], Is.EqualTo((byte)255)); + Assert.That(r.Columns[1].ClrType, Is.EqualTo(typeof(UInt16))); + Assert.That(r.Columns[1].Type, Is.EqualTo(ColumnType.Smallint)); + Assert.That(rows[0][1], Is.EqualTo((ushort)65535)); + Assert.That(r.Columns[2].ClrType, Is.EqualTo(typeof(UInt32))); + Assert.That(r.Columns[2].Type, Is.EqualTo(ColumnType.Mediumint)); + Assert.That(rows[0][2], Is.EqualTo((uint)16777215)); + Assert.That(r.Columns[3].ClrType, Is.EqualTo(typeof(UInt32))); + Assert.That(r.Columns[3].Type, Is.EqualTo(ColumnType.Int)); + Assert.That(rows[0][3], Is.EqualTo((uint)4294967295)); + Assert.That(r.Columns[4].ClrType, Is.EqualTo(typeof(UInt64))); + Assert.That(r.Columns[4].Type, Is.EqualTo(ColumnType.Bigint)); + Assert.That(rows[0][4], Is.EqualTo((ulong)18446744073709551615)); } [Test] @@ -179,9 +179,9 @@ public void Bit() RowResult r = ExecuteSelectStatement(GetSession().GetSchema("test").GetTable("test").Select()); var rows = r.FetchAll(); Assert.That(r.Columns, Has.One.Items); - Assert.AreEqual(typeof(UInt64), r.Columns[0].ClrType); - Assert.AreEqual(ColumnType.Bit, r.Columns[0].Type); - Assert.AreEqual((ulong)127, rows[0][0]); + Assert.That(r.Columns[0].ClrType, Is.EqualTo(typeof(UInt64))); + Assert.That(r.Columns[0].Type, Is.EqualTo(ColumnType.Bit)); + Assert.That(rows[0][0], Is.EqualTo((ulong)127)); } [Test] @@ -194,14 +194,14 @@ public void Decimal() RowResult r = ExecuteSelectStatement(GetSession().GetSchema("test").GetTable("test").Select()); var rows = r.FetchAll(); Assert.That(r.Columns, Has.One.Items); - Assert.AreEqual(typeof(decimal), r.Columns[0].ClrType); - Assert.AreEqual(ColumnType.Decimal, r.Columns[0].Type); - Assert.AreEqual(-1.23m, rows[0][0]); - Assert.AreEqual(-12.345m, rows[1][0]); - Assert.AreEqual(5m, rows[2][0]); - Assert.AreEqual(43m, rows[3][0]); - Assert.AreEqual(14523.2887238m, rows[4][0]); - Assert.AreEqual(-8947.8923784m, rows[5][0]); + Assert.That(r.Columns[0].ClrType, Is.EqualTo(typeof(decimal))); + Assert.That(r.Columns[0].Type, Is.EqualTo(ColumnType.Decimal)); + Assert.That(rows[0][0], Is.EqualTo(-1.23m)); + Assert.That(rows[1][0], Is.EqualTo(-12.345m)); + Assert.That(rows[2][0], Is.EqualTo(5m)); + Assert.That(rows[3][0], Is.EqualTo(43m)); + Assert.That(rows[4][0], Is.EqualTo(14523.2887238m)); + Assert.That(rows[5][0], Is.EqualTo(-8947.8923784m)); } [Test] @@ -214,10 +214,10 @@ public void Json() RowResult r = ExecuteSelectStatement(GetSession().GetSchema("test").GetTable("test").Select()); var rows = r.FetchAll(); Assert.That(r.Columns, Has.One.Items); - Assert.AreEqual(typeof(string), r.Columns[0].ClrType); - Assert.AreEqual(ColumnType.Json, r.Columns[0].Type); - Assert.AreEqual("{\"id\": 1, \"name\": \"John\"}", rows[0][0]); - Assert.AreEqual("[\"a\", 1, \"b\", 2]", rows[1][0]); + Assert.That(r.Columns[0].ClrType, Is.EqualTo(typeof(string))); + Assert.That(r.Columns[0].Type, Is.EqualTo(ColumnType.Json)); + Assert.That(rows[0][0], Is.EqualTo("{\"id\": 1, \"name\": \"John\"}")); + Assert.That(rows[1][0], Is.EqualTo("[\"a\", 1, \"b\", 2]")); } [Test] @@ -229,9 +229,9 @@ public void Strings() RowResult r = ExecuteSelectStatement(GetSession().GetSchema("test").GetTable("test").Select()); var rows = r.FetchAll(); Assert.That(r.Columns, Has.One.Items); - Assert.AreEqual(typeof(string), r.Columns[0].ClrType); - Assert.AreEqual(ColumnType.String, r.Columns[0].Type); - Assert.AreEqual("表", rows[0][0]); + Assert.That(r.Columns[0].ClrType, Is.EqualTo(typeof(string))); + Assert.That(r.Columns[0].Type, Is.EqualTo(ColumnType.String)); + Assert.That(rows[0][0], Is.EqualTo("表")); } [Test] @@ -244,11 +244,11 @@ public void UnsingedZeroFill() RowResult r = ExecuteSelectStatement(GetSession().GetSchema("test").GetTable("test").Select()); var rows = r.FetchAll(); Assert.That(r.Columns, Has.One.Items); - Assert.AreEqual(typeof(UInt32), r.Columns[0].ClrType); - Assert.AreEqual(ColumnType.Int, r.Columns[0].Type); - Assert.False(r.Columns[0].IsNumberSigned); - Assert.True(r.Columns[0].IsPadded); - Assert.AreEqual("0000000100", rows[0][0].ToString()); + Assert.That(r.Columns[0].ClrType, Is.EqualTo(typeof(UInt32))); + Assert.That(r.Columns[0].Type, Is.EqualTo(ColumnType.Int)); + Assert.That(r.Columns[0].IsNumberSigned, Is.False); + Assert.That(r.Columns[0].IsPadded); + Assert.That(rows[0][0].ToString(), Is.EqualTo("0000000100")); } [Test] @@ -260,9 +260,9 @@ public void Bytes() RowResult r = ExecuteSelectStatement(GetSession().GetSchema("test").GetTable("test").Select()); var rows = r.FetchAll(); Assert.That(r.Columns, Has.One.Items); - Assert.AreEqual(typeof(string), r.Columns[0].ClrType); - Assert.AreEqual(ColumnType.String, r.Columns[0].Type); - Assert.AreEqual("John", rows[0][0]); + Assert.That(r.Columns[0].ClrType, Is.EqualTo(typeof(string))); + Assert.That(r.Columns[0].Type, Is.EqualTo(ColumnType.String)); + Assert.That(rows[0][0], Is.EqualTo("John")); } [Test] @@ -274,9 +274,9 @@ public void BytesUsingCollation() RowResult r = ExecuteSelectStatement(GetSession().GetSchema("test").GetTable("test").Select()); var rows = r.FetchAll(); Assert.That(r.Columns, Has.One.Items); - Assert.AreEqual(typeof(string), r.Columns[0].ClrType); - Assert.AreEqual(ColumnType.String, r.Columns[0].Type); - Assert.AreEqual("Mark", rows[0][0]); + Assert.That(r.Columns[0].ClrType, Is.EqualTo(typeof(string))); + Assert.That(r.Columns[0].Type, Is.EqualTo(ColumnType.String)); + Assert.That(rows[0][0], Is.EqualTo("Mark")); } [Test] @@ -288,10 +288,9 @@ public void Geometry() RowResult r = ExecuteSelectStatement(GetSession().GetSchema("test").GetTable("test").Select()); var rows = r.FetchAll(); Assert.That(r.Columns, Has.One.Items); - Assert.AreEqual(typeof(byte[]), r.Columns[0].ClrType); - Assert.AreEqual(ColumnType.Geometry, r.Columns[0].Type); - Assert.AreEqual("0000000001020000000400000000000000000000000000000000000000000000000000244000000000000024400000000000003440000000000000394000000000000049400000000000004E40", - BitConverter.ToString((byte[])rows[0][0]).Replace("-", "")); + Assert.That(r.Columns[0].ClrType, Is.EqualTo(typeof(byte[]))); + Assert.That(r.Columns[0].Type, Is.EqualTo(ColumnType.Geometry)); + Assert.That(BitConverter.ToString((byte[])rows[0][0]).Replace("-", ""), Is.EqualTo("0000000001020000000400000000000000000000000000000000000000000000000000244000000000000024400000000000003440000000000000394000000000000049400000000000004E40")); } [Test] @@ -302,13 +301,13 @@ public void BlobTypes() RowResult r = ExecuteSelectStatement(GetSession().GetSchema(schemaName).GetTable("test").Select()); var rows = r.FetchAll(); - Assert.AreEqual(2, r.Columns.Count); - Assert.AreEqual(typeof(byte[]), r.Columns[0].ClrType); - Assert.AreEqual(typeof(string), r.Columns[1].ClrType); - Assert.AreEqual(ColumnType.Bytes, r.Columns[0].Type); - Assert.AreEqual(ColumnType.String, r.Columns[1].Type); - Assert.AreEqual(CharSetMap.GetEncoding(r.Columns[0].CharacterSetName).GetBytes("Car"), rows[0][0]); - Assert.AreEqual("Plane", rows[0][1]); + Assert.That(r.Columns.Count, Is.EqualTo(2)); + Assert.That(r.Columns[0].ClrType, Is.EqualTo(typeof(byte[]))); + Assert.That(r.Columns[1].ClrType, Is.EqualTo(typeof(string))); + Assert.That(r.Columns[0].Type, Is.EqualTo(ColumnType.Bytes)); + Assert.That(r.Columns[1].Type, Is.EqualTo(ColumnType.String)); + Assert.That(rows[0][0], Is.EqualTo(CharSetMap.GetEncoding(r.Columns[0].CharacterSetName).GetBytes("Car"))); + Assert.That(rows[0][1], Is.EqualTo("Plane")); } } } diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/DateTimeTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/DateTimeTests.cs index 8ae4ee483..cfaefd5f7 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/DateTimeTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/DateTimeTests.cs @@ -47,12 +47,12 @@ public void DateTime() RowResult r = ExecuteSelectStatement(GetSession().GetSchema("test").GetTable("test").Select("dt")); var rows = r.FetchAll(); Assert.That(r.Columns, Has.One.Items); - Assert.AreEqual(typeof(DateTime), r.Columns[0].ClrType); - Assert.AreEqual(ColumnType.DateTime, r.Columns[0].Type); + Assert.That(r.Columns[0].ClrType, Is.EqualTo(typeof(DateTime))); + Assert.That(r.Columns[0].Type, Is.EqualTo(ColumnType.DateTime)); Assert.That(rows, Has.One.Items); DateTime dt = (DateTime)rows[0]["dt"]; DateTime test = new DateTime(2001, 2, 3, 4, 5, 6); - Assert.AreEqual(test, dt); + Assert.That(dt, Is.EqualTo(test)); } [Test] @@ -64,12 +64,12 @@ public void Date() RowResult r = ExecuteSelectStatement(GetSession().GetSchema("test").GetTable("test").Select("dt")); var rows = r.FetchAll(); Assert.That(r.Columns, Has.One.Items); - Assert.AreEqual(typeof(DateTime), r.Columns[0].ClrType); - Assert.AreEqual(ColumnType.Date, r.Columns[0].Type); + Assert.That(r.Columns[0].ClrType, Is.EqualTo(typeof(DateTime))); + Assert.That(r.Columns[0].Type, Is.EqualTo(ColumnType.Date)); Assert.That(rows, Has.One.Items); DateTime dt = (DateTime)rows[0]["dt"]; DateTime test = new DateTime(2001, 2, 3); - Assert.AreEqual(test, dt); + Assert.That(dt, Is.EqualTo(test)); } [Test] @@ -81,13 +81,13 @@ public void Timestamp() RowResult r = ExecuteSelectStatement(GetSession().GetSchema("test").GetTable("test").Select("dt")); var rows = r.FetchAll(); Assert.That(r.Columns, Has.One.Items); - Assert.AreEqual(typeof(DateTime), r.Columns[0].ClrType); + Assert.That(r.Columns[0].ClrType, Is.EqualTo(typeof(DateTime))); //TODO: this should support timestamp - Assert.AreEqual(ColumnType.Timestamp, r.Columns[0].Type); + Assert.That(r.Columns[0].Type, Is.EqualTo(ColumnType.Timestamp)); Assert.That(rows, Has.One.Items); DateTime dt = (DateTime)rows[0]["dt"]; DateTime test = new DateTime(2001, 2, 3); - Assert.AreEqual(test, dt); + Assert.That(dt, Is.EqualTo(test)); } [Test] @@ -99,12 +99,12 @@ public void Time() RowResult r = ExecuteSelectStatement(GetSession().GetSchema("test").GetTable("test").Select("dt")); var rows = r.FetchAll(); Assert.That(r.Columns, Has.One.Items); - Assert.AreEqual(typeof(TimeSpan), r.Columns[0].ClrType); - Assert.AreEqual(ColumnType.Time, r.Columns[0].Type); + Assert.That(r.Columns[0].ClrType, Is.EqualTo(typeof(TimeSpan))); + Assert.That(r.Columns[0].Type, Is.EqualTo(ColumnType.Time)); Assert.That(rows, Has.One.Items); TimeSpan t = (TimeSpan)rows[0]["dt"]; TimeSpan test = new TimeSpan(1, 2, 3); - Assert.AreEqual(test, t); + Assert.That(t, Is.EqualTo(test)); } [Test] @@ -116,12 +116,12 @@ public void NegativeTime() RowResult r = ExecuteSelectStatement(GetSession().GetSchema("test").GetTable("test").Select("dt")); var rows = r.FetchAll(); Assert.That(r.Columns, Has.One.Items); - Assert.AreEqual(typeof(TimeSpan), r.Columns[0].ClrType); - Assert.AreEqual(ColumnType.Time, r.Columns[0].Type); + Assert.That(r.Columns[0].ClrType, Is.EqualTo(typeof(TimeSpan))); + Assert.That(r.Columns[0].Type, Is.EqualTo(ColumnType.Time)); Assert.That(rows, Has.One.Items); TimeSpan t = (TimeSpan)rows[0]["dt"]; TimeSpan test = new TimeSpan(-1, 2, 3); - Assert.AreEqual(test, t); + Assert.That(t, Is.EqualTo(test)); } } } diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/RelationalGCTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/RelationalGCTests.cs index 34d1aaa12..f5e731796 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/RelationalGCTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/RelationalGCTests.cs @@ -48,10 +48,10 @@ public void FetchAllNoReference() WeakReference wr = new WeakReference(result); result = null; GC.Collect(); - Assert.False(wr.IsAlive); - Assert.AreEqual(2, rows.Count); - Assert.AreEqual(22, rows[0]["age"]); - Assert.AreEqual("Patric", rows[1]["name"]); + Assert.That(wr.IsAlive, Is.False); + Assert.That(rows.Count, Is.EqualTo(2)); + Assert.That(rows[0]["age"], Is.EqualTo(22)); + Assert.That(rows[1]["name"], Is.EqualTo("Patric")); } #endif } diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/RowBufferingTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/RowBufferingTests.cs index 3809bb29b..7724b265b 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/RowBufferingTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/RowBufferingTests.cs @@ -43,15 +43,15 @@ public void SmartBuffering() ExecuteSQL("INSERT INTO test2 VALUES (1,0)"); var rowResult = ExecuteSelectStatement(testSchema.GetTable("test1").Select("id")); - Assert.AreEqual(0, rowResult.IndexOf("id")); + Assert.That(rowResult.IndexOf("id"), Is.EqualTo(0)); foreach (var row in rowResult) { var result = ExecuteUpdateStatement(testSchema.GetTable("test2").Update().Where("id=1").Set("val", row["id"])); - Assert.AreEqual(1, result.AffectedItemsCount); + Assert.That(result.AffectedItemsCount, Is.EqualTo(1)); } Row valRow = ExecuteSelectStatement(testSchema.GetTable("test2").Select("val")).FetchOne(); - Assert.AreEqual(4, valRow[0]); + Assert.That(valRow[0], Is.EqualTo(4)); } } } diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/SqlTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/SqlTests.cs index 4ffb01a71..d5c906c3c 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/SqlTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/SqlTests.cs @@ -54,9 +54,9 @@ public void ReturnSimpleScalar() using (var ss = MySQLX.GetSession(ConnectionString)) { SqlResult r = ss.SQL("SELECT * FROM test.test").Execute(); - Assert.True(r.Next()); - Assert.AreEqual(1, r[0]); - Assert.False(r.NextResult()); + Assert.That(r.Next()); + Assert.That(r[0], Is.EqualTo(1)); + Assert.That(r.NextResult(), Is.False); } } @@ -68,13 +68,13 @@ public void ExecuteStoredProcedure() Session session = GetSession(true); var result = ExecuteSQLStatement(session.SQL("CALL my_proc()")); - Assert.True(result.HasData); + Assert.That(result.HasData); var row = result.FetchOne(); - Assert.NotNull(row); - Assert.AreEqual((sbyte)5, row[0]); - Assert.False(result.Next()); - Assert.Null(result.FetchOne()); - Assert.False(result.NextResult()); + Assert.That(row, Is.Not.Null); + Assert.That(row[0], Is.EqualTo((sbyte)5)); + Assert.That(result.Next(), Is.False); + Assert.That(result.FetchOne(), Is.Null); + Assert.That(result.NextResult(), Is.False); } [Test] @@ -85,28 +85,28 @@ public void ExecuteStoredProcedureMultipleResults() Session session = GetSession(true); var result = ExecuteSQLStatement(session.SQL("CALL my_proc()")); - Assert.True(result.HasData); + Assert.That(result.HasData); var row = result.FetchOne(); - Assert.NotNull(row); - Assert.AreEqual((sbyte)5, row[0]); - Assert.False(result.Next()); - Assert.Null(result.FetchOne()); + Assert.That(row, Is.Not.Null); + Assert.That(row[0], Is.EqualTo((sbyte)5)); + Assert.That(result.Next(), Is.False); + Assert.That(result.FetchOne(), Is.Null); - Assert.True(result.NextResult()); + Assert.That(result.NextResult()); row = result.FetchOne(); - Assert.NotNull(row); - Assert.AreEqual("A", row[0]); - Assert.False(result.Next()); - Assert.Null(result.FetchOne()); + Assert.That(row, Is.Not.Null); + Assert.That(row[0], Is.EqualTo("A")); + Assert.That(result.Next(), Is.False); + Assert.That(result.FetchOne(), Is.Null); - Assert.True(result.NextResult()); + Assert.That(result.NextResult()); row = result.FetchOne(); - Assert.NotNull(row); - Assert.AreEqual((sbyte)10, row[0]); - Assert.False(result.Next()); - Assert.Null(result.FetchOne()); + Assert.That(row, Is.Not.Null); + Assert.That(row[0], Is.EqualTo((sbyte)10)); + Assert.That(result.Next(), Is.False); + Assert.That(result.FetchOne(), Is.Null); - Assert.False(result.NextResult()); + Assert.That(result.NextResult(), Is.False); } [Test] @@ -120,10 +120,10 @@ public void Bind() .Bind(++i, ((char)('@' + i)).ToString())); SqlResult result = ExecuteSQLStatement(GetSession(true).SQL("select * from test.test where id=?").Bind(5)); - Assert.True(result.Next()); + Assert.That(result.Next()); Assert.That(result.Rows, Has.One.Items); - Assert.AreEqual(5, result[0]); - Assert.AreEqual("E", result[1]); + Assert.That(result[0], Is.EqualTo(5)); + Assert.That(result[1], Is.EqualTo("E")); } [Test] @@ -134,12 +134,12 @@ public void BindNull() var session = GetSession(true); var result = ExecuteSQLStatement(session.SQL("INSERT INTO test.test VALUES(1, ?), (2, 'B');").Bind(null)); - Assert.AreEqual(2ul, result.AffectedItemsCount); + Assert.That(result.AffectedItemsCount, Is.EqualTo(2ul)); var sqlResult = ExecuteSQLStatement(session.SQL("SELECT * FROM test.test WHERE letter is ?").Bind(null)).FetchAll(); Assert.That(sqlResult, Has.One.Items); - Assert.AreEqual(1, sqlResult[0][0]); - Assert.Null(sqlResult[0][1]); + Assert.That(sqlResult[0][0], Is.EqualTo(1)); + Assert.That(sqlResult[0][1], Is.Null); } [Test] @@ -148,7 +148,7 @@ public void Alias() var session = GetSession(true); var stmt = ExecuteSQLStatement(session.SQL("SELECT 1 AS UNO")); var result = stmt.FetchAll(); - Assert.AreEqual("UNO", stmt.Columns[0].ColumnLabel); + Assert.That(stmt.Columns[0].ColumnLabel, Is.EqualTo("UNO")); } #region WL14389 @@ -163,7 +163,7 @@ public void ProcedureWithNoTable() var sqlRes = session.SQL("call newproc(?, ?)").Bind(10).Bind("X").Execute(); var ex = Assert.Throws(() => session.SQL("drop procedure if exists newproc ").Execute()); - StringAssert.AreEqualIgnoringCase("Table 'test.notab' doesn't exist", ex.Message); + Assert.That(ex.Message, Is.EqualTo("Table 'test.notab' doesn't exist").IgnoreCase); } [Test, Description("Stored Procedure Table Positive using Session")] @@ -199,13 +199,13 @@ public void TablePositiveSession() do { if (row[0] != null) - Assert.IsNotNull(row[0].ToString()); + Assert.That(row[0].ToString(), Is.Not.Null); if (row[1] != null) - Assert.IsNotNull(row[1].ToString()); + Assert.That(row[1].ToString(), Is.Not.Null); if (row[2] != null) - Assert.IsNotNull(row[2].ToString()); + Assert.That(row[2].ToString(), Is.Not.Null); } while (res.Next()); while (res.NextResult()) ; } @@ -293,13 +293,13 @@ public void StoredProcTablePositiveStringBuilderSession() do { if (row[0] != null) - Assert.IsNotNull(row[0].ToString()); + Assert.That(row[0].ToString(), Is.Not.Null); if (row[1] != null) - Assert.IsNotNull(row[1].ToString()); + Assert.That(row[1].ToString(), Is.Not.Null); if (row[2] != null) - Assert.IsNotNull(row[2].ToString()); + Assert.That(row[2].ToString(), Is.Not.Null); } while (res.Next()); while (res.NextResult()) ; } @@ -382,7 +382,7 @@ public void StoredProcReturnsNull() if (res.HasData) { var row = res.FetchOne(); - Assert.IsNull(row); + Assert.That(row, Is.Null); } res.Next(); res.NextResult(); @@ -417,7 +417,7 @@ public void BindSupportSessionSQLNumericDatatypes() myResult = sessionTest.SQL("SELECT @my_var").Execute(); // Gets the row and prints the first column row = myResult.FetchOne(); - Assert.IsNotNull(row[0].ToString()); + Assert.That(row[0].ToString(), Is.Not.Null); sessionTest.SQL("DROP DATABASE DBName").Execute(); } @@ -440,7 +440,7 @@ public void BindSupportSessionSQLNumericDatatypes() myResult = sessionTest.SQL("SELECT @my_var").Execute(); // Gets the row and prints the first column row = myResult.FetchOne(); - Assert.IsNotNull(row[0].ToString()); + Assert.That(row[0].ToString(), Is.Not.Null); sessionTest.SQL("DROP DATABASE DBName").Execute(); } @@ -462,7 +462,7 @@ public void BindSupportSessionSQLNumericDatatypes() myResult = sessionTest.SQL("SELECT @my_var").Execute(); // Gets the row and prints the first column row = myResult.FetchOne(); - Assert.IsNotNull(row[0].ToString()); + Assert.That(row[0].ToString(), Is.Not.Null); sessionTest.SQL("DROP DATABASE DBName").Execute(); } @@ -484,7 +484,7 @@ public void BindSupportSessionSQLNumericDatatypes() myResult = sessionTest.SQL("SELECT @my_var").Execute(); // Gets the row and prints the first column row = myResult.FetchOne(); - Assert.IsNotNull(row[0].ToString()); + Assert.That(row[0].ToString(), Is.Not.Null); sessionTest.SQL("DROP DATABASE DBName").Execute(); } @@ -506,7 +506,7 @@ public void BindSupportSessionSQLNumericDatatypes() myResult = sessionTest.SQL("SELECT @my_var").Execute(); // Gets the row and prints the first column row = myResult.FetchOne(); - Assert.IsNotNull(row[0].ToString()); + Assert.That(row[0].ToString(), Is.Not.Null); sessionTest.SQL("DROP DATABASE DBName").Execute(); } @@ -528,7 +528,7 @@ public void BindSupportSessionSQLNumericDatatypes() myResult = sessionTest.SQL("SELECT @my_var").Execute(); // Gets the row and prints the first column row = myResult.FetchOne(); - Assert.IsNotNull(row[0].ToString()); + Assert.That(row[0].ToString(), Is.Not.Null); sessionTest.SQL("DROP DATABASE DBName").Execute(); } @@ -550,7 +550,7 @@ public void BindSupportSessionSQLNumericDatatypes() myResult = sessionTest.SQL("SELECT @my_var").Execute(); // Gets the row and prints the first column row = myResult.FetchOne(); - Assert.IsNotNull(row[0].ToString()); + Assert.That(row[0].ToString(), Is.Not.Null); sessionTest.SQL("DROP DATABASE DBName").Execute(); } @@ -572,7 +572,7 @@ public void BindSupportSessionSQLNumericDatatypes() myResult = sessionTest.SQL("SELECT @my_var").Execute(); // Gets the row and prints the first column row = myResult.FetchOne(); - Assert.IsNotNull(row[0].ToString()); + Assert.That(row[0].ToString(), Is.Not.Null); sessionTest.SQL("DROP DATABASE DBName").Execute(); } } @@ -605,7 +605,7 @@ public void BindSupportSessionSQLDateTimetypes() myResult = sessionTest.SQL("SELECT @my_var").Execute(); // Gets the row and prints the first column row = myResult.FetchOne(); - Assert.IsNotNull(row[0].ToString()); + Assert.That(row[0].ToString(), Is.Not.Null); sessionTest.SQL("DROP DATABASE DBName").Execute(); } @@ -627,7 +627,7 @@ public void BindSupportSessionSQLDateTimetypes() myResult = sessionTest.SQL("SELECT @my_var").Execute(); // Gets the row and prints the first column row = myResult.FetchOne(); - Assert.IsNotNull(row[0].ToString()); + Assert.That(row[0].ToString(), Is.Not.Null); sessionTest.SQL("DROP DATABASE DBName").Execute(); } @@ -649,7 +649,7 @@ public void BindSupportSessionSQLDateTimetypes() myResult = sessionTest.SQL("SELECT @my_var").Execute(); // Gets the row and prints the first column row = myResult.FetchOne(); - Assert.IsNotNull(row[0].ToString()); + Assert.That(row[0].ToString(), Is.Not.Null); sessionTest.SQL("DROP DATABASE DBName").Execute(); } @@ -671,7 +671,7 @@ public void BindSupportSessionSQLDateTimetypes() myResult = sessionTest.SQL("SELECT @my_var").Execute(); // Gets the row and prints the first column row = myResult.FetchOne(); - Assert.IsNotNull(row[0].ToString()); + Assert.That(row[0].ToString(), Is.Not.Null); sessionTest.SQL("DROP DATABASE DBName").Execute(); } @@ -693,7 +693,7 @@ public void BindSupportSessionSQLDateTimetypes() myResult = sessionTest.SQL("SELECT @my_var").Execute(); // Gets the row and prints the first column row = myResult.FetchOne(); - Assert.IsNotNull(row[0].ToString()); + Assert.That(row[0].ToString(), Is.Not.Null); sessionTest.SQL("DROP DATABASE DBName").Execute(); } } @@ -726,7 +726,7 @@ public void BindSupportSessionSQLStringtypes() myResult = sessionTest.SQL("SELECT @my_var").Execute(); // Gets the row and prints the first column row = myResult.FetchOne(); - Assert.IsNotNull(row[0].ToString()); + Assert.That(row[0].ToString(), Is.Not.Null); sessionTest.SQL("DROP DATABASE DBName").Execute(); } @@ -748,7 +748,7 @@ public void BindSupportSessionSQLStringtypes() myResult = sessionTest.SQL("SELECT @my_var").Execute(); // Gets the row and prints the first column row = myResult.FetchOne(); - Assert.IsNotNull(row[0].ToString()); + Assert.That(row[0].ToString(), Is.Not.Null); sessionTest.SQL("DROP DATABASE DBName").Execute(); } @@ -770,7 +770,7 @@ public void BindSupportSessionSQLStringtypes() myResult = sessionTest.SQL("SELECT @my_var").Execute(); // Gets the row and prints the first column row = myResult.FetchOne(); - Assert.IsNotNull(row[0].ToString()); + Assert.That(row[0].ToString(), Is.Not.Null); sessionTest.SQL("DROP DATABASE DBName").Execute(); } @@ -792,7 +792,7 @@ public void BindSupportSessionSQLStringtypes() myResult = sessionTest.SQL("SELECT @my_var").Execute(); // Gets the row and prints the first column row = myResult.FetchOne(); - Assert.IsNotNull(row[0].ToString()); + Assert.That(row[0].ToString(), Is.Not.Null); sessionTest.SQL("DROP DATABASE DBName").Execute(); } @@ -814,7 +814,7 @@ public void BindSupportSessionSQLStringtypes() myResult = sessionTest.SQL("SELECT @my_var").Execute(); // Gets the row and prints the first column row = myResult.FetchOne(); - Assert.IsNotNull(row[0].ToString()); + Assert.That(row[0].ToString(), Is.Not.Null); sessionTest.SQL("DROP DATABASE DBName").Execute(); } @@ -836,7 +836,7 @@ public void BindSupportSessionSQLStringtypes() myResult = sessionTest.SQL("SELECT @my_var").Execute(); // Gets the row and prints the first column row = myResult.FetchOne(); - Assert.IsNotNull(row[0].ToString()); + Assert.That(row[0].ToString(), Is.Not.Null); sessionTest.SQL("DROP DATABASE DBName").Execute(); } @@ -858,7 +858,7 @@ public void BindSupportSessionSQLStringtypes() myResult = sessionTest.SQL("SELECT @my_var").Execute(); // Gets the row and prints the first column row = myResult.FetchOne(); - Assert.IsNotNull(row[0].ToString()); + Assert.That(row[0].ToString(), Is.Not.Null); sessionTest.SQL("DROP DATABASE DBName").Execute(); } } @@ -941,15 +941,15 @@ public void MixedChainedCommands() RowResult r = session.GetSchema("test").GetTable("test").Select("c1").Execute(); var rows = r.FetchAll(); - Assert.AreEqual(1, r.Columns.Count, "Matching"); - Assert.AreEqual(typeof(float).ToString(), r.Columns[0].ClrType.ToString(), "Matching"); - Assert.AreEqual(MySqlDbType.Float.ToString(), r.Columns[0].Type.ToString(), "Matching"); - Assert.AreEqual(14, (int)r.Columns[0].Length, "Matching"); - Assert.AreEqual(8, (int)r.Columns[0].FractionalDigits, "Matching"); - Assert.AreEqual(3, rows.Count, "Matching"); - Assert.AreEqual(22.7f, (float)rows[0][0], "Matching"); - Assert.AreEqual(-100000.38984f, (float)rows[1][0], "Matching"); - Assert.AreEqual(0f, (float)rows[2][0], "Matching"); + Assert.That(r.Columns.Count, Is.EqualTo(1), "Matching"); + Assert.That(r.Columns[0].ClrType.ToString(), Is.EqualTo(typeof(float).ToString()), "Matching"); + Assert.That(r.Columns[0].Type.ToString(), Is.EqualTo(MySqlDbType.Float.ToString()), "Matching"); + Assert.That((int)r.Columns[0].Length, Is.EqualTo(14), "Matching"); + Assert.That((int)r.Columns[0].FractionalDigits, Is.EqualTo(8), "Matching"); + Assert.That(rows.Count, Is.EqualTo(3), "Matching"); + Assert.That((float)rows[0][0], Is.EqualTo(22.7f), "Matching"); + Assert.That((float)rows[1][0], Is.EqualTo(-100000.38984f), "Matching"); + Assert.That((float)rows[2][0], Is.EqualTo(0f), "Matching"); } [Test, Description("Test MySQLX plugin MySQL Date Time Bug")] @@ -961,7 +961,7 @@ public void DateTimeCheck() RowResult r = session.GetSchema("test").GetTable("test1212").Select("dt").Execute(); var rows = r.FetchAll(); - Assert.AreEqual(1, r.Columns.Count, "Matching Coulumn Count"); + Assert.That(r.Columns.Count, Is.EqualTo(1), "Matching Coulumn Count"); } @@ -974,7 +974,7 @@ public void DateTimeJSON() ExecuteSQL(@"INSERT INTO test.test VALUES(100000,' { ""name"" : ""bob"",""Date"": ""2015-10-09"",""Time"": ""12:18:29.000000"",""DateTimeOfRegistration"": ""2015-10-09 12:18:29.000000"",""age"":12} ')"); RowResult r = session.GetSchema("test").GetTable("test").Select("jsoncolumn").Execute(); var rows = r.FetchAll(); - Assert.AreEqual(1, r.Columns.Count, "Matching"); + Assert.That(r.Columns.Count, Is.EqualTo(1), "Matching"); } [Test, Description("Test MySQLX plugin JSON Variant")] @@ -988,7 +988,7 @@ public void JSONVariant() ExecuteSQL(@"INSERT INTO test VALUES (2, '[""a"", {""b"": [true, false]}, [10, 20]]')"); ExecuteSQL(@"INSERT INTO test VALUES (3, '{""id"":1,""name"":""test""}')"); var r = ExecuteSQL(@"SELECT JSON_EXTRACT('{""id"": 1, ""name"": ""test""}','$.name')").FetchOne(); - Assert.AreEqual("\"test\"", r[0]); + Assert.That(r[0], Is.EqualTo("\"test\"")); } [Test, Description("Test MySQLX plugin big int as PK")] @@ -1000,9 +1000,9 @@ public void BigIntasPK() ExecuteSQL("DROP TABLE IF EXISTS Test"); ExecuteSQL("CREATE TABLE test (Id bigint NOT NULL PRIMARY KEY, jsoncolumn JSON)"); var res = ExecuteSQL("INSERT INTO test VALUES (934157136952, '[1]')"); - Assert.AreEqual(1, res.AffectedItemsCount); + Assert.That(res.AffectedItemsCount, Is.EqualTo(1)); res = ExecuteSQL(@"INSERT INTO test VALUES (9223372036854775807, '[""a"", {""b"": [true, false]}, [10, 20]]')"); - Assert.AreEqual(1, res.AffectedItemsCount); + Assert.That(res.AffectedItemsCount, Is.EqualTo(1)); Assert.Throws(() => ExecuteSQL("INSERT INTO test VALUES ('str1', '[1]')")); } @@ -1017,9 +1017,9 @@ public void TinyIntasPK() ss.SQL("DROP TABLE IF EXISTS test.test").Execute(); ss.SQL("CREATE TABLE test.test (Id tinyint NOT NULL PRIMARY KEY, jsoncolumn JSON)").Execute(); var res = ss.SQL("INSERT INTO test.test VALUES (1, '[1]')").Execute(); - Assert.AreEqual(1, res.AffectedItemsCount); + Assert.That(res.AffectedItemsCount, Is.EqualTo(1)); res = ss.SQL(@"INSERT INTO test.test VALUES (2, '[""a"", {""b"": [true, false]}, [10, 20]]')").Execute(); - Assert.AreEqual(1, res.AffectedItemsCount); + Assert.That(res.AffectedItemsCount, Is.EqualTo(1)); Assert.Throws(() => ss.SQL("INSERT INTO test.test VALUES ('str1', '[1]')").Execute()); } } @@ -1035,9 +1035,9 @@ public void SmallIntasPK() ss.SQL("DROP TABLE IF EXISTS test.test").Execute(); ss.SQL("CREATE TABLE test.test (Id smallint NOT NULL PRIMARY KEY, jsoncolumn JSON)").Execute(); var res = ss.SQL("INSERT INTO test.test VALUES (99, '[1]')").Execute(); - Assert.AreEqual(1, res.AffectedItemsCount); + Assert.That(res.AffectedItemsCount, Is.EqualTo(1)); res = ss.SQL(@"INSERT INTO test.test VALUES (1, '[""a"", {""b"": [true, false]}, [10, 20]]')").Execute(); - Assert.AreEqual(1, res.AffectedItemsCount); + Assert.That(res.AffectedItemsCount, Is.EqualTo(1)); Assert.Throws(() => ss.SQL("INSERT INTO test.test VALUES ('str1', '[1]')").Execute()); ss.SQL("DROP TABLE IF EXISTS test.test"); } @@ -1057,7 +1057,7 @@ public void DataValidation() while (result.Next()) { Assert.That(result.Rows, Has.Exactly(3).Items); - Assert.True(expecteddataValue.Contains(result[0].ToString())); + Assert.That(expecteddataValue.Contains(result[0].ToString())); } } } diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/TableAsyncTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/TableAsyncTests.cs index c071fecbb..7cfcd16d1 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/TableAsyncTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/TableAsyncTests.cs @@ -58,8 +58,8 @@ public void MultipleTableInsertAsync() tasksList.Add(table.Insert().Values(i, i % 250).ExecuteAsync()); } - Assert.True(Task.WaitAll(tasksList.ToArray(), TimeSpan.FromMinutes(2)), "WaitAll timeout"); - Assert.AreEqual(200, table.Count()); + Assert.That(Task.WaitAll(tasksList.ToArray(), TimeSpan.FromMinutes(2)), "WaitAll timeout"); + Assert.That(table.Count(), Is.EqualTo(200)); } [Test] @@ -83,16 +83,16 @@ public void MultipleTableSelectAsync() tasksList.Add(table.Select().Where("age = :age").Bind("aGe", i).ExecuteAsync()); } - Assert.True(Task.WaitAll(tasksList.ToArray(), TimeSpan.FromMinutes(2)), "WaitAll timeout"); + Assert.That(Task.WaitAll(tasksList.ToArray(), TimeSpan.FromMinutes(2)), "WaitAll timeout"); foreach (Task task in tasksList) { - Assert.AreEqual(2, task.Result.Columns.Count); + Assert.That(task.Result.Columns.Count, Is.EqualTo(2)); Assert.That(task.Result.Rows, Has.One.Items); int value = (int)task.Result.Rows[0][1]; - Assert.False(validator.Contains(value), value + " value exists"); + Assert.That(validator.Contains(value), Is.False, value + " value exists"); validator.Add(value); } - Assert.AreEqual(rows, validator.Count); + Assert.That(validator.Count, Is.EqualTo(rows)); } #region WL14389 [Test, Description("Table.Select() with shared lock and Table.Update() ")] @@ -116,7 +116,7 @@ private Task SubProcess1() } catch (MySqlException ex) { - Assert.True(ex.Message.Contains("Duplicate")); + Assert.That(ex.Message.Contains("Duplicate")); } var table2 = session2.GetSchema("test").GetTable("test"); @@ -124,7 +124,7 @@ private Task SubProcess1() for (var i = 0; i < 1000; i++) { var result = table2.Update().Where("id = 1").Set("age", 2).Execute(); - Assert.IsNotNull(result); + Assert.That(result, Is.Not.Null); } } @@ -149,7 +149,7 @@ private Task SubProcess2() } catch (MySqlException ex) { - Assert.True(ex.Message.Contains("Duplicate")); + Assert.That(ex.Message.Contains("Duplicate")); } var table2 = session2.GetSchema("test").GetTable("test"); diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/TableDeleteTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/TableDeleteTests.cs index 508eefec0..a423a0723 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/TableDeleteTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/TableDeleteTests.cs @@ -51,7 +51,7 @@ public void SetUp() insertStatement.Values(i, i); } ExecuteInsertStatement(insertStatement); - Assert.AreEqual(rowsToInsert, CountRows()); + Assert.That(CountRows(), Is.EqualTo(rowsToInsert)); } private long CountRows() @@ -62,7 +62,7 @@ private long CountRows() private void ExecuteDelete(TableDeleteStatement statement, int expectedRowsCount) { Result result = ExecuteDeleteStatement(statement); - Assert.AreEqual(expectedRowsCount, CountRows()); + Assert.That(CountRows(), Is.EqualTo(expectedRowsCount)); } [Test] @@ -101,17 +101,17 @@ public void DeleteBindTest() public void DeleteWithInOperator() { Table table = testSchema.GetTable("test"); - Assert.AreEqual(10, CountRows()); + Assert.That(CountRows(), Is.EqualTo(10)); - Assert.AreEqual(2, ExecuteDeleteStatement(table.Delete().Where("id IN (1,2)")).AffectedItemsCount); - Assert.AreEqual(8, CountRows()); + Assert.That(ExecuteDeleteStatement(table.Delete().Where("id IN (1,2)")).AffectedItemsCount, Is.EqualTo(2)); + Assert.That(CountRows(), Is.EqualTo(8)); Assert.Throws(() => ExecuteDeleteStatement(table.Delete().Where("a IN [3]"))); Assert.Throws(() => ExecuteDeleteStatement(table.Delete().Where("3 IN a"))); Assert.Throws(() => ExecuteDeleteStatement(table.Delete().Where("age IN [3]"))); - Assert.AreEqual(1, ExecuteDeleteStatement(table.Delete().Where("age IN (3)")).AffectedItemsCount); - Assert.AreEqual(7, CountRows()); + Assert.That(ExecuteDeleteStatement(table.Delete().Where("age IN (3)")).AffectedItemsCount, Is.EqualTo(1)); + Assert.That(CountRows(), Is.EqualTo(7)); } } } diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/TableInsertTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/TableInsertTests.cs index d831154fd..206563e21 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/TableInsertTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/TableInsertTests.cs @@ -52,17 +52,17 @@ public void InsertMultipleValues() .Values("Henry", "22") .Values("Patric", 30) ); - Assert.AreEqual(2, result.AffectedItemsCount); + Assert.That(result.AffectedItemsCount, Is.EqualTo(2)); var selectResult = ExecuteSelectStatement(table.Select()); while (selectResult.Next()) ; - Assert.AreEqual(2, selectResult.Rows.Count); - Assert.AreEqual("Henry", selectResult.Rows.ToArray()[0][0]); - Assert.AreEqual(22, selectResult.Rows.ToArray()[0][1]); - Assert.AreEqual("Patric", selectResult.Rows.ToArray()[1][0]); - Assert.AreEqual(30, selectResult.Rows.ToArray()[1][1]); + Assert.That(selectResult.Rows.Count, Is.EqualTo(2)); + Assert.That(selectResult.Rows.ToArray()[0][0], Is.EqualTo("Henry")); + Assert.That(selectResult.Rows.ToArray()[0][1], Is.EqualTo(22)); + Assert.That(selectResult.Rows.ToArray()[1][0], Is.EqualTo("Patric")); + Assert.That(selectResult.Rows.ToArray()[1][1], Is.EqualTo(30)); - Assert.AreEqual(2, table.Count()); + Assert.That(table.Count(), Is.EqualTo(2)); } [Test] @@ -72,13 +72,13 @@ public void InsertExpressions() Table table = testSchema.GetTable("test"); var result = ExecuteInsertStatement(table.Insert("name", "age").Values("MARK", "34")); - Assert.AreEqual(1, result.AffectedItemsCount); + Assert.That(result.AffectedItemsCount, Is.EqualTo(1)); var selectResult = ExecuteSelectStatement(table.Select()); while (selectResult.Next()) ; Assert.That(selectResult.Rows, Has.One.Items); - Assert.AreEqual("MARK", selectResult.Rows.ToArray()[0][0]); - Assert.AreEqual(34, selectResult.Rows.ToArray()[0][1]); + Assert.That(selectResult.Rows.ToArray()[0][0], Is.EqualTo("MARK")); + Assert.That(selectResult.Rows.ToArray()[0][1], Is.EqualTo(34)); } [Test] @@ -89,10 +89,10 @@ public void ReuseStatement() var stmt = table.Insert("name", "age"); var result = ExecuteInsertStatement(stmt.Values("MARK", "34")); - Assert.AreEqual(1, result.AffectedItemsCount); + Assert.That(result.AffectedItemsCount, Is.EqualTo(1)); // error 5014 - Wrong number of fields in row being inserted - Assert.AreEqual(5014u, Assert.Throws(() => result = ExecuteInsertStatement(stmt.Values("George", 34, 1))).Code); - Assert.AreEqual(5014u, Assert.Throws(() => ExecuteInsertStatement(stmt.Values("George", 34))).Code); + Assert.That(Assert.Throws(() => result = ExecuteInsertStatement(stmt.Values("George", 34, 1))).Code, Is.EqualTo(5014u)); + Assert.That(Assert.Throws(() => ExecuteInsertStatement(stmt.Values("George", 34))).Code, Is.EqualTo(5014u)); Assert.That(ExecuteSelectStatement(table.Select()).FetchAll(), Has.One.Items); } @@ -117,10 +117,10 @@ public void InsertWithExpressionsAlikeValues(string specialChar) var selectResult = ExecuteSelectStatement(table.Select()); while (selectResult.Next()) ; - Assert.AreEqual(1, insertResult.AffectedItemsCount); + Assert.That(insertResult.AffectedItemsCount, Is.EqualTo(1)); Assert.That(selectResult.Rows, Has.One.Items); - StringAssert.AreEqualIgnoringCase("1", selectResult.Rows.ToArray()[0][0].ToString()); - StringAssert.AreEqualIgnoringCase(value, selectResult.Rows.ToArray()[0][1].ToString()); + Assert.That(selectResult.Rows.ToArray()[0][0].ToString(), Is.EqualTo("1").IgnoreCase); + Assert.That(selectResult.Rows.ToArray()[0][1].ToString(), Is.EqualTo(value).IgnoreCase); } } } diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/TableSelectTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/TableSelectTests.cs index 693435fc1..78ef32930 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/TableSelectTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/TableSelectTests.cs @@ -69,7 +69,7 @@ public void TearDown() public void FetchOne() { Table t = testSchema.GetTable("test"); - Assert.AreEqual(38, ExecuteSelectStatement(t.Select("age")).FetchOne()["age"]); + Assert.That(ExecuteSelectStatement(t.Select("age")).FetchOne()["age"], Is.EqualTo(38)); } private void MultiTableSelectTest(TableSelectStatement statement, object[][] expectedValues) @@ -77,13 +77,13 @@ private void MultiTableSelectTest(TableSelectStatement statement, object[][] exp RowResult result = ExecuteSelectStatement(statement); int rowCount = result.FetchAll().Count; - Assert.AreEqual(expectedValues.Length, rowCount); - Assert.AreEqual(expectedValues.Length, result.Rows.Count); + Assert.That(rowCount, Is.EqualTo(expectedValues.Length)); + Assert.That(result.Rows.Count, Is.EqualTo(expectedValues.Length)); for (int i = 0; i < expectedValues.Length; i++) { for (int j = 0; j < expectedValues[i].Length; j++) { - Assert.AreEqual(expectedValues[i][j], result.Rows.ToArray()[i][j]); + Assert.That(result.Rows.ToArray()[i][j], Is.EqualTo(expectedValues[i][j])); } } } @@ -124,14 +124,14 @@ public void AllColumns() var table = testSchema.GetTable("test"); var select = ExecuteSelectStatement(table.Select("*, 42 as a_number, '43' as a_string")); var rows = select.FetchAll(); - Assert.AreEqual(6, select.Columns.Count); - Assert.AreEqual(allRows.Length, rows.Count); - Assert.AreEqual(allRows[0][0], rows[0]["id"]); - Assert.AreEqual(allRows[0][1], rows[0]["name"]); - Assert.AreEqual(allRows[0][2], rows[0]["age"]); - Assert.AreEqual(allRows[0][3], rows[0]["additionalinfo"]); - Assert.AreEqual((sbyte)42, rows[0]["a_number"]); - Assert.AreEqual("43", rows[0]["a_string"]); + Assert.That(select.Columns.Count, Is.EqualTo(6)); + Assert.That(rows.Count, Is.EqualTo(allRows.Length)); + Assert.That(rows[0]["id"], Is.EqualTo(allRows[0][0])); + Assert.That(rows[0]["name"], Is.EqualTo(allRows[0][1])); + Assert.That(rows[0]["age"], Is.EqualTo(allRows[0][2])); + Assert.That(rows[0]["additionalinfo"], Is.EqualTo(allRows[0][3])); + Assert.That(rows[0]["a_number"], Is.EqualTo((sbyte)42)); + Assert.That(rows[0]["a_string"], Is.EqualTo("43")); } [Test] @@ -142,7 +142,7 @@ public void CountAllColumns() var rows = select.FetchAll(); Assert.That(select.Columns, Has.One.Items); Assert.That(rows, Has.One.Items); - Assert.AreEqual(allRows.Length + 10, (long)rows[0][0]); + Assert.That((long)rows[0][0], Is.EqualTo(allRows.Length + 10)); } [Test] @@ -153,8 +153,8 @@ public void MultipleBind() var select = ExecuteSelectStatement(table.Select().Where("Name = :nAme && Age = :aGe").Bind("agE", validationRow[2]).Bind("naMe", validationRow[1])); var rows = select.FetchAll(); Assert.That(rows, Has.One.Items); - Assert.AreEqual(validationRow[1], rows[0]["namE"]); - Assert.AreEqual(validationRow[2], rows[0]["AGe"]); + Assert.That(rows[0]["namE"], Is.EqualTo(validationRow[1])); + Assert.That(rows[0]["AGe"], Is.EqualTo(validationRow[2])); } [Test] @@ -164,9 +164,9 @@ public void DatetimeAndMicroseconds() ExecuteSQL("INSERT INTO test.testDate VALUES(1, 'JOHN', '1985-10-21 16:34:22.123456')"); ExecuteSQL("INSERT INTO test.testDate VALUES(1, 'BILL', '1985-10-21 10:00:45.987')"); var rows = ExecuteSelectStatement(GetSession().GetSchema("test").GetTable("testDate").Select()).FetchAll(); - Assert.AreEqual(2, rows.Count); - Assert.AreEqual(new DateTime(1985, 10, 21, 16, 34, 22).AddTicks(1234560), (DateTime)rows[0]["birthday"]); - Assert.AreEqual(new DateTime(1985, 10, 21, 10, 0, 45).AddTicks(9870000), (DateTime)rows[1]["birthday"]); + Assert.That(rows.Count, Is.EqualTo(2)); + Assert.That((DateTime)rows[0]["birthday"], Is.EqualTo(new DateTime(1985, 10, 21, 16, 34, 22).AddTicks(1234560))); + Assert.That((DateTime)rows[1]["birthday"], Is.EqualTo(new DateTime(1985, 10, 21, 10, 0, 45).AddTicks(9870000))); } [Test] @@ -176,9 +176,9 @@ public void DatetimeAndMilliseconds() ExecuteSQL("INSERT INTO test.testDate2 VALUES(1, 'JOHN', '1985-10-21 16:34:22.123456')"); ExecuteSQL("INSERT INTO test.testDate2 VALUES(1, 'BILL', '1985-10-21 10:00:45.098')"); var rows = ExecuteSelectStatement(GetSession().GetSchema("test").GetTable("testDate2").Select()).FetchAll(); - Assert.AreEqual(2, rows.Count); - Assert.AreEqual(new DateTime(1985, 10, 21, 16, 34, 22).AddTicks(1230000), (DateTime)rows[0]["birthday"]); - Assert.AreEqual(new DateTime(1985, 10, 21, 10, 0, 45).AddTicks(980000), (DateTime)rows[1]["birthday"]); + Assert.That(rows.Count, Is.EqualTo(2)); + Assert.That((DateTime)rows[0]["birthday"], Is.EqualTo(new DateTime(1985, 10, 21, 16, 34, 22).AddTicks(1230000))); + Assert.That((DateTime)rows[1]["birthday"], Is.EqualTo(new DateTime(1985, 10, 21, 10, 0, 45).AddTicks(980000))); } [Test] @@ -189,10 +189,10 @@ public void RowLockingNotSupportedInOlderVersions() Table table = session.Schema.GetTable("test"); Exception ex = Assert.Throws(() => ExecuteSelectStatement(table.Select().LockShared())); - Assert.AreEqual("This functionality is only supported from server version 8.0.3 onwards.", ex.Message); + Assert.That(ex.Message, Is.EqualTo("This functionality is only supported from server version 8.0.3 onwards.")); ex = Assert.Throws(() => ExecuteSelectStatement(table.Select().LockExclusive())); - Assert.AreEqual("This functionality is only supported from server version 8.0.3 onwards.", ex.Message); + Assert.That(ex.Message, Is.EqualTo("This functionality is only supported from server version 8.0.3 onwards.")); } [Test] @@ -248,7 +248,7 @@ public void SimpleExclusiveLock() // Session2 blocks due to to LockExclusive() not allowing to read locked rows. ExecuteSQLStatement(session2.SQL("SET SESSION innodb_lock_wait_timeout=1")); Exception ex = Assert.Throws(() => ExecuteSelectStatement(table2.Select().Where("id = 1").LockExclusive())); - Assert.AreEqual("Lock wait timeout exceeded; try restarting transaction", ex.Message); + Assert.That(ex.Message, Is.EqualTo("Lock wait timeout exceeded; try restarting transaction")); ExecuteSQLStatement(session.SQL("ROLLBACK")); ExecuteSQLStatement(session2.SQL("ROLLBACK")); @@ -278,11 +278,11 @@ public void SharedLockForbidsToModifyDocuments() // Modify() is allowed for non-locked rows. Result result = ExecuteUpdateStatement(table2.Update().Where("id = 2").Set("age", 2)); - Assert.AreEqual(1, result.AffectedItemsCount); + Assert.That(result.AffectedItemsCount, Is.EqualTo(1)); // Session1 blocks, Modify() is not allowed for locked rows. ExecuteSQLStatement(session2.SQL("SET SESSION innodb_lock_wait_timeout=1")); Exception ex = Assert.Throws(() => ExecuteUpdateStatement(table2.Update().Where("id = 1").Set("age", 2))); - Assert.AreEqual("Lock wait timeout exceeded; try restarting transaction", ex.Message); + Assert.That(ex.Message, Is.EqualTo("Lock wait timeout exceeded; try restarting transaction")); ExecuteSQLStatement(session.SQL("ROLLBACK")); // Modify() is allowed since row isn't locked anymore. @@ -311,11 +311,11 @@ public void ExclusiveLockForbidsToModifyDocuments() // Modify() is allowed for non-locked rows. Result result = ExecuteUpdateStatement(table2.Update().Where("id = 2").Set("age", 2)); - Assert.AreEqual(1, result.AffectedItemsCount); + Assert.That(result.AffectedItemsCount, Is.EqualTo(1)); // Session1 blocks, Modify() is not allowed for locked rows. ExecuteSQLStatement(session2.SQL("SET SESSION innodb_lock_wait_timeout=1")); Exception ex = Assert.Throws(() => ExecuteUpdateStatement(table2.Update().Where("id = 1").Set("age", 2))); - Assert.AreEqual("Lock wait timeout exceeded; try restarting transaction", ex.Message); + Assert.That(ex.Message, Is.EqualTo("Lock wait timeout exceeded; try restarting transaction")); ExecuteSQLStatement(session.SQL("ROLLBACK")); // Modify() is allowed since row isn't locked anymore. @@ -348,7 +348,7 @@ public void SharedLockAfterExclusiveLock() // Session2 blocks due to LockExclusive() not allowing to read locked rows. ExecuteSQLStatement(session2.SQL("SET SESSION innodb_lock_wait_timeout=1")); Exception ex = Assert.Throws(() => ExecuteSelectStatement(table2.Select().Where("id = 1").LockShared())); - Assert.AreEqual("Lock wait timeout exceeded; try restarting transaction", ex.Message); + Assert.That(ex.Message, Is.EqualTo("Lock wait timeout exceeded; try restarting transaction")); // Session unlocks rows. ExecuteSQLStatement(session.SQL("ROLLBACK")); @@ -374,7 +374,7 @@ public void ExclusiveLockAfterSharedLock() ExecuteSQLStatement(session.SQL("START TRANSACTION")); RowResult rowResult = ExecuteSelectStatement(table.Select().Where("id in (1, 3)").LockShared()); - Assert.AreEqual(2, rowResult.FetchAll().Count); + Assert.That(rowResult.FetchAll().Count, Is.EqualTo(2)); ExecuteSQLStatement(session2.SQL("START TRANSACTION")); // Should return immediately since row isn't locked. @@ -385,7 +385,7 @@ public void ExclusiveLockAfterSharedLock() // Session2 blocks due to to LockExclusive() not allowing to read locked rows. ExecuteSQLStatement(session2.SQL("SET SESSION innodb_lock_wait_timeout=1")); Exception ex = Assert.Throws(() => ExecuteSelectStatement(table2.Select().Where("id = 1").LockExclusive())); - Assert.AreEqual("Lock wait timeout exceeded; try restarting transaction", ex.Message); + Assert.That(ex.Message, Is.EqualTo("Lock wait timeout exceeded; try restarting transaction")); // Session unlocks rows. ExecuteSQLStatement(session.SQL("ROLLBACK")); @@ -399,15 +399,15 @@ public void ExclusiveLockAfterSharedLock() public void SelectWithInOperator() { Table table = testSchema.GetTable("test"); - Assert.AreEqual(3, ExecuteSelectStatement(table.Select()).FetchAll().Count); + Assert.That(ExecuteSelectStatement(table.Select()).FetchAll().Count, Is.EqualTo(3)); - Assert.AreEqual(2, ExecuteSelectStatement(table.Select().Where("name IN (\"jonh doe\", \"milton green\")")).FetchAll().Count); + Assert.That(ExecuteSelectStatement(table.Select().Where("name IN (\"jonh doe\", \"milton green\")")).FetchAll().Count, Is.EqualTo(2)); Assert.That(ExecuteSelectStatement(table.Select().Where("name NOT IN (\"jonh doe\", \"milton green\")")).FetchAll(), Has.One.Items); - CollectionAssert.IsEmpty(ExecuteSelectStatement(table.Select().Where("name IN (\"\", \"\")")).FetchAll()); - CollectionAssert.IsEmpty(ExecuteSelectStatement(table.Select().Where("\"\" IN (1,2,3)")).FetchAll()); - CollectionAssert.IsEmpty(ExecuteSelectStatement(table.Select().Where("name IN ('', '')")).FetchAll()); - CollectionAssert.IsEmpty(ExecuteSelectStatement(table.Select().Where("'' IN (1,2,3)")).FetchAll()); - Assert.AreEqual(3, ExecuteSelectStatement(table.Select().Where("'' IN ('')")).FetchAll().Count); + Assert.That(ExecuteSelectStatement(table.Select().Where("name IN (\"\", \"\")")).FetchAll(), Is.Empty); + Assert.That(ExecuteSelectStatement(table.Select().Where("\"\" IN (1,2,3)")).FetchAll(), Is.Empty); + Assert.That(ExecuteSelectStatement(table.Select().Where("name IN ('', '')")).FetchAll(), Is.Empty); + Assert.That(ExecuteSelectStatement(table.Select().Where("'' IN (1,2,3)")).FetchAll(), Is.Empty); + Assert.That(ExecuteSelectStatement(table.Select().Where("'' IN ('')")).FetchAll().Count, Is.EqualTo(3)); Assert.Throws(() => ExecuteSelectStatement(table.Select().Where("name NOT IN [\"jonh doe\", \"milton green\"]")).FetchAll()); Assert.Throws(() => ExecuteSelectStatement(table.Select().Where("a IN [3]")).FetchAll()); @@ -433,55 +433,55 @@ public void Grouping() statement = statement.Values(user); } - Assert.AreEqual(4, ExecuteInsertStatement(statement).AffectedItemsCount); + Assert.That(ExecuteInsertStatement(statement).AffectedItemsCount, Is.EqualTo(4)); // GroupBy returns 5 rows since age 45 and 24 is repeated. var result = ExecuteSelectStatement(table.Select().GroupBy("age")); - Assert.AreEqual(5, result.FetchAll().Count); + Assert.That(result.FetchAll().Count, Is.EqualTo(5)); // GroupBy with null. result = ExecuteSelectStatement(table.Select("id as ID", "name as Name", "age as Age").GroupBy(null)); - Assert.AreEqual(7, result.FetchAll().Count); + Assert.That(result.FetchAll().Count, Is.EqualTo(7)); result = ExecuteSelectStatement(table.Select("id as ID", "name as Name", "age as Age").GroupBy(null, null)); - Assert.AreEqual(7, result.FetchAll().Count); + Assert.That(result.FetchAll().Count, Is.EqualTo(7)); result = ExecuteSelectStatement(table.Select("id as ID", "name as Name", "age as Age").GroupBy(null, "age")); - Assert.AreEqual(5, result.FetchAll().Count); + Assert.That(result.FetchAll().Count, Is.EqualTo(5)); // Having operation. // Having reduces the original 5 rows to 3 since 2 rows have a cnt=2, due to the repeated names. result = ExecuteSelectStatement(table.Select("id", "count(name) as cnt", "age").GroupBy("age").Having("cnt = 1")); - Assert.AreEqual(3, result.FetchAll().Count); + Assert.That(result.FetchAll().Count, Is.EqualTo(3)); // Having with null. result = ExecuteSelectStatement(table.Select("id as ID", "count(name) as cnt", "age as Age").GroupBy("age").Having(null)); - Assert.AreEqual(5, result.FetchAll().Count); + Assert.That(result.FetchAll().Count, Is.EqualTo(5)); // GroupBy with invalid field name. var ex = Assert.Throws(() => ExecuteSelectStatement(table.Select("id as ID", "name as Name", "age as Age").GroupBy("none"))); - Assert.AreEqual("Unknown column 'none' in 'group statement'", ex.Message); + Assert.That(ex.Message, Is.EqualTo("Unknown column 'none' in 'group statement'")); // GroupBy with empty strings. var ex2 = Assert.Throws(() => ExecuteSelectStatement(table.Select("id as ID", "name as Name", "age as Age").GroupBy(""))); - Assert.AreEqual("No more tokens when expecting one at token pos 0", ex2.Message); + Assert.That(ex2.Message, Is.EqualTo("No more tokens when expecting one at token pos 0")); ex2 = Assert.Throws(() => ExecuteSelectStatement(table.Select("id as ID", "name as Name", "age as Age").GroupBy(" "))); - Assert.AreEqual("No more tokens when expecting one at token pos 0", ex2.Message); + Assert.That(ex2.Message, Is.EqualTo("No more tokens when expecting one at token pos 0")); ex2 = Assert.Throws(() => ExecuteSelectStatement(table.Select("id as ID", "name as Name", "age as Age").GroupBy(string.Empty))); - Assert.AreEqual("No more tokens when expecting one at token pos 0", ex2.Message); + Assert.That(ex2.Message, Is.EqualTo("No more tokens when expecting one at token pos 0")); // Having with invalid field name. ex = Assert.Throws(() => ExecuteSelectStatement(table.Select("id as ID", "count(name) as cnt", "age as Age").GroupBy("age").Having("none = 1"))); - Assert.AreEqual("Unknown column 'none' in 'having clause'", ex.Message); + Assert.That(ex.Message, Is.EqualTo("Unknown column 'none' in 'having clause'")); // Having with empty strings. ex2 = Assert.Throws(() => ExecuteSelectStatement(table.Select("id as ID", "count(name) as cnt", "age as Age").GroupBy("age").Having(""))); - Assert.AreEqual("Unable to parse query ''", ex2.Message); - Assert.AreEqual("No more tokens when expecting one at token pos 0", ex2.InnerException.Message); + Assert.That(ex2.Message, Is.EqualTo("Unable to parse query ''")); + Assert.That(ex2.InnerException.Message, Is.EqualTo("No more tokens when expecting one at token pos 0")); ex2 = Assert.Throws(() => ExecuteSelectStatement(table.Select("id as ID", "count(name) as cnt", "age as Age").GroupBy("age").Having(" "))); - Assert.AreEqual("Unable to parse query ' '", ex2.Message); - Assert.AreEqual("No more tokens when expecting one at token pos 0", ex2.InnerException.Message); + Assert.That(ex2.Message, Is.EqualTo("Unable to parse query ' '")); + Assert.That(ex2.InnerException.Message, Is.EqualTo("No more tokens when expecting one at token pos 0")); ex2 = Assert.Throws(() => ExecuteSelectStatement(table.Select("id as ID", "count(name) as cnt", "age as Age").GroupBy("age").Having(string.Empty))); - Assert.AreEqual("Unable to parse query ''", ex2.Message); - Assert.AreEqual("No more tokens when expecting one at token pos 0", ex2.InnerException.Message); + Assert.That(ex2.Message, Is.EqualTo("Unable to parse query ''")); + Assert.That(ex2.InnerException.Message, Is.EqualTo("No more tokens when expecting one at token pos 0")); } /// @@ -524,11 +524,11 @@ public void SelectWithInBlanksAndBrackets() // Test using parenthesis should return result count = table.Select().Where("name IN (\"john doe\", \"milton green\")").Execute().FetchAll().Count; - Assert.True(count > 0); + Assert.That(count > 0); // Using parenthesis should return empty resultset for empty parameters count = table.Select().Where("name IN ('', ' ')").Execute().FetchAll().Count; - Assert.True(count == 0); + Assert.That(count == 0); } [TestCase(":hobbies IN additionalinfo->$.hobbies", "hobbies", "painting", 3)] @@ -538,15 +538,15 @@ public void SelectWithInBlanksAndBrackets() public void InOperatorBindingJson(string condition, string bind, string value, int id) { Table table = testSchema.GetTable("test"); - Assert.AreEqual(3, ExecuteSelectStatement(table.Select()).FetchAll().Count); + Assert.That(ExecuteSelectStatement(table.Select()).FetchAll().Count, Is.EqualTo(3)); var stmt = table.Select().Where(condition); if (bind != null) stmt.Bind(bind, value); var result = ExecuteSelectStatement(stmt).FetchAll(); - Assert.AreEqual(id == 0 ? 0 : 1, result.Count); + Assert.That(result.Count, Is.EqualTo(id == 0 ? 0 : 1)); if (id > 0) { - Assert.AreEqual(id, result[0]["id"]); + Assert.That(result[0]["id"], Is.EqualTo(id)); } } @@ -571,28 +571,28 @@ public void ExclusiveLockAfterSharedLockDefaultWaiting() ExecuteSQLStatement(session.SQL("START TRANSACTION")); var rowResult = ExecuteSelectStatement(table.Select().Where("id = 1").LockShared()); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); + Assert.That(rowResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID"); ExecuteSQLStatement(session2.SQL("START TRANSACTION")); // Should return immediately since document isn't locked. rowResult = table2.Select().Where("id = 2").LockExclusive(LockContention.Default).Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); + Assert.That(rowResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID"); // Session2 blocks as LockExclusive trying to access locked document ExecuteSQLStatement(session2.SQL("SET SESSION innodb_lock_wait_timeout=1")); Exception ex = Assert.Throws(() => ExecuteSelectStatement(table2.Select().Where("id = 1").LockExclusive(LockContention.Default))); - Assert.AreEqual("Lock wait timeout exceeded; try restarting transaction", ex.Message); + Assert.That(ex.Message, Is.EqualTo("Lock wait timeout exceeded; try restarting transaction")); // Session2 blocks due to to LockShared() not allowing to modify locked documents. Result result1; ex = Assert.Throws(() => result1 = table2.Update().Where("id = 1").Set("a", 2).Execute()); - Assert.AreEqual("Lock wait timeout exceeded; try restarting transaction", ex.Message); + Assert.That(ex.Message, Is.EqualTo("Lock wait timeout exceeded; try restarting transaction")); // Session2 returns immediately as session is committed. session.Commit(); var result = table2.Update().Where("id = 1").Set("a", 2).Execute(); - Assert.AreEqual(1, result.AffectedItemsCount); + Assert.That(result.AffectedItemsCount, Is.EqualTo(1)); ExecuteSQLStatement(session.SQL("ROLLBACK")); ExecuteSQLStatement(session2.SQL("ROLLBACK")); @@ -618,12 +618,12 @@ public void SharedLockAfterExclusiveLockWithNoWait() session.SQL("START TRANSACTION").Execute(); var rowResult = table.Select().Where("id = 1").LockExclusive().Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); + Assert.That(rowResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID"); session2.SQL("START TRANSACTION").Execute(); // Should return immediately since document isn't locked. rowResult = table2.Select().Where("id = 2").LockShared(LockContention.NoWait).Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); + Assert.That(rowResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID"); // Session2 blocks due to to LockExclusive() not allowing to read locked documents. ExecuteSQLStatement(session2.SQL("SET SESSION innodb_lock_wait_timeout=1")); @@ -635,7 +635,7 @@ public void SharedLockAfterExclusiveLockWithNoWait() session.Commit(); var result = table2.Update().Where("id = 1").Set("a", 2).Execute(); - Assert.AreEqual(1, result.AffectedItemsCount); + Assert.That(result.AffectedItemsCount, Is.EqualTo(1)); ExecuteSQLStatement(session.SQL("ROLLBACK")); ExecuteSQLStatement(session2.SQL("ROLLBACK")); @@ -660,12 +660,12 @@ public void NonAsciiCharsForUtf8mb4() tabNew.Insert().Values("abcNew£¢€©§°√", "{ \"name\": \"abcNew£¢€©§°√\", \"age\": 2 , \"misc\": 1.2}").Execute(); RowResult result = tabNew.Select("c1", "c2").Where("c1 ='\u201C\u2199\u2197\u2196\u2198\u201D'").Execute(); var r1 = result.FetchOne(); - Assert.AreEqual(name1, r1[0].ToString());//"“↙↗↖↘”" - Assert.AreNotEqual(name2, r1[1].ToString());//"{\"age\": 1, \"misc\": 1.2, \"name\": \"??????????????????\"}" + Assert.That(r1[0].ToString(), Is.EqualTo(name1));//"“↙↗↖↘”" + Assert.That(r1[1].ToString(), Is.Not.EqualTo(name2));//"{\"age\": 1, \"misc\": 1.2, \"name\": \"??????????????????\"}" var t = session.SQL("SELECT c1, CONVERT(c2 USING utf8mb4) FROM newTable WHERE c1 = '\u201C\u2199\u2197\u2196\u2198\u201D'").Execute(); r1 = t.FetchOne(); - Assert.AreEqual(name1, r1[0].ToString());//"“↙↗↖↘”" - Assert.AreEqual(name2, r1[1].ToString());//"{\"age\": 1, \"misc\": 1.2, \"name\": \"??????????????????\"}" + Assert.That(r1[0].ToString(), Is.EqualTo(name1));//"“↙↗↖↘”" + Assert.That(r1[1].ToString(), Is.EqualTo(name2));//"{\"age\": 1, \"misc\": 1.2, \"name\": \"??????????????????\"}" Collection coll = CreateCollection("test"); @@ -691,7 +691,7 @@ record = record + "\"}"; Add("{ \"name\": \"xyz£¢€©§°√\", \"age\": 6 , \"misc\": 10}").Execute(); var docs = coll.Find("name = '\u201C\u2199\u2197\u2196\u2198\u201D' and age>= 4 and age <= 6").Execute(); DbDoc doc = docs.FetchOne(); - Assert.AreEqual(name1, doc["name"]); + Assert.That(doc["name"], Is.EqualTo(name1)); session.SQL("drop table if exists test").Execute(); session.SQL("drop table if exists newTable").Execute(); } @@ -706,7 +706,7 @@ public void DatatypesOnCreateTable() session.SQL("insert into test1(c1) values(1000)").Execute(); RowResult r = session.GetSchema(schemaName).GetTable("test1").Select("c1").Execute(); r.FetchAll(); - Assert.AreEqual("1000", r.Rows[0][0].ToString(), "Matching the values"); + Assert.That(r.Rows[0][0].ToString(), Is.EqualTo("1000"), "Matching the values"); session.SQL("drop table if exists test1").Execute(); } @@ -728,25 +728,25 @@ public void TableExpressionWhereBindGroupBy() .Execute(); if (i == 28) match = name; - Assert.AreEqual((ulong)j, result.AffectedItemsCount, "Matching the values"); + Assert.That(result.AffectedItemsCount, Is.EqualTo((ulong)j), "Matching the values"); j = j + 1; } var whereResult = table.Select("name", "age").Where("age == 28").Execute(); int rowCount = whereResult.FetchAll().Count; - Assert.AreEqual(1, rowCount, "Matching the row count"); - Assert.AreEqual(match, whereResult.Rows.ToArray()[0][0].ToString(), "Matching the name"); + Assert.That(rowCount, Is.EqualTo(1), "Matching the row count"); + Assert.That(whereResult.Rows.ToArray()[0][0].ToString(), Is.EqualTo(match), "Matching the name"); whereResult = table.Select("name", "age").Where("age == 100").Execute(); rowCount = whereResult.FetchAll().Count; - Assert.AreEqual(0, rowCount, "Matching that there is no such value "); + Assert.That(rowCount, Is.EqualTo(0), "Matching that there is no such value "); whereResult = table.Select().Where("name like :name").Bind("nAme", "%ABCDEFGHIJ%").Execute(); rowCount = whereResult.FetchAll().Count; for (int i = 0; i < whereResult.Rows.Count; i++) { var res = whereResult.Rows.ToArray()[i][0]; - StringAssert.Contains("ABCDEFGHIJ", res.ToString()); + Assert.That(res.ToString(), Does.Contain("ABCDEFGHIJ")); } whereResult = table.Select().Where("name like :name").Bind("nAme", "%ABCD%").Execute(); @@ -754,7 +754,7 @@ public void TableExpressionWhereBindGroupBy() for (int j = 0; j < whereResult.Rows.Count; j++) { var res = whereResult.Rows.ToArray()[j][0]; - StringAssert.Contains("ABCD", res.ToString()); + Assert.That(res.ToString(), Does.Contain("ABCD")); } } @@ -768,36 +768,36 @@ public void TableSelectFetchValuesInOrder() .Values("MARK", 34) .Execute(); - Assert.AreEqual((ulong)1, result.AffectedItemsCount, "Matching the values"); + Assert.That(result.AffectedItemsCount, Is.EqualTo((ulong)1), "Matching the values"); result = table.Insert("name", "age") .Values("richie", 16) .Execute(); - Assert.AreEqual((ulong)1, result.AffectedItemsCount, "Matching the values"); + Assert.That(result.AffectedItemsCount, Is.EqualTo((ulong)1), "Matching the values"); var selectResult = table.Select().Execute(); while (selectResult.Next()) ; - Assert.AreEqual(2, selectResult.Rows.Count, "Matching the row count"); - Assert.AreEqual("MARK", selectResult.Rows.ToArray()[0][0].ToString(), "Matching the value MARK"); - Assert.AreEqual(34, (int)selectResult.Rows.ToArray()[0][1], "Matching the age 34"); - Assert.AreEqual("richie", selectResult.Rows.ToArray()[1][0].ToString(), "Matching the value richie"); - Assert.AreEqual(16, (int)selectResult.Rows.ToArray()[1][1], "Matching the age 16"); + Assert.That(selectResult.Rows.Count, Is.EqualTo(2), "Matching the row count"); + Assert.That(selectResult.Rows.ToArray()[0][0].ToString(), Is.EqualTo("MARK"), "Matching the value MARK"); + Assert.That((int)selectResult.Rows.ToArray()[0][1], Is.EqualTo(34), "Matching the age 34"); + Assert.That(selectResult.Rows.ToArray()[1][0].ToString(), Is.EqualTo("richie"), "Matching the value richie"); + Assert.That((int)selectResult.Rows.ToArray()[1][1], Is.EqualTo(16), "Matching the age 16"); var result1 = testSchema.GetTable("test").Select().OrderBy("age desc").Execute(); int rowCount = result1.FetchAll().Count; for (int i = 0; i < rowCount; i++) { - Assert.AreEqual("45", result1.Rows[0][2].ToString(), "Matching the values"); - Assert.AreEqual("38", result1.Rows[1][2].ToString(), "Matching the values"); - Assert.AreEqual("24", result1.Rows[2][2].ToString(), "Matching the values"); + Assert.That(result1.Rows[0][2].ToString(), Is.EqualTo("45"), "Matching the values"); + Assert.That(result1.Rows[1][2].ToString(), Is.EqualTo("38"), "Matching the values"); + Assert.That(result1.Rows[2][2].ToString(), Is.EqualTo("24"), "Matching the values"); } result1 = testSchema.GetTable("test").Select().OrderBy("age asc").Execute(); rowCount = result1.FetchAll().Count; for (int i = 0; i < rowCount; i++) { - Assert.AreEqual("24", result1.Rows[0][2].ToString(), "Matching the values"); - Assert.AreEqual("38", result1.Rows[1][2].ToString(), "Matching the values"); - Assert.AreEqual("45", result1.Rows[2][2].ToString(), "Matching the values"); + Assert.That(result1.Rows[0][2].ToString(), Is.EqualTo("24"), "Matching the values"); + Assert.That(result1.Rows[1][2].ToString(), Is.EqualTo("38"), "Matching the values"); + Assert.That(result1.Rows[2][2].ToString(), Is.EqualTo("45"), "Matching the values"); } } @@ -820,12 +820,12 @@ public void DoubleExclusiveLockWithNoWait() session.SQL("START TRANSACTION").Execute(); var rowResult = table.Select().Where("id = 1").LockExclusive().Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); + Assert.That(rowResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID"); session2.SQL("START TRANSACTION").Execute(); // Should return immediately since document isn't locked. rowResult = table2.Select().Where("id = 2").LockExclusive(LockContention.NoWait).Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); + Assert.That(rowResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID"); // Session2 blocks due to to LockExclusive() not allowing to read locked documents. ExecuteSQLStatement(session2.SQL("SET SESSION innodb_lock_wait_timeout=1")); @@ -838,7 +838,7 @@ public void DoubleExclusiveLockWithNoWait() // Session2 returns immediately as session is committed. session.Commit(); var result = table2.Update().Where("id = 1").Set("a", 2).Execute(); - Assert.AreEqual(1, result.AffectedItemsCount); + Assert.That(result.AffectedItemsCount, Is.EqualTo(1)); session.SQL("ROLLBACK").Execute(); session2.SQL("ROLLBACK").Execute(); } @@ -862,17 +862,17 @@ public void DoubleSharedLockWithNoWait() session.SQL("START TRANSACTION").Execute(); var rowResult = table.Select().Where("id = 1").LockShared().Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); + Assert.That(rowResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID"); session2.SQL("START TRANSACTION").Execute(); // Should return immediately since document isn't locked. rowResult = table2.Select().Where("id = 2").LockShared(LockContention.NoWait).Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); + Assert.That(rowResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID"); // Session2 doesnt block as LockShare trying to read locked(Lock_shared) document session2.SQL("SET SESSION innodb_lock_wait_timeout=1").Execute(); rowResult = table2.Select().Where("id = 1").LockShared(LockContention.NoWait).Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); + Assert.That(rowResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID"); // Session2 blocks due to to LockShared() not allowing to modify locked documents. Result result1; @@ -881,7 +881,7 @@ public void DoubleSharedLockWithNoWait() // Session2 returns immediately as session is committed. session.Commit(); var result = table2.Update().Where("id = 1").Set("a", 2).Execute(); - Assert.AreEqual(1, result.AffectedItemsCount); + Assert.That(result.AffectedItemsCount, Is.EqualTo(1)); session.SQL("ROLLBACK").Execute(); session2.SQL("ROLLBACK").Execute(); } @@ -905,12 +905,12 @@ public void ExclusiveLockAfterSharedLockWithNoWait() session.SQL("START TRANSACTION").Execute(); var rowResult = table.Select().Where("id = 1").LockShared().Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); + Assert.That(rowResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID"); session2.SQL("START TRANSACTION").Execute(); // Should return immediately since document isn't locked. rowResult = table2.Select().Where("id = 2").LockExclusive(LockContention.NoWait).Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); + Assert.That(rowResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID"); // Session2 blocks as LockExclusive() trying to access locked(LockShared) documents. ExecuteSQLStatement(session2.SQL("SET SESSION innodb_lock_wait_timeout=1")); @@ -923,7 +923,7 @@ public void ExclusiveLockAfterSharedLockWithNoWait() // Session2 returns immediately as session is committed. session.Commit(); var result = table2.Update().Where("id = 1").Set("a", 2).Execute(); - Assert.AreEqual(1, result.AffectedItemsCount); + Assert.That(result.AffectedItemsCount, Is.EqualTo(1)); session.SQL("ROLLBACK").Execute(); session2.SQL("ROLLBACK").Execute(); } @@ -947,17 +947,17 @@ public void SharedLockAfterExclusiveWithSkiplock() session.SQL("START TRANSACTION").Execute(); var rowResult = table.Select().Where("id = 1").LockExclusive().Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); + Assert.That(rowResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID"); session2.SQL("START TRANSACTION").Execute(); // Should return immediately since document isn't locked. rowResult = table2.Select().Where("id = 2").LockShared(LockContention.NoWait).Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); + Assert.That(rowResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID"); // Session2 blocks due to to LockExclusive() not allowing to read locked documents. ExecuteSQLStatement(session2.SQL("SET SESSION innodb_lock_wait_timeout=1")); rowResult = table2.Select().Where("id = 1").LockShared(LockContention.SkipLocked).Execute(); - Assert.AreEqual(0, rowResult.FetchAll().Count, "Matching the document ID"); + Assert.That(rowResult.FetchAll().Count, Is.EqualTo(0), "Matching the document ID"); // Session2 blocks due to to LockExclusive() not allowing to modify locked documents. Result result1; @@ -966,7 +966,7 @@ public void SharedLockAfterExclusiveWithSkiplock() // Session2 returns immediately as session is committed. session.Commit(); var result = table2.Update().Where("id = 1").Set("a", 2).Execute(); - Assert.AreEqual(1, (int)result.AffectedItemsCount, "Matching the record count"); + Assert.That((int)result.AffectedItemsCount, Is.EqualTo(1), "Matching the record count"); session.SQL("ROLLBACK").Execute(); session2.SQL("ROLLBACK").Execute(); @@ -991,17 +991,17 @@ public void DoubleExclusiveLockWithSkiplock() session.SQL("START TRANSACTION").Execute(); var rowResult = table.Select().Where("id = 1").LockExclusive().Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); + Assert.That(rowResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID"); session2.SQL("START TRANSACTION").Execute(); // Should return immediately since document isn't locked. rowResult = table2.Select().Where("id = 2").LockExclusive(LockContention.SkipLocked).Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); + Assert.That(rowResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID"); // Session2 doesn't block as SKIPLOCK used ExecuteSQLStatement(session2.SQL("SET SESSION innodb_lock_wait_timeout=1")); rowResult = table2.Select().Where("id = 1").LockExclusive(LockContention.SkipLocked).Execute(); - Assert.AreEqual(0, rowResult.FetchAll().Count, "Matching the document ID"); + Assert.That(rowResult.FetchAll().Count, Is.EqualTo(0), "Matching the document ID"); // Session2 blocks due to to LockExclusive() not allowing to modify locked documents. Result result1; Assert.Throws(() => result1 = table2.Update().Where("id = 1").Set("a", 2).Execute()); @@ -1009,7 +1009,7 @@ public void DoubleExclusiveLockWithSkiplock() // Session2 returns immediately as session is committed. session.Commit(); var result = table2.Update().Where("id = 1").Set("a", 2).Execute(); - Assert.AreEqual(1, (int)result.AffectedItemsCount, "Matching the record count"); + Assert.That((int)result.AffectedItemsCount, Is.EqualTo(1), "Matching the record count"); session.SQL("ROLLBACK").Execute(); session2.SQL("ROLLBACK").Execute(); } @@ -1032,17 +1032,17 @@ public void DoubleSharedLockWithSkiplock() session.SQL("START TRANSACTION").Execute(); var rowResult = table.Select().Where("id = 1").LockShared().Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); + Assert.That(rowResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID"); session2.SQL("START TRANSACTION").Execute(); // Should return immediately since document isn't locked. rowResult = table2.Select().Where("id = 2").LockShared(LockContention.SkipLocked).Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); + Assert.That(rowResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID"); // Session2 doesn't block as SKIPLOCK being used ExecuteSQLStatement(session2.SQL("SET SESSION innodb_lock_wait_timeout=1")); rowResult = table2.Select().Where("id = 1").LockShared(LockContention.SkipLocked).Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); + Assert.That(rowResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID"); // Session2 blocks due to to LockShared() not allowing to modify locked documents. Result result1; @@ -1051,7 +1051,7 @@ public void DoubleSharedLockWithSkiplock() // Session2 returns immediately as session is committed. session.Commit(); var result = table2.Update().Where("id = 1").Set("a", 2).Execute(); - Assert.AreEqual(1, (int)result.AffectedItemsCount, "Matching the record count"); + Assert.That((int)result.AffectedItemsCount, Is.EqualTo(1), "Matching the record count"); session.SQL("ROLLBACK").Execute(); session2.SQL("ROLLBACK").Execute(); } @@ -1075,17 +1075,17 @@ public void ExclusiveLockAfterSharedLockWithSkiplock() session.SQL("START TRANSACTION").Execute(); var rowResult = table.Select().Where("id = 1").LockShared().Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); + Assert.That(rowResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID"); session2.SQL("START TRANSACTION").Execute(); // Should return immediately since document isn't locked. rowResult = table2.Select().Where("id = 2").LockExclusive(LockContention.SkipLocked).Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); + Assert.That(rowResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID"); // Session2 doesn't block as SKIPLOCK being used ExecuteSQLStatement(session2.SQL("SET SESSION innodb_lock_wait_timeout=1")); rowResult = table2.Select().Where("id = 1").LockExclusive(LockContention.SkipLocked).Execute(); - Assert.AreEqual(0, rowResult.FetchAll().Count, "Matching the document ID"); + Assert.That(rowResult.FetchAll().Count, Is.EqualTo(0), "Matching the document ID"); // Session2 blocks due to to LockExclusive() not allowing to modify locked documents. Result result1; @@ -1094,7 +1094,7 @@ public void ExclusiveLockAfterSharedLockWithSkiplock() // Session2 returns immediately as session is committed. session.Commit(); var result = table2.Update().Where("id = 1").Set("a", 2).Execute(); - Assert.AreEqual(1, (int)result.AffectedItemsCount, "Matching the record count"); + Assert.That((int)result.AffectedItemsCount, Is.EqualTo(1), "Matching the record count"); session.SQL("ROLLBACK").Execute(); session2.SQL("ROLLBACK").Execute(); } @@ -1118,12 +1118,12 @@ public void ExclusiveLockBeforeSharedLockWithoutAwaiting() session.SQL("START TRANSACTION").Execute(); var rowResult = table.Select().Where("id = 1").LockExclusive().Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); + Assert.That(rowResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID"); session2.SQL("START TRANSACTION").Execute(); // Should return immediately since document isn't locked. rowResult = table2.Select().Where("id = 2").LockShared().Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); + Assert.That(rowResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID"); // Session2 blocks due to to LockExclusive() not allowing to read locked documents. ExecuteSQLStatement(session2.SQL("SET SESSION innodb_lock_wait_timeout=1")); @@ -1136,7 +1136,7 @@ public void ExclusiveLockBeforeSharedLockWithoutAwaiting() // Session2 returns immediately as session is committed. session.Commit(); var result = table2.Update().Where("id = 1").Set("a", 2).Execute(); - Assert.AreEqual(1, (int)result.AffectedItemsCount, "Matching the record count"); + Assert.That((int)result.AffectedItemsCount, Is.EqualTo(1), "Matching the record count"); session.SQL("ROLLBACK").Execute(); session2.SQL("ROLLBACK").Execute(); } @@ -1155,12 +1155,12 @@ public void DoubleExclusiveLockWithoutWaiting() session.SQL("START TRANSACTION").Execute(); var rowResult = table.Select().Where("id = 1").LockExclusive().Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); + Assert.That(rowResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID"); session2.SQL("START TRANSACTION").Execute(); // Should return immediately since document isn't locked. rowResult = table2.Select().Where("id = 2").LockExclusive().Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); + Assert.That(rowResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID"); // Session2 blocks due to to LockExclusive() not allowing to read locked documents. ExecuteSQLStatement(session2.SQL("SET SESSION innodb_lock_wait_timeout=1")); @@ -1173,7 +1173,7 @@ public void DoubleExclusiveLockWithoutWaiting() // Session2 returns immediately as session is committed. session.Commit(); var result = table2.Update().Where("id = 1").Set("age", 2).Execute(); - Assert.AreEqual(1, (int)result.AffectedItemsCount, "Matching the record count"); + Assert.That((int)result.AffectedItemsCount, Is.EqualTo(1), "Matching the record count"); session.SQL("ROLLBACK").Execute(); session2.SQL("ROLLBACK").Execute(); } @@ -1196,16 +1196,16 @@ public void DoubleSharedLockWithoutWaiting() session.SQL("START TRANSACTION").Execute(); var rowResult = table.Select().Where("id = 1").LockShared().Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); + Assert.That(rowResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID"); session2.SQL("START TRANSACTION").Execute(); // Should return immediately since document isn't locked. rowResult = table2.Select().Where("id = 2").LockShared().Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); + Assert.That(rowResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID"); ExecuteSQLStatement(session2.SQL("SET SESSION innodb_lock_wait_timeout=1")); rowResult = table2.Select().Where("id = 1").LockShared().Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); + Assert.That(rowResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID"); // Session2 blocks due to to LockExclusive() not allowing to modify locked documents. Result result1; @@ -1214,7 +1214,7 @@ public void DoubleSharedLockWithoutWaiting() // Session2 returns immediately as session is committed. session.Commit(); var result = table2.Update().Where("id = 1").Set("a", 2).Execute(); - Assert.AreEqual(1, (int)result.AffectedItemsCount, "Matching the record count"); + Assert.That((int)result.AffectedItemsCount, Is.EqualTo(1), "Matching the record count"); session.SQL("ROLLBACK").Execute(); session2.SQL("ROLLBACK").Execute(); } @@ -1238,12 +1238,12 @@ public void SharedLockBeforeExclusiveLockWithoutWaiting() session.SQL("START TRANSACTION").Execute(); var rowResult = table.Select().Where("id = 1").LockShared().Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); + Assert.That(rowResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID"); session2.SQL("START TRANSACTION").Execute(); // Should return immediately since document isn't locked. rowResult = table2.Select().Where("id = 2").LockExclusive().Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); + Assert.That(rowResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID"); // Session2 blocks as LockExclusive() is trying to read locked documents. ExecuteSQLStatement(session2.SQL("SET SESSION innodb_lock_wait_timeout=1")); @@ -1256,7 +1256,7 @@ public void SharedLockBeforeExclusiveLockWithoutWaiting() // Session2 returns immediately as session is committed. session.Commit(); var result = table2.Update().Where("id = 1").Set("a", 2).Execute(); - Assert.AreEqual(1, (int)result.AffectedItemsCount, "Matching the record count"); + Assert.That((int)result.AffectedItemsCount, Is.EqualTo(1), "Matching the record count"); session.SQL("ROLLBACK").Execute(); session2.SQL("ROLLBACK").Execute(); } @@ -1284,7 +1284,7 @@ public void SingleLockExclusiveWithNoWaitAndSkip() session2.SQL("START TRANSACTION").Execute(); // Should return immediately since document isn't locked. var rowResult1 = table2.Select().Where("id = 2").LockExclusive(LockContention.NoWait).Execute(); - Assert.AreEqual(1, rowResult1.FetchAll().Count, "Matching the document ID"); + Assert.That(rowResult1.FetchAll().Count, Is.EqualTo(1), "Matching the document ID"); // Session2 blocks due to to LockExclusive() not allowing to read locked documents. ExecuteSQLStatement(session2.SQL("SET SESSION innodb_lock_wait_timeout=1")); @@ -1292,10 +1292,10 @@ public void SingleLockExclusiveWithNoWaitAndSkip() Assert.Throws(() => ExecuteSelectStatement(table2.Select().Where("id = 1").LockShared(LockContention.NoWait))); var rowResult = table2.Select().Where("id = 1").LockShared(LockContention.SkipLocked).Execute(); - Assert.AreEqual(0, rowResult.FetchAll().Count, "Matching the document ID"); + Assert.That(rowResult.FetchAll().Count, Is.EqualTo(0), "Matching the document ID"); rowResult = table2.Select().Where("id = 1").LockExclusive(LockContention.SkipLocked).Execute(); - Assert.AreEqual(0, rowResult.FetchAll().Count, "Matching the document ID"); + Assert.That(rowResult.FetchAll().Count, Is.EqualTo(0), "Matching the document ID"); session.SQL("ROLLBACK").Execute(); session2.SQL("ROLLBACK").Execute(); @@ -1320,7 +1320,7 @@ public void ChainedExclusiveLocks() session.SQL("START TRANSACTION").Execute(); var rowResult = table.Select().Where("id = 1").LockShared().Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); + Assert.That(rowResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID"); session2.SQL("START TRANSACTION").Execute(); ExecuteSQLStatement(session2.SQL("SET SESSION innodb_lock_wait_timeout=1")); @@ -1331,10 +1331,10 @@ public void ChainedExclusiveLocks() .LockExclusive(LockContention.NoWait))); rowResult = table2.Select().Where("id = 1").LockExclusive(LockContention.SkipLocked).LockShared(LockContention.SkipLocked).Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); + Assert.That(rowResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID"); rowResult = table2.Select().Where("id = 1").LockShared(LockContention.SkipLocked).LockExclusive(LockContention.SkipLocked).Execute(); - Assert.AreEqual(0, rowResult.FetchAll().Count, "Matching the document ID"); + Assert.That(rowResult.FetchAll().Count, Is.EqualTo(0), "Matching the document ID"); session.SQL("ROLLBACK").Execute(); session2.SQL("ROLLBACK").Execute(); } @@ -1355,13 +1355,13 @@ public void TableGetAutoIncrementValue() .Execute(); var docId = result.AutoIncrementValue; - Assert.AreEqual("100", docId.ToString(), "Matching the value if already it is inserted"); + Assert.That(docId.ToString(), Is.EqualTo("100"), "Matching the value if already it is inserted"); result = table.Insert("address_number2") .Values("Test the document id by 2nd insert without id in address table") .Execute(); docId = result.AutoIncrementValue; - Assert.AreEqual("101", docId.ToString(), "Matching the value if already it is inserted"); + Assert.That(docId.ToString(), Is.EqualTo("101"), "Matching the value if already it is inserted"); session.SQL("CREATE TABLE address2" + "(address_number3 INT NOT NULL AUTO_INCREMENT, " + @@ -1373,7 +1373,7 @@ public void TableGetAutoIncrementValue() .Execute(); docId = result.AutoIncrementValue; - Assert.AreEqual("1", docId.ToString(), "Matching the auto increment value"); + Assert.That(docId.ToString(), Is.EqualTo("1"), "Matching the auto increment value"); session.SQL("CREATE TABLE address3" + "(address_number5 MEDIUMINT NOT NULL AUTO_INCREMENT, " + @@ -1387,7 +1387,7 @@ public void TableGetAutoIncrementValue() .Execute(); docId = result.AutoIncrementValue; - Assert.AreEqual("300", docId.ToString(), "Matching the value if more than one documents inserted"); + Assert.That(docId.ToString(), Is.EqualTo("300"), "Matching the value if more than one documents inserted"); result = table.Insert("address_number6") .Values("Test multiple document ids in address table - 4th document without ID") @@ -1396,7 +1396,7 @@ public void TableGetAutoIncrementValue() .Execute(); docId = result.AutoIncrementValue; - Assert.AreEqual("301", docId.ToString(), "Matching the value if more than one documents inserted"); + Assert.That(docId.ToString(), Is.EqualTo("301"), "Matching the value if more than one documents inserted"); session.SQL("CREATE TABLE address4" + "(address_number7 INT NOT NULL AUTO_INCREMENT, " + @@ -1410,7 +1410,7 @@ public void TableGetAutoIncrementValue() .Execute(); docId = result.AutoIncrementValue; - Assert.AreEqual("1", docId.ToString(), "Matching the auto increment value"); + Assert.That(docId.ToString(), Is.EqualTo("1"), "Matching the auto increment value"); result = table.Insert("address_number8") .Values("Test the document ids in address table without unique id - 4th document") @@ -1419,7 +1419,7 @@ public void TableGetAutoIncrementValue() .Execute(); docId = result.AutoIncrementValue; - Assert.AreEqual("4", docId.ToString(), "Matching the auto increment value"); + Assert.That(docId.ToString(), Is.EqualTo("4"), "Matching the auto increment value"); session.SQL("CREATE TABLE address5" + "(address_number9 INT, " + @@ -1435,7 +1435,7 @@ public void TableGetAutoIncrementValue() .Execute(); docId = result.AutoIncrementValue; - Assert.AreEqual("1", docId.ToString(), "Matching the auto increment value"); + Assert.That(docId.ToString(), Is.EqualTo("1"), "Matching the auto increment value"); session.SQL("drop table if exists address1").Execute(); session.SQL("drop table if exists address2").Execute(); session.SQL("drop table if exists address3").Execute(); @@ -1455,14 +1455,14 @@ public void FetchoneReturnsNullNoRows() { var result = testSchema.GetTable("test2").Update().Where("id=1").Set("val", row["id"]).Execute(); //WL11843-Core API v1 alignment Changes - Assert.AreEqual(1, result.AffectedItemsCount, "Matching"); + Assert.That(result.AffectedItemsCount, Is.EqualTo(1), "Matching"); } Row valRow = testSchema.GetTable("test2").Select("val").Execute().FetchOne(); - Assert.AreEqual("4", valRow[0].ToString(), "Matching"); + Assert.That(valRow[0].ToString(), Is.EqualTo("4"), "Matching"); ExecuteSQL("DELETE FROM test2 WHERE id=1"); valRow = testSchema.GetTable("test2").Select("val").Execute().FetchOne(); - Assert.IsNull(valRow); + Assert.That(valRow, Is.Null); ExecuteSQL("DROP TABLE if exists test1"); ExecuteSQL("DROP TABLE if exists test2"); } @@ -1479,11 +1479,11 @@ public void FetchoneReturnsNullNoTable() { var result = testSchema.GetTable("test222").Update().Where("id=1").Set("val", row["id"]).Execute(); //WL11843-Core API v1 alignment Changes - Assert.AreEqual(1, result.AffectedItemsCount, "Matching"); + Assert.That(result.AffectedItemsCount, Is.EqualTo(1), "Matching"); } Row valRow = testSchema.GetTable("test222").Select("val").Execute().FetchOne(); - Assert.AreEqual("4", valRow[0].ToString(), "Matching"); + Assert.That(valRow[0].ToString(), Is.EqualTo("4"), "Matching"); ExecuteSQL("DROP TABLE test222"); Assert.Throws(() => valRow = testSchema.GetTable("test222").Select("val").Execute().FetchOne()); ExecuteSQL("DROP TABLE IF EXISTS test111"); @@ -1504,12 +1504,12 @@ public void DoubleChainedLocksWithTwoSessions_S1() session.SQL("START TRANSACTION").Execute(); var rowResult = table.Select().Where("id = 1").LockExclusive().Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the record ID"); + Assert.That(rowResult.FetchAll().Count, Is.EqualTo(1), "Matching the record ID"); session2.SQL("START TRANSACTION").Execute(); // Should return immediately since document isn't locked. rowResult = table2.Select().Where("id = 2").LockExclusive().Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the record ID"); + Assert.That(rowResult.FetchAll().Count, Is.EqualTo(1), "Matching the record ID"); // Session2 blocks due to to LockExclusive() not allowing to read locked documents. ExecuteSQLStatement(session2.SQL("SET SESSION innodb_lock_wait_timeout=1")); @@ -1531,12 +1531,12 @@ public void DoubleChainedLocksWithTwoSessions_S1() session.SQL("START TRANSACTION").Execute(); var rowResult = table.Select().Where("id = 1").LockShared().LockExclusive().Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the record ID"); + Assert.That(rowResult.FetchAll().Count, Is.EqualTo(1), "Matching the record ID"); session2.SQL("START TRANSACTION").Execute(); // Should return immediately since document isn't locked. rowResult = table2.Select().Where("id = 2").LockShared().LockExclusive().Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the record ID"); + Assert.That(rowResult.FetchAll().Count, Is.EqualTo(1), "Matching the record ID"); // Session2 blocks due to to LockExclusive() not allowing to read locked documents. ExecuteSQLStatement(session2.SQL("SET SESSION innodb_lock_wait_timeout=1")); @@ -1566,17 +1566,17 @@ public void DoubleChainedLocksWithTwoSessions_S2() session.SQL("START TRANSACTION").Execute(); var rowResult = table.Select().Where("id = 1").LockShared().Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the record ID"); + Assert.That(rowResult.FetchAll().Count, Is.EqualTo(1), "Matching the record ID"); session2.SQL("START TRANSACTION").Execute(); // Should return immediately since document isn't locked. rowResult = table2.Select().Where("id = 1").Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the record ID"); + Assert.That(rowResult.FetchAll().Count, Is.EqualTo(1), "Matching the record ID"); // Session2 blocks due to to LockExclusive() not allowing to read locked documents. ExecuteSQLStatement(session2.SQL("SET SESSION innodb_lock_wait_timeout=1")); var result = table2.Update().Where("id = 2").Set("age", 30).Execute(); - Assert.AreEqual(1, (int)result.AffectedItemsCount, "Match being done"); + Assert.That((int)result.AffectedItemsCount, Is.EqualTo(1), "Match being done"); Assert.Throws(() => ExecuteSelectStatement(table2.Select().Where("id = 1").LockExclusive())); // Session2 blocks due to to LockExclusive() not allowing to modify locked documents. @@ -1596,17 +1596,17 @@ public void DoubleChainedLocksWithTwoSessions_S2() session.SQL("START TRANSACTION").Execute(); var rowResult = table.Select().Where("id = 1").LockExclusive().LockShared().Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the record ID"); + Assert.That(rowResult.FetchAll().Count, Is.EqualTo(1), "Matching the record ID"); session2.SQL("START TRANSACTION").Execute(); // Should return immediately since document isn't locked. rowResult = table2.Select().Where("id = 1").Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the record ID"); + Assert.That(rowResult.FetchAll().Count, Is.EqualTo(1), "Matching the record ID"); // Session2 blocks due to to LockExclusive() not allowing to read locked documents. session2.SQL("SET SESSION innodb_lock_wait_timeout=1").Execute(); var result = table2.Update().Where("id = 2").Set("age", 30).Execute(); - Assert.AreEqual(1, (int)result.AffectedItemsCount, "Match being done"); + Assert.That((int)result.AffectedItemsCount, Is.EqualTo(1), "Match being done"); Assert.Throws(() => ExecuteSelectStatement(table2.Select().Where("id = 1").LockShared().LockExclusive())); // Session2 blocks due to to LockExclusive() not allowing to modify locked documents. @@ -1633,12 +1633,12 @@ public void SingleExclusiveLock() session.SQL("START TRANSACTION").Execute(); var rowResult = table.Select().Where("id = 1").LockExclusive().Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the record ID"); + Assert.That(rowResult.FetchAll().Count, Is.EqualTo(1), "Matching the record ID"); session2.SQL("START TRANSACTION").Execute(); // Should return immediately since document isn't locked. rowResult = table2.Select().Where("id = 2").Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the record ID"); + Assert.That(rowResult.FetchAll().Count, Is.EqualTo(1), "Matching the record ID"); // Session2 blocks due to to LockExclusive() not allowing to read locked documents. session2.SQL("SET SESSION innodb_lock_wait_timeout=1").Execute(); @@ -1664,16 +1664,16 @@ public void SingleTransactionWithLocks() session.SQL("START TRANSACTION").Execute(); var rowResult = table.Select().Where("id in (1,3)").LockShared().Execute(); - Assert.AreEqual(2, rowResult.FetchAll().Count, "Matching the record ID"); + Assert.That(rowResult.FetchAll().Count, Is.EqualTo(2), "Matching the record ID"); rowResult = table2.Select().Where("id = 2").LockExclusive().Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the record ID"); + Assert.That(rowResult.FetchAll().Count, Is.EqualTo(1), "Matching the record ID"); rowResult = table2.Select().Where("id = 2").LockShared().Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the record ID"); + Assert.That(rowResult.FetchAll().Count, Is.EqualTo(1), "Matching the record ID"); // Session2 blocks due to to LockExclusive() not allowing to read locked documents. session.SQL("SET SESSION innodb_lock_wait_timeout=1").Execute(); table2.Select().Where("id = 2").LockExclusive().Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the record ID"); + Assert.That(rowResult.FetchAll().Count, Is.EqualTo(1), "Matching the record ID"); session2.SQL("SET SESSION innodb_lock_wait_timeout=1").Execute(); Assert.Throws(() => ExecuteSelectStatement(table2.Select().Where("id = 1").LockExclusive())); @@ -1683,10 +1683,10 @@ public void SingleTransactionWithLocks() session.SQL("ROLLBACK").Execute(); rowResult = table2.Select().Where("id = 1").LockExclusive().Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); + Assert.That(rowResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID"); session2.SQL("ROLLBACK").Execute(); rowResult = table.Select().Where("id = 2").LockExclusive().Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); + Assert.That(rowResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID"); } } @@ -1710,12 +1710,12 @@ public void IteratedExclusiveLocks() session.SQL("START TRANSACTION").Execute(); var rowResult = table.Select().Where("id = 1").LockExclusive().Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the record ID"); + Assert.That(rowResult.FetchAll().Count, Is.EqualTo(1), "Matching the record ID"); session2.SQL("START TRANSACTION").Execute(); // Should return immediately since document isn't locked. rowResult = table2.Select().Where("id = 2").LockExclusive().Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the record ID"); + Assert.That(rowResult.FetchAll().Count, Is.EqualTo(1), "Matching the record ID"); // Session2 blocks due to to LockExclusive() not allowing to read locked documents. session2.SQL("SET SESSION innodb_lock_wait_timeout=1").Execute(); diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/TableUpdateTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/TableUpdateTests.cs index 5ea8882b3..da0dcdd62 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/TableUpdateTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/TableUpdateTests.cs @@ -57,7 +57,7 @@ public void SetUp() insertStatement.Values(i, i, i); } ExecuteInsertStatement(insertStatement); - Assert.AreEqual(rowsToInsert, CountRows()); + Assert.That(CountRows(), Is.EqualTo(rowsToInsert)); } private int CountRows() @@ -90,7 +90,7 @@ private void ValidateUpdate(TableUpdateStatement statement) { foreach (var set in statement.updates) { - Assert.AreEqual(set.Value.ToString(), row.GetString(set.Path)); + Assert.That(row.GetString(set.Path), Is.EqualTo(set.Value.ToString())); } } } @@ -146,17 +146,17 @@ public void UpdateBind() public void UpdateWithInOperator() { Table table = testSchema.GetTable("test"); - Assert.AreEqual(10, CountRows()); + Assert.That(CountRows(), Is.EqualTo(10)); - Assert.AreEqual(2, ExecuteUpdateStatement(table.Update().Where("id IN (1,2)").Set("id", 0)).AffectedItemsCount); - Assert.AreEqual(2, ExecuteSelectStatement(table.Select().Where("id = 0")).FetchAll().Count); + Assert.That(ExecuteUpdateStatement(table.Update().Where("id IN (1,2)").Set("id", 0)).AffectedItemsCount, Is.EqualTo(2)); + Assert.That(ExecuteSelectStatement(table.Select().Where("id = 0")).FetchAll().Count, Is.EqualTo(2)); Assert.Throws(() => ExecuteDeleteStatement(table.Delete().Where("a IN [3]"))); Assert.Throws(() => ExecuteDeleteStatement(table.Delete().Where("3 IN a"))); Assert.Throws(() => ExecuteUpdateStatement(table.Update().Where("age IN [3]").Set("id", 0))); - Assert.AreEqual(1, ExecuteUpdateStatement(table.Update().Where("age IN (3)").Set("id", 0)).AffectedItemsCount); - Assert.AreEqual(3, ExecuteSelectStatement(table.Select().Where("id = 0")).FetchAll().Count); + Assert.That(ExecuteUpdateStatement(table.Update().Where("age IN (3)").Set("id", 0)).AffectedItemsCount, Is.EqualTo(1)); + Assert.That(ExecuteSelectStatement(table.Select().Where("id = 0")).FetchAll().Count, Is.EqualTo(3)); } #region WL14389 @@ -196,46 +196,46 @@ public void TableSelectGroupBy() t = table.Select().Limit(2).Offset(1000000).Execute(); result = table.Select().GroupBy("age").Execute(); - Assert.AreEqual(5, result.FetchAll().Count); + Assert.That(result.FetchAll().Count, Is.EqualTo(5)); // GroupBy with null. result = table.Select("id as ID", "name as Name", "age as Age").GroupBy(null).Execute(); - Assert.AreEqual(7, result.FetchAll().Count); + Assert.That(result.FetchAll().Count, Is.EqualTo(7)); result = table.Select("id as ID", "name as Name", "age as Age").GroupBy(null, null).Execute(); - Assert.AreEqual(7, result.FetchAll().Count); + Assert.That(result.FetchAll().Count, Is.EqualTo(7)); result = table.Select("id as ID", "name as Name", "age as Age").GroupBy(null, "age").Execute(); - Assert.AreEqual(5, result.FetchAll().Count); + Assert.That(result.FetchAll().Count, Is.EqualTo(5)); // Having operation. // Having reduces the original 5 rows to 3 since 2 rows have a cnt=2, due to the repeated names. result = table.Select("id", "count(name) as cnt", "age").GroupBy("age").Having("cnt = 1").Execute(); - Assert.AreEqual(3, result.FetchAll().Count); + Assert.That(result.FetchAll().Count, Is.EqualTo(3)); // Having with null. result = table.Select("id as ID", "count(name) as cnt", "age as Age").GroupBy("age").Having(null).Execute(); - Assert.AreEqual(5, result.FetchAll().Count); + Assert.That(result.FetchAll().Count, Is.EqualTo(5)); // GroupBy with invalid field name. Exception ex = Assert.Throws(() => ExecuteSelectStatement(table.Select("id as ID", "name as Name", "age as Age").GroupBy("Required"))); - Assert.AreEqual("Unknown column 'Required' in 'group statement'", ex.Message); + Assert.That(ex.Message, Is.EqualTo("Unknown column 'Required' in 'group statement'")); ex = Assert.Throws(() => ExecuteSelectStatement(table.Select("id as ID", "name as Name", "age as Age").GroupBy(""))); - Assert.AreEqual("No more tokens when expecting one at token pos 0", ex.Message); + Assert.That(ex.Message, Is.EqualTo("No more tokens when expecting one at token pos 0")); ex = Assert.Throws(() => ExecuteSelectStatement(table.Select("id as ID", "name as Name", "age as Age").GroupBy(" "))); - Assert.AreEqual("No more tokens when expecting one at token pos 0", ex.Message); + Assert.That(ex.Message, Is.EqualTo("No more tokens when expecting one at token pos 0")); ex = Assert.Throws(() => ExecuteSelectStatement(table.Select("id as ID", "name as Name", "age as Age").GroupBy(string.Empty))); - Assert.AreEqual("No more tokens when expecting one at token pos 0", ex.Message); + Assert.That(ex.Message, Is.EqualTo("No more tokens when expecting one at token pos 0")); ex = Assert.Throws(() => ExecuteSelectStatement(table.Select("id as ID", "count(name) as cnt", "age as Age").GroupBy("age").Having("Required = 1"))); - Assert.AreEqual("Unknown column 'Required' in 'having clause'", ex.Message); + Assert.That(ex.Message, Is.EqualTo("Unknown column 'Required' in 'having clause'")); ex = Assert.Throws(() => ExecuteSelectStatement(table.Select("id as ID", "count(name) as cnt", "age as Age").GroupBy("age").Having(""))); - Assert.AreEqual("Unable to parse query ''", ex.Message); - Assert.AreEqual("No more tokens when expecting one at token pos 0", ex.InnerException.Message); + Assert.That(ex.Message, Is.EqualTo("Unable to parse query ''")); + Assert.That(ex.InnerException.Message, Is.EqualTo("No more tokens when expecting one at token pos 0")); Assert.Throws(() => ExecuteSelectStatement(table.Select("id as ID", "count(name) as cnt", "age as Age").GroupBy("age").Having(" "))); Assert.Throws(() => ExecuteSelectStatement(table.Select("id as ID", "count(name) as cnt", "age as Age").GroupBy("age").Having(string.Empty))); @@ -258,12 +258,12 @@ public void ExclusiveLockBeforeSharedLockDefaultWaiting() session.SQL("START TRANSACTION").Execute(); var rowResult = table.Select().Where("id = 1").LockExclusive().Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); + Assert.That(rowResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID"); session2.SQL("START TRANSACTION").Execute(); // Should return immediately since document isn't locked. rowResult = table2.Select().Where("id = 2").LockShared(LockContention.Default).Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); + Assert.That(rowResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID"); // Session2 blocks due to to LockExclusive() not allowing to read locked documents. session2.SQL("SET SESSION innodb_lock_wait_timeout=1").Execute(); @@ -276,7 +276,7 @@ public void ExclusiveLockBeforeSharedLockDefaultWaiting() // Session2 returns immediately as session is committed. session.Commit(); var result = table2.Update().Where("id = 1").Set("a", 2).Execute(); - Assert.AreEqual(1, (int)result.AffectedItemsCount, "Matching the deleted record count"); + Assert.That((int)result.AffectedItemsCount, Is.EqualTo(1), "Matching the deleted record count"); session.SQL("ROLLBACK").Execute(); session2.SQL("ROLLBACK").Execute(); @@ -299,16 +299,16 @@ public void SharedLockDefaultWaiting() session.SQL("START TRANSACTION").Execute(); var rowResult = table.Select().Where("id = 1").LockShared().Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); + Assert.That(rowResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID"); session2.SQL("START TRANSACTION").Execute(); // Should return immediately since document isn't locked. rowResult = table2.Select().Where("id = 2").LockShared(LockContention.Default).Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); + Assert.That(rowResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID"); session2.SQL("SET SESSION innodb_lock_wait_timeout=1").Execute(); rowResult = table2.Select().Where("id = 1").LockShared(LockContention.Default).Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); + Assert.That(rowResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID"); // Session2 blocks due to to LockShared() not allowing to modify locked documents. Result result1; Assert.Throws(() => result1 = table2.Update().Where("id = 1").Set("a", 2).Execute()); @@ -339,12 +339,12 @@ public void OnlyExclusiveLocksWithDefaultWaiting() session.SQL("START TRANSACTION").Execute(); var rowResult = table.Select().Where("id = 1").LockExclusive().Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); + Assert.That(rowResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID"); session2.SQL("START TRANSACTION").Execute(); // Should return immediately since document isn't locked. rowResult = table2.Select().Where("id = 2").LockExclusive(LockContention.Default).Execute(); - Assert.AreEqual(1, rowResult.FetchAll().Count, "Matching the document ID"); + Assert.That(rowResult.FetchAll().Count, Is.EqualTo(1), "Matching the document ID"); // Session2 blocks due to to LockExclusive() not allowing to read locked documents. session2.SQL("SET SESSION innodb_lock_wait_timeout=1").Execute(); diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/ViewTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/ViewTests.cs index 3d046bc76..9548fdd96 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/ViewTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/ViewTests.cs @@ -54,12 +54,12 @@ public void TryUpdatingView() ExecuteSQL("CREATE VIEW view2 AS select *, 1 from test"); List
tables = testSchema.GetTables(); - Assert.AreEqual(2, tables.Count); + Assert.That(tables.Count, Is.EqualTo(2)); Table view = tables.First(i => i.IsView); - Assert.AreEqual("view2", view.Name); + Assert.That(view.Name, Is.EqualTo("view2")); MySqlException ex = Assert.Throws(() => ExecuteInsertStatement(view.Insert().Values(1))); - Assert.AreEqual("Column '1' is not updatable", ex.Message); + Assert.That(ex.Message, Is.EqualTo("Column '1' is not updatable")); } [Test] @@ -70,8 +70,8 @@ public void GetView() Table table = testSchema.GetTable("test"); Table view = testSchema.GetTable("view1"); - Assert.True(view.IsView); - Assert.False(table.IsView); + Assert.That(view.IsView); + Assert.That(table.IsView, Is.False); ExecuteSQL("DROP VIEW view1"); } @@ -100,13 +100,13 @@ public void CreateJoinAndGetTableValidation() ExecuteSQL("CREATE VIEW view2 AS select * from test.test2"); var tables = testSchema.GetTables(); - Assert.AreEqual(true, tables.Count == 4, "Match being done"); - Assert.AreEqual(2, tables.Count(i => !i.IsView), "Match being done when isview not true"); - Assert.AreEqual(2, tables.Count(i => i.IsView), "Match being done when isview true"); + Assert.That(tables.Count == 4, Is.EqualTo(true), "Match being done"); + Assert.That(tables.Count(i => !i.IsView), Is.EqualTo(2), "Match being done when isview not true"); + Assert.That(tables.Count(i => i.IsView), Is.EqualTo(2), "Match being done when isview true"); List colls = testSchema.GetCollections(); - Assert.AreEqual(1, colls.Count, "Match being done"); + Assert.That(colls.Count, Is.EqualTo(1), "Match being done"); var view1 = testSchema.GetTable("view1"); - Assert.True(view1.IsView); + Assert.That(view1.IsView); //Valid Scenario-1 view1.Select().Execute(); @@ -125,7 +125,7 @@ public void CreateJoinAndGetTableValidation() "CREATE VIEW myView AS SELECT a.ID1 as a_tID,b.ID2 as b_tID, a.firstname as a_firstname, " + "b.lastname as b_lastname FROM test1 a JOIN test2 b ON a.ID1=b.ID2;"); var joinedview = testSchema.GetTable("myView"); - Assert.True(joinedview.IsView); + Assert.That(joinedview.IsView); joinedview.Select().Execute(); result = joinedview.Update().Set("a_firstname", "Peter").Where("a_tID=1").Execute(); @@ -137,7 +137,7 @@ public void CreateJoinAndGetTableValidation() //Valid View - Invalid Select/Insert/Update Statements-Scenario-3 var view2 = testSchema.GetTable("view2"); - Assert.True(view2.IsView); + Assert.That(view2.IsView); Assert.Throws(() => view2.Select("id2", "age").Execute()); @@ -148,7 +148,7 @@ public void CreateJoinAndGetTableValidation() view2.Select().Execute(); var res = view2.Delete().Where("id2=100").Execute(); - Assert.AreEqual(0, res.AffectedItemsCount, "View2-Not Possible to remove an invalid record"); + Assert.That(res.AffectedItemsCount, Is.EqualTo(0), "View2-Not Possible to remove an invalid record"); //View Doesn't Exist-Scenario-4 var view3 = testSchema.GetTable("view3"); @@ -160,7 +160,7 @@ public void CreateJoinAndGetTableValidation() //View Passed as Null-Scenario-6 var view4 = testSchema.GetTable("test1"); - Assert.IsFalse(view4.IsView); + Assert.That(view4.IsView, Is.False); //Change the query processing env-Scenario-7 ExecuteSQL("SET sql_mode = '';"); @@ -187,14 +187,14 @@ public void ViewsGetTables() ExecuteSQL("CREATE VIEW view2 AS select * from test.test2"); ExecuteSQL("SELECT * FROM view2"); var tables = testSchema.GetTables(); - Assert.True(tables.Count >= 4, "Match being done"); - Assert.AreEqual(2, tables.Count(i => !i.IsView), "Match being done when isview not true"); - Assert.AreEqual(2, tables.Count(i => i.IsView), "Match being done when isview true"); + Assert.That(tables.Count >= 4, "Match being done"); + Assert.That(tables.Count(i => !i.IsView), Is.EqualTo(2), "Match being done when isview not true"); + Assert.That(tables.Count(i => i.IsView), Is.EqualTo(2), "Match being done when isview true"); List colls = testSchema.GetCollections(); - Assert.AreEqual(1, colls.Count, "Match being done"); + Assert.That(colls.Count, Is.EqualTo(1), "Match being done"); var view1 = tables[2]; - Assert.True(view1.IsView); + Assert.That(view1.IsView); //Valid Scenario-1 view1.Select().Execute(); @@ -213,7 +213,7 @@ public void ViewsGetTables() "CREATE VIEW myView AS SELECT a.ID1 as a_tID,b.ID2 as b_tID, a.firstname as a_firstname, " + "b.lastname as b_lastname FROM test1 a JOIN test2 b ON a.ID1=b.ID2;"); var joinedview = testSchema.GetTables(); - Assert.True(joinedview[0].IsView); + Assert.That(joinedview[0].IsView); joinedview[0].Select().Execute(); result = joinedview[0].Update().Set("a_firstname", "Peter").Where("a_tID=1").Execute(); result = joinedview[0].Update().Set("a_firstname", "Rob").Where("a_tID=1").Execute(); @@ -225,7 +225,7 @@ public void ViewsGetTables() ExecuteSQL("DROP VIEW " + joinedview[0].Name); //Valid View - Invalid Select/Insert/Update Statements-Scenario-3 var view2 = testSchema.GetTables(); - Assert.True(view2[3].IsView); + Assert.That(view2[3].IsView); Assert.Throws(() => view2[3].Select("id2", "age").Execute()); @@ -238,7 +238,7 @@ public void ViewsGetTables() view2[3].Select().Execute(); var res = view2[3].Delete().Where("id2=100").Execute(); //WL11843-Core API v1 alignment Changes - Assert.AreEqual(0, res.AffectedItemsCount); + Assert.That(res.AffectedItemsCount, Is.EqualTo(0)); //Change the query processing env-Scenario-5 ExecuteSQL("SET sql_mode = '';"); @@ -250,7 +250,7 @@ public void ViewsGetTables() ExecuteSQL("DROP VIEW view2"); //GetTables when there no tables/views -Scenario-4 var view3 = testSchema.GetTables(); - Assert.AreEqual(0, view3.Count()); + Assert.That(view3.Count(), Is.EqualTo(0)); } #endregion WL14389 diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/SchemaTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/SchemaTests.cs index 95e68b92d..9f66e0459 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/SchemaTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/SchemaTests.cs @@ -48,12 +48,12 @@ public void GetSchemas() Session session = GetSession(); List schemas = session.GetSchemas(); - Assert.True(schemas.Exists(s => s.Name == base.testSchema.Name)); + Assert.That(schemas.Exists(s => s.Name == base.testSchema.Name)); Schema schema = session.GetSchema(schemaName); - Assert.AreEqual(schemaName, schema.Name); + Assert.That(schema.Name, Is.EqualTo(schemaName)); schema = session.GetSchema(null); - Assert.IsNull(schema.Name); + Assert.That(schema.Name, Is.Null); } [Test] @@ -61,7 +61,7 @@ public void GetInvalidSchema() { Session s = GetSession(); Schema schema = s.GetSchema("test-schema"); - Assert.False(SchemaExistsInDatabase(schema)); + Assert.That(SchemaExistsInDatabase(schema), Is.False); } [Test] @@ -71,7 +71,7 @@ public void GetAllTables() ExecuteSQL("CREATE TABLE test(id int)"); List
tables = testSchema.GetTables(); - Assert.True(tables.Count == 1); + Assert.That(tables.Count == 1); } [Test] @@ -85,9 +85,9 @@ public void GetAllViews() ExecuteSQL("CREATE VIEW view2 AS select * from test"); List
tables = testSchema.GetTables(); - Assert.AreEqual(3, tables.Count); - Assert.AreEqual(1, tables.Count(i => !i.IsView)); - Assert.AreEqual(2, tables.Count(i => i.IsView)); + Assert.That(tables.Count, Is.EqualTo(3)); + Assert.That(tables.Count(i => !i.IsView), Is.EqualTo(1)); + Assert.That(tables.Count(i => i.IsView), Is.EqualTo(2)); List colls = testSchema.GetCollections(); Assert.That(colls, Has.One.Items); @@ -100,14 +100,14 @@ public void GetCollectionAsTable() Collection testCollection = CreateCollection("test"); Result r = ExecuteAddStatement(testCollection.Add(@"{ ""_id"": 1, ""foo"": 1 }")); - Assert.AreEqual(1, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(1)); Table test = testSchema.GetCollectionAsTable("test"); - Assert.True(TableExistsInDatabase(test)); + Assert.That(TableExistsInDatabase(test)); RowResult result = ExecuteSelectStatement(test.Select("_id")); - Assert.True(result.Next()); - Assert.AreEqual("1", result[0]); + Assert.That(result.Next()); + Assert.That(result[0], Is.EqualTo("1")); } [Test] @@ -117,15 +117,15 @@ public void DropSchema() Session session = GetSession(); session.CreateSchema(schemaName); Schema schema = session.GetSchema(schemaName); - Assert.True(SchemaExistsInDatabase(schema)); + Assert.That(SchemaExistsInDatabase(schema)); // Drop existing schema. session.DropSchema(schemaName); - Assert.False(SchemaExistsInDatabase(schema)); + Assert.That(SchemaExistsInDatabase(schema), Is.False); // Drop non-existing schema. session.DropSchema(schemaName); - Assert.False(SchemaExistsInDatabase(schema)); + Assert.That(SchemaExistsInDatabase(schema), Is.False); // Empty, whitespace and null schema name. Assert.Throws(() => session.DropSchema(string.Empty)); @@ -203,7 +203,7 @@ public void CreateValidSchema() db = session.CreateSchema("test_123456789"); } else { db = session.CreateSchema("test_123456789"); } - Assert.True(db.ExistsInDatabase()); + Assert.That(db.ExistsInDatabase()); Assert.Throws(() => session.CreateSchema("test_123456789")); session.DropSchema("test_123456789"); Assert.Throws(() => session.CreateSchema("test_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789")); @@ -217,10 +217,10 @@ public void SessionSetSchema() if (!session.GetSchema("test1").ExistsInDatabase()) session.CreateSchema("test1"); Assert.DoesNotThrow(() => session.SetCurrentSchema("test1")); - Assert.AreEqual("test1", session.Schema.Name); + Assert.That(session.Schema.Name, Is.EqualTo("test1")); // Retry the same schema Assert.DoesNotThrow(() => session.SetCurrentSchema("test1")); - Assert.AreEqual("test1", session.Schema.Name); + Assert.That(session.Schema.Name, Is.EqualTo("test1")); session.Schema.CreateCollection("my_collection_123456789"); session.Schema.DropCollection("my_collection_123456789"); //Exceptions @@ -231,7 +231,7 @@ public void SessionSetSchema() //No Active Schema using (Session sessionPlain = MySQLX.GetSession(ConnectionString)) { - Assert.IsNull(sessionPlain.GetCurrentSchema()); + Assert.That(sessionPlain.GetCurrentSchema(), Is.Null); } } @@ -257,7 +257,7 @@ public void SessionChangeCurrentSchema() session.SQL("DROP DATABASE IF EXISTS dbname1").Execute(); session.SQL("CREATE DATABASE dbname1").Execute(); session.SQL("USE dbname1").Execute(); - StringAssert.AreEqualIgnoringCase("dbname1", session.GetCurrentSchema().Name); + Assert.That(session.GetCurrentSchema().Name, Is.EqualTo("dbname1").IgnoreCase); session.SQL("CREATE TABLE address1" + "(address_number INT NOT NULL AUTO_INCREMENT, " + "building_name VARCHAR(100) NOT NULL, " + @@ -270,7 +270,7 @@ public void SessionChangeCurrentSchema() session.SQL("DROP DATABASE IF EXISTS dbname2").Execute(); session.SQL("CREATE DATABASE dbname2").Execute(); session.SQL("USE dbname2").Execute(); - StringAssert.AreEqualIgnoringCase("dbname2", session.GetCurrentSchema().Name); + Assert.That(session.GetCurrentSchema().Name, Is.EqualTo("dbname2").IgnoreCase); session.SQL("CREATE TABLE address2" + "(address_number INT NOT NULL AUTO_INCREMENT, " + "building_name VARCHAR(100) NOT NULL, " + @@ -280,11 +280,11 @@ public void SessionChangeCurrentSchema() " VALUES " + "(2,'MySQL2','BGL2');").Execute(); session.SetCurrentSchema("dbname1"); - Assert.AreEqual("dbname1", session.Schema.Name); + Assert.That(session.Schema.Name, Is.EqualTo("dbname1")); session.SQL("SELECT * FROM address1").Execute(); session.SQL("DROP TABLE address1").Execute(); session.SetCurrentSchema("dbname2"); - StringAssert.AreEqualIgnoringCase("dbName2", session.Schema.Name); + Assert.That(session.Schema.Name, Is.EqualTo("dbName2").IgnoreCase); session.SQL("SELECT * FROM address2").Execute(); session.SQL("DROP TABLE address2").Execute(); session.SQL("DROP DATABASE dbname1").Execute(); diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/SessionTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/SessionTests.cs index 13f0ff70c..78aedaa65 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/SessionTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/SessionTests.cs @@ -50,9 +50,9 @@ public class SessionTests : BaseTest public void CanCloseSession() { Session s = MySQLX.GetSession(ConnectionString); - Assert.True(s.InternalSession.SessionState == SessionState.Open); + Assert.That(s.InternalSession.SessionState == SessionState.Open); s.Close(); - Assert.AreEqual(s.InternalSession.SessionState, SessionState.Closed); + Assert.That(SessionState.Closed, Is.EqualTo(s.InternalSession.SessionState)); } [Test] @@ -60,9 +60,9 @@ public void CanCloseSession() public void NoPassword() { Session session = MySQLX.GetSession(ConnectionStringNoPassword); - Assert.True(session.InternalSession.SessionState == SessionState.Open); + Assert.That(session.InternalSession.SessionState == SessionState.Open); session.Close(); - Assert.AreEqual(session.InternalSession.SessionState, SessionState.Closed); + Assert.That(SessionState.Closed, Is.EqualTo(session.InternalSession.SessionState)); } [Test] @@ -70,9 +70,9 @@ public void NoPassword() public void SessionClose() { Session session = MySQLX.GetSession(ConnectionString); - Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); + Assert.That(session.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); session.Close(); - Assert.AreEqual(SessionState.Closed, session.InternalSession.SessionState); + Assert.That(session.InternalSession.SessionState, Is.EqualTo(SessionState.Closed)); } [Test] @@ -89,15 +89,15 @@ public void CountClosedSession() for (int i = 0; i < 20; i++) { Session session = MySQLX.GetSession(ConnectionString); - Assert.True(session.InternalSession.SessionState == SessionState.Open); + Assert.That(session.InternalSession.SessionState == SessionState.Open); session.Close(); - Assert.AreEqual(session.InternalSession.SessionState, SessionState.Closed); + Assert.That(SessionState.Closed, Is.EqualTo(session.InternalSession.SessionState)); } newSessions = ExecuteSQLStatement(nodeSession.SQL("show processlist")).FetchAll().Count; } - Assert.AreEqual(sessions, newSessions); + Assert.That(newSessions, Is.EqualTo(sessions)); } [Test] @@ -114,7 +114,7 @@ public void ConnectionStringAsAnonymousType() using (var testSession = MySQLX.GetSession(connstring)) { - Assert.AreEqual(SessionState.Open, testSession.InternalSession.SessionState); + Assert.That(testSession.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); } } @@ -124,12 +124,12 @@ public void SessionGetSetCurrentSchema() { using (Session testSession = MySQLX.GetSession(ConnectionString)) { - Assert.AreEqual(SessionState.Open, testSession.InternalSession.SessionState); - Assert.Null(testSession.GetCurrentSchema()); + Assert.That(testSession.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); + Assert.That(testSession.GetCurrentSchema(), Is.Null); Assert.Throws(() => testSession.SetCurrentSchema("")); testSession.SetCurrentSchema(schemaName); - Assert.AreEqual(schemaName, testSession.Schema.Name); - Assert.AreEqual(schemaName, testSession.GetCurrentSchema().Name); + Assert.That(testSession.Schema.Name, Is.EqualTo(schemaName)); + Assert.That(testSession.GetCurrentSchema().Name, Is.EqualTo(schemaName)); } } @@ -139,10 +139,10 @@ public void SessionUsingSchema() { using (Session mySession = MySQLX.GetSession(ConnectionString + $";database={schemaName};")) { - Assert.AreEqual(SessionState.Open, mySession.InternalSession.SessionState); - Assert.AreEqual(schemaName, mySession.Schema.Name); - Assert.AreEqual(schemaName, mySession.GetCurrentSchema().Name); - Assert.True(SchemaExistsInDatabase(mySession.Schema)); + Assert.That(mySession.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); + Assert.That(mySession.Schema.Name, Is.EqualTo(schemaName)); + Assert.That(mySession.GetCurrentSchema().Name, Is.EqualTo(schemaName)); + Assert.That(SchemaExistsInDatabase(mySession.Schema)); } } @@ -152,19 +152,19 @@ public void SessionUsingDefaultSchema() { using (Session mySession = MySQLX.GetSession(ConnectionString + $";database={schemaName};")) { - Assert.AreEqual(SessionState.Open, mySession.InternalSession.SessionState); - Assert.AreEqual(schemaName, mySession.DefaultSchema.Name); - Assert.AreEqual(schemaName, mySession.GetCurrentSchema().Name); - Assert.True(mySession.Schema.ExistsInDatabase()); + Assert.That(mySession.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); + Assert.That(mySession.DefaultSchema.Name, Is.EqualTo(schemaName)); + Assert.That(mySession.GetCurrentSchema().Name, Is.EqualTo(schemaName)); + Assert.That(mySession.Schema.ExistsInDatabase()); mySession.SetCurrentSchema("mysql"); - Assert.AreNotEqual(mySession.DefaultSchema.Name, mySession.Schema.Name); + Assert.That(mySession.Schema.Name, Is.Not.EqualTo(mySession.DefaultSchema.Name)); } // DefaultSchema is null because no database was provided in the connection string/URI. using (Session mySession = MySQLX.GetSession(ConnectionString)) { - Assert.AreEqual(SessionState.Open, mySession.InternalSession.SessionState); - Assert.Null(mySession.DefaultSchema); + Assert.That(mySession.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); + Assert.That(mySession.DefaultSchema, Is.Null); } } @@ -184,7 +184,7 @@ public void SessionUsingDefaultSchemaWithAnonymousObject() database = "mysql" })) { - Assert.AreEqual("mysql", internalSession.DefaultSchema.Name); + Assert.That(internalSession.DefaultSchema.Name, Is.EqualTo("mysql")); } // DefaultSchema is null when no database is provided. @@ -197,7 +197,7 @@ public void SessionUsingDefaultSchemaWithAnonymousObject() sslmode = MySqlSslMode.Required, })) { - Assert.Null(internalSession.DefaultSchema); + Assert.That(internalSession.DefaultSchema, Is.Null); } // Access denied error is raised when database does not exist for servers 8.0.12 and below. @@ -216,9 +216,9 @@ public void SessionUsingDefaultSchemaWithAnonymousObject() )); if (session.InternalSession.GetServerVersion().isAtLeast(8, 0, 13)) - StringAssert.StartsWith(string.Format("Unknown database 'test1'"), exception.Message); + Assert.That(exception.Message, Does.StartWith(string.Format("Unknown database 'test1'"))); else - StringAssert.StartsWith(string.Format("Access denied"), exception.Message); + Assert.That(exception.Message, Does.StartWith(string.Format("Access denied"))); } [Test] @@ -227,7 +227,7 @@ public void SessionUsingDefaultSchemaWithConnectionURI() { using (var session = MySQLX.GetSession(ConnectionStringUri + "?database=mysql")) { - Assert.AreEqual("mysql", session.DefaultSchema.Name); + Assert.That(session.DefaultSchema.Name, Is.EqualTo("mysql")); } } @@ -284,7 +284,7 @@ public void ConnectionUsingUri() { using (var session = MySQLX.GetSession(ConnectionStringUri)) { - Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); + Assert.That(session.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); } } @@ -307,7 +307,7 @@ public void IPv6() using (var session = MySQLX.GetSession(csBuilder.ToString())) { - Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); + Assert.That(session.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); } } @@ -322,7 +322,7 @@ public void IPv6AsUrl() string connString = $"mysqlx://{csBuilder.UserID}:{csBuilder.Password}@[{ipv6}]:{XPort}"; using (Session session = MySQLX.GetSession(connString)) { - Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); + Assert.That(session.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); } } @@ -336,7 +336,7 @@ public void IPv6AsAnonymous() using (Session session = MySQLX.GetSession(new { server = ipv6, user = csBuilder.UserID, password = csBuilder.Password, port = XPort })) { - Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); + Assert.That(session.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); } } @@ -349,89 +349,89 @@ public void CreateSessionWithUnsupportedOptions() // Use a connection URI. var ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "pipe=MYSQL")); - StringAssert.StartsWith(errorMessage, ex.Message); + Assert.That(ex.Message, Does.StartWith(errorMessage)); ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "compress=true")); - StringAssert.StartsWith(errorMessage, ex.Message); + Assert.That(ex.Message, Does.StartWith(errorMessage)); ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "allow batch=false")); - StringAssert.StartsWith(errorMessage, ex.Message); + Assert.That(ex.Message, Does.StartWith(errorMessage)); ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "logging=true")); - StringAssert.StartsWith(errorMessage, ex.Message); + Assert.That(ex.Message, Does.StartWith(errorMessage)); ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "sharedmemoryname=MYSQL")); - StringAssert.StartsWith(errorMessage, ex.Message); + Assert.That(ex.Message, Does.StartWith(errorMessage)); ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "defaultcommandtimeout=30")); - StringAssert.StartsWith(errorMessage, ex.Message); + Assert.That(ex.Message, Does.StartWith(errorMessage)); ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "usedefaultcommandtimeoutforef=true")); - StringAssert.StartsWith(errorMessage, ex.Message); + Assert.That(ex.Message, Does.StartWith(errorMessage)); ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "persistsecurityinfo=false")); - StringAssert.StartsWith(errorMessage, ex.Message); + Assert.That(ex.Message, Does.StartWith(errorMessage)); ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "encrypt=false")); - StringAssert.StartsWith(errorMessage, ex.Message); + Assert.That(ex.Message, Does.StartWith(errorMessage)); ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "integratedsecurity=true")); - StringAssert.StartsWith(errorMessage, ex.Message); + Assert.That(ex.Message, Does.StartWith(errorMessage)); ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "allowpublickeyretrieval=false")); - StringAssert.StartsWith(errorMessage, ex.Message); + Assert.That(ex.Message, Does.StartWith(errorMessage)); ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "autoenlist=true")); - StringAssert.StartsWith(errorMessage, ex.Message); + Assert.That(ex.Message, Does.StartWith(errorMessage)); ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "includesecurityasserts=false")); - StringAssert.StartsWith(errorMessage, ex.Message); + Assert.That(ex.Message, Does.StartWith(errorMessage)); ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "allowzerodatetime=true")); - StringAssert.StartsWith(errorMessage, ex.Message); + Assert.That(ex.Message, Does.StartWith(errorMessage)); ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "convert zero datetime=false")); - StringAssert.StartsWith(errorMessage, ex.Message); + Assert.That(ex.Message, Does.StartWith(errorMessage)); ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "useusageadvisor=true")); - StringAssert.StartsWith(errorMessage, ex.Message); + Assert.That(ex.Message, Does.StartWith(errorMessage)); ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "procedurecachesize=50")); - StringAssert.StartsWith(errorMessage, ex.Message); + Assert.That(ex.Message, Does.StartWith(errorMessage)); ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "useperformancemonitor=true")); - StringAssert.StartsWith(errorMessage, ex.Message); + Assert.That(ex.Message, Does.StartWith(errorMessage)); ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "respectbinaryflags=true")); - StringAssert.StartsWith(errorMessage, ex.Message); + Assert.That(ex.Message, Does.StartWith(errorMessage)); ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "treat tiny as boolean=false")); - StringAssert.StartsWith(errorMessage, ex.Message); + Assert.That(ex.Message, Does.StartWith(errorMessage)); ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "allowuservariables=true")); - StringAssert.StartsWith(errorMessage, ex.Message); + Assert.That(ex.Message, Does.StartWith(errorMessage)); ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "interactive=false")); - StringAssert.StartsWith(errorMessage, ex.Message); + Assert.That(ex.Message, Does.StartWith(errorMessage)); ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "functionsreturnstring=true")); - StringAssert.StartsWith(errorMessage, ex.Message); + Assert.That(ex.Message, Does.StartWith(errorMessage)); ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "useaffectedrows=false")); - StringAssert.StartsWith(errorMessage, ex.Message); + Assert.That(ex.Message, Does.StartWith(errorMessage)); ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "oldguids=true")); - StringAssert.StartsWith(errorMessage, ex.Message); + Assert.That(ex.Message, Does.StartWith(errorMessage)); ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "sqlservermode=false")); - StringAssert.StartsWith(errorMessage, ex.Message); + Assert.That(ex.Message, Does.StartWith(errorMessage)); ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "tablecaching=true")); - StringAssert.StartsWith(errorMessage, ex.Message); + Assert.That(ex.Message, Does.StartWith(errorMessage)); ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "defaulttablecacheage=60")); - StringAssert.StartsWith(errorMessage, ex.Message); + Assert.That(ex.Message, Does.StartWith(errorMessage)); ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "checkparameters=true")); - StringAssert.StartsWith(errorMessage, ex.Message); + Assert.That(ex.Message, Does.StartWith(errorMessage)); ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "replication=replication_group")); - StringAssert.StartsWith(errorMessage, ex.Message); + Assert.That(ex.Message, Does.StartWith(errorMessage)); ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "exceptioninterceptors=none")); - StringAssert.StartsWith(errorMessage, ex.Message); + Assert.That(ex.Message, Does.StartWith(errorMessage)); ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "commandinterceptors=none")); - StringAssert.StartsWith(errorMessage, ex.Message); + Assert.That(ex.Message, Does.StartWith(errorMessage)); ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "connectionlifetime=100")); - StringAssert.StartsWith(errorMessage, ex.Message); + Assert.That(ex.Message, Does.StartWith(errorMessage)); ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "pooling=false")); - StringAssert.StartsWith(errorMessage, ex.Message); + Assert.That(ex.Message, Does.StartWith(errorMessage)); ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "minpoolsize=0")); - StringAssert.StartsWith(errorMessage, ex.Message); + Assert.That(ex.Message, Does.StartWith(errorMessage)); ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "maxpoolsize=20")); - StringAssert.StartsWith(errorMessage, ex.Message); + Assert.That(ex.Message, Does.StartWith(errorMessage)); ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "connectionreset=false")); - StringAssert.StartsWith(errorMessage, ex.Message); + Assert.That(ex.Message, Does.StartWith(errorMessage)); ex = Assert.Throws(() => MySQLX.GetSession(connectionUri + "cacheserverproperties=true")); - StringAssert.StartsWith(errorMessage, ex.Message); + Assert.That(ex.Message, Does.StartWith(errorMessage)); // Use a connection string. ex = Assert.Throws(() => MySQLX.GetSession("treatblobsasutf8=false")); - StringAssert.StartsWith(errorMessage, ex.Message); + Assert.That(ex.Message, Does.StartWith(errorMessage)); ex = Assert.Throws(() => MySQLX.GetSession("blobasutf8includepattern=pattern")); - StringAssert.StartsWith(errorMessage, ex.Message); + Assert.That(ex.Message, Does.StartWith(errorMessage)); ex = Assert.Throws(() => MySQLX.GetSession("blobasutf8excludepattern=pattern")); - StringAssert.StartsWith(errorMessage, ex.Message); + Assert.That(ex.Message, Does.StartWith(errorMessage)); } [Test] @@ -440,15 +440,15 @@ public void CreateBuilderWithUnsupportedOptions() { var errorMessage = "Option not supported."; var ex = Assert.Throws(() => new MySqlXConnectionStringBuilder("pipe=MYSQL")); - StringAssert.StartsWith(errorMessage, ex.Message); + Assert.That(ex.Message, Does.StartWith(errorMessage)); ex = Assert.Throws(() => new MySqlXConnectionStringBuilder("allow batch=false")); - StringAssert.StartsWith(errorMessage, ex.Message); + Assert.That(ex.Message, Does.StartWith(errorMessage)); ex = Assert.Throws(() => new MySqlXConnectionStringBuilder("respectbinaryflags=true")); - StringAssert.StartsWith(errorMessage, ex.Message); + Assert.That(ex.Message, Does.StartWith(errorMessage)); ex = Assert.Throws(() => new MySqlXConnectionStringBuilder("pooling=false")); - StringAssert.StartsWith(errorMessage, ex.Message); + Assert.That(ex.Message, Does.StartWith(errorMessage)); ex = Assert.Throws(() => new MySqlXConnectionStringBuilder("cacheserverproperties=true")); - StringAssert.StartsWith(errorMessage, ex.Message); + Assert.That(ex.Message, Does.StartWith(errorMessage)); } [Test] @@ -466,11 +466,11 @@ public void GetUri() try { - Assert.AreEqual(session.Settings[connectionOption.Key], internalSession.Settings[connectionOption.Key]); + Assert.That(internalSession.Settings[connectionOption.Key], Is.EqualTo(session.Settings[connectionOption.Key])); } catch (ArgumentException ex) { - StringAssert.StartsWith("Option not supported.", ex.Message); + Assert.That(ex.Message, Does.StartWith("Option not supported.")); } } } @@ -489,15 +489,15 @@ public void ConnectTimeout() // ConnectionString. using (Session session = MySQLX.GetSession(ConnectionString + ";connect-timeout=5000;")) { - Assert.True(session.Settings.ConnectTimeout == 5000); - Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); + Assert.That(session.Settings.ConnectTimeout == 5000); + Assert.That(session.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); } // ConnectionURI. using (Session session = MySQLX.GetSession(ConnectionStringUri + "?connecttimeout=6500")) { - Assert.True(session.Settings.ConnectTimeout == 6500); - Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); + Assert.That(session.Settings.ConnectTimeout == 6500); + Assert.That(session.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); } // Anonymous Object using default value, 10000ms. @@ -512,8 +512,8 @@ public void ConnectTimeout() using (var testSession = MySQLX.GetSession(connstring)) { - Assert.True(session.Settings.ConnectTimeout == 10000); - Assert.AreEqual(SessionState.Open, testSession.InternalSession.SessionState); + Assert.That(session.Settings.ConnectTimeout == 10000); + Assert.That(testSession.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); } // Create a session using the fail over functionality passing two diferrent Server address(one of them is fake host). Must succeed after 2000ms @@ -537,46 +537,46 @@ public void ConnectTimeout() DateTime start = DateTime.Now; Assert.Throws(() => MySQLX.GetSession(conn)); TimeSpan diff = DateTime.Now.Subtract(start); - Assert.True(diff.TotalSeconds > 19 && diff.TotalSeconds < 21, String.Format("Timeout exceeded ({0}). Actual time: {1}", "Fail over failure", diff)); + Assert.That(diff.TotalSeconds > 19 && diff.TotalSeconds < 21, String.Format("Timeout exceeded ({0}). Actual time: {1}", "Fail over failure", diff)); // Valid session no time out start = DateTime.Now; using (Session session = MySQLX.GetSession(ConnectionStringUri + "?connecttimeout=2000")) session.SQL("SELECT SLEEP(10)").Execute(); diff = DateTime.Now.Subtract(start); - Assert.True(diff.TotalSeconds > 10); + Assert.That(diff.TotalSeconds > 10); //Invalid Values for Connection Timeout parameter var ex = Assert.Throws(() => MySQLX.GetSession(ConnectionString + ";connect-timeout=-1;")); - Assert.AreEqual(ResourcesX.InvalidConnectionTimeoutValue, ex.Message); + Assert.That(ex.Message, Is.EqualTo(ResourcesX.InvalidConnectionTimeoutValue)); ex = Assert.Throws(() => MySQLX.GetSession(ConnectionString + ";connect-timeout=foo;")); - Assert.AreEqual(ResourcesX.InvalidConnectionTimeoutValue, ex.Message); + Assert.That(ex.Message, Is.EqualTo(ResourcesX.InvalidConnectionTimeoutValue)); ex = Assert.Throws(() => MySQLX.GetSession(ConnectionString + ";connect-timeout='';")); - Assert.AreEqual(ResourcesX.InvalidConnectionTimeoutValue, ex.Message); + Assert.That(ex.Message, Is.EqualTo(ResourcesX.InvalidConnectionTimeoutValue)); ex = Assert.Throws(() => MySQLX.GetSession(ConnectionString + ";connect-timeout=10.5;")); - Assert.AreEqual(ResourcesX.InvalidConnectionTimeoutValue, ex.Message); + Assert.That(ex.Message, Is.EqualTo(ResourcesX.InvalidConnectionTimeoutValue)); ex = Assert.Throws(() => MySQLX.GetSession(ConnectionString + ";connect-timeout=" + Int32.MaxValue + 1)); - Assert.AreEqual(ResourcesX.InvalidConnectionTimeoutValue, ex.Message); + Assert.That(ex.Message, Is.EqualTo(ResourcesX.InvalidConnectionTimeoutValue)); ex = Assert.Throws(() => MySQLX.GetSession(ConnectionString + ";connect-timeout=10.5;")); - Assert.AreEqual(ResourcesX.InvalidConnectionTimeoutValue, ex.Message); + Assert.That(ex.Message, Is.EqualTo(ResourcesX.InvalidConnectionTimeoutValue)); ex = Assert.Throws(() => MySQLX.GetSession(ConnectionString + ";connect-timeout=;")); - Assert.AreEqual(ResourcesX.InvalidConnectionTimeoutValue, ex.Message); + Assert.That(ex.Message, Is.EqualTo(ResourcesX.InvalidConnectionTimeoutValue)); ex = Assert.Throws(() => MySQLX.GetSession(ConnectionStringUri + "?connect-timeout= ")); - Assert.AreEqual(ResourcesX.InvalidConnectionTimeoutValue, ex.Message); + Assert.That(ex.Message, Is.EqualTo(ResourcesX.InvalidConnectionTimeoutValue)); ex = Assert.Throws(() => MySQLX.GetSession(ConnectionStringUri + "?connecttimeout=")); - Assert.AreEqual(ResourcesX.InvalidConnectionTimeoutValue, ex.Message); + Assert.That(ex.Message, Is.EqualTo(ResourcesX.InvalidConnectionTimeoutValue)); // Valid value for ConnectionTimeout, invalid credentials var exception = Assert.Throws(() => MySQLX.GetSession($"server={Host};user=test;password=noPass;port={XPort};connect-timeout=2000;")); - Assert.NotNull(exception); + Assert.That(exception, Is.Not.Null); } private void TestConnectTimeoutFailureTimeout(String connString, int minTime, int maxTime, string test) @@ -584,7 +584,7 @@ private void TestConnectTimeoutFailureTimeout(String connString, int minTime, in DateTime start = DateTime.Now; Assert.Throws(() => MySQLX.GetSession(connString)); TimeSpan diff = DateTime.Now.Subtract(start); - Assert.True(diff.TotalSeconds > minTime && diff.TotalSeconds < maxTime, String.Format("Timeout exceeded ({0}). Actual time: {1}", test, diff)); + Assert.That(diff.TotalSeconds > minTime && diff.TotalSeconds < maxTime, String.Format("Timeout exceeded ({0}). Actual time: {1}", test, diff)); } private void TestConnectTimeoutSuccessTimeout(String connString, int minTime, int maxTime, string test) @@ -592,7 +592,7 @@ private void TestConnectTimeoutSuccessTimeout(String connString, int minTime, in DateTime start = DateTime.Now; MySQLX.GetSession(connString); TimeSpan diff = DateTime.Now.Subtract(start); - Assert.True(diff.TotalSeconds > minTime && diff.TotalSeconds < maxTime, String.Format("Timeout exceeded ({0}). Actual time: {1}", test, diff)); + Assert.That(diff.TotalSeconds > minTime && diff.TotalSeconds < maxTime, String.Format("Timeout exceeded ({0}). Actual time: {1}", test, diff)); } [Test] @@ -608,11 +608,11 @@ public void MaxConnections() Session newSession = MySQLX.GetSession(ConnectionString); sessions.Add(newSession); } - Assert.False(true, "MySqlException should be thrown"); + Assert.That(true, Is.False, "MySqlException should be thrown"); } catch (MySqlException ex) { - Assert.AreEqual(ResourcesX.UnableToOpenSession, ex.Message); + Assert.That(ex.Message, Is.EqualTo(ResourcesX.UnableToOpenSession)); } finally { @@ -624,18 +624,18 @@ protected void CheckConnectionData(string connectionData, string user, string pa { string result = this.session.ParseConnectionData(connectionData); var csbuilder = new MySqlXConnectionStringBuilder(result); - Assert.True(user == csbuilder.UserID, string.Format("Expected:{0} Current:{1} in {2}", user, csbuilder.UserID, connectionData)); - Assert.True(password == csbuilder.Password, string.Format("Expected:{0} Current:{1} in {2}", password, csbuilder.Password, connectionData)); - Assert.True(server == csbuilder.Server, string.Format("Expected:{0} Current:{1} in {2}", server, csbuilder.Server, connectionData)); - Assert.True(port == csbuilder.Port, string.Format("Expected:{0} Current:{1} in {2}", port, csbuilder.Port, connectionData)); + Assert.That(user == csbuilder.UserID, string.Format("Expected:{0} Current:{1} in {2}", user, csbuilder.UserID, connectionData)); + Assert.That(password == csbuilder.Password, string.Format("Expected:{0} Current:{1} in {2}", password, csbuilder.Password, connectionData)); + Assert.That(server == csbuilder.Server, string.Format("Expected:{0} Current:{1} in {2}", server, csbuilder.Server, connectionData)); + Assert.That(port == csbuilder.Port, string.Format("Expected:{0} Current:{1} in {2}", port, csbuilder.Port, connectionData)); if (parameters != null) { if (parameters.Length % 2 != 0) throw new ArgumentOutOfRangeException(); for (int i = 0; i < parameters.Length; i += 2) { - Assert.True(csbuilder.ContainsKey(parameters[i])); - Assert.AreEqual(parameters[i + 1], csbuilder[parameters[i]].ToString()); + Assert.That(csbuilder.ContainsKey(parameters[i])); + Assert.That(csbuilder[parameters[i]].ToString(), Is.EqualTo(parameters[i + 1])); } } } @@ -676,18 +676,18 @@ public void ConnectionAttributes() // Errors var ex = Assert.Throws(() => MySQLX.GetSession(ConnectionString + ";connection-attributes=[_key=value]")); - Assert.AreEqual(ResourcesX.InvalidUserDefinedAttribute, ex.Message); + Assert.That(ex.Message, Is.EqualTo(ResourcesX.InvalidUserDefinedAttribute)); ex = Assert.Throws(() => MySQLX.GetSession(ConnectionString + ";connection-attributes=123")); - Assert.AreEqual(ResourcesX.InvalidConnectionAttributes, ex.Message); + Assert.That(ex.Message, Is.EqualTo(ResourcesX.InvalidConnectionAttributes)); ex = Assert.Throws(() => MySQLX.GetSession(ConnectionString + ";connection-attributes=[key=value,key=value2]")); - Assert.AreEqual(string.Format(ResourcesX.DuplicateUserDefinedAttribute, "key"), ex.Message); + Assert.That(ex.Message, Is.EqualTo(string.Format(ResourcesX.DuplicateUserDefinedAttribute, "key"))); ex = Assert.Throws(() => MySQLX.GetSession(new { server = Host, port = XPort, user = RootUser, connectionattributes = "=" })); ex = Assert.Throws(() => MySQLX.GetSession(ConnectionString + ";connectionattributes=[=bar]")); - Assert.AreEqual(string.Format(ResourcesX.EmptyKeyConnectionAttribute), ex.Message); + Assert.That(ex.Message, Is.EqualTo(string.Format(ResourcesX.EmptyKeyConnectionAttribute))); } private void TestConnectionAttributes(string connString, Dictionary userAttrs = null) @@ -696,31 +696,31 @@ private void TestConnectionAttributes(string connString, Dictionary(() => MySQLX.GetSession(connString)); sw.Stop(); - Assert.True(sw.Elapsed.Seconds > 0 && sw.Elapsed.Seconds < 21); + Assert.That(sw.Elapsed.Seconds > 0 && sw.Elapsed.Seconds < 21); connStr = "mysqlx://" + session.Settings.UserID + ":" + session.Settings.Password + "@[" + strList + "]" + "/?connect-timeout=" + connectionTimeout; sw = new Stopwatch(); sw.Start(); Assert.Throws(() => MySQLX.GetSession(connString)); sw.Stop(); - Assert.True(sw.Elapsed.Seconds > 0 && sw.Elapsed.Seconds < 21); + Assert.That(sw.Elapsed.Seconds > 0 && sw.Elapsed.Seconds < 21); var connObj1 = new { @@ -1930,7 +1930,7 @@ public void ConnectTimeoutSeveralAddreses() sw.Start(); Assert.Throws(() => MySQLX.GetSession(connString)); sw.Stop(); - Assert.True(sw.Elapsed.Seconds > 0 && sw.Elapsed.Seconds < 21); + Assert.That(sw.Elapsed.Seconds > 0 && sw.Elapsed.Seconds < 21); } [Test, Description("(connectionString,connectionUri,Anonymous Object.Test that the timeout will be reset for each connection attempt in a failover scenario")] @@ -1946,14 +1946,14 @@ public void ConnectTimeoutWithFailoverAndNotValidHost() sw.Start(); Assert.Throws(() => MySQLX.GetSession(connString)); sw.Stop(); - Assert.True(sw.Elapsed.Seconds > 0 && sw.Elapsed.Seconds < 10); + Assert.That(sw.Elapsed.Seconds > 0 && sw.Elapsed.Seconds < 10); // URI var connStr = "mysqlx://" + session.Settings.UserID + ":" + session.Settings.Password + "@[" + hostList + "]" + "/?connect-timeout=" + connectionTimeout; sw = new Stopwatch(); sw.Start(); Assert.Throws(() => MySQLX.GetSession(connString)); sw.Stop(); - Assert.True(sw.Elapsed.Seconds > 0 && sw.Elapsed.Seconds < 10); + Assert.That(sw.Elapsed.Seconds > 0 && sw.Elapsed.Seconds < 10); // Object var connObj = new @@ -1968,7 +1968,7 @@ public void ConnectTimeoutWithFailoverAndNotValidHost() sw.Start(); Assert.Throws(() => MySQLX.GetSession(connString)); sw.Stop(); - Assert.True(sw.Elapsed.Seconds > 0 && sw.Elapsed.Seconds < 10); + Assert.That(sw.Elapsed.Seconds > 0 && sw.Elapsed.Seconds < 10); } [Test, Description("Confirm that the timeout is only applied to the connection process, not to any subsequent operation after the connection is established")] @@ -1982,7 +1982,7 @@ public void ValidateConnectTimeoutScope() { conn.SQL("SELECT SLEEP(10)").Execute(); var res = conn.SQL("select @@port").Execute().FirstOrDefault(); - Assert.IsNotNull(res); + Assert.That(res, Is.Not.Null); } connStr = "mysqlx://" + session.Settings.UserID + ":" + session.Settings.Password + "@" + session.Settings.Server + ":" + XPort + "?connect-timeout=10000;"; @@ -1990,7 +1990,7 @@ public void ValidateConnectTimeoutScope() { conn.SQL("SELECT SLEEP(10)").Execute(); var res = conn.SQL("select @@port").Execute().FirstOrDefault(); - Assert.IsNotNull(res); + Assert.That(res, Is.Not.Null); } var connObj = new @@ -2005,7 +2005,7 @@ public void ValidateConnectTimeoutScope() { conn.SQL("SELECT SLEEP(10)").Execute(); var res = conn.SQL("select @@port").Execute().FirstOrDefault(); - Assert.IsNotNull(res); + Assert.That(res, Is.Not.Null); } var connStrBuilder = new MySqlXConnectionStringBuilder(); @@ -2018,7 +2018,7 @@ public void ValidateConnectTimeoutScope() { conn.SQL("SELECT SLEEP(10)").Execute(); var res = conn.SQL("select @@port").Execute().FirstOrDefault(); - Assert.IsNotNull(res); + Assert.That(res, Is.Not.Null); } connStr = "server=" + session.Settings.Server + ";user=" + session.Settings.UserID + ";port=" + XPort + ";password=" @@ -2028,7 +2028,7 @@ public void ValidateConnectTimeoutScope() { conn.SQL("SELECT SLEEP(10)").Execute(); var res = conn.SQL("select @@port").Execute().FirstOrDefault(); - Assert.IsNotNull(res); + Assert.That(res, Is.Not.Null); } connStr = ConnectionString + ";protocol=Socket;" + @@ -2041,7 +2041,7 @@ public void ValidateConnectTimeoutScope() { conn.SQL("SELECT SLEEP(10)").Execute(); var res = conn.SQL("select @@port").Execute().FirstOrDefault(); - Assert.IsNotNull(res); + Assert.That(res, Is.Not.Null); } mysqlx0 = new MySqlXConnectionStringBuilder(); @@ -2065,7 +2065,7 @@ public void ValidateConnectTimeoutScope() { conn.SQL("SELECT SLEEP(10)").Execute(); var res = conn.SQL("select @@port").Execute().FirstOrDefault(); - Assert.IsNotNull(res); + Assert.That(res, Is.Not.Null); } } @@ -2180,7 +2180,7 @@ public void SessionStressTest() { using (Session session1 = MySQLX.GetSession(ConnectionString)) { - Assert.AreEqual(SessionState.Open, session1.InternalSession.SessionState); + Assert.That(session1.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); session1.Close(); } } @@ -2206,13 +2206,13 @@ public void SessionAuditPluginTest() { using (var mysqlx = MySQLX.GetSession(ConnectionString)) { - Assert.AreEqual(SessionState.Open, mysqlx.InternalSession.SessionState); + Assert.That(mysqlx.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); mysqlx.Close(); } using (var mysql = new MySqlConnection($"server={Host};user={session.Settings.UserID};port={Port};password={session.Settings.Password}")) { mysql.Open(); - Assert.AreEqual(ConnectionState.Open, mysql.connectionState); + Assert.That(mysql.connectionState, Is.EqualTo(ConnectionState.Open)); mysql.Close(); } Assert.Throws(() => MySQLX.GetSession($"server={Host};user={session.Settings.UserID};port={XPort};password=wrong")); @@ -2228,7 +2228,7 @@ public void ClassicClientXProtocol() using (var session1 = new MySqlConnection(connectionString)) { Exception ex = Assert.Throws(() => session1.Open()); - Assert.AreEqual("Unsupported protocol version.", ex.Message); + Assert.That(ex.Message, Is.EqualTo("Unsupported protocol version.")); } } @@ -2240,7 +2240,7 @@ public void TestConnectObjectTimeoutSuccessTimeout(object connString, int minTim sw.Start(); var conn = MySQLX.GetSession(connString); sw.Stop(); - Assert.True(sw.Elapsed.Seconds >= minTime && sw.Elapsed.Seconds <= maxTime, String.Format("Timeout exceeded ({0}). Actual time: {1}", test, sw.Elapsed)); + Assert.That(sw.Elapsed.Seconds >= minTime && sw.Elapsed.Seconds <= maxTime, String.Format("Timeout exceeded ({0}). Actual time: {1}", test, sw.Elapsed)); } public void TestConnectStringTimeoutSuccessTimeout(String connString, int minTime, int maxTime, string test) @@ -2249,7 +2249,7 @@ public void TestConnectStringTimeoutSuccessTimeout(String connString, int minTim sw.Start(); var conn = MySQLX.GetSession(connString); sw.Stop(); - Assert.True(sw.Elapsed.Seconds >= minTime && sw.Elapsed.Seconds <= maxTime, String.Format("Timeout exceeded ({0}). Actual time: {1}", test, sw.Elapsed)); + Assert.That(sw.Elapsed.Seconds >= minTime && sw.Elapsed.Seconds <= maxTime, String.Format("Timeout exceeded ({0}). Actual time: {1}", test, sw.Elapsed)); } public void TestConnectObjTimeoutFailureTimeout(object connString, int minTime, int maxTime, string test) @@ -2258,7 +2258,7 @@ public void TestConnectObjTimeoutFailureTimeout(object connString, int minTime, sw.Start(); Assert.Catch(() => MySQLX.GetSession(connString)); sw.Stop(); - Assert.True(sw.Elapsed.Seconds >= minTime && sw.Elapsed.Seconds < maxTime, String.Format("Timeout exceeded ({0}). Actual time: {1}", test, sw.Elapsed)); + Assert.That(sw.Elapsed.Seconds >= minTime && sw.Elapsed.Seconds < maxTime, String.Format("Timeout exceeded ({0}). Actual time: {1}", test, sw.Elapsed)); } public void TestConnectStringTimeoutFailureTimeout(String connString, int minTime, int maxTime, string test) @@ -2267,7 +2267,7 @@ public void TestConnectStringTimeoutFailureTimeout(String connString, int minTim sw.Start(); Assert.Catch(() => MySQLX.GetSession(connString)); sw.Stop(); - Assert.True(sw.Elapsed.Seconds >= minTime && sw.Elapsed.Seconds < maxTime, String.Format("Timeout exceeded ({0}). Actual time: {1}", test, sw.Elapsed)); + Assert.That(sw.Elapsed.Seconds >= minTime && sw.Elapsed.Seconds < maxTime, String.Format("Timeout exceeded ({0}). Actual time: {1}", test, sw.Elapsed)); } public void TestClientQueueTimeout(Client client, int minTime, int maxTime, string test) @@ -2276,7 +2276,7 @@ public void TestClientQueueTimeout(Client client, int minTime, int maxTime, stri sw.Start(); Assert.Throws(() => client.GetSession()); sw.Stop(); - Assert.True(sw.Elapsed.Seconds >= minTime && sw.Elapsed.Seconds < maxTime, + Assert.That(sw.Elapsed.Seconds >= minTime && sw.Elapsed.Seconds < maxTime, String.Format("Timeout exceeded ({0}). Actual time: {1}", test, sw.Elapsed)); } @@ -2288,7 +2288,7 @@ public void TestClientSuccessTimeout(int minTime, int maxTime, string test, stri sw.Start(); client.GetSession(); sw.Stop(); - Assert.True(sw.Elapsed.Seconds >= minTime && sw.Elapsed.Seconds < maxTime, String.Format("Timeout exceeded ({0}). Actual time: {1}", test, sw.Elapsed)); + Assert.That(sw.Elapsed.Seconds >= minTime && sw.Elapsed.Seconds < maxTime, String.Format("Timeout exceeded ({0}). Actual time: {1}", test, sw.Elapsed)); } } @@ -2300,7 +2300,7 @@ public void TestClientSuccessTimeout(int minTime, int maxTime, string test, obje sw.Start(); client.GetSession(); sw.Stop(); - Assert.True(sw.Elapsed.Seconds >= minTime && sw.Elapsed.Seconds < maxTime, String.Format("Timeout exceeded ({0}). Actual time: {1}", test, sw.Elapsed)); + Assert.That(sw.Elapsed.Seconds >= minTime && sw.Elapsed.Seconds < maxTime, String.Format("Timeout exceeded ({0}). Actual time: {1}", test, sw.Elapsed)); } } public void TestFailureTimeout(Client client, int minTime, int maxTime, string test) @@ -2308,7 +2308,7 @@ public void TestFailureTimeout(Client client, int minTime, int maxTime, string t DateTime start = DateTime.Now; Assert.Catch(() => client.GetSession()); TimeSpan diff = DateTime.Now.Subtract(start); - Assert.True(diff.TotalSeconds >= minTime && diff.TotalSeconds < maxTime, String.Format("Timeout exceeded ({0}). Actual time: {1}", test, diff)); + Assert.That(diff.TotalSeconds >= minTime && diff.TotalSeconds < maxTime, String.Format("Timeout exceeded ({0}). Actual time: {1}", test, diff)); } private void MeasureConnectionString(string connStr, int maxTime, string test, int iteration) @@ -2322,7 +2322,7 @@ private void MeasureConnectionString(string connStr, int maxTime, string test, i } sw.Stop(); - Assert.True(sw.Elapsed.Seconds < maxTime, String.Format("Timeout exceeded ({0}). Actual time: {1}", test, sw.Elapsed)); + Assert.That(sw.Elapsed.Seconds < maxTime, String.Format("Timeout exceeded ({0}). Actual time: {1}", test, sw.Elapsed)); } private void MeasureConnectionObject(object connStr, int maxTime, string test, int iteration) @@ -2336,7 +2336,7 @@ private void MeasureConnectionObject(object connStr, int maxTime, string test, i } sw.Stop(); - Assert.True(sw.Elapsed.Seconds < maxTime, String.Format("Timeout exceeded ({0}). Actual time: {1}", test, sw.Elapsed)); + Assert.That(sw.Elapsed.Seconds < maxTime, String.Format("Timeout exceeded ({0}). Actual time: {1}", test, sw.Elapsed)); } public long NanoTime() diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/SslTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/SslTests.cs index 6e399c635..a91d11915 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/SslTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/SslTests.cs @@ -45,9 +45,9 @@ public void SslSession() { using (var s3 = MySQLX.GetSession(ConnectionStringUri)) { - Assert.AreEqual(SessionState.Open, s3.InternalSession.SessionState); + Assert.That(s3.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); var result = ExecuteSQLStatement(s3.SQL("SHOW SESSION STATUS LIKE 'Mysqlx_ssl_version';")).FetchAll(); - StringAssert.StartsWith("TLSv1", result[0][1].ToString()); + Assert.That(result[0][1].ToString(), Does.StartWith("TLSv1")); } } @@ -58,9 +58,9 @@ public void SslEmptyCertificate() // if certificate is empty, it connects without a certificate using (var s1 = MySQLX.GetSession(connstring)) { - Assert.AreEqual(SessionState.Open, s1.InternalSession.SessionState); + Assert.That(s1.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); var result = ExecuteSQLStatement(s1.SQL("SHOW SESSION STATUS LIKE 'Mysqlx_ssl_version';")).FetchAll(); - StringAssert.StartsWith("TLSv1", result[0][1].ToString()); + Assert.That(result[0][1].ToString(), Does.StartWith("TLSv1")); } } @@ -71,12 +71,12 @@ public void SslOptions() // sslmode is valid. using (var connection = MySQLX.GetSession(connectionUri + "?sslmode=required")) { - Assert.AreEqual(SessionState.Open, connection.InternalSession.SessionState); + Assert.That(connection.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); } using (var connection = MySQLX.GetSession(connectionUri + "?ssl-mode=required")) { - Assert.AreEqual(SessionState.Open, connection.InternalSession.SessionState); + Assert.That(connection.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); } // sslenable is invalid. @@ -86,17 +86,17 @@ public void SslOptions() // sslmode=Required is default value. using (var connection = MySQLX.GetSession(connectionUri)) { - Assert.AreEqual(connection.Settings.SslMode, MySqlSslMode.Required); + Assert.That(MySqlSslMode.Required, Is.EqualTo(connection.Settings.SslMode)); } // sslmode case insensitive. using (var connection = MySQLX.GetSession(connectionUri + "?SsL-mOdE=required")) { - Assert.AreEqual(SessionState.Open, connection.InternalSession.SessionState); + Assert.That(connection.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); } using (var connection = MySQLX.GetSession(connectionUri + "?SsL-mOdE=VeRiFyca&ssl-ca=../../../../MySql.Data.Tests/client.pfx&ssl-ca-pwd=pass")) { - Assert.AreEqual(SessionState.Open, connection.InternalSession.SessionState); + Assert.That(connection.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); var uri = connection.Uri; } @@ -115,7 +115,7 @@ public void SslRequiredByDefault() { using (var connection = MySQLX.GetSession(ConnectionStringUri)) { - Assert.AreEqual(MySqlSslMode.Required, connection.Settings.SslMode); + Assert.That(connection.Settings.SslMode, Is.EqualTo(MySqlSslMode.Required)); } } @@ -130,9 +130,9 @@ public void SslPreferredIsInvalid() // In connection string. var exception = Assert.Throws(() => MySQLX.GetSession(ConnectionStringUri + "?ssl-mode=Preferred")); - Assert.AreEqual(string.Format(expectedErrorMessage, "Preferred"), exception.Message); + Assert.That(exception.Message, Is.EqualTo(string.Format(expectedErrorMessage, "Preferred"))); exception = Assert.Throws(() => MySQLX.GetSession(ConnectionStringUri + "?ssl-mode=Prefered")); - Assert.AreEqual(string.Format(expectedErrorMessage, "Prefered"), exception.Message); + Assert.That(exception.Message, Is.EqualTo(string.Format(expectedErrorMessage, "Prefered"))); // In anonymous object. var builder = new MySqlXConnectionStringBuilder(ConnectionString); @@ -145,18 +145,18 @@ public void SslPreferredIsInvalid() sslmode = MySqlSslMode.Prefered }; exception = Assert.Throws(() => MySQLX.GetSession(connectionObject)); - Assert.AreEqual(string.Format(expectedErrorMessage, prefered), exception.Message); + Assert.That(exception.Message, Is.EqualTo(string.Format(expectedErrorMessage, prefered))); // In MySqlXConnectionStringBuilder. builder = new MySqlXConnectionStringBuilder(ConnectionString); builder.SslMode = MySqlSslMode.Prefered; exception = Assert.Throws(() => MySQLX.GetSession(connectionObject)); - Assert.AreEqual(string.Format(expectedErrorMessage, prefered), exception.Message); + Assert.That(exception.Message, Is.EqualTo(string.Format(expectedErrorMessage, prefered))); builder = new MySqlXConnectionStringBuilder(ConnectionString); builder.SslMode = MySqlSslMode.Preferred; exception = Assert.Throws(() => MySQLX.GetSession(connectionObject)); - Assert.AreEqual(string.Format(expectedErrorMessage, prefered), exception.Message); + Assert.That(exception.Message, Is.EqualTo(string.Format(expectedErrorMessage, prefered))); } [Test] @@ -200,9 +200,9 @@ public void GetUriWithSSLParameters() // Authentication mode AUTO/DEFAULT is internally assigned, hence it is expected to be different in this scenario. if (connectionOption == "auth") - Assert.AreEqual(MySqlAuthenticationMode.PLAIN, internalSession.Settings[connectionOption]); + Assert.That(internalSession.Settings[connectionOption], Is.EqualTo(MySqlAuthenticationMode.PLAIN)); else - Assert.AreEqual(builder[connectionOption], internalSession.Settings[connectionOption]); + Assert.That(internalSession.Settings[connectionOption], Is.EqualTo(builder[connectionOption])); } } } @@ -238,17 +238,17 @@ public void GetUriKeepsSSLMode() using (var internalSession = MySQLX.GetSession(uri)) { - Assert.AreEqual(builder.Server, internalSession.Settings.Server); - Assert.AreEqual(builder.UserID, internalSession.Settings.UserID); - Assert.AreEqual(builder.Password, internalSession.Settings.Password); - Assert.AreEqual(builder.Port, internalSession.Settings.Port); - Assert.AreEqual(builder.Database, internalSession.Settings.Database); - Assert.AreEqual(builder.CharacterSet, internalSession.Settings.CharacterSet); - Assert.AreEqual(builder.SslMode, internalSession.Settings.SslMode); - Assert.AreEqual(builder.SslCa, internalSession.Settings.SslCa); - Assert.AreEqual(builder.CertificatePassword, internalSession.Settings.CertificatePassword); - Assert.AreEqual(builder.ConnectTimeout, internalSession.Settings.ConnectTimeout); - Assert.AreEqual(MySqlAuthenticationMode.PLAIN, internalSession.Settings.Auth); + Assert.That(internalSession.Settings.Server, Is.EqualTo(builder.Server)); + Assert.That(internalSession.Settings.UserID, Is.EqualTo(builder.UserID)); + Assert.That(internalSession.Settings.Password, Is.EqualTo(builder.Password)); + Assert.That(internalSession.Settings.Port, Is.EqualTo(builder.Port)); + Assert.That(internalSession.Settings.Database, Is.EqualTo(builder.Database)); + Assert.That(internalSession.Settings.CharacterSet, Is.EqualTo(builder.CharacterSet)); + Assert.That(internalSession.Settings.SslMode, Is.EqualTo(builder.SslMode)); + Assert.That(internalSession.Settings.SslCa, Is.EqualTo(builder.SslCa)); + Assert.That(internalSession.Settings.CertificatePassword, Is.EqualTo(builder.CertificatePassword)); + Assert.That(internalSession.Settings.ConnectTimeout, Is.EqualTo(builder.ConnectTimeout)); + Assert.That(internalSession.Settings.Auth, Is.EqualTo(MySqlAuthenticationMode.PLAIN)); } } @@ -292,15 +292,15 @@ public void TlsVersionTest(string tlsVersion, int error) { case 1: ex = Assert.Throws(SetTlsVersion).Message; - StringAssert.AreEqualIgnoringCase(MySql.Data.Resources.TlsVersionsEmpty, ex); + Assert.That(ex, Is.EqualTo(MySql.Data.Resources.TlsVersionsEmpty).IgnoreCase); break; case 2: ex = Assert.Throws(SetTlsVersion).Message; - StringAssert.AreEqualIgnoringCase(MySql.Data.Resources.TlsUnsupportedVersions, ex); + Assert.That(ex, Is.EqualTo(MySql.Data.Resources.TlsUnsupportedVersions).IgnoreCase); break; case 3: ex = Assert.Throws(SetTlsVersion).Message; - StringAssert.AreEqualIgnoringCase(MySql.Data.Resources.TlsNonValidProtocols, ex); + Assert.That(ex, Is.EqualTo(MySql.Data.Resources.TlsNonValidProtocols).IgnoreCase); break; case 4: SetTlsVersion(); @@ -313,13 +313,13 @@ public void TlsVersionTest(string tlsVersion, int error) using (var internalSession = MySQLX.GetSession(builder.ConnectionString)) { uri = internalSession.Uri; - Assert.AreEqual(SessionState.Open, internalSession.InternalSession.SessionState); - StringAssert.StartsWith(tls, internalSession.SQL("SHOW SESSION STATUS LIKE 'mysqlx_ssl_version'").Execute().FetchAll()[0][1].ToString()); + Assert.That(internalSession.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); + Assert.That(internalSession.SQL("SHOW SESSION STATUS LIKE 'mysqlx_ssl_version'").Execute().FetchAll()[0][1].ToString(), Does.StartWith(tls)); } using (var internalSession = MySQLX.GetSession(uri)) { - Assert.AreEqual(SessionState.Open, internalSession.InternalSession.SessionState); - StringAssert.StartsWith(tls, internalSession.SQL("SHOW SESSION STATUS LIKE 'mysqlx_ssl_version'").Execute().FetchAll()[0][1].ToString()); + Assert.That(internalSession.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); + Assert.That(internalSession.SQL("SHOW SESSION STATUS LIKE 'mysqlx_ssl_version'").Execute().FetchAll()[0][1].ToString(), Does.StartWith(tls)); } break; @@ -350,13 +350,13 @@ public void TlsVersionNoSslTest(string tlsVersion) using (var internalSession = MySQLX.GetSession(builder.ConnectionString)) { uri = internalSession.Uri; - Assert.AreEqual(SessionState.Open, internalSession.InternalSession.SessionState); - Assert.IsEmpty(internalSession.SQL("SHOW SESSION STATUS LIKE 'mysqlx_ssl_version'").Execute().FetchAll()[0][1].ToString()); + Assert.That(internalSession.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); + Assert.That(internalSession.SQL("SHOW SESSION STATUS LIKE 'mysqlx_ssl_version'").Execute().FetchAll()[0][1].ToString(), Is.Empty); } using (var internalSession = MySQLX.GetSession(uri)) { - Assert.AreEqual(SessionState.Open, internalSession.InternalSession.SessionState); - Assert.IsEmpty(internalSession.SQL("SHOW SESSION STATUS LIKE 'mysqlx_ssl_version'").Execute().FetchAll()[0][1].ToString()); + Assert.That(internalSession.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); + Assert.That(internalSession.SQL("SHOW SESSION STATUS LIKE 'mysqlx_ssl_version'").Execute().FetchAll()[0][1].ToString(), Is.Empty); } } @@ -371,9 +371,9 @@ public void SslCertificate() string connstring = ConnectionStringUri + $"/?ssl-ca={path}client.pfx&ssl-ca-pwd=pass"; using (var s3 = MySQLX.GetSession(connstring)) { - Assert.AreEqual(SessionState.Open, s3.InternalSession.SessionState); + Assert.That(s3.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); var result = ExecuteSQLStatement(s3.SQL("SHOW SESSION STATUS LIKE 'Mysqlx_ssl_version';")).FetchAll(); - StringAssert.StartsWith("TLSv1", result[0][1].ToString()); + Assert.That(result[0][1].ToString(), Does.StartWith("TLSv1")); } } @@ -391,21 +391,21 @@ public void SslCertificatePathKeepsCase() // Connection string in basic format. string connString = ConnectionString + ";ssl-ca=" + certificatePath + ";ssl-ca-pwd=pass;"; var stringBuilder = new MySqlXConnectionStringBuilder(connString); - Assert.AreEqual(certificatePath, stringBuilder.CertificateFile); - Assert.AreEqual(certificatePath, stringBuilder.SslCa); - Assert.True(stringBuilder.ConnectionString.Contains(certificatePath)); + Assert.That(stringBuilder.CertificateFile, Is.EqualTo(certificatePath)); + Assert.That(stringBuilder.SslCa, Is.EqualTo(certificatePath)); + Assert.That(stringBuilder.ConnectionString.Contains(certificatePath)); connString = stringBuilder.ToString(); - Assert.True(connString.Contains(certificatePath)); + Assert.That(connString.Contains(certificatePath)); // Connection string in uri format. string connStringUri = ConnectionStringUri + "/?ssl-ca=" + certificatePath + "& ssl-ca-pwd=pass;"; using (var session = MySQLX.GetSession(connStringUri)) { - Assert.AreEqual(certificatePath, session.Settings.CertificateFile); - Assert.AreEqual(certificatePath, session.Settings.SslCa); - Assert.True(session.Settings.ConnectionString.Contains(certificatePath)); + Assert.That(session.Settings.CertificateFile, Is.EqualTo(certificatePath)); + Assert.That(session.Settings.SslCa, Is.EqualTo(certificatePath)); + Assert.That(session.Settings.ConnectionString.Contains(certificatePath)); connString = session.Settings.ToString(); - Assert.True(connString.Contains(certificatePath)); + Assert.That(connString.Contains(certificatePath)); } } @@ -420,7 +420,7 @@ public void SslCertificatePathVariations(string certificatePath) using (var session = MySQLX.GetSession(connStringUri)) { - Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); + Assert.That(session.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); } } @@ -435,20 +435,20 @@ public void SslCertificateConnectionOptionsExistAndDefaultToNull() var builder = new MySqlXConnectionStringBuilder(); // Options exist. - Assert.True(builder.values.ContainsKey("sslca")); - Assert.True(builder.values.ContainsKey("sslcert")); - Assert.True(builder.values.ContainsKey("sslkey")); + Assert.That(builder.values.ContainsKey("sslca")); + Assert.That(builder.values.ContainsKey("sslcert")); + Assert.That(builder.values.ContainsKey("sslkey")); // Options default to null. - Assert.Null(builder["sslca"]); - Assert.Null(builder["sslcert"]); - Assert.Null(builder["sslkey"]); - Assert.Null(builder["ssl-ca"]); - Assert.Null(builder["ssl-cert"]); - Assert.Null(builder["ssl-key"]); - Assert.Null(builder.SslCa); - Assert.Null(builder.SslCert); - Assert.Null(builder.SslKey); + Assert.That(builder["sslca"], Is.Null); + Assert.That(builder["sslcert"], Is.Null); + Assert.That(builder["sslkey"], Is.Null); + Assert.That(builder["ssl-ca"], Is.Null); + Assert.That(builder["ssl-cert"], Is.Null); + Assert.That(builder["ssl-key"], Is.Null); + Assert.That(builder.SslCa, Is.Null); + Assert.That(builder.SslCert, Is.Null); + Assert.That(builder.SslKey, Is.Null); // Null or whitespace options are ignored. builder = new MySqlXConnectionStringBuilder(ConnectionString); @@ -457,18 +457,18 @@ public void SslCertificateConnectionOptionsExistAndDefaultToNull() builder.SslKey = " "; using (var session = MySQLX.GetSession(builder.ConnectionString)) { - Assert.Null(session.Settings.SslCa); - Assert.Null(session.Settings.SslCert); - Assert.AreEqual(" ", session.Settings.SslKey); + Assert.That(session.Settings.SslCa, Is.Null); + Assert.That(session.Settings.SslCert, Is.Null); + Assert.That(session.Settings.SslKey, Is.EqualTo(" ")); session.Close(); } // Failing to provide a value defaults to null. using (var session = MySQLX.GetSession($"{ConnectionString};sslca=;sslcert=;sslkey=")) { - Assert.Null(session.Settings.SslCa); - Assert.Null(session.Settings.SslCert); - Assert.Null(session.Settings.SslKey); + Assert.That(session.Settings.SslCa, Is.Null); + Assert.That(session.Settings.SslCert, Is.Null); + Assert.That(session.Settings.SslKey, Is.Null); session.Close(); } } @@ -480,13 +480,13 @@ public void MissingSslCaConnectionOption() var builder = new MySqlXConnectionStringBuilder(ConnectionString); builder.SslMode = MySqlSslMode.VerifyCA; var exception = Assert.Throws(() => MySQLX.GetSession(builder.ConnectionString)); - Assert.AreEqual(MySql.Data.Resources.SslConnectionError, exception.Message); - Assert.AreEqual(string.Format(MySql.Data.Resources.FilePathNotSet, nameof(builder.SslCa)), exception.InnerException.Message); + Assert.That(exception.Message, Is.EqualTo(MySql.Data.Resources.SslConnectionError)); + Assert.That(exception.InnerException.Message, Is.EqualTo(string.Format(MySql.Data.Resources.FilePathNotSet, nameof(builder.SslCa)))); builder.SslMode = MySqlSslMode.VerifyFull; exception = Assert.Throws(() => MySQLX.GetSession(builder.ConnectionString)); - Assert.AreEqual(MySql.Data.Resources.SslConnectionError, exception.Message); - Assert.AreEqual(string.Format(MySql.Data.Resources.FilePathNotSet, nameof(builder.SslCa)), exception.InnerException.Message); + Assert.That(exception.Message, Is.EqualTo(MySql.Data.Resources.SslConnectionError)); + Assert.That(exception.InnerException.Message, Is.EqualTo(string.Format(MySql.Data.Resources.FilePathNotSet, nameof(builder.SslCa)))); } [Test] @@ -498,8 +498,8 @@ public void MissingSslCertConnectionOption() builder.SslCert = string.Empty; builder.SslMode = MySqlSslMode.VerifyFull; var exception = Assert.Throws(() => MySQLX.GetSession(builder.ConnectionString)); - Assert.AreEqual(MySql.Data.Resources.SslConnectionError, exception.Message); - Assert.AreEqual(string.Format(MySql.Data.Resources.FilePathNotSet, nameof(builder.SslCert)), exception.InnerException.Message); + Assert.That(exception.Message, Is.EqualTo(MySql.Data.Resources.SslConnectionError)); + Assert.That(exception.InnerException.Message, Is.EqualTo(string.Format(MySql.Data.Resources.FilePathNotSet, nameof(builder.SslCert)))); } [Test] @@ -512,8 +512,8 @@ public void MissingSslKeyConnectionOption() builder.SslKey = " "; builder.SslMode = MySqlSslMode.VerifyFull; var exception = Assert.Throws(() => MySQLX.GetSession(builder.ConnectionString)); - Assert.AreEqual(MySql.Data.Resources.SslConnectionError, exception.Message); - Assert.AreEqual(string.Format(MySql.Data.Resources.FilePathNotSet, nameof(builder.SslKey)), exception.InnerException.Message); + Assert.That(exception.Message, Is.EqualTo(MySql.Data.Resources.SslConnectionError)); + Assert.That(exception.InnerException.Message, Is.EqualTo(string.Format(MySql.Data.Resources.FilePathNotSet, nameof(builder.SslKey)))); } [Test] @@ -524,8 +524,8 @@ public void InvalidFileNameForSslCaConnectionOption() builder.SslCa = "C:\\certs\\ca.pema"; builder.SslMode = MySqlSslMode.VerifyCA; var exception = Assert.Throws(() => MySQLX.GetSession(builder.ConnectionString)); - Assert.AreEqual(MySql.Data.Resources.SslConnectionError, exception.Message); - Assert.AreEqual(MySql.Data.Resources.FileNotFound, exception.InnerException.Message); + Assert.That(exception.Message, Is.EqualTo(MySql.Data.Resources.SslConnectionError)); + Assert.That(exception.InnerException.Message, Is.EqualTo(MySql.Data.Resources.FileNotFound)); } [Test] @@ -537,8 +537,8 @@ public void InvalidFileNameForSslCertConnectionOption() builder.SslCert = "C:\\certs\\client-cert"; builder.SslMode = MySqlSslMode.VerifyFull; var exception = Assert.Throws(() => MySQLX.GetSession(builder.ConnectionString)); - Assert.AreEqual(MySql.Data.Resources.SslConnectionError, exception.Message); - Assert.AreEqual(MySql.Data.Resources.FileNotFound, exception.InnerException.Message); + Assert.That(exception.Message, Is.EqualTo(MySql.Data.Resources.SslConnectionError)); + Assert.That(exception.InnerException.Message, Is.EqualTo(MySql.Data.Resources.FileNotFound)); } [Test] @@ -551,8 +551,8 @@ public void InvalidFileNameForSslKeyConnectionOption() builder.SslKey = "file"; builder.SslMode = MySqlSslMode.VerifyFull; var exception = Assert.Throws(() => MySQLX.GetSession(builder.ConnectionString)); - Assert.AreEqual(MySql.Data.Resources.SslConnectionError, exception.Message); - Assert.AreEqual(MySql.Data.Resources.FileNotFound, exception.InnerException.Message); + Assert.That(exception.Message, Is.EqualTo(MySql.Data.Resources.SslConnectionError)); + Assert.That(exception.InnerException.Message, Is.EqualTo(MySql.Data.Resources.FileNotFound)); } [Test] @@ -626,23 +626,23 @@ public void AttemptConnectionWithDummyPemCertificates() builder.SslCa = sslCa.Replace("ca.pem", "ca_dummy.pem"); builder.SslMode = MySqlSslMode.VerifyCA; var exception = Assert.Throws(() => MySQLX.GetSession(builder.ConnectionString)); - Assert.AreEqual(MySql.Data.Resources.SslConnectionError, exception.Message); - Assert.AreEqual(MySql.Data.Resources.FileIsNotACertificate, exception.InnerException.Message); + Assert.That(exception.Message, Is.EqualTo(MySql.Data.Resources.SslConnectionError)); + Assert.That(exception.InnerException.Message, Is.EqualTo(MySql.Data.Resources.FileIsNotACertificate)); builder.SslCa = sslCa; builder.SslCert = sslCert.Replace("client-cert.pem", "client-cert_dummy.pem"); builder.SslMode = MySqlSslMode.VerifyFull; exception = Assert.Throws(() => MySQLX.GetSession(builder.ConnectionString)); - Assert.AreEqual(MySql.Data.Resources.SslConnectionError, exception.Message); - Assert.AreEqual(MySql.Data.Resources.FileIsNotACertificate, exception.InnerException.Message); + Assert.That(exception.Message, Is.EqualTo(MySql.Data.Resources.SslConnectionError)); + Assert.That(exception.InnerException.Message, Is.EqualTo(MySql.Data.Resources.FileIsNotACertificate)); builder.SslCa = sslCa; builder.SslCert = sslCert; builder.SslKey = sslKey.Replace("client-key.pem", "client-key_dummy.pem"); builder.SslMode = MySqlSslMode.VerifyFull; exception = Assert.Throws(() => MySQLX.GetSession(builder.ConnectionString)); - Assert.AreEqual(MySql.Data.Resources.SslConnectionError, exception.Message); - Assert.AreEqual(MySql.Data.Resources.FileIsNotAKey, exception.InnerException.Message); + Assert.That(exception.Message, Is.EqualTo(MySql.Data.Resources.SslConnectionError)); + Assert.That(exception.InnerException.Message, Is.EqualTo(MySql.Data.Resources.FileIsNotAKey)); } [Test] @@ -653,28 +653,28 @@ public void AttemptConnectionWitSwitchedPemCertificates() builder.SslCa = sslCert; builder.SslMode = MySqlSslMode.VerifyCA; var exception = Assert.Throws(() => MySQLX.GetSession(builder.ConnectionString)); - Assert.AreEqual(MySql.Data.Resources.SslConnectionError, exception.Message); - Assert.AreEqual(MySql.Data.Resources.SslCertificateIsNotCA, exception.InnerException.Message); + Assert.That(exception.Message, Is.EqualTo(MySql.Data.Resources.SslConnectionError)); + Assert.That(exception.InnerException.Message, Is.EqualTo(MySql.Data.Resources.SslCertificateIsNotCA)); builder.SslCa = sslKey; builder.SslMode = MySqlSslMode.VerifyCA; exception = Assert.Throws(() => MySQLX.GetSession(builder.ConnectionString)); - Assert.AreEqual(MySql.Data.Resources.SslConnectionError, exception.Message); - Assert.AreEqual(MySql.Data.Resources.FileIsNotACertificate, exception.InnerException.Message); + Assert.That(exception.Message, Is.EqualTo(MySql.Data.Resources.SslConnectionError)); + Assert.That(exception.InnerException.Message, Is.EqualTo(MySql.Data.Resources.FileIsNotACertificate)); builder.SslCa = sslCa; builder.SslCert = sslCa; builder.SslMode = MySqlSslMode.VerifyFull; exception = Assert.Throws(() => MySQLX.GetSession(builder.ConnectionString)); - Assert.AreEqual(MySql.Data.Resources.SslConnectionError, exception.Message); - Assert.AreEqual(MySql.Data.Resources.InvalidSslCertificate, exception.InnerException.Message); + Assert.That(exception.Message, Is.EqualTo(MySql.Data.Resources.SslConnectionError)); + Assert.That(exception.InnerException.Message, Is.EqualTo(MySql.Data.Resources.InvalidSslCertificate)); builder.SslCert = sslCert; builder.SslKey = sslCa; builder.SslMode = MySqlSslMode.VerifyFull; exception = Assert.Throws(() => MySQLX.GetSession(builder.ConnectionString)); - Assert.AreEqual(MySql.Data.Resources.SslConnectionError, exception.Message); - Assert.AreEqual(MySql.Data.Resources.FileIsNotAKey, exception.InnerException.Message); + Assert.That(exception.Message, Is.EqualTo(MySql.Data.Resources.SslConnectionError)); + Assert.That(exception.InnerException.Message, Is.EqualTo(MySql.Data.Resources.FileIsNotAKey)); } #endregion @@ -693,9 +693,9 @@ public void PfxCertificateWithUri() connStr = ConnectionStringUri + $"?ssl-mode=Required&ssl-ca={clientPfx}&ssl-ca-pwd={sslCertificatePassword}"; using (var c = MySQLX.GetSession(connStr)) { - Assert.AreEqual(SessionState.Open, c.InternalSession.SessionState); + Assert.That(c.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); var res = ExecuteSQLStatement(c.SQL("SHOW SESSION STATUS LIKE 'Mysqlx_ssl_version';")).FetchAll(); - StringAssert.StartsWith("TLSv1", res[0][1].ToString()); + Assert.That(res[0][1].ToString(), Does.StartWith("TLSv1")); } } @@ -707,9 +707,9 @@ public void PfxCertificateWithConnectionString() var connStr = ConnectionString + $";ssl-mode=Required;ssl-ca={clientPfx};ssl-ca-pwd={sslCertificatePassword};"; using (Session c = MySQLX.GetSession(connStr)) { - Assert.AreEqual(SessionState.Open, c.InternalSession.SessionState); + Assert.That(c.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); var res = ExecuteSQLStatement(c.SQL("SHOW SESSION STATUS LIKE 'Mysqlx_ssl_version';")).FetchAll(); - StringAssert.StartsWith("TLSv1", res[0][1].ToString()); + Assert.That(res[0][1].ToString(), Does.StartWith("TLSv1")); } //wrong certificate @@ -733,13 +733,13 @@ public void ConnectUsingCertificateFileAndTlsVersionXplugin() using (var session1 = MySQLX.GetSession(builder.ConnectionString)) { var result = session1.SQL("show variables like '%tls_version%'").Execute().FetchOne(); - StringAssert.Contains("TLSv1", result[1].ToString()); + Assert.That(result[1].ToString(), Does.Contain("TLSv1")); result = session1.SQL("show status like 'Mysqlx_ssl_cipher'").Execute().FetchOne(); - Assert.True(result[1].ToString().Trim().Length > 0); + Assert.That(result[1].ToString().Trim().Length > 0); result = session1.SQL("show status like 'Mysqlx_ssl_version'").Execute().FetchOne(); - StringAssert.AreEqualIgnoringCase("TLSv1.2", result[1].ToString()); + Assert.That(result[1].ToString(), Is.EqualTo("TLSv1.2").IgnoreCase); } } @@ -752,9 +752,9 @@ public void TlsVersionInConnectionStringXplugin(string tlsVersion) var connStr = ConnectionString + $";sslmode=Required;tls-version={tlsVersion}"; using (var c = MySQLX.GetSession(connStr)) { - Assert.AreEqual(SessionState.Open, c.InternalSession.SessionState); + Assert.That(c.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); var res = c.SQL("SHOW SESSION STATUS LIKE 'Mysqlx_ssl_version';").Execute().FetchAll(); - StringAssert.AreEqualIgnoringCase(tlsVersion, res[0][1].ToString()); + Assert.That(res[0][1].ToString(), Is.EqualTo(tlsVersion).IgnoreCase); } } @@ -779,7 +779,7 @@ public void PemCertDifferentSSLmodes() { using (var session1 = MySQLX.GetSession(connStr)) { - Assert.AreEqual(SessionState.Open, session1.InternalSession.SessionState); + Assert.That(session1.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); } } else @@ -798,9 +798,9 @@ public void PemCertDifferentSSLmodes() using (var session1 = MySQLX.GetSession(connStr)) { var result = session1.SQL(CommandText1).Execute().FetchAll(); - Assert.AreEqual(result[0][1].ToString(), result[0][1].ToString(), "Matching the Cipher"); + Assert.That(result[0][1].ToString(), Is.EqualTo(result[0][1].ToString()), "Matching the Cipher"); result = session1.SQL(CommandText2).Execute().FetchAll(); - Assert.AreEqual(tls, result[0][1].ToString(), "Matching the TLS version"); + Assert.That(result[0][1].ToString(), Is.EqualTo(tls), "Matching the TLS version"); } } } @@ -811,7 +811,7 @@ public void PemCertDifferentSSLmodes() { using (var session1 = MySQLX.GetSession(connStr)) { - Assert.AreEqual(SessionState.Open, session1.InternalSession.SessionState); + Assert.That(session1.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); } } else @@ -830,9 +830,9 @@ public void PemCertDifferentSSLmodes() using (var session1 = MySQLX.GetSession(connStr)) { var result = session1.SQL(CommandText1).Execute().FetchAll(); - Assert.AreEqual(result[0][1].ToString(), result[0][1].ToString(), "Matching the Cipher"); + Assert.That(result[0][1].ToString(), Is.EqualTo(result[0][1].ToString()), "Matching the Cipher"); result = session1.SQL(CommandText2).Execute().FetchAll(); - Assert.AreEqual(tls, result[0][1].ToString(), "Matching the TLS version"); + Assert.That(result[0][1].ToString(), Is.EqualTo(tls), "Matching the TLS version"); } } } @@ -855,7 +855,7 @@ public void PemCertDifferentSSLmodes() { using (var session1 = MySQLX.GetSession(connStr)) { - Assert.AreEqual(SessionState.Open, session1.InternalSession.SessionState); + Assert.That(session1.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); } } else @@ -874,9 +874,9 @@ public void PemCertDifferentSSLmodes() using (var session1 = MySQLX.GetSession(connObject)) { var result = session1.SQL(CommandText1).Execute().FetchAll(); - Assert.AreEqual(result[0][1].ToString(), result[0][1].ToString(), "Matching the Cipher"); + Assert.That(result[0][1].ToString(), Is.EqualTo(result[0][1].ToString()), "Matching the Cipher"); result = session1.SQL(CommandText2).Execute().FetchAll(); - Assert.AreEqual(tls, result[0][1].ToString(), "Matching the TLS version"); + Assert.That(result[0][1].ToString(), Is.EqualTo(tls), "Matching the TLS version"); } } } @@ -902,9 +902,9 @@ public void PemCertDifferentSSLmodes() using (var session1 = MySQLX.GetSession(conn.ConnectionString)) { var result = session1.SQL(CommandText1).Execute().FetchAll(); - Assert.AreEqual(result[0][1].ToString(), result[0][1].ToString(), "Matching the Cipher"); + Assert.That(result[0][1].ToString(), Is.EqualTo(result[0][1].ToString()), "Matching the Cipher"); result = session1.SQL(CommandText2).Execute().FetchAll(); - Assert.AreEqual(tls, result[0][1].ToString(), "Matching the TLS version"); + Assert.That(result[0][1].ToString(), Is.EqualTo(tls), "Matching the TLS version"); } } } @@ -1387,7 +1387,7 @@ public void SecurityTlsCheck() using (Session session1 = MySQLX.GetSession(conStrX + $";ssl-mode={mode};tls-version=TLSv1.2")) { var sess = session1.SQL("select variable_value from performance_schema.session_status where variable_name='mysqlx_ssl_version'").Execute().FetchOne()[0]; - Assert.AreEqual("TLSv1.2", sess); + Assert.That(sess, Is.EqualTo("TLSv1.2")); } version = new string[] { "[TLSv1.1,TLSv1.2]", "[TLSv1,TLSv1.2]" }; @@ -1397,7 +1397,7 @@ public void SecurityTlsCheck() using (Session session1 = MySQLX.GetSession(conStrX + ";ssl-mode=" + mode + ";tls-version=" + version[i])) { var sess = session1.SQL("select variable_value from performance_schema.session_status where variable_name='mysqlx_ssl_version'").Execute().FetchOne()[0]; - Assert.AreEqual(ver1Tls[i], sess); + Assert.That(sess, Is.EqualTo(ver1Tls[i])); } } } @@ -1413,19 +1413,19 @@ public void Tlsv13Bug() using (session1 = MySQLX.GetSession(conStr + ";tls-version=TLSv1.3")) { var sess1 = session1.SQL("select variable_value from performance_schema.session_status where variable_name='mysqlx_ssl_version'").Execute().FetchOne()[0]; - Assert.AreEqual("TLSv1.3", sess1); + Assert.That(sess1, Is.EqualTo("TLSv1.3")); } using (session1 = MySQLX.GetSession(conStr + ";tls-version=TLSv1.2")) { var sess1 = session1.SQL("select variable_value from performance_schema.session_status where variable_name='mysqlx_ssl_version'").Execute().FetchOne()[0]; - Assert.AreEqual("TLSv1.2", sess1); + Assert.That(sess1, Is.EqualTo("TLSv1.2")); } using (session1 = MySQLX.GetSession(conStr + ";tls-version=TLSv1.2,TLSv1.3")) { var sess1 = session1.SQL("select variable_value from performance_schema.session_status where variable_name='mysqlx_ssl_version'").Execute().FetchOne()[0]; - Assert.AreEqual("TLSv1.3", sess1); + Assert.That(sess1, Is.EqualTo("TLSv1.3")); } } @@ -1443,7 +1443,7 @@ public void Tlsv13Linux() foreach (string tlsVersion in version) { - Assert.AreEqual(SessionState.Open, MySQLX.GetSession(conStr + ";ssl-mode=" + mode + ";tls-version=" + tlsVersion).InternalSession.SessionState); + Assert.That(MySQLX.GetSession(conStr + ";ssl-mode=" + mode + ";tls-version=" + tlsVersion).InternalSession.SessionState, Is.EqualTo(SessionState.Open)); } version = new string[] { "[TLSv1,TLSv1.3]", "[TLSv1.1,TLSv1.3]", "[TLSv1,TLSv1.2,TLSv1.3]", "[TLSv1.2,TLSv1.3]", "[TLSv1,TLSv1.1,TLSv1.2,TLSv1.3]" }; @@ -1453,7 +1453,7 @@ public void Tlsv13Linux() using (var session1 = MySQLX.GetSession(conStr + ";ssl-mode=" + mode + ";tls-version=" + version[i])) { var sess = session1.SQL("select variable_value from performance_schema.session_status where variable_name='mysqlx_ssl_version'").Execute().FetchOne()[0]; - Assert.True(sess.ToString().Contains("TLSv1")); + Assert.That(sess.ToString().Contains("TLSv1")); } } } @@ -1468,9 +1468,9 @@ private void AssertTlsConnection(string inputString) using (var session1 = MySQLX.GetSession(inputString)) { var result = session1.SQL(CommandText1).Execute().FetchAll(); - Assert.AreEqual(cipher, result[0][1].ToString(), "Matching the Cipher"); + Assert.That(result[0][1].ToString(), Is.EqualTo(cipher), "Matching the Cipher"); result = session1.SQL(CommandText2).Execute().FetchAll(); - Assert.AreEqual(tls, result[0][1].ToString(), "Matching the TLS version"); + Assert.That(result[0][1].ToString(), Is.EqualTo(tls), "Matching the TLS version"); } } @@ -1483,9 +1483,9 @@ private void AssertTlsConnection(object inputObject) using (var session1 = MySQLX.GetSession(inputObject)) { var result = session1.SQL(CommandText1).Execute().FetchAll(); - Assert.AreEqual(cipher, result[0][1].ToString(), "Matching the Cipher"); + Assert.That(result[0][1].ToString(), Is.EqualTo(cipher), "Matching the Cipher"); result = session1.SQL(CommandText2).Execute().FetchAll(); - Assert.AreEqual(tls, result[0][1].ToString(), "Matching the TLS version"); + Assert.That(result[0][1].ToString(), Is.EqualTo(tls), "Matching the TLS version"); } } @@ -1506,8 +1506,8 @@ public void SslOptionsCombinedWhenDisabled(MySqlSslMode sslMode, string sslOptio using var session = MySQLX.GetSession(connStr); var encryption = session.SQL("SHOW SESSION STATUS LIKE 'mysqlx_ssl_cipher'").Execute().FetchAll()[0][1].ToString(); - Assert.IsEmpty(encryption); - Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); + Assert.That(encryption, Is.Empty); + Assert.That(session.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); // ConnectionString Uri var connStrUri = ConnectionStringUri + $"?ssl-mode={sslMode}&{sslOption}"; @@ -1515,8 +1515,8 @@ public void SslOptionsCombinedWhenDisabled(MySqlSslMode sslMode, string sslOptio using var sessionUri = MySQLX.GetSession(connStrUri); encryption = sessionUri.SQL("SHOW SESSION STATUS LIKE 'mysqlx_ssl_cipher'").Execute().FetchAll()[0][1].ToString(); - Assert.IsEmpty(encryption); - Assert.AreEqual(SessionState.Open, sessionUri.InternalSession.SessionState); + Assert.That(encryption, Is.Empty); + Assert.That(sessionUri.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); } [Test] @@ -1527,16 +1527,16 @@ public void SslRequiredAndDisabled() using var sessionUriDisabled = MySQLX.GetSession(connStrUri); var encryption = sessionUriDisabled.SQL("SHOW SESSION STATUS LIKE 'mysqlx_ssl_cipher'").Execute().FetchAll()[0][1].ToString(); - Assert.IsEmpty(encryption); - Assert.AreEqual(SessionState.Open, sessionUriDisabled.InternalSession.SessionState); + Assert.That(encryption, Is.Empty); + Assert.That(sessionUriDisabled.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); connStrUri = ConnectionStringUri + $"?ssl-mode={MySqlSslMode.Disabled}&ssl-mode={MySqlSslMode.Required}"; using var sessionUriRequired = MySQLX.GetSession(connStrUri); encryption = sessionUriRequired.SQL("SHOW SESSION STATUS LIKE 'mysqlx_ssl_cipher'").Execute().FetchAll()[0][1].ToString(); - Assert.IsNotEmpty(encryption); - Assert.AreEqual(SessionState.Open, sessionUriRequired.InternalSession.SessionState); + Assert.That(encryption, Is.Not.Empty); + Assert.That(sessionUriRequired.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); } } } diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/TransactionTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/TransactionTests.cs index 092aa057e..6045bd692 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/TransactionTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/TransactionTests.cs @@ -61,17 +61,17 @@ public void Commit() coll.Session.StartTransaction(); Result r = ExecuteAddStatement(coll.Add(docs)); - Assert.AreEqual(4, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(4)); // now roll it back coll.Session.Commit(); var foundDocs = ExecuteFindStatement(coll.Find()); - Assert.True(foundDocs.Next()); - Assert.True(foundDocs.Next()); - Assert.True(foundDocs.Next()); - Assert.True(foundDocs.Next()); - Assert.False(foundDocs.Next()); + Assert.That(foundDocs.Next()); + Assert.That(foundDocs.Next()); + Assert.That(foundDocs.Next()); + Assert.That(foundDocs.Next()); + Assert.That(foundDocs.Next(), Is.False); } [Test] @@ -90,13 +90,13 @@ public void Rollback() coll.Session.StartTransaction(); Result r = ExecuteAddStatement(coll.Add(docs)); - Assert.AreEqual(4, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(4)); // now roll it back coll.Session.Rollback(); var foundDocs = ExecuteFindStatement(coll.Find()); - Assert.False(foundDocs.Next()); + Assert.That(foundDocs.Next(), Is.False); } #region Savepoints @@ -109,7 +109,7 @@ public void CreateUnnamedSavepoint() session.StartTransaction(); string spName = session.SetSavepoint(); - Assert.False(string.IsNullOrWhiteSpace(spName)); + Assert.That(string.IsNullOrWhiteSpace(spName), Is.False); session.Rollback(); } @@ -129,7 +129,7 @@ public void RollbackToSavepoint() ExecuteAddStatement(coll.Add("{ \"test\": \"test\" }")); var sp = session.SetSavepoint(); ExecuteAddStatement(coll.Add("{ \"test\": \"test\" }")); - Assert.AreEqual(2, ExecuteFindStatement(coll.Find()).FetchAll().Count); + Assert.That(ExecuteFindStatement(coll.Find()).FetchAll().Count, Is.EqualTo(2)); session.RollbackTo(sp); Assert.That(ExecuteFindStatement(coll.Find()).FetchAll(), Has.One.Items); @@ -147,9 +147,9 @@ public void ReleaseSavepoint() ExecuteAddStatement(coll.Add("{ \"test\": \"test\" }")); var sp = sessionTest.SetSavepoint(); ExecuteAddStatement(coll.Add("{ \"test2\": \"test2\" }")); - Assert.AreEqual(2, ExecuteFindStatement(coll.Find()).FetchAll().Count); + Assert.That(ExecuteFindStatement(coll.Find()).FetchAll().Count, Is.EqualTo(2)); sessionTest.ReleaseSavepoint(sp); - Assert.AreEqual(2, ExecuteFindStatement(coll.Find()).FetchAll().Count); + Assert.That(ExecuteFindStatement(coll.Find()).FetchAll().Count, Is.EqualTo(2)); sessionTest.Rollback(); } } @@ -162,7 +162,7 @@ public void CreateNamedSavepoint() session.StartTransaction(); string spName = session.SetSavepoint("mySavedPoint"); - Assert.False(string.IsNullOrWhiteSpace(spName)); + Assert.That(string.IsNullOrWhiteSpace(spName), Is.False); session.Rollback(); } @@ -180,7 +180,7 @@ public void RollbackToNamedSavepoint() ExecuteAddStatement(coll.Add("{ \"test\": \"test\" }")); var sp = session.SetSavepoint("mySavedPoint"); ExecuteAddStatement(coll.Add("{ \"test2\": \"test2\" }")); - Assert.AreEqual(2, ExecuteFindStatement(coll.Find()).FetchAll().Count); + Assert.That(ExecuteFindStatement(coll.Find()).FetchAll().Count, Is.EqualTo(2)); session.RollbackTo(sp); Assert.That(ExecuteFindStatement(coll.Find()).FetchAll(), Has.One.Items); session.Rollback(); @@ -199,9 +199,9 @@ public void ReleaseNamedSavepoint() ExecuteAddStatement(coll.Add("{ \"test\": \"test\" }")); var sp = session.SetSavepoint("mySavedPoint"); ExecuteAddStatement(coll.Add("{ \"test2\": \"test2\" }")); - Assert.AreEqual(2, ExecuteFindStatement(coll.Find()).FetchAll().Count); + Assert.That(ExecuteFindStatement(coll.Find()).FetchAll().Count, Is.EqualTo(2)); session.ReleaseSavepoint(sp); - Assert.AreEqual(2, ExecuteFindStatement(coll.Find()).FetchAll().Count); + Assert.That(ExecuteFindStatement(coll.Find()).FetchAll().Count, Is.EqualTo(2)); session.Rollback(); } } @@ -214,10 +214,10 @@ public void NonExistentSavepoint() session.StartTransaction(); Exception exception = Assert.Throws(() => session.RollbackTo("nonExistentSavePoint")); - Assert.AreEqual("SAVEPOINT nonExistentSavePoint does not exist", exception.Message); + Assert.That(exception.Message, Is.EqualTo("SAVEPOINT nonExistentSavePoint does not exist")); exception = Assert.Throws(() => session.ReleaseSavepoint("nonExistentSavePoint")); - Assert.AreEqual("SAVEPOINT nonExistentSavePoint does not exist", exception.Message); + Assert.That(exception.Message, Is.EqualTo("SAVEPOINT nonExistentSavePoint does not exist")); session.Rollback(); } @@ -232,17 +232,17 @@ public void CreateSavepointWithWeirdNames() session.StartTransaction(); Exception ex = Assert.Throws(() => session.SetSavepoint("")); - StringAssert.StartsWith(errorMessage, ex.Message); + Assert.That(ex.Message, Does.StartWith(errorMessage)); ex = Assert.Throws(() => session.SetSavepoint(" ")); - StringAssert.StartsWith(errorMessage, ex.Message); + Assert.That(ex.Message, Does.StartWith(errorMessage)); ex = Assert.Throws(() => session.SetSavepoint(null)); - StringAssert.StartsWith(errorMessage, ex.Message); + Assert.That(ex.Message, Does.StartWith(errorMessage)); ex = Assert.Throws(() => session.SetSavepoint("-")); - StringAssert.StartsWith(errorMessage, ex.Message); + Assert.That(ex.Message, Does.StartWith(errorMessage)); ex = Assert.Throws(() => session.SetSavepoint("mysp+")); - StringAssert.StartsWith(errorMessage, ex.Message); + Assert.That(ex.Message, Does.StartWith(errorMessage)); ex = Assert.Throws(() => session.SetSavepoint("3306")); - StringAssert.StartsWith(errorMessage, ex.Message); + Assert.That(ex.Message, Does.StartWith(errorMessage)); var sp = session.SetSavepoint("_"); session.RollbackTo(sp); @@ -272,7 +272,7 @@ public void OverwriteSavepoint() ExecuteAddStatement(coll.Add("{ \"test4\": \"test4\" }")); sp = session.SetSavepoint("mySP"); session.RollbackTo(sp); - Assert.AreEqual(4, ExecuteFindStatement(coll.Find()).FetchAll().Count); + Assert.That(ExecuteFindStatement(coll.Find()).FetchAll().Count, Is.EqualTo(4)); session.Rollback(); } @@ -288,7 +288,7 @@ public void MultipleReleasesForSavepoint() var sp = session.SetSavepoint("mySP"); session.ReleaseSavepoint(sp); Exception exception = Assert.Throws(() => session.ReleaseSavepoint(sp)); - Assert.AreEqual(string.Format("SAVEPOINT {0} does not exist", sp), exception.Message); + Assert.That(exception.Message, Is.EqualTo(string.Format("SAVEPOINT {0} does not exist", sp))); session.Rollback(); } @@ -305,9 +305,9 @@ public void RollbackAndReleaseAfterTransactionCommit() ExecuteAddStatement(coll.Add("{ \"test\": \"test\" }")); sessionTest.Commit(); Exception exception = Assert.Throws(() => sessionTest.RollbackTo(sp)); - Assert.AreEqual(string.Format("SAVEPOINT {0} does not exist", sp), exception.Message); + Assert.That(exception.Message, Is.EqualTo(string.Format("SAVEPOINT {0} does not exist", sp))); exception = Assert.Throws(() => sessionTest.ReleaseSavepoint(sp)); - Assert.AreEqual(string.Format("SAVEPOINT {0} does not exist", sp), exception.Message); + Assert.That(exception.Message, Is.EqualTo(string.Format("SAVEPOINT {0} does not exist", sp))); } } @@ -325,10 +325,10 @@ public void RollbackAndReleaseAfterTransactionRollback() sessionTest.Rollback(); Exception exception = Assert.Throws(() => sessionTest.RollbackTo(sp)); - Assert.AreEqual(string.Format("SAVEPOINT {0} does not exist", sp), exception.Message); + Assert.That(exception.Message, Is.EqualTo(string.Format("SAVEPOINT {0} does not exist", sp))); exception = Assert.Throws(() => sessionTest.ReleaseSavepoint(sp)); - Assert.AreEqual(string.Format("SAVEPOINT {0} does not exist", sp), exception.Message); + Assert.That(exception.Message, Is.EqualTo(string.Format("SAVEPOINT {0} does not exist", sp))); } } @@ -369,7 +369,7 @@ public void CommitValidWarning() sessionPlain.StartTransaction(); table.Insert().Values(5).Execute(); sessionPlain.Commit(); - Assert.AreEqual(1, table.Count()); + Assert.That(table.Count(), Is.EqualTo(1)); } } @@ -388,9 +388,9 @@ public void CommitInvalidWarning() sessionPlain.StartTransaction(); Assert.Throws(() => sessionPlain.GetSchema("test").GetTable("temp").Insert().Values("abcdef").Execute()); sessionPlain.Commit(); - Assert.AreEqual(0, table.Count()); + Assert.That(table.Count(), Is.EqualTo(0)); var warnings = sessionPlain.SQL("DROP TABLE IF EXISTS temp1").Execute().Warnings; - Assert.IsTrue(warnings.Count > 0); + Assert.That(warnings.Count > 0); sessionPlain.Commit(); } } @@ -409,8 +409,8 @@ public void RollbackValidWarning() sessionPlain.StartTransaction(); var res = table.Insert().Values(5).Execute(); sessionPlain.Rollback(); - Assert.AreEqual(0, table.Count()); - Assert.AreEqual(0, res.Warnings.Count); + Assert.That(table.Count(), Is.EqualTo(0)); + Assert.That(res.Warnings.Count, Is.EqualTo(0)); } } @@ -430,9 +430,9 @@ public void RollbackInvalidWarning() sessionPlain.StartTransaction(); Assert.Throws(() => sessionPlain.GetSchema("test").GetTable("temp").Insert().Values("abcdef").Execute()); sessionPlain.Rollback(); - Assert.AreEqual(0, table.Count()); + Assert.That(table.Count(), Is.EqualTo(0)); var res = sessionPlain.SQL("DROP TABLE IF EXISTS temp1").Execute(); - Assert.IsTrue(res.Warnings.Count > 0); + Assert.That(res.Warnings.Count > 0); } } @@ -467,21 +467,21 @@ public void CommitRollbackInvalidWarning() coll.Session.StartTransaction(); Result r = coll.Add(docs1).Execute(); - Assert.AreEqual(2, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(2)); r = coll.Add(docs2).Execute(); - Assert.AreEqual(2, r.AffectedItemsCount); + Assert.That(r.AffectedItemsCount, Is.EqualTo(2)); r = coll.Add(docs3).Execute(); Assert.Throws(() => coll.Add(docs3).Execute()); coll.Session.Commit(); - Assert.AreEqual(6, coll.Count()); + Assert.That(coll.Count(), Is.EqualTo(6)); // now Rollback coll.Session.Rollback(); - Assert.AreEqual(6, coll.Count()); + Assert.That(coll.Count(), Is.EqualTo(6)); var foundDocs = coll.Find().Execute(); - Assert.IsNotNull(foundDocs); + Assert.That(foundDocs, Is.Not.Null); } [Test, Description("MySQLX plugin Warnings")] @@ -494,12 +494,12 @@ public void Warnings() Collection coll = CreateCollection("test"); Result r = coll.Add("{ \"foo\": 1 }").Execute(); - Assert.AreEqual(1, r.AffectedItemsCount); - Assert.AreEqual(1, coll.Count()); + Assert.That(r.AffectedItemsCount, Is.EqualTo(1)); + Assert.That(coll.Count(), Is.EqualTo(1)); r = coll.Add("{ \"fool\": 2 }").Execute(); - Assert.AreEqual(0, r.Warnings.Count); + Assert.That(r.Warnings.Count, Is.EqualTo(0)); r = coll.Add("{ \"fool\": 10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 }").Execute(); - Assert.AreEqual(0, r.Warnings.Count); + Assert.That(r.Warnings.Count, Is.EqualTo(0)); sessionTest.SQL("use test").Execute(); sessionTest.SQL("CREATE TABLE nontrac(id INT primary key) ENGINE=MyISAM;").Execute(); @@ -511,19 +511,19 @@ public void Warnings() sessionTest.StartTransaction(); var res = sessionTest.SQL("drop table if exists t1, t2").Execute(); - Assert.AreEqual(2, res.Warnings.Count); - Assert.AreEqual(1051, res.Warnings[0].Code); + Assert.That(res.Warnings.Count, Is.EqualTo(2)); + Assert.That(res.Warnings[0].Code, Is.EqualTo(1051)); - Assert.AreEqual(1051, res.Warnings[1].Code); + Assert.That(res.Warnings[1].Code, Is.EqualTo(1051)); res = sessionTest.SQL("create table t1 (a int) engine=innodb").Execute(); - Assert.AreEqual(0, res.Warnings.Count); + Assert.That(res.Warnings.Count, Is.EqualTo(0)); res = sessionTest.SQL("create table t2 (a int) engine=myisam").Execute(); - Assert.AreEqual(0, res.Warnings.Count); + Assert.That(res.Warnings.Count, Is.EqualTo(0)); res = sessionTest.SQL("insert into t1 values(1)").Execute(); - Assert.AreEqual(0, res.Warnings.Count); + Assert.That(res.Warnings.Count, Is.EqualTo(0)); res = sessionTest.SQL("insert into t2 select * from t1").Execute(); - Assert.AreEqual(1, res.Warnings.Count); + Assert.That(res.Warnings.Count, Is.EqualTo(1)); sessionTest.Commit(); } @@ -562,7 +562,7 @@ public void RollbackToSameSavepoint() session.RollbackTo(sp); var doc = col.Find().Execute(); var docs = doc.FetchAll().Count(); - Assert.AreEqual(2, docs); + Assert.That(docs, Is.EqualTo(2)); } @@ -624,7 +624,7 @@ public void MultipleSavepointsAndRollback(string savePoint1, string savePoint2) session.RollbackTo(sp); var doc = col.Find().Execute(); var docs = doc.FetchAll().Count(); - Assert.AreEqual(2, docs); + Assert.That(docs, Is.EqualTo(2)); } [Test, Description("Test creating a savepoint without starting a transaction")] @@ -676,7 +676,7 @@ public void ValidateSavepointsReleased() var doc = col.Find().Execute(); var docs = doc.FetchAll().Count(); - Assert.AreEqual(4, docs); + Assert.That(docs, Is.EqualTo(4)); } @@ -706,7 +706,7 @@ public void NestedTransactions() session.Rollback(); var doc = col.Find().Execute(); var docs = doc.FetchAll().Count(); - Assert.AreEqual(2, docs); + Assert.That(docs, Is.EqualTo(2)); } [Test, Description("Test the behaviour of Savepoints created immediately after one another")] @@ -726,7 +726,7 @@ public void SavepointsCreatedImmediately() session.RollbackTo(sp); var doc = col.Find().Execute(); var docs = doc.FetchAll().Count(); - Assert.AreEqual(2, docs); + Assert.That(docs, Is.EqualTo(2)); } [Test, Description("Test MySQLX plugin Commit After Commit")] @@ -762,33 +762,33 @@ public void CommitAfterCommit() coll.Session.StartTransaction(); Result r = coll.Add(docs1).Execute(); - Assert.AreEqual(2, r.AffectedItemsCount, "Matching"); + Assert.That(r.AffectedItemsCount, Is.EqualTo(2), "Matching"); r = coll.Add(docs2).Execute(); - Assert.AreEqual(2, r.AffectedItemsCount, "Matching"); + Assert.That(r.AffectedItemsCount, Is.EqualTo(2), "Matching"); r = coll.Add(docs3).Execute(); - Assert.AreEqual(2, r.AffectedItemsCount, "Matching"); + Assert.That(r.AffectedItemsCount, Is.EqualTo(2), "Matching"); // now Commit coll.Session.Commit(); // start the transaction coll.Session.StartTransaction(); r = coll.Add(docs4).Execute(); - Assert.AreEqual(2, r.AffectedItemsCount, "Matching"); + Assert.That(r.AffectedItemsCount, Is.EqualTo(2), "Matching"); // now Commit Again coll.Session.Commit(); var foundDocs = coll.Find().Execute(); - Assert.AreEqual(true, foundDocs.Next(), "Matching"); - Assert.AreEqual(true, foundDocs.Next(), "Matching"); - Assert.AreEqual(true, foundDocs.Next(), "Matching"); - Assert.AreEqual(true, foundDocs.Next(), "Matching"); - Assert.AreEqual(true, foundDocs.Next(), "Matching"); - Assert.AreEqual(true, foundDocs.Next(), "Matching"); - Assert.AreEqual(true, foundDocs.Next(), "Matching"); - Assert.AreEqual(true, foundDocs.Next(), "Matching"); - Assert.AreEqual(false, foundDocs.Next(), "Matching"); + Assert.That(foundDocs.Next(), Is.EqualTo(true), "Matching"); + Assert.That(foundDocs.Next(), Is.EqualTo(true), "Matching"); + Assert.That(foundDocs.Next(), Is.EqualTo(true), "Matching"); + Assert.That(foundDocs.Next(), Is.EqualTo(true), "Matching"); + Assert.That(foundDocs.Next(), Is.EqualTo(true), "Matching"); + Assert.That(foundDocs.Next(), Is.EqualTo(true), "Matching"); + Assert.That(foundDocs.Next(), Is.EqualTo(true), "Matching"); + Assert.That(foundDocs.Next(), Is.EqualTo(true), "Matching"); + Assert.That(foundDocs.Next(), Is.EqualTo(false), "Matching"); } @@ -819,19 +819,19 @@ public void RollBackMultiple() coll.Session.StartTransaction(); Result r = coll.Add(docs1).Execute(); - Assert.AreEqual(2, r.AffectedItemsCount, "Matching"); + Assert.That(r.AffectedItemsCount, Is.EqualTo(2), "Matching"); r = coll.Add(docs2).Execute(); - Assert.AreEqual(2, r.AffectedItemsCount, "Matching"); + Assert.That(r.AffectedItemsCount, Is.EqualTo(2), "Matching"); r = coll.Add(docs3).Execute(); - Assert.AreEqual(2, r.AffectedItemsCount, "Matching"); + Assert.That(r.AffectedItemsCount, Is.EqualTo(2), "Matching"); // now Rollback coll.Session.Rollback(); var foundDocs = coll.Find().Execute(); - Assert.AreEqual(false, foundDocs.Next(), "Matching"); + Assert.That(foundDocs.Next(), Is.EqualTo(false), "Matching"); } @@ -869,13 +869,13 @@ public void RollBackAfterRollBack() Result r = coll.Add(docs1).Execute(); //WL11843-Core API v1 alignment Changes - Assert.AreEqual(2, r.AffectedItemsCount, "Matching"); + Assert.That(r.AffectedItemsCount, Is.EqualTo(2), "Matching"); r = coll.Add(docs2).Execute(); - Assert.AreEqual(2, r.AffectedItemsCount, "Matching"); + Assert.That(r.AffectedItemsCount, Is.EqualTo(2), "Matching"); r = coll.Add(docs3).Execute(); - Assert.AreEqual(2, r.AffectedItemsCount, "Matching"); + Assert.That(r.AffectedItemsCount, Is.EqualTo(2), "Matching"); // now Rollback coll.Session.Rollback(); @@ -884,13 +884,13 @@ public void RollBackAfterRollBack() coll.Session.StartTransaction(); r = coll.Add(docs4).Execute(); - Assert.AreEqual(2, r.AffectedItemsCount, "Matching"); + Assert.That(r.AffectedItemsCount, Is.EqualTo(2), "Matching"); // now Rollback Again coll.Session.Rollback(); var foundDocs = coll.Find().Execute(); - Assert.AreEqual(false, foundDocs.Next(), "Matching"); + Assert.That(foundDocs.Next(), Is.EqualTo(false), "Matching"); } @@ -922,13 +922,13 @@ public void CommitRollBack() Result r = coll.Add(docs1).Execute(); //WL11843-Core API v1 alignment Changes - Assert.AreEqual(2, r.AffectedItemsCount, "Matching"); + Assert.That(r.AffectedItemsCount, Is.EqualTo(2), "Matching"); r = coll.Add(docs2).Execute(); - Assert.AreEqual(2, r.AffectedItemsCount, "Matching"); + Assert.That(r.AffectedItemsCount, Is.EqualTo(2), "Matching"); r = coll.Add(docs3).Execute(); - Assert.AreEqual(2, r.AffectedItemsCount, "Matching"); + Assert.That(r.AffectedItemsCount, Is.EqualTo(2), "Matching"); //now Commit coll.Session.Commit(); @@ -936,13 +936,13 @@ public void CommitRollBack() coll.Session.Rollback(); var foundDocs = coll.Find().Execute(); - Assert.AreEqual(true, foundDocs.Next(), "Matching"); - Assert.AreEqual(true, foundDocs.Next(), "Matching"); - Assert.AreEqual(true, foundDocs.Next(), "Matching"); - Assert.AreEqual(true, foundDocs.Next(), "Matching"); - Assert.AreEqual(true, foundDocs.Next(), "Matching"); - Assert.AreEqual(true, foundDocs.Next(), "Matching"); - Assert.AreEqual(false, foundDocs.Next(), "Matching"); + Assert.That(foundDocs.Next(), Is.EqualTo(true), "Matching"); + Assert.That(foundDocs.Next(), Is.EqualTo(true), "Matching"); + Assert.That(foundDocs.Next(), Is.EqualTo(true), "Matching"); + Assert.That(foundDocs.Next(), Is.EqualTo(true), "Matching"); + Assert.That(foundDocs.Next(), Is.EqualTo(true), "Matching"); + Assert.That(foundDocs.Next(), Is.EqualTo(true), "Matching"); + Assert.That(foundDocs.Next(), Is.EqualTo(false), "Matching"); } @@ -972,22 +972,22 @@ public void RollBackCommit() // start the transaction coll.Session.StartTransaction(); Result r = coll.Add(docs1).Execute(); - Assert.AreEqual(2, r.AffectedItemsCount, "Matching"); + Assert.That(r.AffectedItemsCount, Is.EqualTo(2), "Matching"); // now Rollback coll.Session.Rollback(); r = coll.Add(docs2).Execute(); - Assert.AreEqual(2, r.AffectedItemsCount, "Matching"); + Assert.That(r.AffectedItemsCount, Is.EqualTo(2), "Matching"); r = coll.Add(docs3).Execute(); - Assert.AreEqual(2, r.AffectedItemsCount, "Matching"); + Assert.That(r.AffectedItemsCount, Is.EqualTo(2), "Matching"); //now Commit coll.Session.Commit(); var foundDocs = coll.Find().Execute(); - Assert.AreEqual(true, foundDocs.Next(), "Matching"); - Assert.AreEqual(true, foundDocs.Next(), "Matching"); - Assert.AreEqual(true, foundDocs.Next(), "Matching"); - Assert.AreEqual(true, foundDocs.Next(), "Matching"); - Assert.AreEqual(false, foundDocs.Next(), "Matching"); + Assert.That(foundDocs.Next(), Is.EqualTo(true), "Matching"); + Assert.That(foundDocs.Next(), Is.EqualTo(true), "Matching"); + Assert.That(foundDocs.Next(), Is.EqualTo(true), "Matching"); + Assert.That(foundDocs.Next(), Is.EqualTo(true), "Matching"); + Assert.That(foundDocs.Next(), Is.EqualTo(false), "Matching"); } diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/UnixSocketsTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/UnixSocketsTests.cs index 680642278..17c083be1 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/UnixSocketsTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/UnixSocketsTests.cs @@ -52,14 +52,14 @@ public void ConnectionWithUriConnectionString() using (var session = MySQLX.GetSession("mysqlx://root:@" + defaultUnixSocket + "?protocol=unix&sslmode=none")) { - Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); - Assert.AreEqual(defaultUnixSocket, session.Settings.Server); + Assert.That(session.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); + Assert.That(session.Settings.Server, Is.EqualTo(defaultUnixSocket)); } using (var session = MySQLX.GetSession("mysqlx://root:@" + defaultUnixSocket.Replace("/", "%2F") + "?protocol=unix&sslmode=none")) { - Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); - Assert.AreEqual(defaultUnixSocket, session.Settings.Server); + Assert.That(session.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); + Assert.That(session.Settings.Server, Is.EqualTo(defaultUnixSocket)); } } @@ -71,8 +71,8 @@ public void ConnectionWithUriConnectionStringIncludingSchema() using (var session = MySQLX.GetSession($"mysqlx://root:@({defaultUnixSocket})/mysql?protocol=unix&sslmode=none")) { - Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); - Assert.AreEqual(defaultUnixSocket, session.Settings.Server); + Assert.That(session.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); + Assert.That(session.Settings.Server, Is.EqualTo(defaultUnixSocket)); } } @@ -84,14 +84,14 @@ public void ConnectionWithParenthesisEnclosedSockets() using (var session = MySQLX.GetSession($"mysqlx://{RootUser}:@({defaultUnixSocket})?protocol=unix&sslmode=none")) { - Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); - Assert.AreEqual(defaultUnixSocket, session.Settings.Server); + Assert.That(session.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); + Assert.That(session.Settings.Server, Is.EqualTo(defaultUnixSocket)); } using (var session = MySQLX.GetSession($"server=({defaultUnixSocket});uid={RootUser};protocol=unix;sslmode=none")) { - Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); - Assert.AreEqual(defaultUnixSocket, session.Settings.Server); + Assert.That(session.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); + Assert.That(session.Settings.Server, Is.EqualTo(defaultUnixSocket)); } using (var session = MySQLX.GetSession(new @@ -102,8 +102,8 @@ public void ConnectionWithParenthesisEnclosedSockets() sslmode = MySqlSslMode.Disabled })) { - Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); - Assert.AreEqual(defaultUnixSocket, session.Settings.Server); + Assert.That(session.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); + Assert.That(session.Settings.Server, Is.EqualTo(defaultUnixSocket)); } } @@ -115,8 +115,8 @@ public void ConnectionWithBasicConnectionString() using (var session = MySQLX.GetSession($"server={defaultUnixSocket};uid={RootUser};protocol=unixsocket;sslmode=none")) { - Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); - Assert.AreEqual(defaultUnixSocket, session.Settings.Server); + Assert.That(session.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); + Assert.That(session.Settings.Server, Is.EqualTo(defaultUnixSocket)); } } @@ -134,8 +134,8 @@ public void ConnectionWithAnonymousObject() sslmode = MySqlSslMode.Disabled })) { - Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); - Assert.AreEqual(defaultUnixSocket, session.Settings.Server); + Assert.That(session.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); + Assert.That(session.Settings.Server, Is.EqualTo(defaultUnixSocket)); } } @@ -156,50 +156,50 @@ public void Failover() using (var session = MySQLX.GetSession($"server=/tmp/mysql.sock1, (/tmp/mysql.sock2) ,(%2Ftmp%2Fmysql.sock3) ,{defaultUnixSocket};uid={RootUser};protocol=unix;sslmode=none;")) { - Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); - Assert.AreEqual(defaultUnixSocket, session.Settings.Server); + Assert.That(session.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); + Assert.That(session.Settings.Server, Is.EqualTo(defaultUnixSocket)); } using (var session = MySQLX.GetSession($"server=(address=/tmp/mysql.sock1, priority=100),(address=(/tmp/mysql.sock2),priority=99),(address=(%2tmp%2mysql.sock3),priority=98),(address={defaultUnixSocket},priority=97);uid={RootUser};protocol=unix;sslmode=none;")) { - Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); - Assert.AreEqual(defaultUnixSocket, session.Settings.Server); + Assert.That(session.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); + Assert.That(session.Settings.Server, Is.EqualTo(defaultUnixSocket)); } using (var session = MySQLX.GetSession($"server=(address={defaultUnixSocket},priority=100);uid={RootUser};protocol=unix;sslmode=none;")) { - Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); - Assert.AreEqual(defaultUnixSocket, session.Settings.Server); + Assert.That(session.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); + Assert.That(session.Settings.Server, Is.EqualTo(defaultUnixSocket)); } using (var session = MySQLX.GetSession($"server=(address=({defaultUnixSocket}),priority=100);uid={RootUser};protocol=unix;sslmode=none;")) { - Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); - Assert.AreEqual(defaultUnixSocket, session.Settings.Server); + Assert.That(session.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); + Assert.That(session.Settings.Server, Is.EqualTo(defaultUnixSocket)); } using (var session = MySQLX.GetSession($"mysqlx://{RootUser}:@[./tmp/mysql.sock, (../tmp/mysql.sock) ,(%2Ftmpsocket%2Fmysql.sock) , {defaultUnixSocket}]?protocol=unix&sslmode=none")) { - Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); - Assert.AreEqual(defaultUnixSocket, session.Settings.Server); + Assert.That(session.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); + Assert.That(session.Settings.Server, Is.EqualTo(defaultUnixSocket)); } using (var session = MySQLX.GetSession($"mysqlx://{RootUser}:@[(address=./tmp/mysql.sock,priority=100),(address=(../tmp/mysql.sock),priority=99),(address=(%2tmpsocket%2mysql.sock),priority=98),(address={defaultUnixSocket},priority=97)]?protocol=unix&sslmode=none")) { - Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); - Assert.AreEqual(defaultUnixSocket, session.Settings.Server); + Assert.That(session.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); + Assert.That(session.Settings.Server, Is.EqualTo(defaultUnixSocket)); } using (var session = MySQLX.GetSession($"mysqlx://{RootUser}:@[(address={defaultUnixSocket},priority=100)]?protocol=unix&sslmode=none")) { - Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); - Assert.AreEqual(defaultUnixSocket, session.Settings.Server); + Assert.That(session.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); + Assert.That(session.Settings.Server, Is.EqualTo(defaultUnixSocket)); } using (var session = MySQLX.GetSession($"mysqlx://{RootUser}:@[(address=({defaultUnixSocket}),priority=100)]?protocol=unix&sslmode=none")) { - Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); - Assert.AreEqual(defaultUnixSocket, session.Settings.Server); + Assert.That(session.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); + Assert.That(session.Settings.Server, Is.EqualTo(defaultUnixSocket)); } using (var session = MySQLX.GetSession(new @@ -210,8 +210,8 @@ public void Failover() sslmode = MySqlSslMode.Disabled })) { - Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); - Assert.AreEqual(defaultUnixSocket, session.Settings.Server); + Assert.That(session.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); + Assert.That(session.Settings.Server, Is.EqualTo(defaultUnixSocket)); } using (var session = MySQLX.GetSession(new @@ -222,8 +222,8 @@ public void Failover() sslmode = MySqlSslMode.Disabled })) { - Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); - Assert.AreEqual(defaultUnixSocket, session.Settings.Server); + Assert.That(session.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); + Assert.That(session.Settings.Server, Is.EqualTo(defaultUnixSocket)); } using (var session = MySQLX.GetSession(new @@ -234,8 +234,8 @@ public void Failover() sslmode = MySqlSslMode.Disabled })) { - Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); - Assert.AreEqual(defaultUnixSocket, session.Settings.Server); + Assert.That(session.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); + Assert.That(session.Settings.Server, Is.EqualTo(defaultUnixSocket)); } using (var session = MySQLX.GetSession(new @@ -246,8 +246,8 @@ public void Failover() sslmode = MySqlSslMode.Disabled })) { - Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); - Assert.AreEqual(defaultUnixSocket, session.Settings.Server); + Assert.That(session.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); + Assert.That(session.Settings.Server, Is.EqualTo(defaultUnixSocket)); } } } diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/XAuth.cs b/MySQL.Data/tests/MySqlX.Data.Tests/XAuth.cs index 4cd927b21..24ae47b85 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/XAuth.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/XAuth.cs @@ -57,18 +57,18 @@ public void DefaultAuthNullPlugin() connectionString = $"server={Host};user={builder.UserID};port={XPort};password={builder.Password}"; using (var session1 = MySQLX.GetSession(connectionString)) { - Assert.AreEqual(MySqlAuthenticationMode.PLAIN, session1.Settings.Auth); + Assert.That(session1.Settings.Auth, Is.EqualTo(MySqlAuthenticationMode.PLAIN)); var result = session1.SQL("SHOW SESSION STATUS LIKE 'Mysqlx_ssl_version';").Execute().FetchAll(); - Assert.True(result[0][1].ToString().Contains("TLSv1")); + Assert.That(result[0][1].ToString().Contains("TLSv1")); } connectionString = connectionString + ";sslmode=none;"; using (var session1 = MySQLX.GetSession(connectionString)) - Assert.AreEqual(defaultAuthPlugin == "mysql_native_password" ? MySqlAuthenticationMode.MYSQL41 : MySqlAuthenticationMode.SHA256_MEMORY, session1.Settings.Auth); + Assert.That(session1.Settings.Auth, Is.EqualTo(defaultAuthPlugin == "mysql_native_password" ? MySqlAuthenticationMode.MYSQL41 : MySqlAuthenticationMode.SHA256_MEMORY)); connectionString = $"server={Host};user={builder.UserID};port={XPort};password={builder.Password};ssl-mode=VerifyCA;ssl-ca={sslCa};ssl-ca-pwd=pass;"; using (var session1 = MySQLX.GetSession(connectionString)) - Assert.AreEqual(MySqlAuthenticationMode.PLAIN, session1.Settings.Auth); + Assert.That(session1.Settings.Auth, Is.EqualTo(MySqlAuthenticationMode.PLAIN)); //invalid values connectionString = $"server={Host};user={builder.UserID};port={XPort};password={builder.Password};ssl-mode=required;auth=shaa256memory"; @@ -79,21 +79,21 @@ public void DefaultAuthNullPlugin() builder.Server + ":" + XPort; using (var session1 = MySQLX.GetSession(connectionStringUri)) { - Assert.AreEqual(MySqlAuthenticationMode.PLAIN, session1.Settings.Auth); + Assert.That(session1.Settings.Auth, Is.EqualTo(MySqlAuthenticationMode.PLAIN)); var result = session1.SQL("SHOW SESSION STATUS LIKE 'Mysqlx_ssl_version';").Execute().FetchAll(); - Assert.True(result[0][1].ToString().Contains("TLSv1")); + Assert.That(result[0][1].ToString().Contains("TLSv1")); } connectionStringUri = connectionStringUri + "?sslmode=none"; using (var session1 = MySQLX.GetSession(connectionStringUri)) - Assert.AreEqual(defaultAuthPlugin == "mysql_native_password" ? MySqlAuthenticationMode.MYSQL41 : MySqlAuthenticationMode.SHA256_MEMORY, session1.Settings.Auth); + Assert.That(session1.Settings.Auth, Is.EqualTo(defaultAuthPlugin == "mysql_native_password" ? MySqlAuthenticationMode.MYSQL41 : MySqlAuthenticationMode.SHA256_MEMORY)); //Anonymous Object using (var session1 = MySQLX.GetSession(new { server = builder.Server, port = XPort, user = builder.UserID, password = builder.Password })) { - Assert.AreEqual(MySqlAuthenticationMode.PLAIN, session1.Settings.Auth); + Assert.That(session1.Settings.Auth, Is.EqualTo(MySqlAuthenticationMode.PLAIN)); var result = session1.SQL("SHOW SESSION STATUS LIKE 'Mysqlx_ssl_version';").Execute().FetchAll(); - Assert.True(result[0][1].ToString().Contains("TLSv1")); + Assert.That(result[0][1].ToString().Contains("TLSv1")); } using (var session1 = MySQLX.GetSession( @@ -105,32 +105,32 @@ public void DefaultAuthNullPlugin() sslmode = MySqlSslMode.Disabled, password = builder.Password })) - Assert.AreEqual(defaultAuthPlugin == "mysql_native_password" ? MySqlAuthenticationMode.MYSQL41 : MySqlAuthenticationMode.SHA256_MEMORY, session1.Settings.Auth); + Assert.That(session1.Settings.Auth, Is.EqualTo(defaultAuthPlugin == "mysql_native_password" ? MySqlAuthenticationMode.MYSQL41 : MySqlAuthenticationMode.SHA256_MEMORY)); ExecuteSQL("flush privileges"); connectionString = $"server={Host};user={builder.UserID};port={XPort};password={builder.Password};ssl-mode=none"; if (defaultAuthPlugin == "mysql_native_password") - Assert.NotNull(MySQLX.GetSession(connectionString)); + Assert.That(MySQLX.GetSession(connectionString), Is.Not.Null); else Assert.Throws(() => MySQLX.GetSession(connectionString)); //URI connectionStringUri = $"mysqlx://{builder.UserID}:{builder.Password}@{builder.Server}:{XPort}?sslmode=none"; if (defaultAuthPlugin == "mysql_native_password") - Assert.NotNull(MySQLX.GetSession(connectionStringUri)); + Assert.That(MySQLX.GetSession(connectionStringUri), Is.Not.Null); else Assert.Throws(() => MySQLX.GetSession(connectionStringUri)); //Anonymous Object if (defaultAuthPlugin == "mysql_native_password") - Assert.NotNull(MySQLX.GetSession(new + Assert.That(MySQLX.GetSession(new { server = Host, port = XPort, user = builder.UserID, sslmode = MySqlSslMode.Disabled, password = builder.Password - })); + }), Is.Not.Null); else Assert.Throws(() => MySQLX.GetSession(new { @@ -211,29 +211,29 @@ public void MySqlNativePlugin() //Connection String connectionString = $"server={Host};user={builder.UserID};port={XPort};password={builder.Password}"; using (var session1 = MySQLX.GetSession(connectionString)) - Assert.AreEqual(MySqlAuthenticationMode.PLAIN, session1.Settings.Auth); + Assert.That(session1.Settings.Auth, Is.EqualTo(MySqlAuthenticationMode.PLAIN)); connectionString += ";ssl-mode=VerifyCA;ssl-ca=" + sslCa + ";ssl-ca-pwd=pass;"; using (var session1 = MySQLX.GetSession(connectionString)) - Assert.AreEqual(MySqlAuthenticationMode.PLAIN, session1.Settings.Auth); + Assert.That(session1.Settings.Auth, Is.EqualTo(MySqlAuthenticationMode.PLAIN)); connectionString = $"server={Host};user={builder.UserID};port={XPort};password={builder.Password};ssl-mode=none"; using (var session1 = MySQLX.GetSession(connectionString)) - Assert.AreEqual(MySqlAuthenticationMode.MYSQL41, session1.Settings.Auth); + Assert.That(session1.Settings.Auth, Is.EqualTo(MySqlAuthenticationMode.MYSQL41)); connectionString = $"server={Host};user={builder.UserID};port={XPort};password={builder.Password};ssl-mode=Required;ssl-ca={sslCa};ssl-ca-pwd=pass;"; using (var session1 = MySQLX.GetSession(connectionString)) - Assert.AreEqual(MySqlAuthenticationMode.PLAIN, session1.Settings.Auth); + Assert.That(session1.Settings.Auth, Is.EqualTo(MySqlAuthenticationMode.PLAIN)); //URI ExecuteSQL("flush privileges"); connectionStringUri = $"mysqlx://{builder.UserID}:{builder.Password}@{builder.Server}:{XPort}"; using (var session1 = MySQLX.GetSession(connectionStringUri)) - Assert.AreEqual(MySqlAuthenticationMode.PLAIN, session1.Settings.Auth); + Assert.That(session1.Settings.Auth, Is.EqualTo(MySqlAuthenticationMode.PLAIN)); connectionStringUri = connectionStringUri + "?ssl-mode=none"; using (var session1 = MySQLX.GetSession(connectionStringUri)) - Assert.AreEqual(MySqlAuthenticationMode.MYSQL41, session1.Settings.Auth); + Assert.That(session1.Settings.Auth, Is.EqualTo(MySqlAuthenticationMode.MYSQL41)); //Anonymous Object ExecuteSQL("flush privileges"); @@ -244,7 +244,7 @@ public void MySqlNativePlugin() user = builder.UserID, password = builder.Password })) - Assert.AreEqual(MySqlAuthenticationMode.PLAIN, session1.Settings.Auth); + Assert.That(session1.Settings.Auth, Is.EqualTo(MySqlAuthenticationMode.PLAIN)); using (var session1 = MySQLX.GetSession(new { @@ -254,7 +254,7 @@ public void MySqlNativePlugin() sslmode = MySqlSslMode.Disabled, password = builder.Password })) - Assert.AreEqual(MySqlAuthenticationMode.MYSQL41, session1.Settings.Auth); + Assert.That(session1.Settings.Auth, Is.EqualTo(MySqlAuthenticationMode.MYSQL41)); } [Test] @@ -274,14 +274,14 @@ public void ConnectUsingMySQL41Auth() using (var session = MySQLX.GetSession(connectionStringUri + "?auth=MySQL41")) { - Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); - Assert.AreEqual(MySqlAuthenticationMode.MYSQL41, session.Settings.Auth); + Assert.That(session.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); + Assert.That(session.Settings.Auth, Is.EqualTo(MySqlAuthenticationMode.MYSQL41)); } using (var session = MySQLX.GetSession(connectionStringUri + "?auth=mysql41&sslmode=none")) { - Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); - Assert.AreEqual(MySqlAuthenticationMode.MYSQL41, session.Settings.Auth); + Assert.That(session.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); + Assert.That(session.Settings.Auth, Is.EqualTo(MySqlAuthenticationMode.MYSQL41)); } } @@ -300,17 +300,17 @@ public void DefaultAuth() // Default to PLAIN when TLS is enabled. using (var session = MySQLX.GetSession(connString)) { - Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); - Assert.AreEqual(MySqlAuthenticationMode.PLAIN, session.Settings.Auth); + Assert.That(session.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); + Assert.That(session.Settings.Auth, Is.EqualTo(MySqlAuthenticationMode.PLAIN)); var result = ExecuteSQLStatement(session.SQL("SHOW SESSION STATUS LIKE 'Mysqlx_ssl_version';")).FetchAll(); - StringAssert.StartsWith("TLSv1", result[0][1].ToString()); + Assert.That(result[0][1].ToString(), Does.StartWith("TLSv1")); } // Default to SHA256_MEMORY when TLS is not enabled. using (var session = MySQLX.GetSession(connString + "?sslmode=none")) { - Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); - Assert.AreEqual(MySqlAuthenticationMode.SHA256_MEMORY, session.Settings.Auth); + Assert.That(session.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); + Assert.That(session.Settings.Auth, Is.EqualTo(MySqlAuthenticationMode.SHA256_MEMORY)); } } @@ -322,16 +322,16 @@ public void ConnectUsingSha256Memory() using (var session = MySQLX.GetSession(ConnectionStringUri + "?auth=SHA256_MEMORY")) { - Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); - Assert.AreEqual(MySqlAuthenticationMode.SHA256_MEMORY, session.Settings.Auth); + Assert.That(session.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); + Assert.That(session.Settings.Auth, Is.EqualTo(MySqlAuthenticationMode.SHA256_MEMORY)); var result = session.SQL("SHOW SESSION STATUS LIKE 'Mysqlx_ssl_version';").Execute().FetchAll(); - Assert.True(result[0][1].ToString().Contains("TLSv1")); + Assert.That(result[0][1].ToString().Contains("TLSv1")); } using (var session = MySQLX.GetSession(ConnectionStringUri + "?auth=SHA256_MEMORY&sslmode=none")) { - Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); - Assert.AreEqual(MySqlAuthenticationMode.SHA256_MEMORY, session.Settings.Auth); + Assert.That(session.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); + Assert.That(session.Settings.Auth, Is.EqualTo(MySqlAuthenticationMode.SHA256_MEMORY)); } using (var session1 = MySQLX.GetSession( @@ -345,8 +345,8 @@ public void ConnectUsingSha256Memory() auth = MySqlAuthenticationMode.SHA256_MEMORY })) { - Assert.AreEqual(SessionState.Open, session1.InternalSession.SessionState); - Assert.AreEqual(MySqlAuthenticationMode.SHA256_MEMORY, session1.Settings.Auth); + Assert.That(session1.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); + Assert.That(session1.Settings.Auth, Is.EqualTo(MySqlAuthenticationMode.SHA256_MEMORY)); } //Exceptions @@ -433,31 +433,31 @@ public void NativeAuthValidAndInvalidConnection() var cs = $"server={Host};user={user};port={XPort};password={pwd}"; //Connection String using (var session1 = MySQLX.GetSession(ConnectionString)) - Assert.AreEqual(MySqlAuthenticationMode.PLAIN, session1.Settings.Auth); + Assert.That(session1.Settings.Auth, Is.EqualTo(MySqlAuthenticationMode.PLAIN)); using (var session1 = MySQLX.GetSession(cs + ";auth=mysql41")) - Assert.AreEqual(MySqlAuthenticationMode.MYSQL41, session1.Settings.Auth); + Assert.That(session1.Settings.Auth, Is.EqualTo(MySqlAuthenticationMode.MYSQL41)); using (var session1 = MySQLX.GetSession(cs + ";auth=mysql41;ssl-mode=none")) - Assert.AreEqual(MySqlAuthenticationMode.MYSQL41, session1.Settings.Auth); + Assert.That(session1.Settings.Auth, Is.EqualTo(MySqlAuthenticationMode.MYSQL41)); using (var session1 = MySQLX.GetSession(cs + ";auth=mysql41;ssl-mode=Required")) - Assert.AreEqual(MySqlAuthenticationMode.MYSQL41, session1.Settings.Auth); + Assert.That(session1.Settings.Auth, Is.EqualTo(MySqlAuthenticationMode.MYSQL41)); using (var session1 = MySQLX.GetSession(ConnectionString + ";auth=PLAIN")) - Assert.AreEqual(MySqlAuthenticationMode.PLAIN, session1.Settings.Auth); + Assert.That(session1.Settings.Auth, Is.EqualTo(MySqlAuthenticationMode.PLAIN)); using (var session1 = MySQLX.GetSession(ConnectionString + ";auth=plain;ssl-mode=Required")) - Assert.AreEqual(MySqlAuthenticationMode.PLAIN, session1.Settings.Auth); + Assert.That(session1.Settings.Auth, Is.EqualTo(MySqlAuthenticationMode.PLAIN)); using (var session1 = MySQLX.GetSession(cs + ";ssl-mode=none")) - Assert.AreEqual(MySqlAuthenticationMode.MYSQL41, session1.Settings.Auth); + Assert.That(session1.Settings.Auth, Is.EqualTo(MySqlAuthenticationMode.MYSQL41)); using (var session1 = MySQLX.GetSession(ConnectionString + ";ssl-mode=Required")) { - Assert.AreEqual(MySqlAuthenticationMode.PLAIN, session1.Settings.Auth); + Assert.That(session1.Settings.Auth, Is.EqualTo(MySqlAuthenticationMode.PLAIN)); var result = session.SQL("SHOW SESSION STATUS LIKE 'Mysqlx_ssl_version';").Execute().FetchAll(); - Assert.True(result[0][1].ToString().Contains("TLSv1")); + Assert.That(result[0][1].ToString().Contains("TLSv1")); } Assert.Throws(() => MySQLX.GetSession(ConnectionString + ";auth=PLAIN;ssl-mode=none")); @@ -469,33 +469,33 @@ public void NativeAuthValidAndInvalidConnection() Assert.Throws(() => MySQLX.GetSession(ConnectionString + ";auth=INVALID;ssl-mode=Required")); //Uri using (var session1 = MySQLX.GetSession(ConnectionStringUriNative)) - Assert.AreEqual(MySqlAuthenticationMode.PLAIN, session1.Settings.Auth); + Assert.That(session1.Settings.Auth, Is.EqualTo(MySqlAuthenticationMode.PLAIN)); using (var session1 = MySQLX.GetSession(ConnectionStringUriNative + "?auth=MySQL41")) - Assert.AreEqual(MySqlAuthenticationMode.MYSQL41, session1.Settings.Auth); + Assert.That(session1.Settings.Auth, Is.EqualTo(MySqlAuthenticationMode.MYSQL41)); using (var session1 = MySQLX.GetSession(ConnectionStringUriNative + "?auth=MySQL41&ssl-mode=none")) - Assert.AreEqual(MySqlAuthenticationMode.MYSQL41, session1.Settings.Auth); + Assert.That(session1.Settings.Auth, Is.EqualTo(MySqlAuthenticationMode.MYSQL41)); using (var session1 = MySQLX.GetSession(ConnectionStringUriNative + "?auth=MySQL41&ssl-mode=Required")) - Assert.AreEqual(MySqlAuthenticationMode.MYSQL41, session1.Settings.Auth); + Assert.That(session1.Settings.Auth, Is.EqualTo(MySqlAuthenticationMode.MYSQL41)); using (var session1 = MySQLX.GetSession(ConnectionStringUriNative + "?auth=PLAIN")) - Assert.AreEqual(MySqlAuthenticationMode.PLAIN, session1.Settings.Auth); + Assert.That(session1.Settings.Auth, Is.EqualTo(MySqlAuthenticationMode.PLAIN)); Assert.Throws(() => MySQLX.GetSession(ConnectionStringUriNative + "?auth=PLAIN&ssl-mode=none")); using (var session1 = MySQLX.GetSession(ConnectionStringUriNative + "?auth=PLAIN&ssl-mode=Required")) - Assert.AreEqual(MySqlAuthenticationMode.PLAIN, session1.Settings.Auth); + Assert.That(session1.Settings.Auth, Is.EqualTo(MySqlAuthenticationMode.PLAIN)); using (var session1 = MySQLX.GetSession(ConnectionStringUriNative + "?ssl-mode=none")) - Assert.AreEqual(MySqlAuthenticationMode.MYSQL41, session1.Settings.Auth); + Assert.That(session1.Settings.Auth, Is.EqualTo(MySqlAuthenticationMode.MYSQL41)); using (var session1 = MySQLX.GetSession(ConnectionStringUriNative + "?ssl-mode=Required")) { - Assert.AreEqual(MySqlAuthenticationMode.PLAIN, session1.Settings.Auth); + Assert.That(session1.Settings.Auth, Is.EqualTo(MySqlAuthenticationMode.PLAIN)); var result = session.SQL("SHOW SESSION STATUS LIKE 'Mysqlx_ssl_version';").Execute().FetchAll(); - Assert.True(result[0][1].ToString().Contains("TLSv1")); + Assert.That(result[0][1].ToString().Contains("TLSv1")); } Assert.Throws(() => MySQLX.GetSession(ConnectionStringUriNative + "?auth=EXTERNAL")); @@ -512,7 +512,7 @@ public void NativeAuthValidAndInvalidConnection() user = user, password = pwd })) - Assert.AreEqual(MySqlAuthenticationMode.PLAIN, session1.Settings.Auth); + Assert.That(session1.Settings.Auth, Is.EqualTo(MySqlAuthenticationMode.PLAIN)); using (var session1 = MySQLX.GetSession(new { @@ -522,7 +522,7 @@ public void NativeAuthValidAndInvalidConnection() password = pwd, auth = MySqlAuthenticationMode.MYSQL41 })) - Assert.AreEqual(MySqlAuthenticationMode.MYSQL41, session1.Settings.Auth); + Assert.That(session1.Settings.Auth, Is.EqualTo(MySqlAuthenticationMode.MYSQL41)); using (var session1 = MySQLX.GetSession(new { @@ -533,7 +533,7 @@ public void NativeAuthValidAndInvalidConnection() auth = MySqlAuthenticationMode.MYSQL41, sslmode = MySqlSslMode.Disabled })) - Assert.AreEqual(MySqlAuthenticationMode.MYSQL41, session1.Settings.Auth); + Assert.That(session1.Settings.Auth, Is.EqualTo(MySqlAuthenticationMode.MYSQL41)); using (var session1 = MySQLX.GetSession(new { @@ -544,7 +544,7 @@ public void NativeAuthValidAndInvalidConnection() auth = MySqlAuthenticationMode.MYSQL41, sslmode = MySqlSslMode.Required })) - Assert.AreEqual(MySqlAuthenticationMode.MYSQL41, session1.Settings.Auth); + Assert.That(session1.Settings.Auth, Is.EqualTo(MySqlAuthenticationMode.MYSQL41)); using (var session1 = MySQLX.GetSession(new { @@ -554,7 +554,7 @@ public void NativeAuthValidAndInvalidConnection() password = pwd, auth = MySqlAuthenticationMode.PLAIN })) - Assert.AreEqual(MySqlAuthenticationMode.PLAIN, session1.Settings.Auth); + Assert.That(session1.Settings.Auth, Is.EqualTo(MySqlAuthenticationMode.PLAIN)); Assert.Throws(() => MySQLX.GetSession(new { @@ -575,7 +575,7 @@ public void NativeAuthValidAndInvalidConnection() auth = MySqlAuthenticationMode.PLAIN, sslmode = MySqlSslMode.Required })) - Assert.AreEqual(MySqlAuthenticationMode.PLAIN, session1.Settings.Auth); + Assert.That(session1.Settings.Auth, Is.EqualTo(MySqlAuthenticationMode.PLAIN)); using (var session1 = MySQLX.GetSession(new { @@ -585,7 +585,7 @@ public void NativeAuthValidAndInvalidConnection() password = pwd, sslmode = MySqlSslMode.Disabled })) - Assert.AreEqual(MySqlAuthenticationMode.MYSQL41, session1.Settings.Auth); + Assert.That(session1.Settings.Auth, Is.EqualTo(MySqlAuthenticationMode.MYSQL41)); using (var session1 = MySQLX.GetSession(new { @@ -596,9 +596,9 @@ public void NativeAuthValidAndInvalidConnection() sslmode = MySqlSslMode.Required })) { - Assert.AreEqual(MySqlAuthenticationMode.PLAIN, session1.Settings.Auth); + Assert.That(session1.Settings.Auth, Is.EqualTo(MySqlAuthenticationMode.PLAIN)); var result = session1.SQL("SHOW SESSION STATUS LIKE 'Mysqlx_ssl_version';").Execute().FetchAll(); - Assert.True(result[0][1].ToString().Contains("TLSv1")); + Assert.That(result[0][1].ToString().Contains("TLSv1")); } Assert.Throws(() => MySQLX.GetSession(new @@ -618,10 +618,10 @@ public void ConnectUsingExternalAuth() { // Should fail since EXTERNAL is currently not supported by X Plugin. Exception ex = Assert.Throws(() => MySQLX.GetSession(ConnectionString + ";auth=EXTERNAL")); - Assert.AreEqual("Invalid authentication method EXTERNAL", ex.Message); + Assert.That(ex.Message, Is.EqualTo("Invalid authentication method EXTERNAL")); ex = Assert.Throws(() => MySQLX.GetSession(ConnectionStringUri + "?auth=EXTERNAL")); - Assert.AreEqual("Invalid authentication method EXTERNAL", ex.Message); + Assert.That(ex.Message, Is.EqualTo("Invalid authentication method EXTERNAL")); } [Test] @@ -630,14 +630,14 @@ public void ConnectUsingPlainAuth() { using (var session = MySQLX.GetSession(ConnectionString + ";auth=pLaIn")) { - Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); - Assert.AreEqual(MySqlAuthenticationMode.PLAIN, session.Settings.Auth); + Assert.That(session.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); + Assert.That(session.Settings.Auth, Is.EqualTo(MySqlAuthenticationMode.PLAIN)); } using (var session = MySQLX.GetSession(ConnectionStringUri + "?auth=pLaIn")) { - Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); - Assert.AreEqual(MySqlAuthenticationMode.PLAIN, session.Settings.Auth); + Assert.That(session.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); + Assert.That(session.Settings.Auth, Is.EqualTo(MySqlAuthenticationMode.PLAIN)); } // Should fail since PLAIN requires TLS to be enabled. @@ -660,29 +660,29 @@ public void ConnectUsingSha256PasswordPlugin() // User with password over TLS connection. using (var session = MySQLX.GetSession(connectionStringUri)) { - Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); + Assert.That(session.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); var result = ExecuteSQLStatement(session.SQL(string.Format("SELECT `User`, `plugin` FROM `mysql`.`user` WHERE `User` = '{0}';", userName))).FetchAll(); - Assert.AreEqual(userName, session.Settings.UserID); - Assert.AreEqual(session.Settings.UserID, result[0][0].ToString()); - Assert.AreEqual(pluginName, result[0][1].ToString()); + Assert.That(session.Settings.UserID, Is.EqualTo(userName)); + Assert.That(result[0][0].ToString(), Is.EqualTo(session.Settings.UserID)); + Assert.That(result[0][1].ToString(), Is.EqualTo(pluginName)); } // Connect over non-TLS connection. using (var session = MySQLX.GetSession(connectionStringUri + "?sslmode=none")) { - Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); - Assert.AreEqual(MySqlAuthenticationMode.SHA256_MEMORY, session.Settings.Auth); + Assert.That(session.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); + Assert.That(session.Settings.Auth, Is.EqualTo(MySqlAuthenticationMode.SHA256_MEMORY)); } // User without password over TLS connection. ExecuteSQL($"ALTER USER {userName}@'%' IDENTIFIED BY ''"); using (var session = MySQLX.GetSession(ConnectionStringUri.Replace("test:test", string.Format("{0}:{1}", userName, "")))) { - Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); + Assert.That(session.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); var result = ExecuteSQLStatement(session.SQL(string.Format("SELECT `User`, `plugin` FROM `mysql`.`user` WHERE `User` = '{0}';", userName))).FetchAll(); - Assert.AreEqual(userName, session.Settings.UserID); - Assert.AreEqual(session.Settings.UserID, result[0][0].ToString()); - Assert.AreEqual(pluginName, result[0][1].ToString()); + Assert.That(session.Settings.UserID, Is.EqualTo(userName)); + Assert.That(result[0][0].ToString(), Is.EqualTo(session.Settings.UserID)); + Assert.That(result[0][1].ToString(), Is.EqualTo(pluginName)); } } diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/XConnectionStringBuilderTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/XConnectionStringBuilderTests.cs index 2df0497af..78154a965 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/XConnectionStringBuilderTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/XConnectionStringBuilderTests.cs @@ -57,7 +57,7 @@ static XConnectionStringBuilderTests() public void SessionCanBeOpened() { using (var session = MySQLX.GetSession(_xConnectionURI)) - Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); + Assert.That(session.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); } [Test] @@ -66,16 +66,16 @@ public void ConnectionAfterSessionCanBeOpened() if (!Platform.IsWindows()) Assert.Ignore("Check for Linux OS"); using (var session = MySQLX.GetSession(_xConnectionURI)) - Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); + Assert.That(session.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); using (var connection = new MySqlConnection(_connectionStringWithSslMode)) { connection.Open(); - Assert.AreEqual(ConnectionState.Open, connection.State); + Assert.That(connection.State, Is.EqualTo(ConnectionState.Open)); } using (var session = MySQLX.GetSession(_xConnectionURI + "?sslca=client.pfx&certificatepassword=pass")) - Assert.AreEqual(SessionState.Open, session.InternalSession.SessionState); + Assert.That(session.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); } #if !NET452 @@ -87,7 +87,7 @@ public void ConnectionAfterSessionCanBeOpened() public void ValidateTlsVersionOptionAsString(string options, string result) { MySqlXConnectionStringBuilder builder = new MySqlXConnectionStringBuilder(_connectionString + options); - Assert.AreEqual(result, builder.TlsVersion); + Assert.That(builder.TlsVersion, Is.EqualTo(result)); } #if !NET452 @@ -101,7 +101,7 @@ public void ValidateTlsVersionOptionAsProperty(string options, string result) MySqlXConnectionStringBuilder builder = new MySqlXConnectionStringBuilder(_connectionString); builder.TlsVersion = options; - Assert.AreEqual(result, builder.TlsVersion); + Assert.That(builder.TlsVersion, Is.EqualTo(result)); } #if !NET452 @@ -122,7 +122,7 @@ public void ValidateTlsVersionOptionAndSslMode(MySqlSslMode? sslMode1, string op if (result != null) { builder.TlsVersion = options; - StringAssert.AreEqualIgnoringCase(result, builder.TlsVersion); + Assert.That(builder.TlsVersion, Is.EqualTo(result).IgnoreCase); } else Assert.Throws(() => { builder.TlsVersion = options; }); @@ -142,7 +142,7 @@ public void CaseInsensitiveAuthOption() for (int j = 0; j < values.GetLength(1); j++) { var builder = new MySqlXConnectionStringBuilder(String.Format("server=localhost;auth={0}", values[i, j])); - Assert.AreEqual((MySqlAuthenticationMode)(i + 1), builder.Auth); + Assert.That(builder.Auth, Is.EqualTo((MySqlAuthenticationMode)(i + 1))); } } } @@ -154,7 +154,7 @@ public void IncorrectAuthOptionThrowsArgumentException() foreach (var value in values) { Exception ex = Assert.Throws(() => new MySqlXConnectionStringBuilder(String.Format("server=localhost;aUth={0}", value))); - Assert.AreEqual(String.Format("Value '{0}' is not of the correct type.", value), ex.Message); + Assert.That(ex.Message, Is.EqualTo(String.Format("Value '{0}' is not of the correct type.", value))); } } @@ -171,21 +171,21 @@ public void TryGetValue() CompressionAlgorithm = "deflate, lz4", }; - Assert.IsTrue(connStringBuilder.ContainsKey("dnssrv")); - Assert.IsTrue(connStringBuilder.TryGetValue("dns-srv", out var dnssrv)); - Assert.AreEqual(connStringBuilder.DnsSrv, (bool)dnssrv); + Assert.That(connStringBuilder.ContainsKey("dnssrv")); + Assert.That(connStringBuilder.TryGetValue("dns-srv", out var dnssrv)); + Assert.That((bool)dnssrv, Is.EqualTo(connStringBuilder.DnsSrv)); - Assert.IsTrue(connStringBuilder.ContainsKey("compressionAlgorithms")); - Assert.IsTrue(connStringBuilder.TryGetValue("Compression-Algorithms", out var compressionAlgorithm)); - StringAssert.AreEqualIgnoringCase(connStringBuilder.CompressionAlgorithm, (string)compressionAlgorithm); + Assert.That(connStringBuilder.ContainsKey("compressionAlgorithms")); + Assert.That(connStringBuilder.TryGetValue("Compression-Algorithms", out var compressionAlgorithm)); + Assert.That((string)compressionAlgorithm, Is.EqualTo(connStringBuilder.CompressionAlgorithm).IgnoreCase); // Default value - Assert.IsTrue(connStringBuilder.TryGetValue("connection-attributes", out var connectionattributes)); - Assert.AreEqual(connStringBuilder.GetOption("connection-attributes").DefaultValue, connectionattributes); + Assert.That(connStringBuilder.TryGetValue("connection-attributes", out var connectionattributes)); + Assert.That(connectionattributes, Is.EqualTo(connStringBuilder.GetOption("connection-attributes").DefaultValue)); // Non existing option - Assert.IsFalse(connStringBuilder.TryGetValue("foo", out var nonexistingoption)); - Assert.IsNull(nonexistingoption); + Assert.That(connStringBuilder.TryGetValue("foo", out var nonexistingoption), Is.False); + Assert.That(nonexistingoption, Is.Null); } } } diff --git a/MySql.Web/tests/GlobalUsings.cs b/MySql.Web/tests/GlobalUsings.cs deleted file mode 100644 index 575c7cfd0..000000000 --- a/MySql.Web/tests/GlobalUsings.cs +++ /dev/null @@ -1,5 +0,0 @@ -global using Assert = NUnit.Framework.Legacy.ClassicAssert; -global using CollectionAssert = NUnit.Framework.Legacy.CollectionAssert; -global using StringAssert = NUnit.Framework.Legacy.StringAssert; -global using DirectoryAssert = NUnit.Framework.Legacy.DirectoryAssert; -global using FileAssert = NUnit.Framework.Legacy.FileAssert; diff --git a/MySql.Web/tests/PersonalizationTests.cs b/MySql.Web/tests/PersonalizationTests.cs index 23ef47655..d90553ce9 100644 --- a/MySql.Web/tests/PersonalizationTests.cs +++ b/MySql.Web/tests/PersonalizationTests.cs @@ -144,7 +144,7 @@ public void CanFindState() psq.PathToMatch = "~/default.aspx"; psq.UserInactiveSinceDate = DateTime.UtcNow.AddMinutes(1); var collection = p.FindState(PersonalizationScope.User, psq, 1, 1, out totalRecords); - Assert.AreEqual(1, totalRecords); + Assert.That(totalRecords, Is.EqualTo(1)); } [Test] @@ -159,7 +159,7 @@ public void CanGetCountofStateForUser() psq.UserInactiveSinceDate = DateTime.UtcNow.AddMinutes(1); //System.Threading.Thread.Sleep(1000); totalRecords = p.GetCountOfState(PersonalizationScope.User, psq); - Assert.AreEqual(1, totalRecords); + Assert.That(totalRecords, Is.EqualTo(1)); } [Test] @@ -172,7 +172,7 @@ public void CanGetCountofStateForAllUsers() psq.PathToMatch = "~/default.aspx"; psq.UserInactiveSinceDate = DateTime.UtcNow; totalRecords = p.GetCountOfState(PersonalizationScope.Shared, psq); - Assert.AreEqual(1, totalRecords); + Assert.That(totalRecords, Is.EqualTo(1)); } [Test] @@ -188,7 +188,7 @@ public void CanResetStateForUser() users[0] = @"GabPC\Gab"; totalRecords = p.ResetState(PersonalizationScope.User, paths, users); - Assert.AreEqual(1, totalRecords); + Assert.That(totalRecords, Is.EqualTo(1)); } [Test] @@ -205,7 +205,7 @@ public void CanResetStateForAllUsers() int totalRecords; totalRecords = p.ResetState(PersonalizationScope.Shared, paths, users); - Assert.AreEqual(1, totalRecords); + Assert.That(totalRecords, Is.EqualTo(1)); } [Test] @@ -216,7 +216,7 @@ public void CanResetAllState() int totalRecords; totalRecords = p.ResetState(PersonalizationScope.Shared, null, null); - Assert.AreEqual(1, totalRecords); + Assert.That(totalRecords, Is.EqualTo(1)); } @@ -228,7 +228,7 @@ public void CanResetUsertState() int totalRecords; totalRecords = p.ResetUserState("~/default.aspx", Convert.ToDateTime("2038-01-19 03:14:07.999999")); // TimeStamp MaxValue - Assert.AreEqual(1, totalRecords); + Assert.That(totalRecords, Is.EqualTo(1)); } } diff --git a/MySql.Web/tests/ProfileTests.cs b/MySql.Web/tests/ProfileTests.cs index f1ac081ba..2de577133 100644 --- a/MySql.Web/tests/ProfileTests.cs +++ b/MySql.Web/tests/ProfileTests.cs @@ -79,26 +79,26 @@ public void SettingValuesCreatesAnAppAndUserId() provider.SetPropertyValues(ctx, values); DataTable dt = FillTable("SELECT * FROM my_aspnet_applications"); - Assert.True(1 == dt.Rows.Count, "Rows count on table my_aspnet_applications is not 1"); + Assert.That(1 == dt.Rows.Count, "Rows count on table my_aspnet_applications is not 1"); dt = FillTable("SELECT * FROM my_aspnet_users"); - Assert.True(1 == dt.Rows.Count, "Rows count on table my_aspnet_users is not 1"); + Assert.That(1 == dt.Rows.Count, "Rows count on table my_aspnet_users is not 1"); dt = FillTable("SELECT * FROM my_aspnet_profiles"); - Assert.True(1 == dt.Rows.Count, "Rows count on table my_aspnet_profiles is not 1"); + Assert.That(1 == dt.Rows.Count, "Rows count on table my_aspnet_profiles is not 1"); values["color"].PropertyValue = "green"; provider.SetPropertyValues(ctx, values); dt = FillTable("SELECT * FROM my_aspnet_applications"); - Assert.True(1 == dt.Rows.Count, "Rows count on table my_aspnet_applications is not 1 after setting property"); + Assert.That(1 == dt.Rows.Count, "Rows count on table my_aspnet_applications is not 1 after setting property"); dt = FillTable("SELECT * FROM my_aspnet_users"); - Assert.True(1 == dt.Rows.Count, "Rows count on table my_aspnet_users is not 1 after setting property"); + Assert.That(1 == dt.Rows.Count, "Rows count on table my_aspnet_users is not 1 after setting property"); dt = FillTable("SELECT * FROM my_aspnet_profiles"); - Assert.True(1 == dt.Rows.Count, "Rows count on table my_aspnet_profiles is not 1 after setting property"); + Assert.That(1 == dt.Rows.Count, "Rows count on table my_aspnet_profiles is not 1 after setting property"); } [Test] @@ -120,13 +120,13 @@ public void AnonymousUserSettingNonAnonymousProperties() provider.SetPropertyValues(ctx, values); DataTable dt = FillTable("SELECT * FROM my_aspnet_applications"); - Assert.True(0 == dt.Rows.Count, "Table my_aspnet_applications Rows is not 0"); + Assert.That(0 == dt.Rows.Count, "Table my_aspnet_applications Rows is not 0"); dt = FillTable("SELECT * FROM my_aspnet_users"); - Assert.True(0 == dt.Rows.Count, "Table my_aspnet_users Rows is not 0"); + Assert.That(0 == dt.Rows.Count, "Table my_aspnet_users Rows is not 0"); dt = FillTable("SELECT * FROM my_aspnet_profiles"); - Assert.True(0 == dt.Rows.Count, "Table my_aspnet_profiles Rows is not 0"); + Assert.That(0 == dt.Rows.Count, "Table my_aspnet_profiles Rows is not 0"); } @@ -143,11 +143,11 @@ public void StringCollectionAsProperty() profile.Save(); DataTable dt = FillTable("SELECT * FROM my_aspnet_applications"); - Assert.AreEqual(1, dt.Rows.Count); + Assert.That(dt.Rows.Count, Is.EqualTo(1)); dt = FillTable("SELECT * FROM my_aspnet_users"); - Assert.AreEqual(1, dt.Rows.Count); + Assert.That(dt.Rows.Count, Is.EqualTo(1)); dt = FillTable("SELECT * FROM my_aspnet_profiles"); - Assert.AreEqual(1, dt.Rows.Count); + Assert.That(dt.Rows.Count, Is.EqualTo(1)); // now retrieve them SettingsPropertyCollection getProps = new SettingsPropertyCollection(); @@ -161,13 +161,13 @@ public void StringCollectionAsProperty() ctx.Add("IsAuthenticated", true); ctx.Add("UserName", "foo"); SettingsPropertyValueCollection getValues = provider.GetPropertyValues(ctx, getProps); - Assert.AreEqual(1, getValues.Count); + Assert.That(getValues.Count, Is.EqualTo(1)); SettingsPropertyValue getValue1 = getValues["FavoriteColors"]; StringCollection outValue = (StringCollection)getValue1.PropertyValue; - Assert.AreEqual(3, outValue.Count); - Assert.AreEqual("red", outValue[0]); - Assert.AreEqual("green", outValue[1]); - Assert.AreEqual("blue", outValue[2]); + Assert.That(outValue.Count, Is.EqualTo(3)); + Assert.That(outValue[0], Is.EqualTo("red")); + Assert.That(outValue[1], Is.EqualTo("green")); + Assert.That(outValue[2], Is.EqualTo("blue")); } [Test] @@ -191,9 +191,9 @@ public void AuthenticatedDateTime() ctx.Add("UserName", "foo"); SettingsPropertyValueCollection getValues = provider.GetPropertyValues(ctx, getProps); - Assert.AreEqual(1, getValues.Count); + Assert.That(getValues.Count, Is.EqualTo(1)); SettingsPropertyValue getValue1 = getValues["BirthDate"]; - Assert.AreEqual(date, getValue1.PropertyValue); + Assert.That(getValue1.PropertyValue, Is.EqualTo(date)); } /// @@ -235,9 +235,9 @@ public void AuthenticatedStringProperty() ctx.Add("UserName", "foo"); SettingsPropertyValueCollection getValues = provider.GetPropertyValues(ctx, getProps); - Assert.AreEqual(1, getValues.Count); + Assert.That(getValues.Count, Is.EqualTo(1)); SettingsPropertyValue getValue1 = getValues["Name"]; - Assert.AreEqual("Fred Flintstone", getValue1.PropertyValue); + Assert.That(getValue1.PropertyValue, Is.EqualTo("Fred Flintstone")); } /// @@ -264,7 +264,7 @@ public void GetAllProfiles() int total; ProfileInfoCollection profiles = provider.GetAllProfiles( ProfileAuthenticationOption.All, 0, 10, out total); - Assert.AreEqual(1, total); + Assert.That(total, Is.EqualTo(1)); } /// @@ -277,11 +277,11 @@ public void DeleteProfiles() profile.SetPropertyValue("Name", "this is my name"); profile.Save(); profile = ProfileBase.Create("foo", true); // refresh profile from database - Assert.AreEqual("this is my name", profile.GetPropertyValue("Name")); + Assert.That(profile.GetPropertyValue("Name"), Is.EqualTo("this is my name")); - Assert.AreEqual(1, ProfileManager.DeleteProfiles(new string[] { "foo" })); + Assert.That(ProfileManager.DeleteProfiles(new string[] { "foo" }), Is.EqualTo(1)); profile = ProfileBase.Create("foo", true); // refresh profile from database - Assert.AreEqual(string.Empty, profile.GetPropertyValue("Name")); + Assert.That(profile.GetPropertyValue("Name"), Is.Empty); } } diff --git a/MySql.Web/tests/RoleManagement.cs b/MySql.Web/tests/RoleManagement.cs index 764b43da1..225919241 100644 --- a/MySql.Web/tests/RoleManagement.cs +++ b/MySql.Web/tests/RoleManagement.cs @@ -57,7 +57,7 @@ private void AddUser(string username, string password) MembershipCreateStatus status; membershipProvider.CreateUser(username, password, "foo@bar.com", null, null, true, null, out status); - Assert.False(status != MembershipCreateStatus.Success, "User creation failed"); + Assert.That(status == MembershipCreateStatus.Success, "User creation failed"); } private void AttemptToAddUserToRole(string username, string role) @@ -79,8 +79,8 @@ public void CreateAndDeleteRoles() // Add the role roleProvider.CreateRole("Administrator"); string[] roles = roleProvider.GetAllRoles(); - Assert.AreEqual(1, roles.Length); - Assert.AreEqual("Administrator", roles[0]); + Assert.That(roles.Length, Is.EqualTo(1)); + Assert.That(roles[0], Is.EqualTo("Administrator")); roleProvider.DeleteRole("Administrator", false); } @@ -92,13 +92,13 @@ public void AddUserToRole() roleProvider.AddUsersToRoles(new string[] { "eve" }, new string[] { "Administrator" }); - Assert.True(roleProvider.IsUserInRole("eve", "Administrator")); + Assert.That(roleProvider.IsUserInRole("eve", "Administrator")); roleProvider.RemoveUsersFromRoles(new string[] { "eve" }, new string[] { "Administrator" }); - Assert.False(roleProvider.IsUserInRole("eve", "Administrator")); + Assert.That(!roleProvider.IsUserInRole("eve", "Administrator")); roleProvider.DeleteRole("Administrator", false); - Assert.AreEqual(0, roleProvider.GetAllRoles().Length); + Assert.That(roleProvider.GetAllRoles().Length, Is.EqualTo(0)); //clean up membershipProvider.DeleteUser("eve", true); @@ -114,7 +114,7 @@ public void AddNonExistingUserToRole() roleProvider.CreateRole("Administrator"); roleProvider.AddUsersToRoles(new string[] { "eve" }, new string[] { "Administrator" }); - Assert.True(roleProvider.IsUserInRole("eve", "Administrator")); + Assert.That(roleProvider.IsUserInRole("eve", "Administrator")); //Cleanup roleProvider.RemoveUsersFromRoles(new string[] { "eve" }, new string[] { "Administrator" }); @@ -144,10 +144,10 @@ public void AddUserToRoleWithRoleClass() MembershipCreateStatus status; membershipProvider.CreateUser("eve", "eve1@eve", "eve@boo.com", "question", "answer", true, null, out status); - Assert.AreEqual(MembershipCreateStatus.Success, status); + Assert.That(status, Is.EqualTo(MembershipCreateStatus.Success)); roleProvider.AddUsersToRoles(new string[] { "eve" }, new string[] { "Administrator" }); - Assert.True(roleProvider.IsUserInRole("eve", "Administrator")); + Assert.That(roleProvider.IsUserInRole("eve", "Administrator")); //Cleanup membershipProvider.DeleteUser("eve", true); @@ -191,10 +191,10 @@ public void IsUserInRoleCrossDomain() roleProvider.CreateRole("Administrator"); roleProvider.AddUsersToRoles(new string[] { "foo" }, new string[] { "Administrator" }); - Assert.False(r2.IsUserInRole("foo", "Administrator")); + Assert.That(!r2.IsUserInRole("foo", "Administrator")); roleProvider.DeleteRole("Administrator", false); - Assert.AreEqual(0, roleProvider.GetAllRoles().Length); + Assert.That(roleProvider.GetAllRoles().Length, Is.EqualTo(0)); //Cleanup provider.DeleteUser("foo", true); @@ -218,12 +218,12 @@ public void TestUserRemoveFindFromRole() roleProvider.CreateRole("Administrator"); roleProvider.AddUsersToRoles(new string[] { "eve" }, new string[] { "Administrator" }); - Assert.True(roleProvider.IsUserInRole("eve", "Administrator")); + Assert.That(roleProvider.IsUserInRole("eve", "Administrator")); string[] users = roleProvider.FindUsersInRole("Administrator", "eve"); - Assert.AreEqual(1, users.Length); - Assert.AreEqual("eve", users[0]); + Assert.That(users.Length, Is.EqualTo(1)); + Assert.That(users[0], Is.EqualTo("eve")); roleProvider.RemoveUsersFromRoles(new string[] { "eve" }, new string[] { "Administrator" }); - Assert.False(roleProvider.IsUserInRole("eve", "Administrator")); + Assert.That(!roleProvider.IsUserInRole("eve", "Administrator")); //Cleanup membershipProvider.DeleteUser("eve", true); diff --git a/MySql.Web/tests/SchemaManagerTests.cs b/MySql.Web/tests/SchemaManagerTests.cs index a8304eb16..86dd3790d 100644 --- a/MySql.Web/tests/SchemaManagerTests.cs +++ b/MySql.Web/tests/SchemaManagerTests.cs @@ -76,12 +76,12 @@ public void SchemaCheck() { provider.Initialize(null, config); if (i < SchemaManager.Version) - Assert.False(false, "Should have failed"); + Assert.That(false, Is.False, "Should have failed"); } catch (ProviderException) { if (i == SchemaManager.Version) - Assert.False(false, "This should not have failed"); + Assert.That(false, Is.False, "This should not have failed"); } } } @@ -98,14 +98,14 @@ public void CurrentSchema() MySqlCommand cmd = new MySqlCommand("SELECT * FROM my_aspnet_schemaversion", Connection); object ver = cmd.ExecuteScalar(); - Assert.AreEqual(4, ver); + Assert.That(ver, Is.EqualTo(4)); cmd.CommandText = "SHOW CREATE TABLE my_aspnet_membership"; using (MySqlDataReader reader = cmd.ExecuteReader()) { reader.Read(); string createSql = reader.GetString(1); - Assert.True(createSql.IndexOf("CHARSET=utf8") != -1); + Assert.That(createSql.IndexOf("CHARSET=utf8") != -1); } } @@ -142,7 +142,7 @@ Password varchar(128) NOT NULL, reader.Read(); string createTable = reader.GetString(1); int index = createTable.IndexOf("COMMENT='1'"); - Assert.AreNotEqual(-1, index); + Assert.That(index, Is.Not.EqualTo(-1)); } execSQL(@" ALTER TABLE mysql_Membership @@ -153,7 +153,7 @@ Password varchar(128) NOT NULL, reader.Read(); string createTable = reader.GetString(1); int index = createTable.IndexOf("COMMENT='2'"); - Assert.AreNotEqual(-1, index); + Assert.That(index, Is.Not.EqualTo(-1)); } } @@ -178,84 +178,84 @@ private void LoadData() execSQL(@"INSERT INTO mysql_UsersInRoles VALUES ('user1', 'role1', 'app2')"); execSQL(@"INSERT INTO mysql_UsersInRoles VALUES ('user2', 'role2', 'app2')"); LoadSchema(3); - Assert.False(TableExists("mysql_membership")); - Assert.False(TableExists("mysql_roles")); - Assert.False(TableExists("mysql_usersinroles")); + Assert.That(!TableExists("mysql_membership")); + Assert.That(!TableExists("mysql_roles")); + Assert.That(!TableExists("mysql_usersinroles")); } [Test] public void CheckAppsUpgrade() { DataTable apps = FillTable("SELECT * FROM my_aspnet_applications"); - Assert.AreEqual(2, apps.Rows.Count); - Assert.AreEqual(1, apps.Rows[0]["id"]); - Assert.AreEqual("app1", apps.Rows[0]["name"]); - Assert.AreEqual(2, apps.Rows[1]["id"]); - Assert.AreEqual("app2", apps.Rows[1]["name"]); + Assert.That(apps.Rows.Count, Is.EqualTo(2)); + Assert.That(apps.Rows[0]["id"], Is.EqualTo(1)); + Assert.That(apps.Rows[0]["name"], Is.EqualTo("app1")); + Assert.That(apps.Rows[1]["id"], Is.EqualTo(2)); + Assert.That(apps.Rows[1]["name"], Is.EqualTo("app2")); } [Test] public void CheckUsersUpgrade() { DataTable dt = FillTable("SELECT * FROM my_aspnet_users"); - Assert.AreEqual(4, dt.Rows.Count); - Assert.AreEqual(1, dt.Rows[0]["id"]); - Assert.AreEqual(1, dt.Rows[0]["applicationId"]); - Assert.AreEqual("user1", dt.Rows[0]["name"]); - Assert.AreEqual(2, dt.Rows[1]["id"]); - Assert.AreEqual(1, dt.Rows[1]["applicationId"]); - Assert.AreEqual("user2", dt.Rows[1]["name"]); - Assert.AreEqual(3, dt.Rows[2]["id"]); - Assert.AreEqual(2, dt.Rows[2]["applicationId"]); - Assert.AreEqual("user1", dt.Rows[2]["name"]); - Assert.AreEqual(4, dt.Rows[3]["id"]); - Assert.AreEqual(2, dt.Rows[3]["applicationId"]); - Assert.AreEqual("user2", dt.Rows[3]["name"]); + Assert.That(dt.Rows.Count, Is.EqualTo(4)); + Assert.That(dt.Rows[0]["id"], Is.EqualTo(1)); + Assert.That(dt.Rows[0]["applicationId"], Is.EqualTo(1)); + Assert.That(dt.Rows[0]["name"], Is.EqualTo("user1")); + Assert.That(dt.Rows[1]["id"], Is.EqualTo(2)); + Assert.That(dt.Rows[1]["applicationId"], Is.EqualTo(1)); + Assert.That(dt.Rows[1]["name"], Is.EqualTo("user2")); + Assert.That(dt.Rows[2]["id"], Is.EqualTo(3)); + Assert.That(dt.Rows[2]["applicationId"], Is.EqualTo(2)); + Assert.That(dt.Rows[2]["name"], Is.EqualTo("user1")); + Assert.That(dt.Rows[3]["id"], Is.EqualTo(4)); + Assert.That(dt.Rows[3]["applicationId"], Is.EqualTo(2)); + Assert.That(dt.Rows[3]["name"], Is.EqualTo("user2")); } [Test] public void CheckRolesUpgrade() { DataTable dt = FillTable("SELECT * FROM my_aspnet_roles"); - Assert.AreEqual(4, dt.Rows.Count); - Assert.AreEqual(1, dt.Rows[0]["id"]); - Assert.AreEqual(1, dt.Rows[0]["applicationId"]); - Assert.AreEqual("role1", dt.Rows[0]["name"]); - Assert.AreEqual(2, dt.Rows[1]["id"]); - Assert.AreEqual(1, dt.Rows[1]["applicationId"]); - Assert.AreEqual("role2", dt.Rows[1]["name"]); - Assert.AreEqual(3, dt.Rows[2]["id"]); - Assert.AreEqual(2, dt.Rows[2]["applicationId"]); - Assert.AreEqual("role1", dt.Rows[2]["name"]); - Assert.AreEqual(4, dt.Rows[3]["id"]); - Assert.AreEqual(2, dt.Rows[3]["applicationId"]); - Assert.AreEqual("role2", dt.Rows[3]["name"]); + Assert.That(dt.Rows.Count, Is.EqualTo(4)); + Assert.That(dt.Rows[0]["id"], Is.EqualTo(1)); + Assert.That(dt.Rows[0]["applicationId"], Is.EqualTo(1)); + Assert.That(dt.Rows[0]["name"], Is.EqualTo("role1")); + Assert.That(dt.Rows[1]["id"], Is.EqualTo(2)); + Assert.That(dt.Rows[1]["applicationId"], Is.EqualTo(1)); + Assert.That(dt.Rows[1]["name"], Is.EqualTo("role2")); + Assert.That(dt.Rows[2]["id"], Is.EqualTo(3)); + Assert.That(dt.Rows[2]["applicationId"], Is.EqualTo(2)); + Assert.That(dt.Rows[2]["name"], Is.EqualTo("role1")); + Assert.That(dt.Rows[3]["id"], Is.EqualTo(4)); + Assert.That(dt.Rows[3]["applicationId"], Is.EqualTo(2)); + Assert.That(dt.Rows[3]["name"], Is.EqualTo("role2")); } [Test] public void CheckMembershipUpgrade() { DataTable dt = FillTable("SELECT * FROM my_aspnet_membership"); - Assert.AreEqual(4, dt.Rows.Count); - Assert.AreEqual(1, dt.Rows[0]["userid"]); - Assert.AreEqual(2, dt.Rows[1]["userid"]); - Assert.AreEqual(3, dt.Rows[2]["userid"]); - Assert.AreEqual(4, dt.Rows[3]["userid"]); + Assert.That(dt.Rows.Count, Is.EqualTo(4)); + Assert.That(dt.Rows[0]["userid"], Is.EqualTo(1)); + Assert.That(dt.Rows[1]["userid"], Is.EqualTo(2)); + Assert.That(dt.Rows[2]["userid"], Is.EqualTo(3)); + Assert.That(dt.Rows[3]["userid"], Is.EqualTo(4)); } [Test] public void CheckUsersInRolesUpgrade() { DataTable dt = FillTable("SELECT * FROM my_aspnet_usersinroles"); - Assert.AreEqual(4, dt.Rows.Count); - Assert.AreEqual(1, dt.Rows[0]["userid"]); - Assert.AreEqual(1, dt.Rows[0]["roleid"]); - Assert.AreEqual(2, dt.Rows[1]["userid"]); - Assert.AreEqual(2, dt.Rows[1]["roleid"]); - Assert.AreEqual(3, dt.Rows[2]["userid"]); - Assert.AreEqual(3, dt.Rows[2]["roleid"]); - Assert.AreEqual(4, dt.Rows[3]["userid"]); - Assert.AreEqual(4, dt.Rows[3]["roleid"]); + Assert.That(dt.Rows.Count, Is.EqualTo(4)); + Assert.That(dt.Rows[0]["userid"], Is.EqualTo(1)); + Assert.That(dt.Rows[0]["roleid"], Is.EqualTo(1)); + Assert.That(dt.Rows[1]["userid"], Is.EqualTo(2)); + Assert.That(dt.Rows[1]["roleid"], Is.EqualTo(2)); + Assert.That(dt.Rows[2]["userid"], Is.EqualTo(3)); + Assert.That(dt.Rows[2]["roleid"], Is.EqualTo(3)); + Assert.That(dt.Rows[3]["userid"], Is.EqualTo(4)); + Assert.That(dt.Rows[3]["roleid"], Is.EqualTo(4)); } /// @@ -300,7 +300,7 @@ public void SchemaTablesUseSameEngine() lastEngine = currentEngine; } - Assert.AreEqual(lastEngine, currentEngine); + Assert.That(currentEngine, Is.EqualTo(lastEngine)); } } } @@ -314,7 +314,7 @@ public void InitializeInvalidConnStringThrowsArgumentException() config.Add("connectionString", badConnectionString); Exception ex = Assert.Throws(() => provider.Initialize(null, config)); - Assert.AreEqual("Option not supported.\r\nParameter name: fookey", ex.Message); + Assert.That(ex.Message, Is.EqualTo("Option not supported.\r\nParameter name: fookey")); } } } diff --git a/MySql.Web/tests/SchemaTests.cs b/MySql.Web/tests/SchemaTests.cs index 71f8bf050..f1217ae8f 100644 --- a/MySql.Web/tests/SchemaTests.cs +++ b/MySql.Web/tests/SchemaTests.cs @@ -73,12 +73,12 @@ public void SchemaCheck() { provider.Initialize(null, config); if (i < SchemaManager.Version) - Assert.False(false, "Should have failed"); + Assert.That(false, Is.False, "Should have failed"); } catch (ProviderException) { if (i == SchemaManager.Version) - Assert.False(false, "This should not have failed"); + Assert.That(false, Is.False, "This should not have failed"); } } } @@ -95,14 +95,14 @@ public void CurrentSchema() MySqlCommand cmd = new MySqlCommand("SELECT * FROM my_aspnet_schemaversion", Connection); object ver = cmd.ExecuteScalar(); - Assert.AreEqual(4, ver); + Assert.That(ver, Is.EqualTo(4)); cmd.CommandText = "SHOW CREATE TABLE my_aspnet_membership"; using (MySqlDataReader reader = cmd.ExecuteReader()) { reader.Read(); string createSql = reader.GetString(1); - Assert.True(createSql.IndexOf("CHARSET=utf8") != -1); + Assert.That(createSql.IndexOf("CHARSET=utf8") != -1); } } @@ -139,7 +139,7 @@ Password varchar(128) NOT NULL, reader.Read(); string createTable = reader.GetString(1); int index = createTable.IndexOf("COMMENT='1'"); - Assert.AreNotEqual(-1, index); + Assert.That(index, Is.Not.EqualTo(-1)); } execSQL(@" ALTER TABLE mysql_Membership @@ -150,7 +150,7 @@ Password varchar(128) NOT NULL, reader.Read(); string createTable = reader.GetString(1); int index = createTable.IndexOf("COMMENT='2'"); - Assert.AreNotEqual(-1, index); + Assert.That(index, Is.Not.EqualTo(-1)); } } @@ -175,20 +175,20 @@ private void LoadData() execSQL(@"INSERT INTO mysql_UsersInRoles VALUES ('user1', 'role1', 'app2')"); execSQL(@"INSERT INTO mysql_UsersInRoles VALUES ('user2', 'role2', 'app2')"); LoadSchema(3); - Assert.False(TableExists("mysql_membership")); - Assert.False(TableExists("mysql_roles")); - Assert.False(TableExists("mysql_usersinroles")); + Assert.That(!TableExists("mysql_membership")); + Assert.That(!TableExists("mysql_roles")); + Assert.That(!TableExists("mysql_usersinroles")); } [Test] public void CheckAppsUpgrade() { DataTable apps = FillTable("SELECT * FROM my_aspnet_applications"); - Assert.AreEqual(2, apps.Rows.Count); - Assert.AreEqual(1, apps.Rows[0]["id"]); - Assert.AreEqual("app1", apps.Rows[0]["name"]); - Assert.AreEqual(2, apps.Rows[1]["id"]); - Assert.AreEqual("app2", apps.Rows[1]["name"]); + Assert.That(apps.Rows.Count, Is.EqualTo(2)); + Assert.That(apps.Rows[0]["id"], Is.EqualTo(1)); + Assert.That(apps.Rows[0]["name"], Is.EqualTo("app1")); + Assert.That(apps.Rows[1]["id"], Is.EqualTo(2)); + Assert.That(apps.Rows[1]["name"], Is.EqualTo("app2")); } //[Test] diff --git a/MySql.Web/tests/SessionTests.cs b/MySql.Web/tests/SessionTests.cs index 51418899c..8ee91b96b 100644 --- a/MySql.Web/tests/SessionTests.cs +++ b/MySql.Web/tests/SessionTests.cs @@ -147,7 +147,7 @@ public void SessionItemWithExpireCallback() SetSessionItemExpiredCallback(true); _evt.WaitOne(); - Assert.AreEqual(strSessionID, calledId); + Assert.That(calledId, Is.EqualTo(strSessionID)); int i = 0; while (((long)CountSessions() != 0) && (i < 10)) @@ -156,7 +156,7 @@ public void SessionItemWithExpireCallback() i++; } - Assert.AreEqual(0, CountSessions()); + Assert.That(CountSessions(), Is.EqualTo(0)); } @@ -166,7 +166,7 @@ public void SessionItemWithoutExpireCallback() execSQL(@"delete from my_aspnet_sessions; delete from my_aspnet_sessioncleanup;"); SetSessionItemExpiredCallback(false); - Assert.AreNotEqual(strSessionID, calledId); + Assert.That(calledId, Is.Not.EqualTo(strSessionID)); int i = 0; while (((long)MySqlHelper.ExecuteScalar(Connection, "SELECT Count(*) FROM my_aspnet_sessions;") != 0) && (i < 10)) @@ -175,7 +175,7 @@ public void SessionItemWithoutExpireCallback() i++; } - Assert.AreEqual(0, CountSessions()); + Assert.That(CountSessions(), Is.EqualTo(0)); } [Test] @@ -202,7 +202,7 @@ public void DeleteSessionAppSpecific() } session.Dispose(); - Assert.AreEqual(1, CountSessions()); + Assert.That(CountSessions(), Is.EqualTo(1)); session.Dispose(); } @@ -340,7 +340,7 @@ public void SessionLocking() // OK if wait is less than session timeout Debug.WriteLine(string.Empty); Debug.WriteLine(totalMillisecs); - Assert.True(totalMillisecs < 30000); + Assert.That(totalMillisecs < 30000); } finally { diff --git a/MySql.Web/tests/SimpleMembership.cs b/MySql.Web/tests/SimpleMembership.cs index d76ba9cfe..cb13ccc79 100644 --- a/MySql.Web/tests/SimpleMembership.cs +++ b/MySql.Web/tests/SimpleMembership.cs @@ -74,7 +74,7 @@ public void Cleanup() public void CheckIfRoleNotExists() { var roleExists = _simpleRoleProvider.RoleExists("roleName"); - Assert.False(roleExists); + Assert.That(!roleExists); } [Test] @@ -84,7 +84,7 @@ public void CheckIfRoleExists() { _simpleRoleProvider.CreateRole("Administrator"); var roleExists = _simpleRoleProvider.RoleExists("Administrator"); - Assert.True(roleExists); + Assert.That(roleExists); } } @@ -92,12 +92,12 @@ public void CheckIfRoleExists() public void CreateUserAndAccountTest() { MySqlWebSecurity.CreateUserAndAccount(_userName, _pass); - Assert.True(MySqlWebSecurity.UserExists(_userName)); + Assert.That(MySqlWebSecurity.UserExists(_userName)); var user = MySqlHelper.ExecuteDataRow(ConnectionString, string.Format("select * from {0} where {1} = '{2}'", _userTable, _userNameColumn, _userName)); - Assert.IsNotNull(user); - Assert.AreEqual(_userName, user[_userNameColumn]); + Assert.That(user, Is.Not.Null); + Assert.That(user[_userNameColumn], Is.EqualTo(_userName)); - Assert.True(_simpleProvider.ValidateUser(_userName, _pass)); + Assert.That(_simpleProvider.ValidateUser(_userName, _pass)); //We need to mock the login because in that method there is a call to "FormsAuthentication.SetAuthCookie" which causes an "Object reference not set to an instance of an object" exception, because the test doesn't run on web application context //Assert.True(MySqlWebSecurity.Login(_userName, _pass)); } @@ -108,16 +108,16 @@ public void ChangePasswordTest() { string newPass = "newpassword"; MySqlWebSecurity.CreateUserAndAccount(_userName, _pass); - Assert.True(MySqlWebSecurity.UserExists(_userName)); + Assert.That(MySqlWebSecurity.UserExists(_userName)); //We need to mock the login because in that method there is a call to "FormsAuthentication.SetAuthCookie" which causes an "Object reference not set to an instance of an object" exception, because the test doesn't run on web application context - Assert.True(_simpleProvider.ValidateUser(_userName, _pass)); + Assert.That(_simpleProvider.ValidateUser(_userName, _pass)); //Assert.True(MySqlWebSecurity.Login(_userName, _pass)); - Assert.True(MySqlWebSecurity.ChangePassword(_userName, _pass, newPass)); + Assert.That(MySqlWebSecurity.ChangePassword(_userName, _pass, newPass)); - Assert.True(_simpleProvider.ValidateUser(_userName, newPass)); + Assert.That(_simpleProvider.ValidateUser(_userName, newPass)); //Assert.True(MySqlWebSecurity.Login(_userName, newPass)); } @@ -125,16 +125,16 @@ public void ChangePasswordTest() public void ConfirmAccountWithTokenTest() { var token = MySqlWebSecurity.CreateUserAndAccount(_userName, _pass, null, true); - Assert.True(MySqlWebSecurity.UserExists(_userName)); - Assert.True(MySqlWebSecurity.ConfirmAccount(token)); + Assert.That(MySqlWebSecurity.UserExists(_userName)); + Assert.That(MySqlWebSecurity.ConfirmAccount(token)); } [Test] public void ConfirmAccountWithUserAndTokenTest() { var token = MySqlWebSecurity.CreateUserAndAccount(_userName, _pass, null, true); - Assert.True(MySqlWebSecurity.UserExists(_userName)); - Assert.True(MySqlWebSecurity.ConfirmAccount(_userName, token)); + Assert.That(MySqlWebSecurity.UserExists(_userName)); + Assert.That(MySqlWebSecurity.ConfirmAccount(_userName, token)); } [Test] @@ -142,8 +142,8 @@ public void ConfirmAccountWithoutTokenTest() { var token = "falsetoken"; MySqlWebSecurity.CreateUserAndAccount(_userName, _pass); - Assert.True(MySqlWebSecurity.UserExists(_userName)); - Assert.False(MySqlWebSecurity.ConfirmAccount(token)); + Assert.That(MySqlWebSecurity.UserExists(_userName)); + Assert.That(!MySqlWebSecurity.ConfirmAccount(token)); } [Test] @@ -152,39 +152,39 @@ public void CreatedDateTest() execSQL(@"delete from userprofile; delete from webpages_membership;"); MySqlWebSecurity.CreateUserAndAccount(_userName, _pass); - Assert.AreNotEqual(DateTime.MinValue, MySqlWebSecurity.GetCreateDate(_userName)); + Assert.That(MySqlWebSecurity.GetCreateDate(_userName), Is.Not.EqualTo(DateTime.MinValue)); } [Test] public void DeleteTest() { _simpleProvider.CreateUserAndAccount(_userName, _pass, false, null); - Assert.True(_simpleProvider.DeleteAccount(_userName)); + Assert.That(_simpleProvider.DeleteAccount(_userName)); _simpleProvider.CreateAccount(_userName, _pass, false); - Assert.True(_simpleProvider.DeleteUser(_userName, true)); + Assert.That(_simpleProvider.DeleteUser(_userName, true)); } [Test] public void UserIsConfirmedTest() { MySqlWebSecurity.CreateUserAndAccount(_userName, _pass, null, true); - Assert.False(MySqlWebSecurity.IsConfirmed(_userName)); + Assert.That(!MySqlWebSecurity.IsConfirmed(_userName)); } [Test] public void UserIsLockedOutTest() { MySqlWebSecurity.CreateUserAndAccount(_userName, _pass, null, true); - Assert.False(MySqlWebSecurity.IsAccountLockedOut(_userName, 5, 60)); + Assert.That(!MySqlWebSecurity.IsAccountLockedOut(_userName, 5, 60)); } [Test] public void PasswordTest() { MySqlWebSecurity.CreateUserAndAccount(_userName, _pass); - Assert.AreEqual(DateTime.MinValue, MySqlWebSecurity.GetLastPasswordFailureDate(_userName)); - Assert.AreNotEqual(DateTime.MinValue, MySqlWebSecurity.GetPasswordChangedDate(_userName)); - Assert.AreEqual(0, MySqlWebSecurity.GetPasswordFailuresSinceLastSuccess(_userName)); + Assert.That(MySqlWebSecurity.GetLastPasswordFailureDate(_userName), Is.EqualTo(DateTime.MinValue)); + Assert.That(MySqlWebSecurity.GetPasswordChangedDate(_userName), Is.Not.EqualTo(DateTime.MinValue)); + Assert.That(MySqlWebSecurity.GetPasswordFailuresSinceLastSuccess(_userName), Is.EqualTo(0)); } //Password reset token must be assigned to the user but that field is not added in any part of the code, so maybe that field must be handled manually by the user @@ -194,10 +194,10 @@ public void PasswordResetTokenTest() { var token = MySqlWebSecurity.CreateUserAndAccount(_userName, _pass, null, true); int userID = MySqlWebSecurity.GetUserId(_userName); - Assert.True(MySqlWebSecurity.ConfirmAccount(token)); + Assert.That(MySqlWebSecurity.ConfirmAccount(token)); var newToken = MySqlWebSecurity.GeneratePasswordResetToken(_userName, 1440); - Assert.AreNotEqual(null, newToken); - Assert.AreEqual(MySqlWebSecurity.GetUserIdFromPasswordResetToken(newToken), userID); + Assert.That(newToken, Is.Not.EqualTo(null)); + Assert.That(userID, Is.EqualTo(MySqlWebSecurity.GetUserIdFromPasswordResetToken(newToken))); } #region WL14389 @@ -218,10 +218,10 @@ public void CreateUserAccountWithAttributes(int id, string userN, bool? token) break; } - Assert.True(MySqlWebSecurity.UserExists(userN)); + Assert.That(MySqlWebSecurity.UserExists(userN)); var user = MySqlHelper.ExecuteDataRow(ConnectionString, string.Format("select * from {0} where {1} = '{2}'", _userTable, _userNameColumn, userN)); - Assert.IsNotNull(user); - Assert.AreEqual(userN, user[_userNameColumn]); + Assert.That(user, Is.Not.Null); + Assert.That(user[_userNameColumn], Is.EqualTo(userN)); } #endregion diff --git a/MySql.Web/tests/SiteMapTests.cs b/MySql.Web/tests/SiteMapTests.cs index 1e66800c6..18e9d94a0 100644 --- a/MySql.Web/tests/SiteMapTests.cs +++ b/MySql.Web/tests/SiteMapTests.cs @@ -80,39 +80,39 @@ public void TestBuildSiteMap() SimpleWorkerRequest req = new SimpleWorkerRequest("/dummy", Environment.CurrentDirectory, "default.aspx", null, new StringWriter()); HttpContext.Current = new HttpContext(req); - Assert.AreEqual(node.Title, "Evan's Gambit"); + Assert.That("Evan's Gambit", Is.EqualTo(node.Title)); SiteMapNode nodep = prov.GetParentNode(node); - Assert.AreEqual(node.Description, "The Funny Italian Game"); - Assert.False(node.HasChildNodes); + Assert.That("The Funny Italian Game", Is.EqualTo(node.Description)); + Assert.That(!node.HasChildNodes); SiteMapNode node2 = node.NextSibling; - Assert.IsNotNull(node2); - Assert.AreEqual(node2.Title, "Sicilian Defense"); - Assert.AreEqual(node2.Description, "Sharp Double Edge Defense"); + Assert.That(node2, Is.Not.Null); + Assert.That("Sicilian Defense", Is.EqualTo(node2.Title)); + Assert.That("Sharp Double Edge Defense", Is.EqualTo(node2.Description)); node = node.PreviousSibling; - Assert.IsNotNull(node); - Assert.AreEqual(node.Title, "Ruy Lopez"); - Assert.AreEqual(node.Description, "The spanish opening"); - Assert.False(node.HasChildNodes); - Assert.IsNotNull(node.NextSibling); + Assert.That(node, Is.Not.Null); + Assert.That("Ruy Lopez", Is.EqualTo(node.Title)); + Assert.That("The spanish opening", Is.EqualTo(node.Description)); + Assert.That(!node.HasChildNodes); + Assert.That(node.NextSibling, Is.Not.Null); node = node.ParentNode; - Assert.AreEqual(node.Title, "Chess Openings"); + Assert.That("Chess Openings", Is.EqualTo(node.Title)); node = node.ParentNode; - Assert.AreEqual(node.Title, "Index"); + Assert.That("Index", Is.EqualTo(node.Title)); node = node.ParentNode; - Assert.IsNull(node); + Assert.That(node, Is.Null); node = prov.RootNode; - Assert.AreEqual(node.Title, "Index"); + Assert.That("Index", Is.EqualTo(node.Title)); string[] childData = new string[] { "Chess Openings", "Middle Game", "Endings" }; for (int i = 0; i < node.ChildNodes.Count; i++) { SiteMapNode child = node.ChildNodes[i]; - Assert.AreEqual(child.Title, childData[i]); + Assert.That(childData[i], Is.EqualTo(child.Title)); } } } diff --git a/MySql.Web/tests/UserManagement.cs b/MySql.Web/tests/UserManagement.cs index 0c312bbbf..a022e2045 100644 --- a/MySql.Web/tests/UserManagement.cs +++ b/MySql.Web/tests/UserManagement.cs @@ -55,16 +55,16 @@ private void CreateUserWithFormat(MembershipPasswordFormat format) // create the user MembershipCreateStatus status; provider.CreateUser("foo", "barbar!", "foo@bar.com", null, null, true, null, out status); - Assert.AreEqual(MembershipCreateStatus.Success, status); + Assert.That(status, Is.EqualTo(MembershipCreateStatus.Success)); // verify that the password format is hashed. DataTable table = FillTable("SELECT * FROM my_aspnet_membership"); MembershipPasswordFormat rowFormat = (MembershipPasswordFormat)Convert.ToInt32(table.Rows[0]["PasswordFormat"]); - Assert.AreEqual(format, rowFormat); + Assert.That(rowFormat, Is.EqualTo(format)); // then attempt to verify the user - Assert.True(provider.ValidateUser("foo", "barbar!")); + Assert.That(provider.ValidateUser("foo", "barbar!")); } @@ -108,19 +108,19 @@ public void ChangePassword() CreateUserWithFormat(MembershipPasswordFormat.Hashed); ArgumentException ex = Assert.Throws(() => provider.ChangePassword("foo", "barbar!", "bar2")); - Assert.AreEqual("newPassword", ex.ParamName); - Assert.True(ex.Message.Contains("length of parameter")); + Assert.That(ex.ParamName, Is.EqualTo("newPassword")); + Assert.That(ex.Message.Contains("length of parameter")); ArgumentException ex1 = Assert.Throws(() => provider.ChangePassword("foo", "barbar!", "barbar2")); - Assert.AreEqual("newPassword", ex1.ParamName); - Assert.True(ex1.Message.Contains("alpha numeric")); + Assert.That(ex1.ParamName, Is.EqualTo("newPassword")); + Assert.That(ex1.Message.Contains("alpha numeric")); // now test regex strength testing bool result = provider.ChangePassword("foo", "barbar!", "zzzxxx!"); - Assert.False(result); + Assert.That(!result); // now do one that should work result = provider.ChangePassword("foo", "barbar!", "barfoo!"); - Assert.True(result); + Assert.That(result); provider.ValidateUser("foo", "barfoo!"); @@ -146,26 +146,26 @@ public void CreateUserWithErrors() MembershipCreateStatus status; MembershipUser user = provider.CreateUser("foo", "xyz", "foo@bar.com", null, null, true, null, out status); - Assert.IsNull(user); - Assert.AreEqual(MembershipCreateStatus.InvalidPassword, status); + Assert.That(user, Is.Null); + Assert.That(status, Is.EqualTo(MembershipCreateStatus.InvalidPassword)); // now with not enough non-alphas user = provider.CreateUser("foo", "xyz1234", "foo@bar.com", null, null, true, null, out status); - Assert.IsNull(user); - Assert.AreEqual(MembershipCreateStatus.InvalidPassword, status); + Assert.That(user, Is.Null); + Assert.That(status, Is.EqualTo(MembershipCreateStatus.InvalidPassword)); // now one that doesn't pass the regex test user = provider.CreateUser("foo", "xyzxyz!", "foo@bar.com", null, null, true, null, out status); - Assert.IsNull(user); - Assert.AreEqual(MembershipCreateStatus.InvalidPassword, status); + Assert.That(user, Is.Null); + Assert.That(status, Is.EqualTo(MembershipCreateStatus.InvalidPassword)); // now one that works user = provider.CreateUser("foo", "barbar!", "foo@bar.com", null, null, true, null, out status); - Assert.IsNotNull(user); - Assert.AreEqual(MembershipCreateStatus.Success, status); + Assert.That(user, Is.Not.Null); + Assert.That(status, Is.EqualTo(MembershipCreateStatus.Success)); //Cleanup provider.DeleteUser("foo", true); @@ -178,11 +178,11 @@ public void DeleteUser() execSQL(@"delete from my_aspnet_membership; delete from my_aspnet_users;"); CreateUserWithFormat(MembershipPasswordFormat.Hashed); - Assert.True(provider.DeleteUser("foo", true)); + Assert.That(provider.DeleteUser("foo", true)); DataTable table = FillTable("SELECT * FROM my_aspnet_membership"); - Assert.AreEqual(0, table.Rows.Count); + Assert.That(table.Rows.Count, Is.EqualTo(0)); table = FillTable("SELECT * FROM my_aspnet_users"); - Assert.AreEqual(0, table.Rows.Count); + Assert.That(table.Rows.Count, Is.EqualTo(0)); CreateUserWithFormat(MembershipPasswordFormat.Hashed); provider = new MySQLMembershipProvider(); @@ -190,11 +190,11 @@ public void DeleteUser() config.Add("connectionStringName", "LocalMySqlServer"); config.Add("applicationName", "/"); provider.Initialize(null, config); - Assert.True(Membership.DeleteUser("foo", false)); + Assert.That(Membership.DeleteUser("foo", false)); table = FillTable("SELECT * FROM my_aspnet_membership"); - Assert.AreEqual(0, table.Rows.Count); + Assert.That(table.Rows.Count, Is.EqualTo(0)); table = FillTable("SELECT * FROM my_aspnet_users"); - Assert.AreEqual(1, table.Rows.Count); + Assert.That(table.Rows.Count, Is.EqualTo(1)); } [Test] @@ -203,8 +203,8 @@ public void FindUsersByName() CreateUserWithFormat(MembershipPasswordFormat.Hashed); int records; MembershipUserCollection users = provider.FindUsersByName("F%", 0, 10, out records); - Assert.AreEqual(1, records); - Assert.AreEqual("foo", users["foo"].UserName); + Assert.That(records, Is.EqualTo(1)); + Assert.That(users["foo"].UserName, Is.EqualTo("foo")); //Cleanup provider.DeleteUser("foo", true); @@ -217,8 +217,8 @@ public void FindUsersByEmail() int records; MembershipUserCollection users = provider.FindUsersByEmail("foo@bar.com", 0, 10, out records); - Assert.AreEqual(1, records); - Assert.AreEqual("foo", users["foo"].UserName); + Assert.That(records, Is.EqualTo(1)); + Assert.That(users["foo"].UserName, Is.EqualTo("foo")); //Cleanup provider.DeleteUser("foo", true); @@ -233,18 +233,18 @@ public void TestCreateUserOverrides() Membership.CreateUser("foo", "barbar!", null, "question", "answer", true, out status); int records; MembershipUserCollection users = Membership.FindUsersByName("F%", 0, 10, out records); - Assert.AreEqual(1, records); - Assert.AreEqual("foo", users["foo"].UserName); + Assert.That(records, Is.EqualTo(1)); + Assert.That(users["foo"].UserName, Is.EqualTo("foo")); Membership.CreateUser("test", "barbar!", "myemail@host.com", "question", "answer", true, out status); users = Membership.FindUsersByName("T%", 0, 10, out records); - Assert.AreEqual(1, records); - Assert.AreEqual("test", users["test"].UserName); + Assert.That(records, Is.EqualTo(1)); + Assert.That(users["test"].UserName, Is.EqualTo("test")); } catch (Exception ex) { - Assert.True(ex.Message != String.Empty, ex.Message); + Assert.That(ex.Message != String.Empty, ex.Message); } //Cleanup @@ -256,14 +256,14 @@ public void TestCreateUserOverrides() public void NumberOfUsersOnline() { int numOnline = Membership.GetNumberOfUsersOnline(); - Assert.AreEqual(0, numOnline); + Assert.That(numOnline, Is.EqualTo(0)); MembershipCreateStatus status; Membership.CreateUser("foo", "barbar!", null, "question", "answer", true, out status); Membership.CreateUser("foo2", "barbar!", null, "question", "answer", true, out status); numOnline = Membership.GetNumberOfUsersOnline(); - Assert.AreEqual(2, numOnline); + Assert.That(numOnline, Is.EqualTo(2)); //Cleanup Membership.DeleteUser("foo"); @@ -275,23 +275,23 @@ public void UnlockUser() { MembershipCreateStatus status; Membership.CreateUser("foo", "barbar!", null, "question", "answer", true, out status); - Assert.False(Membership.ValidateUser("foo", "bar2")); - Assert.False(Membership.ValidateUser("foo", "bar3")); - Assert.False(Membership.ValidateUser("foo", "bar3")); - Assert.False(Membership.ValidateUser("foo", "bar3")); - Assert.False(Membership.ValidateUser("foo", "bar3")); + Assert.That(!Membership.ValidateUser("foo", "bar2")); + Assert.That(!Membership.ValidateUser("foo", "bar3")); + Assert.That(!Membership.ValidateUser("foo", "bar3")); + Assert.That(!Membership.ValidateUser("foo", "bar3")); + Assert.That(!Membership.ValidateUser("foo", "bar3")); // the user should be locked now so the right password should fail - Assert.False(Membership.ValidateUser("foo", "barbar!")); + Assert.That(!Membership.ValidateUser("foo", "barbar!")); MembershipUser user = Membership.GetUser("foo"); - Assert.True(user.IsLockedOut); + Assert.That(user.IsLockedOut); - Assert.True(user.UnlockUser()); + Assert.That(user.UnlockUser()); user = Membership.GetUser("foo"); - Assert.False(user.IsLockedOut); + Assert.That(!user.IsLockedOut); - Assert.True(Membership.ValidateUser("foo", "barbar!")); + Assert.That(Membership.ValidateUser("foo", "barbar!")); //Cleanup Membership.DeleteUser("foo"); @@ -303,13 +303,13 @@ public void GetUsernameByEmail() MembershipCreateStatus status; Membership.CreateUser("foo", "barbar!", "foo@bar.com", "question", "answer", true, out status); string username = Membership.GetUserNameByEmail("foo@bar.com"); - Assert.AreEqual("foo", username); + Assert.That(username, Is.EqualTo("foo")); username = Membership.GetUserNameByEmail("foo@b.com"); - Assert.IsNull(username); + Assert.That(username, Is.Null); username = Membership.GetUserNameByEmail(" foo@bar.com "); - Assert.AreEqual("foo", username); + Assert.That(username, Is.EqualTo("foo")); //Cleanup Membership.DeleteUser("foo"); @@ -320,7 +320,7 @@ public void UpdateUser() { MembershipCreateStatus status; Membership.CreateUser("foo", "barbar!", "foo@bar.com", "color", "blue", true, out status); - Assert.AreEqual(MembershipCreateStatus.Success, status); + Assert.That(status, Is.EqualTo(MembershipCreateStatus.Success)); MembershipUser user = Membership.GetUser("foo"); @@ -332,11 +332,11 @@ public void UpdateUser() Membership.UpdateUser(user); MembershipUser newUser = Membership.GetUser("foo"); - Assert.AreEqual(user.Comment, newUser.Comment); - Assert.AreEqual(user.Email, newUser.Email); - Assert.AreEqual(user.IsApproved, newUser.IsApproved); - Assert.AreEqual(user.LastActivityDate, newUser.LastActivityDate); - Assert.AreEqual(user.LastLoginDate, newUser.LastLoginDate); + Assert.That(newUser.Comment, Is.EqualTo(user.Comment)); + Assert.That(newUser.Email, Is.EqualTo(user.Email)); + Assert.That(newUser.IsApproved, Is.EqualTo(user.IsApproved)); + Assert.That(newUser.LastActivityDate, Is.EqualTo(user.LastActivityDate)); + Assert.That(newUser.LastLoginDate, Is.EqualTo(user.LastLoginDate)); //Cleanup Membership.DeleteUser("foo"); @@ -350,11 +350,11 @@ private void ChangePasswordQAHelper(MembershipUser user, string pw, string newQ, } catch (ArgumentNullException ane) { - Assert.AreEqual("password", ane.ParamName); + Assert.That(ane.ParamName, Is.EqualTo("password")); } catch (ArgumentException) { - Assert.IsNotNull(pw); + Assert.That(pw, Is.Not.Null); } } @@ -363,7 +363,7 @@ public void ChangePasswordQuestionAndAnswer() { MembershipCreateStatus status; Membership.CreateUser("foo", "barbar!", "foo@bar.com", "color", "blue", true, out status); - Assert.AreEqual(MembershipCreateStatus.Success, status); + Assert.That(status, Is.EqualTo(MembershipCreateStatus.Success)); MembershipUser user = Membership.GetUser("foo"); ChangePasswordQAHelper(user, "", "newQ", "newA"); @@ -372,10 +372,10 @@ public void ChangePasswordQuestionAndAnswer() ChangePasswordQAHelper(user, null, "newQ", "newA"); bool result = user.ChangePasswordQuestionAndAnswer("barbar!", "newQ", "newA"); - Assert.True(result); + Assert.That(result); user = Membership.GetUser("foo"); - Assert.AreEqual("newQ", user.PasswordQuestion); + Assert.That(user.PasswordQuestion, Is.EqualTo("newQ")); //Cleanup Membership.DeleteUser("foo"); @@ -392,18 +392,18 @@ public void GetAllUsers() "question", "answer", true, out status); MembershipUserCollection users = Membership.GetAllUsers(); - Assert.AreEqual(100, users.Count); + Assert.That(users.Count, Is.EqualTo(100)); int index = 0; foreach (MembershipUser user in users) - Assert.AreEqual(String.Format("foo{0}", index++), user.UserName); + Assert.That(user.UserName, Is.EqualTo(String.Format("foo{0}", index++))); int total; users = Membership.GetAllUsers(2, 10, out total); - Assert.AreEqual(10, users.Count); - Assert.AreEqual(100, total); + Assert.That(users.Count, Is.EqualTo(10)); + Assert.That(total, Is.EqualTo(100)); index = 0; foreach (MembershipUser user in users) - Assert.AreEqual(String.Format("foo2{0}", index++), user.UserName); + Assert.That(user.UserName, Is.EqualTo(String.Format("foo2{0}", index++))); //Cleanup MySqlHelper.ExecuteScalar(Connection, "DELETE FROM my_aspnet_users"); @@ -435,7 +435,7 @@ private void GetPasswordHelper(bool requireQA, bool enablePasswordRetrieval, str else { Exception ex = Assert.Throws(() => provider.GetPassword("foo", answer)); - Assert.AreEqual(ex.Message, "Password Retrieval Not Enabled."); + Assert.That("Password Retrieval Not Enabled.", Is.EqualTo(ex.Message)); } } else @@ -452,7 +452,7 @@ private void GetPasswordHelper(bool requireQA, bool enablePasswordRetrieval, str else { password = provider.GetPassword("foo", answer); - Assert.AreEqual("barbar!", password); + Assert.That(password, Is.EqualTo("barbar!")); } } @@ -509,7 +509,7 @@ public void GetUser() MembershipCreateStatus status; Membership.CreateUser("foo", "barbar!", null, "question", "answer", true, out status); MembershipUser user = Membership.GetUser(1); - Assert.AreEqual("foo", user.UserName); + Assert.That(user.UserName, Is.EqualTo("foo")); // now move the activity date back outside the login // window @@ -517,10 +517,10 @@ public void GetUser() Membership.UpdateUser(user); user = Membership.GetUser("foo"); - Assert.False(user.IsOnline); + Assert.That(!user.IsOnline); user = Membership.GetUser("foo", true); - Assert.True(user.IsOnline); + Assert.That(user.IsOnline); // now move the activity date back outside the login // window again @@ -528,10 +528,10 @@ public void GetUser() Membership.UpdateUser(user); user = Membership.GetUser(1); - Assert.False(user.IsOnline); + Assert.That(!user.IsOnline); user = Membership.GetUser(1, true); - Assert.True(user.IsOnline); + Assert.That(user.IsOnline); //Cleanup Membership.DeleteUser("foo"); @@ -553,15 +553,15 @@ public void FindUsers() MembershipUserCollection users = Membership.FindUsersByName("fo%"); - Assert.AreEqual(100, users.Count); + Assert.That(users.Count, Is.EqualTo(100)); int total; users = Membership.FindUsersByName("fo%", 2, 10, out total); - Assert.AreEqual(10, users.Count); - Assert.AreEqual(100, total); + Assert.That(users.Count, Is.EqualTo(10)); + Assert.That(total, Is.EqualTo(100)); int index = 0; foreach (MembershipUser user in users) - Assert.AreEqual(String.Format("foo2{0}", index++), user.UserName); + Assert.That(user.UserName, Is.EqualTo(String.Format("foo2{0}", index++))); //Cleanup MySqlHelper.ExecuteScalar(Connection, "DELETE FROM my_aspnet_users"); @@ -582,10 +582,10 @@ public void CreateUserWithNoQA() provider.Initialize(null, config); Exception ex = Assert.Throws(() => provider.CreateUser("foo", "barbar!", "foo@bar.com", "color", null, true, null, out status)); - Assert.True(ex.Message.StartsWith("Password answer supplied is invalid", StringComparison.OrdinalIgnoreCase)); + Assert.That(ex.Message.StartsWith("Password answer supplied is invalid", StringComparison.OrdinalIgnoreCase)); ex = Assert.Throws(() => provider.CreateUser("foo", "barbar!", "foo@bar.com", "", "blue", true, null, out status)); - Assert.True(ex.Message.StartsWith("Password question supplied is invalid", StringComparison.OrdinalIgnoreCase)); + Assert.That(ex.Message.StartsWith("Password question supplied is invalid", StringComparison.OrdinalIgnoreCase)); } @@ -601,10 +601,10 @@ public void MinRequiredAlpha() MembershipCreateStatus status; MembershipUser user = provider.CreateUser("foo", "pw!pass", "email", null, null, true, null, out status); - Assert.IsNull(user); + Assert.That(user, Is.Null); user = provider.CreateUser("foo", "pw!pa!!", "email", null, null, true, null, out status); - Assert.IsNotNull(user); + Assert.That(user, Is.Not.Null); //Cleanup Membership.DeleteUser("foo"); @@ -628,10 +628,10 @@ public void GetPasswordWithNullValues() provider.Initialize(null, config); MembershipUser user = provider.CreateUser("foo", "barbar!", "foo@bar.com", null, null, true, null, out status); - Assert.IsNotNull(user); + Assert.That(user, Is.Not.Null); string pw = provider.GetPassword("foo", null); - Assert.AreEqual("barbar!", pw); + Assert.That(pw, Is.EqualTo("barbar!")); //Cleanup Membership.DeleteUser("foo"); @@ -654,10 +654,10 @@ public void GetEncryptedPassword() provider.Initialize(null, config); MembershipUser user = provider.CreateUser("foo", "barbar!", "foo@bar.com", null, null, true, null, out status); - Assert.IsNotNull(user); + Assert.That(user, Is.Not.Null); string pw = provider.GetPassword("foo", null); - Assert.AreEqual("barbar!", pw); + Assert.That(pw, Is.EqualTo("barbar!")); //Cleanup provider.DeleteUser("foo", true); @@ -688,7 +688,7 @@ public void CrossAppLogin() provider2.Initialize(null, config2); bool worked = provider2.ValidateUser("foo", "bar!bar"); - Assert.AreEqual(false, worked); + Assert.That(worked, Is.EqualTo(false)); //Cleanup provider.DeleteUser("foo", true); @@ -734,7 +734,7 @@ public void ChangeAppName() provider.Initialize(null, config); MembershipCreateStatus status; provider.CreateUser("foo", "bar!bar", null, null, null, true, null, out status); - Assert.True(status == MembershipCreateStatus.Success); + Assert.That(status == MembershipCreateStatus.Success); MySQLMembershipProvider provider2 = new MySQLMembershipProvider(); NameValueCollection config2 = new NameValueCollection(); @@ -744,11 +744,11 @@ public void ChangeAppName() config2.Add("passwordFormat", "Clear"); provider2.Initialize(null, config2); provider2.CreateUser("foo2", "foo!foo", null, null, null, true, null, out status); - Assert.True(status == MembershipCreateStatus.Success); + Assert.That(status == MembershipCreateStatus.Success); provider.ApplicationName = "/myapp"; - Assert.False(provider.ValidateUser("foo", "bar!bar")); - Assert.True(provider.ValidateUser("foo2", "foo!foo")); + Assert.That(!provider.ValidateUser("foo", "bar!bar")); + Assert.That(provider.ValidateUser("foo2", "foo!foo")); //Cleanup //provider.DeleteUser("foo2", true); @@ -767,10 +767,10 @@ public void GetUserLooksForExactUsername() Membership.CreateUser("code", "thecode!", null, "question", "answer", true, out status); MembershipUser user = Membership.GetUser("code"); - Assert.AreEqual("code", user.UserName); + Assert.That(user.UserName, Is.EqualTo("code")); user = Membership.GetUser("co_e"); - Assert.IsNull(user); + Assert.That(user, Is.Null); //Cleanup Membership.DeleteUser("code"); @@ -783,10 +783,10 @@ public void GetUserNameByEmailLooksForExactEmail() Membership.CreateUser("code", "thecode!", "code@mysql.com", "question", "answer", true, out status); string username = Membership.GetUserNameByEmail("code@mysql.com"); - Assert.AreEqual("code", username); + Assert.That(username, Is.EqualTo("code")); username = Membership.GetUserNameByEmail("co_e@mysql.com"); - Assert.IsNull(username); + Assert.That(username, Is.Null); //Cleanup Membership.DeleteUser("code"); @@ -807,20 +807,20 @@ public void CreateUserWithLeadingAndTrailingSpaces() MembershipCreateStatus status; MembershipUser muser1 = provider.CreateUser(" with trailing space ", "dummypassword1!", "w@w1.w", "yes", "yes", true, null, out status); - Assert.AreNotEqual(null, muser1); + Assert.That(muser1, Is.Not.EqualTo(null)); MembershipUser muser2 = provider.GetUser("with trailing space", false); - Assert.AreNotEqual(null, muser1); + Assert.That(muser1, Is.Not.EqualTo(null)); Roles.CreateRole("SomeRole"); - Assert.True(Roles.GetAllRoles().Length > 0); + Assert.That(Roles.GetAllRoles().Length > 0); bool isInRole = Roles.IsUserInRole(muser2.UserName, "SomeRole"); - Assert.False(isInRole); + Assert.That(!isInRole); Roles.AddUserToRole(muser2.UserName, "SomeRole"); isInRole = Roles.IsUserInRole(muser2.UserName, "SomeRole"); - Assert.True(isInRole); + Assert.That(isInRole); } } } From 339317f1a6806d38d7b23908933737817a6faf2c Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Sun, 26 May 2024 17:37:37 -0600 Subject: [PATCH 061/125] WL#16402 [Use Assumptions instead of Assert.Ignore in testsuite] Change-Id: Ie9128d5fa19b59265fa0773b8003360ace751f2c --- CHANGES | 1 + .../FluentAPITests.cs | 30 ++------- .../LoadingRelatedDataTests.cs | 15 +---- .../MySQLTypeMapperTests.cs | 5 +- .../MySQLDatabaseModelFactoryTest.cs | 5 +- .../DatesTypesTests.cs | 5 +- .../tests/MySql.Data.Tests/AttributeTests.cs | 16 ++--- .../tests/MySql.Data.Tests/AuthTests.cs | 12 ++-- .../tests/MySql.Data.Tests/CharSetTests.cs | 5 +- .../MySql.Data.Tests/CharSetUTF8Tests.cs | 2 +- .../ClientSideFailoverTests.cs | 4 +- .../ConnectionStringBuilderTests.cs | 6 +- .../tests/MySql.Data.Tests/ConnectionTests.cs | 25 ++++---- .../tests/MySql.Data.Tests/DataTypeTests.cs | 15 ++--- .../netstandard2_0/GetSchemaTests.cs | 19 +++--- .../netstandard2_0/MySQLHelperTests.cs | 2 +- .../netstandard2_0/MySqlDataAdapterTests.cs | 2 +- .../tests/MySql.Data.Tests/PoolingTests.cs | 2 +- MySQL.Data/tests/MySql.Data.Tests/SslTests.cs | 31 +++++----- .../tests/MySql.Data.Tests/StoredProcedure.cs | 7 +-- MySQL.Data/tests/MySql.Data.Tests/Syntax.cs | 2 +- .../tests/MySql.Data.Tests/Transactions.cs | 4 +- .../tests/MySql.Data.Tests/UnixSockets.cs | 6 +- .../tests/MySqlX.Data.Tests/BasicFindTests.cs | 62 +++++++++---------- .../CharsetAndCollationTests.cs | 22 +++---- .../ClientSideFailoverTests.cs | 12 ++-- .../tests/MySqlX.Data.Tests/ClientTests.cs | 50 +++++++-------- .../MySqlX.Data.Tests/CloseConnectionTests.cs | 14 ++--- .../MySqlX.Data.Tests/CollectionIndexTests.cs | 44 ++++++------- .../MySqlX.Data.Tests/CollectionTests.cs | 24 +++---- .../MySqlX.Data.Tests/CompressionTests.cs | 14 ++--- .../MySqlX.Data.Tests/CrudInsertTests.cs | 62 +++++++++---------- .../MySqlX.Data.Tests/CrudRemoveTests.cs | 2 +- .../MySqlX.Data.Tests/CrudUpdateTests.cs | 20 +++--- .../tests/MySqlX.Data.Tests/MergePatch.cs | 48 +++++++------- .../PreparedStatementsTests.cs | 4 +- .../RelationalTests/SqlTests.cs | 36 +++++------ .../RelationalTests/TableSelectTests.cs | 60 +++++++++--------- .../RelationalTests/TableUpdateTests.cs | 6 +- .../tests/MySqlX.Data.Tests/SchemaTests.cs | 6 +- .../tests/MySqlX.Data.Tests/SessionTests.cs | 20 +++--- .../tests/MySqlX.Data.Tests/SslTests.cs | 44 ++++++------- .../MySqlX.Data.Tests/TransactionTests.cs | 36 +++++------ MySQL.Data/tests/MySqlX.Data.Tests/XAuth.cs | 32 ++++------ .../XConnectionStringBuilderTests.cs | 2 +- 45 files changed, 393 insertions(+), 448 deletions(-) diff --git a/CHANGES b/CHANGES index 6467ea3be..8d2032816 100644 --- a/CHANGES +++ b/CHANGES @@ -1,5 +1,6 @@ 9.1.0 - Updated test suite to use constraint-based assertions (WL16397). +- Changed testsuite to use assummptions instead of Assert.Ignore (WL16402). 9.0.0 diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/FluentAPITests.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/FluentAPITests.cs index 8a81ddb6f..4a4c79982 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/FluentAPITests.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/FluentAPITests.cs @@ -57,10 +57,7 @@ public void OneTimeTearDown() [Test] public void EnsureRelationalPatterns() { - if (!TestUtils.IsAtLeast(5, 7, 0)) - { - Assert.Ignore(); - } + Assume.That(TestUtils.IsAtLeast(5, 7, 0)); var serviceCollection = new ServiceCollection(); serviceCollection.AddEntityFrameworkMySQL() @@ -227,10 +224,7 @@ public void CanUseConcurrency() [Test] public void CanUseConcurrencyToken() { - if (!TestUtils.IsAtLeast(5, 7, 0)) - { - Assert.Ignore(); - } + Assume.That(TestUtils.IsAtLeast(5, 7, 0)); var serviceCollection = new ServiceCollection(); serviceCollection.AddEntityFrameworkMySQL() @@ -256,10 +250,7 @@ public void CanUseConcurrencyToken() [Test] public void CanUseContainsInQuery() { - if (!TestUtils.IsAtLeast(5, 7, 0)) - { - Assert.Ignore(); - } + Assume.That(TestUtils.IsAtLeast(5, 7, 0)); var serviceCollection = new ServiceCollection(); serviceCollection.AddEntityFrameworkMySQL() @@ -283,10 +274,7 @@ public void CanUseContainsInQuery() [Test] public void CanUseContainsVarInQuery() { - if (!TestUtils.IsAtLeast(5, 7, 0)) - { - Assert.Ignore(); - } + Assume.That(TestUtils.IsAtLeast(5, 7, 0)); var serviceCollection = new ServiceCollection(); serviceCollection.AddEntityFrameworkMySQL() @@ -311,10 +299,7 @@ public void CanUseContainsVarInQuery() [Test] public void CanUseContainsWithInvalidValue() { - if (!TestUtils.IsAtLeast(5, 7, 0)) - { - Assert.Ignore(); - } + Assume.That(TestUtils.IsAtLeast(5, 7, 0)); var serviceCollection = new ServiceCollection(); serviceCollection.AddEntityFrameworkMySQL() @@ -340,10 +325,7 @@ public void CanUseContainsWithInvalidValue() [Test] public void CanUseContainsWithVariableInQuery() { - if (!TestUtils.IsAtLeast(5, 7, 0)) - { - Assert.Ignore(); - } + Assume.That(TestUtils.IsAtLeast(5, 7, 0)); var serviceCollection = new ServiceCollection(); serviceCollection.AddEntityFrameworkMySQL() diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/LoadingRelatedDataTests.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/LoadingRelatedDataTests.cs index 4378672b3..c0c67bf8b 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/LoadingRelatedDataTests.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/LoadingRelatedDataTests.cs @@ -169,10 +169,7 @@ public void DbSetFind() [Test] public void JsonDataTest() { - if (!TestUtils.IsAtLeast(5, 7, 0)) - { - Assert.Ignore(); - } + Assume.That(TestUtils.IsAtLeast(5, 7, 0)); using (JsonContext context = new JsonContext()) { @@ -219,10 +216,7 @@ public void JsonDataTest() [Test] public void JsonInvalidData() { - if (!TestUtils.IsAtLeast(5, 7, 0)) - { - Assert.Ignore(); - } + Assume.That(TestUtils.IsAtLeast(5, 7, 0)); using (JsonContext context = new JsonContext()) { @@ -242,10 +236,7 @@ public void JsonInvalidData() [Test] public void ComputedColumns() { - if (!TestUtils.IsAtLeast(5, 7, 0)) - { - Assert.Ignore(); - } + Assume.That(TestUtils.IsAtLeast(5, 7, 0)); using (FiguresContext context = new FiguresContext()) { diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/MySQLTypeMapperTests.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/MySQLTypeMapperTests.cs index 8e7173496..e94c583c5 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/MySQLTypeMapperTests.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/MySQLTypeMapperTests.cs @@ -55,10 +55,7 @@ public void OneTimeTearDown() [Test] public void InsertAllDataTypes() { - if (!TestUtils.IsAtLeast(5, 7, 0)) - { - Assert.Ignore(); - } + Assume.That(TestUtils.IsAtLeast(5, 7, 0)); DateTime now = new DateTime(DateTime.Today.AddSeconds(1).AddMilliseconds(1).AddTicks(10).Ticks); diff --git a/EFCore/tests/MySql.EFCore.Design.Tests/MySQLDatabaseModelFactoryTest.cs b/EFCore/tests/MySql.EFCore.Design.Tests/MySQLDatabaseModelFactoryTest.cs index a520b0c2c..a5032f43a 100644 --- a/EFCore/tests/MySql.EFCore.Design.Tests/MySQLDatabaseModelFactoryTest.cs +++ b/EFCore/tests/MySql.EFCore.Design.Tests/MySQLDatabaseModelFactoryTest.cs @@ -265,10 +265,7 @@ private void Test(string createSql, IEnumerable tables, IEnumerable System.IndexOutOfRangeException: There is no row at position 3."); - if (Version < new Version(5, 6, 5)) - Assert.Ignore("MySQL Server version no compatible"); + Assume.That(Version >= new Version(5, 6, 5)); using (var ctx = new TestContext(ConnectionString)) { diff --git a/MySQL.Data/tests/MySql.Data.Tests/AttributeTests.cs b/MySQL.Data/tests/MySql.Data.Tests/AttributeTests.cs index 2dbeba0e0..3ec9b1aff 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/AttributeTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/AttributeTests.cs @@ -48,7 +48,7 @@ public void SetUp() [TestCase(false)] public void SetAttributesWithoutParams(bool prepare) { - if (!Connection.driver.SupportsQueryAttributes) Assert.Ignore("MySQL Server version does not support query attributes."); + Assume.That(Connection.driver.SupportsQueryAttributes, "MySQL Server version does not support query attributes."); using MySqlCommand cmd = new MySqlCommand(); cmd.Connection = Connection; @@ -86,7 +86,7 @@ public void SetAttributesWithoutParams(bool prepare) [TestCase("DoubleType", 1234.567)] public void ValueTypes(string name, object value) { - if (!Connection.driver.SupportsQueryAttributes) Assert.Ignore("MySQL Server version does not support query attributes."); + Assume.That(Connection.driver.SupportsQueryAttributes, "MySQL Server version does not support query attributes."); using MySqlCommand cmd = new MySqlCommand(); cmd.Connection = Connection; @@ -99,7 +99,7 @@ public void ValueTypes(string name, object value) [Test] public void TimeSpanValueType() { - if (!Connection.driver.SupportsQueryAttributes) Assert.Ignore("MySQL Server version does not support query attributes."); + Assume.That(Connection.driver.SupportsQueryAttributes, "MySQL Server version does not support query attributes."); TimeSpan time = new TimeSpan(01, 19, 25); @@ -114,7 +114,7 @@ public void TimeSpanValueType() [Test] public void DateTimeValueType() { - if (!Connection.driver.SupportsQueryAttributes) Assert.Ignore("MySQL Server version does not support query attributes."); + Assume.That(Connection.driver.SupportsQueryAttributes, "MySQL Server version does not support query attributes."); DateTime dateTime = DateTime.Now; @@ -143,7 +143,7 @@ public void ClearAttributes() [Test] public void SameNameAttribute() { - if (!Connection.driver.SupportsQueryAttributes) Assert.Ignore("MySQL Server version does not support query attributes."); + Assume.That(Connection.driver.SupportsQueryAttributes, "MySQL Server version does not support query attributes."); using MySqlCommand cmd = new MySqlCommand(); cmd.Connection = Connection; @@ -160,7 +160,7 @@ public void SameNameAttribute() [TestCase(false)] public void QueryAttributesNotSupported(bool prepare) { - if (Connection.driver.SupportsQueryAttributes) Assert.Ignore("Query attributes supported."); + Assume.That(!Connection.driver.SupportsQueryAttributes,"Query attributes supported."); MySqlTrace.Listeners.Clear(); MySqlTrace.Switch.Level = System.Diagnostics.SourceLevels.Warning; @@ -185,7 +185,7 @@ public void QueryAttributesNotSupported(bool prepare) [TestCase(false)] public void AttributesAndParameters(bool prepare) { - if (!Connection.driver.SupportsQueryAttributes) Assert.Ignore("MySQL Server version does not support query attributes."); + Assume.That(Connection.driver.SupportsQueryAttributes, "MySQL Server version does not support query attributes."); using MySqlCommand cmd = new MySqlCommand(); cmd.Connection = Connection; @@ -222,7 +222,7 @@ public void InvalidValues() [TestCase(false)] public void ParameterOverridesAttributeValue(bool prepare) { - if (!Connection.driver.SupportsQueryAttributes) Assert.Ignore("MySQL Server version does not support query attributes."); + Assume.That(Connection.driver.SupportsQueryAttributes, "MySQL Server version does not support query attributes."); using var cmd = new MySqlCommand("select mysql_query_attribute_string('name') as attribute, mysql_query_attribute_string('name2') as attribute2, @name as parameter, @name2 as parameter2, mysql_query_attribute_string('attr') as attribute3", Connection); cmd.Attributes.SetAttribute("name", "attribute"); diff --git a/MySQL.Data/tests/MySql.Data.Tests/AuthTests.cs b/MySQL.Data/tests/MySql.Data.Tests/AuthTests.cs index 29fe191f8..0a3a3df2d 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/AuthTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/AuthTests.cs @@ -358,8 +358,7 @@ private void TestIntegratedSecurityWithUser(string user, bool pooling) [Property("Category", "Security")] public void ConnectUsingMySqlNativePasswordPlugin() { - if (!Check_Plugin_Enabled("mysql_native_password")) - Assert.Ignore("mysql_native_password plugin must be enabled on the server to run this test"); + Assume.That(Check_Plugin_Enabled("mysql_native_password"), "mysql_native_password plugin must be enabled on the server to run this test"); string userName = "testNtvPass"; string password = "mysql"; @@ -1835,12 +1834,9 @@ public void AuthPlainAndMySql41() "with secure connections(classic connection).Server started with mysql native password plugin")] public void Sha256AndNativeWithCertificates() { - if (Version < new Version("8.0.4")) - Assert.Ignore("This test is for MySql 8.0.4 or higher"); - if (!Check_Plugin_Enabled("mysql_native_password")) - Assert.Ignore("mysql_native_password plugin must be enabled on the server to run this test"); - if (!Check_Plugin_Enabled("caching_sha2_password")) - Assert.Ignore("This test needs plugin caching_sha2_password"); + Assume.That(Version >= new Version("8.0.4"), "This test is for MySql 8.0.4 or higher"); + Assume.That(Check_Plugin_Enabled("mysql_native_password"), "mysql_native_password plugin must be enabled on the server to run this test"); + Assume.That(Check_Plugin_Enabled("caching_sha2_password"), "This test needs plugin caching_sha2_password"); // Test connection for VALID user in LDAP server with different SSLMode values, expected result pass string assemblyPath = Assembly.GetExecutingAssembly().Location.Replace(String.Format("{0}.dll", diff --git a/MySQL.Data/tests/MySql.Data.Tests/CharSetTests.cs b/MySQL.Data/tests/MySql.Data.Tests/CharSetTests.cs index 698c274ca..d3021e26d 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/CharSetTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/CharSetTests.cs @@ -503,8 +503,7 @@ public void CharacterVariablesByDefault() [Test] public void DatabaseCaseSentitive() { - if (Version >= new Version(8, 0, 0) || !Platform.IsWindows()) Assert.Ignore("This test is only for Windows OS and MySql higher than 8.0."); - + Assume.That(Version >= new Version(8, 0, 0) && Platform.IsWindows(), "This test is only for Windows OS and MySql higher than 8.0."); ExecuteSQL("DROP PROCEDURE IF EXISTS spTest"); ExecuteSQL(@"CREATE PROCEDURE spTest () BEGIN SELECT ""test""; END"); @@ -528,7 +527,7 @@ public void DatabaseCaseSentitive() [Test] public void PoundSymbolInJsonColumn() { - if (Version < new Version(5, 7, 0)) Assert.Ignore("JSON data type not available in MySQL Server v5.6"); + Assume.That(Version >= new Version(5, 7, 0), "JSON data type not available in MySQL Server v5.6"); ExecuteSQL("CREATE TABLE `PoundTable`(`TextColumn` VARCHAR(20) NULL, `JsonColumn` JSON);"); ExecuteSQL("INSERT INTO `PoundTable`(`TextColumn`, `JsonColumn`) VALUES('£', JSON_OBJECT('Value', '£'));"); diff --git a/MySQL.Data/tests/MySql.Data.Tests/CharSetUTF8Tests.cs b/MySQL.Data/tests/MySql.Data.Tests/CharSetUTF8Tests.cs index 33bb95c5f..7202be6cf 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/CharSetUTF8Tests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/CharSetUTF8Tests.cs @@ -78,7 +78,7 @@ public void UTF8BlogsTruncating() public void GetSchemaOnUTF8() { #if !NETFRAMEWORK - if (!Platform.IsWindows()) Assert.Ignore(); + Assume.That(Platform.IsWindows()); #endif ExecuteSQL("CREATE TABLE Test(name VARCHAR(40) NOT NULL, name2 VARCHAR(20)) " + "CHARACTER SET utf8"); diff --git a/MySQL.Data/tests/MySql.Data.Tests/ClientSideFailoverTests.cs b/MySQL.Data/tests/MySql.Data.Tests/ClientSideFailoverTests.cs index 829fae591..313f4c353 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/ClientSideFailoverTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/ClientSideFailoverTests.cs @@ -55,7 +55,7 @@ public void RandomMethod(string server, bool shouldPass = true) if (Settings.Server.Contains("::1")) { ipv6 = GetMySqlServerIp(true); - if (string.IsNullOrEmpty(ipv6)) Assert.Ignore("No IPv6 available."); + Assume.That(!string.IsNullOrEmpty(ipv6), "No IPv6 available."); Settings.Server = server.Replace("::1", ipv6); } @@ -83,7 +83,7 @@ private static ConnectionState TryConnection(string connString) public void PriorityMethod() { #if !NETFRAMEWORK - if (!System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.Windows)) Assert.Ignore(); + Assume.That(System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.Windows)); #endif // Multiple hosts and validate proper order assigned to hosts. Settings.Pooling = false; diff --git a/MySQL.Data/tests/MySql.Data.Tests/ConnectionStringBuilderTests.cs b/MySQL.Data/tests/MySql.Data.Tests/ConnectionStringBuilderTests.cs index 5f04d2c1b..bf4bd2450 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/ConnectionStringBuilderTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/ConnectionStringBuilderTests.cs @@ -196,7 +196,7 @@ public void DotnetCoreNotCurrentlySupported() [Test] public void NonWindowsOSNotCurrentlySupported() { - if (Platform.IsWindows()) Assert.Ignore("This test is for non Windows OS only."); + Assume.That(!Platform.IsWindows(), "This test is for non Windows OS only."); List options = new List(new string[] { @@ -282,7 +282,7 @@ public void UsingPwdAliases(string alias) [Test, Description("Session BaseString/MySQLConnectionString Builder")] public void ConnectionStringBuilderClassicTests() { - if (!Platform.IsWindows()) Assert.Ignore("This test is for Windows OS only."); + Assume.That(Platform.IsWindows(), "This test is for Windows OS only."); MySqlConnectionStringBuilder mysql = new MySqlConnectionStringBuilder(Settings.ConnectionString); @@ -442,7 +442,7 @@ public void TryGetValue() [Test] public void KerberosAuthModeTest() { - if (!Platform.IsWindows()) Assert.Ignore("This test is for Windows OS only."); + Assume.That(Platform.IsWindows(), "This test is for Windows OS only."); string connString; MySqlConnection conn; diff --git a/MySQL.Data/tests/MySql.Data.Tests/ConnectionTests.cs b/MySQL.Data/tests/MySql.Data.Tests/ConnectionTests.cs index c2fef3dab..0b53cf79a 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/ConnectionTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/ConnectionTests.cs @@ -763,12 +763,12 @@ public void TestNonSupportedOptions() [Test] public void IPv6Connection() { - if (Version < new Version(5, 6, 0)) return; + Assume.That(Version >= new Version(5, 6, 0)); MySqlConnectionStringBuilder sb = new MySqlConnectionStringBuilder(Connection.ConnectionString); sb.Server = GetMySqlServerIp(true); - if (sb.Server == string.Empty) Assert.Ignore("No IPv6 available."); + Assume.That(sb.Server != string.Empty, "No IPv6 available."); using (MySqlConnection conn = new MySqlConnection(sb.ToString())) { @@ -855,7 +855,7 @@ public void ExpiredPwdWithOldPassword() [Ignore("To be able to connect using Named Pipes, it requires to start the server supporting the protocol")] public void ConnectUsingNamedPipes() { - if (!Platform.IsWindows()) Assert.Ignore("Shared Memory is only supported on Windows."); + Assume.That(Platform.IsWindows(), "Named Pipes is only supported on Windows."); var sb = new MySqlConnectionStringBuilder() { @@ -881,7 +881,7 @@ public void ConnectUsingNamedPipes() [Ignore("To be able to connect using Named Pipes, it requires to start the server supporting the protocol")] public void NamedPipesMultithreadConnection() { - if (!Platform.IsWindows()) Assert.Ignore("Named Pipes is only supported on Windows."); + Assume.That(Platform.IsWindows(), "Named Pipes is only supported on Windows."); var sb = new MySqlConnectionStringBuilder() { @@ -925,9 +925,10 @@ public void NamedPipesMultithreadConnection() /// [Test] [Property("Category", "Security")] + [Ignore("To be able to connect using Shared Memory, it requires to start the server supporting the protocol")] public void ConnectUsingSharedMemory() { - if (!Platform.IsWindows()) Assert.Ignore("Shared Memory is only supported on Windows."); + Assume.That(Platform.IsWindows(), "Shared Memory is only supported on Windows."); var sb = new MySqlConnectionStringBuilder() { @@ -962,7 +963,7 @@ public void ConnectUsingSharedMemory() [Ignore("To be able to connect using Shared Memory, it requires to start the server supporting the protocol")] public void SharedMemoryMultithreadConnection() { - if (!Platform.IsWindows()) Assert.Ignore("Shared Memory is only supported on Windows."); + Assume.That(Platform.IsWindows(), "Shared Memory is only supported on Windows."); var sb = new MySqlConnectionStringBuilder() { @@ -1208,7 +1209,7 @@ public void MediumTextMalformedPkg() [Test, Description("Verify Compression in classic protocol where default connection string is used without any option")] public void CompressionUnit() { - if (Version < new Version(8, 0, 0)) Assert.Ignore("This test is for MySql 8.0 or higher."); + Assume.That(Version >= new Version(8, 0, 0), "This test is for MySql 8.0 or higher."); using (var dbConn = new MySqlConnection(Connection.ConnectionString + ";UseCompression=True")) { var cmd = new MySqlCommand(); @@ -1296,7 +1297,7 @@ public void CompressionUnit() [Test, Description("Verify Compression in classic protocol where default connection string is used without any option")] public void CompressionValidationInClassicProtocol() { - if (Version < new Version(8, 0, 0)) Assert.Ignore("This test is for MySql 8.0 or higher."); + Assume.That(Version >= new Version(8, 0, 0), "This test is for MySql 8.0 or higher."); string[] compressionAlgorithms = new string[] { "zlib", "zstd", "uncompressed", "uncompressed,zlib", "uncompressed,zstd", "zstd,zlib", "zstd,zlib,uncompressed" }; for (int k = 0; k < compressionAlgorithms.Length; k++) { @@ -1438,7 +1439,7 @@ public void CompressionValidationInClassicProtocol() [Test, Description("Test MySql Password Expiration with blank password")] public void ExpiredBlankPassword() { - if (Version < new Version(8, 0, 0)) Assert.Ignore("This test is for MySql 8.0 or higher."); + Assume.That(Version >= new Version(8, 0, 0), "This test is for MySql 8.0 or higher."); string host = Host == "localhost" ? Host : "%"; MySqlConnectionStringBuilder sb = new MySqlConnectionStringBuilder(Connection.ConnectionString); @@ -1473,7 +1474,7 @@ public void ExpiredBlankPassword() [Test, Description("Test MySql Password Expiration with query variables")] public void ExpiredPasswordBug2() { - if (Version < new Version(8, 0, 0)) Assert.Ignore("This test is for MySql 8.0 or higher."); + Assume.That(Version >= new Version(8, 0, 0), "This test is for MySql 8.0 or higher."); var _expiredPwd = "expiredPwd"; SetupExpiredPasswordUser(_expiredPwd); @@ -1498,7 +1499,7 @@ public void ExpiredPasswordBug2() [Test, Description("Test MySql Password Expiration with IsPasswordExpired validation")] public void ExpiredPasswordBug3() { - if (Version < new Version(8, 0, 0)) Assert.Ignore("This test is for MySql 8.0 or higher."); + Assume.That(Version >= new Version(8, 0, 0), "This test is for MySql 8.0 or higher."); string host = Host == "localhost" ? Host : "%"; var _expiredPwd = "expiredPwd"; @@ -1541,7 +1542,7 @@ public void ExpiredPasswordBug3() [Test, Description("Test MySql Password Expiration and set password")] public void ExpiredPasswordBug4() { - if (Version < new Version(8, 0, 0)) Assert.Ignore("This test is for MySql 8.0 or higher."); + Assume.That(Version >= new Version(8, 0, 0), "This test is for MySql 8.0 or higher."); string host = Host == "localhost" ? Host : "%"; var _expiredPwd = "expiredPwd"; diff --git a/MySQL.Data/tests/MySql.Data.Tests/DataTypeTests.cs b/MySQL.Data/tests/MySql.Data.Tests/DataTypeTests.cs index acb1cea84..784409462 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/DataTypeTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/DataTypeTests.cs @@ -1240,7 +1240,7 @@ public void Timediff() [Test] public void CanReadJsonValue() { - if (Version < new Version(5, 7)) Assert.Ignore("This test is for MySql 5.7 or higher"); ; + Assume.That(Version >= new Version(5, 7, 0), "This test is for MySql 5.7 or higher."); ExecuteSQL("CREATE TABLE Test(Id int NOT NULL PRIMARY KEY, jsoncolumn JSON)"); MySqlCommand cmd = new MySqlCommand("INSERT INTO Test VALUES (@id, '[1]')", Connection); cmd.Parameters.AddWithValue("@id", 1); @@ -1503,7 +1503,7 @@ public void UnexpectedColumnSize() [Test, Description("Test Can Read long JSON Values")] public void ReadJSONLongValues() { - if (Version < new Version(5, 7)) Assert.Ignore("This test is for MySql 5.7 or higher."); + Assume.That(Version >= new Version(5, 7, 0), "This test is for MySql 5.7 or higher."); var sb = new StringBuilder("0"); for (int x = 1; x <= 575; x++) { @@ -1547,7 +1547,7 @@ public void ReadJSONLongValues() [Test, Description("Test Can Read JSON Value Stress")] public void ReadJSONValueStress() { - if (Version < new Version(5, 7)) Assert.Ignore("This test is for MySql 5.7 or higher."); + Assume.That(Version >= new Version(5, 7, 0), "This test is for MySql 5.7 or higher."); ExecuteSQL("CREATE TABLE Test (Id int NOT NULL PRIMARY KEY, jsoncolumn JSON)"); string jsonTest = null; for (var i = 0; i < 1000; i++) @@ -1664,8 +1664,7 @@ public void GetIntForTinyInt(bool treatAsBool, bool isPrepared) [Test] public void BadVectorDataThrowsException() { - if (Version < new Version(9, 0, 0)) - Assert.Ignore(); + Assume.That(Version >= new Version(9, 0, 0), "This test is for MySql 9.0 or higher."); ExecuteSQL(@"CREATE TABLE Test (vector1 VECTOR)"); using var cmd = new MySqlCommand(); @@ -1682,8 +1681,7 @@ public void BadVectorDataThrowsException() [TestCase(true)] public void InsertAndSelectVector(bool prepared) { - if (Version < new Version(9, 0, 0)) - Assert.Ignore(); + Assume.That(Version >= new Version(9, 0, 0), "This test is for MySql 9.0 or higher."); ExecuteSQL(@"CREATE TABLE Test (vector1 VECTOR)"); using var cmd = new MySqlCommand(); @@ -1724,8 +1722,7 @@ public void InsertAndSelectVector(bool prepared) [TestCase(true)] public void VectorReturnedFromSproc(bool prepared) { - if (Version < new Version(9, 0, 0)) - Assert.Ignore(); + Assume.That(Version >= new Version(9, 0, 0), "This test is for MySql 9.0 or higher."); ExecuteSQL("DROP PROCEDURE IF EXISTS spTest"); ExecuteSQL(@"CREATE PROCEDURE spTest (OUT v1 VECTOR) BEGIN diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/GetSchemaTests.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/GetSchemaTests.cs index 115f2b263..c36c31488 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/GetSchemaTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/GetSchemaTests.cs @@ -76,8 +76,7 @@ public void Collections() [Test] public void DataTypes() { - if (Version < new Version(9, 0, 0)) - Assert.Ignore(); + Assume.That(Version >= new Version(9, 0, 0), "This test is for MySql 9.0 or higher."); DataTable dt = Connection.GetSchema("DataTypes", new string[] { }); @@ -250,8 +249,8 @@ col3 varchar(50) character set utf8, col4 tinyint unsigned, [Test] public void CanGetSchemaInformationGeneratedColumns() { - if (!System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.Windows)) Assert.Ignore(); - if (Version < new Version(5, 7, 6)) Assert.Ignore(); + Assume.That(System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.Windows)); + Assume.That(Version >= new Version(5, 7, 6)); ExecuteSQL("CREATE TABLE `Test` (`ID` int NOT NULL AUTO_INCREMENT PRIMARY KEY, `Name` char(35) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL)"); @@ -490,7 +489,7 @@ public void SingleForeignKey() [Test] public void ForeignKeys() { - if (!System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.Windows)) Assert.Ignore(); + Assume.That(System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.Windows)); ExecuteSQL("DROP TABLE IF EXISTS product_order"); ExecuteSQL("DROP TABLE IF EXISTS customer"); @@ -681,8 +680,8 @@ public void ColumnSizeWithOldGuids() [Test] public void IsLongProperty() { - if (!Platform.IsWindows()) Assert.Ignore("This test is for Windows OS only."); - if (Version < new Version(5, 7, 6)) Assert.Ignore("This test is for MySql 5.7.6 or higher"); + Assume.That(Platform.IsWindows(), "This test is for Windows OS only."); + Assume.That(Version >= new Version(5, 7, 6), "This test is for MySql 5.7.6 or higher"); ExecuteSQL("Drop table if exists datatypes1"); ExecuteSQL("create table datatypes1(`longtext` longtext,`longblob` longblob)"); ExecuteSQL("insert into datatypes1 values('test', _binary'test')"); @@ -706,8 +705,8 @@ public void IsLongProperty() [Test] public void NumericPrecisionProperty() { - if (!Platform.IsWindows()) Assert.Ignore("This test is for Windows OS only."); - if (Version < new Version(5, 7, 6)) Assert.Ignore(); + Assume.That(Platform.IsWindows(), "This test is for Windows OS only."); + Assume.That(Version >= new Version(5, 7, 6), "This test is for MySql 5.7.6 or higher"); ExecuteSQL("Drop table if exists datatypes2"); ExecuteSQL("create table datatypes2(decimal0 decimal(8, 0))"); using (var cmd = Connection.CreateCommand()) @@ -744,7 +743,7 @@ public void GetSchemaReturnColumnsByOrdinalPosition() [Test, Description("Test to verify different variations in Generated Coloumns")] public void GeneratedColumnsVariations() { - if (Version < new Version(5, 7)) Assert.Ignore("This test is for MySql 5.7 or higher"); + Assume.That(Version >= new Version(5, 7, 0), "This test is for MySql 5.7 or higher"); using (var conn = new MySqlConnection(Settings.ConnectionString)) { diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MySQLHelperTests.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MySQLHelperTests.cs index c16d037f8..02ead71d3 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MySQLHelperTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MySQLHelperTests.cs @@ -48,7 +48,7 @@ protected override void Cleanup() [Test] public void EscapeStringMethodCanEscapeQuotationMark() { - if (!System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.Windows)) Assert.Ignore(); + Assume.That(System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.Windows)); ExecuteSQL("CREATE TABLE Test (id int NOT NULL, name VARCHAR(100))"); diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MySqlDataAdapterTests.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MySqlDataAdapterTests.cs index 0df4429a5..fa7802e05 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MySqlDataAdapterTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MySqlDataAdapterTests.cs @@ -564,7 +564,7 @@ public void SkippingRowsLargerThan1024() [Test] public void TestBatchingInserts() { - if (!System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.Windows)) Assert.Ignore(); + Assume.That(System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.Windows)); ExecuteSQL("CREATE TABLE Test (id INT, name VARCHAR(20), PRIMARY KEY(id))"); diff --git a/MySQL.Data/tests/MySql.Data.Tests/PoolingTests.cs b/MySQL.Data/tests/MySql.Data.Tests/PoolingTests.cs index 5e502aed6..bc638723a 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/PoolingTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/PoolingTests.cs @@ -659,7 +659,7 @@ public void MultipleConnectionWithPooling() [Test, Description("Verify the connection is not in CLOSE_WAIT state after failed connection due to Connection Limit")] public void CloseWaitScenario1() { - if (!Platform.IsWindows()) Assert.Ignore("This test is only for Windows OS"); + Assume.That(Platform.IsWindows(), "This test is only for Windows OS"); var poolSize = 5; var connectionString = $"server={Host};user={Settings.UserID};database={Settings.Database};port={Port};password={Settings.Password};Pooling=true;Max Pool Size={poolSize};SSL Mode=None;ConnectionTimeout=5"; List connectionList = new(); diff --git a/MySQL.Data/tests/MySql.Data.Tests/SslTests.cs b/MySQL.Data/tests/MySql.Data.Tests/SslTests.cs index 713fb3a99..4ff7c7a36 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/SslTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/SslTests.cs @@ -214,8 +214,7 @@ public void SslOverrided() [Property("Category", "Security")] public void TlsVersionTest(string tlsVersion, int error) { - if (error == 4 && Platform.IsMacOSX()) - Assert.Ignore(); + Assume.That(error != 4 || !Platform.IsMacOSX()); var builder = new MySqlConnectionStringBuilder(Connection.ConnectionString); void SetTlsVersion() { builder.TlsVersion = tlsVersion; } @@ -364,7 +363,7 @@ public void ConnectUsingPFXCertificates() public void InvalidCertificateThumbprint() { #if !NETFRAMEWORK - if (!System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.Windows)) Assert.Ignore(); + Assume.That(System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.Windows)); #endif // Create a mock of certificate store @@ -767,7 +766,7 @@ public void ShowVariablesRemoved() [Test] public void ConnectUsingCertificateFileAndTlsVersion() { - if (Version <= new Version(8, 0, 16)) Assert.Ignore("This test for MySql server 8.0.16 or higher"); + Assume.That(Version >= new Version(8, 0, 16), "This test for MySql server 8.0.16 or higher"); var builder = new MySqlConnectionStringBuilder(Settings.ConnectionString); builder.SslMode = MySqlSslMode.Required; builder.CertificateFile = "client.pfx"; @@ -802,8 +801,8 @@ public void ConnectUsingCertificateFileAndTlsVersion() [Test, Description("Classic-Scenario(correct ssl-ca,wrong ssl-key/ssl-cert,ssl-mode required and default)")] public void CorrectSslcaWrongSslkeySslcertRequiredMode() { - if (!Platform.IsWindows()) Assert.Ignore("This test is only for Windows OS"); - if (Version <= new Version(8, 0, 16)) Assert.Ignore("This test for MySql server 8.0.16 or higher"); + Assume.That(Platform.IsWindows(), "This test is only for Windows OS"); + Assume.That(Version >= new Version(8, 0, 16), "This test for MySql server 8.0.16 or higher"); string[] sslcertlist = new string[] { "", " ", null, "file", "file.pem" }; string[] sslkeylist = new string[] { "", " ", null, "file", "file.pem" }; for (int i = 0; i < sslcertlist.Length; i++) @@ -887,8 +886,8 @@ public void CorrectSslcaWrongSslkeySslcertRequiredMode() [Test, Description("Clasic-Scenario(correct ssl-ca,no ssl-key/ssl-cert,ssl-mode required and default)")] public void CorrectSslcaNoSslkeyorCertRequiredMode() { - if (!Platform.IsWindows()) Assert.Ignore("This test is only for Windows OS"); - if (Version <= new Version(8, 0, 16)) Assert.Ignore("This test for MySql server 8.0.16 or higher"); + Assume.That(Platform.IsWindows(), "This test is only for Windows OS"); + Assume.That(Version >= new Version(8, 0, 16), "This test for MySql server 8.0.16 or higher"); var connClassic = new MySqlConnectionStringBuilder(); connClassic.Server = Host; connClassic.Port = Convert.ToUInt32(Port); @@ -969,9 +968,9 @@ public void CorrectSslcaNoSslkeyorCertRequiredMode() [Test, Description("checking different versions of TLS versions")] public void SecurityTlsCheck() { - if (!Platform.IsWindows()) Assert.Ignore("This test is only for Windows OS"); - if (Version <= new Version(8, 0, 16)) Assert.Ignore("This test for MySql server 8.0.16 or higher"); - if (!ServerHaveSsl()) Assert.Ignore("Server doesn't have Ssl support"); + Assume.That(Platform.IsWindows(), "This test is only for Windows OS"); + Assume.That(Version >= new Version(8, 0, 16), "This test for MySql server 8.0.16 or higher"); + Assume.That(ServerHaveSsl(), "Server doesn't have Ssl support"); MySqlSslMode[] modes = { MySqlSslMode.Required, MySqlSslMode.VerifyCA, MySqlSslMode.VerifyFull }; String[] version; @@ -1010,8 +1009,8 @@ public void SecurityTlsCheck() [Test, Description("checking errors when invalid values are used ")] public void InvalidTlsversionValues() { - if (Version <= new Version(8, 0, 16)) Assert.Ignore("This test for MySql server 8.0.16 or higher"); - if (!ServerHaveSsl()) Assert.Ignore("Server doesn't have Ssl support"); + Assume.That(Version >= new Version(8, 0, 16), "This test for MySql server 8.0.16 or higher"); + Assume.That(ServerHaveSsl(), "Server doesn't have Ssl support"); string[] version = new string[] { "null", "v1", "[ ]", "[TLSv1.9]", "[TLSv1.1,TLSv1.7]", "ui9" };//blank space is considered as default value var conStr = $"server={Host};port={Port};userid={Settings.UserID};password={Settings.Password};SslCa={_sslCa};SslCert={_sslCert};SslKey={_sslKey};ssl-ca-pwd=pass"; @@ -1032,7 +1031,7 @@ public void InvalidTlsversionValues() [Test, Description("Default SSL user with SSL but without SSL Parameters")] public void SslUserWithoutSslParams() { - if (!ServerHaveSsl()) Assert.Ignore("Server doesn't have Ssl support"); + Assume.That(ServerHaveSsl(), "Server doesn't have Ssl support"); MySqlCommand cmd = new MySqlCommand(); string connstr = $"server={Host};user={Settings.UserID};port={Port};password={Settings.Password};sslmode={MySqlSslMode.Disabled}"; using (var c = new MySqlConnection(connstr)) @@ -1056,8 +1055,8 @@ public void SslUserWithoutSslParams() [Test] public void PositiveSslConnectionWithCertificates() { - if (Version < new Version(5, 7, 0)) Assert.Ignore("This test is for MySql Server 5.7 or higher"); - if (!ServerHaveSsl()) Assert.Ignore("Server doesn't have Ssl support"); + Assume.That(Version >= new Version(5, 7, 0), "This test for MySql server 5.7 or higher"); + Assume.That(ServerHaveSsl(), "Server doesn't have Ssl support"); MySqlCommand cmd = new MySqlCommand(); var connStr = $"server={Host};port={Port};user={Settings.UserID};password={Settings.Password};CertificateFile={_sslCa};CertificatePassword=pass;SSL Mode=Required;"; diff --git a/MySQL.Data/tests/MySql.Data.Tests/StoredProcedure.cs b/MySQL.Data/tests/MySql.Data.Tests/StoredProcedure.cs index 8a96eafd1..bb02fef1a 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/StoredProcedure.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/StoredProcedure.cs @@ -746,7 +746,6 @@ public void DeriveParameters() [Test] public void ProcedureCacheMiss() { - if (Version.Major == new Version(5, 7, 43).Major && Version.Minor == new Version(5, 7, 43).Minor) Assert.Ignore("Test temporaly deactivated for MySQL Server version 5.7.x due to a possible bug"); ExecuteSQL("CREATE PROCEDURE spTest(id INT) BEGIN SELECT 1; END"); @@ -932,7 +931,7 @@ public void VerifyParametersType() [Test] public void PassJsonParameter() { - if (Version < new Version(5, 7, 8)) Assert.Ignore("JSON data type was included in MySQL Server from v5.7.8"); + Assume.That(Version >= new Version(5, 7, 8), "JSON data type was included in MySQL Server from v5.7.8"); ExecuteSQL("CREATE TABLE Test(jsonValue json NOT NULL)"); ExecuteSQL("CREATE PROCEDURE spTest(IN p_jsonValue JSON) BEGIN INSERT INTO Test VALUES(p_jsonValue); END"); @@ -1045,7 +1044,7 @@ public void PassEnumParameter() [Test] public void EventsStatementsHistory() { - if (Version < new Version(8, 0, 0)) Assert.Ignore("This test is for MySql 8.0 or higher"); + Assume.That(Version >= new Version(8, 0, 0), "This test is for MySql 8.0 or higher"); bool testResult = false; var spName = "spGetCount"; var cmd = new MySqlCommand(" show variables like 'general_log'", Connection); @@ -1053,7 +1052,7 @@ public void EventsStatementsHistory() { while (rdr.Read()) { - if (rdr.GetString(1) != "ON") Assert.Ignore("general_log is disabled"); + Assume.That(rdr.GetString(1) == "ON", "general_log is disabled"); } } diff --git a/MySQL.Data/tests/MySql.Data.Tests/Syntax.cs b/MySQL.Data/tests/MySql.Data.Tests/Syntax.cs index 9b27c98ff..282317497 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Syntax.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Syntax.cs @@ -534,7 +534,7 @@ public void QueryNormalizerCrash2() public void TokenizerBatching() { #if !NETFRAMEWORK - if (!System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.Windows)) Assert.Ignore(); + Assume.That(System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.Windows)); #endif ExecuteSQL("CREATE TABLE Test (id INT, expr INT,name VARCHAR(20), PRIMARY KEY(id))"); diff --git a/MySQL.Data/tests/MySql.Data.Tests/Transactions.cs b/MySQL.Data/tests/MySql.Data.Tests/Transactions.cs index 585875433..0ac8a5152 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Transactions.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Transactions.cs @@ -253,7 +253,7 @@ public void EnlistTransactionWNestedTrxTest() public void ManualEnlistment() { #if !NETFRAMEWORK - if (!System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.Windows)) Assert.Ignore(); + Assume.That(System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.Windows)); #endif ExecuteSQL("DROP TABLE IF EXISTS Test"); ExecuteSQL("CREATE TABLE Test (key2 VARCHAR(1), name VARCHAR(100), name2 VARCHAR(100))"); @@ -567,7 +567,7 @@ public void ReusingSameConnectionTest() public void ScopeTimeoutWithMySqlHelper() { #if !NETFRAMEWORK - if (!System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.Windows)) Assert.Ignore(); + Assume.That(System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.Windows)); #endif ExecuteSQL("DROP TABLE IF EXISTS Test"); ExecuteSQL("CREATE TABLE Test (id int)"); diff --git a/MySQL.Data/tests/MySql.Data.Tests/UnixSockets.cs b/MySQL.Data/tests/MySql.Data.Tests/UnixSockets.cs index 3499e1f32..7d70267cd 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/UnixSockets.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/UnixSockets.cs @@ -42,11 +42,7 @@ public void ConnectionTest() { string unixConnectionString = $"server={UnixSocket};user={Settings.UserID};password={Settings.Password};protocol=unix;"; - if (Platform.IsWindows()) - { - Console.Error.WriteLine($"{nameof(ConnectionTest)} ignored because it's a Windows system."); - Assert.Ignore(); - } + Assume.That(!Platform.IsWindows()); using (MySqlConnection conn = new MySqlConnection(unixConnectionString)) { diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/BasicFindTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/BasicFindTests.cs index d04d0e200..df3f15a85 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/BasicFindTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/BasicFindTests.cs @@ -207,7 +207,7 @@ public void BindJsonAsString() [Test] public void RowLockingNotSupportedInOlderVersions() { - if (session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql lower than 8.0.3."); + Assume.That(!session.Version.isAtLeast(8, 0, 3), "This test is for MySql lower than 8.0.3."); Collection coll = CreateCollection("test"); Exception ex = Assert.Throws(() => ExecuteFindStatement(coll.Find().LockShared())); @@ -220,7 +220,7 @@ public void RowLockingNotSupportedInOlderVersions() [Test] public void SimpleSharedLock() { - if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 3), "This test is for MySql 8.0.3 or higher"); ExecuteSQLStatement(session.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); using (var session2 = MySQLX.GetSession(ConnectionString)) @@ -256,7 +256,7 @@ public void SimpleSharedLock() [Test] public void SharedLockForbidsToModifyDocuments() { - if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 3), "This test is for MySql 8.0.3 or higher"); ExecuteSQLStatement(session.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); using (var session2 = MySQLX.GetSession(ConnectionString)) @@ -299,7 +299,7 @@ public void SharedLockForbidsToModifyDocuments() [Test] public void ExclusiveLockForbidsToModifyDocuments() { - if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 3), "This test is for MySql 8.0.3 or higher"); ExecuteSQLStatement(session.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); using (var session2 = MySQLX.GetSession(ConnectionString)) @@ -341,7 +341,7 @@ public void ExclusiveLockForbidsToModifyDocuments() [Test] public void SharedLockAfterExclusiveLock() { - if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 3), "This test is for MySql 8.0.3 or higher"); ExecuteSQLStatement(session.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); using (var session2 = MySQLX.GetSession(ConnectionString)) @@ -383,7 +383,7 @@ public void SharedLockAfterExclusiveLock() [Test] public void ExclusiveLockAfterSharedLock() { - if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 3), "This test is for MySql 8.0.3 or higher"); ExecuteSQLStatement(session.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); using (var session2 = MySQLX.GetSession(ConnectionString)) @@ -426,7 +426,7 @@ public void ExclusiveLockAfterSharedLock() [Test] public void ExclusiveLockAfterExclusiveLock() { - if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 3), "This test is for MySql 8.0.3 or higher"); ExecuteSQLStatement(session.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); using (var session2 = MySQLX.GetSession(ConnectionString)) @@ -467,7 +467,7 @@ public void ExclusiveLockAfterExclusiveLock() [Test] public void InOperatorWithListOfValues() { - if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 3), "This test is for MySql 8.0.3 or higher"); // Validates the IN operator allows expressions of the type // ( compExpr ["NOT"] "IN" "(" argsList ")" ) | ( compExpr ["NOT"] "IN" "[" argsList "]" ) @@ -523,7 +523,7 @@ public void InOperatorWithListOfValues() [Test] public void InOperatorWithCompExpr() { - if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 3), "This test is for MySql 8.0.3 or higher"); // Validates the IN operator allows expressions of the type: compExpr ["NOT"] "IN" compExpr Collection coll = CreateCollection("test"); @@ -561,7 +561,7 @@ public void InOperatorWithCompExpr() [Test] public void InOperatorWithJsonArrays() { - if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 3), "This test is for MySql 8.0.3 or higher"); Collection coll = CreateCollection("test"); var docString = "{ \"_id\": \"1001\", \"ARR\":[1,2,3], \"ARR1\":[\"name\", \"name2\", \"name3\"]}"; @@ -620,7 +620,7 @@ public enum LockMode { Exclusive, Shared } [TestCase(LockContention.SkipLocked, LockMode.Shared)] public void LockExclusiveAndSharedWithWaitingOptions(LockContention lockOption, LockMode lockMode) { - if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher."); + Assume.That(session.Version.isAtLeast(8, 0, 3), "This test is for MySql 8.0.3 or higher"); string collectionName = "test"; var coll = CreateCollection(collectionName); @@ -1301,7 +1301,7 @@ public void FindWithManyConditions() [Test, Description("Reading exclusively locked anonymous object array using LockShared without waiting option. ")] public void ExclusiveLocksAndCommit(int scenario) { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 11), "This test is for MySql 8.0.11 or higher"); ExecuteSQLStatement(session.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); using (var session2 = MySQLX.GetSession(ConnectionString)) @@ -1371,7 +1371,7 @@ public void ExclusiveLocksAndCommit(int scenario) [Test, Description("Reading a document which was locked using lock_shared without waiting option")] public void SharedLockAndCommit(LockMode? lockMode) { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 11), "This test is for MySql 8.0.11 or higher"); ExecuteSQLStatement(session.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); using (var session2 = MySQLX.GetSession(ConnectionString)) { @@ -1431,7 +1431,7 @@ public void SharedLockAndCommit(LockMode? lockMode) [Test, Description("Reading a document using lock_shared using SKIPLOCK and NOWAIT options with CRUD operations happening parallely.")] public void SharedAndExclusiveLockWithSkipAndNoWait(LockMode lockMode) { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 11), "This test is for MySql 8.0.11 or higher"); ExecuteSQLStatement(session.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); using (var session2 = MySQLX.GetSession(ConnectionString)) { @@ -1478,7 +1478,7 @@ public void SharedAndExclusiveLockWithSkipAndNoWait(LockMode lockMode) [Test, Description("Multiple lock calls using NOWAIT and SKIPLOCK waiting option. ")] public void MultipleLocksWithNowaitAndSkiplock() { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 11), "This test is for MySql 8.0.11 or higher"); ExecuteSQLStatement(session.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); using (var session2 = MySQLX.GetSession(ConnectionString)) { @@ -1521,7 +1521,7 @@ public void MultipleLocksWithNowaitAndSkiplock() [Test, Description("Reading multiple rows in a locked document(lock_shared) using SKIPLOCK and NOWAIT ")] public void LockSharedMultipleReads() { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 11), "This test is for MySql 8.0.11 or higher"); ExecuteSQLStatement(session.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); using (var session2 = MySQLX.GetSession(ConnectionString)) { @@ -1562,7 +1562,7 @@ public void LockSharedMultipleReads() [Test, Description("Reading multiple rows in an exclusively locked document using SKIPLOCK and NOWAIT ")] public void LockExclusiveMultipleReads() { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 11), "This test is for MySql 8.0.11 or higher"); ExecuteSQLStatement(session.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); using (var session2 = MySQLX.GetSession(ConnectionString)) { @@ -1600,7 +1600,7 @@ public void LockExclusiveMultipleReads() [Test, Description("Collection.Find() with shared lock and Collection.Modify() normal from two sessions. ")] public void LockSharedAndModify() { - if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 3), "This test is for MySql 8.0.3 or higher"); ExecuteSQLStatement(session.SQL("SET autocommit = 0")); using (var session2 = MySQLX.GetSession(ConnectionString)) { @@ -1640,7 +1640,7 @@ public void LockSharedAndModify() [Test, Description("Collection.Find() with shared lock from two sessions. ")] public void LockSharedTwoSessions() { - if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 3), "This test is for MySql 8.0.3 or higher"); ExecuteSQLStatement(session.SQL("SET autocommit = 0")); using (var session2 = MySQLX.GetSession(ConnectionString)) { @@ -1677,7 +1677,7 @@ public void LockSharedTwoSessions() [Test, Description("Collection.Find() with exclusive lock and Collection.Find() with shared lock from two sessions. ")] public void LockExclusiveFindAndLockSharedFind() { - if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 3), "This test is for MySql 8.0.3 or higher"); ExecuteSQLStatement(session.SQL("SET autocommit = 0")); using (var session2 = MySQLX.GetSession(ConnectionString)) { @@ -1719,7 +1719,7 @@ public void LockExclusiveFindAndLockSharedFind() [Test, Description("Collection.Find() with shared lock and Collection.Find() with exclusive lock from two sessions. ")] public void LockSharedFindAndExclusiveLocks() { - if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 3), "This test is for MySql 8.0.3 or higher"); ExecuteSQLStatement(session.SQL("SET autocommit = 0")); using (var session2 = MySQLX.GetSession(ConnectionString)) { @@ -1766,7 +1766,7 @@ public void LockSharedFindAndExclusiveLocks() [Test, Description("Collection.Find() with exclusive lock and Collection.Find() with exclusive lock from two sessions. ")] public void LockExclusiveWithRollback() { - if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 3), "This test is for MySql 8.0.3 or higher"); ExecuteSQLStatement(session.SQL("SET autocommit = 0")); using (var session2 = MySQLX.GetSession(ConnectionString)) { @@ -1810,7 +1810,7 @@ public void LockExclusiveWithRollback() [Test, Description("Collection.Find() with exclusive lock and Collection.Find() with exclusive lock from two sessions--Select multiple records ")] public void LockExclusiveWithINSelection() { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 11), "This test is for MySql 8.0.11 or higher"); ExecuteSQLStatement(session.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); using (var session2 = MySQLX.GetSession(ConnectionString)) { @@ -1853,7 +1853,7 @@ public void LockExclusiveWithINSelection() [Test, Description("Collection.Find() with shared lock twice ")] public void LockSharedReadTwice() { - if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 3), "This test is for MySql 8.0.3 or higher"); ExecuteSQLStatement(session.SQL("SET autocommit = 0")); using (var session2 = MySQLX.GetSession(ConnectionString)) { @@ -1893,8 +1893,8 @@ public void LockSharedReadTwice() [Test, Description("Test MySQLX plugin Collection Array or Object contains operator Scenarios-1")] public void FindInJsonObjects() { - if (!Platform.IsWindows()) Assert.Ignore("This test is for Windows OS only"); - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher."); + Assume.That(Platform.IsWindows(), "This test is for Windows OS only"); + Assume.That(session.Version.isAtLeast(8, 0, 11), "This test is for MySql 8.0.11 or higher"); var col = CreateCollection("my_collection_1"); string json = @"{ ""_id"": 0, ""title"": ""Book 0"" ,""pages"": 10,""name"": ""Jeoff Archer""}"; @@ -2004,7 +2004,7 @@ public void FindInJsonObjects() [Test, Description("Test MySQLX plugin Collection Array or Object contains operator Scenarios-3")] public void FindAndCountJsonValues() { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher."); + Assume.That(session.Version.isAtLeast(8, 0, 11), "This test is for MySql 8.0.11 or higher"); var col = CreateCollection("my_collection_1"); Result add; @@ -2039,7 +2039,7 @@ public void FindAndCountJsonValues() [Test, Description("Test MySQLX plugin Collection Array or Object contains operator Scenarios-4")] public void CheckCountAfterSort() { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher."); + Assume.That(session.Version.isAtLeast(8, 0, 11), "This test is for MySql 8.0.11 or higher"); var coll = CreateCollection("test"); coll.Add("{ \"name\": \"abcdefghijk\", \"age\": 1 , \"misc\": 1.2}") .Add("{ \"name\": \"xyz\", \"age\": 6 , \"misc\": 19.59}").Execute(); @@ -2056,7 +2056,7 @@ public void CheckCountAfterSort() [Test, Description("Test MySQLX plugin Find with overlap Bugs")] public void FindUsingOverLapsBug() { - if (!session.Version.isAtLeast(8, 0, 17)) Assert.Ignore("This test is for MySql 8.0.17 or higher."); + Assume.That(session.Version.isAtLeast(8, 0, 17), "This test is for MySql 8.0.17 or higher"); String json = ""; String[] splName = { "+", "*", "/", "a+b", "#1", "%", "&", "@1", "!1", "~", "^", "(", ")", "{", "}", "[", "]", "|", "JSON", "ADD", "JSON_EXTRACT", "JSON_OBJECT", @@ -2133,7 +2133,7 @@ public void FindUsingOverLapsBug() [Test, Description("Test MySQLX plugin Find with overlap and Many conditions")] public void FindUsingOverLapsManyConditions() { - if (!session.Version.isAtLeast(8, 0, 17)) Assert.Ignore("This test is for MySql 8.0.17 or higher."); + Assume.That(session.Version.isAtLeast(8, 0, 17), "This test is for MySql 8.0.17 or higher"); int Condition = 45; int i, j = 0; String query = ""; @@ -2255,7 +2255,7 @@ public void CollectionFindFieldMatchingCount() [Test, Description("GetName,Schema and Count")] public void CollectionGetNameSchemaCount() { - if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher"); + Assume.That(session.Version.isAtLeast(5, 7, 0), "This test is for MySql 5.7 or higher"); var col = CreateCollection("my_collection_123456789"); Result r = col.Add(@"{ ""_id"": 1, ""foo"": 1 }").Execute(); diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/CharsetAndCollationTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/CharsetAndCollationTests.cs index be95bf4c2..3bb644245 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/CharsetAndCollationTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/CharsetAndCollationTests.cs @@ -227,7 +227,7 @@ public void NamesAreReturnedAsStrings() [Test, Description("Column Default Datatypes")] public void ColumnDefaultDatatypes() { - if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 3), "This test is for MySql 8.0.3 or higher"); session.SQL($"USE {schemaName}").Execute(); session.SQL("Drop table if exists address").Execute(); session.SQL("CREATE TABLE address" + @@ -327,7 +327,7 @@ public void ColumnDefaultDatatypes() [Test, Description("Column Custom Datatypes(Unsigned,Padded,CharacterSet,Collation)")] public void ColumnCustomDatatypes() { - if (!session.Version.isAtLeast(8, 0, 14)) Assert.Ignore("This test is for MySql 8.0.14 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 14), "This test is for MySql 8.0.14 or higher"); var defaultCharset = "utf8mb4"; session.SQL($"USE {schemaName}").Execute(); session.SQL("CREATE TABLE IF NOT EXISTS address" + @@ -426,7 +426,7 @@ public void ColumnCustomDatatypes() [Test, Description("Column Join Two tables")] public void ColumnJoin() { - if (!session.Version.isAtLeast(8, 0, 14)) Assert.Ignore("This test is for MySql 8.0.14 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 14), "This test is for MySql 8.0.14 or higher"); var defaultCharset = "utf8mb4"; session.SQL($"USE {schemaName}").Execute(); session.SQL("CREATE TABLE address1" + @@ -718,7 +718,7 @@ public void ColumnCharacterDefaultDatatype() [Test, Description("Column Character Custom Datatype")] public void ColumnCharacterCustomDatatype() { - if (!session.Version.isAtLeast(8, 0, 14)) Assert.Ignore("This test is for MySql 8.0.14 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 14), "This test is for MySql 8.0.14 or higher"); var defaultCharset = "utf8mb4"; session.SQL($"USE {schemaName}").Execute(); session.SQL("Drop table if exists address").Execute(); @@ -781,7 +781,7 @@ public void ColumnCharacterCustomDatatype() [Test, Description("Column Geometric Datatypes")] public void ColumnCharacterGeometricDatatype() { - if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 3), "This test is for MySql 8.0.3 or higher"); session.SQL($"USE {schemaName}").Execute(); session.SQL($"drop table if exists geotest").Execute(); session.SQL("CREATE TABLE geotest (g GEOMETRY,p POINT,l LINESTRING,po POLYGON,mp MULTIPOINT,ml MULTILINESTRING,mpo MULTIPOLYGON,gc GEOMETRYCOLLECTION);").Execute(); @@ -819,7 +819,7 @@ public void ColumnCharacterGeometricDatatype() [Test, Description("Column Blob Datatype")] public void ColumnCharacterBlobDatatype() { - if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 3), "This test is for MySql 8.0.3 or higher"); session.SQL($"USE {schemaName}").Execute(); session.SQL($"drop table if exists geotest").Execute(); @@ -862,7 +862,7 @@ public void ColumnCharacterBlobDatatype() [Test, Description("Verify that different language specific collations are availabe for charset utf8mb4 when server version is 8.0 or greater")] public void LanguageSpecificCollations() { - if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 3), "This test is for MySql 8.0.3 or higher"); var charset = "utf8mb4"; string[] collationname = { @@ -908,7 +908,7 @@ public void LanguageSpecificCollations() [Test] public void VerifyRenamedCollations() { - if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 3), "This test is for MySql 8.0.3 or higher"); var charset = "utf8mb3"; var collation = session.Version.isAtLeast(8, 0, 30) ? "utf8mb3" : "utf8"; @@ -957,7 +957,7 @@ public void VerifyRenamedCollations() [Test, Description("Verify default charset and collation")] public void VerifyLatinCharsetAndCollation() { - if (!session.Version.isAtLeast(8, 0, 14)) Assert.Ignore("This test is for MySql 8.0.14 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 14), "This test is for MySql 8.0.14 or higher"); var database_name = "collation_test"; var charset = "latin1"; var collationname = "latin1_danish_ci"; @@ -981,8 +981,8 @@ public void VerifyLatinCharsetAndCollation() [Test, Description("Create table/db with collation utf8mb4_0900_bin and insert non ascii characters and fetch data")] public void Utf8mb4BinaryNopadCollationTable() { - if (!Platform.IsWindows()) Assert.Ignore("This test is for Windows OS only."); - if (!_serverVersion.isAtLeast(8, 0, 17)) Assert.Ignore("This test is for MySql 8.0.17 or higher"); + Assume.That(Platform.IsWindows(), "This test is for Windows OS only."); + Assume.That(session.Version.isAtLeast(8, 0, 17), "This test is for MySql 8.0.17 or higher"); char t_char; var charset = "utf8mb4"; var collation = "utf8mb4_0900_ai_ci"; diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/ClientSideFailoverTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/ClientSideFailoverTests.cs index d3c8d0ceb..34834ca26 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/ClientSideFailoverTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/ClientSideFailoverTests.cs @@ -454,7 +454,7 @@ public void PriorityMethodWithAnonymousTypes() [Test, Description("Test MySQLX Client Side Failover(Implicit Failover -Not supported)")] public void ImplicitFailover() { - if (!session.Version.isAtLeast(8, 0, 8)) Assert.Ignore("This test is for MySql 8.0.8 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 8), "This test is for MySql 8.0.8 or higher"); MySqlXConnectionStringBuilder sb = new MySqlXConnectionStringBuilder(ConnectionString); string ipV6Address = GetIPV6Address(); string connectionString = $"mysqlx://test:test@[{sb.Server},{Host},{ipV6Address}:{sb.Port}]?implicit-failover"; @@ -464,7 +464,7 @@ public void ImplicitFailover() [Test, Description("Provide 101 hosts to connection without priority where 1st 100 hosts are invalid ones(Internal priority is set from 100...0) and the last host is valid")] public void ManyInvalidHost() { - if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher"); + Assume.That(session.Version.isAtLeast(5, 7, 0), "This test is for MySql 5.7 or higher"); var connectionTimeout = 1; MySqlXConnectionStringBuilder sb = new MySqlXConnectionStringBuilder(ConnectionString); @@ -540,7 +540,7 @@ public void ManyInvalidHost() [Test, Description("Provide two hosts to connection with priority where both are valid")] public void TwoValidHost() { - if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher"); + Assume.That(session.Version.isAtLeast(5, 7, 0), "This test is for MySql 5.7 or higher"); MySqlXConnectionStringBuilder sb = new MySqlXConnectionStringBuilder(ConnectionString); var connStr = $"mysqlx://test:test@[ (address={Host}:{XPort}, priority=0,address={Host}:{XPort}, priority=100)]?ssl-mode=Required"; @@ -575,7 +575,7 @@ public void TwoValidHost() [Test, Description("Provide two hosts to connection with priority where both are valid-with default port")] public void TwoValidHostWithDefaultPort() { - if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher"); + Assume.That(session.Version.isAtLeast(5, 7, 0), "This test is for MySql 5.7 or higher"); MySqlXConnectionStringBuilder sb = new MySqlXConnectionStringBuilder(ConnectionString); var connStr = "mysqlx://test:test" + @@ -609,7 +609,7 @@ public void TwoValidHostWithDefaultPort() [Test, Description("Provide a single host to connection with priority and disconnect and connect again(iterate priority from 0 - 100) ")] public void IteratedPriority() { - if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher"); + Assume.That(session.Version.isAtLeast(5, 7, 0), "This test is for MySql 5.7 or higher"); var connectionTimeout = 900; // Automatically set priority if no priority is given. @@ -662,7 +662,7 @@ public void IteratedPriority() [Test, Description("Provide a single host to connection with priority with SSL")] public void PriorityWithSsl() { - if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher"); + Assume.That(session.Version.isAtLeast(5, 7, 0), "This test is for MySql 5.7 or higher"); var certificatePassword = "pass"; var certificatewrongPassword = "wrongpass"; diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/ClientTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/ClientTests.cs index 895fc3c1c..f56f03b76 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/ClientTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/ClientTests.cs @@ -264,7 +264,7 @@ public void PoolingTest(PoolingTestData poolingTestData) [Property("Category", "Security")] public void QueueTimeoutTest() { - if (Platform.IsWindows()) Assert.Ignore("Fix this for Windows OS"); + Assume.That(!Platform.IsWindows(), "Fix this for Windows OS"); int timeout = 3000; using (Client client = MySQLX.GetClient(ConnectionString, new { pooling = new { maxSize = 1, queueTimeout = timeout } })) { @@ -427,7 +427,7 @@ private void ResetTestAfterClose(Session session, int threadId, int id) [Property("Category", "Security")] public void ConnectionAttributes() { - if (!(session.Version.isAtLeast(8, 0, 16))) Assert.Ignore("This test is for MySql 8.0.16 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 16), "This test is for MySql 8.0.16 or higher"); // Validate that MySQLX.GetSession() supports a new 'connection-attributes' query parameter // with default values and all the client attributes starts with a '_'. @@ -817,7 +817,7 @@ public void maxIdleTimeOptionTests(string inputType) [Test, Description("Test queueTimeout with different values")] public void QueueTimeoutOptionTests(string inputType) { - if (Platform.IsWindows()) Assert.Ignore("Fix this for Windows OS"); + Assume.That(!Platform.IsWindows(), "Fix this for Windows OS"); int timeoutMS = 3000; string[] connectionpooling = { "{ \"pooling\": { \"maxSize\": 2,\"queueTimeout\": " + timeoutMS + " } }", "{ \"pooling\": { \"queueTimeout\": true} }", "{ \"pooling\": { \"queueTimeout\": 'true'} }", "{ \"pooling\": { \"queueTimeout\": -1} }", "{ \"pooling\": { \"queueTimeout\": 84584759345 } }", "{ \"pooling\": { \"queueTimeout\": } }" }; @@ -1424,7 +1424,7 @@ public void SessionResetConnectionState() [Test, Description("MAX LENGTH OF KEY VALUE PAIR OF USER DEFINED CONNECTION ATTRIBUTES")] public void ConnectionAttributesLongValue() { - if (!(session.Version.isAtLeast(8, 0, 16))) Assert.Ignore("This test is for MySql 8.0.16 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 16), "This test is for MySql 8.0.16 or higher"); var serverSupportedSize = Convert.ToInt32(session.SQL("select @@Global.performance_schema_session_connect_attrs_size;").Execute().First()[0]); var connectAttributesLost = Convert.ToInt32(session.SQL("SHOW STATUS LIKE 'Performance_schema_session_connect_attrs_lost'").Execute().FirstOrDefault()[1]); @@ -1473,7 +1473,7 @@ public void ConnectionAttributesLongValue() [Test, Description("GETSESSION THROWS EXCEPTION WHEN EQUAL IS USED AS PARAM FOR CONN ATTRIBUTE IN CONN ANONYMOUS OBJECT-WL#12514")] public void GetSessionExceptionWithConnetionAttribute() { - if (!(session.Version.isAtLeast(8, 0, 16))) Assert.Ignore("This test is for MySql 8.0.16 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 16), "This test is for MySql 8.0.16 or higher"); MySqlXConnectionStringBuilder sb = new MySqlXConnectionStringBuilder(ConnectionString); using (Client client = MySQLX.GetClient(new { server = sb.Server, port = XPort, user = sb.UserID, password = sb.Password, ConnectionAttributes = "=" } , "{ \"pooling\": { \"enabled\": true } }")) @@ -1486,8 +1486,8 @@ public void GetSessionExceptionWithConnetionAttribute() [Test, Description("Connection Attributes with arrays")] public void ConnectionAttributesWithArrays() { - if (!Platform.IsWindows()) Assert.Ignore("This test is for Windows OS only"); - if (!(session.Version.isAtLeast(8, 0, 16))) Assert.Ignore("This test is for MySql 8.0.16 or higher"); + Assume.That(Platform.IsWindows(), "This test is for Windows OS only."); + Assume.That(session.Version.isAtLeast(8, 0, 16), "This test is for MySql 8.0.16 or higher"); object[] arrayCases = new object[] { "[var1 = 1, 2, 3]", "[var1 = { 1, 2, 3}]" }; for (int i = 0; i < arrayCases.Length; i++) @@ -1576,7 +1576,7 @@ public void ConnectionAttributesWithArrays() [Test] public void NormalConnectionWithUri() { - if (!(session.Version.isAtLeast(8, 0, 16))) Assert.Ignore("This test is for MySql 8.0.16 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 16), "This test is for MySql 8.0.16 or higher"); //Normal connection with URI using (Client client = MySQLX.GetClient(ConnectionStringUri, "{ \"pooling\": { \"enabled\": true } }")) { @@ -1591,7 +1591,7 @@ public void NormalConnectionWithUri() [Ignore("Bug #33234243 need to fix Uri scenario")] public void ConnectionAttributesRepeated() { - if (!(session.Version.isAtLeast(8, 0, 16))) Assert.Ignore("This test is for MySql 8.0.16 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 16), "This test is for MySql 8.0.16 or higher"); //Connection String Assert.Catch(() => MySQLX.GetClient(ConnectionString + ";connection-attributes=true;connection-attributes=true;", "{ \"pooling\": { \"enabled\": true } }")); Assert.Catch(() => MySQLX.GetSession(ConnectionString + ";connection-attributes=true;connection-attributes=true;")); @@ -1603,7 +1603,7 @@ public void ConnectionAttributesRepeated() [Test, Description("Connection Attributes with key Repeated - Extending scenarios in ConnectionAttributes()")] public void ConnectionAttributesKeyRepeatedChars() { - if (!(session.Version.isAtLeast(8, 0, 16))) Assert.Ignore("This test is for MySql 8.0.16 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 16), "This test is for MySql 8.0.16 or higher"); var expectedMsg = string.Format(ResourcesX.DuplicateUserDefinedAttribute, "quua"); //Connection String using (Client client = MySQLX.GetClient(ConnectionString + ";connection-attributes=[quua=bar,quua=qux,key]", "{ \"pooling\": { \"enabled\": true } }")) @@ -1674,7 +1674,7 @@ public void ConnectionAttributesKeyRepeatedChars() [Test, Description("Connection Attributes with key 33 characters - Extending scenarios in ConnectionAttributes()")] public void ConnectionAttributesWithKey33Chars() { - if (!(session.Version.isAtLeast(8, 0, 16))) Assert.Ignore("This test is for MySql 8.0.16 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 16), "This test is for MySql 8.0.16 or higher"); var errorMsg = "Key name beginning with 'foo32foo32foo32foo32foo32foo3232'... is too long, currently limited to 32"; using (Client client = MySQLX.GetClient(ConnectionString + ";connection-attributes=[foo32foo32foo32foo32foo32foo32323=bar,quua=qux,key]", "{ \"pooling\": { \"enabled\": true } }")) { @@ -1741,7 +1741,7 @@ public void ConnectionAttributesWithKey33Chars() [Test, Description("Connection Attributes with invalid combinations - Extending scenarios in ConnectionAttributes()")] public void ConnectionAttributesInvalidCombinations() { - if (!(session.Version.isAtLeast(8, 0, 16))) Assert.Ignore("This test is for MySql 8.0.16 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 16), "This test is for MySql 8.0.16 or higher"); object[] invalid = new object[] { "var1", "1", "2", "(var1)", "{var1}", "[_testValue = test123, emptyValue]" }; var errorMsgs = new string[] { @"The value of ""connection-attributes"" must be either a boolean or a list of key-value pairs.", @"Key names in ""connection-attributes"" cannot start with ""_""." }; for (int i = 0; i < invalid.Length; i++) @@ -1817,8 +1817,8 @@ public void ConnectionAttributesInvalidCombinations() [Test, Description("Connection Attributes with valid combinations - Extending scenarios in ConnectionAttributes()")] public void ConnectionAttributesValidCombinations() { - if (!Platform.IsWindows()) Assert.Ignore("This test is for Windows OS only"); - if (!(session.Version.isAtLeast(8, 0, 16))) Assert.Ignore("This test is for MySql 8.0.16 or higher"); + Assume.That(Platform.IsWindows(), "This test is for Windows OS only."); + Assume.That(session.Version.isAtLeast(8, 0, 16), "This test is for MySql 8.0.16 or higher"); object[] invalid = new object[] { "[var1 = 1]" }; for (int i = 0; i < invalid.Length; i++) @@ -1905,9 +1905,9 @@ public void ConnectionAttributesValidCombinations() [Test, Description("Connection Attributes with key special characters - Extending scenarios in ConnectionAttributes()")] public void ConnectionAttributesKeySpecialChars() { + Assume.That(Platform.IsWindows(), "This test is for Windows OS only."); + Assume.That(session.Version.isAtLeast(8, 0, 16), "This test is for MySql 8.0.16 or higher"); MySqlXConnectionStringBuilder sb = new MySqlXConnectionStringBuilder(ConnectionString); - if (!Platform.IsWindows()) Assert.Ignore("This test is for Windows OS only"); - if (!(session.Version.isAtLeast(8, 0, 16))) Assert.Ignore("This test is for MySql 8.0.16 or higher"); using (Client client = MySQLX.GetClient(ConnectionString + ";connection-attributes=[@#$%^&* %^()=bar,quua=*(&^&#$%,key]", "{ \"pooling\": { \"enabled\": true } }")) { using (Session session = client.GetSession()) @@ -1989,8 +1989,8 @@ public void ConnectionAttributesKeySpecialChars() [Test, Description("Connection Attributes with key with underline characters - Extending scenarios in ConnectionAttributes()")] public void ConnectionAttributesKeyWithUnderLineChars() { - if (!Platform.IsWindows()) Assert.Ignore("This test is for Windows OS only"); - if (!(session.Version.isAtLeast(8, 0, 16))) Assert.Ignore("This test is for MySql 8.0.16 or higher"); + Assume.That(Platform.IsWindows(), "This test is for Windows OS only."); + Assume.That(session.Version.isAtLeast(8, 0, 16), "This test is for MySql 8.0.16 or higher"); MySqlXConnectionStringBuilder sb = new MySqlXConnectionStringBuilder(ConnectionString); var expectedMsg = @"Key names in ""connection-attributes"" cannot start with ""_""."; //Connection string @@ -2058,8 +2058,8 @@ public void ConnectionAttributesKeyWithUnderLineChars() [Test, Description("Connection Attributes with key blank characters - Extending scenarios in ConnectionAttributes()")] public void ConnectionAttributesKeyBlankChars() { - if (!Platform.IsWindows()) Assert.Ignore("This test is for Windows OS only"); - if (!(session.Version.isAtLeast(8, 0, 16))) Assert.Ignore("This test is for MySql 8.0.16 or higher"); + Assume.That(Platform.IsWindows(), "This test is for Windows OS only."); + Assume.That(session.Version.isAtLeast(8, 0, 16), "This test is for MySql 8.0.16 or higher"); MySqlXConnectionStringBuilder sb = new MySqlXConnectionStringBuilder(ConnectionString); var expectedMsg = "Key name in connection attribute cannot be an empty string."; //Connection String @@ -2130,8 +2130,8 @@ public void ConnectionAttributesKeyBlankChars() [Test, Description("Connection Attributes with value 1025characters - Extending scenarios in ConnectionAttributes()")] public void ConnectionAttributesValue1025Chars() { - if (!Platform.IsWindows()) Assert.Ignore("This test is for Windows OS only"); - if (!(session.Version.isAtLeast(8, 0, 16))) Assert.Ignore("This test is for MySql 8.0.16 or higher"); + Assume.That(Platform.IsWindows(), "This test is for Windows OS only."); + Assume.That(session.Version.isAtLeast(8, 0, 16), "This test is for MySql 8.0.16 or higher"); MySqlXConnectionStringBuilder sb = new MySqlXConnectionStringBuilder(ConnectionString); var expectedMsg = "Value is too long for 'foo' attribute, currently limited to 1024"; var strValue = "[foo=12345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781,quua=qux,key=]"; @@ -2201,7 +2201,7 @@ public void ConnectionAttributesValue1025Chars() public void SessionRestore() { // This feature was implemented since MySQL Server 8.0.16 - if (!(session.Version.isAtLeast(8, 0, 16))) Assert.Ignore("This test is for MySql 8.0.16 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 16), "This test is for MySql 8.0.16 or higher"); int size = 2; using (Client client = MySQLX.GetClient(ConnectionString + ";database=test;", new { pooling = new { enabled = true, maxSize = size, queueTimeout = 1000, maxIdleTime = 1000 } })) { @@ -2226,7 +2226,7 @@ public void SessionRestore() public void SessionAuthentication() { // This feature was implemented since MySQL Server 8.0.16 - if (!(session.Version.isAtLeast(8, 0, 16))) Assert.Ignore("This test is for MySql 8.0.16 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 16), "This test is for MySql 8.0.16 or higher"); int size = 1; using (Client client = MySQLX.GetClient(ConnectionString + ";database=test;", new { pooling = new { enabled = true, maxSize = size, queueTimeout = 1000, maxIdleTime = 1000 } })) { @@ -2248,7 +2248,7 @@ public void SessionAuthentication() public void MultiSessionAuthentication() { // This feature was implemented since MySQL Server 8.0.16 - if (!(session.Version.isAtLeast(8, 0, 16))) Assert.Ignore("This test is for MySql 8.0.16 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 16), "This test is for MySql 8.0.16 or higher"); int size = 2; using (Client client = MySQLX.GetClient(ConnectionString + ";database=test;", new { pooling = new { enabled = true, maxSize = size, queueTimeout = 1000, maxIdleTime = 1000 } })) { diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/CloseConnectionTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/CloseConnectionTests.cs index 98f85067e..c98ac4f0e 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/CloseConnectionTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/CloseConnectionTests.cs @@ -51,7 +51,7 @@ public class CloseConnectionTests : BaseTest [Test] public void NotificationKill() { - if (!(session.InternalSession.GetServerVersion().isAtLeast(8, 0, 23))) Assert.Ignore(); + Assume.That(session.Version.isAtLeast(8, 0, 23), "This test is for MySql 8.0.23 or higher"); using (Session session1 = MySQLX.GetSession(ConnectionString)) { Schema test = session1.GetSchema("test"); @@ -73,7 +73,7 @@ public void NotificationKill() [Test] public void NotificationIdle() { - if (!(session.InternalSession.GetServerVersion().isAtLeast(8, 0, 23))) Assert.Ignore(); + Assume.That(session.Version.isAtLeast(8, 0, 23), "This test is for MySql 8.0.23 or higher"); ExecuteSqlAsRoot("SET GLOBAL mysqlx_read_timeout = 5"); ExecuteSqlAsRoot("SET GLOBAL mysqlx_wait_timeout = 5"); @@ -109,7 +109,7 @@ public void NotificationIdle() [Theory] public void CloseWarningsWithCollections(CloseData closeData) { - if (!(session.InternalSession.GetServerVersion().isAtLeast(8, 0, 23))) Assert.Ignore(); + Assume.That(session.Version.isAtLeast(8, 0, 23), "This test is for MySql 8.0.23 or higher"); Session sessionCol = null; sessionCol = MySQLX.GetSession(ConnectionString); @@ -131,7 +131,7 @@ public void CloseWarningsWithCollections(CloseData closeData) [Ignore("This test is marked as Ignore because it shutdown the local MySQL Server, comment this line to run this test manually")] public void NotificationShutdown() { - if (!(session.InternalSession.GetServerVersion().isAtLeast(8, 0, 23))) Assert.Ignore(); + Assume.That(session.Version.isAtLeast(8, 0, 23), "This test is for MySql 8.0.23 or higher"); using (Session localsession = MySQLX.GetSession(BaseTest.ConnectionString)) { @@ -155,7 +155,7 @@ public void NotificationShutdown() [Test] public void PoolTestCloseOneConnection() { - if (!(session.InternalSession.GetServerVersion().isAtLeast(8, 0, 23))) Assert.Ignore(); + Assume.That(session.Version.isAtLeast(8, 0, 23), "This test is for MySql 8.0.23 or higher"); int size = 3; int timeout = 3000; using (Client client = MySQLX.GetClient(ConnectionString + ";database=test;", new { pooling = new { maxSize = size, queueTimeout = timeout } })) @@ -202,7 +202,7 @@ public void PoolTestCloseOneConnection() [Ignore("This test is marked as Ignore because it shutdown the local MySQL Server, comment this line to run this test manually")] public void PoolTestShutdown() { - if (!(session.InternalSession.GetServerVersion().isAtLeast(8, 0, 23))) Assert.Ignore(); + Assume.That(session.Version.isAtLeast(8, 0, 23), "This test is for MySql 8.0.23 or higher"); int size = 3; using (Client client = MySQLX.GetClient(ConnectionString + ";database=test;", new { pooling = new { maxSize = size } })) { @@ -230,7 +230,7 @@ public void PoolTestShutdown() [Test] public void PoolWithIdleConnections() { - if (!(session.InternalSession.GetServerVersion().isAtLeast(8, 0, 23))) Assert.Ignore(); + Assume.That(session.Version.isAtLeast(8, 0, 23), "This test is for MySql 8.0.23 or higher"); int size = 2; ExecuteSqlAsRoot("SET GLOBAL mysqlx_read_timeout = 5"); ExecuteSqlAsRoot("SET GLOBAL mysqlx_wait_timeout = 5"); diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/CollectionIndexTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/CollectionIndexTests.cs index 3da6ab3cb..ed80e6497 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/CollectionIndexTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/CollectionIndexTests.cs @@ -62,7 +62,7 @@ public void IncorrectlyFormatedIndexDefinition() ex = Assert.Throws(() => collection.CreateIndex("myIndex", "{\"fields\": [ { \"field\":$.myField, \"type\":\"TEXT\", \"unexpectedField\" : false } ] }")); Assert.That(ex.Message, Is.EqualTo("Field name 'unexpectedField' is not allowed.")); - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher."); + Assume.That(session.Version.isAtLeast(8, 0, 11), "This test is for MySql 8.0.11 or higher"); collection = CreateCollection("test"); ex = Assert.Throws(() => collection.CreateIndex("myIndex", "{\"fields\": [ { \"field\":$.myField, \"type\":\"INT\" } ], \"type\":\"indexa\" }")); @@ -350,7 +350,7 @@ public void ValidIndexNames() public void CreateIndexWithArrayOption() { var collection = CreateCollection("test"); - if (!session.Version.isAtLeast(8, 0, 17)) Assert.Ignore("This test is for MySql 8.0.17 or higher."); + Assume.That(session.Version.isAtLeast(8, 0, 17), "This test is for MySql 8.0.17 or higher"); // Supported types var doc = new[] { new { _id = 1, name = "Char", myField = new[] { "foo@mail.com", "bar@mail.com", "qux@mail.com" } } }; @@ -393,7 +393,7 @@ public void CreateIndexWithArrayOption() [Test, Description("Add Collection index")] public void AddIndexAndInsertRecords() { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher."); + Assume.That(session.Version.isAtLeast(8, 0, 11), "This test is for MySql 8.0.11 or higher"); Collection testColl = CreateCollection("test1"); Assert.That(testColl.ExistsInDatabase()); testColl.CreateIndex("testIndex", "{\"fields\": [ { \"field\":$.myId, \"type\":\"INTEGER UNSIGNED\" , \"required\":true} ] }"); @@ -409,7 +409,7 @@ public void AddIndexAndInsertRecords() [Test, Description("Create valid index on a single key with all options")] public void InsertWithValidIndexAndNoIndex() { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher."); + Assume.That(session.Version.isAtLeast(8, 0, 11), "This test is for MySql 8.0.11 or higher"); var col = CreateCollection("my_collection"); Result result = col.Add(new { name = "Sakila", age = 15 }).Execute(); col.CreateIndex("myIndex", "{\"fields\": [ { \"field\":$.name, \"type\":\"TEXT(64)\" , \"required\":true} ] }"); @@ -422,7 +422,7 @@ public void InsertWithValidIndexAndNoIndex() [Test, Description("Create a valid index on a single key of all DATATYPES.Datatypes supported: INT [UNSIGNED] TINYINT [UNSIGNED] SMALLINT [UNSIGNED] MEDIUMINT [UNSIGNED] INTEGER [UNSIGNED] BIGINT [UNSIGNED] REAL [UNSIGNED] FLOAT [UNSIGNED] DOUBLE [UNSIGNED] DECIMAL [UNSIGNED] NUMERIC [UNSIGNED] DATE TIME TIMESTAMP DATETIME TEXT[(length)]")] public void IndexOfAllDatatypes() { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher."); + Assume.That(session.Version.isAtLeast(8, 0, 11), "This test is for MySql 8.0.11 or higher"); var col = CreateCollection("my_collection"); Result result = col.Add(new { name = "Sakila", age = 15, date_time = "2010-01-01 00:00:00", time_stamp = "2015-01-01 00:11:02", date_check = "2117-12-17", time_check = "12:14:07", real_check = 12E+4, decimal_check = 122.134, float_check = 11.223, double_check = 23.32343425, numeric_check = 1122.3434, tiny_int = 112, medium_int = 12345, big_int = 1234567, int_check = 174734 }).Execute(); @@ -477,7 +477,7 @@ public void IndexOfAllDatatypes() [Test, Description("Create an index with mismatched data types")] public void IndexWithMismatchedDatatypes() { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher."); + Assume.That(session.Version.isAtLeast(8, 0, 11), "This test is for MySql 8.0.11 or higher"); var col = CreateCollection("my_collection"); Result result = col.Add(new { name = "Sakila", age = 15 }).Execute(); Thread.Sleep(2000); @@ -488,7 +488,7 @@ public void IndexWithMismatchedDatatypes() [Test, Description("Create an index specifiying SPATIAL as the index type for a non spatial data type and vice versa")] public void IndexSpatialForNonSpatialDatatype() { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher."); + Assume.That(session.Version.isAtLeast(8, 0, 11), "This test is for MySql 8.0.11 or higher"); var col = CreateCollection("my_collection"); Result result = col.Add(new { name = "Sakila", age = 15 }).Execute(); Assert.Throws(() => col.CreateIndex("myIndex", "{\"fields\": [ { \"field\":$.name, \"type\":\"TEXT\"} ] , \"type\":\"SPATIAL\" }")); @@ -502,7 +502,7 @@ public void IndexSpatialForNonSpatialDatatype() [Test, Description("Create valid index with index definition given as DbDoc")] public void CreateIndexGivenDbDoc() { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher."); + Assume.That(session.Version.isAtLeast(8, 0, 11), "This test is for MySql 8.0.11 or higher"); var col = CreateCollection("my_collection"); Result result = col.Add(new { name = "Sakila", age = 15 }).Execute(); @@ -518,7 +518,7 @@ public void CreateIndexGivenDbDoc() [Test, Description("Create valid index on member of Array type as key")] public void IndexOnArrayMember() { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher."); + Assume.That(session.Version.isAtLeast(8, 0, 11), "This test is for MySql 8.0.11 or higher"); var col = CreateCollection("my_collection"); @@ -559,7 +559,7 @@ public void IndexOnArrayMember() [Test, Description("Create valid index on member of DbDoc type as key")] public void IndexOnDbDocMember() { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher."); + Assume.That(session.Version.isAtLeast(8, 0, 11), "This test is for MySql 8.0.11 or higher"); var col = CreateCollection("my_collection"); DbDoc data2 = new DbDoc(); data2.SetValue("name", "Sakila"); @@ -575,7 +575,7 @@ public void IndexOnDbDocMember() [Test, Description("Create valid index perform CRUD operations")] public void CountRecordsInsertedWithValidIndex() { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher."); + Assume.That(session.Version.isAtLeast(8, 0, 11), "This test is for MySql 8.0.11 or higher"); var col = CreateCollection("my_collection"); Result result = col.Add(new { name = "Sakila", age = 15 }).Execute(); Assert.Throws(() => col.CreateIndex("myIndex", "{\"fields\": [ { \"field\":$.name, \"type\":\"TEXT\" , \"required\":true} ] }")); @@ -589,7 +589,7 @@ public void CountRecordsInsertedWithValidIndex() [Test, Description("Create invalid index with non-existent key")] public void InvalidIndexNonExistentKey() { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher."); + Assume.That(session.Version.isAtLeast(8, 0, 11), "This test is for MySql 8.0.11 or higher"); var col = CreateCollection("my_collection"); Result result = col.Add(new { age = 15 }).Execute(); Assert.Throws(() => col.CreateIndex("myIndex", "{\"fields\": [ { \"field\":$.name, \"type\":\"TEXT\" , \"required\":\"true\"} ]}")); @@ -598,7 +598,7 @@ public void InvalidIndexNonExistentKey() [Test, Description("Create a valid index in async way")] public async Task CreateIndexInAsync() { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher."); + Assume.That(session.Version.isAtLeast(8, 0, 11), "This test is for MySql 8.0.11 or higher"); var col = CreateCollection("my_collection"); await col.Add(new { name = "Sakila", age = 15 }).ExecuteAsync(); col.CreateIndex("myIndex", "{\"fields\": [ { \"field\":$.name, \"type\":\"TEXT(64)\" , \"required\":true} ] }"); @@ -610,7 +610,7 @@ public async Task CreateIndexInAsync() [Test, Description("Create valid index using a document field type of array and setting array to true with single key on all possible datatypes-data inserted and then index created")] public void IndexWithArrayOptionSingleKeyAfterInsertData() { - if (!session.Version.isAtLeast(8, 0, 17)) Assert.Ignore("This test is for MySql 8.0.17 or higher."); + Assume.That(session.Version.isAtLeast(8, 0, 17), "This test is for MySql 8.0.17 or higher"); var collection = CreateCollection("test"); // Supported types @@ -826,7 +826,7 @@ public void IndexWithArrayOptionSingleKeyAfterInsertData() "inserted and then index created")] public void IndexWithArrayOptionSingleKeyBeforeInsertData() { - if (!session.Version.isAtLeast(8, 0, 17)) Assert.Ignore("This test is for MySql 8.0.17 or higher."); + Assume.That(session.Version.isAtLeast(8, 0, 17), "This test is for MySql 8.0.17 or higher"); var collection = CreateCollection("test"); @@ -981,7 +981,7 @@ public void IndexWithArrayOptionSingleKeyBeforeInsertData() [Test, Description("Create index with array set as null,NULL,multile vel arrays,blank arrays,empty arrays.Also test in multikey scenarios")] public void IndexArrayCombinations() { - if (!session.Version.isAtLeast(8, 0, 17)) Assert.Ignore("This test is for MySql 8.0.17 or higher."); + Assume.That(session.Version.isAtLeast(8, 0, 17), "This test is for MySql 8.0.17 or higher"); var expectedException = "Index field 'array' member must be boolean."; var coll = CreateCollection("test"); @@ -1236,7 +1236,7 @@ public void IndexArrayCombinations() [Test, Description("Index Array Date bug with workaround")] public void IndexArrayBugWorkAround() { - if (!session.Version.isAtLeast(8, 0, 17)) Assert.Ignore("This test is for MySql 8.0.17 or higher."); + Assume.That(session.Version.isAtLeast(8, 0, 17), "This test is for MySql 8.0.17 or higher"); var coll = CreateCollection("test"); var doc = new[] { new { _id = 1, name = "Time", myField = "9:00:00" } };//Bug29692534 var doc22 = new[] { new { _id = 2, name = "Time", myField = new[] { "01:01:01.001", "23:59:59.15", "12:00:00", "1" } } };//Bug29692534 @@ -1402,7 +1402,7 @@ public void IndexArrayBugWorkAround() [Test, Description("Index Array Date bug with workaround")] public void IndexArrayWorkAroundOverlaps() { - if (!session.Version.isAtLeast(8, 0, 17)) Assert.Ignore("This test is for MySql 8.0.17 or higher."); + Assume.That(session.Version.isAtLeast(8, 0, 17), "This test is for MySql 8.0.17 or higher"); var coll = CreateCollection("test"); var doc = new[] { new { _id = 1, name = "Time", myField = "9:00:00" } }; var doc22 = new[] { new { _id = 2, name = "Time", myField = new[] { "01:01:01.001", "23:59:59.15", "12:00:00", "1" } } }; @@ -1623,7 +1623,7 @@ public void IndexArrayWorkAroundOverlaps() public void IndexArrayWithOverlaps() { var coll = CreateCollection("test"); - if (!session.Version.isAtLeast(8, 0, 17)) Assert.Ignore("This test is for MySql 8.0.17 or higher."); + Assume.That(session.Version.isAtLeast(8, 0, 17), "This test is for MySql 8.0.17 or higher"); var doc = new[] { new { _id = 1, name = "Time", myField1 = "9:00:00" } }; var doc22 = new[] { new { _id = 2, name = "Time", myField2 = new[] { "01:01:01.001", "23:59:59.15", "12:00:00", "1" }, myField4 = new[] { "01:01:01.001", "23:59:59.15", "12:00:00", "1" } } }; @@ -1669,7 +1669,7 @@ public void IndexArrayWithOverlaps() public void IndexArrayMultiKey() { var coll = CreateCollection("test"); - if (!session.Version.isAtLeast(8, 0, 17)) Assert.Ignore("This test is for MySql 8.0.17 or higher."); + Assume.That(session.Version.isAtLeast(8, 0, 17), "This test is for MySql 8.0.17 or higher"); coll.CreateIndex("myIndex", "{\"fields\": [{\"field\": $.myField, \"type\":\"CHAR(255)\", \"array\": false}]}"); @@ -1731,7 +1731,7 @@ public void IndexArrayMultiKey() [Test, Description("Test MySQLX plugin Create Collection Multiple Index Type")] public void CreateCollectionMultipleIndexDataType() { - if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher."); + Assume.That(session.Version.isAtLeast(5, 7, 0), "This test is for MySql 5.7 or higher"); Collection testColl = CreateCollection("test"); Assert.That(testColl.ExistsInDatabase(), Is.EqualTo(true), "ExistsInDatabase failed"); @@ -1756,7 +1756,7 @@ public void CreateCollectionMultipleIndexDataType() [Test, Description("Test MySQLX plugin Create Collection Multiple Index Stress")] public void CreateCollectionMultipleIndexStress() { - if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher."); + Assume.That(session.Version.isAtLeast(5, 7, 0), "This test is for MySql 5.7 or higher"); Collection testColl = CreateCollection("test"); Assert.That(testColl.ExistsInDatabase(), Is.EqualTo(true), "ExistsInDatabase failed"); diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/CollectionTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/CollectionTests.cs index e2e1ac3a0..7b9471364 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/CollectionTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/CollectionTests.cs @@ -594,7 +594,7 @@ public void AdditionalCountTests() [Test, Description("Verify Expected exceptions in Count")] public void ExceptionsInCount() { - if (!session.Version.isAtLeast(8, 0, 0)) Assert.Ignore("This test is for MySql 8.0 or higher."); + Assume.That(session.Version.isAtLeast(8, 0, 0), "This test is for MySql 8.0 or higher"); var coll = CreateCollection("testCount"); var docs = new[] { @@ -767,7 +767,7 @@ private Task SubProcessB() [Test, Description("Verify the behaviour of the dropX method for dropCollection under stressed conditions")] public void DropUnderStressedConditions() { - if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher."); + Assume.That(session.Version.isAtLeast(5, 7, 0), "This test is for MySql 5.7 or higher"); Schema schema = session.GetSchema(schemaName); for (var i = 0; i < 10; i++) @@ -781,7 +781,7 @@ public void DropUnderStressedConditions() [Test, Description("Verify that dropX method for dropSchema, dropIndex succeeds in stress conditions")] public void DropObjectsUnderStress() { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher."); + Assume.That(session.Version.isAtLeast(8, 0, 11), "This test is for MySql 8.0.11 or higher"); var schema = session.GetSchema(schemaName); var testColl = CreateCollection("test123"); for (var i = 0; i < 150; i++) @@ -804,7 +804,7 @@ public void DropObjectsUnderStress() [Test, Description("Verify that dropX method for dropIndex succeeds when deleted and created again with various combinations")] public void DropDocuments() { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher."); + Assume.That(session.Version.isAtLeast(8, 0, 11), "This test is for MySql 8.0.11 or higher"); var schema = session.GetSchema(schemaName); schema.DropCollection("test123"); var testColl = schema.CreateCollection("test123"); @@ -828,7 +828,7 @@ public void DropDocuments() [Test, Description("Verify ModifyCollection with level OFF and JSON schema")] public void SchemaValidation_S1() { - if (!session.Version.isAtLeast(8, 0, 19)) Assert.Ignore("This test is for MySql 8.0.19 or higher."); + Assume.That(session.Version.isAtLeast(8, 0, 19), "This test is for MySql 8.0.19 or higher"); var schema = session.GetSchema(schemaName); var options = new CreateCollectionOptions(); var options1 = new ModifyCollectionOptions(); @@ -951,7 +951,7 @@ public void SchemaValidation_S1() [Test, Description("Checking the createcollection() and ModifyCollection() with either the level or the schema")] public void SchemaValidation_S2() { - if (!session.Version.isAtLeast(8, 0, 19)) Assert.Ignore("This test is for MySql 8.0.19 or higher."); + Assume.That(session.Version.isAtLeast(8, 0, 19), "This test is for MySql 8.0.19 or higher"); var schema = session.GetSchema(schemaName); session.SQL($"use {schemaName}").Execute(); var options = new CreateCollectionOptions(); @@ -1132,7 +1132,7 @@ public void SchemaValidation_S2() [Test, Description("Checking the error messages with different level")] public void SchemaValidation_S3() { - if (!session.Version.isAtLeast(8, 0, 19)) Assert.Ignore("This test is for MySql 8.0.19 or higher."); + Assume.That(session.Version.isAtLeast(8, 0, 19), "This test is for MySql 8.0.19 or higher"); session.SQL($"use {schemaName}").Execute(); var options = new CreateCollectionOptions(); var options1 = new ModifyCollectionOptions(); @@ -1256,7 +1256,7 @@ public void SchemaValidation_S3() [Test, Description("Verify ModifyCollection with level OFF and JSON schema with Json schema")] public void ModifyCollectionSchemaValidation() { - if (!session.Version.isAtLeast(8, 0, 19)) Assert.Ignore("This test is for MySql 8.0.19 or higher."); + Assume.That(session.Version.isAtLeast(8, 0, 19), "This test is for MySql 8.0.19 or higher"); session.SQL($"use {schemaName}").Execute(); var schema = session.GetSchema(schemaName); var options = new CreateCollectionOptions(); @@ -1357,7 +1357,7 @@ public void ModifyCollectionSchemaValidation() public void SchemaValidationDeleteRecords() { // Bug30748283 - if (!session.Version.isAtLeast(8, 0, 19)) Assert.Ignore("This test is for MySql 8.0.19 or higher."); + Assume.That(session.Version.isAtLeast(8, 0, 19), "This test is for MySql 8.0.19 or higher"); string doc5 = "{\"id\": \"http://json-schema.org/geo\"," + "\"$schema\": \"http://json-schema.org/draft-06/schema#\"," + "\"description\": \"A Person example\"," @@ -1472,7 +1472,7 @@ public void SchemaValidationDeleteRecords() [Test, Description("Test MySQLX plugin Remove Bind Stress")] public void RemoveBindStress() { - if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher."); + Assume.That(session.Version.isAtLeast(5, 7, 0), "This test is for MySql 5.7 or higher"); Collection coll = CreateCollection("test"); DbDoc[] jsonlist = new DbDoc[10]; DbDoc[] jsonlist1 = new DbDoc[10]; @@ -1508,7 +1508,7 @@ public void RemoveBindStress() [Test, Description("Test MySQLX plugin Get Collection as Table")] public void GetCollectionAsTableStress() { - if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher."); + Assume.That(session.Version.isAtLeast(5, 7, 0), "This test is for MySql 5.7 or higher"); Collection testCollection = CreateCollection("test"); DbDoc[] jsonlist = new DbDoc[1000]; @@ -1540,7 +1540,7 @@ public void GetCollectionAsTableStress() [Test, Description("Test MySQLX plugin GetCollection Exception Scenario")] public void GetCollectionException() { - if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher."); + Assume.That(session.Version.isAtLeast(5, 7, 0), "This test is for MySql 5.7 or higher"); using (Session sessionPlain = MySQLX.GetSession(ConnectionString)) { Schema db = sessionPlain.GetSchema(schemaName); diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/CompressionTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/CompressionTests.cs index 8629fd5ac..d6e7b8a5d 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/CompressionTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/CompressionTests.cs @@ -218,7 +218,7 @@ public void ValidateRequiredCompressionType() [Test] public void NegotiationSucceedsWithExpectedCompressionAlgorithm() { - if (!session.InternalSession.GetServerVersion().isAtLeast(8, 0, 19)) Assert.Ignore("Feature only available since v8.0.19"); + Assume.That(session.Version.isAtLeast(8, 0, 19), "This test is for MySql 8.0.19 or higher"); // Validate zstd_stream is the default. using (var session = MySQLX.GetSession(ConnectionStringUri)) @@ -618,7 +618,7 @@ public void CompressionAlgorithms_Bugs() [Test, Description("Connection Compression tests to verify the values of compress option with connection string, uri, anonymous object, string builder")] public void ConnectionStringCombinations() { - if (!session.Version.isAtLeast(8, 0, 19)) Assert.Ignore("This test is for MySql Server 8.0.19 or higher."); + Assume.That(session.Version.isAtLeast(8, 0, 19), "This test is for MySql 8.0.19 or higher"); MySqlXConnectionStringBuilder sb = new MySqlXConnectionStringBuilder(ConnectionString); sb.SslCa = sslCa; @@ -679,7 +679,7 @@ public void ConnectionStringCombinations() [Test, Description("Verifying the connection pooling with compression option")] public void CompressionWithPolling() { - if (!session.Version.isAtLeast(8, 0, 19)) Assert.Ignore("This test is for MySql 8.0.19 or higher."); + Assume.That(session.Version.isAtLeast(8, 0, 19), "This test is for MySql 8.0.19 or higher"); for (int i = 0; i < 3; i++) { client = MySQLX.GetClient(ConnectionString + ";compression=" + compressValue[i], new { pooling = new { maxSize = 2, queueTimeout = 2000 } }); @@ -706,7 +706,7 @@ public void CompressionWithPolling() [Test, Description("Verify if data sent is compressed")] public void VerifyDataSentCompression() { - if (!session.Version.isAtLeast(8, 0, 19)) Assert.Ignore("This test is for MySql 8.0.19 or higher."); + Assume.That(session.Version.isAtLeast(8, 0, 19), "This test is for MySql 8.0.19 or higher"); int BYTESIZE = 20000; string[] compressValue1 = new string[] { "preferred", "required", "required" }; string[] compressValue2 = new string[] { "disabled", "disabled", "preferred" }; @@ -764,7 +764,7 @@ public void VerifyDataSentCompression() [Test, Description("Verify if data read is compressed")] public void VerifyDataReadCompression() { - if (!session.Version.isAtLeast(8, 0, 19)) Assert.Ignore("This test is for MySql 8.0.19 or higher."); + Assume.That(session.Version.isAtLeast(8, 0, 19), "This test is for MySql 8.0.19 or higher"); const int BYTESIZE = 20000; string[] compressValue1 = new string[] { "preferred", "required" }; for (int i = 0; i < 2; i++) @@ -815,7 +815,7 @@ public void VerifyDataReadCompression() [Test, Description("Verifying the threshold for compression")] public void CompressionThreshold() { - if (!session.Version.isAtLeast(8, 0, 19)) Assert.Ignore("This test is for MySql 8.0.19 or higher."); + Assume.That(session.Version.isAtLeast(8, 0, 19), "This test is for MySql 8.0.19 or higher"); using (session1 = MySQLX.GetSession(ConnectionString + ";compression=required")) { session1.SQL("DROP database if exists compression").Execute(); @@ -879,7 +879,7 @@ public void CompressionThreshold() [Test, Description("Checking the network latency")] public void NetworkLatency() { - if (!session.Version.isAtLeast(8, 0, 19)) Assert.Ignore("This test is for MySql 8.0.19 or higher."); + Assume.That(session.Version.isAtLeast(8, 0, 19), "This test is for MySql 8.0.19 or higher"); const int BYTESIZE = 20000; Stopwatch watch1 = new Stopwatch(); Stopwatch watch2 = new Stopwatch(); diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/CrudInsertTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/CrudInsertTests.cs index d21fe9c36..b849e0bb6 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/CrudInsertTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/CrudInsertTests.cs @@ -403,7 +403,7 @@ public void CollectionAddObjectsFindCondition() [Test, Description("Test MySQLX plugin Collection Scenarios - Add Objects,Find without parameters")] public void CollectionAddFindNoParams() { - if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher."); + Assume.That(session.Version.isAtLeast(5, 7, 0), "This test is for MySql 5.7 or higher"); Collection col = CreateCollection("my_collection_1"); var docs = new[] { @@ -430,7 +430,7 @@ public void CollectionAddFindNoParams() [Test, Description("Test MySQLX plugin Collection Scenarios - Add/Remove JSON Object with id")] public void CollectionAddRemoveJSONObjectID() { - if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher."); + Assume.That(session.Version.isAtLeast(5, 7, 0), "This test is for MySql 5.7 or higher"); using (var sessionPlain = MySQLX.GetSession(ConnectionString + ";sslmode=" + MySqlSslMode.Required)) { Schema db = sessionPlain.GetSchema(schemaName); @@ -453,7 +453,7 @@ public void CollectionAddRemoveJSONObjectID() [Test, Description("Test MySQLX plugin Collection Scenarios - Add/Remove with condition")] public void CollectionAddRemoveJSONObjectCondition() { - if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher."); + Assume.That(session.Version.isAtLeast(5, 7, 0), "This test is for MySql 5.7 or higher"); Schema db = session.GetSchema(schemaName); Collection col = CreateCollection("my_collection_1"); DbDoc DbDocs = new DbDoc(); @@ -470,7 +470,7 @@ public void CollectionAddRemoveJSONObjectCondition() [Test, Description("Test MySQLX plugin Collection Scenarios - Add,Remove with condition limit")] public void CollectionAddRemoveObjectConditionLimit() { - if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher."); + Assume.That(session.Version.isAtLeast(5, 7, 0), "This test is for MySql 5.7 or higher"); Schema db = session.GetSchema(schemaName); Collection col = CreateCollection("my_collection_1"); var docs = new[] @@ -502,7 +502,7 @@ public void CollectionAddRemoveObjectConditionLimit() [Test, Description("Test MySQLX plugin Collection Scenarios - Add/Remove 200 JSON records ")] public void CollectionAddRemove200JSONRecords() { - if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher."); + Assume.That(session.Version.isAtLeast(5, 7, 0), "This test is for MySql 5.7 or higher"); Collection col = CreateCollection("my_collection_1"); var numOfRecords = 200; @@ -530,7 +530,7 @@ public void CollectionAddRemove200JSONRecords() [Test, Description("Test MySQLX plugin Collection Scenarios - Add/Remove documents with limit and orderby ")] public void CollectionAddRemoveJSONRecordsLimitOrderBy() { - if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher."); + Assume.That(session.Version.isAtLeast(5, 7, 0), "This test is for MySql 5.7 or higher"); Schema db = session.GetSchema(schemaName); Collection col = CreateCollection("my_collection_1"); @@ -573,7 +573,7 @@ public void CollectionAddRemoveJSONRecordsLimitOrderBy() [Test, Description("Test MySQLX plugin Collection Scenarios - Add Single/Multiple Docs - Remove Condition/ID/Condition-Limit/Condition-Limit-OrderBy/Bind")] public void CollectionAddRemoveDocsLimitOrderByBind() { - if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher."); + Assume.That(session.Version.isAtLeast(5, 7, 0), "This test is for MySql 5.7 or higher"); Collection col = CreateCollection("my_collection_1"); DbDoc DbDocs = new DbDoc(); DbDocs.SetValue("_id", 100000); @@ -660,7 +660,7 @@ public void CollectionAddRemoveDocsLimitOrderByBind() [Test, Description("Test MySQLX plugin Collection Scenarios - Add Single/Multiple Docs - Remove Condition/ID/Condition-Limit/Condition-Limit-OrderBy/Bind using invalid conditions")] public void CollectionRemoveDocsLimitOrderByBindNegative() { - if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher."); + Assume.That(session.Version.isAtLeast(5, 7, 0), "This test is for MySql 5.7 or higher"); Schema db = session.GetSchema(schemaName); var col = db.CreateCollection("my_collection_1", true); @@ -760,7 +760,7 @@ public void CollectionRemoveDocsLimitOrderByBindNegative() [Test, Description("Test MySQLX plugin - MYSQLCNET_680 Allow Reuse Statement after execute Positive1(after a succesful execute)")] public void AllowReuseStatementAfterExecutePositive1() { - if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher."); + Assume.That(session.Version.isAtLeast(5, 7, 0), "This test is for MySql 5.7 or higher"); Schema db = session.GetSchema(schemaName); var col = db.CreateCollection("my_collection_123456789"); object[] data = new object[] @@ -826,7 +826,7 @@ public void AllowReuseStatementAfterExecutePositive2() [Test, Description("Test MySQLX plugin - MYSQLCNET 755 Collection GetDocumentID")] public void CollectionGetDocumentID() { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher."); + Assume.That(session.Version.isAtLeast(8, 0, 11), "This test is for MySql 8.0.11 or higher"); Collection coll = CreateCollection("test"); var docs = new[] { @@ -916,7 +916,7 @@ public void CheckDocUUIDScenario1() [Test, Description("Test MySQLX UUID Scenario-2(Check UUID generated when multiple JSON docs are added using collection.add().add()..without _id fields)")] public void CheckDocUUIDScenario2() { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher."); + Assume.That(session.Version.isAtLeast(8, 0, 11), "This test is for MySql 8.0.11 or higher"); var col = CreateCollection("my_collection_123456789"); object[] data1 = new object[] { @@ -954,7 +954,7 @@ public void CheckDocUUIDScenario2() [Test, Description("Test MySQLX UUID Scenario-2(Check UUID generated when multiple JSON docs are added using collection.add(doc, doc, doc... ) without _id fields)")] public void CheckDocUUIDScenario3() { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher."); + Assume.That(session.Version.isAtLeast(8, 0, 11), "This test is for MySql 8.0.11 or higher"); var col = CreateCollection("my_collection_123456789"); var stmt = col.Add(@"{ ""foo"": 1 }", @"{""foo"": 2 }", @"{ ""foo"": 3 }", @"{ ""foo"": 4 }"); Result r = col.Add(@"{ ""foo"": 1 }", @"{""foo"": 2 }", @"{ ""foo"": 3 }", @"{ ""foo"": 4 }").Execute(); @@ -977,7 +977,7 @@ public void CheckDocUUIDScenario3() [Test, Description("Test MySQLX UUID Scenario-4(Check UUID generated when multiple JSON docs are added using some containing and some not containing _id fields)")] public void CheckDocUUIDScenario4() { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher."); + Assume.That(session.Version.isAtLeast(8, 0, 11), "This test is for MySql 8.0.11 or higher"); var col = CreateCollection("my_collection_123456789"); object[] data1 = new object[] { @@ -1037,7 +1037,7 @@ public void CheckDocUUIDScenario5() [Test, Description("Test MySQLX UUID Scenario-6(Check that no duplicate UUID is generated by adding multiple doc from the same collection in a session when there are no _id fields)")] public void CheckDocUUIDScenario6() { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher."); + Assume.That(session.Version.isAtLeast(8, 0, 11), "This test is for MySql 8.0.11 or higher"); Collection testCollection = CreateCollection("test"); DbDoc[] jsonlist = new DbDoc[1000]; for (int i = 0; i < 1000; i++) @@ -1100,7 +1100,7 @@ public void CheckDocUUIDScenario7() [Test, Description("Test MySQLX UUID Scenario-8(Check UUID generated when multiple JSON docs are added using collection.add(doc, doc, doc... ) when docs contains _id fields with zero,strings)")] public void CheckDocUUIDScenario8() { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher."); + Assume.That(session.Version.isAtLeast(8, 0, 11), "This test is for MySql 8.0.11 or higher"); var col = CreateCollection("my_collection_123456789"); object[] data1 = new object[] { @@ -1157,7 +1157,7 @@ public void CheckDocUUIDScenario9() [Test, Description("Test MySQLX plugin Collection JSON Depth Scenarios")] public void CollectionAddJSONDepth() { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher."); + Assume.That(session.Version.isAtLeast(8, 0, 11), "This test is for MySql 8.0.11 or higher"); int i, maxArrayelement = 100; Collection col = CreateCollection("my_collection_1"); Collection col1 = CreateCollection("my_collection_2"); @@ -1199,7 +1199,7 @@ public void CollectionAddJSONDepth() [Test, Description("Test MySQLX plugin Collection Add function with null")] public void CollectionAddNullFind() { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher."); + Assume.That(session.Version.isAtLeast(8, 0, 11), "This test is for MySql 8.0.11 or higher"); int i = 1; Collection col = CreateCollection("my_collection_1"); var d1 = new DbDoc(); @@ -1225,7 +1225,7 @@ public void InvalidJSONString() [Test, Description("Test MySQLX plugin JSON String long expression")] public void JSONStringLongExpression() { - if (Platform.IsMacOSX()) Assert.Ignore("Check failure on MacOS: stack overflow");// TO DO + Assume.That(!Platform.IsMacOSX(), "Check failure on MacOs: stack overflow");//TO DO Collection col = CreateCollection("my_collection_1"); String json = "", @@ -1300,7 +1300,7 @@ public void BinaryExpression() [Test, Description("Test MySQLX plugin Invalid JSON String long expression")] public void JSONStringSpecialCharacters() { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher."); + Assume.That(session.Version.isAtLeast(8, 0, 11), "This test is for MySql 8.0.11 or higher"); Collection col = CreateCollection("my_collection_1"); String[] splName = {"+", "*", "/", "a+b", "#1", "%", "&", "@1", "!1", "~", "^", "(", ")", "{", "}", "[", "]", "|", "JSON", "ADD", "JSON_EXTRACT", "JSON_OBJECT", @@ -1321,7 +1321,7 @@ public void JSONStringSpecialCharacters() [Test, Description("Test MySQLX plugin Collections Chained Insert")] public void CollectionsChainedInsert() { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher."); + Assume.That(session.Version.isAtLeast(8, 0, 11), "This test is for MySql 8.0.11 or higher"); Collection col = CreateCollection("my_collection_1"); DbDoc newDoc = new DbDoc(); newDoc.SetValue("F1", 1); @@ -1372,8 +1372,8 @@ public void CollectionsChainedInsert() [Test, Description("Test MySQLX plugin Collection Add Array")] public void CollectionAddArray() { - if (!Platform.IsWindows()) Assert.Ignore("This test is for Windows OS only."); - if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5, 7, 0 or higher."); + Assume.That(Platform.IsWindows(), "This test is for Windows OS only."); + Assume.That(session.Version.isAtLeast(5, 7, 0), "This test is for MySql 5.7 or higher"); int maxrec = 5; var col = CreateCollection("my_collection_1"); DbDoc[] jsonlist = new DbDoc[maxrec]; @@ -1399,8 +1399,8 @@ public void CollectionAddArray() [Test, Description("Test MySQLX plugin Collection JSON Scenarios")] public void CollectionAddJSONDocs() { - if (!Platform.IsWindows()) Assert.Ignore("This test is for Windows OS only."); - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher."); + Assume.That(Platform.IsWindows(), "This test is for Windows OS only."); + Assume.That(session.Version.isAtLeast(8, 0, 11), "This test is for MySql 8.0.11 or higher"); Collection col = CreateCollection("my_collection_1"); string json = @"{ ""_id"": 0, ""title"": ""Book 0"" ,""pages"": 10,""name"": ""Jeoff Archer""}"; @@ -1475,7 +1475,7 @@ public void CollectionAddJSONDocs() [Test, Description("Verify that the field and column _id has a value when it's not given to a document-Scenario-1(single document add)")] public void VerifyIDField() { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("this test is for MySql 8.0.11 or higher."); + Assume.That(session.Version.isAtLeast(8, 0, 11), "This test is for MySql 8.0.11 or higher"); List idStringList = new List(); var col = CreateCollection("my_collection"); Result result = null; @@ -1553,7 +1553,7 @@ public void VerifyIDField() [Test, Description("Unique _ids generated server side for multiple documents, single add and generated ids count should be number of docs added-Scenario3")] public void VerifyIDFieldScenario3() { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("this test is for MySql 8.0.11 or higher."); + Assume.That(session.Version.isAtLeast(8, 0, 11), "This test is for MySql 8.0.11 or higher"); List idStringList = new List(); var col = CreateCollection("my_collection"); Result result = null; @@ -1618,7 +1618,7 @@ public void VerifyIDFieldScenario3() [Test, Description("Verify that the field and column _id has a value when it's not given to a document-Scenario-1(single document add)-when doc already exists")] public void VerifyIDFieldScenario4() { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("this test is for MySql 8.0.11 or higher."); + Assume.That(session.Version.isAtLeast(8, 0, 11), "This test is for MySql 8.0.11 or higher"); List idStringList = new List(); var col = CreateCollection("my_collection"); Result result = null; @@ -1759,7 +1759,7 @@ public void VerifyIDFieldScenario4() [Test, Description("Unique _ids generated server side for multiple documents,multiple add and generated ids count should be number of docs added-when doc already exists Scenario2")] public void VerifyIDFieldScenario5() { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("this test is for MySql 8.0.11 or higher."); + Assume.That(session.Version.isAtLeast(8, 0, 11), "This test is for MySql 8.0.11 or higher"); List idStringList = new List(); Result result = null; string generatedIDs1 = null; @@ -1927,7 +1927,7 @@ public void VerifyIDFieldScenario5() [Test, Description("Unique _ids generated server side for multiple documents, single add and generated ids count should be number of docs added-when doc already exists Scenario3")] public void VerifyIDFieldScenario6() { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("this test is for MySql 8.0.11 or higher."); + Assume.That(session.Version.isAtLeast(8, 0, 11), "This test is for MySql 8.0.11 or higher"); List idStringList = new List(); var col = CreateCollection("my_collection"); Result result = null; @@ -2247,7 +2247,7 @@ public void CollectionAddMultipleDocsSameId() [Test, Description("Verify the behaviour if a sequence is incremented by the user and added as _id for the document")] public void VerifySequenceAndIdAdded() { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher."); + Assume.That(session.Version.isAtLeast(8, 0, 11), "This test is for MySql 8.0.11 or higher"); string incrementedString = null, generatedString = null; var col = CreateCollection("my_collection"); Result result = null; @@ -2287,7 +2287,7 @@ public void VerifySequenceAndIdAdded() [Test, Description("documents inserted concurrently by two threads")] public async Task CollectionConcurrentAdd() { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher."); + Assume.That(session.Version.isAtLeast(8, 0, 11), "This test is for MySql 8.0.11 or higher"); CreateCollection("my_collection"); var r1 = await CollectionAddThread1(); diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/CrudRemoveTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/CrudRemoveTests.cs index e14e77037..1bce4e78c 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/CrudRemoveTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/CrudRemoveTests.cs @@ -197,7 +197,7 @@ public void RemoveAll() [Test] public void RemoveWithInOperator() { - if (!session.InternalSession.GetServerVersion().isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 3), "This test is for MySql 8.0.3 or higher"); Collection collection = CreateCollection("test"); var docs = new[] diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/CrudUpdateTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/CrudUpdateTests.cs index 19216f6a5..c686b97c1 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/CrudUpdateTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/CrudUpdateTests.cs @@ -209,7 +209,7 @@ public void ModifyWithLimit() [Test] public void ModifyWithInOperator() { - if (!session.InternalSession.GetServerVersion().isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 3), "This test is for MySql 8.0.3 or higher"); Collection collection = CreateCollection("test"); var docs = new[] @@ -982,7 +982,7 @@ public void ForbidModifyWithNoCondition_S2() [Test, Description("Test valid modify.patch to change element at Depth n for multiple arrays#Bug))")] public void ModifyPatchNDepth() { - if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher."); + Assume.That(session.Version.isAtLeast(8, 0, 3), "This test is for MySql 8.0.3 or higher"); string json = ""; int i = 0, j = 0, maxField = 100; var collection = CreateCollection("test"); @@ -1012,7 +1012,7 @@ public void ModifyPatchNDepth() [Test, Description("Test valid modify.patch with condition/limit/OrderBy")] public void ModifyPatch() { - if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher."); + Assume.That(session.Version.isAtLeast(8, 0, 3), "This test is for MySql 8.0.3 or higher"); var collection = CreateCollection("test"); var docs = new[] { @@ -1046,7 +1046,7 @@ public void ModifyPatch() [Test, Description("Test valid modify.patch with set/unset")] public void ModifyPatchWithSetUnset() { - if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher."); + Assume.That(session.Version.isAtLeast(8, 0, 3), "This test is for MySql 8.0.3 or higher"); var collection = CreateCollection("test"); var docs = new[] { @@ -1080,7 +1080,7 @@ public void ModifyPatchWithSetUnset() [Test, Description("Test invalid modify.patch to attempt to change _id using modify.patch")] public void ModifyPatchChangeId() { - if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher."); + Assume.That(session.Version.isAtLeast(8, 0, 3), "This test is for MySql 8.0.3 or higher"); var collection = CreateCollection("test"); var docs = new[] { @@ -1118,7 +1118,7 @@ public void ModifyPatchChangeId() [Test, Description("Test modify.patch where the key to be modified has array, dbDoc and normal constant value and condition is matched for all.")] public void ModifyPatchKeyWithArray() { - if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher."); + Assume.That(session.Version.isAtLeast(8, 0, 3), "This test is for MySql 8.0.3 or higher"); var collection = CreateCollection("test"); var docs1 = new[] { @@ -1143,7 +1143,7 @@ public void ModifyPatchKeyWithArray() [Test, Description("Test that documents not matching conditions are not modified.")] public void ModifyPatchNotMatchingConditions() { - if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher."); + Assume.That(session.Version.isAtLeast(8, 0, 3), "This test is for MySql 8.0.3 or higher"); var collection = CreateCollection("test"); var docs = new[] { @@ -1169,7 +1169,7 @@ public void ModifyPatchNotMatchingConditions() [Test, Description("Test modify.patch with different types of records(anonymous object,Json String,DbDoc) with same key and try to replace using a patch")] public void ModifyPatchDifferentTypesSameKey() { - if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher."); + Assume.That(session.Version.isAtLeast(8, 0, 3), "This test is for MySql 8.0.3 or higher"); var collection = CreateCollection("test"); var docs1 = new[] { @@ -1200,7 +1200,7 @@ public void ModifyPatchDifferentTypesSameKey() [Test, Description("GetOne with ExistingID and NewID with doc(Verify the Immutable feature also))")] public void GetOneAndRemoveOne() { - if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher."); + Assume.That(session.Version.isAtLeast(5, 7, 0), "This test is for MySql 5.7 or higher"); var coll = CreateCollection("test"); var docs = new[] { @@ -1259,7 +1259,7 @@ public void GetOneAndRemoveOne() [Test, Description("AddReplaceOne with unique id generated by SQL")] public void AddReplaceOneUniqueId() { - if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher."); + Assume.That(session.Version.isAtLeast(8, 0, 3), "This test is for MySql 8.0.3 or higher"); var collection = CreateCollection("test"); var docs = new[] { diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/MergePatch.cs b/MySQL.Data/tests/MySqlX.Data.Tests/MergePatch.cs index be931efa9..85d2f494b 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/MergePatch.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/MergePatch.cs @@ -134,7 +134,7 @@ public void PatchExpectedExceptions() [Test] public void SimplePatch() { - if (!session.InternalSession.GetServerVersion().isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 3), "This test is for MySql 8.0.3 or higher"); Collection collection = CreateCollection("test"); Result r = ExecuteAddStatement(collection.Add("{ \"_id\": \"123\", \"email\": \"alice@ora.com\", \"startDate\": \"4/1/2017\" }")); @@ -158,7 +158,7 @@ public void SimplePatch() [Test] public void SimplePatchUsingMySqlExpressionClass() { - if (!session.InternalSession.GetServerVersion().isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 3), "This test is for MySql 8.0.3 or higher"); Collection collection = CreateCollection("test"); Result r = ExecuteAddStatement(collection.Add("{ \"_id\": \"123\", \"email\": \"alice@ora.com\", \"startDate\": \"4/1/2017\" }")); @@ -177,7 +177,7 @@ public void SimplePatchUsingMySqlExpressionClass() [Test] public void CRUD() { - if (!session.InternalSession.GetServerVersion().isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 3), "This test is for MySql 8.0.3 or higher"); Collection collection = CreateCollection("test"); Result r = ExecuteAddStatement(collection.Add(documentsAsJsonStrings)); @@ -243,7 +243,7 @@ public void CRUD() [Test] public void ReplaceUpdateInDifferentNestingLevels() { - if (!session.InternalSession.GetServerVersion().isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 3), "This test is for MySql 8.0.3 or higher"); Collection collection = CreateCollection("test"); Result r = ExecuteAddStatement(collection.Add(documentsAsDbDocs)); @@ -276,7 +276,7 @@ public void ReplaceUpdateInDifferentNestingLevels() [Test] public void AddRemoveFieldInDifferentNestingLevels() { - if (!session.InternalSession.GetServerVersion().isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 3), "This test is for MySql 8.0.3 or higher"); Collection collection = CreateCollection("test"); Result r = ExecuteAddStatement(collection.Add(documentsAsDbDocs)); @@ -315,7 +315,7 @@ public void AddRemoveFieldInDifferentNestingLevels() [Test] public void CRUDMultipleFields() { - if (!session.InternalSession.GetServerVersion().isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 3), "This test is for MySql 8.0.3 or higher"); Collection collection = CreateCollection("test"); Result r = ExecuteAddStatement(collection.Add(documentsAsDbDocs)); @@ -364,7 +364,7 @@ public void CRUDMultipleFields() [Test] public void AddNewFieldUsingExpressions() { - if (!session.InternalSession.GetServerVersion().isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 3), "This test is for MySql 8.0.3 or higher"); Collection collection = CreateCollection("test"); Result r = ExecuteAddStatement(collection.Add(documentsAsDbDocs)); @@ -384,7 +384,7 @@ public void AddNewFieldUsingExpressions() [Test] public void ReplaceUpdateUsingExpressions() { - if (!session.InternalSession.GetServerVersion().isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 3), "This test is for MySql 8.0.3 or higher"); Collection collection = CreateCollection("test"); Result r = ExecuteAddStatement(collection.Add(documentsAsDbDocs)); @@ -400,7 +400,7 @@ public void ReplaceUpdateUsingExpressions() [Test] public void ReplaceUpdateIdUsingExpressions() { - if (!session.InternalSession.GetServerVersion().isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 3), "This test is for MySql 8.0.3 or higher"); Collection collection = CreateCollection("test"); Result r = ExecuteAddStatement(collection.Add(documentsAsDbDocs)); @@ -415,7 +415,7 @@ public void ReplaceUpdateIdUsingExpressions() [Test] public void AddIdToNestedDocumentUsingExpressions() { - if (!session.InternalSession.GetServerVersion().isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 3), "This test is for MySql 8.0.3 or higher"); Collection collection = CreateCollection("test"); Result r = ExecuteAddStatement(collection.Add(documentsAsDbDocs)); @@ -431,7 +431,7 @@ public void AddIdToNestedDocumentUsingExpressions() [Test] public void AddNullFieldUsingExpressions() { - if (!session.InternalSession.GetServerVersion().isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 3), "This test is for MySql 8.0.3 or higher"); Collection collection = CreateCollection("test"); Result r = ExecuteAddStatement(collection.Add(documentsAsDbDocs)); @@ -446,7 +446,7 @@ public void AddNullFieldUsingExpressions() [Test] public void ReplaceUpdateNullFieldReturnedFromExpression() { - if (!session.InternalSession.GetServerVersion().isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 3), "This test is for MySql 8.0.3 or higher"); Collection collection = CreateCollection("test"); Result r = ExecuteAddStatement(collection.Add(documentsAsDbDocs)); @@ -462,7 +462,7 @@ public void ReplaceUpdateNullFieldReturnedFromExpression() [Test] public void AddNewFieldReturnedFromExpression() { - if (!session.InternalSession.GetServerVersion().isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 3), "This test is for MySql 8.0.3 or higher"); Collection collection = CreateCollection("test"); Result r = ExecuteAddStatement(collection.Add(documentsAsDbDocs)); @@ -478,7 +478,7 @@ public void AddNewFieldReturnedFromExpression() [Test] public void ReplaceUpdateFieldWithDocumentReturnedFromExpression() { - if (!session.InternalSession.GetServerVersion().isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 3), "This test is for MySql 8.0.3 or higher"); Collection collection = CreateCollection("test"); Result r = ExecuteAddStatement(collection.Add(documentsAsDbDocs)); @@ -498,7 +498,7 @@ public void ReplaceUpdateFieldWithDocumentReturnedFromExpression() [Test] public void ReplaceUpdateId() { - if (!session.InternalSession.GetServerVersion().isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 3), "This test is for MySql 8.0.3 or higher"); Collection collection = CreateCollection("test"); Result r = ExecuteAddStatement(collection.Add(documentsAsDbDocs)); @@ -513,7 +513,7 @@ public void ReplaceUpdateId() [Test] public void AddIdToNestedDocument() { - if (!session.InternalSession.GetServerVersion().isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 3), "This test is for MySql 8.0.3 or higher"); Collection collection = CreateCollection("test"); Result r = ExecuteAddStatement(collection.Add(documentsAsDbDocs)); @@ -535,7 +535,7 @@ public void AddIdToNestedDocument() [Test] public void SetNullToId() { - if (!session.InternalSession.GetServerVersion().isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 3), "This test is for MySql 8.0.3 or higher"); Collection collection = CreateCollection("test"); Result r = ExecuteAddStatement(collection.Add(documentsAsJsonStrings)); @@ -549,7 +549,7 @@ public void SetNullToId() [Test] public void AddNullFields() { - if (!session.InternalSession.GetServerVersion().isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 3), "This test is for MySql 8.0.3 or higher"); Collection collection = CreateCollection("test"); Result r = ExecuteAddStatement(collection.Add(documentsAsJsonStrings)); @@ -580,7 +580,7 @@ public void AddNullFields() [Test] public void AddNestedNullFields() { - if (!session.InternalSession.GetServerVersion().isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 3), "This test is for MySql 8.0.3 or higher"); Collection collection = CreateCollection("test"); Result r = ExecuteAddStatement(collection.Add(documentsAsJsonStrings)); @@ -726,7 +726,7 @@ public void PatchUsingOtherKnownFunctions() public void ModifyPatchMultipleRecords_S1() { - if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher."); + Assume.That(session.Version.isAtLeast(8, 0, 3), "This test is for MySql 8.0.3 or higher"); var collection = CreateCollection("test"); var docs = new[] { @@ -992,7 +992,7 @@ public void ModifyPatchMultipleRecords_S1() [Test, Description("Test valid modify.patch to change element at Depth 5 for multiple arrays))")] public void ModifyInNestedObjects() { - if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher."); + Assume.That(session.Version.isAtLeast(8, 0, 3), "This test is for MySql 8.0.3 or higher"); string json = ""; int i = 0, j = 0, k = 0, l = 0, m = 0, n = 0, maxFld = 10; var collection = CreateCollection("test"); @@ -1324,7 +1324,7 @@ public void ModifyInNestedObjects() [Test, Description("Test valid modify.patch to add/remove fields at Depth for multiple arrays.))")] public void ModifyPatchAtDepthMultipleArrays_S1() { - if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher."); + Assume.That(session.Version.isAtLeast(8, 0, 3), "This test is for MySql 8.0.3 or higher"); Collection collection = CreateCollection("test"); List listDocs = new List(); listDocs.Add(documentsAsDbDocs[0]); @@ -1391,7 +1391,7 @@ public void ModifyPatchAtDepthMultipleArrays_S1() [Test, Description("Test valid modify.patch to use expr to change existing keys in document))")] public void ModifyPatchAtDepthMultipleArrays_S2() { - if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher."); + Assume.That(session.Version.isAtLeast(8, 0, 3), "This test is for MySql 8.0.3 or higher"); DbDoc document = null; Collection collection = CreateCollection("test"); Result r = collection.Add("{ \"_id\": \"123\", \"email\": \"alice@ora.com\", " + @@ -1700,7 +1700,7 @@ public void ModifyPatchAtDepthMultipleArrays_S2() [Test, Description("Test invalid modify.patch to attempt to use invalid string (non JSON string/empty/NULL) as patch string.))")] public void ModifyPatchInvalidString() { - if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher."); + Assume.That(session.Version.isAtLeast(8, 0, 3), "This test is for MySql 8.0.3 or higher"); var collection = CreateCollection("test"); var docs = new[] { diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/PreparedStatementsTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/PreparedStatementsTests.cs index daf2f5f30..56fb53c8b 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/PreparedStatementsTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/PreparedStatementsTests.cs @@ -611,7 +611,7 @@ public void ConnectionPoolingTest() [Test, Description("Deallocate PreparedStatments When Closing Session Load-100 times")] public void DeallocatePreparedStatmentsWhenClosingSessionLoad() { - if (!Platform.IsWindows()) Assert.Ignore("Check for Linux OS"); + Assume.That(Platform.IsWindows(), "Check for Linux OS"); InitCollection(); string threadId; @@ -881,7 +881,7 @@ public void SessionSqlStatementFail() [Test, Description("DELETE WHERE THROWS PARSE EXCEPTION WITH IN OPERATOR FOR ARRAY")] public void DeleteParseException() { - if (!session.Version.isAtLeast(8, 0, 16)) Assert.Ignore("This test is for MySql 8.0.16 or higher."); + Assume.That(session.Version.isAtLeast(8, 0, 16), "This test is for MySql 8.0.16 or higher"); var tableName = "newtable"; Session session1 = null; Client client1 = null; diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/SqlTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/SqlTests.cs index d5c906c3c..7ce44ed11 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/SqlTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/SqlTests.cs @@ -217,7 +217,7 @@ public void TablePositiveSession() [Test, Description("Stored Procedure Table-StringBuilder and Session")] public void StoredProcTablePositiveStringBuilderSession() { - if (!Platform.IsWindows()) Assert.Ignore("This test is for Windows OS only"); + Assume.That(Platform.IsWindows(), "This test is only for Windows OS."); MySqlXConnectionStringBuilder sb = new MySqlXConnectionStringBuilder(ConnectionString); var connectionStringObject = new { connection = "server=" + sb.Server + ";user=" + sb.UserID + ";port=" + sb.Port + ";password=" + sb.Password }; @@ -313,7 +313,7 @@ public void StoredProcTablePositiveStringBuilderSession() [Test, Description("Stored Procedure Table-Negative(procedure returns null)")] public void StoredProcReturnsNull() { - if (!Platform.IsWindows()) Assert.Ignore("This test is for Windows OS only"); + Assume.That(Platform.IsWindows(), "This test is only for Windows OS."); MySqlConnection mysql = new MySqlConnection(ConnectionStringRoot); mysql.Open(); @@ -393,7 +393,7 @@ public void StoredProcReturnsNull() [Test, Description("Bind Support for Session SQL Numeric Datatypes- integer,JSON,tinyint,smallint,mediumint,bigint,float,double,decimal")] public void BindSupportSessionSQLNumericDatatypes() { - if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher"); + Assume.That(session.Version.isAtLeast(5, 7, 0), "This test is for MySql 5.7 or higher"); var connectionString = ConnectionString + ";sslmode=" + MySqlSslMode.Required; SqlResult myResult; Row row; @@ -581,7 +581,7 @@ public void BindSupportSessionSQLNumericDatatypes() [Test, Description("Bind Support for Session SQL DateTime Types- date,datetime,timestamp,time,year(M)")] public void BindSupportSessionSQLDateTimetypes() { - if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher"); + Assume.That(session.Version.isAtLeast(5, 7, 0), "This test is for MySql 5.7 or higher"); //DATE string connectionString = ConnectionString + ";sslmode=" + MySqlSslMode.Required; SqlResult myResult; @@ -702,7 +702,7 @@ public void BindSupportSessionSQLDateTimetypes() [Test, Description("Bind Support for Session SQL String Types- CHAR(M),VARCHAR(M),BLOB,TINYBLOB,MEDIUMBLOB,LONGBLOB,ENUM")] public void BindSupportSessionSQLStringtypes() { - if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher"); + Assume.That(session.Version.isAtLeast(5, 7, 0), "This test is for MySql 5.7 or higher"); //CHAR(20) string connectionString = ConnectionString + ";sslmode=" + MySqlSslMode.Required; SqlResult myResult; @@ -866,7 +866,7 @@ public void BindSupportSessionSQLStringtypes() [Test, Description("Bind Support for Session SQL Negative Tests-Null")] public void BindSupportSessionSQLNegativeTest1() { - if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher"); + Assume.That(session.Version.isAtLeast(5, 7, 0), "This test is for MySql 5.7 or higher"); SqlResult myResult = null; //integer @@ -896,7 +896,7 @@ public void BindSupportSessionSQLNegativeTest1() [Test, Description("Bind Support for Session SQL Negative Tests-Bind Chaining Tests")] public void BindSupportSessionSQLNegativeTest2() { - if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher"); + Assume.That(session.Version.isAtLeast(5, 7, 0), "This test is for MySql 5.7 or higher"); //integer string connectionString = ConnectionString + ";sslmode=" + MySqlSslMode.Required; @@ -932,7 +932,7 @@ public void BindSupportSessionSQLNegativeTest2() [Test, Description("Test MySQLX plugin MySQL mixed scenario")] public void MixedChainedCommands() { - if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher"); + Assume.That(session.Version.isAtLeast(5, 7, 0), "This test is for MySql 5.7 or higher"); ExecuteSQL("Drop table if exists test"); ExecuteSQL("CREATE TABLE test(c1 float(14,8),c2 double GENERATED ALWAYS AS (c1*101/102) Stored COMMENT 'First Gen Col')"); ExecuteSQL("INSERT INTO test(c1) VALUES (22.7)"); @@ -955,7 +955,7 @@ public void MixedChainedCommands() [Test, Description("Test MySQLX plugin MySQL Date Time Bug")] public void DateTimeCheck() { - if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher"); + Assume.That(session.Version.isAtLeast(5, 7, 0), "This test is for MySql 5.7 or higher"); ExecuteSQL("CREATE TABLE test.test1212(dt DATETIME(6))"); ExecuteSQL("INSERT INTO test.test1212 VALUES('2015-10-21 18:01:00.12345678')"); @@ -968,7 +968,7 @@ public void DateTimeCheck() [Test, Description("Test MySQLX plugin MySQL Datetime JSON")] public void DateTimeJSON() { - if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher"); + Assume.That(session.Version.isAtLeast(5, 7, 0), "This test is for MySql 5.7 or higher"); ExecuteSQL("DROP TABLE IF EXISTS test.test"); ExecuteSQL("CREATE TABLE test.test(Id int NOT NULL PRIMARY KEY, jsoncolumn JSON)"); ExecuteSQL(@"INSERT INTO test.test VALUES(100000,' { ""name"" : ""bob"",""Date"": ""2015-10-09"",""Time"": ""12:18:29.000000"",""DateTimeOfRegistration"": ""2015-10-09 12:18:29.000000"",""age"":12} ')"); @@ -980,8 +980,8 @@ public void DateTimeJSON() [Test, Description("Test MySQLX plugin JSON Variant")] public void JSONVariant() { - if (!Platform.IsWindows()) Assert.Ignore("This test is for Windows OS only"); - if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher"); + Assume.That(Platform.IsWindows(), "This test is only for Windows OS."); + Assume.That(session.Version.isAtLeast(5, 7, 0), "This test is for MySql 5.7 or higher"); ExecuteSQL("DROP TABLE IF EXISTS Test"); ExecuteSQL("CREATE TABLE test (Id int NOT NULL PRIMARY KEY, jsoncolumn JSON)"); ExecuteSQL("INSERT INTO test VALUES (1, '[1]')"); @@ -994,8 +994,8 @@ public void JSONVariant() [Test, Description("Test MySQLX plugin big int as PK")] public void BigIntasPK() { - if (!Platform.IsWindows()) Assert.Ignore("This test is for Windows OS only"); - if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher"); + Assume.That(Platform.IsWindows(), "This test is only for Windows OS."); + Assume.That(session.Version.isAtLeast(5, 7, 0), "This test is for MySql 5.7 or higher"); ExecuteSQL("DROP TABLE IF EXISTS Test"); ExecuteSQL("CREATE TABLE test (Id bigint NOT NULL PRIMARY KEY, jsoncolumn JSON)"); @@ -1009,8 +1009,8 @@ public void BigIntasPK() [Test, Description("Test MySQLX plugin tiny int as PK")] public void TinyIntasPK() { - if (!Platform.IsWindows()) Assert.Ignore("This test is for Windows OS only"); - if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher"); + Assume.That(Platform.IsWindows(), "This test is only for Windows OS."); + Assume.That(session.Version.isAtLeast(5, 7, 0), "This test is for MySql 5.7 or higher"); using (var ss = MySQLX.GetSession(ConnectionString)) { @@ -1027,8 +1027,8 @@ public void TinyIntasPK() [Test, Description("Test MySQLX plugin small int as PK")] public void SmallIntasPK() { - if (!Platform.IsWindows()) Assert.Ignore("This test is for Windows OS only"); - if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher"); + Assume.That(Platform.IsWindows(), "This test is only for Windows OS."); + Assume.That(session.Version.isAtLeast(5, 7, 0), "This test is for MySql 5.7 or higher"); using (var ss = MySQLX.GetSession(ConnectionString)) { diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/TableSelectTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/TableSelectTests.cs index 78ef32930..bcb824a7b 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/TableSelectTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/TableSelectTests.cs @@ -198,7 +198,7 @@ public void RowLockingNotSupportedInOlderVersions() [Test] public void SimpleSharedLock() { - if (!session.InternalSession.GetServerVersion().isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 3), "This test is for MySql 8.0.3 or higher"); ExecuteSQLStatement(session.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); using (var session2 = MySQLX.GetSession(ConnectionString)) @@ -227,7 +227,7 @@ public void SimpleSharedLock() [Test] public void SimpleExclusiveLock() { - if (!session.InternalSession.GetServerVersion().isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 3), "This test is for MySql 8.0.3 or higher"); ExecuteSQLStatement(session.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); using (var session2 = MySQLX.GetSession(ConnectionString)) @@ -258,7 +258,7 @@ public void SimpleExclusiveLock() [Test] public void SharedLockForbidsToModifyDocuments() { - if (!session.InternalSession.GetServerVersion().isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 3), "This test is for MySql 8.0.3 or higher"); ExecuteSQLStatement(session.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); using (var session2 = MySQLX.GetSession(ConnectionString)) @@ -294,7 +294,7 @@ public void SharedLockForbidsToModifyDocuments() [Test] public void ExclusiveLockForbidsToModifyDocuments() { - if (!session.InternalSession.GetServerVersion().isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 3), "This test is for MySql 8.0.3 or higher"); ExecuteSQLStatement(session.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); using (var session2 = MySQLX.GetSession(ConnectionString)) @@ -327,7 +327,7 @@ public void ExclusiveLockForbidsToModifyDocuments() [Test] public void SharedLockAfterExclusiveLock() { - if (!session.InternalSession.GetServerVersion().isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 3), "This test is for MySql 8.0.3 or higher"); ExecuteSQLStatement(session.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); using (var session2 = MySQLX.GetSession(ConnectionString)) @@ -362,7 +362,7 @@ public void SharedLockAfterExclusiveLock() [Test] public void ExclusiveLockAfterSharedLock() { - if (!session.InternalSession.GetServerVersion().isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 3), "This test is for MySql 8.0.3 or higher"); ExecuteSQLStatement(session.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); using (var session2 = MySQLX.GetSession(ConnectionString)) @@ -555,7 +555,7 @@ public void InOperatorBindingJson(string condition, string bind, string value, i [Test, Description("Reading locked document(lock_shared) in a table using lock_exclusive with DEFAULT waiting option.")] public void ExclusiveLockAfterSharedLockDefaultWaiting() { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 11), "This test is for MySql 8.0.11 or higher"); session.SQL("DROP TABLE IF EXISTS test.test").Execute(); session.SQL("CREATE TABLE test.test (id INT, a INT)").Execute(); @@ -602,7 +602,7 @@ public void ExclusiveLockAfterSharedLockDefaultWaiting() [Test, Description("Reading exclusively locked document in a table using lock_shared with NOWAIT waiting option. ")] public void SharedLockAfterExclusiveLockWithNoWait() { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 11), "This test is for MySql 8.0.11 or higher"); session.SQL("DROP TABLE IF EXISTS test.test").Execute(); session.SQL("CREATE TABLE test.test (id INT, a INT)").Execute(); @@ -699,7 +699,7 @@ record = record + "\"}"; [Test, Description("Test MySQLX plugin Datatype Tests")] public void DatatypesOnCreateTable() { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 11), "This test is for MySql 8.0.11 or higher"); session.SQL($"use {schemaName}"); session.SQL("create table test1(c1 int,c2 double GENERATED ALWAYS AS (c1*101/102) Stored COMMENT 'First Gen Col',c3 Json GENERATED ALWAYS AS (concat('{\"F1\":',c1,'}')) VIRTUAL COMMENT 'Second Gen /**/Col', c4 bigint GENERATED ALWAYS as (c1*10000) VIRTUAL UNIQUE KEY Comment '3rd Col' NOT NULL)").Execute(); @@ -713,7 +713,7 @@ public void DatatypesOnCreateTable() [Test, Description("Test MySQLX plugin Table Expression using Where")] public void TableExpressionWhereBindGroupBy() { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 11), "This test is for MySql 8.0.11 or higher"); string match = null; session.SQL("create table test1(name VARCHAR(40), age INT)").Execute(); @@ -804,7 +804,7 @@ public void TableSelectFetchValuesInOrder() [Test, Description("Reading exclusively locked document in a table using lock_exclusive with NOWAIT waiting option. ")] public void DoubleExclusiveLockWithNoWait() { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 11), "This test is for MySql 8.0.11 or higher"); session.SQL("DROP TABLE IF EXISTS test.test").Execute(); session.SQL("CREATE TABLE test.test (id INT, a INT)").Execute(); @@ -849,7 +849,7 @@ public void DoubleExclusiveLockWithNoWait() [Test, Description("Reading a locked document(lock_shared) in a table using lock_shared with NOWAIT waiting option. ")] public void DoubleSharedLockWithNoWait() { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 11), "This test is for MySql 8.0.11 or higher"); session.SQL("DROP TABLE IF EXISTS test.test").Execute(); session.SQL("CREATE TABLE test.test (id INT, a INT)").Execute(); @@ -890,7 +890,7 @@ public void DoubleSharedLockWithNoWait() [Test, Description("Reading a locked document(lock_shared) in a table using lock_shared with NOWAIT waiting option. ")] public void ExclusiveLockAfterSharedLockWithNoWait() { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 11), "This test is for MySql 8.0.11 or higher"); session.SQL("DROP TABLE IF EXISTS test.test").Execute(); session.SQL("CREATE TABLE test.test (id INT, a INT)").Execute(); @@ -932,7 +932,7 @@ public void ExclusiveLockAfterSharedLockWithNoWait() [Test, Description("Reading exclusively locked document in a table using lock_shared with SKIPLOCK waiting option. ")] public void SharedLockAfterExclusiveWithSkiplock() { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 11), "This test is for MySql 8.0.11 or higher"); session.SQL("DROP TABLE IF EXISTS test.test").Execute(); session.SQL("CREATE TABLE test.test (id INT, a INT)").Execute(); @@ -976,7 +976,7 @@ public void SharedLockAfterExclusiveWithSkiplock() [Test, Description("Reading exclusively locked document in a table using lock_exclusive with SKIPLOCK waiting option.")] public void DoubleExclusiveLockWithSkiplock() { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 11), "This test is for MySql 8.0.11 or higher"); session.SQL("DROP TABLE IF EXISTS test.test").Execute(); session.SQL("CREATE TABLE test.test (id INT, a INT)").Execute(); @@ -1018,7 +1018,7 @@ public void DoubleExclusiveLockWithSkiplock() [Test, Description("Reading a locked document(lock_shared) in a table using lock_shared with SKIPLOCK waiting option. ")] public void DoubleSharedLockWithSkiplock() { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 11), "This test is for MySql 8.0.11 or higher"); session.SQL("DROP TABLE IF EXISTS test.test").Execute(); session.SQL("CREATE TABLE test.test (id INT, a INT)").Execute(); @@ -1060,7 +1060,7 @@ public void DoubleSharedLockWithSkiplock() [Test, Description("Reading a locked document(lock_shared) in a table using lock_exclusive with SKIPLOCK waiting option.")] public void ExclusiveLockAfterSharedLockWithSkiplock() { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 11), "This test is for MySql 8.0.11 or higher"); session.SQL("DROP TABLE IF EXISTS test.test").Execute(); session.SQL("CREATE TABLE test.test (id INT, a INT)").Execute(); @@ -1103,7 +1103,7 @@ public void ExclusiveLockAfterSharedLockWithSkiplock() [Test, Description("Reading an exclusively locked document in a table using lock_shared without any waiting option. ")] public void ExclusiveLockBeforeSharedLockWithoutAwaiting() { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 11), "This test is for MySql 8.0.11 or higher"); session.SQL("DROP TABLE IF EXISTS test.test").Execute(); session.SQL("CREATE TABLE test.test (id INT, a INT)").Execute(); @@ -1145,7 +1145,7 @@ public void ExclusiveLockBeforeSharedLockWithoutAwaiting() [Test, Description("Reading an exclusively locked document in a table using lock_exclusive without any waiting option.")] public void DoubleExclusiveLockWithoutWaiting() { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 11), "This test is for MySql 8.0.11 or higher"); using (var session2 = MySQLX.GetSession(ConnectionString)) { @@ -1182,7 +1182,7 @@ public void DoubleExclusiveLockWithoutWaiting() [Test, Description("Reading a locked document(lock_shared) in a table using lock_shared without any waiting option.")] public void DoubleSharedLockWithoutWaiting() { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 11), "This test is for MySql 8.0.11 or higher"); session.SQL("DROP TABLE IF EXISTS test.test").Execute(); session.SQL("CREATE TABLE test.test (id INT, a INT)").Execute(); @@ -1223,7 +1223,7 @@ public void DoubleSharedLockWithoutWaiting() [Test, Description("Reading a locked document(lock_shared) in a table using lock_exclusive without any waiting option. ")] public void SharedLockBeforeExclusiveLockWithoutWaiting() { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 11), "This test is for MySql 8.0.11 or higher"); session.SQL("DROP TABLE IF EXISTS test.test").Execute(); session.SQL("CREATE TABLE test.test (id INT, a INT)").Execute(); @@ -1265,7 +1265,7 @@ public void SharedLockBeforeExclusiveLockWithoutWaiting() [Test, Description("Reading a locked document(shared/exclusive) in a table using SKIPLOCK and NOWAIT waiting options when CRUD is happening parallely")] public void SingleLockExclusiveWithNoWaitAndSkip() { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 11), "This test is for MySql 8.0.11 or higher"); session.SQL("DROP TABLE IF EXISTS test.test").Execute(); session.SQL("CREATE TABLE test.test (id INT, a INT)").Execute(); @@ -1305,7 +1305,7 @@ public void SingleLockExclusiveWithNoWaitAndSkip() [Test, Description("Multiple lock calls on a document in table using NOWAIT and SKIPLOCK waiting options")] public void ChainedExclusiveLocks() { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 11), "This test is for MySql 8.0.11 or higher"); session.SQL("DROP TABLE IF EXISTS test.test").Execute(); session.SQL("CREATE TABLE test.test (id INT, a INT)").Execute(); @@ -1343,7 +1343,7 @@ public void ChainedExclusiveLocks() [Test, Description("Test MySQLX plugin - MYSQLCNET 755 Table GetIncrementValue")] public void TableGetAutoIncrementValue() { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 11), "This test is for MySql 8.0.11 or higher"); session.SQL("CREATE TABLE address1" + "(address_number1 MEDIUMINT NOT NULL AUTO_INCREMENT, " + @@ -1492,7 +1492,7 @@ public void FetchoneReturnsNullNoTable() [Test, Description("MySQLX CNET-Test Table.Select() with exclusive lock and Table.Update() normal from two sessions. ")] public void DoubleChainedLocksWithTwoSessions_S1() { - if (!session.InternalSession.GetServerVersion().isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 3), "This test is for MySql 8.0.3 or higher"); session.SQL("SET autocommit = 0").Execute(); using (var session2 = MySQLX.GetSession(ConnectionString)) @@ -1554,7 +1554,7 @@ public void DoubleChainedLocksWithTwoSessions_S1() [Test, Description("MySQLX CNET-Test Table.Select() with shared lock and Table.Update() normal from two sessions. ")] public void DoubleChainedLocksWithTwoSessions_S2() { - if (!session.InternalSession.GetServerVersion().isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 3), "This test is for MySql 8.0.3 or higher"); session.SQL("SET autocommit = 0").Execute(); using (var session2 = MySQLX.GetSession(ConnectionString)) @@ -1621,7 +1621,7 @@ public void DoubleChainedLocksWithTwoSessions_S2() [Test, Description("MySQLX CNET-Test Table.Select() with exclusive lock from two sessions. ")] public void SingleExclusiveLock() { - if (!session.InternalSession.GetServerVersion().isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 3), "This test is for MySql 8.0.3 or higher"); session.SQL("SET autocommit = 0").Execute(); using (var session2 = MySQLX.GetSession(ConnectionString)) @@ -1652,7 +1652,7 @@ public void SingleExclusiveLock() [Test, Description("MySQLX CNET-Test Table.Select() with exclusive lock and Table.Select() with exclusive lock from two sessions-Select multiple records")] public void SingleTransactionWithLocks() { - if (!session.InternalSession.GetServerVersion().isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 3), "This test is for MySql 8.0.3 or higher"); session.SQL("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED").Execute(); using (var session2 = MySQLX.GetSession(ConnectionString)) @@ -1693,8 +1693,8 @@ public void SingleTransactionWithLocks() [Test, Description("MySQLX CNET-Test Table.Select() with exclusive lock and Table.Update() normal from two sessions-50 Iterations")] public void IteratedExclusiveLocks() { - if (!Platform.IsWindows()) Assert.Ignore("This test is for Windows OS only"); - if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); + Assume.That(Platform.IsWindows(), "This test is only for Windows OS."); + Assume.That(session.Version.isAtLeast(8, 0, 3), "This test is for MySql 8.0.3 or higher"); session.SQL("SET autocommit = 0").Execute(); session.SQL("CREATE UNIQUE INDEX myIndex ON test.test (id)").Execute(); diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/TableUpdateTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/TableUpdateTests.cs index da0dcdd62..b8713cea6 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/TableUpdateTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/TableUpdateTests.cs @@ -244,7 +244,7 @@ public void TableSelectGroupBy() [Test, Description("Reading exclusively locked document in a table using lock_shared with DEFAULT waiting option.")] public void ExclusiveLockBeforeSharedLockDefaultWaiting() { - if (!session.InternalSession.GetServerVersion().isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 3), "This test is for MySql 8.0.3 or higher"); session.SQL("DROP TABLE IF EXISTS test.test").Execute(); session.SQL("CREATE TABLE test.test (id INT, a INT)").Execute(); @@ -286,7 +286,7 @@ public void ExclusiveLockBeforeSharedLockDefaultWaiting() [Test, Description("Reading locked document(lock_shared) in a table using lock_shared with DEFAULT waiting option.")] public void SharedLockDefaultWaiting() { - if (!session.InternalSession.GetServerVersion().isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 3), "This test is for MySql 8.0.3 or higher"); session.SQL("DROP TABLE IF EXISTS test.test").Execute(); session.SQL("CREATE TABLE test.test (id INT, a INT)").Execute(); @@ -325,7 +325,7 @@ public void SharedLockDefaultWaiting() [Test,Description("Reading exclusively locked document in a table using lock_exclusive with DEFAULT waiting option ")] public void OnlyExclusiveLocksWithDefaultWaiting() { - if (!session.InternalSession.GetServerVersion().isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher"); + Assume.That(session.Version.isAtLeast(8, 0, 3), "This test is for MySql 8.0.3 or higher"); session.SQL("DROP TABLE IF EXISTS test.test").Execute(); session.SQL("CREATE TABLE test.test (id INT, a INT)").Execute(); diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/SchemaTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/SchemaTests.cs index 9f66e0459..07145c044 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/SchemaTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/SchemaTests.cs @@ -174,7 +174,7 @@ public void ExceptionHandlingSchema() [Test, Description("Test MySQLX plugin Exception Handling Scenario 2")] public void ExceptionHandlingCollection() { - if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher."); + Assume.That(session.Version.isAtLeast(5, 7, 0), "This test is for MySql 5.7 or higher"); Session sessionPlain = MySQLX.GetSession(ConnectionString); @@ -213,7 +213,7 @@ public void CreateValidSchema() [Test, Description("Set Node Schema")] public void SessionSetSchema() { - if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher."); + Assume.That(session.Version.isAtLeast(5, 7, 0), "This test is for MySql 5.7 or higher"); if (!session.GetSchema("test1").ExistsInDatabase()) session.CreateSchema("test1"); Assert.DoesNotThrow(() => session.SetCurrentSchema("test1")); @@ -238,7 +238,7 @@ public void SessionSetSchema() [Test, Description("Session Status before Execution - Negative")] public void SessionClosedBeforeExecution() { - if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher."); + Assume.That(session.Version.isAtLeast(5, 7, 0), "This test is for MySql 5.7 or higher"); Schema schema = null; Session sessionPlain = MySQLX.GetSession(ConnectionString); schema = sessionPlain.GetSchema(schemaName); diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/SessionTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/SessionTests.cs index 78aedaa65..9be27390c 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/SessionTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/SessionTests.cs @@ -255,7 +255,7 @@ public void CheckConnectionUri() CheckConnectionData("mysqlx://myuser:password@[(address=[fe80::bd41:e449:45ee:2e1a%17]:3305,priority=100)]", "myuser", "password", "[fe80::bd41:e449:45ee:2e1a]", 3305); Assert.Throws(() => CheckConnectionData("mysqlx://myuser:password@[(address=fe80::bd41:e449:45ee:2e1a%17,priority=100)]", "myuser", "password", "[fe80::bd41:e449:45ee:2e1a]", 33060)); CheckConnectionData("mysqlx://myuser@localhost/test", "myuser", "", "localhost", 33060, "database", schemaName); -#if NET8_0 +#if NET8_0_OR_GREATER CheckConnectionData("mysqlx://myuser@localhost/test?ssl%20mode=disabled&connecttimeout=10", "myuser", "", "localhost", 33060, "database", schemaName, "ssl mode", "None", "connecttimeout", "10"); #else CheckConnectionData("mysqlx://myuser@localhost/test?ssl%20mode=disabled&connecttimeout=10", "myuser", "", "localhost", 33060, "database", schemaName, "ssl mode", "Disabled", "connecttimeout", "10"); @@ -303,7 +303,7 @@ public void IPv6() csBuilder.Server = GetMySqlServerIp(true); csBuilder.Port = uint.Parse(XPort); - if (string.IsNullOrEmpty(csBuilder.Server)) Assert.Ignore("No IPv6 available."); + Assume.That(!string.IsNullOrEmpty(csBuilder.Server), "No IPv6 available."); using (var session = MySQLX.GetSession(csBuilder.ToString())) { @@ -317,7 +317,7 @@ public void IPv6AsUrl() { var csBuilder = new MySqlXConnectionStringBuilder(ConnectionString); string ipv6 = GetMySqlServerIp(true); - if (string.IsNullOrEmpty(ipv6)) Assert.Ignore("No IPv6 available."); + Assume.That(!string.IsNullOrEmpty(ipv6), "No IPv6 available."); string connString = $"mysqlx://{csBuilder.UserID}:{csBuilder.Password}@[{ipv6}]:{XPort}"; using (Session session = MySQLX.GetSession(connString)) @@ -332,7 +332,7 @@ public void IPv6AsAnonymous() { var csBuilder = new MySqlXConnectionStringBuilder(ConnectionString); string ipv6 = GetMySqlServerIp(true); - if (string.IsNullOrEmpty(ipv6)) Assert.Ignore("No IPv6 available."); + Assume.That(!string.IsNullOrEmpty(ipv6), "No IPv6 available."); using (Session session = MySQLX.GetSession(new { server = ipv6, user = csBuilder.UserID, password = csBuilder.Password, port = XPort })) { @@ -483,7 +483,7 @@ public void GetUri() [Property("Category", "Security")] public void ConnectTimeout() { - if (Platform.IsMacOSX()) Assert.Ignore("Check failure on MacOS: MySQLX.GetSession(connStr), Throws.Exception); @@ -702,7 +702,7 @@ public void PfxCertificateWithUri() [Test, Description("MySQLX ran with Automation for server with TLS")] public void PfxCertificateWithConnectionString() { - if (!session.Version.isAtLeast(8, 0, 0)) Assert.Ignore("This test is for MySql 8.0 or higher."); + Assume.That(session.Version.isAtLeast(8, 0, 0), "This test is for MySql 8.0 or higher"); var connStr = ConnectionString + $";ssl-mode=Required;ssl-ca={clientPfx};ssl-ca-pwd={sslCertificatePassword};"; using (Session c = MySQLX.GetSession(connStr)) @@ -723,7 +723,7 @@ public void PfxCertificateWithConnectionString() [Test] public void ConnectUsingCertificateFileAndTlsVersionXplugin() { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher."); + Assume.That(session.Version.isAtLeast(8, 0, 11), "This test is for MySql 8.0.11 or higher"); var builder = new MySqlConnectionStringBuilder(ConnectionString); builder.SslMode = MySqlSslMode.Required; @@ -746,8 +746,8 @@ public void ConnectUsingCertificateFileAndTlsVersionXplugin() [TestCase("TLSv1.2")] public void TlsVersionInConnectionStringXplugin(string tlsVersion) { - if (!Platform.IsWindows()) Assert.Ignore("This test is for Windows OS only"); - if (!session.Version.isAtLeast(8, 0, 16)) Assert.Ignore("This test is for MySql 8.0.16 or higher."); + Assume.That(Platform.IsWindows(), "This test is only for Windows OS."); + Assume.That(session.Version.isAtLeast(8, 0, 16), "This test is for MySql 8.0.16 or higher"); var connStr = ConnectionString + $";sslmode=Required;tls-version={tlsVersion}"; using (var c = MySQLX.GetSession(connStr)) @@ -761,7 +761,7 @@ public void TlsVersionInConnectionStringXplugin(string tlsVersion) [Test, Description("Verify PEM options (SslCa,SslCert,SslKey) with different SSL modes")] public void PemCertDifferentSSLmodes() { - if (!session.Version.isAtLeast(8, 0, 16)) Assert.Ignore("This test is for MySql 8.0.16 or higher."); + Assume.That(session.Version.isAtLeast(8, 0, 16), "This test is for MySql 8.0.16 or higher"); string CommandText1 = "SHOW STATUS LIKE '%Ssl_cipher%';"; string CommandText2 = "show status like '%Ssl_version%';"; string connStr = null; @@ -913,8 +913,8 @@ public void PemCertDifferentSSLmodes() [Test, Description("MySQLX-scenario (wrong/no ssl-ca,correct ssl-key/ssl-cert,ssl-mode VerifyCA)")] public void IncorrectSslCAVerifyCAMode() { - if (!Platform.IsWindows()) Assert.Ignore("This test is for Windows OS only"); - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher."); + Assume.That(Platform.IsWindows(), "This test is only for Windows OS."); + Assume.That(session.Version.isAtLeast(8, 0, 11), "This test is for MySql 8.0.11 or higher"); string sslmode = "VerifyCA"; string[] sslcalist = new string[] { "ca_dummy.pem", "", " ", null, "file", "file.pem" }; for (int i = 0; i < sslcalist.Length; i++) @@ -983,8 +983,8 @@ public void IncorrectSslCAVerifyCAMode() [Test, Description("MySQLX-Scenario (correct ssl-ca,wrong/no ssl-key/ssl-cert,ssl-mode VerifyCA)")] public void IncorrectSslkeyAndSslcertVerifyCAMode() { - if (!Platform.IsWindows()) Assert.Ignore("This test is for Windows OS only"); - if (!session.Version.isAtLeast(8, 0, 0)) Assert.Ignore("This test is for MySql 8.0 or higher."); + Assume.That(Platform.IsWindows(), "This test is only for Windows OS."); + Assume.That(session.Version.isAtLeast(8, 0, 0), "This test is for MySql 8.0 or higher"); string sslmode = "VerifyCA"; string[] sslcertlist = new string[] { "", " ", null, "file", "file.pem" }; string[] sslkeylist = new string[] { "", " ", null, "file", "file.pem" }; @@ -1060,8 +1060,8 @@ public void IncorrectSslkeyAndSslcertVerifyCAMode() [Test, Description("MySQLX-Scenario (wrong ssl-ca,correct ssl-key/ssl-cert,ssl-mode required and default)")] public void IncorrectSslCACorrectKeyAndCertRequiredMode() { - if (!Platform.IsWindows()) Assert.Ignore("This test is for Windows OS only"); - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher."); + Assume.That(Platform.IsWindows(), "This test is only for Windows OS."); + Assume.That(session.Version.isAtLeast(8, 0, 11), "This test is for MySql 8.0.11 or higher"); string sslmode = "Required"; string[] sslcalist = new string[] { "ca_dummy.pem", "", " ", null, "file", "file.pem" }; List csAndUriList = new List(); @@ -1126,8 +1126,8 @@ public void IncorrectSslCACorrectKeyAndCertRequiredMode() [Test, Description("MySQLX-Scenario (no ssl-ca,correct ssl-key/ssl-cert,ssl-mode required and default)")] public void NoSslcaWithSslkeySslcertRequiredMode() { - if (!Platform.IsWindows()) Assert.Ignore("This test is for Windows OS only"); - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("This test is for MySql 8.0.11 or higher."); + Assume.That(Platform.IsWindows(), "This test is only for Windows OS."); + Assume.That(session.Version.isAtLeast(8, 0, 11), "This test is for MySql 8.0.11 or higher"); string sslmode = "Required"; List csAndUriList = new List(); List connObjectList = new List(); @@ -1171,7 +1171,7 @@ public void NoSslcaWithSslkeySslcertRequiredMode() [Test, Description("MySQLX-Scenario (correct ssl-ca,wrong ssl-key/ssl-cert,ssl-mode required and default)")] public void CorrectSslcaWrongSslkeySslcertRequiredMode() { - if (!Platform.IsWindows()) Assert.Ignore("This test is for Windows OS only"); + Assume.That(Platform.IsWindows(), "This test is only for Windows OS."); string sslmode = "Required"; string[] sslcertlist = new string[] { "", " ", null, "file", "file.pem" }; string[] sslkeylist = new string[] { "", " ", null, "file", "file.pem" }; @@ -1251,8 +1251,8 @@ public void CorrectSslcaWrongSslkeySslcertRequiredMode() [Test, Description("MySQLX-Scenario (correct ssl-ca,no ssl-key/ssl-cert,ssl-mode required and default)")] public void CorrectSslcaNoSslkeyorCertRequiredMode() { - if (!Platform.IsWindows()) Assert.Ignore("This test is for Windows OS only"); - if (!session.Version.isAtLeast(8, 0, 0)) Assert.Ignore("This test is for MySql 8.0 or higher."); + Assume.That(Platform.IsWindows(), "This test is only for Windows OS."); + Assume.That(session.Version.isAtLeast(8, 0, 0), "This test is for MySql 8.0 or higher"); string sslmode = "Required"; List csAndUriList = new List(); //Connection string and Uris @@ -1313,8 +1313,8 @@ public void CorrectSslcaNoSslkeyorCertRequiredMode() [Test, Description("mixed spelling ssl-ca, ssl-key/ssl-cert, ssl-mode VerifyCA and Required)")] public void MixedspellingSslcaSslkeySslcert() { - if (!Platform.IsWindows()) Assert.Ignore("This test is for Windows OS only"); - if (!session.Version.isAtLeast(8, 0, 0)) Assert.Ignore("This test is for MySql 8.0 or higher."); + Assume.That(Platform.IsWindows(), "This test is only for Windows OS."); + Assume.That(session.Version.isAtLeast(8, 0, 0), "This test is for MySql 8.0.0 or higher"); string[] sslmode = new string[] { "VerifyCA", "Required" }; for (int i = 0; i < sslmode.Length; i++) { @@ -1378,7 +1378,7 @@ public void RepeatedTlsOption() [Test, Description("checking different versions of TLS")] public void SecurityTlsCheck() { - if (!Platform.IsWindows()) Assert.Ignore("This test is for Windows OS only"); + Assume.That(Platform.IsWindows(), "This test is only for Windows OS."); MySqlSslMode[] modes = { MySqlSslMode.Required, MySqlSslMode.VerifyCA, MySqlSslMode.VerifyFull }; String[] version, ver1Tls; var conStrX = $"{ConnectionString};SslCa={sslCa};SslCert={sslCert};SslKey={sslKey};ssl-ca-pwd={sslCertificatePassword}"; @@ -1433,7 +1433,7 @@ public void Tlsv13Bug() [Ignore("Fix this")] public void Tlsv13Linux() { - if (Platform.IsWindows()) Assert.Ignore("This test is for Linux OS only"); + Assume.That(!Platform.IsWindows(), "This test is only for Linux OS."); MySqlSslMode[] modes = { MySqlSslMode.Required, MySqlSslMode.VerifyCA, MySqlSslMode.VerifyFull }; var conStr = $"{ConnectionString};SslCa={sslCa};SslCert={sslCert};SslKey={sslKey};ssl-ca-pwd={sslCertificatePassword}"; diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/TransactionTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/TransactionTests.cs index 6045bd692..41975b6eb 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/TransactionTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/TransactionTests.cs @@ -339,7 +339,7 @@ public void RollbackAndReleaseAfterTransactionRollback() [Test, Description("Session Close Transaction")] public void SessionCloseTransaction() { - if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher."); + Assume.That(session.Version.isAtLeast(8, 0, 3), "This test is for MySql 8.0.3 or higher"); using (Session sessionTest = MySQLX.GetSession(ConnectionString)) { Schema db = null; @@ -359,7 +359,7 @@ public void SessionCloseTransaction() [Test, Description("Valid Commit and Check Warning ")] public void CommitValidWarning() { - if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher."); + Assume.That(session.Version.isAtLeast(8, 0, 3), "This test is for MySql 8.0.3 or higher"); using (Session sessionPlain = MySQLX.GetSession(ConnectionString)) { sessionPlain.SetCurrentSchema("test"); @@ -379,7 +379,7 @@ public void CommitValidWarning() [Test, Description("Invalid Commit and Check Warning ")] public void CommitInvalidWarning() { - if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher."); + Assume.That(session.Version.isAtLeast(8, 0, 3), "This test is for MySql 8.0.3 or higher"); using (Session sessionPlain = MySQLX.GetSession(ConnectionString)) { sessionPlain.SetCurrentSchema("test"); @@ -399,7 +399,7 @@ public void CommitInvalidWarning() [Test, Description("Valid Rollback and Check Warning ")] public void RollbackValidWarning() { - if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher."); + Assume.That(session.Version.isAtLeast(8, 0, 3), "This test is for MySql 8.0.3 or higher"); using (Session sessionPlain = MySQLX.GetSession(ConnectionString)) { sessionPlain.SetCurrentSchema("test"); @@ -420,7 +420,7 @@ public void RollbackValidWarning() [Test, Description("Invalid Rollback and Check Warning ")] public void RollbackInvalidWarning() { - if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher."); + Assume.That(session.Version.isAtLeast(8, 0, 3), "This test is for MySql 8.0.3 or higher"); using (Session sessionPlain = MySQLX.GetSession(ConnectionString)) { sessionPlain.SetCurrentSchema("test"); @@ -442,7 +442,7 @@ public void RollbackInvalidWarning() [Test, Description("Commit Rollback Invalid Warning")] public void CommitRollbackInvalidWarning() { - if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher."); + Assume.That(session.Version.isAtLeast(8, 0, 3), "This test is for MySql 8.0.3 or higher"); Collection coll = CreateCollection("test"); var docs1 = new[] { @@ -533,7 +533,7 @@ public void Warnings() [Test, Description("Rollback to same savepoint multiple times")] public void RollbackToSameSavepoint() { - if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher."); + Assume.That(session.Version.isAtLeast(8, 0, 3), "This test is for MySql 8.0.3 or higher"); var col = CreateCollection("my_collection"); session.StartTransaction(); @@ -569,7 +569,7 @@ public void RollbackToSameSavepoint() [Test, Description("Releasing a savepoint multiple times")] public void ReleaseSavepointMoreThanOnce() { - if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher."); + Assume.That(session.Version.isAtLeast(8, 0, 3), "This test is for MySql 8.0.3 or higher"); using (Session sessionTest = MySQLX.GetSession(ConnectionString)) { var col = CreateCollection("my_collection"); @@ -604,7 +604,7 @@ public void ReleaseSavepointMoreThanOnce() [Description("Creating multiple savepoints with SetSavepoint([name]) and rolling back to a specific one")] public void MultipleSavepointsAndRollback(string savePoint1, string savePoint2) { - if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher."); + Assume.That(session.Version.isAtLeast(8, 0, 3), "This test is for MySql 8.0.3 or higher"); var col = CreateCollection("my_collection"); session.StartTransaction(); object[] data = new object[] @@ -630,7 +630,7 @@ public void MultipleSavepointsAndRollback(string savePoint1, string savePoint2) [Test, Description("Test creating a savepoint without starting a transaction")] public void SavepointWithoutTransaction() { - if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher."); + Assume.That(session.Version.isAtLeast(8, 0, 3), "This test is for MySql 8.0.3 or higher"); var col = CreateCollection("my_collection"); object[] data = new object[] { @@ -653,7 +653,7 @@ public void SavepointWithoutTransaction() [Test, Description("Validate that further savepoints get released once you release a preceding savepoint")] public void ValidateSavepointsReleased() { - if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher."); + Assume.That(session.Version.isAtLeast(8, 0, 3), "This test is for MySql 8.0.3 or higher"); var col = CreateCollection("my_collection"); session.StartTransaction(); @@ -684,7 +684,7 @@ public void ValidateSavepointsReleased() [Test, Description("Validate Nested-transactions with multiple savepoints")] public void NestedTransactions() { - if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher."); + Assume.That(session.Version.isAtLeast(8, 0, 3), "This test is for MySql 8.0.3 or higher"); var col = CreateCollection("my_collection"); session.StartTransaction(); object[] data = new object[] @@ -712,7 +712,7 @@ public void NestedTransactions() [Test, Description("Test the behaviour of Savepoints created immediately after one another")] public void SavepointsCreatedImmediately() { - if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher."); + Assume.That(session.Version.isAtLeast(8, 0, 3), "This test is for MySql 8.0.3 or higher"); var col = CreateCollection("my_collection"); session.StartTransaction(); object[] data = new object[] @@ -732,7 +732,7 @@ public void SavepointsCreatedImmediately() [Test, Description("Test MySQLX plugin Commit After Commit")] public void CommitAfterCommit() { - if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher."); + Assume.That(session.Version.isAtLeast(5, 7, 0), "This test is for MySql 5.7 or higher"); Collection coll = CreateCollection("test"); var docs1 = new[] { @@ -795,7 +795,7 @@ public void CommitAfterCommit() [Test, Description("Test MySQLX plugin Rollback Multiple")] public void RollBackMultiple() { - if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher."); + Assume.That(session.Version.isAtLeast(5, 7, 0), "This test is for MySql 5.7 or higher"); Collection coll = CreateCollection("test"); var docs1 = new[] { @@ -838,7 +838,7 @@ public void RollBackMultiple() [Test, Description("Test MySQLX plugin Rollback after RollBack")] public void RollBackAfterRollBack() { - if (!session.Version.isAtLeast(8, 0, 3)) Assert.Ignore("This test is for MySql 8.0.3 or higher."); + Assume.That(session.Version.isAtLeast(8, 0, 3), "This test is for MySql 8.0.3 or higher"); Collection coll = CreateCollection("test"); var docs1 = new[] { @@ -897,7 +897,7 @@ public void RollBackAfterRollBack() [Test, Description("Test MySQLX plugin Commit Rollback")] public void CommitRollBack() { - if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher."); + Assume.That(session.Version.isAtLeast(5, 7, 0), "This test is for MySql 5.7 or higher"); Collection coll = CreateCollection("test"); var docs1 = new[] { @@ -949,7 +949,7 @@ public void CommitRollBack() [Test, Description("Test MySQLX plugin RollBack Commit")] public void RollBackCommit() { - if (!session.Version.isAtLeast(5, 7, 0)) Assert.Ignore("This test is for MySql 5.7 or higher."); + Assume.That(session.Version.isAtLeast(5, 7, 0), "This test is for MySql 5.7 or higher"); Collection coll = CreateCollection("test"); var docs1 = new[] { diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/XAuth.cs b/MySQL.Data/tests/MySqlX.Data.Tests/XAuth.cs index 24ae47b85..b9cccf21e 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/XAuth.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/XAuth.cs @@ -42,8 +42,8 @@ public class XAuth : BaseTest [Property("Category", "Security")] public void DefaultAuthNullPlugin() { - if (!Platform.IsWindows()) Assert.Ignore("Check for Linux OS"); - if (!session.Version.isAtLeast(8, 4, 0)) Assert.Ignore("Test available only to MySQL Server +8.4.0"); + Assume.That(Platform.IsWindows(), "Check For Linux OS"); + Assume.That(session.Version.isAtLeast(8, 4, 0), "This test is for MySql 8.4.0 or higher"); string pluginName = "caching_sha2_password";//default plugin MySqlConnectionStringBuilder builder = new MySqlConnectionStringBuilder(ConnectionString); @@ -146,7 +146,7 @@ public void DefaultAuthNullPlugin() [Property("Category", "Security")] public void DefaultAuthPublicKeyRetrieval() { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("Test available only to MySQL Server +8.0.11"); + Assume.That(session.Version.isAtLeast(8, 0, 11), "This test is for MySql 8.0.11 or higher"); string pluginName = "caching_sha2_password";//default plugin MySqlConnectionStringBuilder builder = new MySqlConnectionStringBuilder(ConnectionString); @@ -198,9 +198,9 @@ public void DefaultAuthPublicKeyRetrieval() [Test, Description("User selects DEFAULT as authentication mechanism-mysql_native_password user,ssl mode default,fresh connection")] public void MySqlNativePlugin() { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("Test available only to MySQL Server +8.0.11"); - if (!Check_Plugin_Enabled("mysql_native_password")) - Assert.Ignore("mysql_native_password plugin must be enabled on the server to run this test"); + Assume.That(session.Version.isAtLeast(8, 0, 11), "This test is for MySql 8.0.11 or higher"); + Assume.That(Check_Plugin_Enabled("mysql_native_password"), "mysql_native_password plugin must be enabled on the server to run this test."); + Assume.That(Check_Plugin_Enabled("caching_sha2_password"), "The caching_sha2_password plugin isn't available."); string pluginName = "mysql_native_password";//mysql_native_password plugin MySqlConnectionStringBuilder builder = new MySqlConnectionStringBuilder(ConnectionString); @@ -261,8 +261,7 @@ public void MySqlNativePlugin() [Property("Category", "Security")] public void ConnectUsingMySQL41Auth() { - if (!Check_Plugin_Enabled("mysql_native_password")) - Assert.Ignore("mysql_native_password plugin must be enabled on the server to run this test"); + Assume.That(Check_Plugin_Enabled("mysql_native_password"), "mysql_native_password plugin must be enabled on the server to run this test."); ExecuteSqlAsRoot("CREATE USER IF NOT EXISTS 'testNative'@'%' identified with mysql_native_password by 'test';"); var connectionStringUri = ConnectionStringUri; @@ -371,13 +370,9 @@ public void ConnectUsingSha256Memory() [Property("Category", "Security")] public void Sha256MemoryAuthWithDifferentPlugin(string pluginName) { - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("Test available only to MySQL Server +8.0.11"); - - if (pluginName == "mysql_native_password") - { - if (!Check_Plugin_Enabled("mysql_native_password")) - Assert.Ignore("mysql_native_password plugin must be enabled on the server to run this test"); - } + Assume.That(session.Version.isAtLeast(8, 0, 11), "This test is for MySql 8.0.11 or higher"); + Assume.That(Check_Plugin_Enabled("mysql_native_password"), "mysql_native_password plugin must be enabled on the server to run this test."); + MySqlConnectionStringBuilder builder = new MySqlConnectionStringBuilder(ConnectionString); builder.UserID = "testDefaultPlugin"; builder.Password = "test"; @@ -422,10 +417,9 @@ public void Sha256MemoryAuthWithDifferentPlugin(string pluginName) [Property("Category", "Security")] public void NativeAuthValidAndInvalidConnection() { - if (!Platform.IsWindows()) Assert.Ignore("Check for Linux OS"); - if (!session.Version.isAtLeast(8, 0, 11)) Assert.Ignore("Test available only to MySQL Server +8.0.11"); - if (!Check_Plugin_Enabled("mysql_native_password")) - Assert.Ignore("mysql_native_password plugin must be enabled on the server to run this test"); + Assume.That(Platform.IsWindows(), "Check for Linux OS"); + Assume.That(session.Version.isAtLeast(8, 0, 11), "This test is for MySql 8.0.11 or higher"); + Assume.That(Check_Plugin_Enabled("mysql_native_password"), "mysql_native_password plugin must be enabled on the server to run this test."); ExecuteSqlAsRoot("CREATE USER IF NOT EXISTS 'testNative'@'%' identified with mysql_native_password by 'test';"); var user = "testNative"; diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/XConnectionStringBuilderTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/XConnectionStringBuilderTests.cs index 78154a965..08acc6603 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/XConnectionStringBuilderTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/XConnectionStringBuilderTests.cs @@ -63,7 +63,7 @@ public void SessionCanBeOpened() [Test] public void ConnectionAfterSessionCanBeOpened() { - if (!Platform.IsWindows()) Assert.Ignore("Check for Linux OS"); + Assume.That(Platform.IsWindows(), "Check for Linux OS"); using (var session = MySQLX.GetSession(_xConnectionURI)) Assert.That(session.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); From 381fb9c854f6285c6a5e964ec40d6d4cc60004e4 Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Fri, 22 Mar 2024 17:53:34 -0600 Subject: [PATCH 062/125] WL#16308 [Add support for .NET 9 and EF Core 9] Added support for .NET 9 and EFCore 9 preview versions. Change-Id: Ib01dfb6715371f413fa2d3c7d38fcf11b7fd94ee --- CHANGES | 1 + .../Conventions/MySQLConventionSetBuilder.cs | 1 - .../MySqlEntityCharsetAttributeConvention.cs | 2 +- ...MySqlEntityCollationAttributeConvention.cs | 2 +- .../Internal/MySQLAnnotationProvider.cs | 8 ++-- .../Internal/MySQLMigrationsModelDiffer.cs | 38 +++++++++++++++++++ .../Migrations/MySQLMigrationsSqlGenerator.cs | 2 +- EFCore/src/MySql.EntityFrameworkCore.csproj | 9 +++++ EFCore/src/Properties/AssemblyInfo.cs | 4 +- .../MySQLStringComparisonMethodTranslator.cs | 10 ++--- .../MySQLParameterBasedSqlProcessor.cs | 2 +- .../MySQLQueryTranslationPostprocessor.cs | 2 +- ...SQLQueryTranslationPostprocessorFactory.cs | 3 +- ...LSqlTranslatingExpressionVisitorFactory.cs | 2 +- .../Internal/MySQLGeometryTypeMapping.cs | 2 +- .../Internal/MySQLTypeMappingSource.cs | 10 ++--- EFCore/src/Update/IMySQLUpdateSqlGenerator.cs | 2 +- .../Update/MySQLModificationCommandBatch.cs | 4 +- EFCore/src/Update/MySQLUpdateSqlGenerator.cs | 2 +- .../Internal/MySQLValueGeneratorSelector.cs | 2 +- EFCore/src/global.json | 5 --- .../ConnectionTests.cs | 2 +- ...Sql.EntityFrameworkCore.Basic.Tests.csproj | 8 ++++ .../MySql.EFCore.Basic.Tests/global.json | 5 --- ...ql.EntityFrameworkCore.Design.Tests.csproj | 17 ++++++++- .../MySql.EFCore.Design.Tests/global.json | 5 --- ...ntityFrameworkCore.Migrations.Tests.csproj | 4 ++ .../MySql.EFCore.Migrations.Tests/global.json | 5 --- EntityFramework/src/global.json | 5 --- .../global.json | 5 --- .../global.json | 5 --- .../global.json | 5 --- MySQL.Data.OpenTelemetry/src/global.json | 5 --- MySQL.Data/src/MySql.Data.csproj | 6 ++- MySQL.Data/src/MySqlDataReader.cs | 2 +- MySQL.Data/src/global.json | 5 --- .../Framework/netstandard2_0/BlobTestsPipe.cs | 6 +-- .../netstandard2_0/BlobTestsPipeCompressed.cs | 6 +-- .../netstandard2_0/BlobTestsSharedMem.cs | 7 +--- .../BlobTestsSharedMemCompressed.cs | 6 +-- .../Framework/netstandard2_0/CmdTestsPipe.cs | 5 --- .../netstandard2_0/CmdTestsPipeCompressed.cs | 5 +-- .../netstandard2_0/CmdTestsSharedMem.cs | 6 +-- .../CmdTestsSharedmemCompressed.cs | 5 --- .../Framework/netstandard2_0/PSPipe.cs | 5 --- .../netstandard2_0/PSPipeCompressed.cs | 7 +--- .../netstandard2_0/PSSharedMemory.cs | 6 +-- .../PSSharedMemoryCompressed.cs | 6 +-- .../netstandard2_0/StressTestsPipe.cs | 4 -- .../StressTestsPipeCompressed.cs | 6 +-- .../netstandard2_0/StressTestsSharedMemory.cs | 6 +-- .../StressTestsSharedMemoryCompressed.cs | 4 +- .../netstandard2_0/TimeoutAndCancel.cs | 1 + .../netstandard2_0/TimeoutAndCancelPipe.cs | 4 -- .../TimeoutAndCancelSharedMemory.cs | 4 +- .../MySql.Data.Tests/MySql.Data.Tests.csproj | 8 +++- MySQL.Data/tests/MySql.Data.Tests/global.json | 5 --- .../MySqlX.Data.Tests.csproj | 6 ++- .../tests/MySqlX.Data.Tests/global.json | 5 --- MySql.Web/src/global.json | 5 --- MySql.Web/tests/global.json | 5 --- 61 files changed, 151 insertions(+), 179 deletions(-) delete mode 100644 EFCore/src/global.json delete mode 100644 EFCore/tests/MySql.EFCore.Basic.Tests/global.json delete mode 100644 EFCore/tests/MySql.EFCore.Design.Tests/global.json delete mode 100644 EFCore/tests/MySql.EFCore.Migrations.Tests/global.json delete mode 100644 EntityFramework/src/global.json delete mode 100644 EntityFramework/tests/MySql.EntityFramework.Basic.Tests/global.json delete mode 100644 EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/global.json delete mode 100644 EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/global.json delete mode 100644 MySQL.Data.OpenTelemetry/src/global.json delete mode 100644 MySQL.Data/src/global.json delete mode 100644 MySQL.Data/tests/MySql.Data.Tests/global.json delete mode 100644 MySQL.Data/tests/MySqlX.Data.Tests/global.json delete mode 100644 MySql.Web/src/global.json delete mode 100644 MySql.Web/tests/global.json diff --git a/CHANGES b/CHANGES index 8d2032816..78347380f 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,7 @@ 9.1.0 - Updated test suite to use constraint-based assertions (WL16397). - Changed testsuite to use assummptions instead of Assert.Ignore (WL16402). +- Added support for .NET 9 and EFCore 9 preview versions (WL16308). 9.0.0 diff --git a/EFCore/src/Metadata/Conventions/MySQLConventionSetBuilder.cs b/EFCore/src/Metadata/Conventions/MySQLConventionSetBuilder.cs index 51691531a..7d7fce3d0 100644 --- a/EFCore/src/Metadata/Conventions/MySQLConventionSetBuilder.cs +++ b/EFCore/src/Metadata/Conventions/MySQLConventionSetBuilder.cs @@ -69,7 +69,6 @@ public override ConventionSet CreateConventionSet() conventionSet.PropertyAddedConventions.Add(new MySqlCollationAttributeConvention(Dependencies)); conventionSet.EntityTypeAddedConventions.Add(new MySqlEntityCharsetAttributeConvention(Dependencies)); conventionSet.EntityTypeAddedConventions.Add(new MySqlEntityCollationAttributeConvention(Dependencies)); - ValueGenerationConvention valueGeneratorConvention = new MySQLValueGenerationConvention(Dependencies, RelationalDependencies); ReplaceConvention(conventionSet.EntityTypeBaseTypeChangedConventions, valueGeneratorConvention); ReplaceConvention(conventionSet.EntityTypePrimaryKeyChangedConventions, valueGeneratorConvention); diff --git a/EFCore/src/Metadata/Conventions/MySqlEntityCharsetAttributeConvention.cs b/EFCore/src/Metadata/Conventions/MySqlEntityCharsetAttributeConvention.cs index 19b084852..3b6be795c 100644 --- a/EFCore/src/Metadata/Conventions/MySqlEntityCharsetAttributeConvention.cs +++ b/EFCore/src/Metadata/Conventions/MySqlEntityCharsetAttributeConvention.cs @@ -34,7 +34,7 @@ namespace MySql.EntityFrameworkCore.Metadata.Conventions { -#if !NET8_0 +#if !NET8_0_OR_GREATER /// /// Represents a character-set attribute for an entity. /// diff --git a/EFCore/src/Metadata/Conventions/MySqlEntityCollationAttributeConvention.cs b/EFCore/src/Metadata/Conventions/MySqlEntityCollationAttributeConvention.cs index a7de5f837..6249a5145 100644 --- a/EFCore/src/Metadata/Conventions/MySqlEntityCollationAttributeConvention.cs +++ b/EFCore/src/Metadata/Conventions/MySqlEntityCollationAttributeConvention.cs @@ -34,7 +34,7 @@ namespace MySql.EntityFrameworkCore.Metadata.Conventions { -#if !NET8_0 +#if !NET8_0_OR_GREATER /// /// Represents a collation attribute for an entity. /// diff --git a/EFCore/src/Metadata/Internal/MySQLAnnotationProvider.cs b/EFCore/src/Metadata/Internal/MySQLAnnotationProvider.cs index 74a77b683..d437571e7 100644 --- a/EFCore/src/Metadata/Internal/MySQLAnnotationProvider.cs +++ b/EFCore/src/Metadata/Internal/MySQLAnnotationProvider.cs @@ -70,7 +70,7 @@ public override IEnumerable For(ITable table, bool designTime) { yield break; } -#if NET8_0 +#if NET8_0_OR_GREATER var entityType = table.EntityTypeMappings.First().TypeBase; if (GetActualTypeBaseCharSet(entityType) is string charSet) yield return new Annotation(MySQLAnnotationNames.Charset, charSet); @@ -132,7 +132,7 @@ public override IEnumerable For(IColumn column, bool designTime) var table = StoreObjectIdentifier.Table(column.Table.Name, column.Table.Schema); var properties = column.PropertyMappings.Select(m => m.Property).ToArray(); -#if NET8_0 +#if NET8_0_OR_GREATER if (column.PropertyMappings.Where(m => m.TableMapping.IsSharedTablePrincipal ?? true && m.TableMapping.TypeBase == m.Property.DeclaringType) .Select(m => m.Property) .FirstOrDefault(p => p.GetValueGenerationStrategy(table) == MySQLValueGenerationStrategy.IdentityColumn) is IProperty identityProperty) @@ -162,7 +162,7 @@ protected virtual string GetActualModelCollation(IModel model) return model.GetCollation()!; } -#if NET8_0 +#if NET8_0_OR_GREATER protected virtual string? GetActualTypeBaseCharSet(ITypeBase typeBase) { var typeBaseCharSet = typeBase.GetCharSet(); @@ -270,7 +270,7 @@ protected virtual string GetActualModelCollation(IModel model) protected virtual string? GetActualPropertyCharSet(IProperty[] properties) { -#if NET8_0 +#if NET8_0_OR_GREATER return properties.Select(p => p.GetCharSet()).FirstOrDefault(s => s is not null) ?? properties.Select( p => p.FindTypeMapping() is MySQLStringTypeMapping diff --git a/EFCore/src/Migrations/Internal/MySQLMigrationsModelDiffer.cs b/EFCore/src/Migrations/Internal/MySQLMigrationsModelDiffer.cs index 22ffaa57a..3c02ec2ed 100644 --- a/EFCore/src/Migrations/Internal/MySQLMigrationsModelDiffer.cs +++ b/EFCore/src/Migrations/Internal/MySQLMigrationsModelDiffer.cs @@ -115,6 +115,44 @@ protected override IEnumerable Add(IColumn target, DiffConte } return base.Add(target, diffContext, inline); } + +#elif NET9_0 + public MySQLMigrationsModelDiffer( + [NotNull] IRelationalTypeMappingSource typeMappingSource, + [NotNull] IMigrationsAnnotationProvider migrationsAnnotations, + [NotNull] IRelationalAnnotationProvider relationalAnnotationProvider, + [NotNull] IRowIdentityMapFactory rowIdentityMapFactory, + [NotNull] CommandBatchPreparerDependencies commandBatchPreparerDependencies) + : base( + typeMappingSource, + migrationsAnnotations, + relationalAnnotationProvider, + rowIdentityMapFactory, + commandBatchPreparerDependencies) + { + } + + protected override IEnumerable Add(IColumn target, DiffContext diffContext, bool inline = false) + { + var _property = target.PropertyMappings.ToArray().FirstOrDefault()!.Property; + if (_property.FindTypeMapping() is RelationalTypeMapping storeType) + { + var valueGenerationStrategy = MySQLValueGenerationStrategyCompatibility.GetValueGenerationStrategy(MigrationsAnnotationProvider.ForRemove(target).ToArray()); + // Ensure that null will be set for the columns default value, if CURRENT_TIMESTAMP has been required, + // or when the store type of the column does not support default values at all. + inline = inline || + (storeType.StoreTypeNameBase == "datetime" || + storeType.StoreTypeNameBase == "timestamp") && + (valueGenerationStrategy == MySQLValueGenerationStrategy.IdentityColumn || + valueGenerationStrategy == MySQLValueGenerationStrategy.ComputedColumn) || + storeType.StoreTypeNameBase.Contains("text") || + storeType.StoreTypeNameBase.Contains("blob") || + storeType.StoreTypeNameBase == "geometry" || + storeType.StoreTypeNameBase == "json"; + } + return base.Add(target, diffContext, inline); + } + #endif diff --git a/EFCore/src/Migrations/MySQLMigrationsSqlGenerator.cs b/EFCore/src/Migrations/MySQLMigrationsSqlGenerator.cs index 39b21d652..2ca5009c3 100644 --- a/EFCore/src/Migrations/MySQLMigrationsSqlGenerator.cs +++ b/EFCore/src/Migrations/MySQLMigrationsSqlGenerator.cs @@ -537,7 +537,7 @@ protected override void Generate( if (model?.GetRelationalModel().FindTable(operation.Name, operation.Schema) != null) { -#if !NET8_0 +#if !NET8_0_OR_GREATER var entity = model?.GetRelationalModel().FindTable(operation.Name, operation.Schema)!.EntityTypeMappings.FirstOrDefault()!.EntityType; #else var entity = model?.GetRelationalModel().FindTable(operation.Name, operation.Schema)!.EntityTypeMappings.FirstOrDefault()!.TypeBase; diff --git a/EFCore/src/MySql.EntityFrameworkCore.csproj b/EFCore/src/MySql.EntityFrameworkCore.csproj index d3230975c..51c6d3741 100644 --- a/EFCore/src/MySql.EntityFrameworkCore.csproj +++ b/EFCore/src/MySql.EntityFrameworkCore.csproj @@ -30,6 +30,10 @@ false + + net9.0;$(TargetFrameworks) + + @@ -40,6 +44,11 @@ + + + + + diff --git a/EFCore/src/Properties/AssemblyInfo.cs b/EFCore/src/Properties/AssemblyInfo.cs index 66005293d..9e1f85f5f 100644 --- a/EFCore/src/Properties/AssemblyInfo.cs +++ b/EFCore/src/Properties/AssemblyInfo.cs @@ -37,7 +37,7 @@ // set of attributes. Change these attribute values to modify the information // associated with an assembly. [assembly: AssemblyTitle("MySql.EntityFrameworkCore")] -[assembly: AssemblyDescription("MySql.EntityFrameworkCore adds support for Microsoft Entity Framework Core (EF Core) 6, 7, and 8.")] +[assembly: AssemblyDescription("MySql.EntityFrameworkCore adds support for Microsoft Entity Framework Core (EF Core) 6, 7, 8 and 9.")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Oracle Corporation")] [assembly: AssemblyProduct("MySQL Connector/NET")] @@ -45,6 +45,8 @@ [assembly: AssemblyCopyright("Copyright © 2021, 2024, Oracle and/or its affiliates.")] #elif NET8_0 [assembly: AssemblyCopyright("Copyright © 2024, Oracle and/or its affiliates.")] +#elif NET9_0 +[assembly: AssemblyCopyright("Copyright © 2024, Oracle and/or its affiliates.")] #endif [assembly: AssemblyTrademark("Oracle®, Java, MySQL, and NetSuite are registered trademarks of Oracle and/or its affiliates.")] [assembly: AssemblyCulture("")] diff --git a/EFCore/src/Query/Expressions/Internal/MySQLStringComparisonMethodTranslator.cs b/EFCore/src/Query/Expressions/Internal/MySQLStringComparisonMethodTranslator.cs index 952e87a71..8fd775d7d 100644 --- a/EFCore/src/Query/Expressions/Internal/MySQLStringComparisonMethodTranslator.cs +++ b/EFCore/src/Query/Expressions/Internal/MySQLStringComparisonMethodTranslator.cs @@ -166,7 +166,7 @@ public MySQLStringComparisonMethodTranslator(ISqlExpressionFactory sqlExpression } else { - #if !NET8_0 +#if !NET8_0_OR_GREATER return new CaseExpression( new[] { @@ -232,7 +232,7 @@ public MySQLStringComparisonMethodTranslator(ISqlExpressionFactory sqlExpression } else { -#if !NET8_0 +#if !NET8_0_OR_GREATER return new CaseExpression( new[] { @@ -330,7 +330,7 @@ private SqlBinaryExpression MakeStartsWithExpressionImpl( } else { -#if !NET8_0 +#if !NET8_0_OR_GREATER return new CaseExpression( new[] { @@ -446,7 +446,7 @@ private SqlExpression MakeEndsWithExpressionImpl( } else { -#if !NET8_0 +#if !NET8_0_OR_GREATER return new CaseExpression( new[] { @@ -565,7 +565,7 @@ private SqlExpression MakeContainsExpressionImpl( e => Utf8Bin(LCase(e)))); } -#if !NET8_0 +#if !NET8_0_OR_GREATER return _sqlExpressionFactory.Case( new[] { diff --git a/EFCore/src/Query/Internal/MySQLParameterBasedSqlProcessor.cs b/EFCore/src/Query/Internal/MySQLParameterBasedSqlProcessor.cs index c73a1f77f..d31ef25e2 100644 --- a/EFCore/src/Query/Internal/MySQLParameterBasedSqlProcessor.cs +++ b/EFCore/src/Query/Internal/MySQLParameterBasedSqlProcessor.cs @@ -62,7 +62,7 @@ protected override SelectExpression ProcessSqlNullability( return selectExpression; } -#elif NET8_0 +#elif NET8_0_OR_GREATER protected override Expression ProcessSqlNullability( Expression selectExpression, IReadOnlyDictionary parametersValues, out bool canCache) { diff --git a/EFCore/src/Query/Internal/MySQLQueryTranslationPostprocessor.cs b/EFCore/src/Query/Internal/MySQLQueryTranslationPostprocessor.cs index 2e96e6b32..0cd1f61f6 100644 --- a/EFCore/src/Query/Internal/MySQLQueryTranslationPostprocessor.cs +++ b/EFCore/src/Query/Internal/MySQLQueryTranslationPostprocessor.cs @@ -39,7 +39,7 @@ internal class MySQLQueryTranslationPostprocessor : RelationalQueryTranslationPo public MySQLQueryTranslationPostprocessor( QueryTranslationPostprocessorDependencies dependencies, RelationalQueryTranslationPostprocessorDependencies relationalDependencies, - QueryCompilationContext queryCompilationContext, + MySQLQueryCompilationContext queryCompilationContext, IMySQLOptions options) : base(dependencies, relationalDependencies, queryCompilationContext) { diff --git a/EFCore/src/Query/Internal/MySQLQueryTranslationPostprocessorFactory.cs b/EFCore/src/Query/Internal/MySQLQueryTranslationPostprocessorFactory.cs index 79bd9c4d3..70d18e8d6 100644 --- a/EFCore/src/Query/Internal/MySQLQueryTranslationPostprocessorFactory.cs +++ b/EFCore/src/Query/Internal/MySQLQueryTranslationPostprocessorFactory.cs @@ -51,7 +51,8 @@ public virtual QueryTranslationPostprocessor Create(QueryCompilationContext quer => new MySQLQueryTranslationPostprocessor( _dependencies, _relationalDependencies, - queryCompilationContext, + (MySQLQueryCompilationContext)queryCompilationContext, _options); } + } diff --git a/EFCore/src/Query/Internal/MySQLSqlTranslatingExpressionVisitorFactory.cs b/EFCore/src/Query/Internal/MySQLSqlTranslatingExpressionVisitorFactory.cs index d83df7410..2361df0cb 100644 --- a/EFCore/src/Query/Internal/MySQLSqlTranslatingExpressionVisitorFactory.cs +++ b/EFCore/src/Query/Internal/MySQLSqlTranslatingExpressionVisitorFactory.cs @@ -45,7 +45,7 @@ public virtual RelationalSqlTranslatingExpressionVisitor Create( QueryableMethodTranslatingExpressionVisitor queryableMethodTranslatingExpressionVisitor) => new MySQLSqlTranslatingExpressionVisitor( _dependencies, - model, + (MySQLQueryCompilationContext)model, queryableMethodTranslatingExpressionVisitor); } } diff --git a/EFCore/src/Storage/Internal/MySQLGeometryTypeMapping.cs b/EFCore/src/Storage/Internal/MySQLGeometryTypeMapping.cs index 02572bf57..f808990f1 100644 --- a/EFCore/src/Storage/Internal/MySQLGeometryTypeMapping.cs +++ b/EFCore/src/Storage/Internal/MySQLGeometryTypeMapping.cs @@ -43,7 +43,7 @@ protected MySQLGeometryTypeMapping(RelationalTypeMappingParameters parameters) { } -#if NET8_0 +#if NET8_0_OR_GREATER public CoreTypeMapping Clone(ValueConverter? converter) => new MySQLGeometryTypeMapping(Parameters.WithComposedConverter(converter,null,null,null,null)); #else diff --git a/EFCore/src/Storage/Internal/MySQLTypeMappingSource.cs b/EFCore/src/Storage/Internal/MySQLTypeMappingSource.cs index 5ee73bf1a..a1b59b05b 100644 --- a/EFCore/src/Storage/Internal/MySQLTypeMappingSource.cs +++ b/EFCore/src/Storage/Internal/MySQLTypeMappingSource.cs @@ -187,7 +187,7 @@ protected void Initialize() { typeof(byte), _utinyint }, { typeof(sbyte), _tinyint }, - #if !NET8_0 + #if !NET8_0_OR_GREATER // DateTime { typeof(DateTime), _datetime.Clone(6, null) }, { typeof(DateOnly), _dateonly }, @@ -252,7 +252,7 @@ protected void Initialize() if (_storeTypeMappings.TryGetValue(storeTypeNameBase!, out mapping)) { -#if !NET8_0 +#if !NET8_0_OR_GREATER return clrType == null ? mapping[0].Clone(in mappingInfo) : mapping.FirstOrDefault(m => m.ClrType == clrType)?.Clone(in mappingInfo); @@ -274,7 +274,7 @@ protected void Initialize() clrType == typeof(DateTimeOffset) || clrType == typeof(TimeSpan)) { -#if !NET8_0 +#if !NET8_0_OR_GREATER return mapping.Clone(mappingInfo.Precision.Value, null); #else return mapping.WithPrecisionAndScale(mappingInfo.Precision.Value, null); @@ -301,7 +301,7 @@ protected void Initialize() mapping = isFixedLength ? _charUnicode : size == null ? _longtextUnicode : _varcharUnicode; -#if !NET8_0 +#if !NET8_0_OR_GREATER return size == null ? mapping : mapping.Clone($"{mapping.StoreTypeNameBase}({size})", size); #else return size == null ? mapping : mapping.WithStoreTypeAndSize($"{mapping.StoreTypeNameBase}({size})", size); @@ -320,7 +320,7 @@ protected void Initialize() return null; } -#if !NET8_0 +#if !NET8_0_OR_GREATER protected override string ParseStoreTypeName(string? storeTypeName, out bool? unicode, out int? size, out int? precision, out int? scale) { var storeTypeBaseName = base.ParseStoreTypeName(storeTypeName, out unicode, out size, out precision, out scale); diff --git a/EFCore/src/Update/IMySQLUpdateSqlGenerator.cs b/EFCore/src/Update/IMySQLUpdateSqlGenerator.cs index 5e94a0019..8b396ecfc 100644 --- a/EFCore/src/Update/IMySQLUpdateSqlGenerator.cs +++ b/EFCore/src/Update/IMySQLUpdateSqlGenerator.cs @@ -42,7 +42,7 @@ ResultSetMapping AppendBulkInsertOperation( [NotNull] IReadOnlyList modificationCommands, int commandPosition); } -#elif NET8_0 +#elif NET8_0_OR_GREATER /// /// /// The service lifetime is . This means a single instance diff --git a/EFCore/src/Update/MySQLModificationCommandBatch.cs b/EFCore/src/Update/MySQLModificationCommandBatch.cs index 965390c17..bcf6df3b9 100644 --- a/EFCore/src/Update/MySQLModificationCommandBatch.cs +++ b/EFCore/src/Update/MySQLModificationCommandBatch.cs @@ -55,7 +55,7 @@ internal class MySQLModificationCommandBatch : AffectedCountModificationCommandB private readonly int _maxBatchSize; private readonly List _bulkInsertCommands = new List(); private int _commandsLeftToLengthCheck = 50; -#elif NET8_0 +#elif NET8_0_OR_GREATER private readonly List _pendingBulkInsertCommands = new(); #endif @@ -200,7 +200,7 @@ protected override void UpdateCachedCommandText(int commandPosition) } } -#elif NET8_0 +#elif NET8_0_OR_GREATER /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to /// the same compatibility standards as public APIs. It may be changed or removed without notice in diff --git a/EFCore/src/Update/MySQLUpdateSqlGenerator.cs b/EFCore/src/Update/MySQLUpdateSqlGenerator.cs index b94d96dba..b7e5431ec 100644 --- a/EFCore/src/Update/MySQLUpdateSqlGenerator.cs +++ b/EFCore/src/Update/MySQLUpdateSqlGenerator.cs @@ -233,7 +233,7 @@ internal enum ResultsGrouping OneResultSet, OneCommandPerResultSet } -#elif NET8_0 +#elif NET8_0_OR_GREATER public virtual ResultSetMapping AppendBulkInsertOperation( StringBuilder commandStringBuilder, IReadOnlyList modificationCommands, diff --git a/EFCore/src/ValueGeneration/Internal/MySQLValueGeneratorSelector.cs b/EFCore/src/ValueGeneration/Internal/MySQLValueGeneratorSelector.cs index 47119f3f1..a332347e1 100644 --- a/EFCore/src/ValueGeneration/Internal/MySQLValueGeneratorSelector.cs +++ b/EFCore/src/ValueGeneration/Internal/MySQLValueGeneratorSelector.cs @@ -52,7 +52,7 @@ public MySQLValueGeneratorSelector( } - #if NET8_0 + #if NET8_0_OR_GREATER /// public ValueGenerator Create(IProperty property, IEntityType entityType) { diff --git a/EFCore/src/global.json b/EFCore/src/global.json deleted file mode 100644 index a8ab760dd..000000000 --- a/EFCore/src/global.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "sdk": { - "allowPrerelease": false - } -} \ No newline at end of file diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/ConnectionTests.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/ConnectionTests.cs index e919b9341..3f32516bf 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/ConnectionTests.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/ConnectionTests.cs @@ -85,7 +85,7 @@ public static RelationalConnectionDependencies CreateDependencies(DbContextOptio TestServiceFactory.Instance.Create(), new MySQLOptions())))); } -#elif NET8_0 +#elif NET8_0_OR_GREATER public static RelationalConnectionDependencies CreateDependencies(DbContextOptions? options = null) { options ??= new DbContextOptionsBuilder() diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/MySql.EntityFrameworkCore.Basic.Tests.csproj b/EFCore/tests/MySql.EFCore.Basic.Tests/MySql.EntityFrameworkCore.Basic.Tests.csproj index c29cff6d4..00582a122 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/MySql.EntityFrameworkCore.Basic.Tests.csproj +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/MySql.EntityFrameworkCore.Basic.Tests.csproj @@ -13,6 +13,10 @@ CS1591,CS1701,CS1702,EF1001 + + net9.0;$(TargetFrameworks) + + @@ -21,6 +25,10 @@ + + + + diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/global.json b/EFCore/tests/MySql.EFCore.Basic.Tests/global.json deleted file mode 100644 index a8ab760dd..000000000 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/global.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "sdk": { - "allowPrerelease": false - } -} \ No newline at end of file diff --git a/EFCore/tests/MySql.EFCore.Design.Tests/MySql.EntityFrameworkCore.Design.Tests.csproj b/EFCore/tests/MySql.EFCore.Design.Tests/MySql.EntityFrameworkCore.Design.Tests.csproj index 939de4597..f047fc92a 100644 --- a/EFCore/tests/MySql.EFCore.Design.Tests/MySql.EntityFrameworkCore.Design.Tests.csproj +++ b/EFCore/tests/MySql.EFCore.Design.Tests/MySql.EntityFrameworkCore.Design.Tests.csproj @@ -13,6 +13,10 @@ $(NoWarn);CS1591,EF1001 + + net9.0;$(TargetFrameworks) + + @@ -24,12 +28,23 @@ - + + + + + + + + + + + + diff --git a/EFCore/tests/MySql.EFCore.Design.Tests/global.json b/EFCore/tests/MySql.EFCore.Design.Tests/global.json deleted file mode 100644 index a8ab760dd..000000000 --- a/EFCore/tests/MySql.EFCore.Design.Tests/global.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "sdk": { - "allowPrerelease": false - } -} \ No newline at end of file diff --git a/EFCore/tests/MySql.EFCore.Migrations.Tests/MySql.EntityFrameworkCore.Migrations.Tests.csproj b/EFCore/tests/MySql.EFCore.Migrations.Tests/MySql.EntityFrameworkCore.Migrations.Tests.csproj index a0c036a21..429a0cc63 100644 --- a/EFCore/tests/MySql.EFCore.Migrations.Tests/MySql.EntityFrameworkCore.Migrations.Tests.csproj +++ b/EFCore/tests/MySql.EFCore.Migrations.Tests/MySql.EntityFrameworkCore.Migrations.Tests.csproj @@ -13,6 +13,10 @@ $(NoWarn);CS1591,EF1001 + + net9.0;$(TargetFrameworks) + + diff --git a/EFCore/tests/MySql.EFCore.Migrations.Tests/global.json b/EFCore/tests/MySql.EFCore.Migrations.Tests/global.json deleted file mode 100644 index a8ab760dd..000000000 --- a/EFCore/tests/MySql.EFCore.Migrations.Tests/global.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "sdk": { - "allowPrerelease": false - } -} \ No newline at end of file diff --git a/EntityFramework/src/global.json b/EntityFramework/src/global.json deleted file mode 100644 index a8ab760dd..000000000 --- a/EntityFramework/src/global.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "sdk": { - "allowPrerelease": false - } -} \ No newline at end of file diff --git a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/global.json b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/global.json deleted file mode 100644 index a8ab760dd..000000000 --- a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/global.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "sdk": { - "allowPrerelease": false - } -} \ No newline at end of file diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/global.json b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/global.json deleted file mode 100644 index a8ab760dd..000000000 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/global.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "sdk": { - "allowPrerelease": false - } -} \ No newline at end of file diff --git a/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/global.json b/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/global.json deleted file mode 100644 index a8ab760dd..000000000 --- a/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/global.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "sdk": { - "allowPrerelease": false - } -} \ No newline at end of file diff --git a/MySQL.Data.OpenTelemetry/src/global.json b/MySQL.Data.OpenTelemetry/src/global.json deleted file mode 100644 index a8ab760dd..000000000 --- a/MySQL.Data.OpenTelemetry/src/global.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "sdk": { - "allowPrerelease": false - } -} \ No newline at end of file diff --git a/MySQL.Data/src/MySql.Data.csproj b/MySQL.Data/src/MySql.Data.csproj index 39432847d..78f716ab5 100644 --- a/MySQL.Data/src/MySql.Data.csproj +++ b/MySQL.Data/src/MySql.Data.csproj @@ -35,6 +35,10 @@ true + + net9.0;$(TargetFrameworks) + + net462;net48;$(TargetFrameworks) @@ -81,7 +85,7 @@ - + diff --git a/MySQL.Data/src/MySqlDataReader.cs b/MySQL.Data/src/MySqlDataReader.cs index 32a441b48..ff86e4368 100644 --- a/MySQL.Data/src/MySqlDataReader.cs +++ b/MySQL.Data/src/MySqlDataReader.cs @@ -336,7 +336,7 @@ public sbyte GetSByte(int i) if (v is MySqlByte) return (sbyte)ChangeType(v, i, typeof(sbyte)); else -#if !NET8_0 +#if !NET8_0_OR_GREATER return checked(((MySqlByte)v).Value); #else return checked((sbyte)((MySqlUByte)v).Value); diff --git a/MySQL.Data/src/global.json b/MySQL.Data/src/global.json deleted file mode 100644 index a8ab760dd..000000000 --- a/MySQL.Data/src/global.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "sdk": { - "allowPrerelease": false - } -} \ No newline at end of file diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/BlobTestsPipe.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/BlobTestsPipe.cs index 645764316..36a9281a9 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/BlobTestsPipe.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/BlobTestsPipe.cs @@ -26,14 +26,12 @@ // along with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +using NUnit.Framework.Internal; + namespace MySql.Data.MySqlClient.Tests { public class BlobTestsPipe : BlobTests { - public BlobTestsPipe(TestFixture fixture) : base(fixture) - { - } - internal override void AdjustConnectionSettings(MySqlConnectionStringBuilder settings) { settings.ConnectionProtocol = MySqlConnectionProtocol.NamedPipe; diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/BlobTestsPipeCompressed.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/BlobTestsPipeCompressed.cs index 880541c8f..bd69d5086 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/BlobTestsPipeCompressed.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/BlobTestsPipeCompressed.cs @@ -27,6 +27,7 @@ // 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +using NUnit.Framework.Internal; using System.ComponentModel; namespace MySql.Data.MySqlClient.Tests @@ -34,11 +35,6 @@ namespace MySql.Data.MySqlClient.Tests [Category("Compressed")] public class BlobTestsPipeCompressed : BlobTests { - public BlobTestsPipeCompressed(TestFixture fixture) : base(fixture) - { - - } - internal override void AdjustConnectionSettings(MySqlConnectionStringBuilder settings) { settings.ConnectionProtocol = MySqlConnectionProtocol.NamedPipe; diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/BlobTestsSharedMem.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/BlobTestsSharedMem.cs index 163a24b5b..c70b45b11 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/BlobTestsSharedMem.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/BlobTestsSharedMem.cs @@ -27,15 +27,12 @@ // 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +using NUnit.Framework.Internal; + namespace MySql.Data.MySqlClient.Tests { public class BlobTestsSharedMem : BlobTests { - - public BlobTestsSharedMem(TestFixture fixture) : base(fixture) - { - } - internal override void AdjustConnectionSettings(MySqlConnectionStringBuilder settings) { settings.ConnectionProtocol = MySqlConnectionProtocol.SharedMemory; diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/BlobTestsSharedMemCompressed.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/BlobTestsSharedMemCompressed.cs index 36c8932ad..bd6193578 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/BlobTestsSharedMemCompressed.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/BlobTestsSharedMemCompressed.cs @@ -27,6 +27,7 @@ // 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +using NUnit.Framework.Internal; using System.ComponentModel; namespace MySql.Data.MySqlClient.Tests @@ -34,11 +35,6 @@ namespace MySql.Data.MySqlClient.Tests [Category("Compressed")] public class BlobTestsSharedMemCompressed : BlobTests { - public BlobTestsSharedMemCompressed(TestFixture fixture) : base(fixture) - { - - } - internal override void AdjustConnectionSettings(MySqlConnectionStringBuilder settings) { settings.ConnectionProtocol = MySqlConnectionProtocol.SharedMemory; diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/CmdTestsPipe.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/CmdTestsPipe.cs index 8a98b187b..d5e732c1b 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/CmdTestsPipe.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/CmdTestsPipe.cs @@ -31,11 +31,6 @@ namespace MySql.Data.MySqlClient.Tests { public class CmdTestsPipe : CmdTests { - - public CmdTestsPipe(TestFixture fixture) : base(fixture) - { - } - internal override void AdjustConnectionSettings(MySqlConnectionStringBuilder settings) { settings.ConnectionProtocol = MySqlConnectionProtocol.NamedPipe; diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/CmdTestsPipeCompressed.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/CmdTestsPipeCompressed.cs index 68ec9c1b1..3e00525f3 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/CmdTestsPipeCompressed.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/CmdTestsPipeCompressed.cs @@ -26,16 +26,13 @@ // along with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +using NUnit.Framework.Internal; using System; namespace MySql.Data.MySqlClient.Tests { public class CmdTestsPipeCompressed : CmdTests { - public CmdTestsPipeCompressed(TestFixture fixture) : base(fixture) - { - } - internal override void AdjustConnectionSettings(MySqlConnectionStringBuilder settings) { settings.ConnectionProtocol = MySqlConnectionProtocol.NamedPipe; diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/CmdTestsSharedMem.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/CmdTestsSharedMem.cs index 75533132f..17945408a 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/CmdTestsSharedMem.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/CmdTestsSharedMem.cs @@ -26,14 +26,12 @@ // along with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +using NUnit.Framework.Internal; + namespace MySql.Data.MySqlClient.Tests { public class CmdTestsSharedMem : CmdTests { - public CmdTestsSharedMem(TestFixture fixture) : base(fixture) - { - } - internal override void AdjustConnectionSettings(MySqlConnectionStringBuilder settings) { settings.ConnectionProtocol = MySqlConnectionProtocol.SharedMemory; diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/CmdTestsSharedmemCompressed.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/CmdTestsSharedmemCompressed.cs index a5a61238e..f92501fdd 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/CmdTestsSharedmemCompressed.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/CmdTestsSharedmemCompressed.cs @@ -31,11 +31,6 @@ namespace MySql.Data.MySqlClient.Tests { public class CmdTestsSharedMemCompressed : CmdTests { - - public CmdTestsSharedMemCompressed(TestFixture fixture) : base(fixture) - { - } - internal override void AdjustConnectionSettings(MySqlConnectionStringBuilder settings) { settings.ConnectionProtocol = MySqlConnectionProtocol.SharedMemory; diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/PSPipe.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/PSPipe.cs index 556ed12d6..310dbc630 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/PSPipe.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/PSPipe.cs @@ -30,11 +30,6 @@ namespace MySql.Data.MySqlClient.Tests { public class PSPipe : PreparedStatements { - - public PSPipe(TestFixture fixture) : base(fixture) - { - } - internal override void AdjustConnectionSettings(MySqlConnectionStringBuilder settings) { settings.ConnectionProtocol = MySqlConnectionProtocol.NamedPipe; diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/PSPipeCompressed.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/PSPipeCompressed.cs index 8554aa4da..c67b92fe1 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/PSPipeCompressed.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/PSPipeCompressed.cs @@ -26,15 +26,12 @@ // along with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +using NUnit.Framework.Internal; + namespace MySql.Data.MySqlClient.Tests { public class PSPipeCompressed : PreparedStatements { - - public PSPipeCompressed(TestFixture fixture) : base(fixture) - { - } - internal override void AdjustConnectionSettings(MySqlConnectionStringBuilder settings) { settings.ConnectionProtocol = MySqlConnectionProtocol.NamedPipe; diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/PSSharedMemory.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/PSSharedMemory.cs index 93c1b3ee5..3c9bcb2d6 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/PSSharedMemory.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/PSSharedMemory.cs @@ -26,14 +26,12 @@ // along with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +using NUnit.Framework.Internal; + namespace MySql.Data.MySqlClient.Tests { public class PSSharedMemory : PreparedStatements { - public PSSharedMemory(TestFixture fixture) : base (fixture) - { - } - internal override void AdjustConnectionSettings(MySqlConnectionStringBuilder settings) { settings.ConnectionProtocol = MySqlConnectionProtocol.SharedMemory; diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/PSSharedMemoryCompressed.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/PSSharedMemoryCompressed.cs index ea2b05efb..ae6452fb4 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/PSSharedMemoryCompressed.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/PSSharedMemoryCompressed.cs @@ -26,14 +26,12 @@ // along with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +using NUnit.Framework.Internal; + namespace MySql.Data.MySqlClient.Tests { public class PSSharedMemoryCompressed : PreparedStatements { - public PSSharedMemoryCompressed(TestFixture fixture) : base(fixture) - { - } - internal override void AdjustConnectionSettings(MySqlConnectionStringBuilder settings) { settings.ConnectionProtocol = MySqlConnectionProtocol.SharedMemory; diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/StressTestsPipe.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/StressTestsPipe.cs index ce7589b61..0e5345faa 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/StressTestsPipe.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/StressTestsPipe.cs @@ -30,10 +30,6 @@ namespace MySql.Data.MySqlClient.Tests { public class StressTestsPipe : StressTests { - public StressTestsPipe(TestFixture fixture) : base(fixture) - { - } - internal override void AdjustConnectionSettings(MySqlConnectionStringBuilder settings) { settings.ConnectionProtocol = MySqlConnectionProtocol.NamedPipe; diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/StressTestsPipeCompressed.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/StressTestsPipeCompressed.cs index 0fcbf6fab..5c64fedf6 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/StressTestsPipeCompressed.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/StressTestsPipeCompressed.cs @@ -26,14 +26,12 @@ // along with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +using NUnit.Framework.Internal; + namespace MySql.Data.MySqlClient.Tests { public class StressTestsPipeCompressed : StressTests { - public StressTestsPipeCompressed(TestFixture fixture) : base(fixture) - { - } - internal override void AdjustConnectionSettings(MySqlConnectionStringBuilder settings) { settings.ConnectionProtocol = MySqlConnectionProtocol.NamedPipe; diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/StressTestsSharedMemory.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/StressTestsSharedMemory.cs index 794e92c25..6944ff02e 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/StressTestsSharedMemory.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/StressTestsSharedMemory.cs @@ -26,14 +26,12 @@ // along with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +using NUnit.Framework.Internal; + namespace MySql.Data.MySqlClient.Tests { public class StressTestsSharedMemory : StressTests { - public StressTestsSharedMemory(TestFixture fixture) : base(fixture) - { - } - internal override void AdjustConnectionSettings(MySqlConnectionStringBuilder settings) { settings.ConnectionProtocol = MySqlConnectionProtocol.SharedMemory; diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/StressTestsSharedMemoryCompressed.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/StressTestsSharedMemoryCompressed.cs index 8872d295d..681d90af5 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/StressTestsSharedMemoryCompressed.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/StressTestsSharedMemoryCompressed.cs @@ -26,11 +26,13 @@ // along with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +using NUnit.Framework.Internal; + namespace MySql.Data.MySqlClient.Tests { public class StressTestsSharedMemoryCompressed : StressTests { - public StressTestsSharedMemoryCompressed(TestFixture fixture) : base(fixture) + public StressTestsSharedMemoryCompressed() : base() { } diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/TimeoutAndCancel.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/TimeoutAndCancel.cs index 51ff85733..5d3fb086b 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/TimeoutAndCancel.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/TimeoutAndCancel.cs @@ -33,6 +33,7 @@ using System.Data; using System.Globalization; using System.IO; +using NUnit.Framework.Internal; namespace MySql.Data.MySqlClient.Tests { diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/TimeoutAndCancelPipe.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/TimeoutAndCancelPipe.cs index db56d7dd4..403617770 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/TimeoutAndCancelPipe.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/TimeoutAndCancelPipe.cs @@ -30,10 +30,6 @@ namespace MySql.Data.MySqlClient.Tests { public class TimeoutAndCancelPipe : TimeoutAndCancel { - public TimeoutAndCancelPipe(TestFixture fixture) : base(fixture) - { - } - internal override void AdjustConnectionSettings(MySqlConnectionStringBuilder settings) { settings.ConnectionProtocol = MySqlConnectionProtocol.NamedPipe; diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/TimeoutAndCancelSharedMemory.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/TimeoutAndCancelSharedMemory.cs index 811c4d7a2..eee7c5c24 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/TimeoutAndCancelSharedMemory.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/TimeoutAndCancelSharedMemory.cs @@ -28,11 +28,13 @@ +using NUnit.Framework.Internal; + namespace MySql.Data.MySqlClient.Tests { public class TimeoutAndCancelSharedMemory : TimeoutAndCancel { - public TimeoutAndCancelSharedMemory(TestFixture fixture) : base(fixture) + public TimeoutAndCancelSharedMemory() : base() { } diff --git a/MySQL.Data/tests/MySql.Data.Tests/MySql.Data.Tests.csproj b/MySQL.Data/tests/MySql.Data.Tests/MySql.Data.Tests.csproj index 3af700db8..03175dec2 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/MySql.Data.Tests.csproj +++ b/MySQL.Data/tests/MySql.Data.Tests/MySql.Data.Tests.csproj @@ -8,7 +8,7 @@ Oracle Oracle MySql.Data.Tests - net8.0;net6.0 + net8.0;net6.0; MySql.Data.Tests MySql;.NET Connector;MySql Connector/NET;netcore;.Net Core;MySql Conector/Net Core;coreclr;C/NET;C/Net Core http://www.mysql.com/common/logos/logo-mysql-170x115.png @@ -28,11 +28,15 @@ CS1591,CS1587,CS1701,CS1702,CS1570,CA2100 + + net9.0;$(TargetFrameworks) + + net462;net48;$(TargetFrameworks) - + diff --git a/MySQL.Data/tests/MySql.Data.Tests/global.json b/MySQL.Data/tests/MySql.Data.Tests/global.json deleted file mode 100644 index a8ab760dd..000000000 --- a/MySQL.Data/tests/MySql.Data.Tests/global.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "sdk": { - "allowPrerelease": false - } -} \ No newline at end of file diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/MySqlX.Data.Tests.csproj b/MySQL.Data/tests/MySqlX.Data.Tests/MySqlX.Data.Tests.csproj index 27f1dff62..5f3390b1e 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/MySqlX.Data.Tests.csproj +++ b/MySQL.Data/tests/MySqlX.Data.Tests/MySqlX.Data.Tests.csproj @@ -8,7 +8,7 @@ Oracle Oracle MySql.Data.Tests - net8.0;net6.0 + net8.0;net6.0; MySqlx.Data.Tests MySql;.NET Connector;MySql Connector/NET;netcore;.Net Core;MySql Conector/Net Core;coreclr;C/NET;C/Net Core http://www.mysql.com/common/logos/logo-mysql-170x115.png @@ -28,6 +28,10 @@ latest + + net9.0;$(TargetFrameworks) + + net462;net48;$(TargetFrameworks) diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/global.json b/MySQL.Data/tests/MySqlX.Data.Tests/global.json deleted file mode 100644 index a8ab760dd..000000000 --- a/MySQL.Data/tests/MySqlX.Data.Tests/global.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "sdk": { - "allowPrerelease": false - } -} \ No newline at end of file diff --git a/MySql.Web/src/global.json b/MySql.Web/src/global.json deleted file mode 100644 index a8ab760dd..000000000 --- a/MySql.Web/src/global.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "sdk": { - "allowPrerelease": false - } -} \ No newline at end of file diff --git a/MySql.Web/tests/global.json b/MySql.Web/tests/global.json deleted file mode 100644 index a8ab760dd..000000000 --- a/MySql.Web/tests/global.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "sdk": { - "allowPrerelease": false - } -} \ No newline at end of file From 5aec3146a8876f67fda0b58d69c20421fb7e2e44 Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Fri, 9 Aug 2024 07:56:03 -0600 Subject: [PATCH 063/125] Updated dependencies Change-Id: Ida31ef86e84df57396cf23cc4e1dcf29182f3dbf --- MySQL.Data/src/MySql.Data.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MySQL.Data/src/MySql.Data.csproj b/MySQL.Data/src/MySql.Data.csproj index 78f716ab5..9f57e77ce 100644 --- a/MySQL.Data/src/MySql.Data.csproj +++ b/MySQL.Data/src/MySql.Data.csproj @@ -90,7 +90,7 @@ - + From 69812d8cab6fcfc8d214e7032fc57efeeef959fa Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Tue, 2 Jul 2024 10:30:19 -0600 Subject: [PATCH 064/125] WL#16453 [Add OpenTelemetry.Api NuGet package] Change-Id: I6e1008abd8f752f90e4e934517a2a87b52ceb675 --- CHANGES | 1 + .../OpenTelemetry.Api/OpenTelemetry.Api.dll | Bin 87640 -> 0 bytes .../src/MySQL.Data.OpenTelemetry.csproj | 5 ++--- 3 files changed, 3 insertions(+), 3 deletions(-) delete mode 100644 Dependencies/OpenTelemetry.Api/OpenTelemetry.Api.dll diff --git a/CHANGES b/CHANGES index 78347380f..a9d5cdf86 100644 --- a/CHANGES +++ b/CHANGES @@ -2,6 +2,7 @@ - Updated test suite to use constraint-based assertions (WL16397). - Changed testsuite to use assummptions instead of Assert.Ignore (WL16402). - Added support for .NET 9 and EFCore 9 preview versions (WL16308). +- Added OpenTelemetry.Api NuGet package reference (WL16453). 9.0.0 diff --git a/Dependencies/OpenTelemetry.Api/OpenTelemetry.Api.dll b/Dependencies/OpenTelemetry.Api/OpenTelemetry.Api.dll deleted file mode 100644 index 9f8aee47ff594dc9b067567faa8014c4496684f0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 87640 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 Ivgb(u2WYJzQ~&?~ diff --git a/MySQL.Data.OpenTelemetry/src/MySQL.Data.OpenTelemetry.csproj b/MySQL.Data.OpenTelemetry/src/MySQL.Data.OpenTelemetry.csproj index 96097c5f2..d2d44f5c7 100644 --- a/MySQL.Data.OpenTelemetry/src/MySQL.Data.OpenTelemetry.csproj +++ b/MySQL.Data.OpenTelemetry/src/MySQL.Data.OpenTelemetry.csproj @@ -40,8 +40,7 @@ - - ..\..\Dependencies\OpenTelemetry.Api\OpenTelemetry.Api.dll - + + \ No newline at end of file From 70518f25aea6c2da6600f551e28cd4e255734594 Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Tue, 27 Aug 2024 16:00:48 -0600 Subject: [PATCH 065/125] Formatted Resources and ResourcesX files. Change-Id: I63d58c77a09856e77dc1ea2b9d9fcc658a2c1806 --- MySQL.Data/src/Resources.Designer.cs | 250 +++++++++++++------------- MySQL.Data/src/Resources.resx | 250 +++++++++++++------------- MySQL.Data/src/ResourcesX.Designer.cs | 126 ++++++------- MySQL.Data/src/ResourcesX.resx | 126 ++++++------- 4 files changed, 376 insertions(+), 376 deletions(-) diff --git a/MySQL.Data/src/Resources.Designer.cs b/MySQL.Data/src/Resources.Designer.cs index c937bc965..991529e42 100644 --- a/MySQL.Data/src/Resources.Designer.cs +++ b/MySQL.Data/src/Resources.Designer.cs @@ -97,7 +97,7 @@ internal static string AuthenticationFailed { } /// - /// Looks up a localized string similar to Authentication method '{0}' not supported by any of the available plugins.. + /// Looks up a localized string similar to Authentication method '{0}' not supported by any of the available plugins. /// internal static string AuthenticationMethodNotSupported { get { @@ -106,7 +106,7 @@ internal static string AuthenticationMethodNotSupported { } /// - /// Looks up a localized string similar to Authentication plugin '{0}' is currently not supported.. + /// Looks up a localized string similar to Authentication plugin '{0}' is currently not supported. /// internal static string AuthenticationPluginNotSupported { get { @@ -142,7 +142,7 @@ internal static string BufferNotLargeEnough { } /// - /// Looks up a localized string similar to Canceling an executing query requires MySQL 5.0 or higher.. + /// Looks up a localized string similar to Canceling an executing query requires MySQL 5.0 or higher. /// internal static string CancelNeeds50 { get { @@ -151,7 +151,7 @@ internal static string CancelNeeds50 { } /// - /// Looks up a localized string similar to Canceling an active query is only supported on MySQL 5.0.0 and above. . + /// Looks up a localized string similar to Canceling an active query is only supported on MySQL 5.0.0 and above. /// internal static string CancelNotSupported { get { @@ -160,7 +160,7 @@ internal static string CancelNotSupported { } /// - /// Looks up a localized string similar to Parameters can only be derived for commands using the StoredProcedure command type.. + /// Looks up a localized string similar to Parameters can only be derived for commands using the StoredProcedure command type. /// internal static string CanNotDeriveParametersForTextCommands { get { @@ -196,7 +196,7 @@ internal static string ChaosNotSupported { } /// - /// Looks up a localized string similar to Clear-password authentication is not supported over insecure channels.. + /// Looks up a localized string similar to Clear-password authentication is not supported over insecure channels. /// internal static string ClearPasswordNotSupported { get { @@ -205,7 +205,7 @@ internal static string ClearPasswordNotSupported { } /// - /// Looks up a localized string similar to The CommandText property has not been properly initialized.. + /// Looks up a localized string similar to The CommandText property has not been properly initialized. /// internal static string CommandTextNotInitialized { get { @@ -214,7 +214,7 @@ internal static string CommandTextNotInitialized { } /// - /// Looks up a localized string similar to Compression is not supported.. + /// Looks up a localized string similar to Compression is not supported. /// internal static string CompressionNotSupported { get { @@ -223,7 +223,7 @@ internal static string CompressionNotSupported { } /// - /// Looks up a localized string similar to The connection is already open.. + /// Looks up a localized string similar to The connection is already open. /// internal static string ConnectionAlreadyOpen { get { @@ -232,7 +232,7 @@ internal static string ConnectionAlreadyOpen { } /// - /// Looks up a localized string similar to Connection unexpectedly terminated.. + /// Looks up a localized string similar to Connection unexpectedly terminated. /// internal static string ConnectionBroken { get { @@ -250,7 +250,7 @@ internal static string ConnectionMustBeOpen { } /// - /// Looks up a localized string similar to The connection is not open.. + /// Looks up a localized string similar to The connection is not open. /// internal static string ConnectionNotOpen { get { @@ -259,7 +259,7 @@ internal static string ConnectionNotOpen { } /// - /// Looks up a localized string similar to The connection property has not been set or is null.. + /// Looks up a localized string similar to The connection property has not been set or is null. /// internal static string ConnectionNotSet { get { @@ -295,7 +295,7 @@ internal static string CSNoSetLength { } /// - /// Looks up a localized string similar to The given value was not in a supported format.. + /// Looks up a localized string similar to The given value was not in a supported format. /// internal static string DataNotInSupportedFormat { get { @@ -304,7 +304,7 @@ internal static string DataNotInSupportedFormat { } /// - /// Looks up a localized string similar to There is already an open DataReader associated with this Connection which must be closed first.. + /// Looks up a localized string similar to There is already an open DataReader associated with this Connection which must be closed first. /// internal static string DataReaderOpen { get { @@ -313,7 +313,7 @@ internal static string DataReaderOpen { } /// - /// Looks up a localized string similar to The default connection encoding was not found. Please report this as a bug along with your connection string and system details.. + /// Looks up a localized string similar to The default connection encoding was not found. Please report this as a bug along with your connection string and system details. /// internal static string DefaultEncodingNotFound { get { @@ -322,7 +322,7 @@ internal static string DefaultEncodingNotFound { } /// - /// Looks up a localized string similar to MySQL Connector/NET does not currently support distributed transactions.. + /// Looks up a localized string similar to MySQL Connector/NET does not currently support distributed transactions. /// internal static string DistributedTxnNotSupported { get { @@ -331,7 +331,7 @@ internal static string DistributedTxnNotSupported { } /// - /// Looks up a localized string similar to Specifying multiple host names with DNS SRV lookup is not permitted.. + /// Looks up a localized string similar to Specifying multiple host names with DNS SRV lookup is not permitted. /// internal static string DnsSrvInvalidConnOptionMultihost { get { @@ -340,7 +340,7 @@ internal static string DnsSrvInvalidConnOptionMultihost { } /// - /// Looks up a localized string similar to Specifying a port number with DNS SRV lookup is not permitted.. + /// Looks up a localized string similar to Specifying a port number with DNS SRV lookup is not permitted. /// internal static string DnsSrvInvalidConnOptionPort { get { @@ -349,7 +349,7 @@ internal static string DnsSrvInvalidConnOptionPort { } /// - /// Looks up a localized string similar to Using Unix domain sockets with DNS SRV lookup is not permitted.. + /// Looks up a localized string similar to Using Unix domain sockets with DNS SRV lookup is not permitted. /// internal static string DnsSrvInvalidConnOptionUnixSocket { get { @@ -358,7 +358,7 @@ internal static string DnsSrvInvalidConnOptionUnixSocket { } /// - /// Looks up a localized string similar to Unable to locate any hosts for {0}.. + /// Looks up a localized string similar to Unable to locate any hosts for {0}. /// internal static string DnsSrvNoHostsAvailable { get { @@ -367,7 +367,7 @@ internal static string DnsSrvNoHostsAvailable { } /// - /// Looks up a localized string similar to Encoding error during validation.. + /// Looks up a localized string similar to Encoding error during validation. /// internal static string EncodingError { get { @@ -385,7 +385,7 @@ internal static string ErrorCreatingSocket { } /// - /// Looks up a localized string similar to Verify that user '{0}'@'{1}' has enough privileges to execute.. + /// Looks up a localized string similar to Verify that user '{0}'@'{1}' has enough privileges to execute. /// internal static string ExecuteProcedureUnauthorized { get { @@ -394,7 +394,7 @@ internal static string ExecuteProcedureUnauthorized { } /// - /// Looks up a localized string similar to Fatal error encountered during command execution.. + /// Looks up a localized string similar to Fatal error encountered during command execution. /// internal static string FatalErrorDuringExecute { get { @@ -403,7 +403,7 @@ internal static string FatalErrorDuringExecute { } /// - /// Looks up a localized string similar to Fatal error encountered during data read.. + /// Looks up a localized string similar to Fatal error encountered during data read. /// internal static string FatalErrorDuringRead { get { @@ -412,7 +412,7 @@ internal static string FatalErrorDuringRead { } /// - /// Looks up a localized string similar to Fatal error encountered attempting to read the resultset.. + /// Looks up a localized string similar to Fatal error encountered attempting to read the resultset. /// internal static string FatalErrorReadingResult { get { @@ -421,7 +421,7 @@ internal static string FatalErrorReadingResult { } /// - /// Looks up a localized string similar to Challenge received is corrupt.. + /// Looks up a localized string similar to Challenge received is corrupt. /// internal static string FidoChallengeCorrupt { get { @@ -430,7 +430,7 @@ internal static string FidoChallengeCorrupt { } /// - /// Looks up a localized string similar to FIDO registration is missing.. + /// Looks up a localized string similar to FIDO registration is missing. /// internal static string FidoRegistrationMissing { get { @@ -439,7 +439,7 @@ internal static string FidoRegistrationMissing { } /// - /// Looks up a localized string similar to File based certificates are only supported when connecting to MySQL Server 5.1 or greater.. + /// Looks up a localized string similar to File based certificates are only supported when connecting to MySQL Server 5.1 or greater. /// internal static string FileBasedCertificateNotSupported { get { @@ -448,7 +448,7 @@ internal static string FileBasedCertificateNotSupported { } /// - /// Looks up a localized string similar to The specified file cannot be converted to a certificate.. + /// Looks up a localized string similar to The specified file cannot be converted to a certificate. /// internal static string FileIsNotACertificate { get { @@ -457,7 +457,7 @@ internal static string FileIsNotACertificate { } /// - /// Looks up a localized string similar to The specified file cannot be converted to a key.. + /// Looks up a localized string similar to The specified file cannot be converted to a key. /// internal static string FileIsNotAKey { get { @@ -466,7 +466,7 @@ internal static string FileIsNotAKey { } /// - /// Looks up a localized string similar to Failed to read file at the specified location.. + /// Looks up a localized string similar to Failed to read file at the specified location. /// internal static string FileNotFound { get { @@ -475,7 +475,7 @@ internal static string FileNotFound { } /// - /// Looks up a localized string similar to No file path has been provided for the connection option {0}.. + /// Looks up a localized string similar to No file path has been provided for the connection option {0}. /// internal static string FilePathNotSet { get { @@ -502,7 +502,7 @@ internal static string FromIndexMustBeValid { } /// - /// Looks up a localized string similar to Call to GetHostEntry failed after {0} while querying for hostname '{1}': SocketErrorCode={2}, ErrorCode={3}, NativeErrorCode={4}.. + /// Looks up a localized string similar to Call to GetHostEntry failed after {0} while querying for hostname '{1}': SocketErrorCode={2}, ErrorCode={3}, NativeErrorCode={4}. /// internal static string GetHostEntryFailed { get { @@ -511,7 +511,7 @@ internal static string GetHostEntryFailed { } /// - /// Looks up a localized string similar to Retrieving procedure metadata for {0} from server.. + /// Looks up a localized string similar to Retrieving procedure metadata for {0} from server. /// internal static string HardProcQuery { get { @@ -520,7 +520,7 @@ internal static string HardProcQuery { } /// - /// Looks up a localized string similar to Value has an unsupported format.. + /// Looks up a localized string similar to Value has an unsupported format. /// internal static string ImproperValueFormat { get { @@ -529,7 +529,7 @@ internal static string ImproperValueFormat { } /// - /// Looks up a localized string similar to An incorrect response was received from the server.. + /// Looks up a localized string similar to An incorrect response was received from the server. /// internal static string IncorrectTransmission { get { @@ -556,7 +556,7 @@ internal static string IndexMustBeValid { } /// - /// Looks up a localized string similar to The provided key is invalid.. + /// Looks up a localized string similar to The provided key is invalid. /// internal static string InvalidCertificateKey { get { @@ -565,7 +565,7 @@ internal static string InvalidCertificateKey { } /// - /// Looks up a localized string similar to Certificate with Thumbprint '{0}' not found.. + /// Looks up a localized string similar to Certificate with Thumbprint '{0}' not found. /// internal static string InvalidCertificateThumbprint { get { @@ -574,7 +574,7 @@ internal static string InvalidCertificateThumbprint { } /// - /// Looks up a localized string similar to You have specified an invalid column ordinal.. + /// Looks up a localized string similar to You have specified an invalid column ordinal. /// internal static string InvalidColumnOrdinal { get { @@ -583,7 +583,7 @@ internal static string InvalidColumnOrdinal { } /// - /// Looks up a localized string similar to The requested value '{0}' is invalid for the given keyword '{1}'.. + /// Looks up a localized string similar to The requested value '{0}' is invalid for the given keyword '{1}'. /// internal static string InvalidConnectionStringValue { get { @@ -592,7 +592,7 @@ internal static string InvalidConnectionStringValue { } /// - /// Looks up a localized string similar to The host name or IP address is invalid.. + /// Looks up a localized string similar to The host name or IP address is invalid. /// internal static string InvalidHostNameOrAddress { get { @@ -601,7 +601,7 @@ internal static string InvalidHostNameOrAddress { } /// - /// Looks up a localized string similar to Microsecond must be a value between 0 and 999999.. + /// Looks up a localized string similar to Microsecond must be a value between 0 and 999999. /// internal static string InvalidMicrosecondValue { get { @@ -610,7 +610,7 @@ internal static string InvalidMicrosecondValue { } /// - /// Looks up a localized string similar to Millisecond must be a value between 0 and 999. For more precision use Microsecond.. + /// Looks up a localized string similar to Millisecond must be a value between 0 and 999. For more precision use Microsecond. /// internal static string InvalidMillisecondValue { get { @@ -619,7 +619,7 @@ internal static string InvalidMillisecondValue { } /// - /// Looks up a localized string similar to Either provide a valid path for 'allowloadlocalinfileinpath' or enable 'allowloadlocalinfile'.. + /// Looks up a localized string similar to Either provide a valid path for 'allowloadlocalinfileinpath' or enable 'allowloadlocalinfile'. /// internal static string InvalidPathForLoadLocalInfile { get { @@ -628,7 +628,7 @@ internal static string InvalidPathForLoadLocalInfile { } /// - /// Looks up a localized string similar to Procedure or function '{0}' cannot be found in database '{1}'.. + /// Looks up a localized string similar to Procedure or function '{0}' cannot be found in database '{1}'. /// internal static string InvalidProcName { get { @@ -637,7 +637,7 @@ internal static string InvalidProcName { } /// - /// Looks up a localized string similar to The certificate is invalid.. + /// Looks up a localized string similar to The certificate is invalid. /// internal static string InvalidSslCertificate { get { @@ -646,7 +646,7 @@ internal static string InvalidSslCertificate { } /// - /// Looks up a localized string similar to Unable to validate the signature.. + /// Looks up a localized string similar to Unable to validate the signature. /// internal static string InvalidSslCertificateSignature { get { @@ -655,7 +655,7 @@ internal static string InvalidSslCertificateSignature { } /// - /// Looks up a localized string similar to Unable to verify the signature.. + /// Looks up a localized string similar to Unable to verify the signature. /// internal static string InvalidSslCertificateSignatureGeneral { get { @@ -664,7 +664,7 @@ internal static string InvalidSslCertificateSignatureGeneral { } /// - /// Looks up a localized string similar to Value '{0}' is not of the correct type.. + /// Looks up a localized string similar to Value '{0}' is not of the correct type. /// internal static string InvalidSslMode { get { @@ -673,7 +673,7 @@ internal static string InvalidSslMode { } /// - /// Looks up a localized string similar to '{0}' is an illegal value for a boolean option.. + /// Looks up a localized string similar to '{0}' is an illegal value for a boolean option. /// internal static string InvalidValueForBoolean { get { @@ -682,7 +682,7 @@ internal static string InvalidValueForBoolean { } /// - /// Looks up a localized string similar to Keyword does not allow null values.. + /// Looks up a localized string similar to Keyword does not allow null values. /// internal static string KeywordNoNull { get { @@ -691,7 +691,7 @@ internal static string KeywordNoNull { } /// - /// Looks up a localized string similar to Option not supported.. + /// Looks up a localized string similar to Option not supported. /// internal static string KeywordNotSupported { get { @@ -700,7 +700,7 @@ internal static string KeywordNotSupported { } /// - /// Looks up a localized string similar to Server asked for stream in response to LOAD DATA LOCAL INFILE, but the functionality is disabled by the client setting 'allowlocalinfile' to 'false'.. + /// Looks up a localized string similar to Server asked for stream in response to LOAD DATA LOCAL INFILE, but the functionality is disabled by the client setting 'allowlocalinfile' to 'false'. /// internal static string LocalInfileDisabled { get { @@ -709,7 +709,7 @@ internal static string LocalInfileDisabled { } /// - /// Looks up a localized string similar to Mixing named and unnamed parameters is not allowed.. + /// Looks up a localized string similar to Mixing named and unnamed parameters is not allowed. /// internal static string MixedParameterNamingNotAllowed { get { @@ -718,7 +718,7 @@ internal static string MixedParameterNamingNotAllowed { } /// - /// Looks up a localized string similar to INTERNAL ERROR: More than one output parameter row detected.. + /// Looks up a localized string similar to INTERNAL ERROR: More than one output parameter row detected. /// internal static string MoreThanOneOPRow { get { @@ -727,7 +727,7 @@ internal static string MoreThanOneOPRow { } /// - /// Looks up a localized string similar to Multiple simultaneous connections or connections with different connection strings inside the same transaction are not currently supported.. + /// Looks up a localized string similar to Multiple simultaneous connections or connections with different connection strings inside the same transaction are not currently supported. /// internal static string MultipleConnectionsInTransactionNotSupported { get { @@ -754,7 +754,7 @@ internal static string NamedPipeNoSetLength { } /// - /// Looks up a localized string similar to The new value must be a MySqlParameter object.. + /// Looks up a localized string similar to The new value must be a MySqlParameter object. /// internal static string NewValueShouldBeMySqlParameter { get { @@ -763,7 +763,7 @@ internal static string NewValueShouldBeMySqlParameter { } /// - /// Looks up a localized string similar to Invalid attempt to call NextResult when the reader is closed.. + /// Looks up a localized string similar to Invalid attempt to call NextResult when the reader is closed. /// internal static string NextResultIsClosed { get { @@ -772,7 +772,7 @@ internal static string NextResultIsClosed { } /// - /// Looks up a localized string similar to When calling stored procedures and 'Use Procedure Bodies' is false, all parameters must have their type explicitly set.. + /// Looks up a localized string similar to When calling stored procedures and 'Use Procedure Bodies' is false, all parameters must have their type explicitly set. /// internal static string NoBodiesAndTypeNotSet { get { @@ -781,7 +781,7 @@ internal static string NoBodiesAndTypeNotSet { } /// - /// Looks up a localized string similar to Nested transactions are not supported.. + /// Looks up a localized string similar to Nested transactions are not supported. /// internal static string NoNestedTransactions { get { @@ -790,7 +790,7 @@ internal static string NoNestedTransactions { } /// - /// Looks up a localized string similar to The host {0} does not support SSL connections.. + /// Looks up a localized string similar to The host {0} does not support SSL connections. /// internal static string NoServerSSLSupport { get { @@ -799,7 +799,7 @@ internal static string NoServerSSLSupport { } /// - /// Looks up a localized string similar to Unix sockets are not supported on Windows.. + /// Looks up a localized string similar to Unix sockets are not supported on Windows. /// internal static string NoUnixSocketsOnWindows { get { @@ -808,7 +808,7 @@ internal static string NoUnixSocketsOnWindows { } /// - /// Looks up a localized string similar to Cannot retrieve Windows identity for current user. Connections that use IntegratedSecurity cannot be pooled. Use either 'ConnectionReset=true' or 'Pooling=false' in the connection string to fix.. + /// Looks up a localized string similar to Cannot retrieve Windows identity for current user. Connections that use IntegratedSecurity cannot be pooled. Use either 'ConnectionReset=true' or 'Pooling=false' in the connection string to fix. /// internal static string NoWindowsIdentity { get { @@ -817,7 +817,7 @@ internal static string NoWindowsIdentity { } /// - /// Looks up a localized string similar to The object is not open or has been disposed.. + /// Looks up a localized string similar to The object is not open or has been disposed. /// internal static string ObjectDisposed { get { @@ -826,7 +826,7 @@ internal static string ObjectDisposed { } /// - /// Looks up a localized string similar to OCI configuration file could not be read.. + /// Looks up a localized string similar to OCI configuration file could not be read. /// internal static string OciConfigFileNotFound { get { @@ -835,7 +835,7 @@ internal static string OciConfigFileNotFound { } /// - /// Looks up a localized string similar to OCI configuration profile not found.. + /// Looks up a localized string similar to OCI configuration profile not found. /// internal static string OciConfigProfileNotFound { get { @@ -844,7 +844,7 @@ internal static string OciConfigProfileNotFound { } /// - /// Looks up a localized string similar to OCI configuration file does not contain a 'fingerprint' or 'key_file' entry.. + /// Looks up a localized string similar to OCI configuration file does not contain a 'fingerprint' or 'key_file' entry. /// internal static string OciEntryNotFound { get { @@ -853,7 +853,7 @@ internal static string OciEntryNotFound { } /// - /// Looks up a localized string similar to OCI configuration entry 'key_file' does not reference a valid key file.. + /// Looks up a localized string similar to OCI configuration entry 'key_file' does not reference a valid key file. /// internal static string OciInvalidKeyFile { get { @@ -862,7 +862,7 @@ internal static string OciInvalidKeyFile { } /// - /// Looks up a localized string similar to Private key could not be found at location given by OCI configuration entry 'key_file'.. + /// Looks up a localized string similar to Private key could not be found at location given by OCI configuration entry 'key_file'. /// internal static string OciKeyFileDoesNotExists { get { @@ -871,7 +871,7 @@ internal static string OciKeyFileDoesNotExists { } /// - /// Looks up a localized string similar to The OCI SDK cannot be found or is not installed.. + /// Looks up a localized string similar to The OCI SDK cannot be found or is not installed. /// internal static string OciSDKNotFound { get { @@ -880,7 +880,7 @@ internal static string OciSDKNotFound { } /// - /// Looks up a localized string similar to Secutiry token file could not be found at location given by OCI configuration entry 'security_token_file'.. + /// Looks up a localized string similar to Secutiry token file could not be found at location given by OCI configuration entry 'security_token_file'. /// internal static string OciSecurityTokenDoesNotExists { get { @@ -889,7 +889,7 @@ internal static string OciSecurityTokenDoesNotExists { } /// - /// Looks up a localized string similar to The size of the OCI security token file exceeds the maximum value of 10KB allowed.. + /// Looks up a localized string similar to The size of the OCI security token file exceeds the maximum value of 10KB allowed. /// internal static string OciSecurityTokenFileExceeds10KB { get { @@ -916,7 +916,7 @@ internal static string OffsetMustBeValid { } /// - /// Looks up a localized string similar to Authentication with old password no longer supported, use 4.1 style passwords.. + /// Looks up a localized string similar to Authentication with old password no longer supported, use 4.1 style passwords. /// internal static string OldPasswordsNotSupported { get { @@ -925,7 +925,7 @@ internal static string OldPasswordsNotSupported { } /// - /// Looks up a localized string similar to The option '{0}' is not currently supported.. + /// Looks up a localized string similar to The option '{0}' is not currently supported. /// internal static string OptionNotCurrentlySupported { get { @@ -934,7 +934,7 @@ internal static string OptionNotCurrentlySupported { } /// - /// Looks up a localized string similar to Parameter '{0}' has already been defined.. + /// Looks up a localized string similar to Parameter '{0}' has already been defined. /// internal static string ParameterAlreadyDefined { get { @@ -961,7 +961,7 @@ internal static string ParameterCannotBeNull { } /// - /// Looks up a localized string similar to Parameter '{0}' can't be null or empty.. + /// Looks up a localized string similar to Parameter '{0}' can't be null or empty. /// internal static string ParameterCannotBeNullOrEmpty { get { @@ -970,7 +970,7 @@ internal static string ParameterCannotBeNullOrEmpty { } /// - /// Looks up a localized string similar to Parameter index was not found in Parameter Collection.. + /// Looks up a localized string similar to Parameter index was not found in Parameter Collection. /// internal static string ParameterIndexNotFound { get { @@ -979,7 +979,7 @@ internal static string ParameterIndexNotFound { } /// - /// Looks up a localized string similar to Parameter is invalid.. + /// Looks up a localized string similar to Parameter is invalid. /// internal static string ParameterIsInvalid { get { @@ -988,7 +988,7 @@ internal static string ParameterIsInvalid { } /// - /// Looks up a localized string similar to Parameter '{0}' must be defined.. + /// Looks up a localized string similar to Parameter '{0}' must be defined. /// internal static string ParameterMustBeDefined { get { @@ -997,7 +997,7 @@ internal static string ParameterMustBeDefined { } /// - /// Looks up a localized string similar to Parameter '{0}' was not found during prepare.. + /// Looks up a localized string similar to Parameter '{0}' was not found during prepare. /// internal static string ParameterNotFoundDuringPrepare { get { @@ -1006,7 +1006,7 @@ internal static string ParameterNotFoundDuringPrepare { } /// - /// Looks up a localized string similar to Parameter can't be null or empty.. + /// Looks up a localized string similar to Parameter can't be null or empty. /// internal static string ParameterNullOrEmpty { get { @@ -1042,7 +1042,7 @@ internal static string PerfMonCategoryName { } /// - /// Looks up a localized string similar to The number of times a procedures metadata had to be queried from the server.. + /// Looks up a localized string similar to The number of times a procedures metadata had to be queried from the server. /// internal static string PerfMonHardProcHelp { get { @@ -1060,7 +1060,7 @@ internal static string PerfMonHardProcName { } /// - /// Looks up a localized string similar to The number of times a procedures metadata was retrieved from the client-side cache.. + /// Looks up a localized string similar to The number of times a procedures metadata was retrieved from the client-side cache. /// internal static string PerfMonSoftProcHelp { get { @@ -1078,7 +1078,7 @@ internal static string PerfMonSoftProcName { } /// - /// Looks up a localized string similar to same name are not supported.. + /// Looks up a localized string similar to same name are not supported. /// internal static string ProcAndFuncSameName { get { @@ -1087,7 +1087,7 @@ internal static string ProcAndFuncSameName { } /// - /// Looks up a localized string similar to MySQL Server {0} dos not support query attributes.. + /// Looks up a localized string similar to MySQL Server {0} dos not support query attributes. /// internal static string QueryAttributesNotSupported { get { @@ -1096,7 +1096,7 @@ internal static string QueryAttributesNotSupported { } /// - /// Looks up a localized string similar to MySQL Connector/NET does not support query attributes with prepared statements for this version of MySQL Server.. + /// Looks up a localized string similar to MySQL Connector/NET does not support query attributes with prepared statements for this version of MySQL Server. /// internal static string QueryAttributesNotSupportedByCnet { get { @@ -1105,7 +1105,7 @@ internal static string QueryAttributesNotSupportedByCnet { } /// - /// Looks up a localized string similar to Packets larger than max_allowed_packet are not allowed.. + /// Looks up a localized string similar to Packets larger than max_allowed_packet are not allowed. /// internal static string QueryTooLarge { get { @@ -1114,7 +1114,7 @@ internal static string QueryTooLarge { } /// - /// Looks up a localized string similar to Reading from the stream has failed.. + /// Looks up a localized string similar to Reading from the stream has failed. /// internal static string ReadFromStreamFailed { get { @@ -1132,7 +1132,7 @@ internal static string ReadingPriorColumnUsingSeqAccess { } /// - /// Looks up a localized string similar to Replicated connections allow only readonly statements.. + /// Looks up a localized string similar to Replicated connections allow only readonly statements. /// internal static string ReplicatedConnectionsAllowOnlyReadonlyStatements { get { @@ -1141,7 +1141,7 @@ internal static string ReplicatedConnectionsAllowOnlyReadonlyStatements { } /// - /// Looks up a localized string similar to Attempt to connect to '{0}' server failed.. + /// Looks up a localized string similar to Attempt to connect to '{0}' server failed. /// internal static string Replication_ConnectionAttemptFailed { get { @@ -1150,7 +1150,7 @@ internal static string Replication_ConnectionAttemptFailed { } /// - /// Looks up a localized string similar to No available server found.. + /// Looks up a localized string similar to No available server found. /// internal static string Replication_NoAvailableServer { get { @@ -1159,7 +1159,7 @@ internal static string Replication_NoAvailableServer { } /// - /// Looks up a localized string similar to Replication group '{0}' not found.. + /// Looks up a localized string similar to Replication group '{0}' not found. /// internal static string ReplicationGroupNotFound { get { @@ -1177,7 +1177,7 @@ internal static string ReplicationServerNotFound { } /// - /// Looks up a localized string similar to Routine '{0}' cannot be found. Either check the spelling or make sure you have sufficient rights to execute the routine.. + /// Looks up a localized string similar to Routine '{0}' cannot be found. Either check the spelling or make sure you have sufficient rights to execute the routine. /// internal static string RoutineNotFound { get { @@ -1195,7 +1195,7 @@ internal static string RoutineRequiresReturnParameter { } /// - /// Looks up a localized string similar to Retrieval of the RSA public key is not enabled for insecure connections.. + /// Looks up a localized string similar to Retrieval of the RSA public key is not enabled for insecure connections. /// internal static string RSAPublicKeyRetrievalNotEnabled { get { @@ -1213,7 +1213,7 @@ internal static string ServerTooOld { } /// - /// Looks up a localized string similar to Snapshot isolation level is not supported.. + /// Looks up a localized string similar to Snapshot isolation level is not supported. /// internal static string SnapshotNotSupported { get { @@ -1231,7 +1231,7 @@ internal static string SocketNoSeek { } /// - /// Looks up a localized string similar to Retrieving procedure metadata for {0} from procedure cache.. + /// Looks up a localized string similar to Retrieving procedure metadata for {0} from procedure cache. /// internal static string SoftProcQuery { get { @@ -1249,7 +1249,7 @@ internal static string SPNotSupported { } /// - /// Looks up a localized string similar to The certificate authority (CA) does not match.. + /// Looks up a localized string similar to The certificate authority (CA) does not match. /// internal static string SslCertificateCAMismatch { get { @@ -1258,7 +1258,7 @@ internal static string SslCertificateCAMismatch { } /// - /// Looks up a localized string similar to The host name does not match the name on the certificate.. + /// Looks up a localized string similar to The host name does not match the name on the certificate. /// internal static string SslCertificateHostNameMismatch { get { @@ -1267,7 +1267,7 @@ internal static string SslCertificateHostNameMismatch { } /// - /// Looks up a localized string similar to The certificate is not a certificate authority (CA).. + /// Looks up a localized string similar to The certificate is not a certificate authority (CA). /// internal static string SslCertificateIsNotCA { get { @@ -1276,7 +1276,7 @@ internal static string SslCertificateIsNotCA { } /// - /// Looks up a localized string similar to SSL Connection error.. + /// Looks up a localized string similar to SSL Connection error. /// internal static string SslConnectionError { get { @@ -1285,7 +1285,7 @@ internal static string SslConnectionError { } /// - /// Looks up a localized string similar to Connection protocol '{0}' does not support SSL connections.. + /// Looks up a localized string similar to Connection protocol '{0}' does not support SSL connections. /// internal static string SslNotAllowedForConnectionProtocol { get { @@ -1321,7 +1321,7 @@ internal static string StreamNoWrite { } /// - /// Looks up a localized string similar to String can't be empty.. + /// Looks up a localized string similar to String can't be empty. /// internal static string StringEmpty { get { @@ -1330,7 +1330,7 @@ internal static string StringEmpty { } /// - /// Looks up a localized string similar to Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding.. + /// Looks up a localized string similar to Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding. /// internal static string Timeout { get { @@ -1339,7 +1339,7 @@ internal static string Timeout { } /// - /// Looks up a localized string similar to error connecting: Timeout expired. The timeout period elapsed prior to obtaining a connection from the pool. This may have occurred because all pooled connections were in use and max pool size was reached.. + /// Looks up a localized string similar to error connecting: Timeout expired. The timeout period elapsed prior to obtaining a connection from the pool. This may have occurred because all pooled connections were in use and max pool size was reached. /// internal static string TimeoutGettingConnection { get { @@ -1348,7 +1348,7 @@ internal static string TimeoutGettingConnection { } /// - /// Looks up a localized string similar to All server connection attempts were aborted. Timeout of {0} seconds was exceeded for each selected server.. + /// Looks up a localized string similar to All server connection attempts were aborted. Timeout of {0} seconds was exceeded for each selected server. /// internal static string TimeOutMultipleHost { get { @@ -1393,7 +1393,7 @@ internal static string TraceCloseConnection { } /// - /// Looks up a localized string similar to Unable to trace. There are more than Int32.MaxValue connections in use.. + /// Looks up a localized string similar to Unable to trace. There are more than Int32.MaxValue connections in use. /// internal static string TraceErrorMoreThanMaxValueConnections { get { @@ -1546,7 +1546,7 @@ internal static string TraceUAWarningSkippedColumns { } /// - /// Looks up a localized string similar to {0}: Usage Advisor Warning: Skipped {2} rows. Consider a more focused query.. + /// Looks up a localized string similar to {0}: Usage Advisor Warning: Skipped {2} rows. Consider a more focused query. /// internal static string TraceUAWarningSkippedRows { get { @@ -1582,7 +1582,7 @@ internal static string TypeIsNotExceptionInterceptor { } /// - /// Looks up a localized string similar to Unable to connect to any of the specified MySQL hosts.. + /// Looks up a localized string similar to Unable to connect to any of the specified MySQL hosts. /// internal static string UnableToConnectToHost { get { @@ -1591,7 +1591,7 @@ internal static string UnableToConnectToHost { } /// - /// Looks up a localized string similar to Unable to create plugin for authentication method '{0}'. Please see inner exception for details.. + /// Looks up a localized string similar to Unable to create plugin for authentication method '{0}'. Please see inner exception for details. /// internal static string UnableToCreateAuthPlugin { get { @@ -1600,7 +1600,7 @@ internal static string UnableToCreateAuthPlugin { } /// - /// Looks up a localized string similar to Unable to derive stored routine parameters. The 'Parameters' information schema table is not available and access to the stored procedure body has been disabled.. + /// Looks up a localized string similar to Unable to derive stored routine parameters. The 'Parameters' information schema table is not available and access to the stored procedure body has been disabled. /// internal static string UnableToDeriveParameters { get { @@ -1609,7 +1609,7 @@ internal static string UnableToDeriveParameters { } /// - /// Looks up a localized string similar to Unable to enable query analysis. Be sure the MySql.Data.EMTrace assembly is properly located and registered.. + /// Looks up a localized string similar to Unable to enable query analysis. Be sure the MySql.Data.EMTrace assembly is properly located and registered. /// internal static string UnableToEnableQueryAnalysis { get { @@ -1627,7 +1627,7 @@ internal static string UnableToEnumerateUDF { } /// - /// Looks up a localized string similar to Unable to execute stored procedure '{0}'.. + /// Looks up a localized string similar to Unable to execute stored procedure '{0}'. /// internal static string UnableToExecuteSP { get { @@ -1636,7 +1636,7 @@ internal static string UnableToExecuteSP { } /// - /// Looks up a localized string similar to There was an error parsing the foreign key definition.. + /// Looks up a localized string similar to There was an error parsing the foreign key definition. /// internal static string UnableToParseFK { get { @@ -1645,7 +1645,7 @@ internal static string UnableToParseFK { } /// - /// Looks up a localized string similar to Error encountered reading the RSA public key.. + /// Looks up a localized string similar to Error encountered reading the RSA public key. /// internal static string UnableToReadRSAKey { get { @@ -1654,7 +1654,7 @@ internal static string UnableToReadRSAKey { } /// - /// Looks up a localized string similar to Unable to retrieve stored procedure metadata for routine '{0}'. Either grant SELECT privilege to mysql.proc for this user or use "check parameters=false" with your connection string.. + /// Looks up a localized string similar to Unable to retrieve stored procedure metadata for routine '{0}'. Either grant SELECT privilege to mysql.proc for this user or use "check parameters=false" with your connection string. /// internal static string UnableToRetrieveParameters { get { @@ -1663,7 +1663,7 @@ internal static string UnableToRetrieveParameters { } /// - /// Looks up a localized string similar to Unable to start a second async operation while one is running.. + /// Looks up a localized string similar to Unable to start a second async operation while one is running. /// internal static string UnableToStartSecondAsyncOp { get { @@ -1681,7 +1681,7 @@ internal static string UnixSocketsNotSupported { } /// - /// Looks up a localized string similar to Unknown authentication method '{0}' was requested.. + /// Looks up a localized string similar to Unknown authentication method '{0}' was requested. /// internal static string UnknownAuthenticationMethod { get { @@ -1699,7 +1699,7 @@ internal static string UnknownConnectionProtocol { } /// - /// Looks up a localized string similar to MySQL user '{0}' does not equal the logged-in Windows user '{1}'.. + /// Looks up a localized string similar to MySQL user '{0}' does not equal the logged-in Windows user '{1}'. /// internal static string UnmatchedWinUserAndMySqlUser { get { @@ -1708,7 +1708,7 @@ internal static string UnmatchedWinUserAndMySqlUser { } /// - /// Looks up a localized string similar to Trying to upload a file from outside the path set on 'allowloadlocalinfileinpath' is invalid.. + /// Looks up a localized string similar to Trying to upload a file from outside the path set on 'allowloadlocalinfileinpath' is invalid. /// internal static string UnsafePathForLoadLocalInfile { get { @@ -1717,7 +1717,7 @@ internal static string UnsafePathForLoadLocalInfile { } /// - /// Looks up a localized string similar to Value '{0}' is not of the correct type.. + /// Looks up a localized string similar to Value '{0}' is not of the correct type. /// internal static string ValueNotCorrectType { get { @@ -1726,7 +1726,7 @@ internal static string ValueNotCorrectType { } /// - /// Looks up a localized string similar to The requested column value could not be treated as or conveted to a Guid.. + /// Looks up a localized string similar to The requested column value could not be treated as or conveted to a Guid. /// internal static string ValueNotSupportedForGuid { get { @@ -1735,7 +1735,7 @@ internal static string ValueNotSupportedForGuid { } /// - /// Looks up a localized string similar to An event handler for WebAuthnActionRequested was not specified.. + /// Looks up a localized string similar to An event handler for WebAuthnActionRequested was not specified. /// internal static string WebAuthnMissingHandler { get { @@ -1744,7 +1744,7 @@ internal static string WebAuthnMissingHandler { } /// - /// Looks up a localized string similar to The timeout of 15 seconds for user interaction with FIDO device has been exceeded.. + /// Looks up a localized string similar to The timeout of 15 seconds for user interaction with FIDO device has been exceeded. /// internal static string WebAuthnTimeout { get { @@ -1762,7 +1762,7 @@ internal static string WinAuthNotSupportOnPlatform { } /// - /// Looks up a localized string similar to Writing to the stream failed.. + /// Looks up a localized string similar to Writing to the stream failed. /// internal static string WriteToStreamFailed { get { @@ -1771,7 +1771,7 @@ internal static string WriteToStreamFailed { } /// - /// Looks up a localized string similar to Parameter '{0}' is not found but a parameter with the name '{1}' is found. Parameter names must include the leading parameter marker.. + /// Looks up a localized string similar to Parameter '{0}' is not found but a parameter with the name '{1}' is found. Parameter names must include the leading parameter marker. /// internal static string WrongParameterName { get { diff --git a/MySQL.Data/src/Resources.resx b/MySQL.Data/src/Resources.resx index 732ef98b1..c5aa46d9a 100644 --- a/MySQL.Data/src/Resources.resx +++ b/MySQL.Data/src/Resources.resx @@ -184,16 +184,16 @@ Connection must be valid and open - There is already an open DataReader associated with this Connection which must be closed first. + There is already an open DataReader associated with this Connection which must be closed first Stored procedures are not supported on this version of MySQL - The connection property has not been set or is null. + The connection property has not been set or is null - The connection is not open. + The connection is not open Improper MySqlCommandBuilder state: adapter is null @@ -214,67 +214,67 @@ Chaos isolation level is not supported - Parameter is invalid. + Parameter is invalid - The connection is already open. + The connection is already open - Option not supported. + Option not supported - Writing to the stream failed. + Writing to the stream failed - Reading from the stream has failed. + Reading from the stream has failed - Packets larger than max_allowed_packet are not allowed. + Packets larger than max_allowed_packet are not allowed - Unable to execute stored procedure '{0}'. + Unable to execute stored procedure '{0}' - same name are not supported. + same name are not supported - Keyword does not allow null values. + Keyword does not allow null values - Value has an unsupported format. + Value has an unsupported format - Procedure or function '{0}' cannot be found in database '{1}'. + Procedure or function '{0}' cannot be found in database '{1}' - Retrieving procedure metadata for {0} from server. + Retrieving procedure metadata for {0} from server - Retrieving procedure metadata for {0} from procedure cache. + Retrieving procedure metadata for {0} from procedure cache - Connection unexpectedly terminated. + Connection unexpectedly terminated - An incorrect response was received from the server. + An incorrect response was received from the server - Canceling an active query is only supported on MySQL 5.0.0 and above. + Canceling an active query is only supported on MySQL 5.0.0 and above - Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding. + Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding - Canceling an executing query requires MySQL 5.0 or higher. + Canceling an executing query requires MySQL 5.0 or higher - Nested transactions are not supported. + Nested transactions are not supported - The CommandText property has not been properly initialized. + The CommandText property has not been properly initialized - There was an error parsing the foreign key definition. + There was an error parsing the foreign key definition This category includes a series of counters for MySQL @@ -283,91 +283,91 @@ .NET Data Provider for MySQL - The number of times a procedures metadata had to be queried from the server. + The number of times a procedures metadata had to be queried from the server Hard Procedure Queries - The number of times a procedures metadata was retrieved from the client-side cache. + The number of times a procedures metadata was retrieved from the client-side cache Soft Procedure Queries - Parameter '{0}' is not found but a parameter with the name '{1}' is found. Parameter names must include the leading parameter marker. + Parameter '{0}' is not found but a parameter with the name '{1}' is found. Parameter names must include the leading parameter marker - Unable to connect to any of the specified MySQL hosts. + Unable to connect to any of the specified MySQL hosts - Unable to retrieve stored procedure metadata for routine '{0}'. Either grant SELECT privilege to mysql.proc for this user or use "check parameters=false" with your connection string. + Unable to retrieve stored procedure metadata for routine '{0}'. Either grant SELECT privilege to mysql.proc for this user or use "check parameters=false" with your connection string - Invalid attempt to call NextResult when the reader is closed. + Invalid attempt to call NextResult when the reader is closed - When calling stored procedures and 'Use Procedure Bodies' is false, all parameters must have their type explicitly set. + When calling stored procedures and 'Use Procedure Bodies' is false, all parameters must have their type explicitly set - error connecting: Timeout expired. The timeout period elapsed prior to obtaining a connection from the pool. This may have occurred because all pooled connections were in use and max pool size was reached. + error connecting: Timeout expired. The timeout period elapsed prior to obtaining a connection from the pool. This may have occurred because all pooled connections were in use and max pool size was reached - Parameter '{0}' has already been defined. + Parameter '{0}' has already been defined - Parameter '{0}' must be defined. + Parameter '{0}' must be defined - The object is not open or has been disposed. + The object is not open or has been disposed - Multiple simultaneous connections or connections with different connection strings inside the same transaction are not currently supported. + Multiple simultaneous connections or connections with different connection strings inside the same transaction are not currently supported - MySQL Connector/NET does not currently support distributed transactions. + MySQL Connector/NET does not currently support distributed transactions - Fatal error encountered during command execution. + Fatal error encountered during command execution - Fatal error encountered during data read. + Fatal error encountered during data read - Fatal error encountered attempting to read the resultset. + Fatal error encountered attempting to read the resultset - Routine '{0}' cannot be found. Either check the spelling or make sure you have sufficient rights to execute the routine. + Routine '{0}' cannot be found. Either check the spelling or make sure you have sufficient rights to execute the routine - Parameter '{0}' was not found during prepare. + Parameter '{0}' was not found during prepare - The requested column value could not be treated as or conveted to a Guid. + The requested column value could not be treated as or conveted to a Guid - Unable to derive stored routine parameters. The 'Parameters' information schema table is not available and access to the stored procedure body has been disabled. + Unable to derive stored routine parameters. The 'Parameters' information schema table is not available and access to the stored procedure body has been disabled - The default connection encoding was not found. Please report this as a bug along with your connection string and system details. + The default connection encoding was not found. Please report this as a bug along with your connection string and system details - Call to GetHostEntry failed after {0} while querying for hostname '{1}': SocketErrorCode={2}, ErrorCode={3}, NativeErrorCode={4}. + Call to GetHostEntry failed after {0} while querying for hostname '{1}': SocketErrorCode={2}, ErrorCode={3}, NativeErrorCode={4} An error occured attempting to enumerate the user-defined functions. Do you have SELECT privileges on the mysql.func table? - The given value was not in a supported format. + The given value was not in a supported format - The host {0} does not support SSL connections. + The host {0} does not support SSL connections Could not find specified column in results: {0} - You have specified an invalid column ordinal. + You have specified an invalid column ordinal Invalid attempt to read a prior column using SequentialAccess @@ -376,19 +376,19 @@ Invalid attempt to access a field before calling Read() - Unable to start a second async operation while one is running. + Unable to start a second async operation while one is running - INTERNAL ERROR: More than one output parameter row detected. + INTERNAL ERROR: More than one output parameter row detected - '{0}' is an illegal value for a boolean option. + '{0}' is an illegal value for a boolean option Connector/NET no longer supports server versions prior to 5.0 - The requested value '{0}' is invalid for the given keyword '{1}'. + The requested value '{0}' is invalid for the given keyword '{1}' {0}: Connection Closed @@ -418,7 +418,7 @@ {0}: Resultset Closed. Total rows={1}, skipped rows={2}, size (bytes)={3} - {0}: Usage Advisor Warning: Skipped {2} rows. Consider a more focused query. + {0}: Usage Advisor Warning: Skipped {2} rows. Consider a more focused query {0}: Usage Advisor Warning: The following columns were not accessed: {2} @@ -436,7 +436,7 @@ {0}: MySql Warning: Level={1}, Code={2}, Message={3} - Unable to trace. There are more than Int32.MaxValue connections in use. + Unable to trace. There are more than Int32.MaxValue connections in use {0}: Statement prepared: sql='{1}', statement id={2} @@ -448,28 +448,28 @@ {0}: Statement executed: statement id = {1} - Unable to enable query analysis. Be sure the MySql.Data.EMTrace assembly is properly located and registered. + Unable to enable query analysis. Be sure the MySql.Data.EMTrace assembly is properly located and registered {0}: Query Normalized: {2} - Cannot retrieve Windows identity for current user. Connections that use IntegratedSecurity cannot be pooled. Use either 'ConnectionReset=true' or 'Pooling=false' in the connection string to fix. + Cannot retrieve Windows identity for current user. Connections that use IntegratedSecurity cannot be pooled. Use either 'ConnectionReset=true' or 'Pooling=false' in the connection string to fix Attempt to call stored function '{0}' without specifying a return parameter - Parameters can only be derived for commands using the StoredProcedure command type. + Parameters can only be derived for commands using the StoredProcedure command type - Replicated connections allow only readonly statements. + Replicated connections allow only readonly statements - File based certificates are only supported when connecting to MySQL Server 5.1 or greater. + File based certificates are only supported when connecting to MySQL Server 5.1 or greater - Snapshot isolation level is not supported. + Snapshot isolation level is not supported Type '{0}' is not derived from BaseExceptionInterceptor @@ -478,7 +478,7 @@ Type '{0}' is not derived from BaseCommandInterceptor - Unknown authentication method '{0}' was requested. + Unknown authentication method '{0}' was requested Authentication to host '{0}' for user '{1}' using method '{2}' failed with message: {3} @@ -487,133 +487,133 @@ Windows authentication connections are not supported on {0} - Authentication method '{0}' not supported by any of the available plugins. + Authentication method '{0}' not supported by any of the available plugins - Unable to create plugin for authentication method '{0}'. Please see inner exception for details. + Unable to create plugin for authentication method '{0}'. Please see inner exception for details - Mixing named and unnamed parameters is not allowed. + Mixing named and unnamed parameters is not allowed - Parameter index was not found in Parameter Collection. + Parameter index was not found in Parameter Collection - Authentication with old password no longer supported, use 4.1 style passwords. + Authentication with old password no longer supported, use 4.1 style passwords - Microsecond must be a value between 0 and 999999. + Microsecond must be a value between 0 and 999999 - Millisecond must be a value between 0 and 999. For more precision use Microsecond. + Millisecond must be a value between 0 and 999. For more precision use Microsecond - No available server found. + No available server found - Attempt to connect to '{0}' server failed. + Attempt to connect to '{0}' server failed Unknown connection protocol - Unix sockets are not supported on Windows. + Unix sockets are not supported on Windows Replicated server not found: '{0}' - Replication group '{0}' not found. + Replication group '{0}' not found - The new value must be a MySqlParameter object. + The new value must be a MySqlParameter object - Value '{0}' is not of the correct type. + Value '{0}' is not of the correct type - Compression is not supported. + Compression is not supported - SSL Connection error. + SSL Connection error - The option '{0}' is not currently supported. + The option '{0}' is not currently supported - Parameter can't be null or empty. + Parameter can't be null or empty - Error encountered reading the RSA public key. + Error encountered reading the RSA public key - Retrieval of the RSA public key is not enabled for insecure connections. + Retrieval of the RSA public key is not enabled for insecure connections - String can't be empty. + String can't be empty - Value '{0}' is not of the correct type. + Value '{0}' is not of the correct type - Parameter '{0}' can't be null or empty. + Parameter '{0}' can't be null or empty - Encoding error during validation. + Encoding error during validation - The specified file cannot be converted to a certificate. + The specified file cannot be converted to a certificate - The specified file cannot be converted to a key. + The specified file cannot be converted to a key - Failed to read file at the specified location. + Failed to read file at the specified location - No file path has been provided for the connection option {0}. + No file path has been provided for the connection option {0} - The provided key is invalid. + The provided key is invalid - The certificate is invalid. + The certificate is invalid - Unable to validate the signature. + Unable to validate the signature - Unable to verify the signature. + Unable to verify the signature - The certificate authority (CA) does not match. + The certificate authority (CA) does not match - The host name does not match the name on the certificate. + The host name does not match the name on the certificate - The certificate is not a certificate authority (CA). + The certificate is not a certificate authority (CA) - Server asked for stream in response to LOAD DATA LOCAL INFILE, but the functionality is disabled by the client setting 'allowlocalinfile' to 'false'. + Server asked for stream in response to LOAD DATA LOCAL INFILE, but the functionality is disabled by the client setting 'allowlocalinfile' to 'false' - The host name or IP address is invalid. + The host name or IP address is invalid - All server connection attempts were aborted. Timeout of {0} seconds was exceeded for each selected server. + All server connection attempts were aborted. Timeout of {0} seconds was exceeded for each selected server - Specifying multiple host names with DNS SRV lookup is not permitted. + Specifying multiple host names with DNS SRV lookup is not permitted - Specifying a port number with DNS SRV lookup is not permitted. + Specifying a port number with DNS SRV lookup is not permitted - Using Unix domain sockets with DNS SRV lookup is not permitted. + Using Unix domain sockets with DNS SRV lookup is not permitted - Unable to locate any hosts for {0}. + Unable to locate any hosts for {0} Specified list of TLS versions only contains non valid TLS protocols. Accepted values are TLSv1.2 and TLSv1.3 @@ -622,72 +622,72 @@ Specified list of TLS versions is empty. Accepted values are TLSv1.2 and TLSv1.3 - Verify that user '{0}'@'{1}' has enough privileges to execute. + Verify that user '{0}'@'{1}' has enough privileges to execute - Clear-password authentication is not supported over insecure channels. + Clear-password authentication is not supported over insecure channels - Trying to upload a file from outside the path set on 'allowloadlocalinfileinpath' is invalid. + Trying to upload a file from outside the path set on 'allowloadlocalinfileinpath' is invalid - Either provide a valid path for 'allowloadlocalinfileinpath' or enable 'allowloadlocalinfile'. + Either provide a valid path for 'allowloadlocalinfileinpath' or enable 'allowloadlocalinfile' - Certificate with Thumbprint '{0}' not found. + Certificate with Thumbprint '{0}' not found - MySQL Server {0} dos not support query attributes. + MySQL Server {0} dos not support query attributes - MySQL Connector/NET does not support query attributes with prepared statements for this version of MySQL Server. + MySQL Connector/NET does not support query attributes with prepared statements for this version of MySQL Server - Connection protocol '{0}' does not support SSL connections. + Connection protocol '{0}' does not support SSL connections - Authentication plugin '{0}' is currently not supported. + Authentication plugin '{0}' is currently not supported - MySQL user '{0}' does not equal the logged-in Windows user '{1}'. + MySQL user '{0}' does not equal the logged-in Windows user '{1}' - The OCI SDK cannot be found or is not installed. + The OCI SDK cannot be found or is not installed - OCI configuration file could not be read. + OCI configuration file could not be read - OCI configuration file does not contain a 'fingerprint' or 'key_file' entry. + OCI configuration file does not contain a 'fingerprint' or 'key_file' entry - OCI configuration entry 'key_file' does not reference a valid key file. + OCI configuration entry 'key_file' does not reference a valid key file - Private key could not be found at location given by OCI configuration entry 'key_file'. + Private key could not be found at location given by OCI configuration entry 'key_file' - The size of the OCI security token file exceeds the maximum value of 10KB allowed. + The size of the OCI security token file exceeds the maximum value of 10KB allowed - OCI configuration profile not found. + OCI configuration profile not found - Secutiry token file could not be found at location given by OCI configuration entry 'security_token_file'. + Secutiry token file could not be found at location given by OCI configuration entry 'security_token_file' TLS protocols TLSv1 and TLSv1.1 are no longer supported. Accepted values are TLSv1.2 and TLSv1.3 - Challenge received is corrupt. + Challenge received is corrupt - FIDO registration is missing. + FIDO registration is missing - An event handler for WebAuthnActionRequested was not specified. + An event handler for WebAuthnActionRequested was not specified - The timeout of 15 seconds for user interaction with FIDO device has been exceeded. + The timeout of 15 seconds for user interaction with FIDO device has been exceeded \ No newline at end of file diff --git a/MySQL.Data/src/ResourcesX.Designer.cs b/MySQL.Data/src/ResourcesX.Designer.cs index 86b984d69..e1b04614d 100644 --- a/MySQL.Data/src/ResourcesX.Designer.cs +++ b/MySQL.Data/src/ResourcesX.Designer.cs @@ -61,7 +61,7 @@ internal ResourcesX() { } /// - /// Looks up a localized string similar to Appdata path is not defined.. + /// Looks up a localized string similar to Appdata path is not defined. /// internal static string AppdataNotDefined { get { @@ -70,7 +70,7 @@ internal static string AppdataNotDefined { } /// - /// Looks up a localized string similar to Authentication failed using MYSQL41 and SHA256_MEMORY. Check the user name and password or try using a secure connection.. + /// Looks up a localized string similar to Authentication failed using MYSQL41 and SHA256_MEMORY. Check the user name and password or try using a secure connection. /// internal static string AuthenticationFailed { get { @@ -79,7 +79,7 @@ internal static string AuthenticationFailed { } /// - /// Looks up a localized string similar to You can't get more sessions because Client is closed.. + /// Looks up a localized string similar to You can't get more sessions because Client is closed. /// internal static string ClientIsClosed { get { @@ -88,7 +88,7 @@ internal static string ClientIsClosed { } /// - /// Looks up a localized string similar to Client option '{0}' does not support value '{1}'.. + /// Looks up a localized string similar to Client option '{0}' does not support value '{1}'. /// internal static string ClientOptionInvalidValue { get { @@ -97,7 +97,7 @@ internal static string ClientOptionInvalidValue { } /// - /// Looks up a localized string similar to Client option '{0}' is not recognized as valid.. + /// Looks up a localized string similar to Client option '{0}' is not recognized as valid. /// internal static string ClientOptionNotValid { get { @@ -106,7 +106,7 @@ internal static string ClientOptionNotValid { } /// - /// Looks up a localized string similar to {0} '{1}' does not exist in schema '{2}'.. + /// Looks up a localized string similar to {0} '{1}' does not exist in schema '{2}'. /// internal static string CollectionTableDoesNotExist { get { @@ -115,7 +115,7 @@ internal static string CollectionTableDoesNotExist { } /// - /// Looks up a localized string similar to Compression requested but the compression algorithm negotiation failed.. + /// Looks up a localized string similar to Compression requested but the compression algorithm negotiation failed. /// internal static string CompressionAlgorithmNegotiationFailed { get { @@ -124,7 +124,7 @@ internal static string CompressionAlgorithmNegotiationFailed { } /// - /// Looks up a localized string similar to Compression using {0} is not supported.. + /// Looks up a localized string similar to Compression using {0} is not supported. /// internal static string CompressionAlgorithmNotSupported { get { @@ -133,7 +133,7 @@ internal static string CompressionAlgorithmNotSupported { } /// - /// Looks up a localized string similar to Compression using {0} is not supported in .NET Framework.. + /// Looks up a localized string similar to Compression using {0} is not supported in .NET Framework. /// internal static string CompressionForSpecificAlgorithmNotSupportedInNetFramework { get { @@ -142,7 +142,7 @@ internal static string CompressionForSpecificAlgorithmNotSupportedInNetFramework } /// - /// Looks up a localized string similar to The connection property 'compression' acceptable values are: 'preferred', 'required' or 'disabled'. The value '{0}' is not acceptable.. + /// Looks up a localized string similar to The connection property 'compression' acceptable values are: 'preferred', 'required' or 'disabled'. The value '{0}' is not acceptable. /// internal static string CompressionInvalidValue { get { @@ -151,7 +151,7 @@ internal static string CompressionInvalidValue { } /// - /// Looks up a localized string similar to Compression is not enabled.. + /// Looks up a localized string similar to Compression is not enabled. /// internal static string CompressionNotEnabled { get { @@ -160,7 +160,7 @@ internal static string CompressionNotEnabled { } /// - /// Looks up a localized string similar to Compression requested but the server does not support it.. + /// Looks up a localized string similar to Compression requested but the server does not support it. /// internal static string CompressionNotSupportedByServer { get { @@ -169,7 +169,7 @@ internal static string CompressionNotSupportedByServer { } /// - /// Looks up a localized string similar to There are still decompressed messages pending to be processed.. + /// Looks up a localized string similar to There are still decompressed messages pending to be processed. /// internal static string CompressionPendingMessagesToProcess { get { @@ -178,7 +178,7 @@ internal static string CompressionPendingMessagesToProcess { } /// - /// Looks up a localized string similar to Custom type mapping is only supported from .NET Core 3.1 and later.. + /// Looks up a localized string similar to Custom type mapping is only supported from .NET Core 3.1 and later. /// internal static string CustomTypeNotSupported { get { @@ -187,7 +187,7 @@ internal static string CustomTypeNotSupported { } /// - /// Looks up a localized string similar to '{0}' cannot be set to false with DNS SRV lookup enabled.. + /// Looks up a localized string similar to '{0}' cannot be set to false with DNS SRV lookup enabled. /// internal static string DnsSrvConflictingOptions { get { @@ -196,7 +196,7 @@ internal static string DnsSrvConflictingOptions { } /// - /// Looks up a localized string similar to Scheme '{0}' is not valid.. + /// Looks up a localized string similar to Scheme '{0}' is not valid. /// internal static string DnsSrvInvalidScheme { get { @@ -205,7 +205,7 @@ internal static string DnsSrvInvalidScheme { } /// - /// Looks up a localized string similar to The document path cannot be null or an empty string.. + /// Looks up a localized string similar to The document path cannot be null or an empty string. /// internal static string DocPathNullOrEmpty { get { @@ -214,7 +214,7 @@ internal static string DocPathNullOrEmpty { } /// - /// Looks up a localized string similar to Duplicate key '{0}' used in "connection-attributes".. + /// Looks up a localized string similar to Duplicate key '{0}' used in "connection-attributes". /// internal static string DuplicateUserDefinedAttribute { get { @@ -223,7 +223,7 @@ internal static string DuplicateUserDefinedAttribute { } /// - /// Looks up a localized string similar to Key name in connection attribute cannot be an empty string.. + /// Looks up a localized string similar to Key name in connection attribute cannot be an empty string. /// internal static string EmptyKeyConnectionAttribute { get { @@ -232,7 +232,7 @@ internal static string EmptyKeyConnectionAttribute { } /// - /// Looks up a localized string similar to At least one option must be specified.. + /// Looks up a localized string similar to At least one option must be specified. /// internal static string EmptyOptions { get { @@ -241,7 +241,7 @@ internal static string EmptyOptions { } /// - /// Looks up a localized string similar to This feature is currently not supported.. + /// Looks up a localized string similar to This feature is currently not supported. /// internal static string FeatureNotSupported { get { @@ -250,7 +250,7 @@ internal static string FeatureNotSupported { } /// - /// Looks up a localized string similar to This functionality is only supported in MySQL {0} and higher.. + /// Looks up a localized string similar to This functionality is only supported in MySQL {0} and higher. /// internal static string FunctionalityNotSupported { get { @@ -259,7 +259,7 @@ internal static string FunctionalityNotSupported { } /// - /// Looks up a localized string similar to Collation with id '{0}' not found.. + /// Looks up a localized string similar to Collation with id '{0}' not found. /// internal static string InvalidCollationId { get { @@ -268,7 +268,7 @@ internal static string InvalidCollationId { } /// - /// Looks up a localized string similar to The value of "connection-attributes" must be either a boolean or a list of key-value pairs.. + /// Looks up a localized string similar to The value of "connection-attributes" must be either a boolean or a list of key-value pairs. /// internal static string InvalidConnectionAttributes { get { @@ -277,7 +277,7 @@ internal static string InvalidConnectionAttributes { } /// - /// Looks up a localized string similar to Connection Data is incorrect.. + /// Looks up a localized string similar to Connection Data is incorrect. /// internal static string InvalidConnectionData { get { @@ -286,7 +286,7 @@ internal static string InvalidConnectionData { } /// - /// Looks up a localized string similar to The connection string is invalid.. + /// Looks up a localized string similar to The connection string is invalid. /// internal static string InvalidConnectionString { get { @@ -295,7 +295,7 @@ internal static string InvalidConnectionString { } /// - /// Looks up a localized string similar to '{0}' is not a valid connection string attribute.. + /// Looks up a localized string similar to '{0}' is not a valid connection string attribute. /// internal static string InvalidConnectionStringAttribute { get { @@ -304,7 +304,7 @@ internal static string InvalidConnectionStringAttribute { } /// - /// Looks up a localized string similar to The connection timeout value must be a positive integer (including 0).. + /// Looks up a localized string similar to The connection timeout value must be a positive integer (including 0). /// internal static string InvalidConnectionTimeoutValue { get { @@ -313,7 +313,7 @@ internal static string InvalidConnectionTimeoutValue { } /// - /// Looks up a localized string similar to Decimal (BCD) format is invalid.. + /// Looks up a localized string similar to Decimal (BCD) format is invalid. /// internal static string InvalidDecimalFormat { get { @@ -322,7 +322,7 @@ internal static string InvalidDecimalFormat { } /// - /// Looks up a localized string similar to Field type with name '{0}' not found.. + /// Looks up a localized string similar to Field type with name '{0}' not found. /// internal static string InvalidFieldType { get { @@ -331,7 +331,7 @@ internal static string InvalidFieldType { } /// - /// Looks up a localized string similar to Index type with name '{0}' not found.. + /// Looks up a localized string similar to Index type with name '{0}' not found. /// internal static string InvalidIndexType { get { @@ -349,7 +349,7 @@ internal static string InvalidJsonDocument { } /// - /// Looks up a localized string similar to {0} is not a valid column name in the row.. + /// Looks up a localized string similar to {0} is not a valid column name in the row. /// internal static string InvalidNameIndex { get { @@ -358,7 +358,7 @@ internal static string InvalidNameIndex { } /// - /// Looks up a localized string similar to {0} is not a valid index for the row.. + /// Looks up a localized string similar to {0} is not a valid index for the row. /// internal static string InvalidRowIndex { get { @@ -367,7 +367,7 @@ internal static string InvalidRowIndex { } /// - /// Looks up a localized string similar to Session state is not valid.. + /// Looks up a localized string similar to Session state is not valid. /// internal static string InvalidSession { get { @@ -394,7 +394,7 @@ internal static string InvalidUriQuery { } /// - /// Looks up a localized string similar to Key names in "connection-attributes" cannot start with "_".. + /// Looks up a localized string similar to Key names in "connection-attributes" cannot start with "_". /// internal static string InvalidUserDefinedAttribute { get { @@ -403,7 +403,7 @@ internal static string InvalidUserDefinedAttribute { } /// - /// Looks up a localized string similar to Json configuration must contain 'uri' or 'host' but not both.. + /// Looks up a localized string similar to Json configuration must contain 'uri' or 'host' but not both. /// internal static string JsonUriOrHost { get { @@ -412,7 +412,7 @@ internal static string JsonUriOrHost { } /// - /// Looks up a localized string similar to Keyword '{0}' not found.. + /// Looks up a localized string similar to Keyword '{0}' not found. /// internal static string KeywordNotFound { get { @@ -421,7 +421,7 @@ internal static string KeywordNotFound { } /// - /// Looks up a localized string similar to Keyword not supported.. + /// Looks up a localized string similar to Keyword not supported. /// internal static string KeywordNotSupported { get { @@ -430,7 +430,7 @@ internal static string KeywordNotSupported { } /// - /// Looks up a localized string similar to Field '{0}' is mandatory.. + /// Looks up a localized string similar to Field '{0}' is mandatory. /// internal static string MandatoryFieldNotFound { get { @@ -439,7 +439,7 @@ internal static string MandatoryFieldNotFound { } /// - /// Looks up a localized string similar to Missed required schema option.. + /// Looks up a localized string similar to Missed required schema option. /// internal static string MissingSchemaOption { get { @@ -448,7 +448,7 @@ internal static string MissingSchemaOption { } /// - /// Looks up a localized string similar to More than one document id was generated. Please use the DocumentIds property instead.. + /// Looks up a localized string similar to More than one document id was generated. Please use the DocumentIds property instead. /// internal static string MoreThanOneDocumentId { get { @@ -466,7 +466,7 @@ internal static string NoDataAtIndex { } /// - /// Looks up a localized string similar to No 'host' has been specified.. + /// Looks up a localized string similar to No 'host' has been specified. /// internal static string NoHost { get { @@ -475,7 +475,7 @@ internal static string NoHost { } /// - /// Looks up a localized string similar to No more data in resultset.. + /// Looks up a localized string similar to No more data in resultset. /// internal static string NoMoreData { get { @@ -493,7 +493,7 @@ internal static string NoObjectFound { } /// - /// Looks up a localized string similar to No placeholders.. + /// Looks up a localized string similar to No placeholders. /// internal static string NoPlaceholders { get { @@ -529,7 +529,7 @@ internal static string NoticeServerShutdown { } /// - /// Looks up a localized string similar to {0} must be a value greater than 0.. + /// Looks up a localized string similar to {0} must be a value greater than 0. /// internal static string NumberNotGreaterThanZero { get { @@ -538,7 +538,7 @@ internal static string NumberNotGreaterThanZero { } /// - /// Looks up a localized string similar to Path not found '{0}'.. + /// Looks up a localized string similar to Path not found '{0}'. /// internal static string PathNotFound { get { @@ -547,7 +547,7 @@ internal static string PathNotFound { } /// - /// Looks up a localized string similar to Queue timeout expired. The timeout period elapsed prior to getting a session from the pool.. + /// Looks up a localized string similar to Queue timeout expired. The timeout period elapsed prior to getting a session from the pool. /// internal static string PoolingQueueTimeout { get { @@ -556,7 +556,7 @@ internal static string PoolingQueueTimeout { } /// - /// Looks up a localized string similar to Providing a port number as part of the host address isn't supported when using connection strings in basic format or anonymous objects. Use URI format instead.. + /// Looks up a localized string similar to Providing a port number as part of the host address isn't supported when using connection strings in basic format or anonymous objects. Use URI format instead. /// internal static string PortNotSupported { get { @@ -565,7 +565,7 @@ internal static string PortNotSupported { } /// - /// Looks up a localized string similar to You must either assign no priority to any of the hosts or give a priority for every host.. + /// Looks up a localized string similar to You must either assign no priority to any of the hosts or give a priority for every host. /// internal static string PriorityForAllOrNoHosts { get { @@ -574,7 +574,7 @@ internal static string PriorityForAllOrNoHosts { } /// - /// Looks up a localized string similar to The priority must be between 0 and 100.. + /// Looks up a localized string similar to The priority must be between 0 and 100. /// internal static string PriorityOutOfLimits { get { @@ -583,7 +583,7 @@ internal static string PriorityOutOfLimits { } /// - /// Looks up a localized string similar to ProgramData path is not defined.. + /// Looks up a localized string similar to ProgramData path is not defined. /// internal static string ProgramDataNotDefined { get { @@ -593,7 +593,7 @@ internal static string ProgramDataNotDefined { /// /// Looks up a localized string similar to Replacement document has an '_id' that is - ///different from the matched document.. + ///different from the matched document. /// internal static string ReplaceWithNoMatchingId { get { @@ -602,7 +602,7 @@ internal static string ReplaceWithNoMatchingId { } /// - /// Looks up a localized string similar to The server doesn't support the requested operation. Please update the MySQL Server, client library, or both.. + /// Looks up a localized string similar to The server doesn't support the requested operation. Please update the MySQL Server, client library, or both. /// internal static string SchemaCreateCollectionMsg { get { @@ -611,7 +611,7 @@ internal static string SchemaCreateCollectionMsg { } /// - /// Looks up a localized string similar to The process of closing the resultset and resulted in results being lost.. + /// Looks up a localized string similar to The process of closing the resultset and resulted in results being lost. /// internal static string ThrowingAwayResults { get { @@ -620,7 +620,7 @@ internal static string ThrowingAwayResults { } /// - /// Looks up a localized string similar to All server connection attempts were aborted. Timeout of {0} milliseconds was exceeded for each selected server.. + /// Looks up a localized string similar to All server connection attempts were aborted. Timeout of {0} milliseconds was exceeded for each selected server. /// internal static string TimeOutMultipleHost { get { @@ -629,7 +629,7 @@ internal static string TimeOutMultipleHost { } /// - /// Looks up a localized string similar to All server connection attempts were aborted. Timeout was exceeded for each selected server.. + /// Looks up a localized string similar to All server connection attempts were aborted. Timeout was exceeded for each selected server. /// internal static string TimeOutMultipleHost0ms { get { @@ -638,7 +638,7 @@ internal static string TimeOutMultipleHost0ms { } /// - /// Looks up a localized string similar to Connection attempt to the server was aborted. Timeout of {0} milliseconds was exceeded.. + /// Looks up a localized string similar to Connection attempt to the server was aborted. Timeout of {0} milliseconds was exceeded. /// internal static string TimeOutSingleHost { get { @@ -647,7 +647,7 @@ internal static string TimeOutSingleHost { } /// - /// Looks up a localized string similar to Connection attempt to the server was aborted. Timeout was exceeded.. + /// Looks up a localized string similar to Connection attempt to the server was aborted. Timeout was exceeded. /// internal static string TimeOutSingleHost0ms { get { @@ -656,7 +656,7 @@ internal static string TimeOutSingleHost0ms { } /// - /// Looks up a localized string similar to Unable to connect to any specified host.. + /// Looks up a localized string similar to Unable to connect to any specified host. /// internal static string UnableToConnect { get { @@ -665,7 +665,7 @@ internal static string UnableToConnect { } /// - /// Looks up a localized string similar to Unable to read or decode data value.. + /// Looks up a localized string similar to Unable to read or decode data value. /// internal static string UnableToDecodeDataValue { get { @@ -674,7 +674,7 @@ internal static string UnableToDecodeDataValue { } /// - /// Looks up a localized string similar to Unable to open a session.. + /// Looks up a localized string similar to Unable to open a session. /// internal static string UnableToOpenSession { get { @@ -692,7 +692,7 @@ internal static string UnexpectedEndOfPacketFound { } /// - /// Looks up a localized string similar to Field name '{0}' is not allowed.. + /// Looks up a localized string similar to Field name '{0}' is not allowed. /// internal static string UnexpectedField { get { @@ -710,7 +710,7 @@ internal static string UnknownPlaceholder { } /// - /// Looks up a localized string similar to Value '{0}' is not of the correct type.. + /// Looks up a localized string similar to Value '{0}' is not of the correct type. /// internal static string ValueNotCorrectType { get { diff --git a/MySQL.Data/src/ResourcesX.resx b/MySQL.Data/src/ResourcesX.resx index 7ec1a4298..c32081e6c 100644 --- a/MySQL.Data/src/ResourcesX.resx +++ b/MySQL.Data/src/ResourcesX.resx @@ -118,52 +118,52 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - Collation with id '{0}' not found. + Collation with id '{0}' not found - Connection Data is incorrect. + Connection Data is incorrect - '{0}' is not a valid connection string attribute. + '{0}' is not a valid connection string attribute - The connection string is invalid. + The connection string is invalid - Decimal (BCD) format is invalid. + Decimal (BCD) format is invalid - {0} is not a valid column name in the row. + {0} is not a valid column name in the row - {0} is not a valid index for the row. + {0} is not a valid index for the row - Keyword not supported. + Keyword not supported - More than one document id was generated. Please use the DocumentIds property instead. + More than one document id was generated. Please use the DocumentIds property instead There is no data at index {0} - No more data in resultset. + No more data in resultset - No placeholders. + No placeholders - Path not found '{0}'. + Path not found '{0}' - The process of closing the resultset and resulted in results being lost. + The process of closing the resultset and resulted in results being lost - Unable to connect to any specified host. + Unable to connect to any specified host - Unable to read or decode data value. + Unable to read or decode data value Unexpected end of packet found while reading data values @@ -172,7 +172,7 @@ Unknown placeholder :{0} - Value '{0}' is not of the correct type. + Value '{0}' is not of the correct type Object '{0}' not found @@ -184,139 +184,139 @@ Invalid uri query value - Json configuration must contain 'uri' or 'host' but not both. + Json configuration must contain 'uri' or 'host' but not both - No 'host' has been specified. + No 'host' has been specified - Appdata path is not defined. + Appdata path is not defined - ProgramData path is not defined. + ProgramData path is not defined - Keyword '{0}' not found. + Keyword '{0}' not found - You must either assign no priority to any of the hosts or give a priority for every host. + You must either assign no priority to any of the hosts or give a priority for every host - The priority must be between 0 and 100. + The priority must be between 0 and 100 - Providing a port number as part of the host address isn't supported when using connection strings in basic format or anonymous objects. Use URI format instead. + Providing a port number as part of the host address isn't supported when using connection strings in basic format or anonymous objects. Use URI format instead - {0} must be a value greater than 0. + {0} must be a value greater than 0 - This functionality is only supported in MySQL {0} and higher. + This functionality is only supported in MySQL {0} and higher - Field '{0}' is mandatory. + Field '{0}' is mandatory - Field name '{0}' is not allowed. + Field name '{0}' is not allowed - Field type with name '{0}' not found. + Field type with name '{0}' not found - Index type with name '{0}' not found. + Index type with name '{0}' not found - Authentication failed using MYSQL41 and SHA256_MEMORY. Check the user name and password or try using a secure connection. + Authentication failed using MYSQL41 and SHA256_MEMORY. Check the user name and password or try using a secure connection - This feature is currently not supported. + This feature is currently not supported The value provided is not a valid JSON document. {0} - The connection timeout value must be a positive integer (including 0). + The connection timeout value must be a positive integer (including 0) - All server connection attempts were aborted. Timeout of {0} milliseconds was exceeded for each selected server. + All server connection attempts were aborted. Timeout of {0} milliseconds was exceeded for each selected server - Connection attempt to the server was aborted. Timeout of {0} milliseconds was exceeded. + Connection attempt to the server was aborted. Timeout of {0} milliseconds was exceeded - All server connection attempts were aborted. Timeout was exceeded for each selected server. + All server connection attempts were aborted. Timeout was exceeded for each selected server - Connection attempt to the server was aborted. Timeout was exceeded. + Connection attempt to the server was aborted. Timeout was exceeded - Client option '{0}' does not support value '{1}'. + Client option '{0}' does not support value '{1}' - Client option '{0}' is not recognized as valid. + Client option '{0}' is not recognized as valid - Queue timeout expired. The timeout period elapsed prior to getting a session from the pool. + Queue timeout expired. The timeout period elapsed prior to getting a session from the pool - Session state is not valid. + Session state is not valid - Unable to open a session. + Unable to open a session - You can't get more sessions because Client is closed. + You can't get more sessions because Client is closed - {0} '{1}' does not exist in schema '{2}'. + {0} '{1}' does not exist in schema '{2}' - Duplicate key '{0}' used in "connection-attributes". + Duplicate key '{0}' used in "connection-attributes" - Key names in "connection-attributes" cannot start with "_". + Key names in "connection-attributes" cannot start with "_" - The value of "connection-attributes" must be either a boolean or a list of key-value pairs. + The value of "connection-attributes" must be either a boolean or a list of key-value pairs - Key name in connection attribute cannot be an empty string. + Key name in connection attribute cannot be an empty string - The server doesn't support the requested operation. Please update the MySQL Server, client library, or both. + The server doesn't support the requested operation. Please update the MySQL Server, client library, or both - At least one option must be specified. + At least one option must be specified - Missed required schema option. + Missed required schema option - Scheme '{0}' is not valid. + Scheme '{0}' is not valid - '{0}' cannot be set to false with DNS SRV lookup enabled. + '{0}' cannot be set to false with DNS SRV lookup enabled - Compression requested but the compression algorithm negotiation failed. + Compression requested but the compression algorithm negotiation failed - The connection property 'compression' acceptable values are: 'preferred', 'required' or 'disabled'. The value '{0}' is not acceptable. + The connection property 'compression' acceptable values are: 'preferred', 'required' or 'disabled'. The value '{0}' is not acceptable - Compression requested but the server does not support it. + Compression requested but the server does not support it - Compression using {0} is not supported. + Compression using {0} is not supported - Compression using {0} is not supported in .NET Framework. + Compression using {0} is not supported in .NET Framework - Compression is not enabled. + Compression is not enabled - There are still decompressed messages pending to be processed. + There are still decompressed messages pending to be processed Connection closed. Reason: connection idle was too long @@ -329,12 +329,12 @@ Replacement document has an '_id' that is -different from the matched document. +different from the matched document - The document path cannot be null or an empty string. + The document path cannot be null or an empty string - Custom type mapping is only supported from .NET Core 3.1 and later. + Custom type mapping is only supported from .NET Core 3.1 and later \ No newline at end of file From 72f607fac1b8ae2f61c14f44ec4897a984ed1e7b Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Wed, 28 Aug 2024 11:37:51 -0600 Subject: [PATCH 066/125] Updated failing tests. Change-Id: I9eb563e8e23e85b71f8eabcb2522d3b2c37e6365 --- .../tests/MySql.Data.Tests/AuthTests.cs | 12 +++--- .../tests/MySql.Data.Tests/BlobTests.cs | 2 +- .../ClientSideFailoverTests.cs | 12 +++--- .../ConnectionStringBuilderTests.cs | 8 ++-- .../tests/MySql.Data.Tests/ConnectionTests.cs | 2 +- .../tests/MySql.Data.Tests/DnsSrvTests.cs | 14 +++---- .../netstandard2_0/UsageAdvisorTests.cs | 6 +-- .../tests/MySql.Data.Tests/ParameterTests.cs | 4 +- .../tests/MySql.Data.Tests/PoolingTests.cs | 4 +- .../MySql.Data.Tests/PreparedStatements.cs | 2 +- .../MySql.Data.Tests/SimpleTransactions.cs | 4 +- .../tests/MySql.Data.Tests/Transactions.cs | 2 +- .../tests/MySqlX.Data.Tests/BasicFindTests.cs | 4 +- .../ClientSideFailoverTests.cs | 38 +++++++++---------- .../tests/MySqlX.Data.Tests/ClientTests.cs | 10 ++--- .../MySqlX.Data.Tests/CollectionIndexTests.cs | 18 ++++----- .../MySqlX.Data.Tests/CollectionTests.cs | 4 +- .../MySqlX.Data.Tests/CompressionTests.cs | 6 +-- .../MySqlX.Data.Tests/CrudRemoveTests.cs | 8 ++-- .../MySqlX.Data.Tests/CrudUpdateTests.cs | 12 +++--- .../tests/MySqlX.Data.Tests/DnsSrvTests.cs | 26 ++++++------- .../RelationalTests/TableSelectTests.cs | 4 +- .../tests/MySqlX.Data.Tests/SessionTests.cs | 4 +- .../tests/MySqlX.Data.Tests/SslTests.cs | 2 +- .../XConnectionStringBuilderTests.cs | 2 +- MySql.Web/tests/SchemaManagerTests.cs | 2 +- 26 files changed, 106 insertions(+), 106 deletions(-) diff --git a/MySQL.Data/tests/MySql.Data.Tests/AuthTests.cs b/MySQL.Data/tests/MySql.Data.Tests/AuthTests.cs index 0a3a3df2d..3d5028a4a 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/AuthTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/AuthTests.cs @@ -463,7 +463,7 @@ public void ConnectUsingSha256PasswordPlugin() if (serverCompiledUsingOpenSsl) { Exception ex = Assert.Throws(() => connection.Open()); - Assert.That(ex.Message, Is.EqualTo("Retrieval of the RSA public key is not enabled for insecure connections.")); + Assert.That(ex.Message, Is.EqualTo(Resources.RSAPublicKeyRetrievalNotEnabled)); } else Assert.Throws(() => connection.Open()); } @@ -541,7 +541,7 @@ public void AllowPublicKeyRetrievalForSha256PasswordPlugin() { Exception ex = Assert.Throws(() => connection.Open()); ; if (serverCompiledUsingOpenSsl) - Assert.That(ex.Message, Is.EqualTo("Retrieval of the RSA public key is not enabled for insecure connections.")); + Assert.That(ex.Message, Is.EqualTo(Resources.RSAPublicKeyRetrievalNotEnabled)); else Assert.That(ex.Message, Does.StartWith("Authentication to host")); } @@ -694,7 +694,7 @@ public void ConnectUsingCachingSha2Plugin() using (MySqlConnection connection = new MySqlConnection(builder.ConnectionString)) { ex = Assert.Throws(() => connection.Open()); - Assert.That(ex.Message, Is.EqualTo("Retrieval of the RSA public key is not enabled for insecure connections.")); + Assert.That(ex.Message, Is.EqualTo(Resources.RSAPublicKeyRetrievalNotEnabled)); } builder.AllowPublicKeyRetrieval = true; @@ -762,7 +762,7 @@ public void AllowPublicKeyRetrievalForCachingSha2PasswordPlugin() { Exception ex = Assert.Throws(() => connection.Open()); if (serverCompiledUsingOpenSsl) - Assert.That(ex.Message, Is.EqualTo("Retrieval of the RSA public key is not enabled for insecure connections.")); + Assert.That(ex.Message, Is.EqualTo(Resources.RSAPublicKeyRetrievalNotEnabled)); else Assert.That(ex.Message, Does.StartWith("Authentication to host")); } @@ -833,7 +833,7 @@ public void CachingSha2AuthFailsAfterFlushPrivileges() { ex = Assert.Throws(() => connection.Open()); if (serverCompiledUsingOpenSsl) - Assert.That(ex.Message, Is.EqualTo("Retrieval of the RSA public key is not enabled for insecure connections.")); + Assert.That(ex.Message, Is.EqualTo(Resources.RSAPublicKeyRetrievalNotEnabled)); else Assert.That(ex.Message, Does.StartWith("Authentication to host")); } @@ -1009,7 +1009,7 @@ public void ConnectUsingClearPasswordPlugin() using (MySqlConnection connection = new MySqlConnection(settings.ConnectionString)) { Exception ex = Assert.Throws(() => connection.Open()); - Assert.That(ex.Message, Does.Contain("Clear-password authentication is not supported over insecure channels")); + Assert.That(ex.Message, Is.EqualTo(Resources.ClearPasswordNotSupported)); } // Test connection for VALID user in LDAP server with different SSLMode values, expected result pass diff --git a/MySQL.Data/tests/MySql.Data.Tests/BlobTests.cs b/MySQL.Data/tests/MySql.Data.Tests/BlobTests.cs index a69bc6902..eaba3d20f 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/BlobTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/BlobTests.cs @@ -297,7 +297,7 @@ public void BlobBiggerThanMaxPacket() cmd.Parameters.AddWithValue("?image", image); Exception ex = Assert.Throws(() => cmd.ExecuteNonQuery()); - Assert.That(ex.Message, Is.EqualTo("Packets larger than max_allowed_packet are not allowed.")); + Assert.That(ex.Message, Is.EqualTo(Resources.QueryTooLarge)); } } diff --git a/MySQL.Data/tests/MySql.Data.Tests/ClientSideFailoverTests.cs b/MySQL.Data/tests/MySql.Data.Tests/ClientSideFailoverTests.cs index 313f4c353..e62d39e50 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/ClientSideFailoverTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/ClientSideFailoverTests.cs @@ -62,7 +62,7 @@ public void RandomMethod(string server, bool shouldPass = true) if (!shouldPass) { Exception ex = Assert.Throws(() => TryConnection(Settings.ConnectionString)); - Assert.That(ex.Message, Is.EqualTo("Unable to connect to any of the specified MySQL hosts.")); + Assert.That(ex.Message, Is.EqualTo(Resources.UnableToConnectToHost)); } else Assert.That(TryConnection(Settings.ConnectionString), Is.EqualTo(ConnectionState.Open)); @@ -133,11 +133,11 @@ public void PriorityMethod() } } - [TestCase("(address=server.example,priority=-20),(address=127.0.0.1,priority=100)", "The priority must be between 0 and 100.", "argument")] // Priority outside the 0-100 allowed range - [TestCase("(address=server.example,priority=-50),(address=127.0.0.1,priority=101)", "The priority must be between 0 and 100.", "argument")] // Priority outside the 0-100 allowed range - [TestCase("(address=server.example),(address=127.0.0.1,priority=100)", "You must either assign no priority to any of the hosts or give a priority for every host.", "argument")] // Set priority for a subset of the hosts. - [TestCase("(address=server.example,priority=50),(address=127.0.0.1,priority=100),(address=server.example)", "You must either assign no priority to any of the hosts or give a priority for every host.", "argument")] // Set priority for a subset of the hosts. - [TestCase("(address=server.example,priority=100),(address=10.10.10.10,priority=25),(address=192.0.10.56,priority=75)", "Unable to connect to any of the specified MySQL hosts.", "mysql")] // Multiple hosts. All attempts fail. + [TestCase("(address=server.example,priority=-20),(address=127.0.0.1,priority=100)", "The priority must be between 0 and 100", "argument")] // Priority outside the 0-100 allowed range + [TestCase("(address=server.example,priority=-50),(address=127.0.0.1,priority=101)", "The priority must be between 0 and 100", "argument")] // Priority outside the 0-100 allowed range + [TestCase("(address=server.example),(address=127.0.0.1,priority=100)", "You must either assign no priority to any of the hosts or give a priority for every host", "argument")] // Set priority for a subset of the hosts. + [TestCase("(address=server.example,priority=50),(address=127.0.0.1,priority=100),(address=server.example)", "You must either assign no priority to any of the hosts or give a priority for every host", "argument")] // Set priority for a subset of the hosts. + [TestCase("(address=server.example,priority=100),(address=10.10.10.10,priority=25),(address=192.0.10.56,priority=75)", "Unable to connect to any of the specified MySQL hosts", "mysql")] // Multiple hosts. All attempts fail. public void PriorityMethodConnectionFail(string server, string exceptionMessage, string exceptionType) { Settings.Server = server.Replace("127.0.0.1", Host); diff --git a/MySQL.Data/tests/MySql.Data.Tests/ConnectionStringBuilderTests.cs b/MySQL.Data/tests/MySql.Data.Tests/ConnectionStringBuilderTests.cs index bf4bd2450..5973f4a9f 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/ConnectionStringBuilderTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/ConnectionStringBuilderTests.cs @@ -65,9 +65,9 @@ public void Simple() Assert.That(Convert.ToInt32(sb.Keepalive), Is.EqualTo(1)); Exception ex = Assert.Throws(() => sb.ConnectionString = "server=localhost;badkey=badvalue"); #if NETFRAMEWORK - Assert.That(ex.Message, Is.EqualTo($"Option not supported.{Environment.NewLine}Parameter name: badkey")); + Assert.That(ex.Message, Is.EqualTo($"Option not supported{Environment.NewLine}Parameter name: badkey")); #else - Assert.That(ex.Message, Is.EqualTo("Option not supported. (Parameter 'badkey')")); + Assert.That(ex.Message, Is.EqualTo("Option not supported (Parameter 'badkey')")); #endif sb.Clear(); Assert.That(Convert.ToInt32(sb.ConnectionTimeout), Is.EqualTo(15)); @@ -151,9 +151,9 @@ public void SettingInvalidKeyThrowsArgumentException(string invalidKey) MySqlConnectionStringBuilder s = new MySqlConnectionStringBuilder(); Exception ex = Assert.Throws(() => s[invalidKey] = "foo"); #if NETFRAMEWORK - Assert.That(ex.Message, Is.EqualTo($"Option not supported.{Environment.NewLine}Parameter name: {invalidKey}")); + Assert.That(ex.Message, Is.EqualTo($"Option not supported{Environment.NewLine}Parameter name: {invalidKey}")); #else - Assert.That(ex.Message, Is.EqualTo($"Option not supported. (Parameter '{invalidKey}')")); + Assert.That(ex.Message, Is.EqualTo($"Option not supported (Parameter '{invalidKey}')")); #endif } diff --git a/MySQL.Data/tests/MySql.Data.Tests/ConnectionTests.cs b/MySQL.Data/tests/MySql.Data.Tests/ConnectionTests.cs index 0b53cf79a..bb0664c28 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/ConnectionTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/ConnectionTests.cs @@ -110,7 +110,7 @@ public void ConnectionPoolExhaustion() { var ex = Assert.Catch(() => CreateCommandTimeoutException()); //Prior to the fix the exception thrown was 'error connecting: Timeout expired. The timeout period elapsed prior to obtaining a connection from the pool. This may have occurred because all pooled connections were in use and max pool size was reached.' after the 10th execution. - Assert.That(ex.Message, Is.EqualTo("Fatal error encountered during command execution.")); + Assert.That(ex.Message, Is.EqualTo("Fatal error encountered during command execution")); } } diff --git a/MySQL.Data/tests/MySql.Data.Tests/DnsSrvTests.cs b/MySQL.Data/tests/MySql.Data.Tests/DnsSrvTests.cs index 205c5d3c6..0aa3f84b6 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/DnsSrvTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/DnsSrvTests.cs @@ -51,13 +51,13 @@ public void DnsSrvConnectionStringInvalidOptions(string connString) var exception = Assert.Throws(() => new MySqlConnection(connString)); } - [TestCase("server=localhost;port=33060;dns-srv=true;", "Specifying a port number with DNS SRV lookup is not permitted.")] - [TestCase("server=localhost,10.10.10.10;dns-srv=true;", "Specifying multiple host names with DNS SRV lookup is not permitted.")] - [TestCase("host=localhost,10.10.10.10;dns-srv=TRUE;", "Specifying multiple host names with DNS SRV lookup is not permitted.")] - [TestCase("server=(address=localhost,priority=100), (address=10.10.10.10,priority=90);dns-srv=true;", "Specifying multiple host names with DNS SRV lookup is not permitted.")] - [TestCase("server=localhost;protocol=unix;Dns-Srv=true;", "Using Unix domain sockets with DNS SRV lookup is not permitted.")] - [TestCase("server=localhost;protocol=unixSocket;dns-srv=true;", "Using Unix domain sockets with DNS SRV lookup is not permitted.")] - [TestCase("server=localhost;connectionprotocol=unix;DnsSrv=true;", "Using Unix domain sockets with DNS SRV lookup is not permitted.")] + [TestCase("server=localhost;port=33060;dns-srv=true;", "Specifying a port number with DNS SRV lookup is not permitted")] + [TestCase("server=localhost,10.10.10.10;dns-srv=true;", "Specifying multiple host names with DNS SRV lookup is not permitted")] + [TestCase("host=localhost,10.10.10.10;dns-srv=TRUE;", "Specifying multiple host names with DNS SRV lookup is not permitted")] + [TestCase("server=(address=localhost,priority=100), (address=10.10.10.10,priority=90);dns-srv=true;", "Specifying multiple host names with DNS SRV lookup is not permitted")] + [TestCase("server=localhost;protocol=unix;Dns-Srv=true;", "Using Unix domain sockets with DNS SRV lookup is not permitted")] + [TestCase("server=localhost;protocol=unixSocket;dns-srv=true;", "Using Unix domain sockets with DNS SRV lookup is not permitted")] + [TestCase("server=localhost;connectionprotocol=unix;DnsSrv=true;", "Using Unix domain sockets with DNS SRV lookup is not permitted")] public void DnsSrvConnectionStringInvalidConfiguration(string connString, string exceptionMessage) { var exception = Assert.Throws(() => new MySqlConnection(connString)); diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/UsageAdvisorTests.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/UsageAdvisorTests.cs index 84652a091..ec5eb62e6 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/UsageAdvisorTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/UsageAdvisorTests.cs @@ -75,12 +75,12 @@ public void NotReadingEveryField() Assert.That(listener.Strings[0], Does.Contain("Query Opened: SELECT * FROM Test; SELECT * FROM Test WHERE id > 2")); Assert.That(listener.Strings[1], Does.Contain("Resultset Opened: field(s) = 2, affected rows = -1, inserted id = -1")); Assert.That(listener.Strings[2], Does.Contain("Usage Advisor Warning: Query does not use an index")); - Assert.That(listener.Strings[3], Does.Contain("Usage Advisor Warning: Skipped 2 rows. Consider a more focused query.")); + Assert.That(listener.Strings[3], Does.Contain("Usage Advisor Warning: Skipped 2 rows. Consider a more focused query")); Assert.That(listener.Strings[4], Does.Contain("Usage Advisor Warning: The following columns were not accessed: name")); Assert.That(listener.Strings[5], Does.Contain("Resultset Closed. Total rows=4, skipped rows=2, size (bytes)=32")); Assert.That(listener.Strings[6], Does.Contain("Resultset Opened: field(s) = 2, affected rows = -1, inserted id = -1")); Assert.That(listener.Strings[7], Does.Contain("Usage Advisor Warning: Query does not use an index")); - Assert.That(listener.Strings[8], Does.Contain("Usage Advisor Warning: Skipped 1 rows. Consider a more focused query.")); + Assert.That(listener.Strings[8], Does.Contain("Usage Advisor Warning: Skipped 1 rows. Consider a more focused query")); Assert.That(listener.Strings[9], Does.Contain("Usage Advisor Warning: The following columns were not accessed: id")); Assert.That(listener.Strings[10], Does.Contain("Resultset Closed. Total rows=2, skipped rows=1, size (bytes)=16")); Assert.That(listener.Strings[11], Does.Contain("Query Closed")); @@ -115,7 +115,7 @@ public void NotReadingEveryRow() Assert.That(listener.Strings[0], Does.Contain("Query Opened: SELECT * FROM Test; SELECT * FROM Test WHERE id > 2")); Assert.That(listener.Strings[1], Does.Contain("Resultset Opened: field(s) = 2, affected rows = -1, inserted id = -1")); Assert.That(listener.Strings[2], Does.Contain("Usage Advisor Warning: Query does not use an index")); - Assert.That(listener.Strings[3], Does.Contain("Usage Advisor Warning: Skipped 2 rows. Consider a more focused query.")); + Assert.That(listener.Strings[3], Does.Contain("Usage Advisor Warning: Skipped 2 rows. Consider a more focused query")); Assert.That(listener.Strings[4], Does.Contain("Usage Advisor Warning: The following columns were not accessed: id,name")); Assert.That(listener.Strings[5], Does.Contain("Resultset Closed. Total rows=4, skipped rows=2, size (bytes)=32")); Assert.That(listener.Strings[6], Does.Contain("Resultset Opened: field(s) = 2, affected rows = -1, inserted id = -1")); diff --git a/MySQL.Data/tests/MySql.Data.Tests/ParameterTests.cs b/MySQL.Data/tests/MySql.Data.Tests/ParameterTests.cs index ce075ed76..bca23970c 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/ParameterTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/ParameterTests.cs @@ -486,7 +486,7 @@ public void DoubleAddingParameters() Assert.That(cmd.Parameters.IndexOf("@id"), Is.EqualTo(-1)); cmd.Parameters.AddWithValue("name", "test"); Exception ex = Assert.Throws(() => cmd.Parameters.AddWithValue("?id", 2)); - Assert.That(ex.Message, Is.EqualTo("Parameter '?id' has already been defined.")); + Assert.That(ex.Message, Is.EqualTo("Parameter '?id' has already been defined")); } /// @@ -696,7 +696,7 @@ public void CanThrowAnExceptionWhenMixingParameterNaming() cmd.Parameters.AddWithValue("?Id", 1); cmd.Parameters.AddWithValue("?name", "test"); Exception ex = Assert.Throws(() => cmd.ExecuteNonQuery()); - Assert.That(ex.Message, Is.EqualTo("Fatal error encountered during command execution.")); + Assert.That(ex.Message, Is.EqualTo("Fatal error encountered during command execution")); } /// diff --git a/MySQL.Data/tests/MySql.Data.Tests/PoolingTests.cs b/MySQL.Data/tests/MySql.Data.Tests/PoolingTests.cs index bc638723a..46b466f8d 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/PoolingTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/PoolingTests.cs @@ -126,7 +126,7 @@ public void ReclaimBrokenConnection() // now attempting to open a connection should fail MySqlConnection c2 = new MySqlConnection(connStr); Exception ex = Assert.Throws(() => c2.Open()); - Assert.That(ex.Message, Does.Contain("error connecting: Timeout expired. The timeout period elapsed prior to obtaining a connection from the pool.")); + Assert.That(ex.Message, Does.Contain("error connecting: Timeout expired. The timeout period elapsed prior to obtaining a connection from the pool")); // we now kill the first connection to simulate a server stoppage KillConnection(c); @@ -134,7 +134,7 @@ public void ReclaimBrokenConnection() // now we do something on the first connection ex = Assert.Throws(() => c.ChangeDatabase("mysql")); - Assert.That(ex.Message, Does.Contain("The connection is not open.")); + Assert.That(ex.Message, Does.Contain("The connection is not open")); // Opening a connection now should work MySqlConnection connection = new MySqlConnection(connStr); diff --git a/MySQL.Data/tests/MySql.Data.Tests/PreparedStatements.cs b/MySQL.Data/tests/MySql.Data.Tests/PreparedStatements.cs index 226e5abcb..53166d748 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/PreparedStatements.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/PreparedStatements.cs @@ -620,7 +620,7 @@ public void PrepareEmptyString() MySqlCommand cmd = new MySqlCommand("", Connection); cmd.Prepare(); Exception ex = Assert.Throws(() => cmd.ExecuteNonQuery()); - Assert.That(ex.Message, Is.EqualTo("The CommandText property has not been properly initialized.")); + Assert.That(ex.Message, Is.EqualTo("The CommandText property has not been properly initialized")); } /// diff --git a/MySQL.Data/tests/MySql.Data.Tests/SimpleTransactions.cs b/MySQL.Data/tests/MySql.Data.Tests/SimpleTransactions.cs index b2719f841..f71fce02c 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/SimpleTransactions.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/SimpleTransactions.cs @@ -81,7 +81,7 @@ public void NestedTransactions() MySqlTransaction t1 = Connection.BeginTransaction(); Exception ex = Assert.Throws(() => { Connection.BeginTransaction(); }); - Assert.That(ex.Message, Is.EqualTo("Nested transactions are not supported.")); + Assert.That(ex.Message, Is.EqualTo("Nested transactions are not supported")); t1.Rollback(); } @@ -99,7 +99,7 @@ public void BeginTransactionOnPreviouslyOpenConnection() } catch (Exception ex) { - Assert.That(ex.Message, Is.EqualTo("The connection is not open.")); + Assert.That(ex.Message, Is.EqualTo("The connection is not open")); } } diff --git a/MySQL.Data/tests/MySql.Data.Tests/Transactions.cs b/MySQL.Data/tests/MySql.Data.Tests/Transactions.cs index 0ac8a5152..83c264d3b 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Transactions.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Transactions.cs @@ -661,7 +661,7 @@ public void SnapshotIsolationLevelThrowsNotSupportedException() { newcon.Open(); var ex = Assert.Throws(() => newcon.BeginTransaction(System.Data.IsolationLevel.Snapshot)); - Assert.That(ex.Message, Is.EqualTo("Snapshot isolation level is not supported.")); + Assert.That(ex.Message, Is.EqualTo("Snapshot isolation level is not supported")); } } diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/BasicFindTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/BasicFindTests.cs index df3f15a85..55208117a 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/BasicFindTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/BasicFindTests.cs @@ -211,10 +211,10 @@ public void RowLockingNotSupportedInOlderVersions() Collection coll = CreateCollection("test"); Exception ex = Assert.Throws(() => ExecuteFindStatement(coll.Find().LockShared())); - Assert.That(ex.Message, Is.EqualTo("This functionality is only supported from server version 8.0.3 onwards.")); + Assert.That(ex.Message, Is.EqualTo("This functionality is only supported from server version 8.0.3 onwards")); ex = Assert.Throws(() => ExecuteFindStatement(coll.Find().LockExclusive())); - Assert.That(ex.Message, Is.EqualTo("This functionality is only supported from server version 8.0.3 onwards.")); + Assert.That(ex.Message, Is.EqualTo("This functionality is only supported from server version 8.0.3 onwards")); } [Test] diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/ClientSideFailoverTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/ClientSideFailoverTests.cs index 34834ca26..d66254a17 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/ClientSideFailoverTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/ClientSideFailoverTests.cs @@ -82,11 +82,11 @@ public void RandomMethodWithBasicFormatConnectionString() // Multiple hosts. All attempts fail. Exception ex = Assert.Throws(() => MySQLX.GetSession($"server= 10.10.10.10, 20.20.20.20 ;port={XPort};uid=test;password=test;connecttimeout={connectionTimeout}")); - Assert.That(ex.Message, Is.EqualTo("Unable to connect to any of the specified MySQL hosts.")); + Assert.That(ex.Message, Is.EqualTo("Unable to connect to any of the specified MySQL hosts")); // Providing port number as part of the host name. ex = Assert.Throws(() => MySQLX.GetSession($"server= 10.10.10.10:33050, 20.20.20.20:33060, {Host}:{XPort} ;port={XPort};uid=test;password=test;connecttimeout={connectionTimeout}")); - Assert.That(ex.Message, Is.EqualTo("Providing a port number as part of the host address isn't supported when using connection strings in basic format or anonymous objects. Use URI format instead.")); + Assert.That(ex.Message, Is.EqualTo("Providing a port number as part of the host address isn't supported when using connection strings in basic format or anonymous objects. Use URI format instead")); } [Test] @@ -167,11 +167,11 @@ public void RandomMethodWithAnonymousTypes() // Multiple hosts. All attempts fail. Exception ex = Assert.Throws(() => MySQLX.GetSession(new { server = "10.10.10.10, 20.20.20.20", port = XPort, uid = uid, password = password, connecttimeout = connectionTimeout })); - Assert.That(ex.Message, Is.EqualTo("Unable to connect to any of the specified MySQL hosts.")); + Assert.That(ex.Message, Is.EqualTo("Unable to connect to any of the specified MySQL hosts")); // Providing port number as part of the host name. ex = Assert.Throws(() => MySQLX.GetSession(new { server = "10.10.10.10:33060, 20.20.20.20:33060", port = XPort, uid = uid, password = password, connecttimeout = connectionTimeout })); - Assert.That(ex.Message, Is.EqualTo("Providing a port number as part of the host address isn't supported when using connection strings in basic format or anonymous objects. Use URI format instead.")); + Assert.That(ex.Message, Is.EqualTo("Providing a port number as part of the host address isn't supported when using connection strings in basic format or anonymous objects. Use URI format instead")); } [Test] @@ -242,18 +242,18 @@ public void PriorityMethodWithBasicFormatConnectionString() // Priority outside the 0-100 allowed range. Exception ex = Assert.Throws(() => MySQLX.GetSession($"server=(address=server.example,priority=-20),(address={Host},priority=100);port=" + XPort + ";uid=test;password=test;connecttimeout=" + connectionTimeout)); - Assert.That(ex.Message, Is.EqualTo("The priority must be between 0 and 100.")); + Assert.That(ex.Message, Is.EqualTo("The priority must be between 0 and 100")); ex = Assert.Throws(() => MySQLX.GetSession($"server=(address=server.example,priority=-50),(address={Host},priority=101);port=" + XPort + ";uid=test;password=test;connecttimeout=" + connectionTimeout)); - Assert.That(ex.Message, Is.EqualTo("The priority must be between 0 and 100.")); + Assert.That(ex.Message, Is.EqualTo("The priority must be between 0 and 100")); // Set priority for a subset of the hosts. ex = Assert.Throws(() => MySQLX.GetSession($"server=(address=server.example),(address={Host},priority=100);port=" + XPort + ";uid=test;password=test;connecttimeout=" + connectionTimeout)); - Assert.That(ex.Message, Is.EqualTo("You must either assign no priority to any of the hosts or give a priority for every host.")); + Assert.That(ex.Message, Is.EqualTo("You must either assign no priority to any of the hosts or give a priority for every host")); ex = Assert.Throws(() => MySQLX.GetSession($"server=(address=server.example,priority=50),(address={Host});port=" + XPort + ";uid=test;password=test;connecttimeout=" + connectionTimeout)); - Assert.That(ex.Message, Is.EqualTo("You must either assign no priority to any of the hosts or give a priority for every host.")); + Assert.That(ex.Message, Is.EqualTo("You must either assign no priority to any of the hosts or give a priority for every host")); ex = Assert.Throws(() => MySQLX.GetSession($"server=(address=server.example,priority=50),(address={Host},priority=100),(address=server.example);port=" + XPort + ";uid=test;password=test;connecttimeout=" + connectionTimeout)); - Assert.That(ex.Message, Is.EqualTo("You must either assign no priority to any of the hosts or give a priority for every host.")); + Assert.That(ex.Message, Is.EqualTo("You must either assign no priority to any of the hosts or give a priority for every host")); // Automatically set priority if no priority is given. string hostList = string.Empty; @@ -324,18 +324,18 @@ public void PriorityMethodWithUriFormatConnectonString() // Priority outside the 0-100 allowed range. Exception ex = Assert.Throws(() => MySQLX.GetSession($"mysqlx://test:test@[(address=server.example,priority=-20),(address={Host}:{XPort},priority=100)]?connecttimeout=" + connectionTimeout)); - Assert.That(ex.Message, Is.EqualTo("The priority must be between 0 and 100.")); + Assert.That(ex.Message, Is.EqualTo("The priority must be between 0 and 100")); ex = Assert.Throws(() => MySQLX.GetSession($"mysqlx://test:test@[(address=server.example,priority=50),(address={Host}:{XPort},priority=101)]?connecttimeout=" + connectionTimeout)); - Assert.That(ex.Message, Is.EqualTo("The priority must be between 0 and 100.")); + Assert.That(ex.Message, Is.EqualTo("The priority must be between 0 and 100")); // Set priority for a subset of the hosts. ex = Assert.Throws(() => MySQLX.GetSession($"mysqlx://test:test@[(address=server.example),(address={Host}:{XPort},priority=100)]?connecttimeout=" + connectionTimeout)); - Assert.That(ex.Message, Is.EqualTo("You must either assign no priority to any of the hosts or give a priority for every host.")); + Assert.That(ex.Message, Is.EqualTo("You must either assign no priority to any of the hosts or give a priority for every host")); ex = Assert.Throws(() => MySQLX.GetSession($"mysqlx://test:test@[(address=server.example,priority=100),(address={Host}:{XPort})]?connecttimeout=" + connectionTimeout)); - Assert.That(ex.Message, Is.EqualTo("You must either assign no priority to any of the hosts or give a priority for every host.")); + Assert.That(ex.Message, Is.EqualTo("You must either assign no priority to any of the hosts or give a priority for every host")); ex = Assert.Throws(() => MySQLX.GetSession($"mysqlx://test:test@[(address=server.example),(address={Host}:{XPort}),(address=server2.example,priority=100)]?connecttimeout=" + connectionTimeout)); - Assert.That(ex.Message, Is.EqualTo("You must either assign no priority to any of the hosts or give a priority for every host.")); + Assert.That(ex.Message, Is.EqualTo("You must either assign no priority to any of the hosts or give a priority for every host")); // Automatically set priority if no priority is given. string hostList = string.Empty; @@ -414,18 +414,18 @@ public void PriorityMethodWithAnonymousTypes() // Priority outside the 0-100 allowed range. Exception ex = Assert.Throws(() => MySQLX.GetSession(new { server = $"(address=server.example,priority=-20),(address={Host},priority=100)", port = XPort, uid = uid, password = password, connecttimeout = connectionTimeout })); - Assert.That(ex.Message, Is.EqualTo("The priority must be between 0 and 100.")); + Assert.That(ex.Message, Is.EqualTo("The priority must be between 0 and 100")); ex = Assert.Throws(() => MySQLX.GetSession(new { server = $"(address=server.example,priority=-50),(address={Host},priority=101)", port = XPort, uid = uid, password = password, connecttimeout = connectionTimeout })); - Assert.That(ex.Message, Is.EqualTo("The priority must be between 0 and 100.")); + Assert.That(ex.Message, Is.EqualTo("The priority must be between 0 and 100")); // Set priority for a subset of the hosts. ex = Assert.Throws(() => MySQLX.GetSession(new { server = $"(address=server.example),(address={Host},priority=100)", port = XPort, uid = uid, password = password, connecttimeout = connectionTimeout })); - Assert.That(ex.Message, Is.EqualTo("You must either assign no priority to any of the hosts or give a priority for every host.")); + Assert.That(ex.Message, Is.EqualTo("You must either assign no priority to any of the hosts or give a priority for every host")); ex = Assert.Throws(() => MySQLX.GetSession(new { server = $"(address=server.example,priority=50),(address={Host})", port = XPort, uid = uid, password = password, connecttimeout = connectionTimeout })); - Assert.That(ex.Message, Is.EqualTo("You must either assign no priority to any of the hosts or give a priority for every host.")); + Assert.That(ex.Message, Is.EqualTo("You must either assign no priority to any of the hosts or give a priority for every host")); ex = Assert.Throws(() => MySQLX.GetSession(new { server = $"(address=server.example,priority=50),(address={Host},priority=100),(address=server.example)", port = XPort, uid = uid, password = password, connecttimeout = connectionTimeout })); - Assert.That(ex.Message, Is.EqualTo("You must either assign no priority to any of the hosts or give a priority for every host.")); + Assert.That(ex.Message, Is.EqualTo("You must either assign no priority to any of the hosts or give a priority for every host")); // Automatically set priority if no priority is given. string hostList = string.Empty; diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/ClientTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/ClientTests.cs index f56f03b76..bc5a2b17c 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/ClientTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/ClientTests.cs @@ -467,7 +467,7 @@ public void ConnectionAttributes() builder.UserID = RootUser; builder.ConnectionAttributes = ";"; ex = Assert.Throws(() => MySQLX.GetClient(builder.ConnectionString, "{ \"pooling\": { \"enabled\": true } }")); - Assert.That(ex.Message, Is.EqualTo("The requested value ';' is invalid for the given keyword 'connection-attributes'.")); + Assert.That(ex.Message, Is.EqualTo("The requested value ';' is invalid for the given keyword 'connection-attributes'")); } private void TestConnectionAttributes(string connString, Dictionary userAttrs = null) @@ -1479,7 +1479,7 @@ public void GetSessionExceptionWithConnetionAttribute() , "{ \"pooling\": { \"enabled\": true } }")) { Exception ex = Assert.Throws(() => client.GetSession()); - Assert.That(ex.Message, Is.EqualTo("The requested value '=' is invalid for the given keyword 'connection-attributes'.")); + Assert.That(ex.Message, Is.EqualTo("The requested value '=' is invalid for the given keyword 'connection-attributes'")); } } @@ -1743,7 +1743,7 @@ public void ConnectionAttributesInvalidCombinations() { Assume.That(session.Version.isAtLeast(8, 0, 16), "This test is for MySql 8.0.16 or higher"); object[] invalid = new object[] { "var1", "1", "2", "(var1)", "{var1}", "[_testValue = test123, emptyValue]" }; - var errorMsgs = new string[] { @"The value of ""connection-attributes"" must be either a boolean or a list of key-value pairs.", @"Key names in ""connection-attributes"" cannot start with ""_""." }; + var errorMsgs = new string[] { @"The value of ""connection-attributes"" must be either a boolean or a list of key-value pairs", @"Key names in ""connection-attributes"" cannot start with ""_""" }; for (int i = 0; i < invalid.Length; i++) { //Connection String @@ -1992,7 +1992,7 @@ public void ConnectionAttributesKeyWithUnderLineChars() Assume.That(Platform.IsWindows(), "This test is for Windows OS only."); Assume.That(session.Version.isAtLeast(8, 0, 16), "This test is for MySql 8.0.16 or higher"); MySqlXConnectionStringBuilder sb = new MySqlXConnectionStringBuilder(ConnectionString); - var expectedMsg = @"Key names in ""connection-attributes"" cannot start with ""_""."; + var expectedMsg = @"Key names in ""connection-attributes"" cannot start with ""_"""; //Connection string using (Client client = MySQLX.GetClient(ConnectionString + ";connection-attributes=[_foo32=bar,quua=qux,key]", "{ \"pooling\": { \"enabled\": true } }")) { @@ -2061,7 +2061,7 @@ public void ConnectionAttributesKeyBlankChars() Assume.That(Platform.IsWindows(), "This test is for Windows OS only."); Assume.That(session.Version.isAtLeast(8, 0, 16), "This test is for MySql 8.0.16 or higher"); MySqlXConnectionStringBuilder sb = new MySqlXConnectionStringBuilder(ConnectionString); - var expectedMsg = "Key name in connection attribute cannot be an empty string."; + var expectedMsg = "Key name in connection attribute cannot be an empty string"; //Connection String using (Client client = MySQLX.GetClient(ConnectionString + ";connection-attributes=[=bar,quua=qux,key]", "{ \"pooling\": { \"enabled\": true } }")) { diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/CollectionIndexTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/CollectionIndexTests.cs index ed80e6497..f8c5f6736 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/CollectionIndexTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/CollectionIndexTests.cs @@ -48,19 +48,19 @@ public void IncorrectlyFormatedIndexDefinition() var collection = CreateCollection("test"); Exception ex = Assert.Throws(() => collection.CreateIndex("myIndex", "{\"type\": \"INDEX\" }")); - Assert.That(ex.Message, Is.EqualTo("Field 'fields' is mandatory.")); + Assert.That(ex.Message, Is.EqualTo("Field 'fields' is mandatory")); ex = Assert.Throws(() => collection.CreateIndex("myIndex", "{\"fields\": [ { \"field\":$.myField, \"type\":\"TEXT\" } ], \"unexpectedField\" : false }")); - Assert.That(ex.Message, Is.EqualTo("Field name 'unexpectedField' is not allowed.")); + Assert.That(ex.Message, Is.EqualTo("Field name 'unexpectedField' is not allowed")); ex = Assert.Throws(() => collection.CreateIndex("myIndex", "{\"fields\": [ { \"fields\":$.myField, \"types\":\"TEXT\" } ] }")); - Assert.That(ex.Message, Is.EqualTo("Field 'field' is mandatory.")); + Assert.That(ex.Message, Is.EqualTo("Field 'field' is mandatory")); ex = Assert.Throws(() => collection.CreateIndex("myIndex", "{\"fields\": [ { \"field\":$.myField, \"types\":\"TEXT\" } ] }")); - Assert.That(ex.Message, Is.EqualTo("Field 'type' is mandatory.")); + Assert.That(ex.Message, Is.EqualTo("Field 'type' is mandatory")); ex = Assert.Throws(() => collection.CreateIndex("myIndex", "{\"fields\": [ { \"field\":$.myField, \"type\":\"TEXT\", \"unexpectedField\" : false } ] }")); - Assert.That(ex.Message, Is.EqualTo("Field name 'unexpectedField' is not allowed.")); + Assert.That(ex.Message, Is.EqualTo("Field name 'unexpectedField' is not allowed")); Assume.That(session.Version.isAtLeast(8, 0, 11), "This test is for MySql 8.0.11 or higher"); collection = CreateCollection("test"); @@ -251,13 +251,13 @@ public void CreateIndexWithInvalidJsonDocumentStructure() var collection = CreateCollection("test"); Exception ex = Assert.Throws(() => collection.CreateIndex("myIndex", "{\"fields\": [ { \"field\":$.myField, \"type\":\"INT\", \"myCustomField\":\"myCustomValue\" } ] }")); - Assert.That(ex.Message, Is.EqualTo("Field name 'myCustomField' is not allowed.")); + Assert.That(ex.Message, Is.EqualTo("Field name 'myCustomField' is not allowed")); ex = Assert.Throws(() => collection.CreateIndex("myIndex", "{\"fields\": [ { \"field\":$.myField, \"mytype\":\"INT\" } ] }")); - Assert.That(ex.Message, Is.EqualTo("Field 'type' is mandatory.")); + Assert.That(ex.Message, Is.EqualTo("Field 'type' is mandatory")); ex = Assert.Throws(() => collection.CreateIndex("myIndex", "{\"fields\": [ { \"myfield\":$.myField, \"type\":\"INT\" } ] }")); - Assert.That(ex.Message, Is.EqualTo("Field 'field' is mandatory.")); + Assert.That(ex.Message, Is.EqualTo("Field 'field' is mandatory")); ex = Assert.Throws(() => collection.CreateIndex("myIndex", "{\"fields\": [ { \"field\":$.name, \"type\":\"TEXT\" , \"myCustomField\":\"myCustomValue\"} ] }")); - Assert.That(ex.Message, Is.EqualTo("Field name 'myCustomField' is not allowed.")); + Assert.That(ex.Message, Is.EqualTo("Field name 'myCustomField' is not allowed")); ex = Assert.Throws(() => collection.CreateIndex("myIndex", "")); Assert.That(ex.Message, Is.EqualTo("The value provided is not a valid JSON document. Index was outside the bounds of the array.")); } diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/CollectionTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/CollectionTests.cs index 7b9471364..6a03fdf4b 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/CollectionTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/CollectionTests.cs @@ -187,9 +187,9 @@ public void CountCollection() // Collection/Table does not exist var ex = Assert.Throws(() => schema.GetCollection("testCount_").Count()); - Assert.That(ex.Message, Is.EqualTo("Collection 'testCount_' does not exist in schema 'test'.")); + Assert.That(ex.Message, Is.EqualTo("Collection 'testCount_' does not exist in schema 'test'")); ex = Assert.Throws(() => schema.GetTable("testCount_").Count()); - Assert.That(ex.Message, Is.EqualTo("Table 'testCount_' does not exist in schema 'test'.")); + Assert.That(ex.Message, Is.EqualTo("Table 'testCount_' does not exist in schema 'test'")); } [Test] diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/CompressionTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/CompressionTests.cs index d6e7b8a5d..88212c2e3 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/CompressionTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/CompressionTests.cs @@ -175,10 +175,10 @@ public void SettingAnInvalidCompressionTypeRaisesException() foreach (var invalidValue in invalidValues) { var exception = Assert.Throws(() => new MySqlXConnectionStringBuilder($"server={Host};port={XPort};compression={invalidValue}")); - Assert.That(exception.Message, Is.EqualTo($"The connection property 'compression' acceptable values are: 'preferred', 'required' or 'disabled'. The value '{invalidValue}' is not acceptable.")); + Assert.That(exception.Message, Is.EqualTo($"The connection property 'compression' acceptable values are: 'preferred', 'required' or 'disabled'. The value '{invalidValue}' is not acceptable")); exception = Assert.Throws(() => MySQLX.GetSession($"server={Host};port={XPort};user=root;compression={invalidValue}")); - Assert.That(exception.Message, Is.EqualTo($"The connection property 'compression' acceptable values are: 'preferred', 'required' or 'disabled'. The value '{invalidValue}' is not acceptable.")); + Assert.That(exception.Message, Is.EqualTo($"The connection property 'compression' acceptable values are: 'preferred', 'required' or 'disabled'. The value '{invalidValue}' is not acceptable")); } } @@ -460,7 +460,7 @@ public void ConfigurableCompressionAlgorithms() // The connection should terminate with an error when compression option is set to required. Exception ex = Assert.Throws(() => MySQLX.GetSession(ConnectionString + ";compression=required;compression-algorithms=NotSupported,SomethingElse;")); - Assert.That(ex.Message, Is.EqualTo("Compression requested but the compression algorithm negotiation failed.")); + Assert.That(ex.Message, Is.EqualTo("Compression requested but the compression algorithm negotiation failed")); // FR4_4 Start server with specific compression algorithm and create session with option // compression-algorithms.Set the option with multiple compression algorithms. diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/CrudRemoveTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/CrudRemoveTests.cs index 1bce4e78c..741cb7a92 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/CrudRemoveTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/CrudRemoveTests.cs @@ -59,9 +59,9 @@ public void RemoveSingleDocumentById() var ex = Assert.Throws(() => coll.Remove("")); #if !NETFRAMEWORK - Assert.That(ex.Message, Is.EqualTo("Parameter can't be null or empty. (Parameter 'condition')")); + Assert.That(ex.Message, Is.EqualTo("Parameter can't be null or empty (Parameter 'condition')")); #else - Assert.That(ex.Message, Is.EqualTo("Parameter can't be null or empty.\r\nParameter name: condition")); + Assert.That(ex.Message, Is.EqualTo("Parameter can't be null or empty\r\nParameter name: condition")); #endif } @@ -176,9 +176,9 @@ public void RemoveAll() // Condition can't be null or empty. string errorMessage = string.Empty; #if !NETFRAMEWORK - errorMessage = "Parameter can't be null or empty. (Parameter 'condition')"; + errorMessage = "Parameter can't be null or empty (Parameter 'condition')"; #else - errorMessage = "Parameter can't be null or empty.\r\nParameter name: condition"; + errorMessage = "Parameter can't be null or empty\r\nParameter name: condition"; #endif Exception ex = Assert.Throws(() => ExecuteRemoveStatement(collection.Remove(string.Empty))); Assert.That(ex.Message, Is.EqualTo(errorMessage)); diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/CrudUpdateTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/CrudUpdateTests.cs index c686b97c1..fab5a0f31 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/CrudUpdateTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/CrudUpdateTests.cs @@ -166,9 +166,9 @@ public void ModifyAll() // Condition can't be null or empty. string errorMessage = string.Empty; #if !NETFRAMEWORK - errorMessage = "Parameter can't be null or empty. (Parameter 'condition')"; + errorMessage = "Parameter can't be null or empty (Parameter 'condition')"; #else - errorMessage = "Parameter can't be null or empty.\r\nParameter name: condition"; + errorMessage = "Parameter can't be null or empty\r\nParameter name: condition"; #endif Exception ex = Assert.Throws(() => ExecuteModifyStatement(collection.Modify(string.Empty))); Assert.That(errorMessage, Is.EqualTo(ex.Message)); @@ -350,9 +350,9 @@ public void ArrayInsert() // Insert an empty string fails. var ex = Assert.Throws(() => ExecuteModifyStatement(collection.Modify("true").ArrayInsert("x[0]", ""))); - Assert.That(ex.Message, Does.Contain("String can't be empty.")); + Assert.That(ex.Message, Does.Contain("String can't be empty")); ex = Assert.Throws(() => ExecuteModifyStatement(collection.Modify("true").ArrayInsert("x[0]", string.Empty))); - Assert.That(ex.Message, Does.Contain("String can't be empty.")); + Assert.That(ex.Message, Does.Contain("String can't be empty")); // Not specifying an index raises an error. var ex2 = Assert.Throws(() => ExecuteModifyStatement(collection.Modify("true").ArrayInsert("dates", "5/1/2018"))); @@ -457,9 +457,9 @@ public void ArrayAppend() Assert.That(document.values.ContainsKey("y"), Is.False); var ex = Assert.Throws(() => ExecuteModifyStatement(collection.Modify("true").ArrayAppend("x", ""))); - Assert.That(ex.Message, Does.Contain("String can't be empty.")); + Assert.That(ex.Message, Does.Contain("String can't be empty")); ex = Assert.Throws(() => ExecuteModifyStatement(collection.Modify("true").ArrayAppend("x", string.Empty))); - Assert.That(ex.Message, Does.Contain("String can't be empty.")); + Assert.That(ex.Message, Does.Contain("String can't be empty")); var col = CreateCollection("my_collection"); var t1 = "{\"_id\": \"1001\", \"ARR\":[1,2,3], \"ARR1\":[\"name1\",\"name2\", \"name3\"]}"; diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/DnsSrvTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/DnsSrvTests.cs index ff82ee248..d6ebc34c8 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/DnsSrvTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/DnsSrvTests.cs @@ -39,13 +39,13 @@ namespace MySqlX.Data.Tests /// public class DnsSrvTests : BaseTest { - [TestCase("server=localhost;port=33060;dns-srv=true;", "Specifying a port number with DNS SRV lookup is not permitted.")] - [TestCase("server=localhost,10.10.10.10;dns-srv=true;", "Specifying multiple host names with DNS SRV lookup is not permitted.")] - [TestCase("host=localhost,10.10.10.10;dns-srv=TRUE;", "Specifying multiple host names with DNS SRV lookup is not permitted.")] - [TestCase("server=(address=localhost,priority=100), (address=10.10.10.10,priority=90);dns-srv=true;", "Specifying multiple host names with DNS SRV lookup is not permitted.")] - [TestCase("server=localhost;protocol=unix;Dns-Srv=true;", "Using Unix domain sockets with DNS SRV lookup is not permitted.")] - [TestCase("server=localhost;protocol=unixSocket;dns-srv=true;", "Using Unix domain sockets with DNS SRV lookup is not permitted.")] - [TestCase("server=localhost;connectionprotocol=unix;DnsSrv=true;", "Using Unix domain sockets with DNS SRV lookup is not permitted.")] + [TestCase("server=localhost;port=33060;dns-srv=true;", "Specifying a port number with DNS SRV lookup is not permitted")] + [TestCase("server=localhost,10.10.10.10;dns-srv=true;", "Specifying multiple host names with DNS SRV lookup is not permitted")] + [TestCase("host=localhost,10.10.10.10;dns-srv=TRUE;", "Specifying multiple host names with DNS SRV lookup is not permitted")] + [TestCase("server=(address=localhost,priority=100), (address=10.10.10.10,priority=90);dns-srv=true;", "Specifying multiple host names with DNS SRV lookup is not permitted")] + [TestCase("server=localhost;protocol=unix;Dns-Srv=true;", "Using Unix domain sockets with DNS SRV lookup is not permitted")] + [TestCase("server=localhost;protocol=unixSocket;dns-srv=true;", "Using Unix domain sockets with DNS SRV lookup is not permitted")] + [TestCase("server=localhost;connectionprotocol=unix;DnsSrv=true;", "Using Unix domain sockets with DNS SRV lookup is not permitted")] public void DnsSrvConnectionStringInvalidConfiguration(string connString, string exceptionMessage) { connString = connString.Replace("localhost", Host).Replace("33060", XPort); @@ -104,12 +104,12 @@ public void DnsSrvConnectionAnonymousTypeInvalidConfiguration() Assert.That(exception.Message, Is.EqualTo(MySql.Data.Resources.DnsSrvInvalidConnOptionUnixSocket)); } - [TestCase("mysqlx+srv://test:test@localhost:33060", "Specifying a port number with DNS SRV lookup is not permitted.")] - [TestCase("mysqlx+srv://test:test@[192.1.10.10,localhost]", "Specifying multiple host names with DNS SRV lookup is not permitted.")] - [TestCase("mysqlx+srv://test:test@[192.1.10.10,localhost:33060]/test", "Specifying multiple host names with DNS SRV lookup is not permitted.")] - [TestCase("mysqlx+srv://test:test@[(address = server.example, priority = 50),(address = localhost:33060,priority=100)]", "Specifying multiple host names with DNS SRV lookup is not permitted.")] - [TestCase("mysqlx+srv://test:test@./tmp/mysql.sock?protocol=unix", "Using Unix domain sockets with DNS SRV lookup is not permitted.")] - [TestCase("mysqlx+srv://test:test@localhost?dns-srv=false;", "'dns-srv' cannot be set to false with DNS SRV lookup enabled.")] + [TestCase("mysqlx+srv://test:test@localhost:33060", "Specifying a port number with DNS SRV lookup is not permitted")] + [TestCase("mysqlx+srv://test:test@[192.1.10.10,localhost]", "Specifying multiple host names with DNS SRV lookup is not permitted")] + [TestCase("mysqlx+srv://test:test@[192.1.10.10,localhost:33060]/test", "Specifying multiple host names with DNS SRV lookup is not permitted")] + [TestCase("mysqlx+srv://test:test@[(address = server.example, priority = 50),(address = localhost:33060,priority=100)]", "Specifying multiple host names with DNS SRV lookup is not permitted")] + [TestCase("mysqlx+srv://test:test@./tmp/mysql.sock?protocol=unix", "Using Unix domain sockets with DNS SRV lookup is not permitted")] + [TestCase("mysqlx+srv://test:test@localhost?dns-srv=false;", "'dns-srv' cannot be set to false with DNS SRV lookup enabled")] public void DnsSrvConnectionStringUriInvalidConfiguration(string connStringUri, string exceptionMessage) { connStringUri = connStringUri.Replace("localhost", Host).Replace("33060", XPort); diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/TableSelectTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/TableSelectTests.cs index bcb824a7b..5e26dc418 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/TableSelectTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/TableSelectTests.cs @@ -189,10 +189,10 @@ public void RowLockingNotSupportedInOlderVersions() Table table = session.Schema.GetTable("test"); Exception ex = Assert.Throws(() => ExecuteSelectStatement(table.Select().LockShared())); - Assert.That(ex.Message, Is.EqualTo("This functionality is only supported from server version 8.0.3 onwards.")); + Assert.That(ex.Message, Is.EqualTo("This functionality is only supported from server version 8.0.3 onwards")); ex = Assert.Throws(() => ExecuteSelectStatement(table.Select().LockExclusive())); - Assert.That(ex.Message, Is.EqualTo("This functionality is only supported from server version 8.0.3 onwards.")); + Assert.That(ex.Message, Is.EqualTo("This functionality is only supported from server version 8.0.3 onwards")); } [Test] diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/SessionTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/SessionTests.cs index 9be27390c..2cb9c748b 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/SessionTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/SessionTests.cs @@ -344,7 +344,7 @@ public void IPv6AsAnonymous() [Property("Category", "Security")] public void CreateSessionWithUnsupportedOptions() { - var errorMessage = "Option not supported."; + var errorMessage = "Option not supported"; var connectionUri = string.Format("{0}?", ConnectionStringUri); // Use a connection URI. @@ -438,7 +438,7 @@ public void CreateSessionWithUnsupportedOptions() [Property("Category", "Security")] public void CreateBuilderWithUnsupportedOptions() { - var errorMessage = "Option not supported."; + var errorMessage = "Option not supported"; var ex = Assert.Throws(() => new MySqlXConnectionStringBuilder("pipe=MYSQL")); Assert.That(ex.Message, Does.StartWith(errorMessage)); ex = Assert.Throws(() => new MySqlXConnectionStringBuilder("allow batch=false")); diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/SslTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/SslTests.cs index 25828c3c7..500a1453e 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/SslTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/SslTests.cs @@ -126,7 +126,7 @@ public void SslPreferredIsInvalid() #if NET8_0_OR_GREATER prefered = "Preferred"; #endif - var expectedErrorMessage = "Value '{0}' is not of the correct type."; + var expectedErrorMessage = "Value '{0}' is not of the correct type"; // In connection string. var exception = Assert.Throws(() => MySQLX.GetSession(ConnectionStringUri + "?ssl-mode=Preferred")); diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/XConnectionStringBuilderTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/XConnectionStringBuilderTests.cs index 08acc6603..7b949d01c 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/XConnectionStringBuilderTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/XConnectionStringBuilderTests.cs @@ -154,7 +154,7 @@ public void IncorrectAuthOptionThrowsArgumentException() foreach (var value in values) { Exception ex = Assert.Throws(() => new MySqlXConnectionStringBuilder(String.Format("server=localhost;aUth={0}", value))); - Assert.That(ex.Message, Is.EqualTo(String.Format("Value '{0}' is not of the correct type.", value))); + Assert.That(ex.Message, Is.EqualTo(String.Format("Value '{0}' is not of the correct type", value))); } } diff --git a/MySql.Web/tests/SchemaManagerTests.cs b/MySql.Web/tests/SchemaManagerTests.cs index 86dd3790d..a4f1f68d2 100644 --- a/MySql.Web/tests/SchemaManagerTests.cs +++ b/MySql.Web/tests/SchemaManagerTests.cs @@ -314,7 +314,7 @@ public void InitializeInvalidConnStringThrowsArgumentException() config.Add("connectionString", badConnectionString); Exception ex = Assert.Throws(() => provider.Initialize(null, config)); - Assert.That(ex.Message, Is.EqualTo("Option not supported.\r\nParameter name: fookey")); + Assert.That(ex.Message, Is.EqualTo("Option not supported\r\nParameter name: fookey")); } } } From 3946ae3e464d9d48f71ca3a1da4864faefb4b2aa Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Sun, 14 Jul 2024 12:06:22 -0600 Subject: [PATCH 067/125] WL#16309 [Fix Code coverage] Change-Id: Idb52593fd76e8b946678432e68618e5d73a278d1 --- CHANGES | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES b/CHANGES index a9d5cdf86..bf1295dbc 100644 --- a/CHANGES +++ b/CHANGES @@ -3,6 +3,7 @@ - Changed testsuite to use assummptions instead of Assert.Ignore (WL16402). - Added support for .NET 9 and EFCore 9 preview versions (WL16308). - Added OpenTelemetry.Api NuGet package reference (WL16453). +- Fixed Code coverage (WL16309). 9.0.0 From 0087ace671d3a8f46193337bccc55018d28458ed Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Mon, 12 Aug 2024 11:48:53 -0600 Subject: [PATCH 068/125] WL#16491 [OpenID Connect authentication support] Change-Id: Ib30ed5528a6080a34d9322cdfe88dd4cf5d86b65 --- CHANGES | 1 + .../Authentication/AuthenticationManager.cs | 1 + .../OpenIdConnectClientAuthentication.cs | 41 ++++++++ .../src/MySqlConnectionStringBuilder.cs | 17 +++- MySQL.Data/src/Resources.Designer.cs | 20 +++- MySQL.Data/src/Resources.resx | 6 ++ .../tests/MySql.Data.Tests/AuthTests.cs | 96 +++++++++++++++++++ 7 files changed, 180 insertions(+), 2 deletions(-) create mode 100644 MySQL.Data/src/Authentication/OpenIdConnectClientAuthentication.cs diff --git a/CHANGES b/CHANGES index bf1295dbc..fd4dba44e 100644 --- a/CHANGES +++ b/CHANGES @@ -4,6 +4,7 @@ - Added support for .NET 9 and EFCore 9 preview versions (WL16308). - Added OpenTelemetry.Api NuGet package reference (WL16453). - Fixed Code coverage (WL16309). +- Added support for OpenID Connect client authentication (WL16491). 9.0.0 diff --git a/MySQL.Data/src/Authentication/AuthenticationManager.cs b/MySQL.Data/src/Authentication/AuthenticationManager.cs index 78e78000d..cbdcf8adb 100644 --- a/MySQL.Data/src/Authentication/AuthenticationManager.cs +++ b/MySQL.Data/src/Authentication/AuthenticationManager.cs @@ -49,6 +49,7 @@ static AuthenticationPluginManager() Plugins["authentication_kerberos_client"] = new PluginInfo("MySql.Data.MySqlClient.Authentication.KerberosAuthenticationPlugin"); Plugins["authentication_oci_client"] = new PluginInfo("MySql.Data.MySqlClient.Authentication.OciAuthenticationPlugin"); Plugins["authentication_webauthn_client"] = new PluginInfo("MySql.Data.MySqlClient.Authentication.WebAuthnAuthenticationPlugin"); + Plugins["authentication_openid_connect_client"] = new PluginInfo("MySql.Data.MySqlClient.Authentication.OpenIdConnectClientAuthentication"); AuthenticationManagerCtorConfiguration(); } diff --git a/MySQL.Data/src/Authentication/OpenIdConnectClientAuthentication.cs b/MySQL.Data/src/Authentication/OpenIdConnectClientAuthentication.cs new file mode 100644 index 000000000..ef330b3c5 --- /dev/null +++ b/MySQL.Data/src/Authentication/OpenIdConnectClientAuthentication.cs @@ -0,0 +1,41 @@ +using MySql.Data.MySqlClient; +using MySql.Data.MySqlClient.Authentication; +using Org.BouncyCastle.Utilities.Encoders; +using System; +using System.Collections.Generic; +using System.Configuration; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace MySql.Data.MySqlClient.Authentication +{ + internal class OpenIdConnectClientAuthentication : MySqlAuthenticationPlugin + { + public override string PluginName => "authentication_openid_connect_client"; + + private static int IdentityToken_sizelimit = 10 * 1024; + + protected override Task MoreDataAsync(byte[] data, bool execAsync) + { + byte[] IdToken = Encoding.GetBytes(Settings.OpenIdIdentityToken); + int responseLength = 10;//1 Byte for capability flag. the rest is for Bytes lenenc. + responseLength += IdToken.Length; + + if (IdToken == null || IdToken.Length == 0) + throw new ArgumentException(Resources.OpenIdIdentityTokenIsEmpty); + + if (IdToken.Length > IdentityToken_sizelimit) + throw new ArgumentException(Resources.OpenIdIdentityTokenTooBig); + + var response = new MySqlPacket(new MemoryStream(responseLength)); + response.Write(new byte[] { 0x01 }); //capability flag. + response.WriteLength(IdToken.Length); + response.Write(IdToken); + + response.Position = 0; + return Task.FromResult(response.Buffer); + } + } +} diff --git a/MySQL.Data/src/MySqlConnectionStringBuilder.cs b/MySQL.Data/src/MySqlConnectionStringBuilder.cs index 0a5d60e11..273da4e44 100644 --- a/MySQL.Data/src/MySqlConnectionStringBuilder.cs +++ b/MySQL.Data/src/MySqlConnectionStringBuilder.cs @@ -144,7 +144,7 @@ static MySqlConnectionStringBuilder() msb.SetValue("kerberosauthmode", value); }, (msb, sender) => msb.KerberosAuthMode)); - + Options.Add(new MySqlConnectionStringOption("openididentitytoken", null, typeof(string), string.Empty, false)); #endregion #region OtherProperties @@ -536,6 +536,21 @@ public KerberosAuthMode KerberosAuthMode set { SetValue("kerberosauthmode", value); } } + /// + /// Gets or sets the Identity Token to be used in OpenID Connect authentication. + /// + /// + /// If is set the value will be used to try to log in using OpenID Connect authentication. + /// + [Category("Authentication")] + [DisplayName("OpenIdIdentityToken")] + [Description("Specifies the Identity Token to use during OpenID Connect authentication.")] + public string OpenIdIdentityToken + { + get { return (string)values["openididentitytoken"]; } + set { SetValue("openididentitytoken", value); } + } + #endregion #region Other Properties diff --git a/MySQL.Data/src/Resources.Designer.cs b/MySQL.Data/src/Resources.Designer.cs index 991529e42..8a38ca951 100644 --- a/MySQL.Data/src/Resources.Designer.cs +++ b/MySQL.Data/src/Resources.Designer.cs @@ -925,7 +925,25 @@ internal static string OldPasswordsNotSupported { } /// - /// Looks up a localized string similar to The option '{0}' is not currently supported. + /// Looks up a localized string similar to The OpenID Connect Identity Token is empty. + /// + internal static string OpenIdIdentityTokenIsEmpty { + get { + return ResourceManager.GetString("OpenIdIdentityTokenIsEmpty", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The OpenID Connect Identity Token is invalid. + /// + internal static string OpenIdIdentityTokenTooBig { + get { + return ResourceManager.GetString("OpenIdIdentityTokenTooBig", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The option '{0}' is not currently supported.. /// internal static string OptionNotCurrentlySupported { get { diff --git a/MySQL.Data/src/Resources.resx b/MySQL.Data/src/Resources.resx index c5aa46d9a..9b6998c6e 100644 --- a/MySQL.Data/src/Resources.resx +++ b/MySQL.Data/src/Resources.resx @@ -690,4 +690,10 @@ The timeout of 15 seconds for user interaction with FIDO device has been exceeded + + The OpenID Connect Identity Token is empty + + + The OpenID Connect Identity Token is invalid + \ No newline at end of file diff --git a/MySQL.Data/tests/MySql.Data.Tests/AuthTests.cs b/MySQL.Data/tests/MySql.Data.Tests/AuthTests.cs index 3d5028a4a..ab6f94bca 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/AuthTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/AuthTests.cs @@ -34,6 +34,7 @@ using System; using System.Collections.Generic; using System.Data; +using System.Linq; using System.Reflection; using System.Text; @@ -1818,6 +1819,101 @@ private static void Conn_WebAuthnActionRequested() } #endregion + #region OpenID Connect client + /// + /// WL16491 - OpenID Connect authentication support + /// + + private static string IdentityToken = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJteXN1YmoiLCJpc3MiOiJodHRw" + + "czovL215aXNzdWVyLmNvbSIsImV4cCI6MjEzNTE5ODEwNX0.kXjtDjcSYhpNP0IgSbQjPuOsd-nBDVulQKgZAq4HkgMPCNINh-EIMbuqvYKkE5a" + + "B6zicm6PHNvxDrS63NjQH7Nh7s29eN50DSK33zQsvdYr8O5eUTL2SrNRqpWgMQ0xlU9Hr4HCw10YmIcwjskANHJxXSgyUCKveeRCR-L-DoNFZDy" + + "UYyd3pu7M1zO-12LjebktMklCQBfiCAcqSNDZDE2s6OkxuoF7VOtK91Wsw17xOZVQDjCZkUDtUrRZs8uxJfbjBonQ7LVQQhg227z8lrUeXewVhx" + + "NKPrf-YUrdMmEfMBjwD9v1AU5onKlkHuW0DtvZmt707Kyd-ve-HgQj1xX-W6BfEPo-28FCcDvLGlXZ8cyB1wPODogKhtc7bq3TPuTkDkegO7AG1" + + "NaYXcbSNEpQQ5zdfbzS_spV2zzJawPK1awNUeT_UA7t4swY4JcrOFkPkXUTqWT9QWvXuxCE9gZUAWIa3FHdeWjzLTZEKB8-ZhPYmyPphkzds9sm" + + "TJi4gawmNtb8WvEpXZUUXIZzIRcunXEdIayr18E9XfFCOCQo8JQOSxY3HQGgzqYk4S0AMeR0BiBIKe9VySsykdAuhLvL51AZDXvKQ9fQDu4lAtk" + + "cXrKCZwA_2RXjLzOM7dkySQu66t-GIIZXxqCdcWf1"; + + private static string OpenId_server_config = "JSON://{\"myissuer\":\"{\\\\\"kty\\\\\": \\\\\"RSA\\\\\",\\\\\"n\\\\\":" + + " \\\\\"zpnGGekMZHmWtpcsBmJdUODRApNHU7_bijsn4E0MWhthfkyK1LilQp5-aemc6Id5yL978CMfn10LXsjGchZKIGAgk52nW7kI3Zt973npwzB2M" + + "YJ4FFqsHQSAM9kvd3iUz2aQG-nVVl9Ia8Yimcssav8sEjOlEqZ1n_JLXavWwI9z-_lkTcZBgsM9jke_tWa1yLjYce009yBmf-sJMDrXZ-3TALrNUDzGt" + + "9mQwDxjE0UGnQIQE7vXJ2O5-k1qXMKPTew32zvRD7Bxcsxe71LRaerEPmgnricajk5LJVsbonavecrvHDCGDvOgzueZrr15kUhXZxZbXmtx6dUYqJ-0A" + + "qbZ0Km3elrYnDFysJR5pJsjmDnH2wzHDQ_gZeC_Up_4d78pzLyXHhiOmyDTLyogmeN7xYunvgzu-B4tepSC9XCSu-WZDmJASFaxRzOJhQBKLX2Ly0XmS" + + "LMXEP-vOupwvEi-SpBOVw2WzxT9dJrK-vI6cBGewB-zHrwsLFBvt1OZVNV5YGpQ1kqFfFoWrtkINFwJc39UnboDqalhvim9K-ITRe6xYk_Dlf9f-BA5b" + + "sry8n3GBBXEjkirM_QFb_DcbBXj1OJX_B0BZAK0bupYgOpxDG_su1a8N3CqOOWJguVzuydl7uW_uicDkCua3cVWd-n8QtXDaM6qZLRTB7q0_ek\\\\\"" + + ",\\\\\"e\\\\\": \\\\\"AQAB\\\\\",\\\\\"alg\\\\\": \\\\\"RS256\\\\\",\\\\\"use\\\\\": \\\\\"sig\\\\\",\\\\\"name" + + "\\\\\": \\\\\"https://myissuer.com\\\\\"}\"}"; + + [Test] + [Ignore("This test requires a server version 9.1.0 or higher configured to use OpenID Connect authentication")] + public void OpenIdConnectClient() + { + Assume.That(Version >= new Version("9.1.0"), "This test is for MySQL 9.1.0 or higher"); + Assume.That(Check_Plugin_Enabled("authentication_openid_connect"), "authentication_openid_connect plugin must be enabled on the server to run this test"); + + ExecuteSQL("SET GLOBAL authentication_openid_connect_configuration = '" + OpenId_server_config + "'", true); + + ExecuteSQL("CREATE USER IF NOT EXISTS 'openid-testuser'@'%' IDENTIFIED WITH 'authentication_openid_connect' AS '{\"identity_provider\" : \"myissuer\", \"user\" : \"mysubj\"}'", true); + + var connStringBuilder1 = new MySqlConnectionStringBuilder() + { + UserID = "openid-testuser", + Server = Settings.Server, + Port = Settings.Port, + OpenIdIdentityToken = IdentityToken + }; + using (MySqlConnection conn = new MySqlConnection(connStringBuilder1.ConnectionString)) + { + conn.Open(); + Assert.That(conn.connectionState, Is.EqualTo(ConnectionState.Open)); + } + + var connStringBuilder2 = new MySqlConnectionStringBuilder() + { + UserID = "openid-testuser", + Server = Settings.Server, + Port = Settings.Port, + OpenIdIdentityToken = IdentityToken, + DefaultAuthenticationPlugin = "authentication_openid_connect_client" + }; + using (MySqlConnection conn = new MySqlConnection(connStringBuilder2.ConnectionString)) + { + conn.Open(); + Assert.That(conn.connectionState, Is.EqualTo(ConnectionState.Open)); + } + + var connStringBuilder3 = new MySqlConnectionStringBuilder() + { + UserID = "openid-testuser", + Server = Settings.Server, + Port = Settings.Port, + OpenIdIdentityToken = "", + DefaultAuthenticationPlugin = "authentication_openid_connect_client" + }; + using (MySqlConnection conn = new MySqlConnection(connStringBuilder3.ConnectionString)) + { + Assert.Throws(() => conn.Open()); + } + + char[] reversedIdentityToken = IdentityToken.ToCharArray(); + Array.Reverse(reversedIdentityToken); + + var connStringBuilder4 = new MySqlConnectionStringBuilder() + { + UserID = "openid-testuser", + Server = Settings.Server, + Port = Settings.Port, + OpenIdIdentityToken = new string(reversedIdentityToken), + DefaultAuthenticationPlugin = "authentication_openid_connect_client" + }; + using (MySqlConnection conn = new MySqlConnection(connStringBuilder4.ConnectionString)) + { + Assert.Throws(() => conn.Open()); + } + + ExecuteSQL("DROP USER IF EXISTS 'openid-testuser'@'%'", true); + } + #endregion + [Test, Description("Test User Authentication Fails with classic protocol")] public void AuthPlainAndMySql41() { From cfc92c1ef1736a554322d73adb1b544edb866e6a Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Wed, 4 Sep 2024 17:57:20 -0600 Subject: [PATCH 069/125] Updated LIUMS Change-Id: I2ae26128b16cd1bd85cd11216c02b0548c26c13d --- LICENSE | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/LICENSE b/LICENSE index b6c7a6e7e..f0067f828 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ Licensing Information User Manual -MySQL Connector/NET 9.0.0 Community +MySQL Connector/NET 9.1.0 Community __________________________________________________________________ Introduction @@ -8,18 +8,18 @@ Introduction This License Information User Manual contains Oracle's product license and other licensing information, including licensing information for third-party software which may be included in this distribution of - MySQL Connector/NET 9.0.0 Community. + MySQL Connector/NET 9.1.0 Community. - Last updated: May 2024 + Last updated: August 2024 Licensing Information - This release of MySQL Connector/NET 9.0.0 Community is brought to you + This release of MySQL Connector/NET 9.1.0 Community is brought to you by the MySQL team at Oracle. This software is released under version 2 of the GNU General Public License (GPLv2), as set forth below, with the following additional permissions: - This distribution of MySQL Connector/NET 9.0.0 Community is designed to + This distribution of MySQL Connector/NET 9.1.0 Community is designed to work with certain software (including but not limited to OpenSSL) that is licensed under separate terms, as designated in a particular file or component or in the license documentation. Without limiting your rights From a9cf9f81021e81bcd8022fba7a7f1448dba464e5 Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Sat, 7 Sep 2024 20:10:54 -0600 Subject: [PATCH 070/125] Updated EF Core references Change-Id: Ib1f144b7e651ade361bd4eb7f575eb656c2d7ea0 --- EFCore/src/MySql.EntityFrameworkCore.csproj | 8 ++++---- .../MySql.EntityFrameworkCore.Basic.Tests.csproj | 6 +++--- .../MySql.EntityFrameworkCore.Design.Tests.csproj | 4 ++-- .../MySql.EntityFrameworkCore.Migrations.Tests.csproj | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/EFCore/src/MySql.EntityFrameworkCore.csproj b/EFCore/src/MySql.EntityFrameworkCore.csproj index 51c6d3741..40ea8927b 100644 --- a/EFCore/src/MySql.EntityFrameworkCore.csproj +++ b/EFCore/src/MySql.EntityFrameworkCore.csproj @@ -35,13 +35,13 @@ - - + + - - + + diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/MySql.EntityFrameworkCore.Basic.Tests.csproj b/EFCore/tests/MySql.EFCore.Basic.Tests/MySql.EntityFrameworkCore.Basic.Tests.csproj index 00582a122..3a15f0496 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/MySql.EntityFrameworkCore.Basic.Tests.csproj +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/MySql.EntityFrameworkCore.Basic.Tests.csproj @@ -18,11 +18,11 @@ - + - + @@ -30,7 +30,7 @@ - + diff --git a/EFCore/tests/MySql.EFCore.Design.Tests/MySql.EntityFrameworkCore.Design.Tests.csproj b/EFCore/tests/MySql.EFCore.Design.Tests/MySql.EntityFrameworkCore.Design.Tests.csproj index f047fc92a..83fe6a293 100644 --- a/EFCore/tests/MySql.EFCore.Design.Tests/MySql.EntityFrameworkCore.Design.Tests.csproj +++ b/EFCore/tests/MySql.EFCore.Design.Tests/MySql.EntityFrameworkCore.Design.Tests.csproj @@ -28,13 +28,13 @@ - + - + diff --git a/EFCore/tests/MySql.EFCore.Migrations.Tests/MySql.EntityFrameworkCore.Migrations.Tests.csproj b/EFCore/tests/MySql.EFCore.Migrations.Tests/MySql.EntityFrameworkCore.Migrations.Tests.csproj index 429a0cc63..9d357b0b8 100644 --- a/EFCore/tests/MySql.EFCore.Migrations.Tests/MySql.EntityFrameworkCore.Migrations.Tests.csproj +++ b/EFCore/tests/MySql.EFCore.Migrations.Tests/MySql.EntityFrameworkCore.Migrations.Tests.csproj @@ -18,7 +18,7 @@ - + From 40c64c612d3fa406990872ad161ac01cbf97b36b Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Sun, 8 Sep 2024 16:07:51 -0600 Subject: [PATCH 071/125] Updated documentation. Change-Id: Ie60211c4cb31ca7168d189b951ac002c777af49c --- Documentation/index.md | 4 ++-- README.md | 2 ++ Release Notes.txt | 12 ++++++------ 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/Documentation/index.md b/Documentation/index.md index ffb271d5f..8c681525e 100644 --- a/Documentation/index.md +++ b/Documentation/index.md @@ -1,6 +1,6 @@ ## MySQL Connector/NET and X DevAPI -MySQL Connector/NET 9.0 supports X Protocol, which enables you to use X DevAPI with the .NET language of choice to develop applications that communicate with a MySQL server functioning as a document store, relational database, or both. +MySQL Connector/NET 9.1 supports X Protocol, which enables you to use X DevAPI with the .NET language of choice to develop applications that communicate with a MySQL server functioning as a document store, relational database, or both. To get started, review the following main classes: @@ -16,7 +16,7 @@ For an introduction to X DevAPI concepts, see the [X DevAPI User Guide](https:// ## MySQL Connector/NET -MySQL Connector/NET 9.0 also supports the development of .NET, .NET Core and .NET Framework applications that require secure, high-performance data connectivity with MySQL through the classic protocol. It supports ADO.NET, Entity Framework and various web providers. +MySQL Connector/NET 9.1 also supports the development of .NET, .NET Core and .NET Framework applications that require secure, high-performance data connectivity with MySQL through the classic protocol. It supports ADO.NET, Entity Framework and various web providers. To get started, review the following main classes: diff --git a/README.md b/README.md index 0a25e8138..f2eab22b9 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,8 @@ From MySQL Connector/NET 8.4, the driver adds support for TLS1.3 and removes sup From MySQL Connector/NET 9.0, the driver removes support for .NET 7 and EF Core 7. +From MySQL Connector/NET 9.1, the driver adds support for .NET 9 and EF Core 9 preview versions. + For detailed information please visit the official [MySQL Connector/NET documentation.](https://dev.mysql.com/doc/connector-net/en/) ## Licensing diff --git a/Release Notes.txt b/Release Notes.txt index b6cf83c91..8ca04ebb3 100644 --- a/Release Notes.txt +++ b/Release Notes.txt @@ -1,10 +1,10 @@ -Connector/NET 9.0 Release Notes +Connector/NET 9.1 Release Notes ------------------------------------ -Welcome to the release notes for Connector/NET 9.0 +Welcome to the release notes for Connector/NET 9.1 -What's new in 9.0 +What's new in 9.1 -------------------- -Connector/NET now uses NUnit 4.1 in the testsuite. -Connector/NET updated 3rd party dependencies. -Connector/NET removes support for .NET 7 and EF Core 7. \ No newline at end of file +Connector/NET adds support for .NET 9 and EF Core 9 preview versions. +Connector/NET adds support for OpenID Connect authentication. +Connector/NET now uses constraint model in testsuite. \ No newline at end of file From 9b45247075ff882133a5b6f2153d0ace25f96ff7 Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Sun, 8 Sep 2024 15:39:32 -0600 Subject: [PATCH 072/125] Bug#35937318 [8.0.33 Removes Important Locks] Change-Id: I080cc163c5bd1bc587631ee121dac57c664b8553 --- CHANGES | 1 + .../MySQLAuthenticationPlugin.cs | 2 +- MySQL.Data/src/CharSetMap.cs | 48 ++++--- MySQL.Data/src/MySql.Data.csproj | 2 +- MySQL.Data/src/MySqlPool.cs | 132 +++++++++++++----- MySQL.Data/src/MySqlPoolManager.cs | 6 +- MySQL.Data/src/NativeDriver.cs | 4 +- .../src/Replication/ReplicationManager.cs | 79 ++++++----- .../src/X/XDevAPI/Common/BaseStatement.cs | 2 +- MySQL.Data/src/common/Ssl.cs | 39 ++++-- 10 files changed, 205 insertions(+), 110 deletions(-) diff --git a/CHANGES b/CHANGES index fd4dba44e..c52e4d610 100644 --- a/CHANGES +++ b/CHANGES @@ -5,6 +5,7 @@ - Added OpenTelemetry.Api NuGet package reference (WL16453). - Fixed Code coverage (WL16309). - Added support for OpenID Connect client authentication (WL16491). +- Fixed bug 8.0.33 Removes Important Locks (MySQL Bug #111759, Oracle Bug #35937318). Thanks to Stuart Lang for the contribution. 9.0.0 diff --git a/MySQL.Data/src/Authentication/MySQLAuthenticationPlugin.cs b/MySQL.Data/src/Authentication/MySQLAuthenticationPlugin.cs index f33b42bd5..9af2e8f3b 100644 --- a/MySQL.Data/src/Authentication/MySQLAuthenticationPlugin.cs +++ b/MySQL.Data/src/Authentication/MySQLAuthenticationPlugin.cs @@ -171,7 +171,7 @@ internal async Task AuthenticateAsync(bool reset, bool execAsync) await packet.WriteStringAsync(PluginName, execAsync).ConfigureAwait(false); await _driver.SetConnectAttrsAsync(execAsync).ConfigureAwait(false); - await _driver.SendPacketAsync(packet, execAsync); + await _driver.SendPacketAsync(packet, execAsync).ConfigureAwait(false); // Read server response. packet = await ReadPacketAsync(execAsync).ConfigureAwait(false); diff --git a/MySQL.Data/src/CharSetMap.cs b/MySQL.Data/src/CharSetMap.cs index 8775e9e3a..52bbc3e02 100644 --- a/MySQL.Data/src/CharSetMap.cs +++ b/MySQL.Data/src/CharSetMap.cs @@ -42,13 +42,12 @@ internal class CharSetMap private static Dictionary _defaultCollations; private static Dictionary _maxLengths; private static Dictionary _mapping; - private static readonly object LockObject; + private static SemaphoreSlim semaphoreSlim = new SemaphoreSlim(1, 1); // we use a static constructor here since we only want to init // the mapping once static CharSetMap() { - LockObject = new Object(); InitializeMapping(); } @@ -57,8 +56,8 @@ public static CharacterSet GetCharacterSet(string charSetName) if (charSetName == null) throw new ArgumentNullException("CharSetName is null"); CharacterSet cs = null; - if (_mapping.ContainsKey(charSetName)) - cs = _mapping[charSetName]; + if (_mapping.TryGetValue(charSetName, out var charset)) + cs = charset; if (cs == null) throw new NotSupportedException("Character set '" + charSetName + "' is not supported by .Net Framework."); @@ -181,27 +180,42 @@ internal static async Task InitCollectionsAsync(MySqlConnection connection, bool internal static async Task GetDefaultCollationAsync(string charset, MySqlConnection connection, bool execAsync, CancellationToken cancellationToken = default) { - SemaphoreSlim semaphoreSlim = new SemaphoreSlim(1); - semaphoreSlim.Wait(); + if (execAsync) + await semaphoreSlim.WaitAsync(cancellationToken); + else + semaphoreSlim.Wait(cancellationToken); - if (_defaultCollations == null) - await InitCollectionsAsync(connection, execAsync, cancellationToken).ConfigureAwait(false); + try + { + if (_defaultCollations == null) + await InitCollectionsAsync(connection, execAsync, cancellationToken).ConfigureAwait(false); + } + finally + { + semaphoreSlim.Release(); + } - semaphoreSlim.Release(); - return !_defaultCollations.ContainsKey(charset) ? null : _defaultCollations[charset]; + return !_defaultCollations.TryGetValue(charset, out string collation) ? null : collation; } internal static async Task GetMaxLengthAsync(string charset, MySqlConnection connection, bool execAsync, CancellationToken cancellationToken = default) { - SemaphoreSlim semaphoreSlim = new SemaphoreSlim(1); - semaphoreSlim.Wait(); - - if (_maxLengths == null) - await InitCollectionsAsync(connection, execAsync, cancellationToken).ConfigureAwait(false); + if (execAsync) + await semaphoreSlim.WaitAsync(cancellationToken); + else + semaphoreSlim.Wait(cancellationToken); - semaphoreSlim.Release(); + try + { + if (_maxLengths == null) + await InitCollectionsAsync(connection, execAsync, cancellationToken).ConfigureAwait(false); + } + finally + { + semaphoreSlim.Release(); + } - return !_maxLengths.ContainsKey(charset) ? 1 : _maxLengths[charset]; + return !_maxLengths.TryGetValue(charset, out int maxLength) ? 1 : maxLength; } } diff --git a/MySQL.Data/src/MySql.Data.csproj b/MySQL.Data/src/MySql.Data.csproj index 9f57e77ce..ebc805e3b 100644 --- a/MySQL.Data/src/MySql.Data.csproj +++ b/MySQL.Data/src/MySql.Data.csproj @@ -42,7 +42,7 @@ net462;net48;$(TargetFrameworks) - + diff --git a/MySQL.Data/src/MySqlPool.cs b/MySQL.Data/src/MySqlPool.cs index 98f28750f..e8efab95f 100644 --- a/MySQL.Data/src/MySqlPool.cs +++ b/MySQL.Data/src/MySqlPool.cs @@ -49,7 +49,9 @@ internal sealed class MySqlPool private readonly AutoResetEvent _autoEvent; private int _available; // Object used to lock the list of host obtained from DNS SRV lookup. - private readonly object _dnsSrvLock = new object(); + private readonly SemaphoreSlim inUsePoolSemaphore = new SemaphoreSlim(1, 1); + private readonly SemaphoreSlim idlePoolSemaphore = new SemaphoreSlim(1, 1); + private readonly SemaphoreSlim dnsSrvSemaphore = new SemaphoreSlim(1, 1); private void EnqueueIdle(Driver driver) { @@ -121,7 +123,12 @@ private async Task GetPooledConnectionAsync(bool execAsync, Cancellation // if we don't have an idle connection but we have room for a new // one, then create it here. - lock ((_idlePool as ICollection).SyncRoot) + if (execAsync) + await idlePoolSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false); + else + idlePoolSemaphore.Wait(cancellationToken); + + try { if (HasIdleConnections) { @@ -129,6 +136,10 @@ private async Task GetPooledConnectionAsync(bool execAsync, Cancellation _idlePool.RemoveLast(); } } + finally + { + idlePoolSemaphore.Release(); + } // Obey the connection timeout if (driver != null) @@ -164,10 +175,20 @@ private async Task GetPooledConnectionAsync(bool execAsync, Cancellation driver = await CreateNewPooledConnectionAsync(execAsync, cancellationToken).ConfigureAwait(false); Debug.Assert(driver != null); - lock ((_inUsePool as ICollection).SyncRoot) + if (execAsync) + await inUsePoolSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false); + else + inUsePoolSemaphore.Wait(cancellationToken); + + try { _inUsePool.Add(driver); } + finally + { + inUsePoolSemaphore.Release(); + } + return driver; } @@ -185,11 +206,20 @@ private async Task CreateNewPooledConnectionAsync(bool execAsync, Cancel public async Task ReleaseConnectionAsync(Driver driver, bool execAsync) { - lock ((_inUsePool as ICollection).SyncRoot) + if (execAsync) + await inUsePoolSemaphore.WaitAsync().ConfigureAwait(false); + else + inUsePoolSemaphore.Wait(); + + try { if (_inUsePool.Contains(driver)) _inUsePool.Remove(driver); } + finally + { + inUsePoolSemaphore.Release(); + } if (driver.ConnectionLifetimeExpired() || BeingCleared) { @@ -198,32 +228,48 @@ public async Task ReleaseConnectionAsync(Driver driver, bool execAsync) } else { - lock ((_idlePool as ICollection).SyncRoot) + if (execAsync) + await idlePoolSemaphore.WaitAsync().ConfigureAwait(false); + else + idlePoolSemaphore.Wait(); + + try { EnqueueIdle(driver); } + finally + { + idlePoolSemaphore.Release(); + } } - SemaphoreSlim semaphoreSlim = new SemaphoreSlim(1); - semaphoreSlim.Wait(); + if (execAsync) + await dnsSrvSemaphore.WaitAsync().ConfigureAwait(false); + else + dnsSrvSemaphore.Wait(); - if (driver.Settings.DnsSrv) + try { - var dnsSrvRecords = DnsSrv.GetDnsSrvRecords(DnsSrv.ServiceName); - FailoverManager.SetHostList(dnsSrvRecords.ConvertAll(r => new FailoverServer(r.Target, r.Port, null)), - FailoverMethod.Sequential); - - foreach (var idleConnection in _idlePool) + if (driver.Settings.DnsSrv) { - string idleServer = idleConnection.Settings.Server; - if (!FailoverManager.FailoverGroup.Hosts.Exists(h => h.Host == idleServer) && !idleConnection.IsInActiveUse) + var dnsSrvRecords = DnsSrv.GetDnsSrvRecords(DnsSrv.ServiceName); + FailoverManager.SetHostList(dnsSrvRecords.ConvertAll(r => new FailoverServer(r.Target, r.Port, null)), + FailoverMethod.Sequential); + + foreach (var idleConnection in _idlePool) { - await idleConnection.CloseAsync(execAsync).ConfigureAwait(false); + string idleServer = idleConnection.Settings.Server; + if (!FailoverManager.FailoverGroup.Hosts.Exists(h => h.Host == idleServer) && !idleConnection.IsInActiveUse) + { + await idleConnection.CloseAsync(execAsync).ConfigureAwait(false); + } } } } - - semaphoreSlim.Release(); + finally + { + dnsSrvSemaphore.Release(); + } Interlocked.Increment(ref _available); _autoEvent.Set(); @@ -238,7 +284,8 @@ public async Task ReleaseConnectionAsync(Driver driver, bool execAsync) /// public void RemoveConnection(Driver driver) { - lock ((_inUsePool as ICollection).SyncRoot) + inUsePoolSemaphore.Wait(); + try { if (_inUsePool.Contains(driver)) { @@ -247,6 +294,10 @@ public void RemoveConnection(Driver driver) _autoEvent.Set(); } } + finally + { + inUsePoolSemaphore.Release(); + } // if we are being cleared and we are out of connections then have // the manager destroy us. @@ -301,21 +352,28 @@ public async Task GetConnectionAsync(bool execAsync, CancellationToken c /// internal async Task ClearAsync(bool execAsync) { - SemaphoreSlim semaphoreSlim = new SemaphoreSlim(1); - semaphoreSlim.Wait(); + if (execAsync) + await idlePoolSemaphore.WaitAsync().ConfigureAwait(false); + else + idlePoolSemaphore.Wait(); - // first, mark ourselves as being cleared - BeingCleared = true; + try + { + // first, mark ourselves as being cleared + BeingCleared = true; - // then we remove all connections sitting in the idle pool - while (_idlePool.Count > 0) + // then we remove all connections sitting in the idle pool + while (_idlePool.Count > 0) + { + Driver d = _idlePool.Last.Value; + await d.CloseAsync(execAsync).ConfigureAwait(false); + _idlePool.RemoveLast(); + } + } + finally { - Driver d = _idlePool.Last.Value; - await d.CloseAsync(execAsync).ConfigureAwait(false); - _idlePool.RemoveLast(); + idlePoolSemaphore.Release(); } - - semaphoreSlim.Release(); // there is nothing left to do here. Now we just wait for all // in use connections to be returned to the pool. When they are // they will be closed. When the last one is closed, the pool will @@ -338,23 +396,29 @@ internal List RemoveOldIdleConnections() var connectionsToClose = new List(); DateTime now = DateTime.Now; - lock ((_idlePool as ICollection).SyncRoot) + idlePoolSemaphore.Wait(); + + try { while (_idlePool.Count > _minSize) { - var iddleConnection = _idlePool.First.Value; - DateTime expirationTime = iddleConnection.IdleSince.Add( + var idleConnection = _idlePool.First.Value; + DateTime expirationTime = idleConnection.IdleSince.Add( new TimeSpan(0, 0, MySqlPoolManager.maxConnectionIdleTime)); if (expirationTime.CompareTo(now) < 0) { - connectionsToClose.Add(iddleConnection); + connectionsToClose.Add(idleConnection); _idlePool.RemoveFirst(); } else break; } } + finally + { + idlePoolSemaphore.Release(); + } return connectionsToClose; } } diff --git a/MySQL.Data/src/MySqlPoolManager.cs b/MySQL.Data/src/MySqlPoolManager.cs index cc16792d0..3e624340a 100644 --- a/MySQL.Data/src/MySqlPoolManager.cs +++ b/MySQL.Data/src/MySqlPoolManager.cs @@ -49,7 +49,7 @@ internal class MySqlPoolManager private static readonly Dictionary Pools = new Dictionary(); private static readonly List ClearingPools = new List(); internal const int DEMOTED_TIMEOUT = 120000; - private static SemaphoreSlim waitHandle = new(1); + private static SemaphoreSlim waitHandle = new(1, 1); #region Properties /// @@ -158,10 +158,6 @@ public static async Task GetPoolAsync(MySqlConnectionStringBuilder se return pool; } - catch (Exception ex) - { - throw; - } finally { waitHandle.Release(); diff --git a/MySQL.Data/src/NativeDriver.cs b/MySQL.Data/src/NativeDriver.cs index b6d6f860b..0afe4712e 100644 --- a/MySQL.Data/src/NativeDriver.cs +++ b/MySQL.Data/src/NativeDriver.cs @@ -117,7 +117,7 @@ private async Task HandleExceptionAsync(MySqlException ex, bool execAsync) internal async Task SendPacketAsync(MySqlPacket p, bool execAsync) { - await stream.SendPacketAsync(p, execAsync); + await stream.SendPacketAsync(p, execAsync).ConfigureAwait(false); } internal async Task SendEmptyPacketAsync(bool execAsync) @@ -421,7 +421,7 @@ public async Task AuthenticateAsync(string authMethod, bool reset, bool execAsyn authPlugin = await MySqlAuthenticationPlugin.GetPluginAsync(authMethod, this, encryptionSeed, execAsync).ConfigureAwait(false); } - await authPlugin.AuthenticateAsync(reset, execAsync); + await authPlugin.AuthenticateAsync(reset, execAsync).ConfigureAwait(false); } #endregion diff --git a/MySQL.Data/src/Replication/ReplicationManager.cs b/MySQL.Data/src/Replication/ReplicationManager.cs index 5c0fb0dd1..48d0e3186 100644 --- a/MySQL.Data/src/Replication/ReplicationManager.cs +++ b/MySQL.Data/src/Replication/ReplicationManager.cs @@ -41,8 +41,7 @@ namespace MySql.Data.MySqlClient.Replication internal static class ReplicationManager { private static List groups = new List(); - private static Object thisLock = new Object(); - //private static Dictionary selectors = new Dictionary(); + private static SemaphoreSlim semaphoreSlim = new SemaphoreSlim(1, 1); static ReplicationManager() { @@ -147,55 +146,61 @@ internal static async Task GetNewConnectionAsync(string groupName, bool source, { do { - SemaphoreSlim semaphoreSlim = new SemaphoreSlim(1); - semaphoreSlim.Wait(); + if (execAsync) + await semaphoreSlim.WaitAsync(cancellationToken).ConfigureAwait(false); + else + semaphoreSlim.Wait(cancellationToken); - if (!IsReplicationGroup(groupName)) return; + try + { + if (!IsReplicationGroup(groupName)) return; - ReplicationServerGroup group = GetGroup(groupName); - ReplicationServer server = group.GetServer(source, connection.Settings); + ReplicationServerGroup group = GetGroup(groupName); + ReplicationServer server = group.GetServer(source, connection.Settings); - if (server == null) - throw new MySqlException(Resources.Replication_NoAvailableServer); + if (server == null) + throw new MySqlException(Resources.Replication_NoAvailableServer); - try - { - bool isNewServer = false; - if (connection.driver == null || !connection.driver.IsOpen) + try { - isNewServer = true; - } - else - { - MySqlConnectionStringBuilder msb = new MySqlConnectionStringBuilder(server.ConnectionString); - if (!msb.Equals(connection.driver.Settings)) + bool isNewServer = false; + if (connection.driver == null || !connection.driver.IsOpen) { isNewServer = true; } + else + { + MySqlConnectionStringBuilder msb = new MySqlConnectionStringBuilder(server.ConnectionString); + if (!msb.Equals(connection.driver.Settings)) + { + isNewServer = true; + } + } + if (isNewServer) + { + Driver driver = await Driver.CreateAsync(new MySqlConnectionStringBuilder(server.ConnectionString), execAsync, cancellationToken).ConfigureAwait(false); + connection.driver = driver; + } + return; } - if (isNewServer) + catch (MySqlException ex) { - Driver driver = await Driver.CreateAsync(new MySqlConnectionStringBuilder(server.ConnectionString), execAsync, cancellationToken).ConfigureAwait(false); - connection.driver = driver; + connection.driver = null; + server.IsAvailable = false; + MySqlTrace.LogError(ex.Number, ex.ToString()); + if (ex.Number == 1042) + { + // retry to open a failed connection and update its status + group.HandleFailover(server, ex); + } + else + throw; } - return; } - catch (MySqlException ex) + finally { - connection.driver = null; - server.IsAvailable = false; - MySqlTrace.LogError(ex.Number, ex.ToString()); - if (ex.Number == 1042) - { - // retry to open a failed connection and update its status - group.HandleFailover(server, ex); - } - else - throw; + semaphoreSlim.Release(); } - - semaphoreSlim.Release(); - } while (true); } } diff --git a/MySQL.Data/src/X/XDevAPI/Common/BaseStatement.cs b/MySQL.Data/src/X/XDevAPI/Common/BaseStatement.cs index a335a59fa..8ead4959a 100644 --- a/MySQL.Data/src/X/XDevAPI/Common/BaseStatement.cs +++ b/MySQL.Data/src/X/XDevAPI/Common/BaseStatement.cs @@ -89,7 +89,7 @@ public async Task ExecuteAsync() }, CancellationToken.None, TaskCreationOptions.None, - Session._scheduler); + Session._scheduler).ConfigureAwait(false); } /// diff --git a/MySQL.Data/src/common/Ssl.cs b/MySQL.Data/src/common/Ssl.cs index 7e16343e5..00a782459 100644 --- a/MySQL.Data/src/common/Ssl.cs +++ b/MySQL.Data/src/common/Ssl.cs @@ -69,7 +69,7 @@ internal class Ssl private static SslProtocols[] tlsProtocols = new SslProtocols[] { SslProtocols.Tls12}; private static Dictionary tlsConnectionRef = new Dictionary(); private static Dictionary tlsRetry = new Dictionary(); - private static Object thisLock = new Object(); + private static SemaphoreSlim semaphoreSlim = new SemaphoreSlim(1, 1); #endregion @@ -232,24 +232,39 @@ public async Task> StartSSLAsync(Stream baseStream, E tlsProtocols = listProtocols.ToArray(); } - if (tlsConnectionRef.ContainsKey(connectionId)) - { - tlsProtocol = tlsConnectionRef[connectionId]; - } + if (execAsync) + await semaphoreSlim.WaitAsync(cancellationToken).ConfigureAwait(false); else + semaphoreSlim.Wait(cancellationToken); + + + try { - if (!tlsRetry.ContainsKey(connectionId)) + if (tlsConnectionRef.TryGetValue(connectionId, out var protocol)) { - lock (tlsRetry) - { - tlsRetry[connectionId] = 0; - } + tlsProtocol = protocol; } - for (int i = tlsRetry[connectionId]; i < tlsProtocols.Length; i++) + else { - tlsProtocol |= tlsProtocols[i]; + if (!tlsRetry.ContainsKey(connectionId)) + { + lock (tlsRetry) + { + tlsRetry[connectionId] = 0; + } + } + for (int i = tlsRetry[connectionId]; i < tlsProtocols.Length; i++) + { + tlsProtocol |= tlsProtocols[i]; + } } } + finally + { + semaphoreSlim.Release(); + } + + try { tlsProtocol = (tlsProtocol == SslProtocols.None) ? SslProtocols.Tls12 : tlsProtocol; From 9b59c9ae5579ba825bda3873fa511534d4e46a80 Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Sun, 15 Sep 2024 15:38:35 -0600 Subject: [PATCH 073/125] Updated CHANGES file with contributors names. Change-Id: Ie0b8a5e811ba46d90f3e14f900a3eb2e7eaded1e --- CHANGES | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGES b/CHANGES index c52e4d610..0368f1289 100644 --- a/CHANGES +++ b/CHANGES @@ -14,7 +14,7 @@ - Remove MySqlX.Data.Performance.Console.Tests project (WL16387). - Updated third party dependencies (WL16291). - Remove .NET 7 and EF Core 7 (WL16386). -- Fixed bug SQL Keyword "RETURNING" not handled properly when updating data (Oracle Bug #36116171). +- Fixed bug SQL Keyword "RETURNING" not handled properly when updating data (Oracle Bug #36116171). Thanks to Wang Shiyao for the contribution. - Fixed bug IIS Website is crashing after upgrading MySQL.Data package to 8.3.0 (Oracle Bug #36483069). - Updated Wix Toolset to 4.0.5 (Oracle Bug #36627858). - Fixed bug disabling of mysql_native_password in server causes errors in testsuite (Oracle Bug #36529814). @@ -32,7 +32,7 @@ - Fixed bug Minpoolsize different than 0 causes connector to hang after first connection (Oracle Bug #36319784). - Fixed bug Tests failing due to removal of 'HAVE_SSL' variable from server (Oracle Bug #36374702). - Added support for Vector data type (WL16175). -- Fixed bug Fix deadlock in mysql poolmanager attempt (Oracle Bug #36380976) +- Fixed bug Fix deadlock in mysql poolmanager attempt (Oracle Bug #36380976). Thanks to Marek Matys for the contribution. - Fixed bug Test failing due to removal of 'default_authentication_plugin' server variable (Oracle Bug #36405198). From 90935198e384a3ad9a19e10451e93ecffa4e3552 Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Sun, 15 Sep 2024 15:54:08 -0600 Subject: [PATCH 074/125] Bug#37032982 [EntityFramework SQL generation of TPT pseudo discriminator column incorrect] Change-Id: Ifbe3a1cd3ff5192741c3d5afe3395a954d85f548 --- CHANGES | 1 + .../src/Statements/SelectStatement.cs | 2 +- .../CodeFirstTests.cs | 37 +++++++++++++ .../Vehicle.cs | 52 +++++++++++++++++++ 4 files changed, 91 insertions(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index 0368f1289..63a3e53ac 100644 --- a/CHANGES +++ b/CHANGES @@ -6,6 +6,7 @@ - Fixed Code coverage (WL16309). - Added support for OpenID Connect client authentication (WL16491). - Fixed bug 8.0.33 Removes Important Locks (MySQL Bug #111759, Oracle Bug #35937318). Thanks to Stuart Lang for the contribution. +- Fixed bug EntityFramework SQL generation of TPT pseudo discriminator column incorrect (MySQL Bug #116028, Oracle Bug #37032982). Thanks to Kristoffer Sjöberg for the contribution. 9.0.0 diff --git a/EntityFramework/src/Statements/SelectStatement.cs b/EntityFramework/src/Statements/SelectStatement.cs index 96d8ab4ea..74e7b2fef 100644 --- a/EntityFramework/src/Statements/SelectStatement.cs +++ b/EntityFramework/src/Statements/SelectStatement.cs @@ -232,7 +232,7 @@ List GetDefaultColumnsForFragment(InputFragment input) if (generator.GetTopOp() == OpType.Join) { newColumn.ColumnAlias = cf.ColumnAlias; - newColumn.PushInput(cf.ColumnName); + newColumn.PushInput(cf.ActualColumnName); if (cf.TableName != null) newColumn.PushInput(cf.TableName); } diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/CodeFirstTests.cs b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/CodeFirstTests.cs index 1b247cd6c..a393ea79d 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/CodeFirstTests.cs +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/CodeFirstTests.cs @@ -191,6 +191,43 @@ public void CallStoredProcedure() } } + /// + /// Tests for fix of http://bugs.mysql.com/bug.php?id=116028 + /// Incorrect discriminator generated column values when it's used code-first, inheritance and in a join statement + /// + [Test] + public void Bug116028_Test1() + { + List vehicles; + using (VehicleDbContext4 context = new VehicleDbContext4()) + { + context.Database.Delete(); + context.Database.Initialize(true); + var manuf = context.Manufacturers.Add(new Manufacturer4 { Name = "ACME" }); + context.Vehicles.Add(new Car4 { Id = 1, Name = "Mustang", Year = 2012, CarProperty = "Car", Manufacturer = manuf }); + context.Vehicles.Add(new Bike4 { Id = 101, Name = "Mountain", Year = 2011, BikeProperty = "Bike", Manufacturer = manuf }); + context.SaveChanges(); + + vehicles = context.Manufacturers.SelectMany(v => v.Vehicles).ToList(); + + int records = -1; + using (MySqlConnection conn = new MySqlConnection(context.Database.Connection.ConnectionString)) + { + conn.Open(); + MySqlCommand cmd = new MySqlCommand("SELECT COUNT(*) FROM Vehicles", conn); + records = Convert.ToInt32(cmd.ExecuteScalar()); + } + + Assert.That(records, Is.EqualTo(context.Vehicles.Count())); + } + using (VehicleDbContext4 context = new VehicleDbContext4()) + { + var vehiclesfromdb = context.Manufacturers.SelectMany(v => v.Vehicles).ToList(); + Assert.That(vehiclesfromdb.OfType().Single().CarProperty, Is.EqualTo(vehicles.OfType().Single().CarProperty)); + Assert.That(vehiclesfromdb.OfType().Single().BikeProperty, Is.EqualTo(vehicles.OfType().Single().BikeProperty)); + } + } + /// /// Tests for fix of http://bugs.mysql.com/bug.php?id=63920 /// Maxlength error when it's used code-first and inheritance (discriminator generated column) diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/Vehicle.cs b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/Vehicle.cs index a5b8989cb..4dd1630e7 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/Vehicle.cs +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/Vehicle.cs @@ -118,6 +118,58 @@ public VehicleDbContext3() : base(CodeFirstFixture.GetEFConnectionString Vehicles { get; set; } + } + public class Vehicle4 + { + public int Id { get; set; } + public int Year { get; set; } + + [MaxLength(1024)] + public string Name { get; set; } + public Guid ManufacturerId { get; set; } + [ForeignKey(nameof(ManufacturerId))] + public virtual Manufacturer4 Manufacturer { get; set; } + } + [DbConfigurationType(typeof(MySqlEFConfiguration))] + public class VehicleDbContext4 : DbContext + { + public DbSet Vehicles { get; set; } + public DbSet Manufacturers { get; set; } + + public VehicleDbContext4() : base(CodeFirstFixture.GetEFConnectionString()) + { + Database.SetInitializer(new VehicleDBInitializer4()); + + } + protected override void OnModelCreating(DbModelBuilder modelBuilder) + { + modelBuilder.Entity().ToTable("Vehicles"); + modelBuilder.Entity().ToTable("Cars"); + modelBuilder.Entity().ToTable("Bikes"); + } + } + public class VehicleDBInitializer4 : DropCreateDatabaseReallyAlways + { + } + public class Accessory { [Key] From 5baf667e7b81943884d483cd1e892c78adc778ab Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Sun, 15 Sep 2024 12:45:13 -0600 Subject: [PATCH 075/125] Bug#35937293 [Connector does crashes when retrieving data from the database] Change-Id: I6eef797885460b48b0ded464809863e3e3dff35a --- CHANGES | 1 + .../src/Authentication/MySqlPemReader.cs | 2 +- MySQL.Data/src/MySqlPacket.cs | 12 +- MySQL.Data/src/PacketBitConverter.cs | 115 ++++++++++++++++++ MySQL.Data/src/Types/MySqlDouble.cs | 4 +- MySQL.Data/src/Types/MySqlGeometry.cs | 8 +- MySQL.Data/src/Types/MySqlSingle.cs | 4 +- 7 files changed, 131 insertions(+), 15 deletions(-) create mode 100644 MySQL.Data/src/PacketBitConverter.cs diff --git a/CHANGES b/CHANGES index 63a3e53ac..04486f4ca 100644 --- a/CHANGES +++ b/CHANGES @@ -7,6 +7,7 @@ - Added support for OpenID Connect client authentication (WL16491). - Fixed bug 8.0.33 Removes Important Locks (MySQL Bug #111759, Oracle Bug #35937318). Thanks to Stuart Lang for the contribution. - Fixed bug EntityFramework SQL generation of TPT pseudo discriminator column incorrect (MySQL Bug #116028, Oracle Bug #37032982). Thanks to Kristoffer Sjöberg for the contribution. +- Fixed bug Connector does crashes when retrieving data from the database (MySQL Bug #111630, Oracle Bug #35937293). Thanks to Sidraya Jayagond for the contribution. 9.0.0 diff --git a/MySQL.Data/src/Authentication/MySqlPemReader.cs b/MySQL.Data/src/Authentication/MySqlPemReader.cs index 95a0bc7a4..22a09ff68 100644 --- a/MySQL.Data/src/Authentication/MySqlPemReader.cs +++ b/MySQL.Data/src/Authentication/MySqlPemReader.cs @@ -113,7 +113,7 @@ static RSACryptoServiceProvider DecodeX509Key(byte[] key) } else return null; - int modulusSize = BitConverter.ToInt32(new byte[] { lowByte, highByte, 0x00, 0x00 }, 0); + int modulusSize = highByte << 8 | lowByte; byte firstByte = reader.ReadByte(); reader.BaseStream.Seek(-1, SeekOrigin.Current); diff --git a/MySQL.Data/src/MySqlPacket.cs b/MySQL.Data/src/MySqlPacket.cs index 70d4f7c45..513a04be7 100644 --- a/MySQL.Data/src/MySqlPacket.cs +++ b/MySQL.Data/src/MySqlPacket.cs @@ -222,9 +222,9 @@ public long ReadLong(int numbytes) switch (numbytes) { - case 2: return BitConverter.ToUInt16(bits, pos); - case 4: return BitConverter.ToUInt32(bits, pos); - case 8: return BitConverter.ToInt64(bits, pos); + case 2: return PacketBitConverter.ToUInt16(bits, pos); + case 4: return PacketBitConverter.ToUInt32(bits, pos); + case 8: return PacketBitConverter.ToInt64(bits, pos); } throw new NotSupportedException("Only byte lengths of 2, 4, or 8 are supported"); } @@ -240,9 +240,9 @@ public ulong ReadULong(int numbytes) switch (numbytes) { - case 2: return BitConverter.ToUInt16(bits, pos); - case 4: return BitConverter.ToUInt32(bits, pos); - case 8: return BitConverter.ToUInt64(bits, pos); + case 2: return PacketBitConverter.ToUInt16(bits, pos); + case 4: return PacketBitConverter.ToUInt32(bits, pos); + case 8: return PacketBitConverter.ToUInt64(bits, pos); } throw new NotSupportedException("Only byte lengths of 2, 4, or 8 are supported"); } diff --git a/MySQL.Data/src/PacketBitConverter.cs b/MySQL.Data/src/PacketBitConverter.cs new file mode 100644 index 000000000..dc185ba94 --- /dev/null +++ b/MySQL.Data/src/PacketBitConverter.cs @@ -0,0 +1,115 @@ +// Copyright © 2004, 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +namespace MySql.Data +{ + public static class PacketBitConverter + { + // Due to the lack of support of the C# BinaryPrimitives class + // on net452 and net48 this class is necessary for back compatibility. + // All instances of PacketBitConverter can be replaced with corresponding + // BinaryPrimitives methods for future versions. + + // The server sends MySql Packets in LittleEndian encoding + // The methods provided by the BitConverter class check for the + // endian-ness of the client system and do conversions accordingly + // which lead to incorrect conversions on BigEndian systems + + // Following function are analogues with BinaryPrimitives.Write*LittleEndian + public static byte[] GetBytes(int value) + { + return new byte[] { + (byte)value, (byte)(value >> 8), (byte)(value >> 16), (byte)(value >> 24) + }; + } + + public static byte[] GetBytes(long value) + { + return new byte[] { + (byte)value, (byte)(value >> 8), (byte)(value >> 16), (byte)(value >> 24), + (byte)(value >> 32), (byte)(value >> 40), (byte)(value >> 48), (byte)(value >> 56) + }; + } + + unsafe public static byte[] GetBytes(float value) + { + int val = *(int*)&value; + return GetBytes(val); + } + + unsafe public static byte[] GetBytes(double value) + { + long val = *(long*)&value; + return GetBytes(val); + } + + // Following functions are analogous to BinaryPrimitives.Read*LittleEndian + unsafe public static float ToSingle(byte[] byteArray, int startIndex) + { + int val = ToInt32(byteArray, startIndex); + return *(float*)&val; + } + + unsafe public static double ToDouble(byte[] byteArray, int startIndex) + { + long val = ToInt64(byteArray, startIndex); + return *(double*)&val; + } + + public static ushort ToUInt16(byte[] byteArray, int startIndex) + { + return (ushort)(byteArray[startIndex++] | byteArray[startIndex] << 8); + } + + public static uint ToUInt32(byte[] byteArray, int startIndex) + { + return (uint)(byteArray[startIndex++] | byteArray[startIndex++] << 8 + | byteArray[startIndex++] << 16 | byteArray[startIndex] << 24); + } + + public static ulong ToUInt64(byte[] byteArray, int startIndex) + { + return (ulong)ToUInt32(byteArray, startIndex) + ((ulong)ToUInt32(byteArray, startIndex + 4) << 32); + } + + public static short ToInt16(byte[] byteArray, int startIndex) + { + return (short)ToUInt16(byteArray, startIndex); + } + + public static int ToInt32(byte[] byteArray, int startIndex) + { + return (int)ToUInt32(byteArray, startIndex); + } + + public static long ToInt64(byte[] byteArray, int startIndex) + { + return (long)ToUInt64(byteArray, startIndex); + } + } +} diff --git a/MySQL.Data/src/Types/MySqlDouble.cs b/MySQL.Data/src/Types/MySqlDouble.cs index 150dda727..9b342b6ba 100644 --- a/MySQL.Data/src/Types/MySqlDouble.cs +++ b/MySQL.Data/src/Types/MySqlDouble.cs @@ -66,7 +66,7 @@ async Task IMySqlValue.WriteValueAsync(MySqlPacket packet, bool binary, object v { double v = val as double? ?? Convert.ToDouble(val); if (binary) - await packet.WriteAsync(BitConverter.GetBytes(v), execAsync).ConfigureAwait(false); + await packet.WriteAsync(PacketBitConverter.GetBytes(v), execAsync).ConfigureAwait(false); else await packet.WriteStringNoNullAsync(v.ToString("R", CultureInfo.InvariantCulture), execAsync).ConfigureAwait(false); } @@ -80,7 +80,7 @@ async Task IMySqlValue.ReadValueAsync(MySqlPacket packet, long leng { byte[] b = new byte[8]; await packet.ReadAsync(b, 0, 8, execAsync).ConfigureAwait(false); - return new MySqlDouble(BitConverter.ToDouble(b, 0)); + return new MySqlDouble(PacketBitConverter.ToDouble(b, 0)); } string s = await packet.ReadStringAsync(length, execAsync).ConfigureAwait(false); diff --git a/MySQL.Data/src/Types/MySqlGeometry.cs b/MySQL.Data/src/Types/MySqlGeometry.cs index 9b71626d9..963ee3837 100644 --- a/MySQL.Data/src/Types/MySqlGeometry.cs +++ b/MySQL.Data/src/Types/MySqlGeometry.cs @@ -109,7 +109,7 @@ internal MySqlGeometry(MySqlDbType type, Double xValue, Double yValue, int srid) this._srid = srid; this.Value = new byte[GEOMETRY_LENGTH]; - byte[] sridBinary = BitConverter.GetBytes(srid); + byte[] sridBinary = PacketBitConverter.GetBytes(srid); for (int i = 0; i < sridBinary.Length; i++) Value[i] = sridBinary[i]; @@ -148,9 +148,9 @@ public MySqlGeometry(MySqlDbType type, byte[] val) var yIndex = val.Length == GEOMETRY_LENGTH ? 17 : 13; Value = buffValue; - _xValue = val.Length >= xIndex + 8 ? BitConverter.ToDouble(val, xIndex) : 0; - _yValue = val.Length >= yIndex + 8 ? BitConverter.ToDouble(val, yIndex) : 0; - this._srid = val.Length == GEOMETRY_LENGTH ? BitConverter.ToInt32(val, 0) : 0; + _xValue = val.Length >= xIndex + 8 ? PacketBitConverter.ToDouble(val, xIndex) : 0; + _yValue = val.Length >= yIndex + 8 ? PacketBitConverter.ToDouble(val, yIndex) : 0; + this._srid = val.Length == GEOMETRY_LENGTH ? PacketBitConverter.ToInt32(val, 0) : 0; this.IsNull = false; this._type = type; } diff --git a/MySQL.Data/src/Types/MySqlSingle.cs b/MySQL.Data/src/Types/MySqlSingle.cs index ff04eedee..9dc777912 100644 --- a/MySQL.Data/src/Types/MySqlSingle.cs +++ b/MySQL.Data/src/Types/MySqlSingle.cs @@ -68,7 +68,7 @@ async Task IMySqlValue.WriteValueAsync(MySqlPacket packet, bool binary, object v { Single v = val as Single? ?? Convert.ToSingle(val); if (binary) - await packet.WriteAsync(BitConverter.GetBytes(v), execAsync).ConfigureAwait(false); + await packet.WriteAsync(PacketBitConverter.GetBytes(v), execAsync).ConfigureAwait(false); else await packet.WriteStringNoNullAsync(v.ToString("R", CultureInfo.InvariantCulture), execAsync).ConfigureAwait(false); } @@ -82,7 +82,7 @@ async Task IMySqlValue.ReadValueAsync(MySqlPacket packet, long leng { byte[] b = new byte[4]; await packet.ReadAsync(b, 0, 4, execAsync).ConfigureAwait(false); - return new MySqlSingle(BitConverter.ToSingle(b, 0)); + return new MySqlSingle(PacketBitConverter.ToSingle(b, 0)); } return new MySqlSingle(Single.Parse(await packet.ReadStringAsync(length, execAsync).ConfigureAwait(false), From e13fbe0580adba77a408f1f38ef68c68d1eadbfa Mon Sep 17 00:00:00 2001 From: Manohar Prajapati Date: Wed, 18 Sep 2024 08:50:47 +0200 Subject: [PATCH 076/125] Updated the LICENSE files --- LICENSE | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/LICENSE b/LICENSE index f0067f828..27bc95437 100644 --- a/LICENSE +++ b/LICENSE @@ -10,7 +10,7 @@ Introduction third-party software which may be included in this distribution of MySQL Connector/NET 9.1.0 Community. - Last updated: August 2024 + Last updated: September 2024 Licensing Information @@ -1017,4 +1017,4 @@ Written Offer for Source Code that included the binary that is the subject of your request, or b. in the case of code licensed under the GPL v3 for as long as Oracle - offers spare parts or customer support for that product model. \ No newline at end of file + offers spare parts or customer support for that product model. From 504668ee77fd43956aa1993e634ba70529d89f4f Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Wed, 18 Sep 2024 09:25:21 -0600 Subject: [PATCH 077/125] Bug#37032982 [EntityFramework SQL generation of TPT pseudo discriminator column incorrect] - Complement Change-Id: I07c704270fee44001d3748ecbf8f58f414c6c743 --- .../MySql.EntityFramework.CodeFirst.Tests/CodeFirstFixture.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/CodeFirstFixture.cs b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/CodeFirstFixture.cs index 49ea6b4e8..e5af704a4 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/CodeFirstFixture.cs +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/CodeFirstFixture.cs @@ -126,6 +126,7 @@ public CodeFirstFixture() DeleteContext(); DeleteContext(); DeleteContext(); + DeleteContext(); DeleteContext(); DeleteContext(); DeleteContext(); From 67e39c50ad8fa3bff218b322caf994a86e791791 Mon Sep 17 00:00:00 2001 From: Filipe Silva Date: Fri, 20 Sep 2024 16:37:34 +0100 Subject: [PATCH 078/125] Updated CONTRIBUTING and README files, and added SECURITY file. Change-Id: Id913dd7371638f18d599305c5eb2ec8e5ef70cb8 --- CONTRIBUTING.md | 69 ++++++++++++++++++++++++++++++------------------- README | 16 ++++++------ README.md | 41 +++++++++++++++++------------ SECURITY.md | 29 +++++++++++++++++++++ 4 files changed, 105 insertions(+), 50 deletions(-) create mode 100644 SECURITY.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 280a049de..e5612e3bd 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,48 +1,65 @@ # Contributing Guidelines -We love getting feedback from our users. Bugs and code contributions are great forms of feedback and we thank you for any bugs you report or code you contribute. +We greatly appreciate feedback from our users, including bug reports and code contributions. Your input helps us improve, and we thank you for any issues you report or code you contribute. ## Reporting Issues -Before reporting a new bug, please [check first](https://bugs.mysql.com/search.php) to see if a similar bug exists. +Before submitting a new bug report, please [check here](https://bugs.mysql.com/search.php) to see if the issue has already been reported. -Bug reports should be as complete as possible. Please try and include the following: -* Complete steps to reproduce the issue. -* Any information about platform and environment that could be specific to the bug. -* Specific version of the product you are using. -* Specific version of the server being used. -* Sample code to help reproduce the issue if possible. +When reporting a bug, ensure your report is as detailed as possible. Please include the following: + +* Clear, reproducible steps to demonstrate the issue. +* Relevant platform and environment information. +* The specific version of the product in use. +* The version of the MySQL Server in use. +* Sample code that can help reproduce the issue, if applicable. ## Contributing Code -Contributing to this project is easy. You just need to follow these steps: +We welcome your code contributions. Before submitting code via a GitHub pull request or by filing a bug on [bugs.mysql.com](https://bugs.mysql.com), you will need to sign the Oracle Contributor Agreement (OCA). Instructions for signing the OCA are available on the [OCA Page](https://oca.opensource.oracle.com). + +**Only pull requests from contributors who have signed the OCA can be accepted.** + +### Submitting a Contribution -* Make sure you have a user account at [bugs.mysql.com](bugs.mysql.com). You'll need to reference this user account when you submit your OCA (Oracle Contributor Agreement). -* Sign the Oracle OCA. You can find instructions for doing that at the [OCA Page](https://oca.opensource.oracle.com/). -* Develop your pull request. - * Make sure you are aware of the requirements for the project (e.g. don't require .NET Core 3.0 if we are curently supporting .NET Core 2.2 and lower). -* Validate your pull request by including tests that sufficiently cover the functionality. -* Verify that the entire test suite passes with your code applied. -* Submit your pull request. While you can submit the pull request with [Github](https://github.com/mysql/mysql-connector-net/pulls), you can also submit it directly with [bugs.mysql.com](https://bugs.mysql.com). +1. Ensure you have a user account at [bugs.mysql.com](https://bugs.mysql.com). You'll need to reference this account when submitting your OCA. +2. Sign the Oracle Contributor Agreement. Instructions are provided on the [OCA Page](https://oca.opensource.oracle.com). +3. Validate your contribution by including tests that adequately cover the functionality you're adding. +4. Ensure the entire test suite passes with your changes applied. +5. Submit your pull request through [GitHub](https://github.com/mysql/mysql-connector-net/pulls/) or upload it to a bug record on [bugs.mysql.com](https://bugs.mysql.com) using the _Contributions_ tab. -Thanks again for being willing to contribute to MySQL. We truly believe in the principles of open source and appreciate any and all contributions to our projects. +### Developing Your Pull Request + +1. Create your pull request, following the [project's requirements](https://dev.mysql.com/doc/connector-net/en/connector-net-installation.html). +2. Include sufficient tests to validate the new functionality. +3. Confirm that the entire test suite passes with your changes applied. +4. Submit the pull request via [GitHub](https://github.com/mysql/mysql-connector-net/pulls/) or directly via [bugs.mysql.com](https://bugs.mysql.com). + +We deeply value contributions to MySQL and thank you for supporting open-source development. ## Setting Up a Development Environment -You can use your preferred .NET IDE to view, edit, and compile the MySQL Connector/NET source code. The configuration setup can be adapted from [Installing from Source](https://dev.mysql.com/doc/connector-net/en/connector-net-installation-source.html). +You can use your preferred .NET IDE to view, edit, and compile the MySQL Connector/NET source code. For project configuration, please refer to the instructions in [Installing from Source](https://dev.mysql.com/doc/connector-net/en/connector-net-installation-source.html). ## Running Tests -Any code you contribute needs to pass our test suite, each of our projects have his own (e.g. MySql.Data.Tests). You must run the entire suite just to make sure that no other functionality have been affected by the change. You can run the test suite by using the IDE of your preference or by CLI with the help of the "dotnet" tool. - +Any code you contribute must pass our test suite. Each project has its own suite (e.g., *MySql.Data.Tests*). Be sure to run the entire test suite to ensure that no other functionality is affected by your changes. You can run the tests using your preferred IDE or via the CLI with the "dotnet" tool. + ## Getting Help -If you need help or just want to get in touch with us, please use the following resources: +If you need assistance or would like to reach out to the community, please use the following resources: -* [MySQL Connector/NET and C# forum](https://forums.mysql.com/list.php?38) -* [MySQL NuGet](https://www.nuget.org/profiles/MySQL) -* [MySQL Bugs database](https://bugs.mysql.com/) +* [MySQL Connector/NET Developer Guide](https://dev.mysql.com/doc/connector-net/en/) +* [MySQL Connector/NET API](https://dev.mysql.com/doc/dev/connector-net/latest/) +* [MySQL NuGet](https://www.nuget.org/profiles/MySQL/) +* [MySQL Connector/NET and C#, Mono, .Net Forum](https://forums.mysql.com/list.php?38) +* [`#connectors` channel on MySQL Community Slack](https://mysqlcommunity.slack.com/messages/connectors/) ([Sign-up](https://lefred.be/mysql-community-on-slack/) required if you do not have an Oracle account.) +* [@MySQL on X](https://x.com/MySQL/). +* [MySQL Blog](https://blogs.oracle.com/mysql/). +* [MySQL Connectors Blog archive](https://dev.mysql.com/blog-archive/?cat=Connectors%20%2F%20Languages). +* [MySQL Newsletter](https://www.mysql.com/news-and-events/newsletter/). +* [MySQL Bugs Tracking System](https://bugs.mysql.com). -We hope to hear from you soon. Enjoy your coding! +We look forward to hearing from you and encourage you to get involved. Happy coding! -[![Twitter Follow](https://img.shields.io/twitter/follow/MySQL.svg?label=Follow%20%40MySQL&style=social)](https://twitter.com/intent/follow?screen_name=MySQL) \ No newline at end of file +[![X (formerly Twitter) Follow](https://img.shields.io/twitter/follow/MySQL?style=social)](https://x.com/intent/follow?screen_name=MySQL) diff --git a/README b/README index 6e6fc8689..7fa428330 100644 --- a/README +++ b/README @@ -1,16 +1,16 @@ Copyright © 2004, 2024, Oracle and/or its affiliates. -This is a release of MySQL Connector/NET, Oracle's fully managed ADO .NET Driver for MySQL. +This is a release of MySQL Connector/NET, Oracle's fully managed ADO .NET Driver +for MySQL. -License information can be found in the LICENSE file. - -This distribution may include materials developed by third parties. -For license and attribution notices for these materials, please refer to the LICENSE file. +License information can be found in the LICENSE file. This distribution may +include materials developed by third parties. For license and attribution +notices for these materials, please refer to the LICENSE file. For more information on MySQL Connector/NET, visit - http://dev.mysql.com/doc/connector-net/en/ +http://dev.mysql.com/doc/connector-net/en/. -For additional downloads and the source of MySQL Connector/NET, visit - http://dev.mysql.com/downloads +For additional downloads and the source of MySQL Connector/NET, visit +http://dev.mysql.com/downloads/. MySQL Connector/NET is brought to you by the MySQL team at Oracle. diff --git a/README.md b/README.md index f2eab22b9..ff4709d51 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # MySQL Connector/NET -[![Languages](https://img.shields.io/github/languages/top/mysql/mysql-connector-net)](https://github.com/mysql/mysql-connector-net) [![License: GNU General Public License (GPLv2)](https://img.shields.io/badge/license-GPLv2_with_FOSS_exception-c30014.svg?style=flat)](LICENSE) [![NuGet](https://img.shields.io/nuget/v/MySql.Data)](https://www.nuget.org/profiles/MySQL) +[![GitHub top language](https://img.shields.io/github/languages/top/mysql/mysql-connector-net)](https://github.com/mysql/mysql-connector-net) [![License: GPLv2 with FOSS exception](https://img.shields.io/badge/license-GPLv2_with_FOSS_exception-c30014)](LICENSE) [![NuGet Version](https://img.shields.io/nuget/v/MySQL.Data)](https://www.nuget.org/profiles/MySQL/) MySQL provides connectivity for client applications developed in .NET compatible programming languages with Connector/NET. @@ -8,30 +8,34 @@ MySQL Connector/NET is a library compatible with .NET Framework and .NET Core, f From MySQL Connector/NET 8.0, the driver also contains an implementation of [MySQL X DevAPI](https://dev.mysql.com/doc/x-devapi-userguide/en/), an Application Programming Interface for working with [MySQL as a Document Store](https://dev.mysql.com/doc/refman/8.0/en/document-store.html) through CRUD-based, NoSQL operations. -From MySQL Connector/NET 8.1, the driver contains an implementation of [OpenTelemetry](https://dev.mysql.com/doc/connector-net/en/connector-net-programming-telemetry.html) which requires the use of the [MySql.Data.OpenTelemetry](https://www.nuget.org/profiles/MySQL/) Nuget package to enable the generation of telemetry data. +From MySQL Connector/NET 8.1, the driver contains an implementation of [OpenTelemetry](https://dev.mysql.com/doc/connector-net/en/connector-net-programming-telemetry.html) which requires the use of the [MySql.Data.OpenTelemetry](https://www.nuget.org/packages/MySql.Data.OpenTelemetry/) Nuget package to enable the generation of telemetry data. -From MySQL Connector/NET 8.2, the driver adds support for [WebAuthn authentication](https://dev.mysql.com/doc/dev/connector-net/latest/api/data_api/MySql.Data.MySqlClient.WebAuthnActionCallback.html), the driver also adds support for [.NET 8](https://learn.microsoft.com/en-us/dotnet/core/whats-new/dotnet-8). +From MySQL Connector/NET 8.2, the driver adds support for [WebAuthn authentication](https://dev.mysql.com/doc/dev/connector-net/latest/api/data_api/MySql.Data.MySqlClient.WebAuthnActionCallback.html), the driver also adds support for [.NET 8](https://learn.microsoft.com/en-us/dotnet/core/whats-new/dotnet-8/). -From MySQL Connector/NET 8.3, the driver also adds support for [.NET 8](https://learn.microsoft.com/en-us/dotnet/core/whats-new/dotnet-8) and [EFCore 8](https://learn.microsoft.com/en-us/ef/core/what-is-new/ef-core-8.0/whatsnew) GA versions. +From MySQL Connector/NET 8.3, the driver also adds support for [.NET 8](https://learn.microsoft.com/en-us/dotnet/core/whats-new/dotnet-8/) and [EFCore 8](https://learn.microsoft.com/en-us/ef/core/what-is-new/ef-core-8.0/whatsnew/) GA versions. From MySQL Connector/NET 8.4, the driver adds support for TLS1.3 and removes support for FIDO authentication plugin. From MySQL Connector/NET 9.0, the driver removes support for .NET 7 and EF Core 7. -From MySQL Connector/NET 9.1, the driver adds support for .NET 9 and EF Core 9 preview versions. +From MySQL Connector/NET 9.1, the driver adds support for [.NET 9](https://learn.microsoft.com/en-us/dotnet/core/whats-new/dotnet-9/overview/) and [EF Core 9](https://learn.microsoft.com/en-us/ef/core/what-is-new/ef-core-9.0/whatsnew/) preview versions. -For detailed information please visit the official [MySQL Connector/NET documentation.](https://dev.mysql.com/doc/connector-net/en/) +For detailed information please visit the official [MySQL Connector/NET documentation](https://dev.mysql.com/doc/connector-net/en/). ## Licensing Please refer to files [README](README) and [LICENSE](LICENSE), available in this repository, and [Legal Notices in documentation](https://dev.mysql.com/doc/connector-net/en/preface.html) for further details. +## Security + +Oracle values the independent security research community and believes that responsible disclosure of security vulnerabilities helps us ensure the security and privacy of all our users. Please refer to the [security guidelines](SECURITY.md) document for additional information. + ## Download & Install MySQL Connector/NET can be installed from precompiled libraries by using MySQL installer or download the libraries itself, both can be found at [Connector/NET download page](https://dev.mysql.com/downloads/connector/net/). Also, you can get the latest stable release from the [official Nuget.org feed](https://www.nuget.org/profiles/MySQL). * By using MySQL Installer, you just need to follow the wizard in order to obtain the precompiled library and then add it to your project. -* If you decided to download the precompiled libraries, decompress the folder and then add the library needed to your project as reference. +* If you decided to download the precompiled libraries, decompress the folder and then add the library needed to your project as a reference. * If you go for NuGet, you could use the NuGet Package Manager inside Visual Studio or use the NuGet Command Line Interface (CLI). ### Building from sources @@ -44,16 +48,21 @@ This repository contains the MySQL Connector/NET source code as per latest relea ## Contributing -There are a few ways to contribute to the Connector/NET code. Please refer to the [contributing guidelines](CONTRIBUTING.md) for additional information. +We greatly appreciate feedback from our users, including bug reports and code contributions. Your input helps us improve, and we thank you for any issues you report or code you contribute. Please refer to the [contributing guidelines](CONTRIBUTING.md) document for additional information. ### Additional Resources -* [MySQL](http://www.mysql.com/) * [MySQL Connector/NET Developer Guide](https://dev.mysql.com/doc/connector-net/en/) -* [MySQL Connector/NET API](https://dev.mysql.com/doc/dev/connector-net/8.0/) -* [MySQL Connector/NET Discussion Forum](https://forums.mysql.com/list.php?38) -* [MySQL Public Bug Tracker](https://bugs.mysql.com) -* [`#connectors` channel in MySQL Community Slack](https://mysqlcommunity.slack.com/messages/connectors) ([Sign-up](https://lefred.be/mysql-community-on-slack/) required when not using an Oracle account) -* For more information about this and other MySQL products, please visit [MySQL Contact & Questions](http://www.mysql.com/about/contact/). - -[![Twitter Follow](https://img.shields.io/twitter/follow/MySQL.svg?label=Follow%20%40MySQL&style=social)](https://twitter.com/intent/follow?screen_name=MySQL) \ No newline at end of file +* [MySQL Connector/NET API](https://dev.mysql.com/doc/dev/connector-net/latest/) +* [MySQL NuGet](https://www.nuget.org/profiles/MySQL/) +* [MySQL Connector/NET and C#, Mono, .Net Forum](https://forums.mysql.com/list.php?38) +* [`#connectors` channel on MySQL Community Slack](https://mysqlcommunity.slack.com/messages/connectors/) ([Sign-up](https://lefred.be/mysql-community-on-slack/) required if you do not have an Oracle account.) +* [@MySQL on X](https://x.com/MySQL/). +* [MySQL Blog](https://blogs.oracle.com/mysql/). +* [MySQL Connectors Blog archive](https://dev.mysql.com/blog-archive/?cat=Connectors%20%2F%20Languages). +* [MySQL Newsletter](https://www.mysql.com/news-and-events/newsletter/). +* [MySQL Bugs Tracking System](https://bugs.mysql.com). + +For more information about this and other MySQL products, please visit [MySQL Contact & Questions](https://www.mysql.com/about/contact/). + +[![X (formerly Twitter) Follow](https://img.shields.io/twitter/follow/MySQL.svg?label=Follow%20%40MySQL&style=social)](https://x.com/intent/follow?screen_name=MySQL) diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 000000000..d25bea8e0 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,29 @@ +# Reporting security vulnerabilities + +Oracle values the independent security research community and believes that +responsible disclosure of security vulnerabilities helps us ensure the security +and privacy of all our users. + +Please do NOT raise a GitHub Issue to report a security vulnerability. If you +believe you have found a security vulnerability, please submit a report to +secalert_us@oracle.com preferably with a proof of concept. Please review some +additional information [on how to report security vulnerabilities to Oracle](https://www.oracle.com/corporate/security-practices/assurance/vulnerability/reporting.html). +We encourage people who contact Oracle Security to use email encryption using +our [encryption key](https://www.oracle.com/security-alerts/encryptionkey.html). + +We ask that you do not use other channels or contact the project maintainers +directly. + +# Security updates, alerts and bulletins + +Security updates will be released on a regular cadence. Many of our projects +will typically release security fixes in conjunction with the Oracle Critical +Patch Update program. Additional information, including past advisories, is +available on our [security alerts page](https://www.oracle.com/security-alerts/). + +# Security-related information + +We will provide security related information such as a threat model, +considerations for secure use, or any known security issues in our +documentation. Please note that labs and sample code are intended to demonstrate +a concept and may not be sufficiently hardened for production use. From ac184e8a3626790551d381732b08680922882dd9 Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Fri, 20 Sep 2024 11:08:10 -0600 Subject: [PATCH 079/125] Added SECURITY, CONTRIBUTING and README files to packages. Change-Id: Id02a5d2a77e32782fe23c14966d72edcf78f8dc1 --- EFCore/src/MySql.EntityFrameworkCore.csproj | 4 ++-- .../src/MySql.Data.EntityFramework.csproj | 7 ++++++- .../MySql.EntityFramework.Basic.Tests.csproj | 2 +- .../MySql.EntityFramework.CodeFirst.Tests.csproj | 2 +- ...MySql.EntityFramework.Migrations.Tests.csproj | 2 +- .../src/MySQL.Data.OpenTelemetry.csproj | 7 ++++++- MySQL.Data/src/MySql.Data.csproj | 16 ++++++---------- .../MySql.Data.Tests/MySql.Data.Tests.csproj | 2 +- .../MySqlX.Data.Tests/MySqlX.Data.Tests.csproj | 2 +- MySql.Web/src/MySql.Web.csproj | 7 ++++++- MySql.Web/tests/MySql.Web.Tests.csproj | 2 +- 11 files changed, 32 insertions(+), 21 deletions(-) diff --git a/EFCore/src/MySql.EntityFrameworkCore.csproj b/EFCore/src/MySql.EntityFrameworkCore.csproj index 40ea8927b..f4c824aa4 100644 --- a/EFCore/src/MySql.EntityFrameworkCore.csproj +++ b/EFCore/src/MySql.EntityFrameworkCore.csproj @@ -7,7 +7,7 @@ MySql;.NET Connector;MySql Entity Framework Core;netcore;.Net Core;MySql Conector/Net Entity Framework Core;coreclr;C/NET;C/Net Core http://www.mysql.com/common/logos/logo-mysql-170x115.png https://github.com/mysql/mysql-connector-net - GPL-2.0-only + GPL-2.0-only WITH Universal-FOSS-exception-1.0 true 10.0 net6.0;net8.0; @@ -29,7 +29,7 @@ false false - + net9.0;$(TargetFrameworks) diff --git a/EntityFramework/src/MySql.Data.EntityFramework.csproj b/EntityFramework/src/MySql.Data.EntityFramework.csproj index 15f1caca9..148d3e97d 100644 --- a/EntityFramework/src/MySql.Data.EntityFramework.csproj +++ b/EntityFramework/src/MySql.Data.EntityFramework.csproj @@ -14,7 +14,7 @@ logo-mysql-170x115.png README.md https://dev.mysql.com/downloads/ - GPL-2.0-only + GPL-2.0-only WITH Universal-FOSS-exception-1.0 true false false @@ -31,6 +31,11 @@ + + + + + diff --git a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/MySql.EntityFramework.Basic.Tests.csproj b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/MySql.EntityFramework.Basic.Tests.csproj index a421205e8..e0fd3608c 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/MySql.EntityFramework.Basic.Tests.csproj +++ b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/MySql.EntityFramework.Basic.Tests.csproj @@ -12,7 +12,7 @@ MySql;.NET Connector;MySql Connector/NET http://www.mysql.com/common/logos/logo-mysql-170x115.png http://dev.mysql.com/downloads/ - GPL-2.0-only + GPL-2.0-only WITH Universal-FOSS-exception-1.0 true false false diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/MySql.EntityFramework.CodeFirst.Tests.csproj b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/MySql.EntityFramework.CodeFirst.Tests.csproj index edc58b2ce..8afd2a09b 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/MySql.EntityFramework.CodeFirst.Tests.csproj +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/MySql.EntityFramework.CodeFirst.Tests.csproj @@ -12,7 +12,7 @@ MySql;.NET Connector;MySql Connector/NET http://www.mysql.com/common/logos/logo-mysql-170x115.png http://dev.mysql.com/downloads/ - GPL-2.0-only + GPL-2.0-only WITH Universal-FOSS-exception-1.0 true false false diff --git a/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/MySql.EntityFramework.Migrations.Tests.csproj b/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/MySql.EntityFramework.Migrations.Tests.csproj index 213dd36a9..8d5a447e3 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/MySql.EntityFramework.Migrations.Tests.csproj +++ b/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/MySql.EntityFramework.Migrations.Tests.csproj @@ -12,7 +12,7 @@ MySql;.NET Connector;MySql Connector/NET http://www.mysql.com/common/logos/logo-mysql-170x115.png http://dev.mysql.com/downloads/ - GPL-2.0-only + GPL-2.0-only WITH Universal-FOSS-exception-1.0 true false false diff --git a/MySQL.Data.OpenTelemetry/src/MySQL.Data.OpenTelemetry.csproj b/MySQL.Data.OpenTelemetry/src/MySQL.Data.OpenTelemetry.csproj index d2d44f5c7..55fd53746 100644 --- a/MySQL.Data.OpenTelemetry/src/MySQL.Data.OpenTelemetry.csproj +++ b/MySQL.Data.OpenTelemetry/src/MySQL.Data.OpenTelemetry.csproj @@ -13,7 +13,7 @@ logo-mysql-170x115.png README.md https://dev.mysql.com/downloads/ - GPL-2.0-only + GPL-2.0-only WITH Universal-FOSS-exception-1.0 true True True @@ -39,6 +39,11 @@ + + + + + diff --git a/MySQL.Data/src/MySql.Data.csproj b/MySQL.Data/src/MySql.Data.csproj index ebc805e3b..0c93df32c 100644 --- a/MySQL.Data/src/MySql.Data.csproj +++ b/MySQL.Data/src/MySql.Data.csproj @@ -15,7 +15,7 @@ logo-mysql-170x115.png README.md https://dev.mysql.com/downloads/ - GPL-2.0-only + GPL-2.0-only WITH Universal-FOSS-exception-1.0 true false false @@ -50,6 +50,11 @@ + + + + + @@ -67,15 +72,6 @@ - - - true - - - true - - - diff --git a/MySQL.Data/tests/MySql.Data.Tests/MySql.Data.Tests.csproj b/MySQL.Data/tests/MySql.Data.Tests/MySql.Data.Tests.csproj index 03175dec2..58c63070c 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/MySql.Data.Tests.csproj +++ b/MySQL.Data/tests/MySql.Data.Tests/MySql.Data.Tests.csproj @@ -13,7 +13,7 @@ MySql;.NET Connector;MySql Connector/NET;netcore;.Net Core;MySql Conector/Net Core;coreclr;C/NET;C/Net Core http://www.mysql.com/common/logos/logo-mysql-170x115.png http://dev.mysql.com/downloads/ - GPL-2.0-only + GPL-2.0-only WITH Universal-FOSS-exception-1.0 true false false diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/MySqlX.Data.Tests.csproj b/MySQL.Data/tests/MySqlX.Data.Tests/MySqlX.Data.Tests.csproj index 5f3390b1e..7d67519c3 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/MySqlX.Data.Tests.csproj +++ b/MySQL.Data/tests/MySqlX.Data.Tests/MySqlX.Data.Tests.csproj @@ -13,7 +13,7 @@ MySql;.NET Connector;MySql Connector/NET;netcore;.Net Core;MySql Conector/Net Core;coreclr;C/NET;C/Net Core http://www.mysql.com/common/logos/logo-mysql-170x115.png http://dev.mysql.com/downloads/ - GPL-2.0-only + GPL-2.0-only WITH Universal-FOSS-exception-1.0 true false false diff --git a/MySql.Web/src/MySql.Web.csproj b/MySql.Web/src/MySql.Web.csproj index 602a6e64c..9172c452c 100644 --- a/MySql.Web/src/MySql.Web.csproj +++ b/MySql.Web/src/MySql.Web.csproj @@ -14,7 +14,7 @@ logo-mysql-170x115.png README.md https://dev.mysql.com/downloads/ - GPL-2.0-only + GPL-2.0-only WITH Universal-FOSS-exception-1.0 true false false @@ -36,6 +36,11 @@ + + + + + diff --git a/MySql.Web/tests/MySql.Web.Tests.csproj b/MySql.Web/tests/MySql.Web.Tests.csproj index 1733d05a7..8bf54e2b2 100644 --- a/MySql.Web/tests/MySql.Web.Tests.csproj +++ b/MySql.Web/tests/MySql.Web.Tests.csproj @@ -12,7 +12,7 @@ MySql;.NET Connector;MySql Connector/NET http://www.mysql.com/common/logos/logo-mysql-170x115.png http://dev.mysql.com/downloads/ - GPL-2.0-only + GPL-2.0-only WITH Universal-FOSS-exception-1.0 true false false From b16ffcfd8d1f5978c391e2b0abc1f11f8aad1420 Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Mon, 23 Sep 2024 18:21:39 -0600 Subject: [PATCH 080/125] Bump up version to 9.2.0 Change-Id: Ie357e24e759ba510248d51bea66167b3e9dccd3e --- CHANGES | 3 +++ .../templates/custom/partials/class.header.tmpl.partial | 2 +- EntityFramework/src/MySql.Data.EntityFramework.csproj | 2 +- .../MySql.EntityFramework.Basic.Tests.csproj | 2 +- .../MySql.EntityFramework.CodeFirst.Tests.csproj | 2 +- .../MySql.EntityFramework.Migrations.Tests.csproj | 2 +- .../src/MySQL.Data.OpenTelemetry.csproj | 2 +- MySQL.Data/src/MySql.Data.csproj | 2 +- MySQL.Data/src/Properties/VersionInfo.cs | 6 +++--- MySQL.Data/tests/MySql.Data.Tests/MySql.Data.Tests.csproj | 2 +- MySQL.Data/tests/MySqlX.Data.Tests/MySqlX.Data.Tests.csproj | 2 +- MySql.Web/src/MySql.Web.csproj | 2 +- MySql.Web/tests/MySql.Web.Tests.csproj | 2 +- 13 files changed, 17 insertions(+), 14 deletions(-) diff --git a/CHANGES b/CHANGES index 04486f4ca..19b152d3d 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,6 @@ +9.2.0 + + 9.1.0 - Updated test suite to use constraint-based assertions (WL16397). - Changed testsuite to use assummptions instead of Assert.Ignore (WL16402). diff --git a/Documentation/templates/custom/partials/class.header.tmpl.partial b/Documentation/templates/custom/partials/class.header.tmpl.partial index 2eff37671..2ee15b21b 100644 --- a/Documentation/templates/custom/partials/class.header.tmpl.partial +++ b/Documentation/templates/custom/partials/class.header.tmpl.partial @@ -25,7 +25,7 @@ {{/implements.0}}
{{__global.namespace}}: {{{namespace.specName.0.value}}}
{{__global.assembly}}: {{assemblies.0}}.dll
-
Version: 9.1.0
+
Version: 9.2.0
{{__global.syntax}}
{{syntax.content.0.value}}
diff --git a/EntityFramework/src/MySql.Data.EntityFramework.csproj b/EntityFramework/src/MySql.Data.EntityFramework.csproj index 148d3e97d..7852d3988 100644 --- a/EntityFramework/src/MySql.Data.EntityFramework.csproj +++ b/EntityFramework/src/MySql.Data.EntityFramework.csproj @@ -4,7 +4,7 @@ MySql.Data.EntityFramework Copyright © 2016, 2024, Oracle and/or its affiliates. en-US - 9.1.0 + 9.2.0 Oracle net462;net48; $(NoWarn);CS1591 diff --git a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/MySql.EntityFramework.Basic.Tests.csproj b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/MySql.EntityFramework.Basic.Tests.csproj index e0fd3608c..d9b06a899 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/MySql.EntityFramework.Basic.Tests.csproj +++ b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/MySql.EntityFramework.Basic.Tests.csproj @@ -4,7 +4,7 @@ MySql.Data.EntityFramework.CodeFirTests Copyright © 2016, 2024, Oracle and/or its affiliates. en-US - 9.1.0 + 9.2.0 Oracle net462;net48; MySql.EntityFramework.Basic.Tests diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/MySql.EntityFramework.CodeFirst.Tests.csproj b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/MySql.EntityFramework.CodeFirst.Tests.csproj index 8afd2a09b..8695f22ac 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/MySql.EntityFramework.CodeFirst.Tests.csproj +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/MySql.EntityFramework.CodeFirst.Tests.csproj @@ -4,7 +4,7 @@ MySql.Data.EntityFramework.CodeFirst.Tests Copyright © 2016, 2024, Oracle and/or its affiliates. en-US - 9.1.0 + 9.2.0 Oracle net462;net48; MySql.EntityFramework.CodeFirst.Tests diff --git a/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/MySql.EntityFramework.Migrations.Tests.csproj b/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/MySql.EntityFramework.Migrations.Tests.csproj index 8d5a447e3..bb23ccb6e 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/MySql.EntityFramework.Migrations.Tests.csproj +++ b/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/MySql.EntityFramework.Migrations.Tests.csproj @@ -4,7 +4,7 @@ MySql.Data.EntityFramework.Migrations.Tests Copyright © 2016, 2024, Oracle and/or its affiliates. en-US - 9.1.0 + 9.2.0 Oracle net462;net48; MySql.EntityFramework.Migrations.Tests diff --git a/MySQL.Data.OpenTelemetry/src/MySQL.Data.OpenTelemetry.csproj b/MySQL.Data.OpenTelemetry/src/MySQL.Data.OpenTelemetry.csproj index 55fd53746..4d65a1c10 100644 --- a/MySQL.Data.OpenTelemetry/src/MySQL.Data.OpenTelemetry.csproj +++ b/MySQL.Data.OpenTelemetry/src/MySQL.Data.OpenTelemetry.csproj @@ -4,7 +4,7 @@ MySql.Data.OpenTelemetry Copyright © 2023, 2024, Oracle and/or its affiliates. en-US - 9.1.0 + 9.2.0 Oracle netstandard2.0 MySql.Data.OpenTelemetry diff --git a/MySQL.Data/src/MySql.Data.csproj b/MySQL.Data/src/MySql.Data.csproj index 0c93df32c..eb3fe9d67 100644 --- a/MySQL.Data/src/MySql.Data.csproj +++ b/MySQL.Data/src/MySql.Data.csproj @@ -5,7 +5,7 @@ MySql.Data.MySqlClient .Net Core Class Library Copyright © 2016, 2024, Oracle and/or its affiliates. en-US - 9.1.0 + 9.2.0 Oracle MySql.Data netstandard2.0;netstandard2.1;net6.0;net8.0; diff --git a/MySQL.Data/src/Properties/VersionInfo.cs b/MySQL.Data/src/Properties/VersionInfo.cs index 123b70f96..127f87162 100644 --- a/MySQL.Data/src/Properties/VersionInfo.cs +++ b/MySQL.Data/src/Properties/VersionInfo.cs @@ -40,7 +40,7 @@ // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("9.1.0")] -[assembly: AssemblyInformationalVersion("9.1.0")] -[assembly: AssemblyFileVersion("9.1.0")] +[assembly: AssemblyVersion("9.2.0")] +[assembly: AssemblyInformationalVersion("9.2.0")] +[assembly: AssemblyFileVersion("9.2.0")] [assembly: NeutralResourcesLanguage("en-US")] diff --git a/MySQL.Data/tests/MySql.Data.Tests/MySql.Data.Tests.csproj b/MySQL.Data/tests/MySql.Data.Tests/MySql.Data.Tests.csproj index 58c63070c..827d07e47 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/MySql.Data.Tests.csproj +++ b/MySQL.Data/tests/MySql.Data.Tests/MySql.Data.Tests.csproj @@ -4,7 +4,7 @@ MySql.Data.Tests MySql.Data.Tests Class Library Copyright © 2016, 2024, Oracle and/or its affiliates. - 9.1.0 + 9.2.0 Oracle Oracle MySql.Data.Tests diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/MySqlX.Data.Tests.csproj b/MySQL.Data/tests/MySqlX.Data.Tests/MySqlX.Data.Tests.csproj index 7d67519c3..42f7c6eb3 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/MySqlX.Data.Tests.csproj +++ b/MySQL.Data/tests/MySqlX.Data.Tests/MySqlX.Data.Tests.csproj @@ -4,7 +4,7 @@ MySql.Data.Tests MySql.Data.Tests Class Library Copyright © 2016, 2024, Oracle and/or its affiliates. - 9.1.0 + 9.2.0 Oracle Oracle MySql.Data.Tests diff --git a/MySql.Web/src/MySql.Web.csproj b/MySql.Web/src/MySql.Web.csproj index 9172c452c..e6d667f7d 100644 --- a/MySql.Web/src/MySql.Web.csproj +++ b/MySql.Web/src/MySql.Web.csproj @@ -4,7 +4,7 @@ MySql.Web Copyright © 2016, 2024, Oracle and/or its affiliates. en-US - 9.1.0 + 9.2.0 Oracle net462;net48; $(NoWarn);CS1591 diff --git a/MySql.Web/tests/MySql.Web.Tests.csproj b/MySql.Web/tests/MySql.Web.Tests.csproj index 8bf54e2b2..2ff8a784f 100644 --- a/MySql.Web/tests/MySql.Web.Tests.csproj +++ b/MySql.Web/tests/MySql.Web.Tests.csproj @@ -4,7 +4,7 @@ MySql.Web.Tests Copyright © 2016, 2024, Oracle and/or its affiliates. en-US - 9.1.0 + 9.2.0 Oracle net462;net48; MySql.Web.Tests From ef2b9c8e12361e2a6381b48e33e315336fe5b058 Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Wed, 4 Dec 2024 13:54:35 -0700 Subject: [PATCH 081/125] Updated System.Text.Json Change-Id: I0cba0ebe408d84894927a91fd5dab4ae7a3c672c --- MySQL.Data/src/MySql.Data.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MySQL.Data/src/MySql.Data.csproj b/MySQL.Data/src/MySql.Data.csproj index eb3fe9d67..e97db2a6f 100644 --- a/MySQL.Data/src/MySql.Data.csproj +++ b/MySQL.Data/src/MySql.Data.csproj @@ -86,7 +86,7 @@ - + From 50dfed130a363cf0c0ecec114c40e2b03acbc76a Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Thu, 5 Dec 2024 17:42:54 -0700 Subject: [PATCH 082/125] WL#16638 [Add support for .NET 9 and EF Core 9 GA versions] Change-Id: Ifaa210fc070ed407f8a0a56557633a516545f3e3 --- CHANGES | 1 + .../Internal/MySQLHistoryRepository.cs | 85 +++ .../Internal/MySQLMigrationDatabaseLockcs.cs | 53 ++ .../src/Migrations/Internal/MySQLMigrator.cs | 675 ++++++++++++++++++ EFCore/src/MySql.EntityFrameworkCore.csproj | 12 +- .../Internal/MySQLBinaryExpression.cs | 16 + .../Internal/MySQLCollateExpression.cs | 49 +- .../MySQLColumnAliasReferenceExpression.cs | 14 + .../MySQLComplexFunctionArgumentExpression.cs | 15 + .../Internal/MySQLJsonArrayIndexExpression.cs | 14 + .../Internal/MySQLJsonTraversalExpression.cs | 14 + .../Internal/MySQLMatchExpression.cs | 16 + .../Internal/MySQLRegexpExpression.cs | 15 + .../MySQLStringComparisonMethodTranslator.cs | 2 +- .../Internal/MySQLDateTimeMethodTranslator.cs | 4 + .../MySQLParameterBasedSqlProcessor.cs | 22 +- .../MySQLParameterBasedSqlProcessorFactory.cs | 5 + .../Internal/MySQLSqlExpressionFactory.cs | 13 +- .../Internal/MySQLSqlNullabilityProcessor.cs | 15 +- ...Sql.EntityFrameworkCore.Basic.Tests.csproj | 6 +- .../Utils/MySqlTestStore.cs | 42 +- ...ql.EntityFrameworkCore.Design.Tests.csproj | 6 +- ...ntityFrameworkCore.Migrations.Tests.csproj | 4 +- MySQL.Data/src/MySql.Data.csproj | 4 +- .../MySql.Data.Tests/MySql.Data.Tests.csproj | 4 +- .../MySqlX.Data.Tests.csproj | 4 +- 26 files changed, 1077 insertions(+), 33 deletions(-) create mode 100644 EFCore/src/Migrations/Internal/MySQLMigrationDatabaseLockcs.cs diff --git a/CHANGES b/CHANGES index 19b152d3d..b5957b9ea 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,5 @@ 9.2.0 +- Added support for .NET 9 and EF Core 9 GA versions (WL16638). 9.1.0 diff --git a/EFCore/src/Migrations/Internal/MySQLHistoryRepository.cs b/EFCore/src/Migrations/Internal/MySQLHistoryRepository.cs index 1a6d4e093..77f84336c 100644 --- a/EFCore/src/Migrations/Internal/MySQLHistoryRepository.cs +++ b/EFCore/src/Migrations/Internal/MySQLHistoryRepository.cs @@ -27,12 +27,15 @@ // 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.Extensions.DependencyInjection; using MySql.EntityFrameworkCore.Utils; using System; using System.Text; +using System.Threading.Tasks; +using System.Threading; namespace MySql.EntityFrameworkCore.Migrations.Internal { @@ -50,7 +53,89 @@ public MySQLHistoryRepository([NotNull] HistoryRepositoryDependencies dependenci : base(dependencies) { } +#if NET9_0 + public override LockReleaseBehavior LockReleaseBehavior => LockReleaseBehavior.Connection; + public override IMigrationsDatabaseLock AcquireDatabaseLock() + { + Dependencies.MigrationsLogger.AcquiringMigrationLock(); + + var dbLock = CreateMigrationDatabaseLock(); + int result; + try + { + result = (int)CreateGetLockCommand().ExecuteScalar(CreateRelationalCommandParameters())!; + } + catch + { + try + { + dbLock.Dispose(); + } + catch + { + } + + throw; + } + + return result < 0 + ? throw new TimeoutException() + : dbLock; + } + + /// + /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to + /// the same compatibility standards as public APIs. It may be changed or removed without notice in + /// any release. You should only use it directly in your code with extreme caution and knowing that + /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// + public override async Task AcquireDatabaseLockAsync(CancellationToken cancellationToken = default) + { + Dependencies.MigrationsLogger.AcquiringMigrationLock(); + + var dbLock = CreateMigrationDatabaseLock(); + int result; + try + { + result = (int)(await CreateGetLockCommand().ExecuteScalarAsync(CreateRelationalCommandParameters(), cancellationToken) + .ConfigureAwait(false))!; + } + catch + { + try + { + await dbLock.DisposeAsync().ConfigureAwait(false); + } + catch + { + } + + throw; + } + + return result < 0 + ? throw new TimeoutException() + : dbLock; + } + + private IRelationalCommand CreateGetLockCommand() + => Dependencies.RawSqlCommandBuilder.Build("DECLARE @result int;EXEC @result = sp_getapplock @Resource = '__EFMigrationsLock', @LockOwner = 'Session', @LockMode = 'Exclusive';SELECT @result", []).RelationalCommand; + + private MySQLMigrationDatabaseLock CreateMigrationDatabaseLock() + => new( + Dependencies.RawSqlCommandBuilder.Build("DECLARE @result int;EXEC @result = sp_releaseapplock @Resource = '__EFMigrationsLock', @LockOwner = 'Session';SELECT @result"), + CreateRelationalCommandParameters(), + this); + + private RelationalCommandParameterObject CreateRelationalCommandParameters() + => new( + Dependencies.Connection, + null, + null, + Dependencies.CurrentContext.Context, + Dependencies.CommandLogger, CommandSource.Migrations); +#endif protected override string ExistsSql { get diff --git a/EFCore/src/Migrations/Internal/MySQLMigrationDatabaseLockcs.cs b/EFCore/src/Migrations/Internal/MySQLMigrationDatabaseLockcs.cs new file mode 100644 index 000000000..139c378dc --- /dev/null +++ b/EFCore/src/Migrations/Internal/MySQLMigrationDatabaseLockcs.cs @@ -0,0 +1,53 @@ +// Copyright © 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage; +using System.Threading; +using System.Threading.Tasks; + +namespace MySql.EntityFrameworkCore.Migrations.Internal +{ +#if NET9_0 + internal class MySQLMigrationDatabaseLock( + IRelationalCommand releaseLockCommand, + RelationalCommandParameterObject relationalCommandParameters, + IHistoryRepository historyRepository, + CancellationToken cancellationToken = default) + : IMigrationsDatabaseLock + { + public virtual IHistoryRepository HistoryRepository => historyRepository; + + public void Dispose() + => releaseLockCommand.ExecuteScalar(relationalCommandParameters); + + public async ValueTask DisposeAsync() + => await releaseLockCommand.ExecuteScalarAsync(relationalCommandParameters, cancellationToken).ConfigureAwait(false); + } +#endif +} diff --git a/EFCore/src/Migrations/Internal/MySQLMigrator.cs b/EFCore/src/Migrations/Internal/MySQLMigrator.cs index 1cff48605..23aa5d493 100644 --- a/EFCore/src/Migrations/Internal/MySQLMigrator.cs +++ b/EFCore/src/Migrations/Internal/MySQLMigrator.cs @@ -28,7 +28,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Diagnostics; +using Microsoft.EntityFrameworkCore.Diagnostics.Internal; using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Migrations.Internal; using Microsoft.EntityFrameworkCore.Migrations.Operations; @@ -36,11 +38,683 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Reflection; using System.Text; using System.Text.RegularExpressions; +using System.Threading.Tasks; +using System.Threading; +using System.Transactions; namespace MySql.EntityFrameworkCore.Migrations.Internal { +#if NET9_0 + public class MySQLMigrator : IMigrator + { + private readonly IMigrationsAssembly _migrationsAssembly; + private readonly IHistoryRepository _historyRepository; + private readonly IRelationalDatabaseCreator _databaseCreator; + private readonly IMigrationsSqlGenerator _migrationsSqlGenerator; + private readonly IRawSqlCommandBuilder _rawSqlCommandBuilder; + private readonly IMigrationCommandExecutor _migrationCommandExecutor; + private readonly IRelationalConnection _connection; + private readonly ISqlGenerationHelper _sqlGenerationHelper; + private readonly ICurrentDbContext _currentContext; + private readonly IModelRuntimeInitializer _modelRuntimeInitializer; + private readonly IDiagnosticsLogger _logger; + private readonly IRelationalCommandDiagnosticsLogger _commandLogger; + private readonly IMigrationsModelDiffer _migrationsModelDiffer; + private readonly IDesignTimeModel _designTimeModel; + private readonly string _activeProvider; + private readonly IDbContextOptions _dbContextOptions; + private readonly IExecutionStrategy _executionStrategy; + + public MySQLMigrator( + IMigrationsAssembly migrationsAssembly, + IHistoryRepository historyRepository, + IDatabaseCreator databaseCreator, + IMigrationsSqlGenerator migrationsSqlGenerator, + IRawSqlCommandBuilder rawSqlCommandBuilder, + IMigrationCommandExecutor migrationCommandExecutor, + IRelationalConnection connection, + ISqlGenerationHelper sqlGenerationHelper, + ICurrentDbContext currentContext, + IModelRuntimeInitializer modelRuntimeInitializer, + IDiagnosticsLogger logger, + IRelationalCommandDiagnosticsLogger commandLogger, + IDatabaseProvider databaseProvider, + IMigrationsModelDiffer migrationsModelDiffer, + IDesignTimeModel designTimeModel, + IDbContextOptions dbContextOptions, + IExecutionStrategy executionStrategy) + { + _migrationsAssembly = migrationsAssembly; + _historyRepository = historyRepository; + _databaseCreator = (IRelationalDatabaseCreator)databaseCreator; + _migrationsSqlGenerator = migrationsSqlGenerator; + _rawSqlCommandBuilder = rawSqlCommandBuilder; + _migrationCommandExecutor = migrationCommandExecutor; + _connection = connection; + _sqlGenerationHelper = sqlGenerationHelper; + _currentContext = currentContext; + _modelRuntimeInitializer = modelRuntimeInitializer; + _logger = logger; + _commandLogger = commandLogger; + _migrationsModelDiffer = migrationsModelDiffer; + _designTimeModel = designTimeModel; + _activeProvider = databaseProvider.Name; + _dbContextOptions = dbContextOptions; + _executionStrategy = executionStrategy; + } + + protected virtual System.Data.IsolationLevel? MigrationTransactionIsolationLevel => null; + + public virtual void Migrate(string? targetMigration) + { + var useTransaction = _connection.CurrentTransaction is null; + if (!useTransaction + && _executionStrategy.RetriesOnFailure) + { + throw new NotSupportedException(RelationalStrings.TransactionSuppressedMigrationInUserTransaction); + } + + if (RelationalResources.LogPendingModelChanges(_logger).WarningBehavior != WarningBehavior.Ignore + && HasPendingModelChanges()) + { + _logger.PendingModelChangesWarning(_currentContext.Context.GetType()); + } + + if (!useTransaction) + { + _logger.MigrationsUserTransactionWarning(); + } + + _logger.MigrateUsingConnection(this, _connection); + + using var transactionScope = new TransactionScope(TransactionScopeOption.Suppress, TransactionScopeAsyncFlowOption.Enabled); + + if (!_databaseCreator.Exists()) + { + _databaseCreator.Create(); + } + + _connection.Open(); + try + { + var state = new MigrationExecutionState(); + if (_historyRepository.LockReleaseBehavior != LockReleaseBehavior.Transaction + && useTransaction) + { + state.DatabaseLock = _historyRepository.AcquireDatabaseLock(); + } + + _executionStrategy.Execute( + this, + static (_, migrator) => + { + migrator._connection.Open(); + try + { + return migrator._historyRepository.CreateIfNotExists(); + } + finally + { + migrator._connection.Close(); + } + }, + verifySucceeded: null); + + _executionStrategy.Execute( + (Migrator: this, + TargetMigration: targetMigration, + State: state, + UseTransaction: useTransaction), + static (c, s) => s.Migrator.MigrateImplementation(c, s.TargetMigration, s.State, s.UseTransaction), + static (_, s) => new ExecutionResult( + successful: s.Migrator.VerifyMigrationSucceeded(s.TargetMigration, s.State), + result: true)); + } + finally + { + _connection.Close(); + } + } + + private bool MigrateImplementation(DbContext context, string? targetMigration, MigrationExecutionState state, bool useTransaction) + { + var connectionOpened = _connection.Open(); + try + { + if (useTransaction) + { + state.Transaction = MigrationTransactionIsolationLevel == null + ? _connection.BeginTransaction() + : _connection.BeginTransaction(MigrationTransactionIsolationLevel.Value); + + state.DatabaseLock = state.DatabaseLock == null + ? _historyRepository.AcquireDatabaseLock() + : state.DatabaseLock.ReacquireIfNeeded(connectionOpened, useTransaction); + } + + PopulateMigrations( + _historyRepository.GetAppliedMigrations().Select(t => t.MigrationId), + targetMigration, + out var migratorData); + + var commandLists = GetMigrationCommandLists(migratorData); + foreach (var commandList in commandLists) + { + var (id, getCommands) = commandList; + if (id != state.CurrentMigrationId) + { + state.CurrentMigrationId = id; + state.LastCommittedCommandIndex = 0; + } + + _migrationCommandExecutor.ExecuteNonQuery(getCommands(), _connection, state, commitTransaction: false, MigrationTransactionIsolationLevel); + } + + var coreOptionsExtension = + _dbContextOptions.FindExtension() + ?? new CoreOptionsExtension(); + + var seed = coreOptionsExtension.Seeder; + if (seed != null) + { + seed(context, state.AnyOperationPerformed); + } + else if (coreOptionsExtension.AsyncSeeder != null) + { + throw new InvalidOperationException(CoreStrings.MissingSeeder); + } + + state.Transaction?.Commit(); + return state.AnyOperationPerformed; + } + finally + { + state.DatabaseLock?.Dispose(); + state.DatabaseLock = null; + state.Transaction?.Dispose(); + state.Transaction = null; + _connection.Close(); + } + } + + public virtual async Task MigrateAsync( + string? targetMigration, + CancellationToken cancellationToken = default) + { + var useTransaction = _connection.CurrentTransaction is null; + if (!useTransaction + && _executionStrategy.RetriesOnFailure) + { + throw new NotSupportedException(RelationalStrings.TransactionSuppressedMigrationInUserTransaction); + } + + if (RelationalResources.LogPendingModelChanges(_logger).WarningBehavior != WarningBehavior.Ignore + && HasPendingModelChanges()) + { + _logger.PendingModelChangesWarning(_currentContext.Context.GetType()); + } + + if (!useTransaction) + { + _logger.MigrationsUserTransactionWarning(); + } + + _logger.MigrateUsingConnection(this, _connection); + + using var transactionScope = new TransactionScope(TransactionScopeOption.Suppress, TransactionScopeAsyncFlowOption.Enabled); + + if (!await _databaseCreator.ExistsAsync(cancellationToken).ConfigureAwait(false)) + { + await _databaseCreator.CreateAsync(cancellationToken).ConfigureAwait(false); + } + + await _connection.OpenAsync(cancellationToken).ConfigureAwait(false); + try + { + var state = new MigrationExecutionState(); + if (_historyRepository.LockReleaseBehavior != LockReleaseBehavior.Transaction + && useTransaction) + { + state.DatabaseLock = await _historyRepository.AcquireDatabaseLockAsync(cancellationToken).ConfigureAwait(false); + } + + await _executionStrategy.ExecuteAsync( + this, + static async (_, migrator, ct) => + { + await migrator._connection.OpenAsync(ct).ConfigureAwait(false); + try + { + return await migrator._historyRepository.CreateIfNotExistsAsync(ct).ConfigureAwait(false); + } + finally + { + await migrator._connection.CloseAsync().ConfigureAwait(false); + } + }, + verifySucceeded: null, + cancellationToken).ConfigureAwait(false); + + await _executionStrategy.ExecuteAsync( + (Migrator: this, + TargetMigration: targetMigration, + State: state, + UseTransaction: useTransaction), + async static (c, s, ct) => await s.Migrator.MigrateImplementationAsync( + c, s.TargetMigration, s.State, s.UseTransaction, ct).ConfigureAwait(false), + async static (_, s, ct) => new ExecutionResult( + successful: await s.Migrator.VerifyMigrationSucceededAsync(s.TargetMigration, s.State, ct).ConfigureAwait(false), + result: true), + cancellationToken) + .ConfigureAwait(false); + } + finally + { + await _connection.CloseAsync().ConfigureAwait(false); + } + } + + private async Task MigrateImplementationAsync( + DbContext context, string? targetMigration, MigrationExecutionState state, bool useTransaction, CancellationToken cancellationToken = default) + { + var connectionOpened = await _connection.OpenAsync(cancellationToken).ConfigureAwait(false); + try + { + if (useTransaction) + { + state.Transaction = await (MigrationTransactionIsolationLevel == null + ? context.Database.BeginTransactionAsync(cancellationToken) + : context.Database.BeginTransactionAsync(MigrationTransactionIsolationLevel.Value, cancellationToken)) + .ConfigureAwait(false); + + state.DatabaseLock = state.DatabaseLock == null + ? await _historyRepository.AcquireDatabaseLockAsync(cancellationToken).ConfigureAwait(false) + : await state.DatabaseLock.ReacquireIfNeededAsync(connectionOpened, useTransaction, cancellationToken) + .ConfigureAwait(false); + } + + PopulateMigrations( + (await _historyRepository.GetAppliedMigrationsAsync(cancellationToken).ConfigureAwait(false)).Select(t => t.MigrationId), + targetMigration, + out var migratorData); + + var commandLists = GetMigrationCommandLists(migratorData); + foreach (var commandList in commandLists) + { + var (id, getCommands) = commandList; + if (id != state.CurrentMigrationId) + { + state.CurrentMigrationId = id; + state.LastCommittedCommandIndex = 0; + } + + await _migrationCommandExecutor.ExecuteNonQueryAsync( + getCommands(), _connection, state, commitTransaction: false, MigrationTransactionIsolationLevel, cancellationToken) + .ConfigureAwait(false); + } + + var coreOptionsExtension = + _dbContextOptions.FindExtension() + ?? new CoreOptionsExtension(); + + var seedAsync = coreOptionsExtension.AsyncSeeder; + if (seedAsync != null) + { + await seedAsync(context, state.AnyOperationPerformed, cancellationToken).ConfigureAwait(false); + } + else if (coreOptionsExtension.Seeder != null) + { + throw new InvalidOperationException(CoreStrings.MissingSeeder); + } + + if (state.Transaction != null) + { + await state.Transaction.CommitAsync(cancellationToken).ConfigureAwait(false); + } + return state.AnyOperationPerformed; + } + finally + { + if (state.DatabaseLock != null) + { + state.DatabaseLock.Dispose(); + state.DatabaseLock = null; + } + if (state.Transaction != null) + { + await state.Transaction.DisposeAsync().ConfigureAwait(false); + state.Transaction = null; + } + await _connection.CloseAsync().ConfigureAwait(false); + } + } + + private IEnumerable<(string, Func>)> GetMigrationCommandLists(MigratorData parameters) + { + var migrationsToApply = parameters.AppliedMigrations; + var migrationsToRevert = parameters.RevertedMigrations; + var actualTargetMigration = parameters.TargetMigration; + + for (var i = 0; i < migrationsToRevert.Count; i++) + { + var migration = migrationsToRevert[i]; + + var index = i; + yield return (migration.GetId(), () => + { + _logger.MigrationReverting(this, migration); + + var commands = GenerateDownSql( + migration, + index != migrationsToRevert.Count - 1 + ? migrationsToRevert[index + 1] + : actualTargetMigration); + if (migration.DownOperations.Count > 1 + && commands.FirstOrDefault(c => c.TransactionSuppressed) is MigrationCommand nonTransactionalCommand) + { + _logger.NonTransactionalMigrationOperationWarning(this, migration, nonTransactionalCommand); + } + + return commands; + } + ); + } + + foreach (var migration in migrationsToApply) + { + yield return (migration.GetId(), () => + { + _logger.MigrationApplying(this, migration); + + var commands = GenerateUpSql(migration); + if (migration.UpOperations.Count > 1 + && commands.FirstOrDefault(c => c.TransactionSuppressed) is MigrationCommand nonTransactionalCommand) + { + _logger.NonTransactionalMigrationOperationWarning(this, migration, nonTransactionalCommand); + } + + return commands; + } + ); + } + + if (migrationsToRevert.Count + migrationsToApply.Count == 0) + { + _logger.MigrationsNotApplied(this); + } + } + + protected virtual void PopulateMigrations( + IEnumerable appliedMigrationEntries, + string? targetMigration, + out MigratorData parameters) + { + var appliedMigrations = new Dictionary(); + var unappliedMigrations = new Dictionary(); + var appliedMigrationEntrySet = new HashSet(appliedMigrationEntries, StringComparer.OrdinalIgnoreCase); + if (_migrationsAssembly.Migrations.Count == 0) + { + _logger.MigrationsNotFound(this, _migrationsAssembly); + } + + foreach (var (key, typeInfo) in _migrationsAssembly.Migrations) + { + if (appliedMigrationEntrySet.Contains(key)) + { + appliedMigrations.Add(key, typeInfo); + } + else + { + unappliedMigrations.Add(key, typeInfo); + } + } + + IReadOnlyList migrationsToApply; + IReadOnlyList migrationsToRevert; + Migration? actualTargetMigration = null; + if (string.IsNullOrEmpty(targetMigration)) + { + migrationsToApply = unappliedMigrations + .OrderBy(m => m.Key) + .Select(p => _migrationsAssembly.CreateMigration(p.Value, _activeProvider)) + .ToList(); + migrationsToRevert = []; + } + else if (targetMigration == Migration.InitialDatabase) + { + migrationsToApply = []; + migrationsToRevert = appliedMigrations + .OrderByDescending(m => m.Key) + .Select(p => _migrationsAssembly.CreateMigration(p.Value, _activeProvider)) + .ToList(); + } + else + { + targetMigration = _migrationsAssembly.GetMigrationId(targetMigration); + migrationsToApply = unappliedMigrations + .Where(m => string.Compare(m.Key, targetMigration, StringComparison.OrdinalIgnoreCase) <= 0) + .OrderBy(m => m.Key) + .Select(p => _migrationsAssembly.CreateMigration(p.Value, _activeProvider)) + .ToList(); + migrationsToRevert = appliedMigrations + .Where(m => string.Compare(m.Key, targetMigration, StringComparison.OrdinalIgnoreCase) > 0) + .OrderByDescending(m => m.Key) + .Select(p => _migrationsAssembly.CreateMigration(p.Value, _activeProvider)) + .ToList(); + actualTargetMigration = appliedMigrations + .Where(m => string.Compare(m.Key, targetMigration, StringComparison.OrdinalIgnoreCase) == 0) + .Select(p => _migrationsAssembly.CreateMigration(p.Value, _activeProvider)) + .SingleOrDefault(); + } + + parameters = new MigratorData(migrationsToApply, migrationsToRevert, actualTargetMigration); + } + + protected virtual bool VerifyMigrationSucceeded( + string? targetMigration, MigrationExecutionState state) + => false; + + protected virtual Task VerifyMigrationSucceededAsync( + string? targetMigration, MigrationExecutionState state, CancellationToken cancellationToken) + => Task.FromResult(false); + + public virtual string GenerateScript( + string? fromMigration = null, + string? toMigration = null, + MigrationsSqlGenerationOptions options = MigrationsSqlGenerationOptions.Default) + { + options |= MigrationsSqlGenerationOptions.Script; + + var idempotent = options.HasFlag(MigrationsSqlGenerationOptions.Idempotent); + var noTransactions = options.HasFlag(MigrationsSqlGenerationOptions.NoTransactions); + + IEnumerable appliedMigrations; + if (string.IsNullOrEmpty(fromMigration) + || fromMigration == Migration.InitialDatabase) + { + appliedMigrations = Enumerable.Empty(); + } + else + { + var fromMigrationId = _migrationsAssembly.GetMigrationId(fromMigration); + appliedMigrations = _migrationsAssembly.Migrations + .Where(t => string.Compare(t.Key, fromMigrationId, StringComparison.OrdinalIgnoreCase) <= 0) + .Select(t => t.Key); + } + + PopulateMigrations(appliedMigrations, toMigration, out var migratorData); + + var builder = new IndentedStringBuilder(); + + if (fromMigration == Migration.InitialDatabase + || string.IsNullOrEmpty(fromMigration)) + { + builder + .Append(_historyRepository.GetCreateIfNotExistsScript()) + .Append(_sqlGenerationHelper.BatchTerminator); + } + + var idempotencyEnd = idempotent + ? _historyRepository.GetEndIfScript() + : null; + var migrationsToApply = migratorData.AppliedMigrations; + var migrationsToRevert = migratorData.RevertedMigrations; + var actualTargetMigration = migratorData.TargetMigration; + var transactionStarted = false; + for (var i = 0; i < migrationsToRevert.Count; i++) + { + var migration = migrationsToRevert[i]; + var previousMigration = i != migrationsToRevert.Count - 1 + ? migrationsToRevert[i + 1] + : actualTargetMigration; + + _logger.MigrationGeneratingDownScript(this, migration, fromMigration, toMigration, idempotent); + + var idempotencyCondition = idempotent + ? _historyRepository.GetBeginIfExistsScript(migration.GetId()) + : null; + + GenerateSqlScript( + GenerateDownSql(migration, previousMigration, options), + builder, _sqlGenerationHelper, ref transactionStarted, noTransactions, idempotencyCondition, idempotencyEnd); + } + + foreach (var migration in migrationsToApply) + { + _logger.MigrationGeneratingUpScript(this, migration, fromMigration, toMigration, idempotent); + + var idempotencyCondition = idempotent + ? _historyRepository.GetBeginIfNotExistsScript(migration.GetId()) + : null; + + GenerateSqlScript( + GenerateUpSql(migration, options), + builder, _sqlGenerationHelper, ref transactionStarted, noTransactions, idempotencyCondition, idempotencyEnd); + } + + if (transactionStarted) + { + builder + .AppendLine(_sqlGenerationHelper.CommitTransactionStatement) + .Append(_sqlGenerationHelper.BatchTerminator); + } + + return builder.ToString(); + } + + private static void GenerateSqlScript( + IEnumerable commands, + IndentedStringBuilder builder, + ISqlGenerationHelper sqlGenerationHelper, + ref bool transactionStarted, + bool noTransactions = false, + string? idempotencyCondition = null, + string? idempotencyEnd = null) + { + foreach (var command in commands) + { + if (!noTransactions) + { + if (!transactionStarted && !command.TransactionSuppressed) + { + builder + .AppendLine(sqlGenerationHelper.StartTransactionStatement); + transactionStarted = true; + } + + if (transactionStarted && command.TransactionSuppressed) + { + builder + .AppendLine(sqlGenerationHelper.CommitTransactionStatement) + .Append(sqlGenerationHelper.BatchTerminator); + transactionStarted = false; + } + } + + if (idempotencyCondition != null + && idempotencyEnd != null) + { + builder.AppendLine(idempotencyCondition); + using (builder.Indent()) + { + builder.AppendLines(command.CommandText); + } + + builder.Append(idempotencyEnd); + } + else + { + builder.Append(command.CommandText); + } + + if (!transactionStarted) + { + builder.Append(sqlGenerationHelper.BatchTerminator); + } + else + { + builder.Append(Environment.NewLine); + } + } + } + + protected virtual IReadOnlyList GenerateUpSql( + Migration migration, + MigrationsSqlGenerationOptions options = MigrationsSqlGenerationOptions.Default) + { + var insertCommand = _rawSqlCommandBuilder.Build( + _historyRepository.GetInsertScript(new HistoryRow(migration.GetId(), ProductInfo.GetVersion()))); + + var operations = _migrationsSqlGenerator + .Generate( + migration.UpOperations, + FinalizeModel(migration.TargetModel), + options); + + return + [ + .. operations, + new MigrationCommand(insertCommand, _currentContext.Context, _commandLogger, + transactionSuppressed: operations.Any(o => o.TransactionSuppressed)), + ]; + } + + protected virtual IReadOnlyList GenerateDownSql( + Migration migration, + Migration? previousMigration, + MigrationsSqlGenerationOptions options = MigrationsSqlGenerationOptions.Default) + { + var deleteCommand = _rawSqlCommandBuilder.Build( + _historyRepository.GetDeleteScript(migration.GetId())); + + var operations = _migrationsSqlGenerator + .Generate( + migration.DownOperations, + previousMigration == null ? null : FinalizeModel(previousMigration.TargetModel), + options); + + return [ + .. operations, + new MigrationCommand(deleteCommand, _currentContext.Context, _commandLogger, + transactionSuppressed: operations.Any(o => o.TransactionSuppressed)) + ]; + } + + private IModel? FinalizeModel(IModel? model) + => model == null + ? null + : _modelRuntimeInitializer.Initialize(model); + + public bool HasPendingModelChanges() + => _migrationsModelDiffer.HasDifferences( + FinalizeModel(_migrationsAssembly.ModelSnapshot?.Model)?.GetRelationalModel(), + _designTimeModel.Model.GetRelationalModel()); + } +#else + internal class MySQLMigrator : Migrator { private static readonly Dictionary> _customMigrationCommands = @@ -350,4 +1024,5 @@ INTO PRIMARY_KEY_COLUMN_NAME #endregion Custom SQL } +#endif } diff --git a/EFCore/src/MySql.EntityFrameworkCore.csproj b/EFCore/src/MySql.EntityFrameworkCore.csproj index f4c824aa4..b2e9a5f12 100644 --- a/EFCore/src/MySql.EntityFrameworkCore.csproj +++ b/EFCore/src/MySql.EntityFrameworkCore.csproj @@ -9,8 +9,8 @@ https://github.com/mysql/mysql-connector-net GPL-2.0-only WITH Universal-FOSS-exception-1.0 true - 10.0 - net6.0;net8.0; + 13.0 + net9.0;net6.0;net8.0; MySql.EntityFrameworkCore MySql.EntityFrameworkCore enable @@ -18,7 +18,7 @@ True ..\..\ConnectorNetPublicKey.snk true - $(NoWarn);CS1591;EF1001 + $(NoWarn);CS1591;EF1001;EF9100 false false false @@ -31,7 +31,7 @@ - net9.0;$(TargetFrameworks) + @@ -45,8 +45,8 @@ - - + + diff --git a/EFCore/src/Query/Expressions/Internal/MySQLBinaryExpression.cs b/EFCore/src/Query/Expressions/Internal/MySQLBinaryExpression.cs index 088c0d229..fb5cb4112 100644 --- a/EFCore/src/Query/Expressions/Internal/MySQLBinaryExpression.cs +++ b/EFCore/src/Query/Expressions/Internal/MySQLBinaryExpression.cs @@ -32,6 +32,7 @@ using MySql.EntityFrameworkCore.Utils; using System; using System.Linq.Expressions; +using System.Reflection; namespace MySql.EntityFrameworkCore.Query.Expressions.Internal { @@ -60,6 +61,9 @@ public MySQLBinaryExpression( Right = right; } +#if NET9_0 + private static ConstructorInfo? _quotingConstructor; +#endif public virtual MySQLBinaryExpressionOperatorType OperatorType { get; } public virtual SqlExpression Left { get; } public virtual SqlExpression Right { get; } @@ -77,6 +81,18 @@ protected override Expression VisitChildren(ExpressionVisitor visitor) return Update(left, right); } +#if NET9_0 + /// + public override Expression Quote() => New( + _quotingConstructor ??= typeof(MySQLBinaryExpression).GetConstructor( + [typeof(ExpressionType), typeof(SqlExpression), typeof(SqlExpression), typeof(Type), typeof(RelationalTypeMapping)])!, + Constant(OperatorType), + Left.Quote(), + Right.Quote(), + Constant(Type), + RelationalExpressionQuotingUtilities.QuoteTypeMapping(TypeMapping)); +#endif + public virtual MySQLBinaryExpression Update(SqlExpression left, SqlExpression right) => left != Left || right != Right ? new MySQLBinaryExpression(OperatorType, left, right, Type, TypeMapping) diff --git a/EFCore/src/Query/Expressions/Internal/MySQLCollateExpression.cs b/EFCore/src/Query/Expressions/Internal/MySQLCollateExpression.cs index 0608e9f98..a88c77b49 100644 --- a/EFCore/src/Query/Expressions/Internal/MySQLCollateExpression.cs +++ b/EFCore/src/Query/Expressions/Internal/MySQLCollateExpression.cs @@ -32,6 +32,7 @@ using System; using System.Linq; using System.Linq.Expressions; +using System.Reflection; namespace MySql.EntityFrameworkCore.Query.Expressions.Internal { @@ -44,17 +45,31 @@ internal class MySQLCollateExpression : SqlExpression private readonly string _charset; private readonly string _collation; +#if NET9_0 + private static ConstructorInfo? _quotingConstructor; +#endif + +#if NET9_0 + public MySQLCollateExpression(SqlExpression operand, string collation) + : base(operand.Type, operand.TypeMapping) + { + Operand = operand; + Collation = collation; + } +#else public MySQLCollateExpression( - SqlExpression valueExpression, - string charset, - string collation, - RelationalTypeMapping? typeMapping) - : base(typeof(string), typeMapping) + SqlExpression valueExpression, + string charset, + string collation, + RelationalTypeMapping? typeMapping) + : base(typeof(string), typeMapping) { _valueExpression = valueExpression; _charset = charset; _collation = collation; } +#endif + /// /// The expression for which a collation is being specified. @@ -66,10 +81,21 @@ public MySQLCollateExpression( /// public virtual string Charset => _charset; +#if NET9_0 + /// + /// The expression on which collation is applied. + /// + public virtual SqlExpression Operand { get; } + + public virtual string Collation { get; } +#else /// /// The collation that the string is being converted to. /// public virtual string Collation => _collation; +#endif + + /// /// Dispatches to the specific visit method for this node type. @@ -100,11 +126,24 @@ protected override Expression VisitChildren(ExpressionVisitor visitor) } +#if NET9_0 + public virtual MySQLCollateExpression Update(SqlExpression operand) + => operand != Operand + ? new MySQLCollateExpression(operand, Collation) + : this; + /// + public override Expression Quote() => New( + _quotingConstructor ??= typeof(MySQLCollateExpression).GetConstructor([typeof(SqlExpression), typeof(string)])!, + Operand.Quote(), + Constant(Collation)); + +#else public virtual MySQLCollateExpression Update(SqlExpression valueExpression) => valueExpression != _valueExpression && valueExpression != null ? new MySQLCollateExpression(valueExpression, _charset, _collation, TypeMapping) : this; +#endif /// /// Tests if this object is considered equal to another. diff --git a/EFCore/src/Query/Expressions/Internal/MySQLColumnAliasReferenceExpression.cs b/EFCore/src/Query/Expressions/Internal/MySQLColumnAliasReferenceExpression.cs index ca30dcf65..49a96f698 100644 --- a/EFCore/src/Query/Expressions/Internal/MySQLColumnAliasReferenceExpression.cs +++ b/EFCore/src/Query/Expressions/Internal/MySQLColumnAliasReferenceExpression.cs @@ -31,6 +31,7 @@ using Microsoft.EntityFrameworkCore.Storage; using System; using System.Linq.Expressions; +using System.Reflection; namespace MySql.EntityFrameworkCore.Query.Expressions.Internal { @@ -39,6 +40,10 @@ namespace MySql.EntityFrameworkCore.Query.Expressions.Internal /// internal class MySQLColumnAliasReferenceExpression : SqlExpression, IEquatable { +#if NET9_0 + private static ConstructorInfo? _quotingConstructor; +#endif + [NotNull] public virtual string Alias { get; } @@ -67,6 +72,15 @@ public virtual MySQLColumnAliasReferenceExpression Update( ? this : new MySQLColumnAliasReferenceExpression(alias, expression, Type, TypeMapping!); +#if NET9_0 + public override Expression Quote() => New( + _quotingConstructor ??= typeof(MySQLColumnAliasReferenceExpression).GetConstructor([typeof(SqlExpression), typeof(string)])!, + Constant(Alias), + Expression.Quote(), + Constant(Type), + RelationalExpressionQuotingUtilities.QuoteTypeMapping(TypeMapping)); +#endif + public override bool Equals(object? obj) => Equals(obj as MySQLColumnAliasReferenceExpression); diff --git a/EFCore/src/Query/Expressions/Internal/MySQLComplexFunctionArgumentExpression.cs b/EFCore/src/Query/Expressions/Internal/MySQLComplexFunctionArgumentExpression.cs index 528ee4a2c..5f176545e 100644 --- a/EFCore/src/Query/Expressions/Internal/MySQLComplexFunctionArgumentExpression.cs +++ b/EFCore/src/Query/Expressions/Internal/MySQLComplexFunctionArgumentExpression.cs @@ -33,11 +33,17 @@ using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; +using System.Reflection; namespace MySql.EntityFrameworkCore.Query.Expressions.Internal { internal class MySQLComplexFunctionArgumentExpression : SqlExpression { + +#if NET9_0 + private static ConstructorInfo? _quotingConstructor; +#endif + /// /// The arguments parts. /// @@ -74,6 +80,15 @@ protected override Expression VisitChildren(ExpressionVisitor visitor) return Update(argumentParts, Delimiter); } +#if NET9_0 + public override Expression Quote() => New( + _quotingConstructor ??= typeof(MySQLComplexFunctionArgumentExpression).GetConstructor([typeof(SqlExpression), typeof(string)])!, + Constant(ArgumentParts), + Constant(Delimiter), + Constant(Type), + RelationalExpressionQuotingUtilities.QuoteTypeMapping(TypeMapping)); +#endif + public virtual MySQLComplexFunctionArgumentExpression Update(IReadOnlyList argumentParts, string delimiter) => !argumentParts.SequenceEqual(ArgumentParts) ? new MySQLComplexFunctionArgumentExpression(argumentParts, delimiter, Type, TypeMapping!) diff --git a/EFCore/src/Query/Expressions/Internal/MySQLJsonArrayIndexExpression.cs b/EFCore/src/Query/Expressions/Internal/MySQLJsonArrayIndexExpression.cs index 0030496c4..6124ce5eb 100644 --- a/EFCore/src/Query/Expressions/Internal/MySQLJsonArrayIndexExpression.cs +++ b/EFCore/src/Query/Expressions/Internal/MySQLJsonArrayIndexExpression.cs @@ -31,6 +31,7 @@ using Microsoft.EntityFrameworkCore.Storage; using System; using System.Linq.Expressions; +using System.Reflection; namespace MySql.EntityFrameworkCore.Query.Expressions.Internal { @@ -39,6 +40,11 @@ namespace MySql.EntityFrameworkCore.Query.Expressions.Internal /// internal class MySQLJsonArrayIndexExpression : SqlExpression, IEquatable { + +#if NET9_0 + private static ConstructorInfo? _quotingConstructor; +#endif + [NotNull] public virtual SqlExpression Expression { get; } @@ -54,6 +60,14 @@ public MySQLJsonArrayIndexExpression( protected override Expression VisitChildren(ExpressionVisitor visitor) => Update((SqlExpression)visitor.Visit(Expression)); +#if NET9_0 + public override Expression Quote() => New( + _quotingConstructor ??= typeof(MySQLJsonArrayIndexExpression).GetConstructor([typeof(SqlExpression), typeof(string)])!, + Expression.Quote(), + Constant(Type), + RelationalExpressionQuotingUtilities.QuoteTypeMapping(TypeMapping)); +#endif + public virtual MySQLJsonArrayIndexExpression Update( [NotNull] SqlExpression expression) => expression == Expression diff --git a/EFCore/src/Query/Expressions/Internal/MySQLJsonTraversalExpression.cs b/EFCore/src/Query/Expressions/Internal/MySQLJsonTraversalExpression.cs index f073a4194..e3b8430ac 100644 --- a/EFCore/src/Query/Expressions/Internal/MySQLJsonTraversalExpression.cs +++ b/EFCore/src/Query/Expressions/Internal/MySQLJsonTraversalExpression.cs @@ -34,6 +34,7 @@ using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; +using System.Reflection; namespace MySql.EntityFrameworkCore.Query.Expressions.Internal { @@ -42,6 +43,10 @@ namespace MySql.EntityFrameworkCore.Query.Expressions.Internal ///
internal class MySQLJsonTraversalExpression : SqlExpression, IEquatable { + +#if NET9_0 + private static ConstructorInfo? _quotingConstructor; +#endif /// /// The JSON column. /// @@ -91,6 +96,15 @@ protected override Expression VisitChildren(ExpressionVisitor visitor) => Update((SqlExpression)visitor.Visit(Expression), Path.Select(p => (SqlExpression)visitor.Visit(p)).ToArray()); +#if NET9_0 + public override Expression Quote() => New( + _quotingConstructor ??= typeof(MySQLJsonTraversalExpression).GetConstructor([typeof(SqlExpression), typeof(string)])!, + Expression.Quote(), + Constant(ReturnsText), + Constant(Type), + RelationalExpressionQuotingUtilities.QuoteTypeMapping(TypeMapping)); +#endif + public virtual MySQLJsonTraversalExpression Update( [NotNull] SqlExpression expression, [NotNull] IReadOnlyList path) diff --git a/EFCore/src/Query/Expressions/Internal/MySQLMatchExpression.cs b/EFCore/src/Query/Expressions/Internal/MySQLMatchExpression.cs index 6469189c7..e90f336a8 100644 --- a/EFCore/src/Query/Expressions/Internal/MySQLMatchExpression.cs +++ b/EFCore/src/Query/Expressions/Internal/MySQLMatchExpression.cs @@ -33,11 +33,17 @@ using MySql.EntityFrameworkCore.Utils; using System; using System.Linq.Expressions; +using System.Reflection; namespace MySql.EntityFrameworkCore.Query.Expressions.Internal { internal class MySQLMatchExpression : SqlExpression { + +#if NET9_0 + private static ConstructorInfo? _quotingConstructor; +#endif + public MySQLMatchExpression( SqlExpression match, SqlExpression against, @@ -75,6 +81,16 @@ protected override Expression VisitChildren(ExpressionVisitor visitor) return Update(match, against); } +#if NET9_0 + public override Expression Quote() => New( + _quotingConstructor ??= typeof(MySQLMatchExpression).GetConstructor([typeof(SqlExpression), typeof(string)])!, + Match.Quote(), + Against.Quote(), + Constant(SearchMode), + Constant(Type), + RelationalExpressionQuotingUtilities.QuoteTypeMapping(TypeMapping)); +#endif + public virtual MySQLMatchExpression Update(SqlExpression match, SqlExpression against) => match != Match || against != Against ? new MySQLMatchExpression( diff --git a/EFCore/src/Query/Expressions/Internal/MySQLRegexpExpression.cs b/EFCore/src/Query/Expressions/Internal/MySQLRegexpExpression.cs index f10d3ea2e..f851e0eaa 100644 --- a/EFCore/src/Query/Expressions/Internal/MySQLRegexpExpression.cs +++ b/EFCore/src/Query/Expressions/Internal/MySQLRegexpExpression.cs @@ -31,11 +31,17 @@ using Microsoft.EntityFrameworkCore.Storage; using MySql.EntityFrameworkCore.Utils; using System.Linq.Expressions; +using System.Reflection; namespace MySql.EntityFrameworkCore.Query.Expressions.Internal { internal class MySQLRegexpExpression : SqlExpression { + +#if NET9_0 + private static ConstructorInfo? _quotingConstructor; +#endif + public MySQLRegexpExpression( [NotNull] SqlExpression match, [NotNull] SqlExpression pattern, @@ -69,6 +75,15 @@ protected override Expression VisitChildren(ExpressionVisitor visitor) return Update(match, pattern); } +#if NET9_0 + public override Expression Quote() => New( + _quotingConstructor ??= typeof(MySQLMatchExpression).GetConstructor([typeof(SqlExpression), typeof(string)])!, + Match.Quote(), + Pattern.Quote(), + Constant(Type), + RelationalExpressionQuotingUtilities.QuoteTypeMapping(TypeMapping)); +#endif + public virtual MySQLRegexpExpression Update(SqlExpression match, SqlExpression pattern) => match != Match || pattern != Pattern diff --git a/EFCore/src/Query/Expressions/Internal/MySQLStringComparisonMethodTranslator.cs b/EFCore/src/Query/Expressions/Internal/MySQLStringComparisonMethodTranslator.cs index 8fd775d7d..32b412960 100644 --- a/EFCore/src/Query/Expressions/Internal/MySQLStringComparisonMethodTranslator.cs +++ b/EFCore/src/Query/Expressions/Internal/MySQLStringComparisonMethodTranslator.cs @@ -281,7 +281,7 @@ private SqlBinaryExpression MakeStartsWithExpressionImpl( SqlExpression prefix, SqlExpression? originalPrefix = null) { - return _sqlExpressionFactory.AndAlso( + return (SqlBinaryExpression)_sqlExpressionFactory.AndAlso( _sqlExpressionFactory.Like( target, _sqlExpressionFactory.ApplyDefaultTypeMapping(_sqlExpressionFactory.Function( diff --git a/EFCore/src/Query/Internal/MySQLDateTimeMethodTranslator.cs b/EFCore/src/Query/Internal/MySQLDateTimeMethodTranslator.cs index d03a3cce7..40fe8c1c6 100644 --- a/EFCore/src/Query/Internal/MySQLDateTimeMethodTranslator.cs +++ b/EFCore/src/Query/Internal/MySQLDateTimeMethodTranslator.cs @@ -100,7 +100,11 @@ public MySQLDateTimeMethodTranslator(ISqlExpressionFactory sqlExpressionFactory) typeof(string)) }, nullable: true, +#if !NET9_0 argumentsPropagateNullability: TrueArrays[1], +#else + argumentsPropagateNullability: new[] { true, false }, +#endif instance!.Type, instance.TypeMapping); } diff --git a/EFCore/src/Query/Internal/MySQLParameterBasedSqlProcessor.cs b/EFCore/src/Query/Internal/MySQLParameterBasedSqlProcessor.cs index d31ef25e2..28ec64a92 100644 --- a/EFCore/src/Query/Internal/MySQLParameterBasedSqlProcessor.cs +++ b/EFCore/src/Query/Internal/MySQLParameterBasedSqlProcessor.cs @@ -39,6 +39,7 @@ internal class MySQLParameterBasedSqlProcessor : RelationalParameterBasedSqlProc { private readonly IMySQLOptions _options; +#if !NET9_0 public MySQLParameterBasedSqlProcessor( RelationalParameterBasedSqlProcessorDependencies dependencies, bool useRelationalNulls, @@ -47,6 +48,16 @@ public MySQLParameterBasedSqlProcessor( { _options = options; } +#else + public MySQLParameterBasedSqlProcessor( + RelationalParameterBasedSqlProcessorDependencies dependencies, + RelationalParameterBasedSqlProcessorParameters parameters, + IMySQLOptions options) + : base(dependencies, parameters) + { + _options = options; + } +#endif /// #if NET6_0 @@ -62,7 +73,7 @@ protected override SelectExpression ProcessSqlNullability( return selectExpression; } -#elif NET8_0_OR_GREATER +#elif NET8_0 protected override Expression ProcessSqlNullability( Expression selectExpression, IReadOnlyDictionary parametersValues, out bool canCache) { @@ -71,6 +82,15 @@ protected override Expression ProcessSqlNullability( return new MySQLSqlNullabilityProcessor(Dependencies, UseRelationalNulls).Process(selectExpression, parametersValues, out canCache); } +#elif NET9_0 + protected override Expression ProcessSqlNullability( + Expression selectExpression, IReadOnlyDictionary parametersValues, out bool canCache) + { + Check.NotNull(selectExpression, nameof(selectExpression)); + Check.NotNull(parametersValues, nameof(parametersValues)); + + return new MySQLSqlNullabilityProcessor(Dependencies, Parameters).Process(selectExpression, parametersValues, out canCache); + } #endif } } diff --git a/EFCore/src/Query/Internal/MySQLParameterBasedSqlProcessorFactory.cs b/EFCore/src/Query/Internal/MySQLParameterBasedSqlProcessorFactory.cs index e99afda1d..aac4cbec9 100644 --- a/EFCore/src/Query/Internal/MySQLParameterBasedSqlProcessorFactory.cs +++ b/EFCore/src/Query/Internal/MySQLParameterBasedSqlProcessorFactory.cs @@ -42,7 +42,12 @@ public MySQLParameterBasedSqlProcessorFactory(RelationalParameterBasedSqlProcess _options = options; } +#if NET9_0 + public RelationalParameterBasedSqlProcessor Create(RelationalParameterBasedSqlProcessorParameters parameters) + => new MySQLParameterBasedSqlProcessor(_dependencies, parameters, _options); +#else public virtual RelationalParameterBasedSqlProcessor Create(bool useRelationalNulls) => new MySQLParameterBasedSqlProcessor(_dependencies, useRelationalNulls, _options); +#endif } } diff --git a/EFCore/src/Query/Internal/MySQLSqlExpressionFactory.cs b/EFCore/src/Query/Internal/MySQLSqlExpressionFactory.cs index bd440a1f1..048670b14 100644 --- a/EFCore/src/Query/Internal/MySQLSqlExpressionFactory.cs +++ b/EFCore/src/Query/Internal/MySQLSqlExpressionFactory.cs @@ -141,11 +141,18 @@ public MySQLCollateExpression Collate( string charset, string collation) => (MySQLCollateExpression)ApplyDefaultTypeMapping( +#if NET9_0 + new MySQLCollateExpression( + valueExpression, + collation) +#else new MySQLCollateExpression( valueExpression, charset, collation, - null)); + null) +#endif + ); public virtual MySQLBinaryExpression MySqlIntegerDivide( SqlExpression left, @@ -287,11 +294,15 @@ private MySQLCollateExpression ApplyTypeMappingOnCollate(MySQLCollateExpression var inferredTypeMapping = ExpressionExtensions.InferTypeMapping(collateExpression.ValueExpression) ?? _typeMappingSource.FindMapping(collateExpression.ValueExpression.Type); +#if NET9_0 + return new MySQLCollateExpression(collateExpression.ValueExpression, collateExpression.Collation); +#else return new MySQLCollateExpression( ApplyTypeMapping(collateExpression.ValueExpression, inferredTypeMapping), collateExpression.Charset, collateExpression.Collation, inferredTypeMapping ?? collateExpression.TypeMapping); +#endif } private SqlExpression ApplyTypeMappingOnRegexp(MySQLRegexpExpression regexpExpression) diff --git a/EFCore/src/Query/Internal/MySQLSqlNullabilityProcessor.cs b/EFCore/src/Query/Internal/MySQLSqlNullabilityProcessor.cs index 936cff59f..28a37ed98 100644 --- a/EFCore/src/Query/Internal/MySQLSqlNullabilityProcessor.cs +++ b/EFCore/src/Query/Internal/MySQLSqlNullabilityProcessor.cs @@ -37,6 +37,8 @@ internal class MySQLSqlNullabilityProcessor : SqlNullabilityProcessor { private readonly ISqlExpressionFactory _sqlExpressionFactory; + +#if !NET9_0 /// /// Creates a new instance of the . /// @@ -47,7 +49,18 @@ public MySQLSqlNullabilityProcessor( bool useRelationalNulls) : base(dependencies, useRelationalNulls) => _sqlExpressionFactory = dependencies.SqlExpressionFactory; - +#else + /// + /// Creates a new instance of the . + /// + /// Parameter object containing dependencies for this class. + /// Parameter object containing parameters for this class. + public MySQLSqlNullabilityProcessor( + RelationalParameterBasedSqlProcessorDependencies dependencies, + RelationalParameterBasedSqlProcessorParameters parameters) + : base(dependencies, parameters) + => _sqlExpressionFactory = dependencies.SqlExpressionFactory; +#endif /// protected override SqlExpression VisitCustomSqlExpression( SqlExpression sqlExpression, bool allowOptimizedExpansion, out bool nullable) diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/MySql.EntityFrameworkCore.Basic.Tests.csproj b/EFCore/tests/MySql.EFCore.Basic.Tests/MySql.EntityFrameworkCore.Basic.Tests.csproj index 3a15f0496..7edc26f6f 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/MySql.EntityFrameworkCore.Basic.Tests.csproj +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/MySql.EntityFrameworkCore.Basic.Tests.csproj @@ -2,7 +2,7 @@ MySql.EntityFrameworkCore.Basic.Tests Class Library - net6.0;net8.0; + net9.0;net6.0;net8.0; MySql.EntityFrameworkCore.Basic.Tests MySql.EntityFrameworkCore.Basic.Tests true @@ -14,7 +14,7 @@ - net9.0;$(TargetFrameworks) + @@ -26,7 +26,7 @@ - + diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/Utils/MySqlTestStore.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/Utils/MySqlTestStore.cs index 5e807de8e..1cbdf19c8 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/Utils/MySqlTestStore.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/Utils/MySqlTestStore.cs @@ -34,6 +34,7 @@ using MySql.EntityFrameworkCore.Infrastructure.Internal; using System; using System.Data; +using System.Data.Common; namespace MySql.EntityFrameworkCore.Basic.Tests.Utils { @@ -225,21 +226,42 @@ public static void DeleteDatabase(string name) public override DbContextOptionsBuilder AddProviderOptions(DbContextOptionsBuilder builder) => builder.UseMySQL(GetContextConnectionString()); +#if NET9_0 + public virtual void Clean(DbContext context) + => context.Database.EnsureDeleted(); +#else public override void Clean(DbContext context) => context.Database.EnsureDeleted(); +#endif - public static MySQLTestStore Create(string name) - => new MySQLTestStore(name); - public static MySQLTestStore GetOrCreate(string name) - => new MySQLTestStore(name); +#if NET9_0 + private MySQLTestStore(string name, DbConnection connection) + : base(name, true, connection) + { + SslMode = true; + connection = new MySqlConnection(RootConnectionString); + } + public static MySQLTestStore Create(string name, DbConnection connection) + => new MySQLTestStore(name, connection); + + public static MySQLTestStore GetOrCreate(string name, DbConnection connection) + => new MySQLTestStore(name, connection); +#else private MySQLTestStore(string name) : base(name, true) { SslMode = true; Connection = new MySqlConnection(RootConnectionString); } + + public static MySQLTestStore Create(string name) + => new MySQLTestStore(name); + + public static MySQLTestStore GetOrCreate(string name) + => new MySQLTestStore(name); +#endif } public class MySQLTestStoreFactory : RelationalTestStoreFactory @@ -250,13 +272,25 @@ protected MySQLTestStoreFactory() { } +#if NET9_0 + public override TestStore Create(string storeName) + => MySQLTestStore.Create(storeName, new MySqlConnection(MySQLTestStore.RootConnectionString)); + + public override TestStore GetOrCreate(string storeName) + => MySQLTestStore.GetOrCreate(storeName, new MySqlConnection(MySQLTestStore.RootConnectionString)); +#else public override TestStore Create(string storeName) => MySQLTestStore.Create(storeName); public override TestStore GetOrCreate(string storeName) => MySQLTestStore.GetOrCreate(storeName); +#endif + + + public override IServiceCollection AddProviderServices(IServiceCollection serviceCollection) => serviceCollection.AddEntityFrameworkMySQL(); + } } diff --git a/EFCore/tests/MySql.EFCore.Design.Tests/MySql.EntityFrameworkCore.Design.Tests.csproj b/EFCore/tests/MySql.EFCore.Design.Tests/MySql.EntityFrameworkCore.Design.Tests.csproj index 83fe6a293..eaf4fc58c 100644 --- a/EFCore/tests/MySql.EFCore.Design.Tests/MySql.EntityFrameworkCore.Design.Tests.csproj +++ b/EFCore/tests/MySql.EFCore.Design.Tests/MySql.EntityFrameworkCore.Design.Tests.csproj @@ -2,7 +2,7 @@ MySql.EntityFrameworkCore.Design.Tests Class Library - net6.0;net8.0; + net9.0;net6.0;net8.0; MySql.EntityFrameworkCore.Design.Tests MySql.EntityFrameworkCore.Design.Tests true @@ -14,7 +14,7 @@ - net9.0;$(TargetFrameworks) + @@ -42,7 +42,7 @@ - + diff --git a/EFCore/tests/MySql.EFCore.Migrations.Tests/MySql.EntityFrameworkCore.Migrations.Tests.csproj b/EFCore/tests/MySql.EFCore.Migrations.Tests/MySql.EntityFrameworkCore.Migrations.Tests.csproj index 9d357b0b8..d99143584 100644 --- a/EFCore/tests/MySql.EFCore.Migrations.Tests/MySql.EntityFrameworkCore.Migrations.Tests.csproj +++ b/EFCore/tests/MySql.EFCore.Migrations.Tests/MySql.EntityFrameworkCore.Migrations.Tests.csproj @@ -2,7 +2,7 @@ MySql.EntityFrameworkCore.Migrations.Tests Class Library - net6.0;net8.0; + net9.0;net6.0;net8.0; MySql.EntityFrameworkCore.Migrations.Tests MySql.EntityFrameworkCore.Migrations.Tests true @@ -14,7 +14,7 @@ - net9.0;$(TargetFrameworks) + diff --git a/MySQL.Data/src/MySql.Data.csproj b/MySQL.Data/src/MySql.Data.csproj index e97db2a6f..f27cf88ca 100644 --- a/MySQL.Data/src/MySql.Data.csproj +++ b/MySQL.Data/src/MySql.Data.csproj @@ -8,7 +8,7 @@ 9.2.0 Oracle MySql.Data - netstandard2.0;netstandard2.1;net6.0;net8.0; + netstandard2.0;netstandard2.1;net9.0;net6.0;net8.0; MySql.Data MySql;.NET Connector;MySql Connector/NET;netcore;.Net Core;MySql Conector/Net Core;coreclr;C/NET;C/Net Core Review ReleaseNotes.txt for details. @@ -36,7 +36,7 @@ - net9.0;$(TargetFrameworks) + diff --git a/MySQL.Data/tests/MySql.Data.Tests/MySql.Data.Tests.csproj b/MySQL.Data/tests/MySql.Data.Tests/MySql.Data.Tests.csproj index 827d07e47..d95ee4112 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/MySql.Data.Tests.csproj +++ b/MySQL.Data/tests/MySql.Data.Tests/MySql.Data.Tests.csproj @@ -8,7 +8,7 @@ Oracle Oracle MySql.Data.Tests - net8.0;net6.0; + net9.0;net8.0;net6.0; MySql.Data.Tests MySql;.NET Connector;MySql Connector/NET;netcore;.Net Core;MySql Conector/Net Core;coreclr;C/NET;C/Net Core http://www.mysql.com/common/logos/logo-mysql-170x115.png @@ -29,7 +29,7 @@ - net9.0;$(TargetFrameworks) + diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/MySqlX.Data.Tests.csproj b/MySQL.Data/tests/MySqlX.Data.Tests/MySqlX.Data.Tests.csproj index 42f7c6eb3..3d856a042 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/MySqlX.Data.Tests.csproj +++ b/MySQL.Data/tests/MySqlX.Data.Tests/MySqlX.Data.Tests.csproj @@ -8,7 +8,7 @@ Oracle Oracle MySql.Data.Tests - net8.0;net6.0; + net9.0;net8.0;net6.0; MySqlx.Data.Tests MySql;.NET Connector;MySql Connector/NET;netcore;.Net Core;MySql Conector/Net Core;coreclr;C/NET;C/Net Core http://www.mysql.com/common/logos/logo-mysql-170x115.png @@ -29,7 +29,7 @@ - net9.0;$(TargetFrameworks) + From 1e0ca06dcf2e42860cc88fbd4353c23afaa7dc28 Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Sat, 9 Nov 2024 19:57:27 -0700 Subject: [PATCH 083/125] WL#16654 [Remove support for .NET 6 and EF Core 6] Change-Id: Id9478e25c63986ec147dfbf8b8120c9b64115999 --- CHANGES | 3 +- .../Internal/MySQLMigrationsModelDiffer.cs | 39 +--- EFCore/src/MySql.EntityFrameworkCore.csproj | 7 +- EFCore/src/Properties/AssemblyInfo.cs | 6 +- .../MySQLParameterBasedSqlProcessor.cs | 15 +- EFCore/src/Update/IMySQLUpdateSqlGenerator.cs | 10 - .../Update/MySQLModificationCommandBatch.cs | 147 +------------- EFCore/src/Update/MySQLUpdateSqlGenerator.cs | 180 ------------------ ...Sql.EntityFrameworkCore.Basic.Tests.csproj | 6 +- ...ql.EntityFrameworkCore.Design.Tests.csproj | 6 +- ...ntityFrameworkCore.Migrations.Tests.csproj | 2 +- MySQL.Data/src/MySql.Data.csproj | 4 +- .../MySql.Data.Tests/MySql.Data.Tests.csproj | 4 +- .../MySqlX.Data.Tests.csproj | 4 +- 14 files changed, 17 insertions(+), 416 deletions(-) diff --git a/CHANGES b/CHANGES index b5957b9ea..8f91d1710 100644 --- a/CHANGES +++ b/CHANGES @@ -1,5 +1,6 @@ 9.2.0 - Added support for .NET 9 and EF Core 9 GA versions (WL16638). +- Removed support for .NET 6 and EFCore 6 (WL16654). 9.1.0 @@ -525,4 +526,4 @@ - Support for MySqlX.Session and NodeSession objects in new Dev API. - Support for Collection and Documents objects new Dev API. - Support for Relational tables in new Dev API. -- Support for Transactions in new Dev API. \ No newline at end of file +- Support for Transactions in new Dev API. diff --git a/EFCore/src/Migrations/Internal/MySQLMigrationsModelDiffer.cs b/EFCore/src/Migrations/Internal/MySQLMigrationsModelDiffer.cs index 3c02ec2ed..809da75ae 100644 --- a/EFCore/src/Migrations/Internal/MySQLMigrationsModelDiffer.cs +++ b/EFCore/src/Migrations/Internal/MySQLMigrationsModelDiffer.cs @@ -44,44 +44,7 @@ namespace MySql.EntityFrameworkCore.Migrations.Internal internal class MySQLMigrationsModelDiffer : MigrationsModelDiffer { -#if NET6_0 - public MySQLMigrationsModelDiffer( - [NotNull] IRelationalTypeMappingSource typeMappingSource, - [NotNull] IMigrationsAnnotationProvider migrationsAnnotations, - [NotNull] IChangeDetector changeDetector, - [NotNull] IUpdateAdapterFactory updateAdapterFactory, - [NotNull] CommandBatchPreparerDependencies commandBatchPreparerDependencies) - : base( - typeMappingSource, - migrationsAnnotations, - changeDetector, - updateAdapterFactory, - commandBatchPreparerDependencies) - { - } - - protected override IEnumerable Add(IColumn target, DiffContext diffContext, bool inline = false) - { - var _property = target.PropertyMappings.ToArray().FirstOrDefault()!.Property; - if (_property.FindTypeMapping() is RelationalTypeMapping storeType) - { - var valueGenerationStrategy = MySQLValueGenerationStrategyCompatibility.GetValueGenerationStrategy(MigrationsAnnotations.ForRemove(target).ToArray()); - // Ensure that null will be set for the columns default value, if CURRENT_TIMESTAMP has been required, - // or when the store type of the column does not support default values at all. - inline = inline || - (storeType.StoreTypeNameBase == "datetime" || - storeType.StoreTypeNameBase == "timestamp") && - (valueGenerationStrategy == MySQLValueGenerationStrategy.IdentityColumn || - valueGenerationStrategy == MySQLValueGenerationStrategy.ComputedColumn) || - storeType.StoreTypeNameBase.Contains("text") || - storeType.StoreTypeNameBase.Contains("blob") || - storeType.StoreTypeNameBase == "geometry" || - storeType.StoreTypeNameBase == "json"; - } - return base.Add(target, diffContext, inline); - } - -#elif NET8_0 +#if NET8_0 public MySQLMigrationsModelDiffer( [NotNull] IRelationalTypeMappingSource typeMappingSource, [NotNull] IMigrationsAnnotationProvider migrationsAnnotations, diff --git a/EFCore/src/MySql.EntityFrameworkCore.csproj b/EFCore/src/MySql.EntityFrameworkCore.csproj index b2e9a5f12..4a6f45014 100644 --- a/EFCore/src/MySql.EntityFrameworkCore.csproj +++ b/EFCore/src/MySql.EntityFrameworkCore.csproj @@ -10,7 +10,7 @@ GPL-2.0-only WITH Universal-FOSS-exception-1.0 true 13.0 - net9.0;net6.0;net8.0; + net9.0;net8.0; MySql.EntityFrameworkCore MySql.EntityFrameworkCore enable @@ -34,11 +34,6 @@ - - - - - diff --git a/EFCore/src/Properties/AssemblyInfo.cs b/EFCore/src/Properties/AssemblyInfo.cs index 9e1f85f5f..a831a6807 100644 --- a/EFCore/src/Properties/AssemblyInfo.cs +++ b/EFCore/src/Properties/AssemblyInfo.cs @@ -37,13 +37,11 @@ // set of attributes. Change these attribute values to modify the information // associated with an assembly. [assembly: AssemblyTitle("MySql.EntityFrameworkCore")] -[assembly: AssemblyDescription("MySql.EntityFrameworkCore adds support for Microsoft Entity Framework Core (EF Core) 6, 7, 8 and 9.")] +[assembly: AssemblyDescription("MySql.EntityFrameworkCore adds support for Microsoft Entity Framework Core (EF Core) 8 and 9.")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Oracle Corporation")] [assembly: AssemblyProduct("MySQL Connector/NET")] -#if NET6_0 -[assembly: AssemblyCopyright("Copyright © 2021, 2024, Oracle and/or its affiliates.")] -#elif NET8_0 +#if NET8_0 [assembly: AssemblyCopyright("Copyright © 2024, Oracle and/or its affiliates.")] #elif NET9_0 [assembly: AssemblyCopyright("Copyright © 2024, Oracle and/or its affiliates.")] diff --git a/EFCore/src/Query/Internal/MySQLParameterBasedSqlProcessor.cs b/EFCore/src/Query/Internal/MySQLParameterBasedSqlProcessor.cs index 28ec64a92..6e0cf9b01 100644 --- a/EFCore/src/Query/Internal/MySQLParameterBasedSqlProcessor.cs +++ b/EFCore/src/Query/Internal/MySQLParameterBasedSqlProcessor.cs @@ -60,20 +60,7 @@ public MySQLParameterBasedSqlProcessor( #endif /// -#if NET6_0 - protected override SelectExpression ProcessSqlNullability( - SelectExpression selectExpression, IReadOnlyDictionary parametersValues, out bool canCache) - { - Check.NotNull(selectExpression, nameof(selectExpression)); - Check.NotNull(parametersValues, nameof(parametersValues)); - - selectExpression = new MySQLSqlNullabilityProcessor(Dependencies, UseRelationalNulls).Process(selectExpression, parametersValues, out canCache); - - selectExpression = (SelectExpression)new MySQLCompatibilityExpressionVisitor(_options).Visit(selectExpression); - - return selectExpression; - } -#elif NET8_0 +#if NET8_0 protected override Expression ProcessSqlNullability( Expression selectExpression, IReadOnlyDictionary parametersValues, out bool canCache) { diff --git a/EFCore/src/Update/IMySQLUpdateSqlGenerator.cs b/EFCore/src/Update/IMySQLUpdateSqlGenerator.cs index 8b396ecfc..905cec451 100644 --- a/EFCore/src/Update/IMySQLUpdateSqlGenerator.cs +++ b/EFCore/src/Update/IMySQLUpdateSqlGenerator.cs @@ -34,15 +34,6 @@ namespace MySql.EntityFrameworkCore.Update { -#if NET6_0 - internal interface IMySQLUpdateSqlGenerator : IUpdateSqlGenerator - { - ResultSetMapping AppendBulkInsertOperation( - [NotNull] StringBuilder commandStringBuilder, - [NotNull] IReadOnlyList modificationCommands, - int commandPosition); - } -#elif NET8_0_OR_GREATER ///
/// /// The service lifetime is . This means a single instance @@ -70,6 +61,5 @@ ResultSetMapping AppendBulkInsertOperation( int commandPosition) => AppendBulkInsertOperation(commandStringBuilder, modificationCommands, commandPosition, out _); } -#endif } diff --git a/EFCore/src/Update/MySQLModificationCommandBatch.cs b/EFCore/src/Update/MySQLModificationCommandBatch.cs index bcf6df3b9..8e238c2dd 100644 --- a/EFCore/src/Update/MySQLModificationCommandBatch.cs +++ b/EFCore/src/Update/MySQLModificationCommandBatch.cs @@ -49,158 +49,14 @@ internal class MySQLModificationCommandBatch : AffectedCountModificationCommandB private const int DefaultNetworkPacketSizeBytes = 4096; private const int MaxScriptLength = 65536 * DefaultNetworkPacketSizeBytes / 2; private const int MaxParameterCount = 2100; -#if NET6_0 - private const int MaxRowCount = 1000; - private int _parameterCount = 1; // Implicit parameter for the command text - private readonly int _maxBatchSize; - private readonly List _bulkInsertCommands = new List(); - private int _commandsLeftToLengthCheck = 50; -#elif NET8_0_OR_GREATER private readonly List _pendingBulkInsertCommands = new(); -#endif + protected new virtual IMySQLUpdateSqlGenerator UpdateSqlGenerator => (IMySQLUpdateSqlGenerator)base.UpdateSqlGenerator; -#if NET6_0 - public MySQLModificationCommandBatch( - [NotNull] ModificationCommandBatchFactoryDependencies dependencies, - int? maxBatchSize) - : base(dependencies) - { - if (maxBatchSize.HasValue - && maxBatchSize.Value <= 0) - { - throw new ArgumentOutOfRangeException(nameof(maxBatchSize), RelationalStrings.InvalidMaxBatchSize(maxBatchSize)); - } - - _maxBatchSize = Math.Min(maxBatchSize ?? int.MaxValue, MaxRowCount); - } - - protected override bool CanAddCommand(IReadOnlyModificationCommand modificationCommand) - { - if (ModificationCommands.Count >= _maxBatchSize) - { - return false; - } - - var additionalParameterCount = CountParameters(modificationCommand); - - if (_parameterCount + additionalParameterCount >= MaxParameterCount) - { - return false; - } - - _parameterCount += additionalParameterCount; - return true; - } - - private static int CountParameters(IReadOnlyModificationCommand modificationCommand) - { - var parameterCount = 0; - - foreach (var columnModification in modificationCommand.ColumnModifications) - { - if (columnModification.UseCurrentValueParameter) - { - parameterCount++; - } - - if (columnModification.UseOriginalValueParameter) - { - parameterCount++; - } - } - - return parameterCount; - } - - /// - protected override bool IsCommandTextValid() - { - if (--_commandsLeftToLengthCheck < 0) - { - var commandTextLength = GetCommandText().Length; - if (commandTextLength >= MaxScriptLength) - { - return false; - } - - var averageCommandLength = commandTextLength / ModificationCommands.Count; - var expectedAdditionalCommandCapacity = (MaxScriptLength - commandTextLength) / averageCommandLength; - _commandsLeftToLengthCheck = Math.Max(1, expectedAdditionalCommandCapacity / 4); - } - - return true; - } - - /// - protected override int GetParameterCount() - => _parameterCount; - - /// - protected override void ResetCommandText() - { - base.ResetCommandText(); - _bulkInsertCommands.Clear(); - } - - /// - protected override string GetCommandText() - => base.GetCommandText() + GetBulkInsertCommandText(ModificationCommands.Count); - - private string GetBulkInsertCommandText(int lastIndex) - { - if (_bulkInsertCommands.Count == 0) - { - return string.Empty; - } - - var stringBuilder = new StringBuilder(); - var resultSetMapping = UpdateSqlGenerator.AppendBulkInsertOperation( - stringBuilder, _bulkInsertCommands, lastIndex - _bulkInsertCommands.Count); - for (var i = lastIndex - _bulkInsertCommands.Count; i < lastIndex; i++) - { - CommandResultSet[i] = resultSetMapping; - } - - if (resultSetMapping != ResultSetMapping.NoResultSet) - { - CommandResultSet[lastIndex - 1] = ResultSetMapping.LastInResultSet; - } - - return stringBuilder.ToString(); - } - - /// - protected override void UpdateCachedCommandText(int commandPosition) - { - var newModificationCommand = ModificationCommands[commandPosition]; - if (newModificationCommand.EntityState == EntityState.Added) - { - if (_bulkInsertCommands.Count > 0 - && !CanBeInsertedInSameStatement(_bulkInsertCommands[0], (ModificationCommand)newModificationCommand)) - { - CachedCommandText.Append(GetBulkInsertCommandText(commandPosition)); - _bulkInsertCommands.Clear(); - } - - _bulkInsertCommands.Add((ModificationCommand)newModificationCommand); - - LastCachedCommandIndex = commandPosition; - } - else - { - CachedCommandText.Append(GetBulkInsertCommandText(commandPosition)); - _bulkInsertCommands.Clear(); - - base.UpdateCachedCommandText(commandPosition); - } - } - -#elif NET8_0_OR_GREATER /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to /// the same compatibility standards as public APIs. It may be changed or removed without notice in @@ -322,7 +178,6 @@ public override async Task ExecuteAsync(IRelationalConnection connection, Cancel throw new DbUpdateException(MySQLStrings.SaveChangesFailed, e.InnerException, e.Entries); } } -#endif private static bool CanBeInsertedInSameStatement( diff --git a/EFCore/src/Update/MySQLUpdateSqlGenerator.cs b/EFCore/src/Update/MySQLUpdateSqlGenerator.cs index b7e5431ec..cc01124ed 100644 --- a/EFCore/src/Update/MySQLUpdateSqlGenerator.cs +++ b/EFCore/src/Update/MySQLUpdateSqlGenerator.cs @@ -57,183 +57,6 @@ public MySQLUpdateSqlGenerator([NotNull] UpdateSqlGeneratorDependencies dependen { } -#if NET6_0 - public virtual ResultSetMapping AppendBulkInsertOperation( - StringBuilder commandStringBuilder, - IReadOnlyList modificationCommands, - int commandPosition) - { - var table = StoreObjectIdentifier.Table(modificationCommands[0].TableName, modificationCommands[0].Schema); - if (modificationCommands.Count == 1 - && modificationCommands[0].ColumnModifications.All( - o => !o.IsKey - || !o.IsRead - || o.Property?.GetValueGenerationStrategy(table) == MySQLValueGenerationStrategy.IdentityColumn)) - { - return AppendInsertOperation(commandStringBuilder, modificationCommands[0], commandPosition); - } - - var readOperations = modificationCommands[0].ColumnModifications.Where(o => o.IsRead).ToList(); - var writeOperations = modificationCommands[0].ColumnModifications.Where(o => o.IsWrite).ToList(); - var keyOperations = modificationCommands[0].ColumnModifications.Where(o => o.IsKey).ToList(); - - var defaultValuesOnly = writeOperations.Count == 0; - var nonIdentityOperations = modificationCommands[0].ColumnModifications - .Where(o => o.Property?.GetValueGenerationStrategy(table) != MySQLValueGenerationStrategy.IdentityColumn) - .ToList(); - - if (defaultValuesOnly) - { - if (nonIdentityOperations.Count == 0 || readOperations.Count == 0) - { - foreach (var modification in modificationCommands) - { - AppendInsertOperation(commandStringBuilder, modification, commandPosition); - } - - return readOperations.Count == 0 - ? ResultSetMapping.NoResultSet - : ResultSetMapping.LastInResultSet; - } - - if (nonIdentityOperations.Count > 1) - { - nonIdentityOperations = new List { nonIdentityOperations.First() }; - } - } - - if (readOperations.Count == 0) - { - return AppendBulkInsertWithoutServerValues(commandStringBuilder, modificationCommands, writeOperations); - } - - foreach (var modification in modificationCommands) - { - AppendInsertOperation(commandStringBuilder, modification, commandPosition); - } - - return ResultSetMapping.LastInResultSet; - } - - private ResultSetMapping AppendBulkInsertWithoutServerValues( - StringBuilder commandStringBuilder, - IReadOnlyList modificationCommands, - List writeOperations) - { - Debug.Assert(writeOperations.Count > 0); - - var name = modificationCommands[0].TableName; - var schema = modificationCommands[0].Schema; - - AppendInsertCommandHeader(commandStringBuilder, name, schema, writeOperations); - AppendValuesHeader(commandStringBuilder, writeOperations); - AppendValues(commandStringBuilder, string.Empty, null, writeOperations); - for (var i = 1; i < modificationCommands.Count; i++) - { - commandStringBuilder.Append(",").AppendLine(); - AppendValues(commandStringBuilder, string.Empty, null, modificationCommands[i].ColumnModifications.Where(o => o.IsWrite).ToList()); - } - commandStringBuilder.Append(SqlGenerationHelper.StatementTerminator).AppendLine(); - - return ResultSetMapping.NoResultSet; - } - - protected override void AppendInsertCommandHeader( - [NotNull] StringBuilder commandStringBuilder, - [NotNull] string name, - string? schema, - [NotNull] IReadOnlyList operations) - { - Check.NotNull(commandStringBuilder, nameof(commandStringBuilder)); - Check.NotEmpty(name, nameof(name)); - Check.NotNull(operations, nameof(operations)); - - base.AppendInsertCommandHeader(commandStringBuilder, name, schema, operations); - - if (operations.Count <= 0) - { - commandStringBuilder.Append(" ()"); - } - } - - protected override void AppendValuesHeader( - [NotNull] StringBuilder commandStringBuilder, - [NotNull] IReadOnlyList operations) - { - Check.NotNull(commandStringBuilder, nameof(commandStringBuilder)); - Check.NotNull(operations, nameof(operations)); - - commandStringBuilder.AppendLine(); - commandStringBuilder.Append("VALUES "); - } - - protected override void AppendValues( - [NotNull] StringBuilder commandStringBuilder, - [NotNull] string name, - string? schema, - [NotNull] IReadOnlyList operations) - { - base.AppendValues(commandStringBuilder, name, schema, operations); - - if (operations.Count <= 0) - { - commandStringBuilder.Append("()"); - } - } - - protected override void AppendIdentityWhereCondition(StringBuilder commandStringBuilder, IColumnModification columnModification) - { - Check.NotNull(columnModification, "columnModification"); - Check.NotNull(commandStringBuilder, "commandStringBuilder"); - commandStringBuilder.AppendFormat("{0} = LAST_INSERT_ID()", SqlGenerationHelper.DelimitIdentifier(columnModification.ColumnName)); - } - - protected override void AppendRowsAffectedWhereCondition(StringBuilder commandStringBuilder, int expectedRowsAffected) - { - Check.NotNull(commandStringBuilder, "commandStringBuilder"); - commandStringBuilder - .Append("ROW_COUNT() = " + expectedRowsAffected.ToString(CultureInfo.InvariantCulture)); - } - - protected override ResultSetMapping AppendSelectAffectedCountCommand(StringBuilder commandStringBuilder, string name, string? schemaName, int commandPosition) - { - Check.NotNull(commandStringBuilder, "commandStringBuilder"); - Check.NotEmpty(name, "name"); - - commandStringBuilder - .Append("SELECT ROW_COUNT()") - .Append(SqlGenerationHelper.StatementTerminator).AppendLine() - .AppendLine(); - - return ResultSetMapping.LastInResultSet; - } - - protected override void AppendWhereAffectedClause( - [NotNull] StringBuilder commandStringBuilder, - [NotNull] IReadOnlyList operations) - { - Check.NotNull(commandStringBuilder, nameof(commandStringBuilder)); - Check.NotNull(operations, nameof(operations)); - - var nonDefaultOperations = operations - .Where( - o => !o.IsKey || - !o.IsRead || - o.Property == null || - !o.Property.ValueGenerated.HasFlag(ValueGenerated.OnAdd) || - MySQLPropertyExtensions.IsCompatibleAutoIncrementColumn(o.Property)) - .ToList() - .AsReadOnly(); - - base.AppendWhereAffectedClause(commandStringBuilder, nonDefaultOperations); - } - - internal enum ResultsGrouping - { - OneResultSet, - OneCommandPerResultSet - } -#elif NET8_0_OR_GREATER public virtual ResultSetMapping AppendBulkInsertOperation( StringBuilder commandStringBuilder, IReadOnlyList modificationCommands, @@ -585,8 +408,5 @@ private void AppendIdentityWhereCondition(StringBuilder commandStringBuilder, IC Check.NotNull(commandStringBuilder, "commandStringBuilder"); commandStringBuilder.AppendFormat("{0} = LAST_INSERT_ID()", SqlGenerationHelper.DelimitIdentifier(columnModification.ColumnName)); } -#endif - - } } diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/MySql.EntityFrameworkCore.Basic.Tests.csproj b/EFCore/tests/MySql.EFCore.Basic.Tests/MySql.EntityFrameworkCore.Basic.Tests.csproj index 7edc26f6f..f406a3fb5 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/MySql.EntityFrameworkCore.Basic.Tests.csproj +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/MySql.EntityFrameworkCore.Basic.Tests.csproj @@ -2,7 +2,7 @@ MySql.EntityFrameworkCore.Basic.Tests Class Library - net9.0;net6.0;net8.0; + net9.0;net8.0; MySql.EntityFrameworkCore.Basic.Tests MySql.EntityFrameworkCore.Basic.Tests true @@ -16,10 +16,6 @@ - - - - diff --git a/EFCore/tests/MySql.EFCore.Design.Tests/MySql.EntityFrameworkCore.Design.Tests.csproj b/EFCore/tests/MySql.EFCore.Design.Tests/MySql.EntityFrameworkCore.Design.Tests.csproj index eaf4fc58c..85a61dbc7 100644 --- a/EFCore/tests/MySql.EFCore.Design.Tests/MySql.EntityFrameworkCore.Design.Tests.csproj +++ b/EFCore/tests/MySql.EFCore.Design.Tests/MySql.EntityFrameworkCore.Design.Tests.csproj @@ -2,7 +2,7 @@ MySql.EntityFrameworkCore.Design.Tests Class Library - net9.0;net6.0;net8.0; + net9.0;net8.0; MySql.EntityFrameworkCore.Design.Tests MySql.EntityFrameworkCore.Design.Tests true @@ -32,10 +32,6 @@ - - - - diff --git a/EFCore/tests/MySql.EFCore.Migrations.Tests/MySql.EntityFrameworkCore.Migrations.Tests.csproj b/EFCore/tests/MySql.EFCore.Migrations.Tests/MySql.EntityFrameworkCore.Migrations.Tests.csproj index d99143584..06039067f 100644 --- a/EFCore/tests/MySql.EFCore.Migrations.Tests/MySql.EntityFrameworkCore.Migrations.Tests.csproj +++ b/EFCore/tests/MySql.EFCore.Migrations.Tests/MySql.EntityFrameworkCore.Migrations.Tests.csproj @@ -2,7 +2,7 @@ MySql.EntityFrameworkCore.Migrations.Tests Class Library - net9.0;net6.0;net8.0; + net9.0;net8.0; MySql.EntityFrameworkCore.Migrations.Tests MySql.EntityFrameworkCore.Migrations.Tests true diff --git a/MySQL.Data/src/MySql.Data.csproj b/MySQL.Data/src/MySql.Data.csproj index f27cf88ca..ac23dd10e 100644 --- a/MySQL.Data/src/MySql.Data.csproj +++ b/MySQL.Data/src/MySql.Data.csproj @@ -8,7 +8,7 @@ 9.2.0 Oracle MySql.Data - netstandard2.0;netstandard2.1;net9.0;net6.0;net8.0; + netstandard2.0;netstandard2.1;net9.0;net8.0; MySql.Data MySql;.NET Connector;MySql Connector/NET;netcore;.Net Core;MySql Conector/Net Core;coreclr;C/NET;C/Net Core Review ReleaseNotes.txt for details. @@ -137,4 +137,4 @@ - \ No newline at end of file + diff --git a/MySQL.Data/tests/MySql.Data.Tests/MySql.Data.Tests.csproj b/MySQL.Data/tests/MySql.Data.Tests/MySql.Data.Tests.csproj index d95ee4112..b0144ddf2 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/MySql.Data.Tests.csproj +++ b/MySQL.Data/tests/MySql.Data.Tests/MySql.Data.Tests.csproj @@ -8,7 +8,7 @@ Oracle Oracle MySql.Data.Tests - net9.0;net8.0;net6.0; + net9.0;net8.0; MySql.Data.Tests MySql;.NET Connector;MySql Connector/NET;netcore;.Net Core;MySql Conector/Net Core;coreclr;C/NET;C/Net Core http://www.mysql.com/common/logos/logo-mysql-170x115.png @@ -138,4 +138,4 @@ - \ No newline at end of file + diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/MySqlX.Data.Tests.csproj b/MySQL.Data/tests/MySqlX.Data.Tests/MySqlX.Data.Tests.csproj index 3d856a042..054e9dda3 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/MySqlX.Data.Tests.csproj +++ b/MySQL.Data/tests/MySqlX.Data.Tests/MySqlX.Data.Tests.csproj @@ -8,7 +8,7 @@ Oracle Oracle MySql.Data.Tests - net9.0;net8.0;net6.0; + net9.0;net8.0; MySqlx.Data.Tests MySql;.NET Connector;MySql Connector/NET;netcore;.Net Core;MySql Conector/Net Core;coreclr;C/NET;C/Net Core http://www.mysql.com/common/logos/logo-mysql-170x115.png @@ -117,4 +117,4 @@ Always - \ No newline at end of file + From 9bdaaaf01ce07cab78aee329bf0b9b3115905dfc Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Sat, 28 Sep 2024 14:38:05 -0600 Subject: [PATCH 084/125] Bug#35240186 [Run inserts in batch command as one block] Change-Id: I6ba904fe2640cc10ae497b9ca011cfee161da8d7 --- CHANGES | 1 + .../src/MySqlConnectionStringBuilder.cs | 13 +++++ MySQL.Data/src/Statement.cs | 7 ++- .../netstandard2_0/MySqlDataAdapterTests.cs | 52 +++++++++++++++++++ 4 files changed, 72 insertions(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index 8f91d1710..37dcf35fa 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,7 @@ 9.2.0 - Added support for .NET 9 and EF Core 9 GA versions (WL16638). - Removed support for .NET 6 and EFCore 6 (WL16654). +- Fixed bug Run inserts in batch command as one block (MySQL Bug #110553, Oracle Bug #35240186). Thanks to Sebastian Schwarzhuber for the contribution. 9.1.0 diff --git a/MySQL.Data/src/MySqlConnectionStringBuilder.cs b/MySQL.Data/src/MySqlConnectionStringBuilder.cs index 273da4e44..f371e6c51 100644 --- a/MySQL.Data/src/MySqlConnectionStringBuilder.cs +++ b/MySQL.Data/src/MySqlConnectionStringBuilder.cs @@ -211,6 +211,7 @@ static MySqlConnectionStringBuilder() (msb, sender, value) => { msb.SetValue("exceptioninterceptors", value); }, (msb, sender) => msb.ExceptionInterceptors)); Options.Add(new MySqlConnectionStringOption("commandinterceptors", "command interceptors", typeof(string), null, false, (msb, sender, value) => { msb.SetValue("commandinterceptors", value); }, (msb, sender) => msb.CommandInterceptors)); + Options.Add(new MySqlConnectionStringOption("rewritebatchedstatements", null, typeof(bool), false, false)); #endregion @@ -864,6 +865,18 @@ public string CommandInterceptors set { SetValue("commandinterceptors", value); } } + /// + /// Gets or sets a boolean indicating if this connection should rewrite batched statements as one block. + /// + [Category("Advanced")] + [DisplayName("Rewrite Batched Statements")] + [Description("Indicates if this connection should rewrite batched statements as one block.")] + public bool RewriteBatchedStatements + { + get { return (bool)values["rewritebatchedstatements"]; } + set { SetValue("rewritebatchedstatements", value); } + } + /// /// Gets or sets the event for the WebauthN callback. /// diff --git a/MySQL.Data/src/Statement.cs b/MySQL.Data/src/Statement.cs index bdddc47b9..5e559af42 100644 --- a/MySQL.Data/src/Statement.cs +++ b/MySQL.Data/src/Statement.cs @@ -181,7 +181,12 @@ protected async Task BindParametersAsync(bool execAsync) //long originalLength = packet.Length - 4; // and attempt to stream the next command - string text = ResolvedCommandText; + string text = ""; + if (Connection.driver.Settings.RewriteBatchedStatements) + text = batchedCmd.BatchableCommandText; + else + text = ResolvedCommandText; + if (text.StartsWith("(", StringComparison.Ordinal)) await packet.WriteStringNoNullAsync(", ", execAsync).ConfigureAwait(false); else diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MySqlDataAdapterTests.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MySqlDataAdapterTests.cs index fa7802e05..2ecdde630 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MySqlDataAdapterTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MySqlDataAdapterTests.cs @@ -31,6 +31,7 @@ using System; using System.Data; using System.Data.Common; +using System.Net; using System.Text; using System.Threading; using System.Threading.Tasks; @@ -722,6 +723,57 @@ public void TestBatchingInsertsMoreThanMaxPacket() Assert.That(dt.Rows[i]["id"], Is.EqualTo(i)); } + /// + /// Bug#35240186 Contribution: Run inserts in batch command as one block + /// + [Test] + [TestCase(true)] + [TestCase(false)] + public void TestBatchingInsertsAllRowsInOneGo(bool rewriteStatements) + { + ExecuteSQL("CREATE TABLE Test (id INT AUTO_INCREMENT, name VARCHAR(20), PRIMARY KEY(id))"); + ExecuteSQL("INSERT INTO Test VALUES (1, 'Test 1')"); + using MySqlConnection conn = new MySqlConnection(Connection.ConnectionString + ";rewritebatchedstatements=" + rewriteStatements.ToString() + ";"); + { + conn.Open(); + bool testing = true; + Console.WriteLine(testing.ToString()); + MySqlDataAdapter da = new MySqlDataAdapter("SELECT * FROM Test", conn); + MySqlCommand ins = new MySqlCommand("INSERT INTO Test (id, name) VALUES (?p1, ?p2)", conn); + da.InsertCommand = ins; + ins.UpdatedRowSource = UpdateRowSource.None; + ins.Parameters.Add("?p1", MySqlDbType.Int32).SourceColumn = "id"; + ins.Parameters.Add("?p2", MySqlDbType.VarChar, 20).SourceColumn = "name"; + + DataTable dt = new DataTable(); + da.Fill(dt); + + for (int i = 1; i <= 3; i++) + { + DataRow row = dt.NewRow(); + row["id"] = DBNull.Value; + row["name"] = "name " + i; + dt.Rows.Add(row); + } + + da.UpdateBatchSize = 0; + da.Update(dt); + MySqlCommand lsid = new MySqlCommand("SELECT LAST_INSERT_ID();", conn); + var lastInsertedId = (ulong)lsid.ExecuteScalar(); + + if (rewriteStatements) + { + //The batched statements are rewritten to be processed all together, that is why the last inserted ID is 2 + Assert.That(lastInsertedId, Is.EqualTo(2)); + } + else + { + //The batched statements are not rewritten, and are processed one by one, in this case the last inserted ID is 4 + Assert.That(lastInsertedId, Is.EqualTo(4)); + } + } + } + [Test] public void FunctionsReturnString() { From e2603d7096418a8fc68454b418d519b98aee53f6 Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Tue, 10 Dec 2024 18:00:35 -0700 Subject: [PATCH 085/125] Updated LIUMS Change-Id: I13da854f6131885ae7c25a7ed520008596ac4734 --- LICENSE | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/LICENSE b/LICENSE index 27bc95437..c353553f9 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ Licensing Information User Manual -MySQL Connector/NET 9.1.0 Community +MySQL Connector/NET 9.2.0 Community __________________________________________________________________ Introduction @@ -8,18 +8,18 @@ Introduction This License Information User Manual contains Oracle's product license and other licensing information, including licensing information for third-party software which may be included in this distribution of - MySQL Connector/NET 9.1.0 Community. + MySQL Connector/NET 9.2.0 Community. - Last updated: September 2024 + Last updated: November 2024 Licensing Information - This release of MySQL Connector/NET 9.1.0 Community is brought to you + This release of MySQL Connector/NET 9.2.0 Community is brought to you by the MySQL team at Oracle. This software is released under version 2 of the GNU General Public License (GPLv2), as set forth below, with the following additional permissions: - This distribution of MySQL Connector/NET 9.1.0 Community is designed to + This distribution of MySQL Connector/NET 9.2.0 Community is designed to work with certain software (including but not limited to OpenSSL) that is licensed under separate terms, as designated in a particular file or component or in the license documentation. Without limiting your rights @@ -1017,4 +1017,4 @@ Written Offer for Source Code that included the binary that is the subject of your request, or b. in the case of code licensed under the GPL v3 for as long as Oracle - offers spare parts or customer support for that product model. + offers spare parts or customer support for that product model. \ No newline at end of file From 78361b73395bad0f4385aa415e082dee9d7fadb6 Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Tue, 10 Dec 2024 18:50:44 -0700 Subject: [PATCH 086/125] Updated copyright year Change-Id: I6a771b844c6ac31839fd101fde71bb351181bd59 --- EFCore/src/Properties/AssemblyInfo.cs | 4 ++-- EntityFramework/src/MySql.Data.EntityFramework.csproj | 2 +- EntityFramework/src/Properties/AssemblyInfo.cs | 2 +- MySQL.Data.OpenTelemetry/src/MySQL.Data.OpenTelemetry.csproj | 2 +- MySQL.Data.OpenTelemetry/src/Properties/AssemblyInfo.cs | 2 +- MySQL.Data/src/MySql.Data.csproj | 2 +- MySQL.Data/src/Properties/AssemblyInfo.cs | 2 +- MySql.Web/src/MySql.Web.csproj | 2 +- MySql.Web/src/Properties/AssemblyInfo.cs | 2 +- README | 2 +- 10 files changed, 11 insertions(+), 11 deletions(-) diff --git a/EFCore/src/Properties/AssemblyInfo.cs b/EFCore/src/Properties/AssemblyInfo.cs index a831a6807..62ca664b2 100644 --- a/EFCore/src/Properties/AssemblyInfo.cs +++ b/EFCore/src/Properties/AssemblyInfo.cs @@ -42,9 +42,9 @@ [assembly: AssemblyCompany("Oracle Corporation")] [assembly: AssemblyProduct("MySQL Connector/NET")] #if NET8_0 -[assembly: AssemblyCopyright("Copyright © 2024, Oracle and/or its affiliates.")] +[assembly: AssemblyCopyright("Copyright © 2025, Oracle and/or its affiliates.")] #elif NET9_0 -[assembly: AssemblyCopyright("Copyright © 2024, Oracle and/or its affiliates.")] +[assembly: AssemblyCopyright("Copyright © 2025, Oracle and/or its affiliates.")] #endif [assembly: AssemblyTrademark("Oracle®, Java, MySQL, and NetSuite are registered trademarks of Oracle and/or its affiliates.")] [assembly: AssemblyCulture("")] diff --git a/EntityFramework/src/MySql.Data.EntityFramework.csproj b/EntityFramework/src/MySql.Data.EntityFramework.csproj index 7852d3988..2f85d431a 100644 --- a/EntityFramework/src/MySql.Data.EntityFramework.csproj +++ b/EntityFramework/src/MySql.Data.EntityFramework.csproj @@ -2,7 +2,7 @@ MySql.Data.EntityFramework - Copyright © 2016, 2024, Oracle and/or its affiliates. + Copyright © 2016, 2025, Oracle and/or its affiliates. en-US 9.2.0 Oracle diff --git a/EntityFramework/src/Properties/AssemblyInfo.cs b/EntityFramework/src/Properties/AssemblyInfo.cs index 795f53733..622e7d7a4 100644 --- a/EntityFramework/src/Properties/AssemblyInfo.cs +++ b/EntityFramework/src/Properties/AssemblyInfo.cs @@ -40,7 +40,7 @@ [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Oracle Corporation")] [assembly: AssemblyProduct("MySQL Connector/NET")] -[assembly: AssemblyCopyright("Copyright © 2008, 2024, Oracle and/or its affiliates.")] +[assembly: AssemblyCopyright("Copyright © 2008, 2025, Oracle and/or its affiliates.")] [assembly: AssemblyTrademark("Oracle®, Java, MySQL, and NetSuite are registered trademarks of Oracle and/or its affiliates.")] [assembly: AssemblyCulture("")] [assembly: SecurityRules(SecurityRuleSet.Level1)] diff --git a/MySQL.Data.OpenTelemetry/src/MySQL.Data.OpenTelemetry.csproj b/MySQL.Data.OpenTelemetry/src/MySQL.Data.OpenTelemetry.csproj index 4d65a1c10..7d8d93231 100644 --- a/MySQL.Data.OpenTelemetry/src/MySQL.Data.OpenTelemetry.csproj +++ b/MySQL.Data.OpenTelemetry/src/MySQL.Data.OpenTelemetry.csproj @@ -2,7 +2,7 @@ MySql.Data.OpenTelemetry - Copyright © 2023, 2024, Oracle and/or its affiliates. + Copyright © 2023, 2025, Oracle and/or its affiliates. en-US 9.2.0 Oracle diff --git a/MySQL.Data.OpenTelemetry/src/Properties/AssemblyInfo.cs b/MySQL.Data.OpenTelemetry/src/Properties/AssemblyInfo.cs index eec58f246..74ae5278a 100644 --- a/MySQL.Data.OpenTelemetry/src/Properties/AssemblyInfo.cs +++ b/MySQL.Data.OpenTelemetry/src/Properties/AssemblyInfo.cs @@ -39,7 +39,7 @@ [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Oracle Corporation")] [assembly: AssemblyProduct("MySQL Connector/NET")] -[assembly: AssemblyCopyright("Copyright � 2023, 2024, Oracle and/or its affiliates.")] +[assembly: AssemblyCopyright("Copyright � 2023, 2025, Oracle and/or its affiliates.")] [assembly: AssemblyTrademark("Oracle�, Java, MySQL, and NetSuite are registered trademarks of Oracle and/or its affiliates.")] [assembly: AssemblyCulture("")] [assembly: SecurityRules(SecurityRuleSet.Level1)] diff --git a/MySQL.Data/src/MySql.Data.csproj b/MySQL.Data/src/MySql.Data.csproj index ac23dd10e..176b7eb93 100644 --- a/MySQL.Data/src/MySql.Data.csproj +++ b/MySQL.Data/src/MySql.Data.csproj @@ -3,7 +3,7 @@ MySql.Data.MySqlClient .Net Core Class Library - Copyright © 2016, 2024, Oracle and/or its affiliates. + Copyright © 2016, 2025, Oracle and/or its affiliates. en-US 9.2.0 Oracle diff --git a/MySQL.Data/src/Properties/AssemblyInfo.cs b/MySQL.Data/src/Properties/AssemblyInfo.cs index 1a1f691c3..04a9e1969 100644 --- a/MySQL.Data/src/Properties/AssemblyInfo.cs +++ b/MySQL.Data/src/Properties/AssemblyInfo.cs @@ -40,7 +40,7 @@ [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Oracle Corporation")] [assembly: AssemblyProduct("MySQL Connector/NET")] -[assembly: AssemblyCopyright("Copyright © 2016, 2024, Oracle and/or its affiliates.")] +[assembly: AssemblyCopyright("Copyright © 2016, 2025, Oracle and/or its affiliates.")] [assembly: AssemblyTrademark("Oracle®, Java, MySQL, and NetSuite are registered trademarks of Oracle and/or its affiliates.")] [assembly: AssemblyCulture("")] [assembly: SecurityRules(SecurityRuleSet.Level1)] diff --git a/MySql.Web/src/MySql.Web.csproj b/MySql.Web/src/MySql.Web.csproj index e6d667f7d..1c47d1d6d 100644 --- a/MySql.Web/src/MySql.Web.csproj +++ b/MySql.Web/src/MySql.Web.csproj @@ -2,7 +2,7 @@ MySql.Web - Copyright © 2016, 2024, Oracle and/or its affiliates. + Copyright © 2016, 2025, Oracle and/or its affiliates. en-US 9.2.0 Oracle diff --git a/MySql.Web/src/Properties/AssemblyInfo.cs b/MySql.Web/src/Properties/AssemblyInfo.cs index 9f1e50067..a621f8972 100644 --- a/MySql.Web/src/Properties/AssemblyInfo.cs +++ b/MySql.Web/src/Properties/AssemblyInfo.cs @@ -39,7 +39,7 @@ [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Oracle Corporation")] [assembly: AssemblyProduct("MySQL Connector/NET")] -[assembly: AssemblyCopyright("Copyright © 2004, 2024, Oracle and/or its affiliates.")] +[assembly: AssemblyCopyright("Copyright © 2004, 2025, Oracle and/or its affiliates.")] [assembly: AssemblyTrademark("Oracle®, Java, MySQL, and NetSuite are registered trademarks of Oracle and/or its affiliates.")] [assembly: AssemblyCulture("")] [assembly: SecurityRules(SecurityRuleSet.Level1)] diff --git a/README b/README index 7fa428330..0a47845c3 100644 --- a/README +++ b/README @@ -1,4 +1,4 @@ -Copyright © 2004, 2024, Oracle and/or its affiliates. +Copyright © 2004, 2025, Oracle and/or its affiliates. This is a release of MySQL Connector/NET, Oracle's fully managed ADO .NET Driver for MySQL. From 9cbfe7f9f9b2654cddc043536bfa23040d916d92 Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Tue, 10 Dec 2024 19:09:44 -0700 Subject: [PATCH 087/125] Updated dependencies versions Change-Id: Icf8f664d4049c68e03b847e71d51d1d274b678ae --- EFCore/src/MySql.EntityFrameworkCore.csproj | 4 ++-- .../MySql.EntityFrameworkCore.Basic.Tests.csproj | 4 +++- .../MySql.EntityFrameworkCore.Design.Tests.csproj | 2 +- EntityFramework/src/MySql.Data.EntityFramework.csproj | 2 +- .../MySql.EntityFramework.Basic.Tests.csproj | 2 +- .../MySql.EntityFramework.CodeFirst.Tests.csproj | 2 +- .../MySql.EntityFramework.Migrations.Tests.csproj | 2 +- 7 files changed, 10 insertions(+), 8 deletions(-) diff --git a/EFCore/src/MySql.EntityFrameworkCore.csproj b/EFCore/src/MySql.EntityFrameworkCore.csproj index 4a6f45014..98a1fb348 100644 --- a/EFCore/src/MySql.EntityFrameworkCore.csproj +++ b/EFCore/src/MySql.EntityFrameworkCore.csproj @@ -35,8 +35,8 @@ - - + + diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/MySql.EntityFrameworkCore.Basic.Tests.csproj b/EFCore/tests/MySql.EFCore.Basic.Tests/MySql.EntityFrameworkCore.Basic.Tests.csproj index f406a3fb5..061239671 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/MySql.EntityFrameworkCore.Basic.Tests.csproj +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/MySql.EntityFrameworkCore.Basic.Tests.csproj @@ -18,7 +18,7 @@ - + @@ -29,6 +29,8 @@ + + diff --git a/EFCore/tests/MySql.EFCore.Design.Tests/MySql.EntityFrameworkCore.Design.Tests.csproj b/EFCore/tests/MySql.EFCore.Design.Tests/MySql.EntityFrameworkCore.Design.Tests.csproj index 85a61dbc7..b63438b20 100644 --- a/EFCore/tests/MySql.EFCore.Design.Tests/MySql.EntityFrameworkCore.Design.Tests.csproj +++ b/EFCore/tests/MySql.EFCore.Design.Tests/MySql.EntityFrameworkCore.Design.Tests.csproj @@ -34,7 +34,7 @@ - + diff --git a/EntityFramework/src/MySql.Data.EntityFramework.csproj b/EntityFramework/src/MySql.Data.EntityFramework.csproj index 2f85d431a..3bf94edc0 100644 --- a/EntityFramework/src/MySql.Data.EntityFramework.csproj +++ b/EntityFramework/src/MySql.Data.EntityFramework.csproj @@ -77,7 +77,7 @@ - + diff --git a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/MySql.EntityFramework.Basic.Tests.csproj b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/MySql.EntityFramework.Basic.Tests.csproj index d9b06a899..cc5342e98 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/MySql.EntityFramework.Basic.Tests.csproj +++ b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/MySql.EntityFramework.Basic.Tests.csproj @@ -44,7 +44,7 @@ - + diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/MySql.EntityFramework.CodeFirst.Tests.csproj b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/MySql.EntityFramework.CodeFirst.Tests.csproj index 8695f22ac..91610f9b1 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/MySql.EntityFramework.CodeFirst.Tests.csproj +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/MySql.EntityFramework.CodeFirst.Tests.csproj @@ -60,7 +60,7 @@ - + diff --git a/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/MySql.EntityFramework.Migrations.Tests.csproj b/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/MySql.EntityFramework.Migrations.Tests.csproj index bb23ccb6e..d880fedad 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/MySql.EntityFramework.Migrations.Tests.csproj +++ b/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/MySql.EntityFramework.Migrations.Tests.csproj @@ -34,7 +34,7 @@ - + From d6ccf0440074f1d74ca554d7c5ce0420d9c8e4dc Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Tue, 10 Dec 2024 21:04:35 -0700 Subject: [PATCH 088/125] Updated documentation Change-Id: I4e8033406d20d13504a224c780a691dbd61e939d --- Documentation/docfx.json | 2 +- Documentation/index.md | 4 ++-- README.md | 4 ++++ Release Notes.txt | 9 ++++----- 4 files changed, 11 insertions(+), 8 deletions(-) diff --git a/Documentation/docfx.json b/Documentation/docfx.json index cd6e78456..349839616 100644 --- a/Documentation/docfx.json +++ b/Documentation/docfx.json @@ -77,7 +77,7 @@ } ], "globalMetadata": { - "_appFooter": "Copyright © 2021, 2024, Oracle and/or its affiliates.", + "_appFooter": "Copyright © 2021, 2025, Oracle and/or its affiliates.", "_appLogoPath": "/images/logo.svg", "_appFaviconPath": "/images/favicon.ico", "_enableSearch": true diff --git a/Documentation/index.md b/Documentation/index.md index 8c681525e..2e7520959 100644 --- a/Documentation/index.md +++ b/Documentation/index.md @@ -1,6 +1,6 @@ ## MySQL Connector/NET and X DevAPI -MySQL Connector/NET 9.1 supports X Protocol, which enables you to use X DevAPI with the .NET language of choice to develop applications that communicate with a MySQL server functioning as a document store, relational database, or both. +MySQL Connector/NET 9.2 supports X Protocol, which enables you to use X DevAPI with the .NET language of choice to develop applications that communicate with a MySQL server functioning as a document store, relational database, or both. To get started, review the following main classes: @@ -16,7 +16,7 @@ For an introduction to X DevAPI concepts, see the [X DevAPI User Guide](https:// ## MySQL Connector/NET -MySQL Connector/NET 9.1 also supports the development of .NET, .NET Core and .NET Framework applications that require secure, high-performance data connectivity with MySQL through the classic protocol. It supports ADO.NET, Entity Framework and various web providers. +MySQL Connector/NET 9.2 also supports the development of .NET, .NET Core and .NET Framework applications that require secure, high-performance data connectivity with MySQL through the classic protocol. It supports ADO.NET, Entity Framework and various web providers. To get started, review the following main classes: diff --git a/README.md b/README.md index ff4709d51..8529fdb9a 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,10 @@ From MySQL Connector/NET 9.0, the driver removes support for .NET 7 and EF Core From MySQL Connector/NET 9.1, the driver adds support for [.NET 9](https://learn.microsoft.com/en-us/dotnet/core/whats-new/dotnet-9/overview/) and [EF Core 9](https://learn.microsoft.com/en-us/ef/core/what-is-new/ef-core-9.0/whatsnew/) preview versions. +From MySQL Connector/NET 9.2, the driver adds support for [.NET 9](https://learn.microsoft.com/en-us/dotnet/core/whats-new/dotnet-9/overview/) and [EF Core 9](https://learn.microsoft.com/en-us/ef/core/what-is-new/ef-core-9.0/whatsnew/) GA versions. + +From MySQL Connector/NET 9.2, the driver removes support for .NET 6 and EF Core 6. + For detailed information please visit the official [MySQL Connector/NET documentation](https://dev.mysql.com/doc/connector-net/en/). ## Licensing diff --git a/Release Notes.txt b/Release Notes.txt index 8ca04ebb3..7d478a2ef 100644 --- a/Release Notes.txt +++ b/Release Notes.txt @@ -1,10 +1,9 @@ -Connector/NET 9.1 Release Notes +Connector/NET 9.2 Release Notes ------------------------------------ Welcome to the release notes for Connector/NET 9.1 -What's new in 9.1 +What's new in 9.2 -------------------- -Connector/NET adds support for .NET 9 and EF Core 9 preview versions. -Connector/NET adds support for OpenID Connect authentication. -Connector/NET now uses constraint model in testsuite. \ No newline at end of file +Connector/NET adds support for .NET 9 and EF Core 9 GA versions. +Connector/NET removes support for .NET6 and EFCore 6. \ No newline at end of file From d4519f16b1c132bcc06aed17b42075833702c429 Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Fri, 6 Dec 2024 12:59:51 -0700 Subject: [PATCH 089/125] Bug#37365939 [Fix failing tests due to server changes] Change-Id: I71571061efeeea01e3cad63aedf51223d9cc6206 --- CHANGES | 1 + MySQL.Data/tests/MySqlX.Data.Tests/SslTests.cs | 16 ++++++++++++++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/CHANGES b/CHANGES index 37dcf35fa..a45f32787 100644 --- a/CHANGES +++ b/CHANGES @@ -2,6 +2,7 @@ - Added support for .NET 9 and EF Core 9 GA versions (WL16638). - Removed support for .NET 6 and EFCore 6 (WL16654). - Fixed bug Run inserts in batch command as one block (MySQL Bug #110553, Oracle Bug #35240186). Thanks to Sebastian Schwarzhuber for the contribution. +- Fixed failing tests due to server changes (Oracle Bug #37365939). 9.1.0 diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/SslTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/SslTests.cs index 500a1453e..d8d9f225b 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/SslTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/SslTests.cs @@ -1463,7 +1463,13 @@ private void AssertTlsConnection(string inputString) { string CommandText1 = "SHOW STATUS LIKE '%Ssl_cipher%';"; string CommandText2 = "show status like '%Ssl_version%';"; - string cipher = "ECDHE-RSA-AES256-GCM-SHA384"; + + string cipher = ""; + if (session.Version.isAtLeast(9, 2, 0)) + cipher = "ECDHE-RSA-AES128-GCM-SHA256"; + else + cipher = "ECDHE-RSA-AES256-GCM-SHA384"; + string tls = "TLSv1.2"; using (var session1 = MySQLX.GetSession(inputString)) { @@ -1478,7 +1484,13 @@ private void AssertTlsConnection(object inputObject) { string CommandText1 = "SHOW STATUS LIKE '%Ssl_cipher%';"; string CommandText2 = "show status like '%Ssl_version%';"; - string cipher = "ECDHE-RSA-AES256-GCM-SHA384"; + + string cipher = ""; + if (session.Version.isAtLeast(9, 2, 0)) + cipher = "ECDHE-RSA-AES128-GCM-SHA256"; + else + cipher = "ECDHE-RSA-AES256-GCM-SHA384"; + string tls = "TLSv1.2"; using (var session1 = MySQLX.GetSession(inputObject)) { From 569d8cfd708f962d340594b94026501e394709f9 Mon Sep 17 00:00:00 2001 From: Swati Gupta Date: Thu, 12 Dec 2024 10:19:10 +0100 Subject: [PATCH 090/125] Updated the LICENSE files --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index c353553f9..bebd4dbf0 100644 --- a/LICENSE +++ b/LICENSE @@ -1017,4 +1017,4 @@ Written Offer for Source Code that included the binary that is the subject of your request, or b. in the case of code licensed under the GPL v3 for as long as Oracle - offers spare parts or customer support for that product model. \ No newline at end of file + offers spare parts or customer support for that product model. From 0947f6a8fc4913e39ef16dfd479a3c04cb4ad5c9 Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Sat, 28 Sep 2024 18:48:15 -0600 Subject: [PATCH 091/125] Bug#36624158 [Fix: MySQLUpdateSqlGenerator to inherit UpdateAndSelectSqlGenerator] Change-Id: Id7fa8f0ceed6ecb42d6ef196692fedafb8ac6b2e --- CHANGES | 1 + EFCore/src/Update/MySQLUpdateSqlGenerator.cs | 25 ++++++++++++++++---- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/CHANGES b/CHANGES index a45f32787..8da3069cc 100644 --- a/CHANGES +++ b/CHANGES @@ -3,6 +3,7 @@ - Removed support for .NET 6 and EFCore 6 (WL16654). - Fixed bug Run inserts in batch command as one block (MySQL Bug #110553, Oracle Bug #35240186). Thanks to Sebastian Schwarzhuber for the contribution. - Fixed failing tests due to server changes (Oracle Bug #37365939). +- Fixed bug Fix: MySQLUpdateSqlGenerator to inherit UpdateAndSelectSqlGenerator (MySQL Bug #115020, Oracle Bug #36624158). Thanks to Hikari Fujioka for the contribution. 9.1.0 diff --git a/EFCore/src/Update/MySQLUpdateSqlGenerator.cs b/EFCore/src/Update/MySQLUpdateSqlGenerator.cs index cc01124ed..c095de786 100644 --- a/EFCore/src/Update/MySQLUpdateSqlGenerator.cs +++ b/EFCore/src/Update/MySQLUpdateSqlGenerator.cs @@ -50,13 +50,14 @@ namespace MySql.EntityFrameworkCore /// This service cannot depend on services registered as . /// /// - internal class MySQLUpdateSqlGenerator : UpdateSqlGenerator, IMySQLUpdateSqlGenerator + internal class MySQLUpdateSqlGenerator : UpdateAndSelectSqlGenerator, IMySQLUpdateSqlGenerator { public MySQLUpdateSqlGenerator([NotNull] UpdateSqlGeneratorDependencies dependencies) : base(dependencies) { } +#if NET8_0_OR_GREATER public virtual ResultSetMapping AppendBulkInsertOperation( StringBuilder commandStringBuilder, IReadOnlyList modificationCommands, @@ -73,7 +74,7 @@ public virtual ResultSetMapping AppendBulkInsertOperation( || !o.IsRead || o.Property?.GetValueGenerationStrategy(table) == MySQLValueGenerationStrategy.IdentityColumn)) { - return AppendInsertOperation(commandStringBuilder, firstCommand, commandPosition, false, out requiresTransaction); + return AppendInsertOperation(commandStringBuilder, firstCommand, commandPosition, out requiresTransaction); } var readOperations = firstCommand.ColumnModifications.Where(o => o.IsRead).ToList(); @@ -114,7 +115,7 @@ public virtual ResultSetMapping AppendBulkInsertOperation( foreach (var modification in modificationCommands) { - AppendInsertOperation(commandStringBuilder, modification, commandPosition, false, out requiresTransaction); + AppendInsertOperation(commandStringBuilder, modification, commandPosition, out requiresTransaction); } return ResultSetMapping.LastInResultSet; @@ -387,7 +388,7 @@ protected override void AppendReturningClause(StringBuilder commandStringBuilder } } - private void AppendRowsAffectedWhereCondition(StringBuilder commandStringBuilder, int expectedRowsAffected) + protected override void AppendRowsAffectedWhereCondition(StringBuilder commandStringBuilder, int expectedRowsAffected) { Check.NotNull(commandStringBuilder, "commandStringBuilder"); commandStringBuilder @@ -402,11 +403,25 @@ private void AppendRowsAffectedWhereCondition(StringBuilder commandStringBuilder protected virtual bool IsIdentityOperation(IColumnModification modification) => modification.IsKey && modification.IsRead; - private void AppendIdentityWhereCondition(StringBuilder commandStringBuilder, IColumnModification columnModification) + protected override void AppendIdentityWhereCondition(StringBuilder commandStringBuilder, IColumnModification columnModification) { Check.NotNull(columnModification, "columnModification"); Check.NotNull(commandStringBuilder, "commandStringBuilder"); commandStringBuilder.AppendFormat("{0} = LAST_INSERT_ID()", SqlGenerationHelper.DelimitIdentifier(columnModification.ColumnName)); } + + protected override ResultSetMapping AppendSelectAffectedCountCommand(StringBuilder commandStringBuilder, string name, string? schemaName, int commandPosition) + { + Check.NotNull(commandStringBuilder, "commandStringBuilder"); + Check.NotEmpty(name, "name"); + + commandStringBuilder + .Append("SELECT ROW_COUNT()") + .Append(SqlGenerationHelper.StatementTerminator).AppendLine() + .AppendLine(); + + return ResultSetMapping.LastInResultSet; + } +#endif } } From 8f69ad3fcd1e8e07ad147a7d9862000d042a6f1a Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Sat, 28 Sep 2024 18:06:01 -0600 Subject: [PATCH 092/125] Bug#36568102 [Fixed NullReferenceException] Change-Id: I10e0aca119293e6a5e84e44bd86eff937d0b4872 --- CHANGES | 1 + MySQL.Data/src/MySQLActivitySource.cs | 9 +++++--- MySQL.Data/tests/MySql.Data.Tests/CmdTests.cs | 11 ++++++++++ MySQL.Data/tests/MySql.Data.Tests/TestBase.cs | 22 +++++++++++++++++++ 4 files changed, 40 insertions(+), 3 deletions(-) diff --git a/CHANGES b/CHANGES index 8da3069cc..3e8018249 100644 --- a/CHANGES +++ b/CHANGES @@ -4,6 +4,7 @@ - Fixed bug Run inserts in batch command as one block (MySQL Bug #110553, Oracle Bug #35240186). Thanks to Sebastian Schwarzhuber for the contribution. - Fixed failing tests due to server changes (Oracle Bug #37365939). - Fixed bug Fix: MySQLUpdateSqlGenerator to inherit UpdateAndSelectSqlGenerator (MySQL Bug #115020, Oracle Bug #36624158). Thanks to Hikari Fujioka for the contribution. +- Fixed bug Fixed NullReferenceException (MySQL Bug #114457, Oracle Bug #36568102). Thanks to Maximilian Bienhüls for the contribution. 9.1.0 diff --git a/MySQL.Data/src/MySQLActivitySource.cs b/MySQL.Data/src/MySQLActivitySource.cs index d156fc6aa..15e9cc665 100644 --- a/MySQL.Data/src/MySQLActivitySource.cs +++ b/MySQL.Data/src/MySQLActivitySource.cs @@ -102,9 +102,12 @@ internal static Activity CommandStart(MySqlCommand command) var settings = command.Connection.Settings; var activity = Activity.Current != null ? Source.StartActivity("SQL Statement", ActivityKind.Client, Activity.Current.Context) : Source.StartActivity("SQL Statement", ActivityKind.Client); - // passing through this attribute will propagate the context into the server - string query_attr = $"00-{Activity.Current.Context.TraceId}-{Activity.Current.Context.SpanId}-00"; - command.Attributes.SetAttribute("traceparent", query_attr); + if (Activity.Current != null) + { + // passing through this attribute will propagate the context into the server + string query_attr = $"00-{Activity.Current.Context.TraceId}-{Activity.Current.Context.SpanId}-00"; + command.Attributes.SetAttribute("traceparent", query_attr); + } activity?.SetTag("db.system", "mysql"); activity?.SetTag("db.name", command.Connection.Database); diff --git a/MySQL.Data/tests/MySql.Data.Tests/CmdTests.cs b/MySQL.Data/tests/MySql.Data.Tests/CmdTests.cs index cc377864e..236252e08 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/CmdTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/CmdTests.cs @@ -179,6 +179,17 @@ public void DeleteTest() Assert.That(Convert.ToInt32(after_cnt), Is.EqualTo(0)); } + #if !NETFRAMEWORK + [Test] + public void ActivityTest() + { + using var cmd = Connection.CreateCommand(); + cmd.CommandText = "SELECT 1;"; + using var _ = TestListener((activity) => Assert.AreEqual("u-cmdtests-0", activity.GetTagItem("db.user"))); + cmd.ExecuteNonQuery(); + } + #endif + [Test] public void CtorTest() { diff --git a/MySQL.Data/tests/MySql.Data.Tests/TestBase.cs b/MySQL.Data/tests/MySql.Data.Tests/TestBase.cs index 80de1b551..8e6894567 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/TestBase.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/TestBase.cs @@ -184,6 +184,28 @@ protected virtual void Cleanup() { } #endregion #region Public Methods + + #if !NETFRAMEWORK + public static ActivityListener TestListener(Action activityCheck) + { + ActivityListener activity_listener = new ActivityListener + { + ShouldListenTo = source => + { + return source.Name == "connector-net"; + }, + ActivityStopped = activity => + { + if (activityCheck != null) + activityCheck(activity); + }, + Sample = (ref ActivityCreationOptions options) => ActivitySamplingResult.AllData, + }; + ActivitySource.AddActivityListener(activity_listener); + return activity_listener; + } + #endif + public MySqlConnection GetConnection(bool asRoot = false) { var s = asRoot ? RootSettings : Settings; From 501e9aa1ca535302cf81b4a42120c352ae6f5792 Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Mon, 21 Oct 2024 18:17:13 -0600 Subject: [PATCH 093/125] Bug#37198051 [MySql.Data.OpenTelemetry dll has a version 0.0.0.0] Change-Id: Id4ed123e7f3ebd9d3a157a48d783b48ac20986cb --- CHANGES | 1 + .../src/MySQL.Data.OpenTelemetry.csproj | 10 +--- .../src/Properties/VersionInfo.cs | 47 +++++++++++++++++++ 3 files changed, 49 insertions(+), 9 deletions(-) create mode 100644 MySQL.Data.OpenTelemetry/src/Properties/VersionInfo.cs diff --git a/CHANGES b/CHANGES index 3e8018249..18a13783a 100644 --- a/CHANGES +++ b/CHANGES @@ -5,6 +5,7 @@ - Fixed failing tests due to server changes (Oracle Bug #37365939). - Fixed bug Fix: MySQLUpdateSqlGenerator to inherit UpdateAndSelectSqlGenerator (MySQL Bug #115020, Oracle Bug #36624158). Thanks to Hikari Fujioka for the contribution. - Fixed bug Fixed NullReferenceException (MySQL Bug #114457, Oracle Bug #36568102). Thanks to Maximilian Bienhüls for the contribution. +- Fixed bug MySql.Data.OpenTelemetry dll has a version 0.0.0.0 (Oracle Bug #37198051). 9.1.0 diff --git a/MySQL.Data.OpenTelemetry/src/MySQL.Data.OpenTelemetry.csproj b/MySQL.Data.OpenTelemetry/src/MySQL.Data.OpenTelemetry.csproj index 7d8d93231..53de7c190 100644 --- a/MySQL.Data.OpenTelemetry/src/MySQL.Data.OpenTelemetry.csproj +++ b/MySQL.Data.OpenTelemetry/src/MySQL.Data.OpenTelemetry.csproj @@ -20,15 +20,7 @@ ..\..\ConnectorNetPublicKey.snk True MySql.Data.OpenTelemetry - false - false - false - false - false - false - false - false - false + false diff --git a/MySQL.Data.OpenTelemetry/src/Properties/VersionInfo.cs b/MySQL.Data.OpenTelemetry/src/Properties/VersionInfo.cs new file mode 100644 index 000000000..8ee3378d9 --- /dev/null +++ b/MySQL.Data.OpenTelemetry/src/Properties/VersionInfo.cs @@ -0,0 +1,47 @@ +// Copyright � 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using System.Reflection; +using System.Resources; + +// +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Revision and Build Numbers +// by using the '*' as shown below: + +[assembly: AssemblyVersion("9.2.0")] +[assembly: AssemblyInformationalVersion("9.2.0.0")] +[assembly: AssemblyFileVersion("9.2.0.0")] +[assembly: NeutralResourcesLanguage("en-US")] + From bd2a066e56dfab3fbe8f7ccb493f5023f23d4072 Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Wed, 30 Oct 2024 20:17:52 -0600 Subject: [PATCH 094/125] Bug#37240118 [Missing VersionInfo file in multiple projects] Change-Id: I5ef748f28e5bc0ffc5c934949fc7b2afc121c357 --- CHANGES | 1 + EFCore/src/MySql.EntityFrameworkCore.csproj | 10 +--- EFCore/src/Properties/VersionInfo.cs | 58 +++++++++++++++++++ .../src/MySql.Data.EntityFramework.csproj | 9 +-- EntityFramework/src/Properties/VersionInfo.cs | 46 +++++++++++++++ .../src/MySQL.Data.OpenTelemetry.csproj | 2 +- MySQL.Data/src/MySql.Data.csproj | 13 +---- MySQL.Data/src/Properties/AssemblyInfo.cs | 2 +- MySQL.Data/src/Properties/VersionInfo.cs | 4 +- MySql.Web/src/MySql.Web.csproj | 9 +-- MySql.Web/src/Properties/VersionInfo.cs | 46 +++++++++++++++ 11 files changed, 162 insertions(+), 38 deletions(-) create mode 100644 EFCore/src/Properties/VersionInfo.cs create mode 100644 EntityFramework/src/Properties/VersionInfo.cs create mode 100644 MySql.Web/src/Properties/VersionInfo.cs diff --git a/CHANGES b/CHANGES index 18a13783a..c9ca4f218 100644 --- a/CHANGES +++ b/CHANGES @@ -6,6 +6,7 @@ - Fixed bug Fix: MySQLUpdateSqlGenerator to inherit UpdateAndSelectSqlGenerator (MySQL Bug #115020, Oracle Bug #36624158). Thanks to Hikari Fujioka for the contribution. - Fixed bug Fixed NullReferenceException (MySQL Bug #114457, Oracle Bug #36568102). Thanks to Maximilian Bienhüls for the contribution. - Fixed bug MySql.Data.OpenTelemetry dll has a version 0.0.0.0 (Oracle Bug #37198051). +- Fixed bug Missing VersionInfo file in multiple projects (Oracle Bug #37240118). 9.1.0 diff --git a/EFCore/src/MySql.EntityFrameworkCore.csproj b/EFCore/src/MySql.EntityFrameworkCore.csproj index 98a1fb348..4c6eb9507 100644 --- a/EFCore/src/MySql.EntityFrameworkCore.csproj +++ b/EFCore/src/MySql.EntityFrameworkCore.csproj @@ -19,15 +19,7 @@ ..\..\ConnectorNetPublicKey.snk true $(NoWarn);CS1591;EF1001;EF9100 - false - false - false - false - false - false - false - false - false + false diff --git a/EFCore/src/Properties/VersionInfo.cs b/EFCore/src/Properties/VersionInfo.cs new file mode 100644 index 000000000..5b4202568 --- /dev/null +++ b/EFCore/src/Properties/VersionInfo.cs @@ -0,0 +1,58 @@ +// Copyright © 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using System.Reflection; +using System.Resources; + +// +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Revision and Build Numbers +// by using the '*' as shown below: + +#if NET6_0 +[assembly: AssemblyVersion("6.0.33")] +[assembly: AssemblyInformationalVersion("6.0.33.0+MySQL9.2.0")] +[assembly: AssemblyFileVersion("6.0.33.0")] +[assembly: NeutralResourcesLanguage("en-US")] +#elif NET8_0 +[assembly: AssemblyVersion("8.0.8")] +[assembly: AssemblyInformationalVersion("8.0.8.0+MySQL9.2.0")] +[assembly: AssemblyFileVersion("8.0.8.0")] +[assembly: NeutralResourcesLanguage("en-US")] +#elif NET9_0 +[assembly: AssemblyVersion("9.0.0")] +[assembly: AssemblyInformationalVersion("9.0.0.0-preview+MySQL9.2.0")] +[assembly: AssemblyFileVersion("9.0.0.0")] +[assembly: NeutralResourcesLanguage("en-US")] +#endif diff --git a/EntityFramework/src/MySql.Data.EntityFramework.csproj b/EntityFramework/src/MySql.Data.EntityFramework.csproj index 3bf94edc0..a441d54d2 100644 --- a/EntityFramework/src/MySql.Data.EntityFramework.csproj +++ b/EntityFramework/src/MySql.Data.EntityFramework.csproj @@ -5,7 +5,7 @@ Copyright © 2016, 2025, Oracle and/or its affiliates. en-US 9.2.0 - Oracle + Oracle Corporation net462;net48; $(NoWarn);CS1591 MySql.Data.EntityFramework @@ -16,12 +16,7 @@ https://dev.mysql.com/downloads/ GPL-2.0-only WITH Universal-FOSS-exception-1.0 true - false - false - false - false - false - false + false diff --git a/EntityFramework/src/Properties/VersionInfo.cs b/EntityFramework/src/Properties/VersionInfo.cs new file mode 100644 index 000000000..b56581caa --- /dev/null +++ b/EntityFramework/src/Properties/VersionInfo.cs @@ -0,0 +1,46 @@ +// Copyright © 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using System.Reflection; +using System.Resources; + +// +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Revision and Build Numbers +// by using the '*' as shown below: + +[assembly: AssemblyVersion("9.2.0")] +[assembly: AssemblyInformationalVersion("9.2.0.0")] +[assembly: AssemblyFileVersion("9.2.0.0")] +[assembly: NeutralResourcesLanguage("en-US")] diff --git a/MySQL.Data.OpenTelemetry/src/MySQL.Data.OpenTelemetry.csproj b/MySQL.Data.OpenTelemetry/src/MySQL.Data.OpenTelemetry.csproj index 53de7c190..2e3a72c00 100644 --- a/MySQL.Data.OpenTelemetry/src/MySQL.Data.OpenTelemetry.csproj +++ b/MySQL.Data.OpenTelemetry/src/MySQL.Data.OpenTelemetry.csproj @@ -5,7 +5,7 @@ Copyright © 2023, 2025, Oracle and/or its affiliates. en-US 9.2.0 - Oracle + Oracle Corporation netstandard2.0 MySql.Data.OpenTelemetry MySql.Data.OpenTelemetry diff --git a/MySQL.Data/src/MySql.Data.csproj b/MySQL.Data/src/MySql.Data.csproj index 176b7eb93..db2a83c0a 100644 --- a/MySQL.Data/src/MySql.Data.csproj +++ b/MySQL.Data/src/MySql.Data.csproj @@ -6,7 +6,7 @@ Copyright © 2016, 2025, Oracle and/or its affiliates. en-US 9.2.0 - Oracle + Oracle Corporation MySql.Data netstandard2.0;netstandard2.1;net9.0;net8.0; MySql.Data @@ -17,16 +17,7 @@ https://dev.mysql.com/downloads/ GPL-2.0-only WITH Universal-FOSS-exception-1.0 true - false - false - false - false - false - false - false - false - false - false + false True True ..\..\ConnectorNetPublicKey.snk diff --git a/MySQL.Data/src/Properties/AssemblyInfo.cs b/MySQL.Data/src/Properties/AssemblyInfo.cs index 04a9e1969..7e6823c70 100644 --- a/MySQL.Data/src/Properties/AssemblyInfo.cs +++ b/MySQL.Data/src/Properties/AssemblyInfo.cs @@ -36,7 +36,7 @@ // set of attributes. Change these attribute values to modify the information // associated with an assembly. [assembly: AssemblyTitle("MySql.Data")] -[assembly: AssemblyDescription("MySql.Data.EntityFramework adds support for cross-platform application deployment with the Entity Framework 6.4 version.")] +[assembly: AssemblyDescription("MySql.Data.MySqlClient .Net Core Class Library.")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Oracle Corporation")] [assembly: AssemblyProduct("MySQL Connector/NET")] diff --git a/MySQL.Data/src/Properties/VersionInfo.cs b/MySQL.Data/src/Properties/VersionInfo.cs index 127f87162..cc8ce728f 100644 --- a/MySQL.Data/src/Properties/VersionInfo.cs +++ b/MySQL.Data/src/Properties/VersionInfo.cs @@ -41,6 +41,6 @@ // by using the '*' as shown below: [assembly: AssemblyVersion("9.2.0")] -[assembly: AssemblyInformationalVersion("9.2.0")] -[assembly: AssemblyFileVersion("9.2.0")] +[assembly: AssemblyInformationalVersion("9.2.0.0")] +[assembly: AssemblyFileVersion("9.2.0.0")] [assembly: NeutralResourcesLanguage("en-US")] diff --git a/MySql.Web/src/MySql.Web.csproj b/MySql.Web/src/MySql.Web.csproj index 1c47d1d6d..b9f420f8d 100644 --- a/MySql.Web/src/MySql.Web.csproj +++ b/MySql.Web/src/MySql.Web.csproj @@ -5,7 +5,7 @@ Copyright © 2016, 2025, Oracle and/or its affiliates. en-US 9.2.0 - Oracle + Oracle Corporation net462;net48; $(NoWarn);CS1591 MySql.Web @@ -16,12 +16,7 @@ https://dev.mysql.com/downloads/ GPL-2.0-only WITH Universal-FOSS-exception-1.0 true - false - false - false - false - false - false + false False True True diff --git a/MySql.Web/src/Properties/VersionInfo.cs b/MySql.Web/src/Properties/VersionInfo.cs new file mode 100644 index 000000000..b56581caa --- /dev/null +++ b/MySql.Web/src/Properties/VersionInfo.cs @@ -0,0 +1,46 @@ +// Copyright © 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using System.Reflection; +using System.Resources; + +// +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Revision and Build Numbers +// by using the '*' as shown below: + +[assembly: AssemblyVersion("9.2.0")] +[assembly: AssemblyInformationalVersion("9.2.0.0")] +[assembly: AssemblyFileVersion("9.2.0.0")] +[assembly: NeutralResourcesLanguage("en-US")] From cfe120eb2ad7cbfb29c898709e8f6761cc7b84d5 Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Mon, 16 Dec 2024 19:19:46 -0700 Subject: [PATCH 095/125] Fixed failing test from Bug#36568102 Change-Id: If699752f120c5956a673d18272fc465b7178ae79 --- MySQL.Data/tests/MySql.Data.Tests/CmdTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MySQL.Data/tests/MySql.Data.Tests/CmdTests.cs b/MySQL.Data/tests/MySql.Data.Tests/CmdTests.cs index 236252e08..86e906c86 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/CmdTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/CmdTests.cs @@ -185,7 +185,7 @@ public void ActivityTest() { using var cmd = Connection.CreateCommand(); cmd.CommandText = "SELECT 1;"; - using var _ = TestListener((activity) => Assert.AreEqual("u-cmdtests-0", activity.GetTagItem("db.user"))); + using var _ = TestListener((activity) => Assert.AreEqual(BaseUserName+"0", activity.GetTagItem("db.user"))); cmd.ExecuteNonQuery(); } #endif From 4ea9d7a64e6d935c8cc228112bb1fd7d5e51a6b6 Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Tue, 17 Dec 2024 16:33:50 -0700 Subject: [PATCH 096/125] Corrected copyright year in multiple projects Change-Id: If878d5934a6205a3064ef5d81194ed7eb7560e2d --- EFCore/src/Properties/AssemblyInfo.cs | 6 +----- EFCore/src/Properties/VersionInfo.cs | 13 ++++--------- .../src/MySql.Data.EntityFramework.csproj | 2 +- MySQL.Data/src/MySql.Data.csproj | 2 +- MySQL.Data/src/Properties/AssemblyInfo.cs | 2 +- MySql.Web/src/MySql.Web.csproj | 2 +- 6 files changed, 9 insertions(+), 18 deletions(-) diff --git a/EFCore/src/Properties/AssemblyInfo.cs b/EFCore/src/Properties/AssemblyInfo.cs index 62ca664b2..e5565c1a9 100644 --- a/EFCore/src/Properties/AssemblyInfo.cs +++ b/EFCore/src/Properties/AssemblyInfo.cs @@ -41,11 +41,7 @@ [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Oracle Corporation")] [assembly: AssemblyProduct("MySQL Connector/NET")] -#if NET8_0 -[assembly: AssemblyCopyright("Copyright © 2025, Oracle and/or its affiliates.")] -#elif NET9_0 -[assembly: AssemblyCopyright("Copyright © 2025, Oracle and/or its affiliates.")] -#endif +[assembly: AssemblyCopyright("Copyright © 2021, 2025, Oracle and/or its affiliates.")] [assembly: AssemblyTrademark("Oracle®, Java, MySQL, and NetSuite are registered trademarks of Oracle and/or its affiliates.")] [assembly: AssemblyCulture("")] [assembly: SecurityRules(SecurityRuleSet.Level1)] diff --git a/EFCore/src/Properties/VersionInfo.cs b/EFCore/src/Properties/VersionInfo.cs index 5b4202568..e4e387204 100644 --- a/EFCore/src/Properties/VersionInfo.cs +++ b/EFCore/src/Properties/VersionInfo.cs @@ -40,15 +40,10 @@ // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -#if NET6_0 -[assembly: AssemblyVersion("6.0.33")] -[assembly: AssemblyInformationalVersion("6.0.33.0+MySQL9.2.0")] -[assembly: AssemblyFileVersion("6.0.33.0")] -[assembly: NeutralResourcesLanguage("en-US")] -#elif NET8_0 -[assembly: AssemblyVersion("8.0.8")] -[assembly: AssemblyInformationalVersion("8.0.8.0+MySQL9.2.0")] -[assembly: AssemblyFileVersion("8.0.8.0")] +#if NET8_0 +[assembly: AssemblyVersion("8.0.11")] +[assembly: AssemblyInformationalVersion("8.0.11.0+MySQL9.2.0")] +[assembly: AssemblyFileVersion("8.0.11.0")] [assembly: NeutralResourcesLanguage("en-US")] #elif NET9_0 [assembly: AssemblyVersion("9.0.0")] diff --git a/EntityFramework/src/MySql.Data.EntityFramework.csproj b/EntityFramework/src/MySql.Data.EntityFramework.csproj index a441d54d2..44e51da4d 100644 --- a/EntityFramework/src/MySql.Data.EntityFramework.csproj +++ b/EntityFramework/src/MySql.Data.EntityFramework.csproj @@ -2,7 +2,7 @@ MySql.Data.EntityFramework - Copyright © 2016, 2025, Oracle and/or its affiliates. + Copyright © 2008, 2025, Oracle and/or its affiliates. en-US 9.2.0 Oracle Corporation diff --git a/MySQL.Data/src/MySql.Data.csproj b/MySQL.Data/src/MySql.Data.csproj index db2a83c0a..ab3649cd1 100644 --- a/MySQL.Data/src/MySql.Data.csproj +++ b/MySQL.Data/src/MySql.Data.csproj @@ -3,7 +3,7 @@ MySql.Data.MySqlClient .Net Core Class Library - Copyright © 2016, 2025, Oracle and/or its affiliates. + Copyright © 2004, 2025, Oracle and/or its affiliates. en-US 9.2.0 Oracle Corporation diff --git a/MySQL.Data/src/Properties/AssemblyInfo.cs b/MySQL.Data/src/Properties/AssemblyInfo.cs index 7e6823c70..7dcf1fca6 100644 --- a/MySQL.Data/src/Properties/AssemblyInfo.cs +++ b/MySQL.Data/src/Properties/AssemblyInfo.cs @@ -40,7 +40,7 @@ [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Oracle Corporation")] [assembly: AssemblyProduct("MySQL Connector/NET")] -[assembly: AssemblyCopyright("Copyright © 2016, 2025, Oracle and/or its affiliates.")] +[assembly: AssemblyCopyright("Copyright © 2004, 2025, Oracle and/or its affiliates.")] [assembly: AssemblyTrademark("Oracle®, Java, MySQL, and NetSuite are registered trademarks of Oracle and/or its affiliates.")] [assembly: AssemblyCulture("")] [assembly: SecurityRules(SecurityRuleSet.Level1)] diff --git a/MySql.Web/src/MySql.Web.csproj b/MySql.Web/src/MySql.Web.csproj index b9f420f8d..9d2d86701 100644 --- a/MySql.Web/src/MySql.Web.csproj +++ b/MySql.Web/src/MySql.Web.csproj @@ -2,7 +2,7 @@ MySql.Web - Copyright © 2016, 2025, Oracle and/or its affiliates. + Copyright © 2004, 2025, Oracle and/or its affiliates. en-US 9.2.0 Oracle Corporation From fe156f745a1e0a2488d3a4a11c4c883c749776cc Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Mon, 16 Dec 2024 17:37:31 -0700 Subject: [PATCH 097/125] Bug#36960454 [Contribution: ConcurrencyFix - Added back in RowCount checking] Change-Id: Ibec9aba52784f88adaa066afab49aa6975330963 --- CHANGES | 1 + EFCore/src/Update/MySQLUpdateSqlGenerator.cs | 8 +- .../ConcurrencyTests.cs | 93 ++++++++++++++++++- .../DbContextClasses/EFFluentAPIContexts.cs | 4 +- .../DbContextClasses/EntitiesClasses.cs | 2 +- 5 files changed, 97 insertions(+), 11 deletions(-) diff --git a/CHANGES b/CHANGES index c9ca4f218..1721922b4 100644 --- a/CHANGES +++ b/CHANGES @@ -7,6 +7,7 @@ - Fixed bug Fixed NullReferenceException (MySQL Bug #114457, Oracle Bug #36568102). Thanks to Maximilian Bienhüls for the contribution. - Fixed bug MySql.Data.OpenTelemetry dll has a version 0.0.0.0 (Oracle Bug #37198051). - Fixed bug Missing VersionInfo file in multiple projects (Oracle Bug #37240118). +- Fixed bug ConcurrencyFix - Added back in RowCount checking (MySQL Bug #115853, Oracle Bug #36960454). Thanks to Ryan Kelly for the contribution. 9.1.0 diff --git a/EFCore/src/Update/MySQLUpdateSqlGenerator.cs b/EFCore/src/Update/MySQLUpdateSqlGenerator.cs index c095de786..145b8fe39 100644 --- a/EFCore/src/Update/MySQLUpdateSqlGenerator.cs +++ b/EFCore/src/Update/MySQLUpdateSqlGenerator.cs @@ -179,7 +179,7 @@ public virtual ResultSetMapping AppendInsertOperation( return AppendSelectAffectedCommand(commandStringBuilder, name, schema, readOperations, keyOperations); } - return readOperations.Count > 0 ? ResultSetMapping.LastInResultSet : ResultSetMapping.NoResults; + return AppendSelectAffectedCountCommand(commandStringBuilder, name, schema, commandPosition); } protected virtual void AppendInsertCommand( @@ -223,7 +223,7 @@ public override ResultSetMapping AppendUpdateOperation( return AppendSelectAffectedCommand(commandStringBuilder, name, schema, readOperations, keyOperations); } - return ResultSetMapping.NoResults; + return AppendSelectAffectedCountCommand(commandStringBuilder, name, schema, commandPosition); } public override ResultSetMapping AppendDeleteOperation( @@ -242,7 +242,7 @@ public override ResultSetMapping AppendDeleteOperation( AppendDeleteCommand(commandStringBuilder, name, schema, Array.Empty(), conditionOperations); - return ResultSetMapping.NoResults; + return AppendSelectAffectedCountCommand(commandStringBuilder, name, schema,commandPosition); } protected override void AppendValues( @@ -420,7 +420,7 @@ protected override ResultSetMapping AppendSelectAffectedCountCommand(StringBuild .Append(SqlGenerationHelper.StatementTerminator).AppendLine() .AppendLine(); - return ResultSetMapping.LastInResultSet; + return ResultSetMapping.ResultSetWithRowsAffectedOnly; } #endif } diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/ConcurrencyTests.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/ConcurrencyTests.cs index a0ac73b84..8e21b9acc 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/ConcurrencyTests.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/ConcurrencyTests.cs @@ -43,8 +43,7 @@ public class ConcurrencyTests public void CanHandleConcurrencyConflicts() { var serviceCollection = new ServiceCollection(); - serviceCollection.AddEntityFrameworkMySQL() - .AddDbContext(); + serviceCollection.AddEntityFrameworkMySQL().AddDbContext(); var serviceProvider = serviceCollection.BuildServiceProvider(); @@ -53,11 +52,11 @@ public void CanHandleConcurrencyConflicts() context.Database.EnsureDeleted(); context.Database.EnsureCreated(); - context.People.Add(new Person { Name = "Mike Redman", SocialSecurityNumber = "SSS1229932", PhoneNumber = "565665656" }); + context.People.Add(new Person { Name = "John Doe", PersonNumber = "3333333333", PhoneNumber = "1111111111" }); context.SaveChanges(); var person = context.People.Single(p => p.PersonId == 1); - person.SocialSecurityNumber = "SS15555"; + person.PersonNumber = "4444444444"; context.Database.ExecuteSqlInterpolated($"UPDATE People SET Name = 'Jane' WHERE PersonId = 1"); @@ -103,5 +102,91 @@ public void CanHandleConcurrencyConflicts() } } } + + [Test] + public void CanHandleUpdateConcurrencyConflicts() + { + var serviceCollection = new ServiceCollection(); + serviceCollection.AddEntityFrameworkMySQL().AddDbContext(); + + var serviceProvider = serviceCollection.BuildServiceProvider(); + + using (var context = serviceProvider.GetRequiredService()) + { + context.Database.EnsureDeleted(); + context.Database.EnsureCreated(); + + context.People.Add(new Person + { Name = "John Doe", PersonNumber = "3333333333", PhoneNumber = "1111111111" }); + context.SaveChanges(); + + var updatePerson1 = context.People.Single(p => p.PersonId == 1); + var updatePerson2 = context.People.Single(p => p.PersonId == 1); + + updatePerson1.PersonNumber = "2222222222"; + updatePerson1.PhoneNumber = "555555555"; + + context.SaveChanges(); + + var item = context.ChangeTracker.Entries().First(x => Object.ReferenceEquals(x.Entity, updatePerson2)); + item.OriginalValues["PersonNumber"] = "3333333333"; + updatePerson2.PersonNumber = "44444444"; + updatePerson2.PhoneNumber = "666666666"; + + TestDelegate action = () => context.SaveChanges(); + Assert.Throws(action); + } + } + + [Test] + public void CanHandleDeleteConcurrencyConflicts() + { + var serviceCollection = new ServiceCollection(); + serviceCollection.AddEntityFrameworkMySQL().AddDbContext(); + + var serviceProvider = serviceCollection.BuildServiceProvider(); + + using (var context = serviceProvider.GetRequiredService()) + { + context.Database.EnsureDeleted(); + context.Database.EnsureCreated(); + context.Remove(new Person { PersonId = 2 , PersonNumber = "88888888" }); + + TestDelegate action = () => context.SaveChanges(); + Assert.Throws(action); + } + } + + [Test] + public void CanHandleInsertConcurrencyConflicts() + { + var serviceCollection = new ServiceCollection(); + serviceCollection.AddEntityFrameworkMySQL().AddDbContext(); + + var serviceProvider = serviceCollection.BuildServiceProvider(); + + using (var context = serviceProvider.GetRequiredService()) + { + context.Database.EnsureDeleted(); + context.Database.EnsureCreated(); + context.People.Add(new Person + { Name = "John Doe", PersonNumber = "3333333333", PhoneNumber = "1111111111" }); + context.SaveChanges(); + + var insertedPerson1 = context.People.Single(p => p.PersonId == 1); + insertedPerson1.PersonNumber = "1111111111"; + + context.SaveChanges(); + + var item = context.ChangeTracker.Entries().First(x => Object.ReferenceEquals(x.Entity, insertedPerson1)); + item.OriginalValues["PersonNumber"] = "3333333333"; + + context.People.Add(new Person + { Name = "John Doe", PersonNumber = "3333333333", PhoneNumber = "1111111111" }); + + TestDelegate action = () => context.SaveChanges(); + Assert.Throws(action); + } + } } } diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/DbContextClasses/EFFluentAPIContexts.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/DbContextClasses/EFFluentAPIContexts.cs index ad39fb4ba..33940a28c 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/DbContextClasses/EFFluentAPIContexts.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/DbContextClasses/EFFluentAPIContexts.cs @@ -27,6 +27,7 @@ // 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; using MySql.EntityFrameworkCore.Basic.Tests.Utils; using MySql.EntityFrameworkCore.Extensions; using System; @@ -151,8 +152,7 @@ public class ConcurrencyTestsContext : MyTestContext protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity() - .Property(p => p.SocialSecurityNumber) - .IsConcurrencyToken(); + .Property(p => p.PersonNumber).IsConcurrencyToken(); } } } diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/DbContextClasses/EntitiesClasses.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/DbContextClasses/EntitiesClasses.cs index 2d3214dba..863606a21 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/DbContextClasses/EntitiesClasses.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/DbContextClasses/EntitiesClasses.cs @@ -165,7 +165,7 @@ public class Person public int PersonId { get; set; } [ConcurrencyCheck] - public string? SocialSecurityNumber { get; set; } + public string? PersonNumber { get; set; } public string? PhoneNumber { get; set; } [ConcurrencyCheck] public string? Name { get; set; } From 69d346f6f2b22e8d4f7aefecb872d855003cec1d Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Fri, 10 Jan 2025 13:01:56 -0700 Subject: [PATCH 098/125] Bump up version to 9.3.0 Change-Id: I6e86a46f25df1125a3a7efb5f9d52e6257f7d1f8 --- CHANGES | 3 +++ .../custom/partials/class.header.tmpl.partial | 2 +- EFCore/src/Properties/VersionInfo.cs | 12 ++++++------ .../src/MySql.Data.EntityFramework.csproj | 2 +- EntityFramework/src/Properties/VersionInfo.cs | 6 +++--- .../MySql.EntityFramework.Basic.Tests.csproj | 2 +- .../MySql.EntityFramework.CodeFirst.Tests.csproj | 2 +- .../MySql.EntityFramework.Migrations.Tests.csproj | 2 +- .../src/MySQL.Data.OpenTelemetry.csproj | 2 +- .../src/Properties/VersionInfo.cs | 6 +++--- MySQL.Data/src/MySql.Data.csproj | 4 ++-- MySQL.Data/src/Properties/VersionInfo.cs | 6 +++--- .../tests/MySql.Data.Tests/MySql.Data.Tests.csproj | 4 ++-- .../tests/MySqlX.Data.Tests/MySqlX.Data.Tests.csproj | 4 ++-- MySql.Web/src/MySql.Web.csproj | 2 +- MySql.Web/src/Properties/VersionInfo.cs | 6 +++--- MySql.Web/tests/MySql.Web.Tests.csproj | 2 +- 17 files changed, 35 insertions(+), 32 deletions(-) diff --git a/CHANGES b/CHANGES index 1721922b4..9b519c42d 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,6 @@ +9.3.0 + + 9.2.0 - Added support for .NET 9 and EF Core 9 GA versions (WL16638). - Removed support for .NET 6 and EFCore 6 (WL16654). diff --git a/Documentation/templates/custom/partials/class.header.tmpl.partial b/Documentation/templates/custom/partials/class.header.tmpl.partial index 2ee15b21b..15ce5e483 100644 --- a/Documentation/templates/custom/partials/class.header.tmpl.partial +++ b/Documentation/templates/custom/partials/class.header.tmpl.partial @@ -25,7 +25,7 @@ {{/implements.0}}
{{__global.namespace}}: {{{namespace.specName.0.value}}}
{{__global.assembly}}: {{assemblies.0}}.dll
-
Version: 9.2.0
+
Version: 9.3.0
{{__global.syntax}}
{{syntax.content.0.value}}
diff --git a/EFCore/src/Properties/VersionInfo.cs b/EFCore/src/Properties/VersionInfo.cs index e4e387204..9ff731567 100644 --- a/EFCore/src/Properties/VersionInfo.cs +++ b/EFCore/src/Properties/VersionInfo.cs @@ -41,13 +41,13 @@ // by using the '*' as shown below: #if NET8_0 -[assembly: AssemblyVersion("8.0.11")] -[assembly: AssemblyInformationalVersion("8.0.11.0+MySQL9.2.0")] -[assembly: AssemblyFileVersion("8.0.11.0")] +[assembly: AssemblyVersion("9.3.0")] +[assembly: AssemblyInformationalVersion("8.0.11.0+MySQL9.3.0")] +[assembly: AssemblyFileVersion("9.3.0.0")] [assembly: NeutralResourcesLanguage("en-US")] #elif NET9_0 -[assembly: AssemblyVersion("9.0.0")] -[assembly: AssemblyInformationalVersion("9.0.0.0-preview+MySQL9.2.0")] -[assembly: AssemblyFileVersion("9.0.0.0")] +[assembly: AssemblyVersion("9.3.0")] +[assembly: AssemblyInformationalVersion("9.0.0.0-preview+MySQL9.3.0")] +[assembly: AssemblyFileVersion("9.3.0.0")] [assembly: NeutralResourcesLanguage("en-US")] #endif diff --git a/EntityFramework/src/MySql.Data.EntityFramework.csproj b/EntityFramework/src/MySql.Data.EntityFramework.csproj index 44e51da4d..d5c63d0f2 100644 --- a/EntityFramework/src/MySql.Data.EntityFramework.csproj +++ b/EntityFramework/src/MySql.Data.EntityFramework.csproj @@ -4,7 +4,7 @@ MySql.Data.EntityFramework Copyright © 2008, 2025, Oracle and/or its affiliates. en-US - 9.2.0 + 9.3.0 Oracle Corporation net462;net48; $(NoWarn);CS1591 diff --git a/EntityFramework/src/Properties/VersionInfo.cs b/EntityFramework/src/Properties/VersionInfo.cs index b56581caa..0e0ddbb1f 100644 --- a/EntityFramework/src/Properties/VersionInfo.cs +++ b/EntityFramework/src/Properties/VersionInfo.cs @@ -40,7 +40,7 @@ // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("9.2.0")] -[assembly: AssemblyInformationalVersion("9.2.0.0")] -[assembly: AssemblyFileVersion("9.2.0.0")] +[assembly: AssemblyVersion("9.3.0")] +[assembly: AssemblyInformationalVersion("9.3.0.0")] +[assembly: AssemblyFileVersion("9.3.0.0")] [assembly: NeutralResourcesLanguage("en-US")] diff --git a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/MySql.EntityFramework.Basic.Tests.csproj b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/MySql.EntityFramework.Basic.Tests.csproj index cc5342e98..92e590f7e 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/MySql.EntityFramework.Basic.Tests.csproj +++ b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/MySql.EntityFramework.Basic.Tests.csproj @@ -4,7 +4,7 @@ MySql.Data.EntityFramework.CodeFirTests Copyright © 2016, 2024, Oracle and/or its affiliates. en-US - 9.2.0 + 9.3.0 Oracle net462;net48; MySql.EntityFramework.Basic.Tests diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/MySql.EntityFramework.CodeFirst.Tests.csproj b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/MySql.EntityFramework.CodeFirst.Tests.csproj index 91610f9b1..ffe3918ea 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/MySql.EntityFramework.CodeFirst.Tests.csproj +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/MySql.EntityFramework.CodeFirst.Tests.csproj @@ -4,7 +4,7 @@ MySql.Data.EntityFramework.CodeFirst.Tests Copyright © 2016, 2024, Oracle and/or its affiliates. en-US - 9.2.0 + 9.3.0 Oracle net462;net48; MySql.EntityFramework.CodeFirst.Tests diff --git a/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/MySql.EntityFramework.Migrations.Tests.csproj b/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/MySql.EntityFramework.Migrations.Tests.csproj index d880fedad..51d53f219 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/MySql.EntityFramework.Migrations.Tests.csproj +++ b/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/MySql.EntityFramework.Migrations.Tests.csproj @@ -4,7 +4,7 @@ MySql.Data.EntityFramework.Migrations.Tests Copyright © 2016, 2024, Oracle and/or its affiliates. en-US - 9.2.0 + 9.3.0 Oracle net462;net48; MySql.EntityFramework.Migrations.Tests diff --git a/MySQL.Data.OpenTelemetry/src/MySQL.Data.OpenTelemetry.csproj b/MySQL.Data.OpenTelemetry/src/MySQL.Data.OpenTelemetry.csproj index 2e3a72c00..f84a6c2e9 100644 --- a/MySQL.Data.OpenTelemetry/src/MySQL.Data.OpenTelemetry.csproj +++ b/MySQL.Data.OpenTelemetry/src/MySQL.Data.OpenTelemetry.csproj @@ -4,7 +4,7 @@ MySql.Data.OpenTelemetry Copyright © 2023, 2025, Oracle and/or its affiliates. en-US - 9.2.0 + 9.3.0 Oracle Corporation netstandard2.0 MySql.Data.OpenTelemetry diff --git a/MySQL.Data.OpenTelemetry/src/Properties/VersionInfo.cs b/MySQL.Data.OpenTelemetry/src/Properties/VersionInfo.cs index 8ee3378d9..ab8190d46 100644 --- a/MySQL.Data.OpenTelemetry/src/Properties/VersionInfo.cs +++ b/MySQL.Data.OpenTelemetry/src/Properties/VersionInfo.cs @@ -40,8 +40,8 @@ // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("9.2.0")] -[assembly: AssemblyInformationalVersion("9.2.0.0")] -[assembly: AssemblyFileVersion("9.2.0.0")] +[assembly: AssemblyVersion("9.3.0")] +[assembly: AssemblyInformationalVersion("9.3.0.0")] +[assembly: AssemblyFileVersion("9.3.0.0")] [assembly: NeutralResourcesLanguage("en-US")] diff --git a/MySQL.Data/src/MySql.Data.csproj b/MySQL.Data/src/MySql.Data.csproj index ab3649cd1..ad5a5506c 100644 --- a/MySQL.Data/src/MySql.Data.csproj +++ b/MySQL.Data/src/MySql.Data.csproj @@ -5,7 +5,7 @@ MySql.Data.MySqlClient .Net Core Class Library Copyright © 2004, 2025, Oracle and/or its affiliates. en-US - 9.2.0 + 9.3.0 Oracle Corporation MySql.Data netstandard2.0;netstandard2.1;net9.0;net8.0; @@ -128,4 +128,4 @@ - + \ No newline at end of file diff --git a/MySQL.Data/src/Properties/VersionInfo.cs b/MySQL.Data/src/Properties/VersionInfo.cs index cc8ce728f..2812dd600 100644 --- a/MySQL.Data/src/Properties/VersionInfo.cs +++ b/MySQL.Data/src/Properties/VersionInfo.cs @@ -40,7 +40,7 @@ // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("9.2.0")] -[assembly: AssemblyInformationalVersion("9.2.0.0")] -[assembly: AssemblyFileVersion("9.2.0.0")] +[assembly: AssemblyVersion("9.3.0")] +[assembly: AssemblyInformationalVersion("9.3.0.0")] +[assembly: AssemblyFileVersion("9.3.0.0")] [assembly: NeutralResourcesLanguage("en-US")] diff --git a/MySQL.Data/tests/MySql.Data.Tests/MySql.Data.Tests.csproj b/MySQL.Data/tests/MySql.Data.Tests/MySql.Data.Tests.csproj index b0144ddf2..abc240e49 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/MySql.Data.Tests.csproj +++ b/MySQL.Data/tests/MySql.Data.Tests/MySql.Data.Tests.csproj @@ -4,7 +4,7 @@ MySql.Data.Tests MySql.Data.Tests Class Library Copyright © 2016, 2024, Oracle and/or its affiliates. - 9.2.0 + 9.3.0 Oracle Oracle MySql.Data.Tests @@ -138,4 +138,4 @@ - + \ No newline at end of file diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/MySqlX.Data.Tests.csproj b/MySQL.Data/tests/MySqlX.Data.Tests/MySqlX.Data.Tests.csproj index 054e9dda3..bda016d41 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/MySqlX.Data.Tests.csproj +++ b/MySQL.Data/tests/MySqlX.Data.Tests/MySqlX.Data.Tests.csproj @@ -4,7 +4,7 @@ MySql.Data.Tests MySql.Data.Tests Class Library Copyright © 2016, 2024, Oracle and/or its affiliates. - 9.2.0 + 9.3.0 Oracle Oracle MySql.Data.Tests @@ -117,4 +117,4 @@ Always - + \ No newline at end of file diff --git a/MySql.Web/src/MySql.Web.csproj b/MySql.Web/src/MySql.Web.csproj index 9d2d86701..78ebb7da5 100644 --- a/MySql.Web/src/MySql.Web.csproj +++ b/MySql.Web/src/MySql.Web.csproj @@ -4,7 +4,7 @@ MySql.Web Copyright © 2004, 2025, Oracle and/or its affiliates. en-US - 9.2.0 + 9.3.0 Oracle Corporation net462;net48; $(NoWarn);CS1591 diff --git a/MySql.Web/src/Properties/VersionInfo.cs b/MySql.Web/src/Properties/VersionInfo.cs index b56581caa..0e0ddbb1f 100644 --- a/MySql.Web/src/Properties/VersionInfo.cs +++ b/MySql.Web/src/Properties/VersionInfo.cs @@ -40,7 +40,7 @@ // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("9.2.0")] -[assembly: AssemblyInformationalVersion("9.2.0.0")] -[assembly: AssemblyFileVersion("9.2.0.0")] +[assembly: AssemblyVersion("9.3.0")] +[assembly: AssemblyInformationalVersion("9.3.0.0")] +[assembly: AssemblyFileVersion("9.3.0.0")] [assembly: NeutralResourcesLanguage("en-US")] diff --git a/MySql.Web/tests/MySql.Web.Tests.csproj b/MySql.Web/tests/MySql.Web.Tests.csproj index 2ff8a784f..aa64682dd 100644 --- a/MySql.Web/tests/MySql.Web.Tests.csproj +++ b/MySql.Web/tests/MySql.Web.Tests.csproj @@ -4,7 +4,7 @@ MySql.Web.Tests Copyright © 2016, 2024, Oracle and/or its affiliates. en-US - 9.2.0 + 9.3.0 Oracle net462;net48; MySql.Web.Tests From 26e80fde1dd9092677a54ff8f5dbaabe1c59e7be Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Fri, 10 Jan 2025 14:42:08 -0700 Subject: [PATCH 099/125] Organization and cleanup Change-Id: Ie1f7dd658933faddb6c23655653bb76a48c8e944 --- .../src/Properties/AssemblyInfo.cs | 6 ++-- .../src/Properties/VersionInfo.cs | 2 +- .../OpenIdConnectClientAuthentication.cs | 30 ++++++++++++++++++- MySQL.Data/src/MySqlConnection.cs | 2 +- MySQL.Data/src/MySqlHelper.cs | 2 +- .../src/X/Protocol/X/Protobuf/MysqlxSql.cs | 2 +- MySQL.Data/tests/MySql.Data.Tests/CmdTests.cs | 2 +- .../tests/MySql.Data.Tests/GlobalUsings.cs | 5 ---- 8 files changed, 37 insertions(+), 14 deletions(-) delete mode 100644 MySQL.Data/tests/MySql.Data.Tests/GlobalUsings.cs diff --git a/MySQL.Data.OpenTelemetry/src/Properties/AssemblyInfo.cs b/MySQL.Data.OpenTelemetry/src/Properties/AssemblyInfo.cs index 74ae5278a..37ea42a17 100644 --- a/MySQL.Data.OpenTelemetry/src/Properties/AssemblyInfo.cs +++ b/MySQL.Data.OpenTelemetry/src/Properties/AssemblyInfo.cs @@ -1,4 +1,4 @@ -// Copyright � 2024, Oracle and/or its affiliates. +// Copyright © 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as @@ -39,8 +39,8 @@ [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Oracle Corporation")] [assembly: AssemblyProduct("MySQL Connector/NET")] -[assembly: AssemblyCopyright("Copyright � 2023, 2025, Oracle and/or its affiliates.")] -[assembly: AssemblyTrademark("Oracle�, Java, MySQL, and NetSuite are registered trademarks of Oracle and/or its affiliates.")] +[assembly: AssemblyCopyright("Copyright © 2023, 2025, Oracle and/or its affiliates.")] +[assembly: AssemblyTrademark("Oracle®, Java, MySQL, and NetSuite are registered trademarks of Oracle and/or its affiliates.")] [assembly: AssemblyCulture("")] [assembly: SecurityRules(SecurityRuleSet.Level1)] [assembly: CLSCompliant(false)] diff --git a/MySQL.Data.OpenTelemetry/src/Properties/VersionInfo.cs b/MySQL.Data.OpenTelemetry/src/Properties/VersionInfo.cs index ab8190d46..c8499687d 100644 --- a/MySQL.Data.OpenTelemetry/src/Properties/VersionInfo.cs +++ b/MySQL.Data.OpenTelemetry/src/Properties/VersionInfo.cs @@ -1,4 +1,4 @@ -// Copyright � 2024, Oracle and/or its affiliates. +// Copyright © 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Authentication/OpenIdConnectClientAuthentication.cs b/MySQL.Data/src/Authentication/OpenIdConnectClientAuthentication.cs index ef330b3c5..44d12ecb4 100644 --- a/MySQL.Data/src/Authentication/OpenIdConnectClientAuthentication.cs +++ b/MySQL.Data/src/Authentication/OpenIdConnectClientAuthentication.cs @@ -1,4 +1,32 @@ -using MySql.Data.MySqlClient; +// Copyright © 2024, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using MySql.Data.MySqlClient; using MySql.Data.MySqlClient.Authentication; using Org.BouncyCastle.Utilities.Encoders; using System; diff --git a/MySQL.Data/src/MySqlConnection.cs b/MySQL.Data/src/MySqlConnection.cs index 8deb192e8..4f633f83b 100644 --- a/MySQL.Data/src/MySqlConnection.cs +++ b/MySQL.Data/src/MySqlConnection.cs @@ -1,4 +1,4 @@ -// Copyright � 2004, 2024, Oracle and/or its affiliates. +// Copyright © 2004, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/MySqlHelper.cs b/MySQL.Data/src/MySqlHelper.cs index 9bf4518a6..052ba4e6b 100644 --- a/MySQL.Data/src/MySqlHelper.cs +++ b/MySQL.Data/src/MySqlHelper.cs @@ -1,4 +1,4 @@ -// Copyright � 2004, 2024, Oracle and/or its affiliates. +// Copyright © 2004, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxSql.cs b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxSql.cs index 62320a573..db509cb32 100644 --- a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxSql.cs +++ b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxSql.cs @@ -1,4 +1,4 @@ -// Copyright � 2022, 2023, Oracle and/or its affiliates. +// Copyright © 2022, 2023, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySql.Data.Tests/CmdTests.cs b/MySQL.Data/tests/MySql.Data.Tests/CmdTests.cs index 86e906c86..171d6630e 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/CmdTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/CmdTests.cs @@ -185,7 +185,7 @@ public void ActivityTest() { using var cmd = Connection.CreateCommand(); cmd.CommandText = "SELECT 1;"; - using var _ = TestListener((activity) => Assert.AreEqual(BaseUserName+"0", activity.GetTagItem("db.user"))); + using var _ = TestListener((activity) => Assert.That(BaseUserName+"0", Is.EqualTo(activity.GetTagItem("db.user")))); cmd.ExecuteNonQuery(); } #endif diff --git a/MySQL.Data/tests/MySql.Data.Tests/GlobalUsings.cs b/MySQL.Data/tests/MySql.Data.Tests/GlobalUsings.cs deleted file mode 100644 index 575c7cfd0..000000000 --- a/MySQL.Data/tests/MySql.Data.Tests/GlobalUsings.cs +++ /dev/null @@ -1,5 +0,0 @@ -global using Assert = NUnit.Framework.Legacy.ClassicAssert; -global using CollectionAssert = NUnit.Framework.Legacy.CollectionAssert; -global using StringAssert = NUnit.Framework.Legacy.StringAssert; -global using DirectoryAssert = NUnit.Framework.Legacy.DirectoryAssert; -global using FileAssert = NUnit.Framework.Legacy.FileAssert; From e31297cabf23c7941bc2ed22a3ed4124f51ca8fe Mon Sep 17 00:00:00 2001 From: Filipe Silva Date: Sat, 11 Jan 2025 01:55:39 +0000 Subject: [PATCH 100/125] Fix enconding in a few files Change-Id: I185779410605b1a08a842f7eae0beb5be26a1d8a --- .../Properties/sakila-data.sql | 2 +- .../Properties/sakila-schema.sql | 2 +- MySQL.Data/src/MySqlCommand.cs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/Properties/sakila-data.sql b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/Properties/sakila-data.sql index fcb99f2f6..e9d80306c 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/Properties/sakila-data.sql +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/Properties/sakila-data.sql @@ -1,7 +1,7 @@ -- Sakila Sample Database Data -- Version 1.0 --- Copyright � 2006, 2024, Oracle and/or its affiliates. +-- Copyright © 2006, 2024, Oracle and/or its affiliates. -- Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/Properties/sakila-schema.sql b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/Properties/sakila-schema.sql index f25502e95..2d4ee1027 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/Properties/sakila-schema.sql +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/Properties/sakila-schema.sql @@ -1,7 +1,7 @@ -- Sakila Sample Database Schema -- Version 1.0 --- Copyright � 2006, 2024, Oracle and/or its affiliates. +-- Copyright © 2006, 2024, Oracle and/or its affiliates. -- Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: diff --git a/MySQL.Data/src/MySqlCommand.cs b/MySQL.Data/src/MySqlCommand.cs index 925229172..9d389fb70 100644 --- a/MySQL.Data/src/MySqlCommand.cs +++ b/MySQL.Data/src/MySqlCommand.cs @@ -1,4 +1,4 @@ -// Copyright � 2004, 2024, Oracle and/or its affiliates. +// Copyright © 2004, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as From a8809a89122effe18432953e9d4b438e55015195 Mon Sep 17 00:00:00 2001 From: Filipe Silva Date: Sat, 11 Jan 2025 02:08:05 +0000 Subject: [PATCH 101/125] Copyright header year bump Change-Id: I73f7149c0bb0c14efeedbf2db48f6483cfae1d6b --- Documentation/docfx.json | 2 +- EFCore/src/DataAnnotations/MySQLCharsetAttribute.cs | 2 +- EFCore/src/DataAnnotations/MySQLCollationAttribute.cs | 2 +- EFCore/src/Design/Internal/MySQLAnnotationCodeGenerator.cs | 2 +- EFCore/src/Design/Internal/MySQLDesignTimeServices.cs | 2 +- EFCore/src/Diagnostics/Internal/MySQLLoggingDefinitions.cs | 2 +- EFCore/src/Diagnostics/MySQLEventId.cs | 2 +- EFCore/src/Extensions/MySQLDatabaseFacadeExtensions.cs | 2 +- EFCore/src/Extensions/MySQLDbContextOptionsExtensions.cs | 2 +- EFCore/src/Extensions/MySQLDbFunctionsEnums.cs | 2 +- EFCore/src/Extensions/MySQLDbFunctionsExtensions.cs | 2 +- EFCore/src/Extensions/MySQLEntityTypeBuilderExtensions.cs | 2 +- EFCore/src/Extensions/MySQLEntityTypeExtensions.cs | 2 +- EFCore/src/Extensions/MySQLIndexExtensions.cs | 2 +- EFCore/src/Extensions/MySQLKeyBuilderExtensions.cs | 2 +- EFCore/src/Extensions/MySQLKeyExtensions.cs | 2 +- EFCore/src/Extensions/MySQLMigrationBuilderExtensions.cs | 2 +- EFCore/src/Extensions/MySQLModelBuilderExtensions.cs | 2 +- EFCore/src/Extensions/MySQLModelExtensions.cs | 2 +- EFCore/src/Extensions/MySQLPropertyBuilderExtensions.cs | 2 +- EFCore/src/Extensions/MySQLPropertyExtensions.cs | 2 +- EFCore/src/Extensions/MySQLServiceCollectionExtensions.cs | 2 +- EFCore/src/Extensions/MySQLTypeBaseExtensions.cs | 2 +- EFCore/src/Extensions/MySqlIndexBuilderExtensions.cs | 2 +- EFCore/src/Infrastructure/Internal/IMySQLOptions.cs | 2 +- EFCore/src/Infrastructure/Internal/MySQLOptionsExtension.cs | 2 +- EFCore/src/Infrastructure/MySQLDbContextOptionsBuilder.cs | 2 +- EFCore/src/Infrastructure/MySQLSchemaBehavior.cs | 2 +- EFCore/src/Internal/MySQLModelValidator.cs | 2 +- EFCore/src/Internal/MySQLOptions.cs | 2 +- EFCore/src/Internal/MySQLRetryingExecutionStrategy.cs | 2 +- .../src/Internal/MySQLValueGenerationStrategyCompatibility.cs | 2 +- EFCore/src/Metadata/Conventions/MySQLConventionSetBuilder.cs | 2 +- .../Metadata/Conventions/MySQLValueGenerationConvention.cs | 2 +- .../Metadata/Conventions/MySqlCharsetAttributeConvention.cs | 2 +- .../Metadata/Conventions/MySqlCollationAttributeConvention.cs | 2 +- .../Conventions/MySqlEntityCharsetAttributeConvention.cs | 2 +- .../Conventions/MySqlEntityCollationAttributeConvention.cs | 2 +- EFCore/src/Metadata/Internal/MySQLAnnotationNames.cs | 2 +- EFCore/src/Metadata/Internal/MySQLAnnotationProvider.cs | 2 +- EFCore/src/Metadata/MySQLValueGenerationStrategy.cs | 2 +- EFCore/src/Migrations/Internal/MySQLHistoryRepository.cs | 2 +- .../src/Migrations/Internal/MySQLMigrationDatabaseLockcs.cs | 2 +- EFCore/src/Migrations/Internal/MySQLMigrationsModelDiffer.cs | 2 +- EFCore/src/Migrations/Internal/MySQLMigrator.cs | 2 +- EFCore/src/Migrations/MySQLMigrationsSqlGenerator.cs | 2 +- EFCore/src/Migrations/Operations/CreateDatabaseOperation.cs | 2 +- EFCore/src/Migrations/Operations/DropDatabaseOperation.cs | 2 +- .../MySQLDropPrimaryKeyAndRecreateForeignKeysOperation.cs | 2 +- ...ySQLDropUniqueConstraintAndRecreateForeignKeysOperation.cs | 2 +- EFCore/src/Properties/AssemblyInfo.cs | 2 +- EFCore/src/Properties/VersionInfo.cs | 2 +- .../Internal/MySQLByteArrayMethodTranslator.cs | 2 +- .../Internal/MySQLDbFunctionsExtensionsMethodTranslator.cs | 2 +- .../Internal/MySQLRegexIsMatchTranslator.cs | 2 +- .../Internal/MySQLStringLengthTranslator.cs | 2 +- .../src/Query/Expressions/Internal/MySQLBinaryExpression.cs | 2 +- .../src/Query/Expressions/Internal/MySQLCollateExpression.cs | 2 +- .../Internal/MySQLColumnAliasReferenceExpression.cs | 2 +- .../Internal/MySQLComplexFunctionArgumentExpression.cs | 2 +- .../Expressions/Internal/MySQLJsonArrayIndexExpression.cs | 2 +- .../Expressions/Internal/MySQLJsonTraversalExpression.cs | 2 +- EFCore/src/Query/Expressions/Internal/MySQLMatchExpression.cs | 2 +- .../src/Query/Expressions/Internal/MySQLRegexpExpression.cs | 2 +- .../Internal/MySQLStringComparisonMethodTranslator.cs | 2 +- EFCore/src/Query/Internal/MySQLCommandParser.cs | 2 +- .../src/Query/Internal/MySQLCompatibilityExpressionVisitor.cs | 2 +- .../src/Query/Internal/MySQLCompiledQueryCacheKeyGenerator.cs | 2 +- EFCore/src/Query/Internal/MySQLConvertTranslator.cs | 2 +- EFCore/src/Query/Internal/MySQLDateDiffFunctionsTranslator.cs | 2 +- EFCore/src/Query/Internal/MySQLDateTimeMemberTranslator.cs | 2 +- EFCore/src/Query/Internal/MySQLDateTimeMethodTranslator.cs | 2 +- EFCore/src/Query/Internal/MySQLEvaluatableExpressionFilter.cs | 2 +- EFCore/src/Query/Internal/MySQLMathTranslator.cs | 2 +- EFCore/src/Query/Internal/MySQLMemberTranslatorProvider.cs | 2 +- .../src/Query/Internal/MySQLMethodCallTranslatorProvider.cs | 2 +- EFCore/src/Query/Internal/MySQLNewGuidTranslator.cs | 2 +- EFCore/src/Query/Internal/MySQLObjectToStringTranslator.cs | 2 +- EFCore/src/Query/Internal/MySQLParameterBasedSqlProcessor.cs | 2 +- .../Query/Internal/MySQLParameterBasedSqlProcessorFactory.cs | 2 +- EFCore/src/Query/Internal/MySQLQueryCompilationContext.cs | 2 +- .../src/Query/Internal/MySQLQueryCompilationContextFactory.cs | 2 +- EFCore/src/Query/Internal/MySQLQueryStringFactory.cs | 2 +- .../src/Query/Internal/MySQLQueryTranslationPostprocessor.cs | 2 +- .../Internal/MySQLQueryTranslationPostprocessorFactory.cs | 2 +- EFCore/src/Query/Internal/MySQLSqlExpressionFactory.cs | 2 +- EFCore/src/Query/Internal/MySQLSqlNullabilityProcessor.cs | 2 +- .../Query/Internal/MySQLSqlTranslatingExpressionVisitor.cs | 2 +- .../Internal/MySQLSqlTranslatingExpressionVisitorFactory.cs | 2 +- EFCore/src/Query/Internal/MySQLStringMemberTranslator.cs | 2 +- EFCore/src/Query/Internal/MySQLStringMethodTranslator.cs | 2 +- EFCore/src/Query/MySQLJsonString.cs | 2 +- EFCore/src/Query/Sql/Internal/MySQLQueryGeneratorFactory.cs | 2 +- EFCore/src/Query/Sql/Internal/MySQLQuerySqlGenerator.cs | 2 +- EFCore/src/Scaffolding/Internal/MySQLCodeGenerator.cs | 2 +- EFCore/src/Scaffolding/Internal/MySQLDataReaderExtension.cs | 2 +- EFCore/src/Scaffolding/Internal/MySQLDatabaseModelFactory.cs | 2 +- EFCore/src/Storage/Internal/ByteArrayComparer.cs | 2 +- EFCore/src/Storage/Internal/BytesToDateTimeConverter.cs | 2 +- EFCore/src/Storage/Internal/IMySQLRelationalConnection.cs | 2 +- EFCore/src/Storage/Internal/MySQLBoolTypeMapping.cs | 2 +- EFCore/src/Storage/Internal/MySQLByteArrayTypeMapping.cs | 2 +- EFCore/src/Storage/Internal/MySQLDatabaseCreator.cs | 2 +- EFCore/src/Storage/Internal/MySQLDateTimeOffsetTypeMapping.cs | 2 +- EFCore/src/Storage/Internal/MySQLDateTypeMapping.cs | 2 +- EFCore/src/Storage/Internal/MySQLDatetimeTypeMapping.cs | 2 +- EFCore/src/Storage/Internal/MySQLDecimalTypeMapping.cs | 2 +- EFCore/src/Storage/Internal/MySQLDoubleTypeMapping.cs | 2 +- EFCore/src/Storage/Internal/MySQLExecutionStrategy.cs | 2 +- EFCore/src/Storage/Internal/MySQLExecutionStrategyFactory.cs | 2 +- EFCore/src/Storage/Internal/MySQLFloatTypeMapping.cs | 2 +- EFCore/src/Storage/Internal/MySQLGeometryTypeMapping.cs | 2 +- EFCore/src/Storage/Internal/MySQLGuidTypeMapping.cs | 2 +- EFCore/src/Storage/Internal/MySQLJsonChangeTrackingOptions.cs | 2 +- EFCore/src/Storage/Internal/MySQLJsonTypeMapping.cs | 2 +- EFCore/src/Storage/Internal/MySQLRelationalConnection.cs | 2 +- .../Storage/Internal/MySQLScaffoldingConnectionSettings.cs | 2 +- EFCore/src/Storage/Internal/MySQLSqlGenerationHelper.cs | 2 +- EFCore/src/Storage/Internal/MySQLStringTypeMapping.cs | 2 +- EFCore/src/Storage/Internal/MySQLTimeSpanMapping.cs | 2 +- .../src/Storage/Internal/MySQLTransientExceptionDetector.cs | 2 +- EFCore/src/Storage/Internal/MySQLTypeMapping.cs | 2 +- EFCore/src/Storage/Internal/MySQLTypeMappingSource.cs | 2 +- EFCore/src/Update/IMySQLUpdateSqlGenerator.cs | 2 +- EFCore/src/Update/MySQLModificationCommandBatch.cs | 2 +- EFCore/src/Update/MySQLModificationCommandBatchFactory.cs | 2 +- EFCore/src/Update/MySQLUpdateSqlGenerator.cs | 2 +- EFCore/src/Utils/Check.cs | 2 +- EFCore/src/Utils/CodeAnnotations.cs | 2 +- EFCore/src/Utils/CodeAttributes.cs | 2 +- EFCore/src/Utils/SharedTypeExtensions.cs | 2 +- EFCore/src/Utils/Static.cs | 2 +- EFCore/src/Utils/StringBuilderExtensions.cs | 2 +- .../ValueGeneration/Internal/MySQLValueGeneratorSelector.cs | 2 +- EFCore/tests/MySql.EFCore.Basic.Tests/BasicGuidTests.cs | 2 +- EFCore/tests/MySql.EFCore.Basic.Tests/ConcurrencyTests.cs | 2 +- EFCore/tests/MySql.EFCore.Basic.Tests/ConnectionTests.cs | 2 +- EFCore/tests/MySql.EFCore.Basic.Tests/DataTests.cs | 2 +- .../DbContextClasses/ConventionsContexts.cs | 2 +- .../DbContextClasses/EFFluentAPIContexts.cs | 2 +- .../DbContextClasses/EntitiesClasses.cs | 2 +- .../DbContextClasses/SakilaLiteContext.cs | 2 +- .../DbContextClasses/TestsContexts.cs | 2 +- EFCore/tests/MySql.EFCore.Basic.Tests/DbFunctionsMySQLTest.cs | 2 +- EFCore/tests/MySql.EFCore.Basic.Tests/EFCoreTests.cs | 2 +- EFCore/tests/MySql.EFCore.Basic.Tests/FluentAPITests.cs | 2 +- EFCore/tests/MySql.EFCore.Basic.Tests/FunctionalTests.cs | 2 +- .../tests/MySql.EFCore.Basic.Tests/LoadingRelatedDataTests.cs | 2 +- EFCore/tests/MySql.EFCore.Basic.Tests/ModelingTests.cs | 2 +- EFCore/tests/MySql.EFCore.Basic.Tests/MultiSchemaTests.cs | 2 +- .../tests/MySql.EFCore.Basic.Tests/MySQLDatabaseFacadeTest.cs | 2 +- EFCore/tests/MySql.EFCore.Basic.Tests/MySQLTypeMapperTests.cs | 2 +- .../MySql.EFCore.Basic.Tests/Properties/DatabaseSetup.sql | 2 +- .../tests/MySql.EFCore.Basic.Tests/ShadowPropertiesTests.cs | 2 +- EFCore/tests/MySql.EFCore.Basic.Tests/UpdateTests.cs | 2 +- .../MySql.EFCore.Basic.Tests/Utils/EntityTestsFixtureClass.cs | 2 +- EFCore/tests/MySql.EFCore.Basic.Tests/Utils/MySqlTestStore.cs | 2 +- EFCore/tests/MySql.EFCore.Basic.Tests/Utils/TestUtils.cs | 2 +- EFCore/tests/MySql.EFCore.Design.Tests/Extensions.cs | 2 +- .../MySQLAnnotationCodeGeneratorTest.cs | 2 +- .../tests/MySql.EFCore.Design.Tests/MySQLCodeGeneratorTest.cs | 2 +- .../MySQLDatabaseModelFactoryTest.cs | 2 +- .../MySql.EFCore.Design.Tests/MySQLDatabaseModelFixture.cs | 2 +- .../MySQLDesignTimeProviderServicesTest.cs | 2 +- .../MySql.EFCore.Design.Tests/Properties/sakiladb-schema.sql | 2 +- EFCore/tests/MySql.EFCore.Design.Tests/Properties/world.sql | 2 +- .../MySQLHistoryRepositoryTests.cs | 2 +- .../MySql.EFCore.Migrations.Tests/MySQLMigrationsTests.cs | 2 +- .../MySqlMigrationsGeneratorTest.cs | 2 +- .../MySqlMigrationsGeneratorTestBase.cs | 2 +- .../MySql.EFCore.Migrations.Tests/Utilities/ContextUtils.cs | 2 +- EntityFramework/src/EFMySqlCommand.cs | 2 +- EntityFramework/src/EFMySqlDataReader.cs | 2 +- EntityFramework/src/Fragments/InputFragment.cs | 2 +- EntityFramework/src/Fragments/JoinFragment.cs | 2 +- EntityFramework/src/Fragments/SqlFragment.cs | 2 +- EntityFramework/src/Fragments/TableFragment.cs | 2 +- EntityFramework/src/Generators/DeleteGenerator.cs | 2 +- EntityFramework/src/Generators/FunctionGenerator.cs | 2 +- EntityFramework/src/Generators/FunctionProcessor.cs | 2 +- EntityFramework/src/Generators/InsertGenerator.cs | 2 +- EntityFramework/src/Generators/Scope.cs | 2 +- EntityFramework/src/Generators/SelectGenerator.cs | 2 +- EntityFramework/src/Generators/SqlGenerator.cs | 2 +- EntityFramework/src/Generators/UpdateGenerator.cs | 2 +- EntityFramework/src/Metadata.cs | 2 +- EntityFramework/src/MySql.Data.EntityFramework.csproj | 2 +- EntityFramework/src/MySqlConnectionFactory.cs | 2 +- EntityFramework/src/MySqlDependencyResolver.cs | 2 +- EntityFramework/src/MySqlEFConfiguration.cs | 2 +- EntityFramework/src/MySqlExecutionStrategy.cs | 2 +- EntityFramework/src/MySqlHistoryContext.cs | 2 +- EntityFramework/src/MySqlLogger.cs | 2 +- EntityFramework/src/MySqlMigrationSqlGenerator.cs | 2 +- EntityFramework/src/MySqlSpatialDataReader.cs | 2 +- EntityFramework/src/MySqlSpatialServices.cs | 2 +- EntityFramework/src/Properties/AssemblyInfo.cs | 2 +- EntityFramework/src/Properties/VersionInfo.cs | 2 +- EntityFramework/src/ProviderManifest.cs | 2 +- EntityFramework/src/ProviderServices.cs | 2 +- EntityFramework/src/Statements/DeleteStatement.cs | 2 +- EntityFramework/src/Statements/InsertStatement.cs | 2 +- EntityFramework/src/Statements/SelectStatement.cs | 2 +- EntityFramework/src/Statements/UpdateStatement.cs | 2 +- .../MySql.EntityFramework.Basic.Tests/AggregateOperators.cs | 2 +- .../MySql.EntityFramework.Basic.Tests/CanonicalFunctions.cs | 2 +- .../tests/MySql.EntityFramework.Basic.Tests/DataTypeTests.cs | 2 +- .../MySql.EntityFramework.Basic.Tests/DatesTypesTests.cs | 2 +- .../tests/MySql.EntityFramework.Basic.Tests/DefaultContext.cs | 2 +- .../tests/MySql.EntityFramework.Basic.Tests/DefaultFixture.cs | 2 +- .../tests/MySql.EntityFramework.Basic.Tests/DeleteTests.cs | 2 +- .../MySql.EntityFramework.Basic.Tests/ExpressionTests.cs | 2 +- .../MySql.EntityFramework.Basic.Tests/GenericListener.cs | 2 +- .../tests/MySql.EntityFramework.Basic.Tests/InsertTests.cs | 2 +- .../tests/MySql.EntityFramework.Basic.Tests/JoinTests.cs | 2 +- .../MySql.EntityFramework.Basic.Tests.csproj | 4 ++-- .../MySql.EntityFramework.Basic.Tests/OrderingAndGrouping.cs | 2 +- .../tests/MySql.EntityFramework.Basic.Tests/Paging.cs | 2 +- .../ProceduresAndFunctions.cs | 2 +- .../Properties/AssemblyInfo.cs | 4 ++-- .../ProviderManifestTests.cs | 2 +- .../ProviderServicesTests.cs | 2 +- .../MySql.EntityFramework.Basic.Tests/RelationalOperators.cs | 2 +- .../MySql.EntityFramework.Basic.Tests/RestrictionOperators.cs | 2 +- .../MySql.EntityFramework.Basic.Tests/SchemaInformation.cs | 2 +- .../tests/MySql.EntityFramework.Basic.Tests/SetOperators.cs | 2 +- .../tests/MySql.EntityFramework.Basic.Tests/SimpleQuery.cs | 2 +- .../tests/MySql.EntityFramework.Basic.Tests/UpdateTests.cs | 2 +- .../tests/MySql.EntityFramework.Basic.Tests/Wizard.cs | 2 +- .../tests/MySql.EntityFramework.CodeFirst.Tests/Blogs.cs | 2 +- .../MySql.EntityFramework.CodeFirst.Tests/CodeFirstFixture.cs | 4 ++-- .../MySql.EntityFramework.CodeFirst.Tests/CodeFirstTests.cs | 2 +- .../ContextForNormalFk.cs | 2 +- .../MySql.EntityFramework.CodeFirst.Tests/ContextForString.cs | 2 +- .../tests/MySql.EntityFramework.CodeFirst.Tests/Dinosauria.cs | 2 +- .../tests/MySql.EntityFramework.CodeFirst.Tests/Movie.cs | 2 +- .../MovieContextCodeBasedConfiguration.cs | 2 +- .../MySql.EntityFramework.CodeFirst.Tests.csproj | 4 ++-- .../MySql.EntityFramework.CodeFirst.Tests/PromotionsDB.cs | 2 +- .../Properties/AssemblyInfo.cs | 4 ++-- .../Properties/sakila-data.sql | 2 +- .../Properties/sakila-schema.sql | 2 +- .../SakilaModel/SakilaDb.cs | 2 +- .../SakilaModel/actor.cs | 2 +- .../SakilaModel/actor_info.cs | 2 +- .../SakilaModel/address.cs | 2 +- .../SakilaModel/category.cs | 2 +- .../MySql.EntityFramework.CodeFirst.Tests/SakilaModel/city.cs | 2 +- .../SakilaModel/country.cs | 2 +- .../SakilaModel/customer.cs | 2 +- .../SakilaModel/customer_list.cs | 2 +- .../MySql.EntityFramework.CodeFirst.Tests/SakilaModel/film.cs | 2 +- .../SakilaModel/film_actor.cs | 2 +- .../SakilaModel/film_category.cs | 2 +- .../SakilaModel/film_list.cs | 2 +- .../SakilaModel/film_text.cs | 2 +- .../SakilaModel/inventory.cs | 2 +- .../SakilaModel/language.cs | 2 +- .../SakilaModel/nicer_but_slower_film_list.cs | 2 +- .../SakilaModel/payment.cs | 2 +- .../SakilaModel/rental.cs | 2 +- .../SakilaModel/sales_by_film_category.cs | 2 +- .../SakilaModel/sales_by_store.cs | 2 +- .../SakilaModel/staff.cs | 2 +- .../SakilaModel/staff_list.cs | 2 +- .../SakilaModel/store.cs | 2 +- .../tests/MySql.EntityFramework.CodeFirst.Tests/Ship.cs | 2 +- .../tests/MySql.EntityFramework.CodeFirst.Tests/SiteDB.cs | 2 +- .../MySql.EntityFramework.CodeFirst.Tests/TransactionTests.cs | 2 +- .../tests/MySql.EntityFramework.CodeFirst.Tests/Vehicle.cs | 2 +- .../MySql.EntityFramework.Migrations.Tests/BlogsModel.cs | 2 +- .../MySql.EntityFramework.Migrations.Tests/MyConfiguration.cs | 2 +- .../MySql.EntityFramework.Migrations.Tests.csproj | 4 ++-- .../MySqlMigrationsTests.cs | 2 +- .../Properties/AssemblyInfo.cs | 4 ++-- .../SetUpMigrationsTests.cs | 2 +- MySQL.Data.OpenTelemetry/src/MySQL.Data.OpenTelemetry.csproj | 2 +- MySQL.Data.OpenTelemetry/src/Properties/AssemblyInfo.cs | 2 +- MySQL.Data.OpenTelemetry/src/Properties/VersionInfo.cs | 2 +- MySQL.Data.OpenTelemetry/src/TraceProviderBuilderExtension.cs | 4 ++-- MySQL.Data/MySql.Replication.Tests/BaseTest.cs | 2 +- MySQL.Data/MySql.Replication.Tests/Properties/AssemblyInfo.cs | 4 ++-- MySQL.Data/MySql.Replication.Tests/ReplicationTest.cs | 2 +- MySQL.Data/MySql.Replication.Tests/SetUp.cs | 2 +- MySQL.Data/src/Authentication/AuthenticationManager.cs | 2 +- .../src/Authentication/CachingSha2AuthenticationPlugin.cs | 2 +- MySQL.Data/src/Authentication/ClearPasswordPlugin.cs | 2 +- MySQL.Data/src/Authentication/FIDO/FidoAssertion.cs | 2 +- MySQL.Data/src/Authentication/FIDO/FidoDevice.cs | 2 +- MySQL.Data/src/Authentication/FIDO/FidoDeviceInfo.cs | 2 +- MySQL.Data/src/Authentication/FIDO/Native/NativeMethods.cs | 2 +- MySQL.Data/src/Authentication/FIDO/Native/Structs.cs | 2 +- .../src/Authentication/FIDO/Utility/ConstStringMarshaler.cs | 2 +- MySQL.Data/src/Authentication/FIDO/Utility/Enums.cs | 2 +- MySQL.Data/src/Authentication/FIDO/Utility/Extensions.cs | 2 +- MySQL.Data/src/Authentication/FIDO/Utility/FidoExceptions.cs | 2 +- MySQL.Data/src/Authentication/FIDO/Utility/Init.cs | 2 +- MySQL.Data/src/Authentication/GSSAPI/Const.cs | 4 ++-- MySQL.Data/src/Authentication/GSSAPI/GssContext.cs | 2 +- MySQL.Data/src/Authentication/GSSAPI/GssContextFlags.cs | 2 +- MySQL.Data/src/Authentication/GSSAPI/GssCredentials.cs | 2 +- MySQL.Data/src/Authentication/GSSAPI/GssapiMechanism.cs | 2 +- .../src/Authentication/GSSAPI/Native/GssBufferDescStruct.cs | 2 +- MySQL.Data/src/Authentication/GSSAPI/Native/GssOidStruct.cs | 2 +- MySQL.Data/src/Authentication/GSSAPI/Native/NativeMethods.cs | 2 +- .../src/Authentication/GSSAPI/Native/NativeMethodsLinux.cs | 2 +- .../src/Authentication/GSSAPI/Native/NativeMethodsWin64.cs | 2 +- MySQL.Data/src/Authentication/GSSAPI/Utility/Disposable.cs | 2 +- .../src/Authentication/GSSAPI/Utility/ExceptionMessages.cs | 2 +- MySQL.Data/src/Authentication/GSSAPI/Utility/GssType.cs | 2 +- .../src/Authentication/GSSAPI/Utility/KerberosConfig.cs | 2 +- MySQL.Data/src/Authentication/GSSAPI/Utility/Pinned.cs | 2 +- MySQL.Data/src/Authentication/KerberosAuthenticationPlugin.cs | 2 +- MySQL.Data/src/Authentication/MySQLAuthenticationPlugin.cs | 2 +- MySQL.Data/src/Authentication/MySqlPemReader.cs | 2 +- MySQL.Data/src/Authentication/MySqlSASLPlugin.cs | 2 +- MySQL.Data/src/Authentication/NativePasswordPlugins.cs | 2 +- MySQL.Data/src/Authentication/OciAuthenticationPlugin.cs | 2 +- .../src/Authentication/OpenIdConnectClientAuthentication.cs | 2 +- MySQL.Data/src/Authentication/SSPI/Const.cs | 2 +- MySQL.Data/src/Authentication/SSPI/NativeMethods.cs | 2 +- MySQL.Data/src/Authentication/SSPI/SspiCredentials.cs | 2 +- MySQL.Data/src/Authentication/SSPI/SspiSecurityContext.cs | 2 +- MySQL.Data/src/Authentication/SSPI/Structs.cs | 2 +- MySQL.Data/src/Authentication/ScramBase.cs | 2 +- MySQL.Data/src/Authentication/ScramSha1Mechanism.cs | 2 +- MySQL.Data/src/Authentication/ScramSha256Mechanism.cs | 2 +- MySQL.Data/src/Authentication/Sha256AuthenticationPlugin.cs | 2 +- .../src/Authentication/Sha256MemoryAuthenticationPlugin.cs | 2 +- MySQL.Data/src/Authentication/WebAuthnAuthenticationPlugin.cs | 2 +- MySQL.Data/src/Authentication/WindowsAuthenticationPlugin.cs | 2 +- MySQL.Data/src/BulkLoader.cs | 2 +- MySQL.Data/src/CharSetMap.cs | 2 +- MySQL.Data/src/CompressedStream.cs | 2 +- MySQL.Data/src/Crypt.cs | 2 +- MySQL.Data/src/Driver.cs | 2 +- MySQL.Data/src/Exception.cs | 2 +- MySQL.Data/src/Failover/FailoverGroup.cs | 2 +- MySQL.Data/src/Failover/FailoverManager.cs | 2 +- MySQL.Data/src/Failover/FailoverServer.cs | 2 +- MySQL.Data/src/Failover/RandomFailoverGroup.cs | 2 +- MySQL.Data/src/Failover/SequentialFailoverGroup.cs | 2 +- MySQL.Data/src/Field.cs | 2 +- MySQL.Data/src/Framework/net462/SystemPerformanceMonitor.cs | 2 +- .../src/Framework/netstandard2_0/AuthenticationManager.cs | 2 +- MySQL.Data/src/Framework/netstandard2_0/CommandBuilder.cs | 2 +- .../src/Framework/netstandard2_0/MySqlClientPermission.cs | 2 +- .../netstandard2_0/MySqlClientPermissionAttribute.cs | 2 +- MySQL.Data/src/Framework/netstandard2_0/MySqlConfiguration.cs | 2 +- MySQL.Data/src/Framework/netstandard2_0/MySqlHelper.cs | 2 +- .../Framework/netstandard2_0/MySqlPromotableTransaction.cs | 2 +- .../src/Framework/netstandard2_0/MySqlSecurityPermission.cs | 2 +- MySQL.Data/src/Framework/netstandard2_0/dataadapter.cs | 2 +- MySQL.Data/src/ISSchemaProvider.cs | 2 +- MySQL.Data/src/Interceptors/CommandInterceptor.cs | 2 +- MySQL.Data/src/Interceptors/ExceptionInterceptor.cs | 2 +- MySQL.Data/src/Interceptors/Interceptor.cs | 2 +- MySQL.Data/src/MySQLActivitySource.cs | 2 +- MySQL.Data/src/MySql.Data.csproj | 2 +- MySQL.Data/src/MySqlAttribute.cs | 2 +- MySQL.Data/src/MySqlAttributeCollection.cs | 2 +- MySQL.Data/src/MySqlBaseConnectionStringBuilder.cs | 2 +- MySQL.Data/src/MySqlClientFactory.cs | 2 +- MySQL.Data/src/MySqlCommand.cs | 2 +- MySQL.Data/src/MySqlConnection.cs | 2 +- MySQL.Data/src/MySqlConnectionStringBuilder.cs | 2 +- MySQL.Data/src/MySqlDataReader.cs | 2 +- MySQL.Data/src/MySqlError.cs | 2 +- MySQL.Data/src/MySqlHelper.cs | 2 +- MySQL.Data/src/MySqlPacket.cs | 2 +- MySQL.Data/src/MySqlParameter.cs | 2 +- MySQL.Data/src/MySqlParameterCollection.cs | 2 +- MySQL.Data/src/MySqlPool.cs | 2 +- MySQL.Data/src/MySqlPoolManager.cs | 2 +- MySQL.Data/src/MySqlScript.cs | 2 +- MySQL.Data/src/MySqlStream.cs | 2 +- MySQL.Data/src/MySqlTrace.cs | 2 +- MySQL.Data/src/MySqlTransaction.cs | 2 +- MySQL.Data/src/MysqlDefs.cs | 2 +- MySQL.Data/src/NativeDriver.cs | 2 +- MySQL.Data/src/OkPacket.cs | 2 +- MySQL.Data/src/PacketBitConverter.cs | 2 +- MySQL.Data/src/PerformanceMonitor.cs | 2 +- MySQL.Data/src/PreparableStatement.cs | 2 +- MySQL.Data/src/ProcedureCache.cs | 2 +- MySQL.Data/src/Properties/AssemblyInfo.cs | 2 +- MySQL.Data/src/Properties/VersionInfo.cs | 2 +- MySQL.Data/src/Replication/ReplicationConfiguration.cs | 2 +- MySQL.Data/src/Replication/ReplicationManager.cs | 2 +- .../src/Replication/ReplicationRoundRobinServerGroup.cs | 2 +- MySQL.Data/src/Replication/ReplicationServer.cs | 2 +- MySQL.Data/src/Replication/ReplicationServerGroup.cs | 2 +- MySQL.Data/src/ResultSet.cs | 2 +- MySQL.Data/src/Runtime.cs | 2 +- MySQL.Data/src/Schema.cs | 2 +- MySQL.Data/src/SchemaProvider.cs | 2 +- MySQL.Data/src/Statement.cs | 2 +- MySQL.Data/src/StoredProcedure.cs | 2 +- MySQL.Data/src/TableCache.cs | 4 ++-- MySQL.Data/src/TimedStream.cs | 2 +- MySQL.Data/src/TracingDriver.cs | 2 +- MySQL.Data/src/Types/IMySqlValue.cs | 2 +- MySQL.Data/src/Types/MetaData.cs | 2 +- MySQL.Data/src/Types/MySqlBinary.cs | 2 +- MySQL.Data/src/Types/MySqlBit.cs | 2 +- MySQL.Data/src/Types/MySqlByte.cs | 2 +- MySQL.Data/src/Types/MySqlConversionException.cs | 2 +- MySQL.Data/src/Types/MySqlDateTime.cs | 2 +- MySQL.Data/src/Types/MySqlDecimal.cs | 2 +- MySQL.Data/src/Types/MySqlDouble.cs | 2 +- MySQL.Data/src/Types/MySqlGeometry.cs | 2 +- MySQL.Data/src/Types/MySqlGuid.cs | 2 +- MySQL.Data/src/Types/MySqlInt16.cs | 2 +- MySQL.Data/src/Types/MySqlInt32.cs | 2 +- MySQL.Data/src/Types/MySqlInt64.cs | 2 +- MySQL.Data/src/Types/MySqlSingle.cs | 2 +- MySQL.Data/src/Types/MySqlString.cs | 2 +- MySQL.Data/src/Types/MySqlTime.cs | 2 +- MySQL.Data/src/Types/MySqlUByte.cs | 2 +- MySQL.Data/src/Types/MySqlUInt16.cs | 2 +- MySQL.Data/src/Types/MySqlUInt32.cs | 2 +- MySQL.Data/src/Types/MySqlUInt64.cs | 2 +- MySQL.Data/src/Utils.cs | 2 +- .../src/X/Authentication/ExternalAuthenticationPlugin.cs | 2 +- .../src/X/Authentication/MySQL41AuthenticationPlugin.cs | 2 +- MySQL.Data/src/X/Authentication/PlainAuthenticationPlugin.cs | 2 +- MySQL.Data/src/X/Common/Tools.cs | 2 +- MySQL.Data/src/X/Common/UnmanagedLibraryLoader.cs | 2 +- MySQL.Data/src/X/Communication/CommunicationPacket.cs | 2 +- MySQL.Data/src/X/Communication/XCompressionController.cs | 2 +- MySQL.Data/src/X/Communication/XPacketProcessor.cs | 2 +- MySQL.Data/src/X/Communication/XPacketReaderWriter.cs | 2 +- MySQL.Data/src/X/Data/CollationMap.cs | 2 +- MySQL.Data/src/X/Data/Enums.cs | 2 +- MySQL.Data/src/X/Protocol/ProtocolBase.cs | 2 +- MySQL.Data/src/X/Protocol/ValueDecoder.cs | 2 +- MySQL.Data/src/X/Protocol/X/BitDecoder.cs | 2 +- MySQL.Data/src/X/Protocol/X/ByteDecoder.cs | 2 +- MySQL.Data/src/X/Protocol/X/DecimalDecoder.cs | 2 +- MySQL.Data/src/X/Protocol/X/Enum.cs | 2 +- MySQL.Data/src/X/Protocol/X/ExpUnparser.cs | 2 +- MySQL.Data/src/X/Protocol/X/ExprParser.cs | 2 +- MySQL.Data/src/X/Protocol/X/ExprUtil.cs | 2 +- MySQL.Data/src/X/Protocol/X/FloatDecoder.cs | 2 +- MySQL.Data/src/X/Protocol/X/IntegerDecoder.cs | 2 +- MySQL.Data/src/X/Protocol/X/Protobuf/Mysqlx.cs | 2 +- MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxConnection.cs | 2 +- MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxCrud.cs | 2 +- MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxCursor.cs | 2 +- MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxDatatypes.cs | 2 +- MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxExpect.cs | 2 +- MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxExpr.cs | 2 +- MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxNotice.cs | 2 +- MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxPrepare.cs | 2 +- MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxResultset.cs | 2 +- MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxSession.cs | 2 +- MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxSql.cs | 2 +- MySQL.Data/src/X/Protocol/X/SetDecoder.cs | 2 +- MySQL.Data/src/X/Protocol/X/XDateTimeDecoder.cs | 2 +- MySQL.Data/src/X/Protocol/X/XProtocol.cs | 2 +- MySQL.Data/src/X/Protocol/X/XTimeDecoder.cs | 2 +- MySQL.Data/src/X/Protocol/X/XValueDecoderFactory.cs | 2 +- MySQL.Data/src/X/RoutingServices/DefaultRoutingService.cs | 2 +- MySQL.Data/src/X/RoutingServices/RoutingServiceBase.cs | 2 +- MySQL.Data/src/X/Serialization/JsonParser.cs | 2 +- MySQL.Data/src/X/Sessions/InternalSession.cs | 2 +- MySQL.Data/src/X/Sessions/QueueTaskScheduler.cs | 2 +- MySQL.Data/src/X/Sessions/XInternalSession.cs | 2 +- MySQL.Data/src/X/XDevAPI/BaseSession.cs | 2 +- MySQL.Data/src/X/XDevAPI/CRUD/AddStatement.cs | 2 +- .../src/X/XDevAPI/CRUD/CreateCollectionIndexStatement.cs | 2 +- MySQL.Data/src/X/XDevAPI/CRUD/CreateIndexParams.cs | 2 +- MySQL.Data/src/X/XDevAPI/CRUD/CrudStatement.cs | 2 +- MySQL.Data/src/X/XDevAPI/CRUD/DocResult.cs | 2 +- MySQL.Data/src/X/XDevAPI/CRUD/FindParams.cs | 2 +- MySQL.Data/src/X/XDevAPI/CRUD/FindStatement.cs | 2 +- MySQL.Data/src/X/XDevAPI/CRUD/ModifyStatement.cs | 2 +- MySQL.Data/src/X/XDevAPI/CRUD/RemoveStatement.cs | 2 +- MySQL.Data/src/X/XDevAPI/CRUD/UpdateSpec.cs | 2 +- MySQL.Data/src/X/XDevAPI/Client.cs | 2 +- MySQL.Data/src/X/XDevAPI/Collection.cs | 2 +- MySQL.Data/src/X/XDevAPI/Common/BaseResult.cs | 2 +- MySQL.Data/src/X/XDevAPI/Common/BaseStatement.cs | 2 +- MySQL.Data/src/X/XDevAPI/Common/BufferingResult.cs | 2 +- MySQL.Data/src/X/XDevAPI/Common/CollectionOptions.cs | 2 +- MySQL.Data/src/X/XDevAPI/Common/ColumnType.cs | 2 +- MySQL.Data/src/X/XDevAPI/Common/ErrorInfo.cs | 2 +- MySQL.Data/src/X/XDevAPI/Common/FilterParams.cs | 2 +- MySQL.Data/src/X/XDevAPI/Common/FilterableStatement.cs | 2 +- MySQL.Data/src/X/XDevAPI/Common/QueryStatement.cs | 2 +- MySQL.Data/src/X/XDevAPI/Common/Result.cs | 2 +- MySQL.Data/src/X/XDevAPI/Common/TargetedBaseStatement.cs | 2 +- MySQL.Data/src/X/XDevAPI/Common/WarningInfo.cs | 2 +- MySQL.Data/src/X/XDevAPI/DatabaseObject.cs | 2 +- MySQL.Data/src/X/XDevAPI/DbDoc.cs | 2 +- MySQL.Data/src/X/XDevAPI/GenericCollection.cs | 2 +- MySQL.Data/src/X/XDevAPI/Iterator.cs | 2 +- MySQL.Data/src/X/XDevAPI/MySqlExpression.cs | 2 +- MySQL.Data/src/X/XDevAPI/MySqlX.cs | 2 +- MySQL.Data/src/X/XDevAPI/MySqlXConnectionStringBuilder.cs | 2 +- MySQL.Data/src/X/XDevAPI/Relational/Column.cs | 2 +- MySQL.Data/src/X/XDevAPI/Relational/InternalRowResult.cs | 2 +- MySQL.Data/src/X/XDevAPI/Relational/Row.cs | 2 +- MySQL.Data/src/X/XDevAPI/Relational/RowResult.cs | 2 +- MySQL.Data/src/X/XDevAPI/Relational/SqlResult.cs | 2 +- MySQL.Data/src/X/XDevAPI/Relational/SqlStatement.cs | 2 +- MySQL.Data/src/X/XDevAPI/Relational/Table.cs | 2 +- MySQL.Data/src/X/XDevAPI/Relational/TableDeleteStatement.cs | 2 +- MySQL.Data/src/X/XDevAPI/Relational/TableInsertStatement.cs | 2 +- MySQL.Data/src/X/XDevAPI/Relational/TableSelectStatement.cs | 2 +- MySQL.Data/src/X/XDevAPI/Relational/TableUpdateStatement.cs | 2 +- MySQL.Data/src/X/XDevAPI/Schema.cs | 2 +- MySQL.Data/src/X/XDevAPI/Session.cs | 2 +- MySQL.Data/src/common/Cache.cs | 2 +- MySQL.Data/src/common/ContextString.cs | 2 +- MySQL.Data/src/common/Dns/DnsEnums.cs | 2 +- MySQL.Data/src/common/Dns/DnsQuestion.cs | 2 +- MySQL.Data/src/common/Dns/DnsRecordHeader.cs | 2 +- MySQL.Data/src/common/Dns/DnsRecordReader.cs | 2 +- MySQL.Data/src/common/Dns/DnsRecordUnknown.cs | 2 +- MySQL.Data/src/common/Dns/DnsRequest.cs | 2 +- MySQL.Data/src/common/Dns/DnsResolver.cs | 2 +- MySQL.Data/src/common/Dns/DnsResourceRecord.cs | 2 +- MySQL.Data/src/common/Dns/DnsResponse.cs | 2 +- MySQL.Data/src/common/Dns/DnsSrvRecord.cs | 2 +- MySQL.Data/src/common/DnsSrv.cs | 2 +- MySQL.Data/src/common/LowResolutionStopwatch.cs | 2 +- MySQL.Data/src/common/MyNetworkStream.cs | 2 +- MySQL.Data/src/common/MySqlConnectionStringOption.cs | 2 +- .../src/common/MySqlConnectionStringOptionCollection.cs | 2 +- MySQL.Data/src/common/MySqlTokenizer.cs | 2 +- MySQL.Data/src/common/NativeMethods.cs | 2 +- MySQL.Data/src/common/Platform.cs | 2 +- MySQL.Data/src/common/QueryNormalizer.cs | 2 +- MySQL.Data/src/common/Ssl.cs | 2 +- MySQL.Data/src/common/SslPemCertificateValidator.cs | 2 +- MySQL.Data/src/common/StreamCreator.cs | 2 +- MySQL.Data/src/common/StringUtility.cs | 2 +- MySQL.Data/src/common/UnixEndPoint.cs | 2 +- MySQL.Data/src/common/Version.cs | 2 +- MySQL.Data/src/common/netstandard2_0/NamedPipeStream.cs | 2 +- MySQL.Data/src/common/netstandard2_0/SharedMemoryStream.cs | 2 +- MySQL.Data/tests/MySql.Data.Tests/AttributeTests.cs | 2 +- MySQL.Data/tests/MySql.Data.Tests/AuthTests.cs | 2 +- MySQL.Data/tests/MySql.Data.Tests/BlobTests.cs | 2 +- MySQL.Data/tests/MySql.Data.Tests/BlobTestsCompressed.cs | 2 +- MySQL.Data/tests/MySql.Data.Tests/CharSetTests.cs | 2 +- MySQL.Data/tests/MySql.Data.Tests/CharSetUTF8Tests.cs | 2 +- MySQL.Data/tests/MySql.Data.Tests/ClientSideFailoverTests.cs | 2 +- MySQL.Data/tests/MySql.Data.Tests/CmdTests.cs | 2 +- MySQL.Data/tests/MySql.Data.Tests/CmdTestsCompressed.cs | 2 +- .../tests/MySql.Data.Tests/ConnectionStringBuilderTests.cs | 2 +- MySQL.Data/tests/MySql.Data.Tests/ConnectionTests.cs | 2 +- MySQL.Data/tests/MySql.Data.Tests/DataTypeTests.cs | 2 +- MySQL.Data/tests/MySql.Data.Tests/DateTimeTests.cs | 2 +- MySQL.Data/tests/MySql.Data.Tests/DnsSrvTests.cs | 2 +- MySQL.Data/tests/MySql.Data.Tests/EventTests.cs | 2 +- MySQL.Data/tests/MySql.Data.Tests/ExceptionTests.cs | 2 +- .../Framework/netstandard2_0/BlobTestsPipe.cs | 2 +- .../Framework/netstandard2_0/BlobTestsPipeCompressed.cs | 2 +- .../Framework/netstandard2_0/BlobTestsSharedMem.cs | 2 +- .../Framework/netstandard2_0/BlobTestsSharedMemCompressed.cs | 2 +- .../MySql.Data.Tests/Framework/netstandard2_0/CmdTestsPipe.cs | 2 +- .../Framework/netstandard2_0/CmdTestsPipeCompressed.cs | 2 +- .../Framework/netstandard2_0/CmdTestsSharedMem.cs | 2 +- .../Framework/netstandard2_0/CmdTestsSharedmemCompressed.cs | 2 +- .../MySql.Data.Tests/Framework/netstandard2_0/CultureTests.cs | 2 +- .../Framework/netstandard2_0/DataTypeTests.cs | 2 +- .../Framework/netstandard2_0/DateTimeTests.cs | 2 +- .../Framework/netstandard2_0/GetSchemaTests.cs | 2 +- .../Framework/netstandard2_0/InstallerTests.cs | 2 +- .../Framework/netstandard2_0/MediumTrust/MediumTrustDomain.cs | 2 +- .../netstandard2_0/MediumTrust/MediumTrustFixtureAttribute.cs | 2 +- .../netstandard2_0/MediumTrust/MediumTrustTestClassCommand.cs | 2 +- .../netstandard2_0/MediumTrust/MediumTrustTestCommand.cs | 2 +- .../netstandard2_0/MediumTrust/MySql.MediumTrustsTests.cs | 2 +- .../netstandard2_0/MediumTrust/MySqlClientPermissionTests.cs | 2 +- .../Framework/netstandard2_0/MySQLHelperTests.cs | 2 +- .../Framework/netstandard2_0/MySqlCommandBuilderTests.cs | 2 +- .../Framework/netstandard2_0/MySqlDataAdapterTests.cs | 2 +- .../Framework/netstandard2_0/MySqlDataReaderTests.cs | 2 +- .../Framework/netstandard2_0/NETCore20Tests.cs | 4 ++-- .../Framework/netstandard2_0/OutputParametersBatchPrepared.cs | 2 +- .../Framework/netstandard2_0/OutputParametersNoBatch.cs | 2 +- .../netstandard2_0/OutputParametersNoBatchPrepared.cs | 2 +- .../tests/MySql.Data.Tests/Framework/netstandard2_0/PSPipe.cs | 2 +- .../Framework/netstandard2_0/PSPipeCompressed.cs | 2 +- .../Framework/netstandard2_0/PSSharedMemory.cs | 2 +- .../Framework/netstandard2_0/PSSharedMemoryCompressed.cs | 2 +- .../Framework/netstandard2_0/PartialTrustSandbox.cs | 2 +- .../MySql.Data.Tests/Framework/netstandard2_0/PerfMonTests.cs | 2 +- .../Framework/netstandard2_0/ProcedureParameterTests.cs | 2 +- .../Framework/netstandard2_0/ReplicationTests.cs | 2 +- .../Framework/netstandard2_0/StressTestsPipe.cs | 2 +- .../Framework/netstandard2_0/StressTestsPipeCompressed.cs | 2 +- .../Framework/netstandard2_0/StressTestsSharedMemory.cs | 2 +- .../netstandard2_0/StressTestsSharedMemoryCompressed.cs | 2 +- .../Framework/netstandard2_0/ThreadingTests.cs | 2 +- .../Framework/netstandard2_0/TimeoutAndCancel.cs | 2 +- .../Framework/netstandard2_0/TimeoutAndCancelCompressed.cs | 2 +- .../Framework/netstandard2_0/TimeoutAndCancelPipe.cs | 2 +- .../Framework/netstandard2_0/TimeoutAndCancelSharedMemory.cs | 2 +- .../MySql.Data.Tests/Framework/netstandard2_0/TypeTests.cs | 2 +- .../Framework/netstandard2_0/UsageAdvisorTests.cs | 2 +- MySQL.Data/tests/MySql.Data.Tests/GenericListener.cs | 2 +- MySQL.Data/tests/MySql.Data.Tests/LoggingTests.cs | 2 +- MySQL.Data/tests/MySql.Data.Tests/MySql.Data.Tests.csproj | 4 ++-- MySQL.Data/tests/MySql.Data.Tests/MySqlBulkLoaderTests.cs | 2 +- MySQL.Data/tests/MySql.Data.Tests/MySqlDataReaderTests.cs | 2 +- MySQL.Data/tests/MySql.Data.Tests/OutputParametersBatch.cs | 2 +- MySQL.Data/tests/MySql.Data.Tests/ParameterTests.cs | 2 +- MySQL.Data/tests/MySql.Data.Tests/PoolingTests.cs | 2 +- .../tests/MySql.Data.Tests/PreparedStatementCompressed.cs | 2 +- MySQL.Data/tests/MySql.Data.Tests/PreparedStatements.cs | 2 +- MySQL.Data/tests/MySql.Data.Tests/Properties/AssemblyInfo.cs | 4 ++-- MySQL.Data/tests/MySql.Data.Tests/ScriptExecution.cs | 2 +- MySQL.Data/tests/MySql.Data.Tests/SimpleTransactions.cs | 2 +- MySQL.Data/tests/MySql.Data.Tests/SqlServerMode.cs | 2 +- MySQL.Data/tests/MySql.Data.Tests/SqlTokenizer.cs | 2 +- MySQL.Data/tests/MySql.Data.Tests/SslTests.cs | 2 +- MySQL.Data/tests/MySql.Data.Tests/StoredProcedure.cs | 2 +- .../tests/MySql.Data.Tests/StoredProcedureWithAccess.cs | 2 +- MySQL.Data/tests/MySql.Data.Tests/StressTests.cs | 2 +- MySQL.Data/tests/MySql.Data.Tests/StressTestsCompressed.cs | 2 +- MySQL.Data/tests/MySql.Data.Tests/Syntax.cs | 2 +- MySQL.Data/tests/MySql.Data.Tests/Syntax2.cs | 2 +- MySQL.Data/tests/MySql.Data.Tests/TableCaching.cs | 2 +- MySQL.Data/tests/MySql.Data.Tests/TestBase.cs | 2 +- MySQL.Data/tests/MySql.Data.Tests/Tokenizer.cs | 2 +- MySQL.Data/tests/MySql.Data.Tests/Transactions.cs | 2 +- MySQL.Data/tests/MySql.Data.Tests/UnixSockets.cs | 2 +- MySQL.Data/tests/MySql.Data.Tests/Utils.cs | 2 +- MySQL.Data/tests/MySqlX.Data.Tests/BaseTest.cs | 2 +- MySQL.Data/tests/MySqlX.Data.Tests/BasicFindTests.cs | 2 +- MySQL.Data/tests/MySqlX.Data.Tests/BasicSelectTests.cs | 2 +- .../tests/MySqlX.Data.Tests/CharsetAndCollationTests.cs | 2 +- MySQL.Data/tests/MySqlX.Data.Tests/ClientSideFailoverTests.cs | 2 +- MySQL.Data/tests/MySqlX.Data.Tests/ClientTests.cs | 2 +- MySQL.Data/tests/MySqlX.Data.Tests/CloseConnectionTests.cs | 2 +- MySQL.Data/tests/MySqlX.Data.Tests/CollectionAsyncTests.cs | 2 +- MySQL.Data/tests/MySqlX.Data.Tests/CollectionIndexTests.cs | 2 +- MySQL.Data/tests/MySqlX.Data.Tests/CollectionTests.cs | 2 +- MySQL.Data/tests/MySqlX.Data.Tests/CompressionTests.cs | 2 +- MySQL.Data/tests/MySqlX.Data.Tests/CrudInsertTests.cs | 2 +- MySQL.Data/tests/MySqlX.Data.Tests/CrudRemoveTests.cs | 2 +- MySQL.Data/tests/MySqlX.Data.Tests/CrudTests/CrudGCTests.cs | 2 +- .../tests/MySqlX.Data.Tests/CrudTests/DocBufferingTests.cs | 2 +- MySQL.Data/tests/MySqlX.Data.Tests/CrudUpdateTests.cs | 2 +- MySQL.Data/tests/MySqlX.Data.Tests/CustomTypeTests.cs | 2 +- MySQL.Data/tests/MySqlX.Data.Tests/DbDocTests.cs | 2 +- MySQL.Data/tests/MySqlX.Data.Tests/DnsSrvTests.cs | 2 +- MySQL.Data/tests/MySqlX.Data.Tests/ExprParserTests.cs | 2 +- MySQL.Data/tests/MySqlX.Data.Tests/GenericListener.cs | 2 +- MySQL.Data/tests/MySqlX.Data.Tests/JsonParserTests.cs | 2 +- MySQL.Data/tests/MySqlX.Data.Tests/MergePatch.cs | 2 +- MySQL.Data/tests/MySqlX.Data.Tests/MySqlX.Data.Tests.csproj | 4 ++-- MySQL.Data/tests/MySqlX.Data.Tests/PerformanceTests.cs | 2 +- MySQL.Data/tests/MySqlX.Data.Tests/PreparedStatementsTests.cs | 2 +- MySQL.Data/tests/MySqlX.Data.Tests/Properties/AssemblyInfo.cs | 4 ++-- .../MySqlX.Data.Tests/RelationalTests/ColumnMetadataTests.cs | 2 +- .../tests/MySqlX.Data.Tests/RelationalTests/DataTypeTests.cs | 2 +- .../tests/MySqlX.Data.Tests/RelationalTests/DateTimeTests.cs | 2 +- .../MySqlX.Data.Tests/RelationalTests/RelationalGCTests.cs | 2 +- .../MySqlX.Data.Tests/RelationalTests/RowBufferingTests.cs | 2 +- .../tests/MySqlX.Data.Tests/RelationalTests/SqlTests.cs | 2 +- .../MySqlX.Data.Tests/RelationalTests/TableAsyncTests.cs | 2 +- .../MySqlX.Data.Tests/RelationalTests/TableDeleteTests.cs | 2 +- .../MySqlX.Data.Tests/RelationalTests/TableInsertTests.cs | 2 +- .../MySqlX.Data.Tests/RelationalTests/TableSelectTests.cs | 2 +- .../MySqlX.Data.Tests/RelationalTests/TableUpdateTests.cs | 2 +- .../tests/MySqlX.Data.Tests/RelationalTests/ViewTests.cs | 2 +- MySQL.Data/tests/MySqlX.Data.Tests/SchemaTests.cs | 2 +- MySQL.Data/tests/MySqlX.Data.Tests/SessionTests.cs | 2 +- MySQL.Data/tests/MySqlX.Data.Tests/SslTests.cs | 2 +- MySQL.Data/tests/MySqlX.Data.Tests/TransactionTests.cs | 2 +- MySQL.Data/tests/MySqlX.Data.Tests/UnixSocketsTests.cs | 2 +- MySQL.Data/tests/MySqlX.Data.Tests/XAuth.cs | 2 +- .../tests/MySqlX.Data.Tests/XConnectionStringBuilderTests.cs | 2 +- MySql.Web/src/Application.cs | 2 +- MySql.Web/src/ConfigUtility.cs | 2 +- MySql.Web/src/MembershipProvider.cs | 2 +- MySql.Web/src/MySql.Web.csproj | 2 +- MySql.Web/src/MySqlDatabaseWrapper.cs | 2 +- MySql.Web/src/MySqlWebSecurity.cs | 2 +- MySql.Web/src/PersonalizationConnectionHelper.cs | 2 +- MySql.Web/src/PersonalizationProvider.cs | 2 +- MySql.Web/src/PersonalizationProviderProcedures.cs | 2 +- MySql.Web/src/ProfileProvider.cs | 2 +- MySql.Web/src/Properties/AssemblyInfo.cs | 2 +- MySql.Web/src/Properties/VersionInfo.cs | 2 +- MySql.Web/src/RoleProvider.cs | 2 +- MySql.Web/src/Runtime.cs | 2 +- MySql.Web/src/SchemaManager.cs | 2 +- MySql.Web/src/SessionProvider.cs | 2 +- MySql.Web/src/SimpleMembershipProvider.cs | 2 +- MySql.Web/src/SimpleRoleProvider.cs | 2 +- MySql.Web/src/SiteMapProvider.cs | 2 +- MySql.Web/tests/MySql.Web.Tests.csproj | 4 ++-- MySql.Web/tests/PersonalizationTests.cs | 2 +- MySql.Web/tests/ProfileTests.cs | 2 +- MySql.Web/tests/Properties/AssemblyInfo.cs | 4 ++-- MySql.Web/tests/RoleManagement.cs | 2 +- MySql.Web/tests/SchemaManagerTests.cs | 2 +- MySql.Web/tests/SchemaTests.cs | 2 +- MySql.Web/tests/SessionLocking/Global.asax.cs | 2 +- MySql.Web/tests/SessionLocking/InitSessionLocking.aspx.cs | 2 +- MySql.Web/tests/SessionLocking/read.aspx.cs | 2 +- MySql.Web/tests/SessionLocking/write.aspx.cs | 2 +- MySql.Web/tests/SessionLocking/write2.aspx.cs | 2 +- MySql.Web/tests/SessionTests.cs | 2 +- MySql.Web/tests/SimpleMembership.cs | 2 +- MySql.Web/tests/SiteMapTests.cs | 2 +- MySql.Web/tests/TestProfile.cs | 2 +- MySql.Web/tests/UserManagement.cs | 2 +- MySql.Web/tests/WebTestBase.cs | 2 +- 715 files changed, 733 insertions(+), 733 deletions(-) diff --git a/Documentation/docfx.json b/Documentation/docfx.json index 349839616..d01f8fce2 100644 --- a/Documentation/docfx.json +++ b/Documentation/docfx.json @@ -86,4 +86,4 @@ "markdownEngineName": "markdig", "xrefService": [ "https://xref.docs.microsoft.com/query?uid={uid}" ] } -} \ No newline at end of file +} diff --git a/EFCore/src/DataAnnotations/MySQLCharsetAttribute.cs b/EFCore/src/DataAnnotations/MySQLCharsetAttribute.cs index 72907a16b..6541f6d5e 100644 --- a/EFCore/src/DataAnnotations/MySQLCharsetAttribute.cs +++ b/EFCore/src/DataAnnotations/MySQLCharsetAttribute.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/DataAnnotations/MySQLCollationAttribute.cs b/EFCore/src/DataAnnotations/MySQLCollationAttribute.cs index a1a10b00c..53cdb1bb8 100644 --- a/EFCore/src/DataAnnotations/MySQLCollationAttribute.cs +++ b/EFCore/src/DataAnnotations/MySQLCollationAttribute.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Design/Internal/MySQLAnnotationCodeGenerator.cs b/EFCore/src/Design/Internal/MySQLAnnotationCodeGenerator.cs index 3bc26690f..4fce96898 100644 --- a/EFCore/src/Design/Internal/MySQLAnnotationCodeGenerator.cs +++ b/EFCore/src/Design/Internal/MySQLAnnotationCodeGenerator.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Design/Internal/MySQLDesignTimeServices.cs b/EFCore/src/Design/Internal/MySQLDesignTimeServices.cs index a621f6a8f..30389cea5 100644 --- a/EFCore/src/Design/Internal/MySQLDesignTimeServices.cs +++ b/EFCore/src/Design/Internal/MySQLDesignTimeServices.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Diagnostics/Internal/MySQLLoggingDefinitions.cs b/EFCore/src/Diagnostics/Internal/MySQLLoggingDefinitions.cs index b95397df1..6ac04605a 100644 --- a/EFCore/src/Diagnostics/Internal/MySQLLoggingDefinitions.cs +++ b/EFCore/src/Diagnostics/Internal/MySQLLoggingDefinitions.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Diagnostics/MySQLEventId.cs b/EFCore/src/Diagnostics/MySQLEventId.cs index c51b1d6a8..e2a639ea6 100644 --- a/EFCore/src/Diagnostics/MySQLEventId.cs +++ b/EFCore/src/Diagnostics/MySQLEventId.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Extensions/MySQLDatabaseFacadeExtensions.cs b/EFCore/src/Extensions/MySQLDatabaseFacadeExtensions.cs index 4e6b24506..43f02dfe9 100644 --- a/EFCore/src/Extensions/MySQLDatabaseFacadeExtensions.cs +++ b/EFCore/src/Extensions/MySQLDatabaseFacadeExtensions.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Extensions/MySQLDbContextOptionsExtensions.cs b/EFCore/src/Extensions/MySQLDbContextOptionsExtensions.cs index 02306ebf6..9cc0b5150 100644 --- a/EFCore/src/Extensions/MySQLDbContextOptionsExtensions.cs +++ b/EFCore/src/Extensions/MySQLDbContextOptionsExtensions.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Extensions/MySQLDbFunctionsEnums.cs b/EFCore/src/Extensions/MySQLDbFunctionsEnums.cs index 867fac2e9..48e224773 100644 --- a/EFCore/src/Extensions/MySQLDbFunctionsEnums.cs +++ b/EFCore/src/Extensions/MySQLDbFunctionsEnums.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Extensions/MySQLDbFunctionsExtensions.cs b/EFCore/src/Extensions/MySQLDbFunctionsExtensions.cs index fcb9042ae..6cc956262 100644 --- a/EFCore/src/Extensions/MySQLDbFunctionsExtensions.cs +++ b/EFCore/src/Extensions/MySQLDbFunctionsExtensions.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Extensions/MySQLEntityTypeBuilderExtensions.cs b/EFCore/src/Extensions/MySQLEntityTypeBuilderExtensions.cs index fd8bf9b6a..33bc3b1e4 100644 --- a/EFCore/src/Extensions/MySQLEntityTypeBuilderExtensions.cs +++ b/EFCore/src/Extensions/MySQLEntityTypeBuilderExtensions.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Extensions/MySQLEntityTypeExtensions.cs b/EFCore/src/Extensions/MySQLEntityTypeExtensions.cs index 5465bfc06..9eec6cc26 100644 --- a/EFCore/src/Extensions/MySQLEntityTypeExtensions.cs +++ b/EFCore/src/Extensions/MySQLEntityTypeExtensions.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Extensions/MySQLIndexExtensions.cs b/EFCore/src/Extensions/MySQLIndexExtensions.cs index 0759214c0..bc4be7b3c 100644 --- a/EFCore/src/Extensions/MySQLIndexExtensions.cs +++ b/EFCore/src/Extensions/MySQLIndexExtensions.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Extensions/MySQLKeyBuilderExtensions.cs b/EFCore/src/Extensions/MySQLKeyBuilderExtensions.cs index 147d7f03b..72727aefb 100644 --- a/EFCore/src/Extensions/MySQLKeyBuilderExtensions.cs +++ b/EFCore/src/Extensions/MySQLKeyBuilderExtensions.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Extensions/MySQLKeyExtensions.cs b/EFCore/src/Extensions/MySQLKeyExtensions.cs index 71007b148..2be6817e1 100644 --- a/EFCore/src/Extensions/MySQLKeyExtensions.cs +++ b/EFCore/src/Extensions/MySQLKeyExtensions.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Extensions/MySQLMigrationBuilderExtensions.cs b/EFCore/src/Extensions/MySQLMigrationBuilderExtensions.cs index ff668966f..6aef77044 100644 --- a/EFCore/src/Extensions/MySQLMigrationBuilderExtensions.cs +++ b/EFCore/src/Extensions/MySQLMigrationBuilderExtensions.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Extensions/MySQLModelBuilderExtensions.cs b/EFCore/src/Extensions/MySQLModelBuilderExtensions.cs index 532b9eed3..89a4a2801 100644 --- a/EFCore/src/Extensions/MySQLModelBuilderExtensions.cs +++ b/EFCore/src/Extensions/MySQLModelBuilderExtensions.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Extensions/MySQLModelExtensions.cs b/EFCore/src/Extensions/MySQLModelExtensions.cs index 7f9f2cbb8..f2284ec4f 100644 --- a/EFCore/src/Extensions/MySQLModelExtensions.cs +++ b/EFCore/src/Extensions/MySQLModelExtensions.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Extensions/MySQLPropertyBuilderExtensions.cs b/EFCore/src/Extensions/MySQLPropertyBuilderExtensions.cs index 145f99d6e..88729618a 100644 --- a/EFCore/src/Extensions/MySQLPropertyBuilderExtensions.cs +++ b/EFCore/src/Extensions/MySQLPropertyBuilderExtensions.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Extensions/MySQLPropertyExtensions.cs b/EFCore/src/Extensions/MySQLPropertyExtensions.cs index 976550298..ebc0ebed1 100644 --- a/EFCore/src/Extensions/MySQLPropertyExtensions.cs +++ b/EFCore/src/Extensions/MySQLPropertyExtensions.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Extensions/MySQLServiceCollectionExtensions.cs b/EFCore/src/Extensions/MySQLServiceCollectionExtensions.cs index ce2e455a8..42317fa9b 100644 --- a/EFCore/src/Extensions/MySQLServiceCollectionExtensions.cs +++ b/EFCore/src/Extensions/MySQLServiceCollectionExtensions.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Extensions/MySQLTypeBaseExtensions.cs b/EFCore/src/Extensions/MySQLTypeBaseExtensions.cs index 509a2120d..ba1e608bc 100644 --- a/EFCore/src/Extensions/MySQLTypeBaseExtensions.cs +++ b/EFCore/src/Extensions/MySQLTypeBaseExtensions.cs @@ -1,4 +1,4 @@ -// Copyright © 2023, 2024, Oracle and/or its affiliates. +// Copyright © 2023, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Extensions/MySqlIndexBuilderExtensions.cs b/EFCore/src/Extensions/MySqlIndexBuilderExtensions.cs index 7cee66361..43257933f 100644 --- a/EFCore/src/Extensions/MySqlIndexBuilderExtensions.cs +++ b/EFCore/src/Extensions/MySqlIndexBuilderExtensions.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Infrastructure/Internal/IMySQLOptions.cs b/EFCore/src/Infrastructure/Internal/IMySQLOptions.cs index e23f97c94..116f21644 100644 --- a/EFCore/src/Infrastructure/Internal/IMySQLOptions.cs +++ b/EFCore/src/Infrastructure/Internal/IMySQLOptions.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Infrastructure/Internal/MySQLOptionsExtension.cs b/EFCore/src/Infrastructure/Internal/MySQLOptionsExtension.cs index c6c590b25..e2fc4616d 100644 --- a/EFCore/src/Infrastructure/Internal/MySQLOptionsExtension.cs +++ b/EFCore/src/Infrastructure/Internal/MySQLOptionsExtension.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Infrastructure/MySQLDbContextOptionsBuilder.cs b/EFCore/src/Infrastructure/MySQLDbContextOptionsBuilder.cs index 350318233..b01a40fcf 100644 --- a/EFCore/src/Infrastructure/MySQLDbContextOptionsBuilder.cs +++ b/EFCore/src/Infrastructure/MySQLDbContextOptionsBuilder.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Infrastructure/MySQLSchemaBehavior.cs b/EFCore/src/Infrastructure/MySQLSchemaBehavior.cs index acb97d767..75f1002e7 100644 --- a/EFCore/src/Infrastructure/MySQLSchemaBehavior.cs +++ b/EFCore/src/Infrastructure/MySQLSchemaBehavior.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Internal/MySQLModelValidator.cs b/EFCore/src/Internal/MySQLModelValidator.cs index d8c4f4d2d..3ffd0388f 100644 --- a/EFCore/src/Internal/MySQLModelValidator.cs +++ b/EFCore/src/Internal/MySQLModelValidator.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Internal/MySQLOptions.cs b/EFCore/src/Internal/MySQLOptions.cs index a238b6abe..de900fed8 100644 --- a/EFCore/src/Internal/MySQLOptions.cs +++ b/EFCore/src/Internal/MySQLOptions.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Internal/MySQLRetryingExecutionStrategy.cs b/EFCore/src/Internal/MySQLRetryingExecutionStrategy.cs index 3ee230428..980fce139 100644 --- a/EFCore/src/Internal/MySQLRetryingExecutionStrategy.cs +++ b/EFCore/src/Internal/MySQLRetryingExecutionStrategy.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Internal/MySQLValueGenerationStrategyCompatibility.cs b/EFCore/src/Internal/MySQLValueGenerationStrategyCompatibility.cs index 913c31738..2697dc2e7 100644 --- a/EFCore/src/Internal/MySQLValueGenerationStrategyCompatibility.cs +++ b/EFCore/src/Internal/MySQLValueGenerationStrategyCompatibility.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Metadata/Conventions/MySQLConventionSetBuilder.cs b/EFCore/src/Metadata/Conventions/MySQLConventionSetBuilder.cs index 7d7fce3d0..3566c9fab 100644 --- a/EFCore/src/Metadata/Conventions/MySQLConventionSetBuilder.cs +++ b/EFCore/src/Metadata/Conventions/MySQLConventionSetBuilder.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Metadata/Conventions/MySQLValueGenerationConvention.cs b/EFCore/src/Metadata/Conventions/MySQLValueGenerationConvention.cs index 02167937a..4088d5797 100644 --- a/EFCore/src/Metadata/Conventions/MySQLValueGenerationConvention.cs +++ b/EFCore/src/Metadata/Conventions/MySQLValueGenerationConvention.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Metadata/Conventions/MySqlCharsetAttributeConvention.cs b/EFCore/src/Metadata/Conventions/MySqlCharsetAttributeConvention.cs index 4a7a91ac0..521cc2471 100644 --- a/EFCore/src/Metadata/Conventions/MySqlCharsetAttributeConvention.cs +++ b/EFCore/src/Metadata/Conventions/MySqlCharsetAttributeConvention.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Metadata/Conventions/MySqlCollationAttributeConvention.cs b/EFCore/src/Metadata/Conventions/MySqlCollationAttributeConvention.cs index 31aead290..9582ae16a 100644 --- a/EFCore/src/Metadata/Conventions/MySqlCollationAttributeConvention.cs +++ b/EFCore/src/Metadata/Conventions/MySqlCollationAttributeConvention.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Metadata/Conventions/MySqlEntityCharsetAttributeConvention.cs b/EFCore/src/Metadata/Conventions/MySqlEntityCharsetAttributeConvention.cs index 3b6be795c..9721eac51 100644 --- a/EFCore/src/Metadata/Conventions/MySqlEntityCharsetAttributeConvention.cs +++ b/EFCore/src/Metadata/Conventions/MySqlEntityCharsetAttributeConvention.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Metadata/Conventions/MySqlEntityCollationAttributeConvention.cs b/EFCore/src/Metadata/Conventions/MySqlEntityCollationAttributeConvention.cs index 6249a5145..5c2ea15c3 100644 --- a/EFCore/src/Metadata/Conventions/MySqlEntityCollationAttributeConvention.cs +++ b/EFCore/src/Metadata/Conventions/MySqlEntityCollationAttributeConvention.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Metadata/Internal/MySQLAnnotationNames.cs b/EFCore/src/Metadata/Internal/MySQLAnnotationNames.cs index 55dbdd66f..b60e8c7ca 100644 --- a/EFCore/src/Metadata/Internal/MySQLAnnotationNames.cs +++ b/EFCore/src/Metadata/Internal/MySQLAnnotationNames.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Metadata/Internal/MySQLAnnotationProvider.cs b/EFCore/src/Metadata/Internal/MySQLAnnotationProvider.cs index d437571e7..15783391d 100644 --- a/EFCore/src/Metadata/Internal/MySQLAnnotationProvider.cs +++ b/EFCore/src/Metadata/Internal/MySQLAnnotationProvider.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Metadata/MySQLValueGenerationStrategy.cs b/EFCore/src/Metadata/MySQLValueGenerationStrategy.cs index ca361acb4..730a80900 100644 --- a/EFCore/src/Metadata/MySQLValueGenerationStrategy.cs +++ b/EFCore/src/Metadata/MySQLValueGenerationStrategy.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Migrations/Internal/MySQLHistoryRepository.cs b/EFCore/src/Migrations/Internal/MySQLHistoryRepository.cs index 77f84336c..c5c86ebb6 100644 --- a/EFCore/src/Migrations/Internal/MySQLHistoryRepository.cs +++ b/EFCore/src/Migrations/Internal/MySQLHistoryRepository.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Migrations/Internal/MySQLMigrationDatabaseLockcs.cs b/EFCore/src/Migrations/Internal/MySQLMigrationDatabaseLockcs.cs index 139c378dc..ccd651a16 100644 --- a/EFCore/src/Migrations/Internal/MySQLMigrationDatabaseLockcs.cs +++ b/EFCore/src/Migrations/Internal/MySQLMigrationDatabaseLockcs.cs @@ -1,4 +1,4 @@ -// Copyright © 2024, Oracle and/or its affiliates. +// Copyright © 2024, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Migrations/Internal/MySQLMigrationsModelDiffer.cs b/EFCore/src/Migrations/Internal/MySQLMigrationsModelDiffer.cs index 809da75ae..ac7fc3e4f 100644 --- a/EFCore/src/Migrations/Internal/MySQLMigrationsModelDiffer.cs +++ b/EFCore/src/Migrations/Internal/MySQLMigrationsModelDiffer.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Migrations/Internal/MySQLMigrator.cs b/EFCore/src/Migrations/Internal/MySQLMigrator.cs index 23aa5d493..3534d9152 100644 --- a/EFCore/src/Migrations/Internal/MySQLMigrator.cs +++ b/EFCore/src/Migrations/Internal/MySQLMigrator.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Migrations/MySQLMigrationsSqlGenerator.cs b/EFCore/src/Migrations/MySQLMigrationsSqlGenerator.cs index 2ca5009c3..239ff6753 100644 --- a/EFCore/src/Migrations/MySQLMigrationsSqlGenerator.cs +++ b/EFCore/src/Migrations/MySQLMigrationsSqlGenerator.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Migrations/Operations/CreateDatabaseOperation.cs b/EFCore/src/Migrations/Operations/CreateDatabaseOperation.cs index 4dc9706fc..1e266a2ff 100644 --- a/EFCore/src/Migrations/Operations/CreateDatabaseOperation.cs +++ b/EFCore/src/Migrations/Operations/CreateDatabaseOperation.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Migrations/Operations/DropDatabaseOperation.cs b/EFCore/src/Migrations/Operations/DropDatabaseOperation.cs index 0e485c20b..bb9dc3bf0 100644 --- a/EFCore/src/Migrations/Operations/DropDatabaseOperation.cs +++ b/EFCore/src/Migrations/Operations/DropDatabaseOperation.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Migrations/Operations/MySQLDropPrimaryKeyAndRecreateForeignKeysOperation.cs b/EFCore/src/Migrations/Operations/MySQLDropPrimaryKeyAndRecreateForeignKeysOperation.cs index 4480fcc73..1626aff58 100644 --- a/EFCore/src/Migrations/Operations/MySQLDropPrimaryKeyAndRecreateForeignKeysOperation.cs +++ b/EFCore/src/Migrations/Operations/MySQLDropPrimaryKeyAndRecreateForeignKeysOperation.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Migrations/Operations/MySQLDropUniqueConstraintAndRecreateForeignKeysOperation.cs b/EFCore/src/Migrations/Operations/MySQLDropUniqueConstraintAndRecreateForeignKeysOperation.cs index 8989394bd..005a01f4b 100644 --- a/EFCore/src/Migrations/Operations/MySQLDropUniqueConstraintAndRecreateForeignKeysOperation.cs +++ b/EFCore/src/Migrations/Operations/MySQLDropUniqueConstraintAndRecreateForeignKeysOperation.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Properties/AssemblyInfo.cs b/EFCore/src/Properties/AssemblyInfo.cs index e5565c1a9..48eeec93c 100644 --- a/EFCore/src/Properties/AssemblyInfo.cs +++ b/EFCore/src/Properties/AssemblyInfo.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Properties/VersionInfo.cs b/EFCore/src/Properties/VersionInfo.cs index 9ff731567..9833fee26 100644 --- a/EFCore/src/Properties/VersionInfo.cs +++ b/EFCore/src/Properties/VersionInfo.cs @@ -1,4 +1,4 @@ -// Copyright © 2024, Oracle and/or its affiliates. +// Copyright © 2024, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Query/ExpressionTranslators/Internal/MySQLByteArrayMethodTranslator.cs b/EFCore/src/Query/ExpressionTranslators/Internal/MySQLByteArrayMethodTranslator.cs index d1a59fef5..61466321f 100644 --- a/EFCore/src/Query/ExpressionTranslators/Internal/MySQLByteArrayMethodTranslator.cs +++ b/EFCore/src/Query/ExpressionTranslators/Internal/MySQLByteArrayMethodTranslator.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Query/ExpressionTranslators/Internal/MySQLDbFunctionsExtensionsMethodTranslator.cs b/EFCore/src/Query/ExpressionTranslators/Internal/MySQLDbFunctionsExtensionsMethodTranslator.cs index 6bb8eb80f..82688e6cf 100644 --- a/EFCore/src/Query/ExpressionTranslators/Internal/MySQLDbFunctionsExtensionsMethodTranslator.cs +++ b/EFCore/src/Query/ExpressionTranslators/Internal/MySQLDbFunctionsExtensionsMethodTranslator.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Query/ExpressionTranslators/Internal/MySQLRegexIsMatchTranslator.cs b/EFCore/src/Query/ExpressionTranslators/Internal/MySQLRegexIsMatchTranslator.cs index f46e445cb..bda2f2990 100644 --- a/EFCore/src/Query/ExpressionTranslators/Internal/MySQLRegexIsMatchTranslator.cs +++ b/EFCore/src/Query/ExpressionTranslators/Internal/MySQLRegexIsMatchTranslator.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Query/ExpressionTranslators/Internal/MySQLStringLengthTranslator.cs b/EFCore/src/Query/ExpressionTranslators/Internal/MySQLStringLengthTranslator.cs index 2bb6e6986..64d23c763 100644 --- a/EFCore/src/Query/ExpressionTranslators/Internal/MySQLStringLengthTranslator.cs +++ b/EFCore/src/Query/ExpressionTranslators/Internal/MySQLStringLengthTranslator.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Query/Expressions/Internal/MySQLBinaryExpression.cs b/EFCore/src/Query/Expressions/Internal/MySQLBinaryExpression.cs index fb5cb4112..6b07143ad 100644 --- a/EFCore/src/Query/Expressions/Internal/MySQLBinaryExpression.cs +++ b/EFCore/src/Query/Expressions/Internal/MySQLBinaryExpression.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Query/Expressions/Internal/MySQLCollateExpression.cs b/EFCore/src/Query/Expressions/Internal/MySQLCollateExpression.cs index a88c77b49..bbb59165a 100644 --- a/EFCore/src/Query/Expressions/Internal/MySQLCollateExpression.cs +++ b/EFCore/src/Query/Expressions/Internal/MySQLCollateExpression.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Query/Expressions/Internal/MySQLColumnAliasReferenceExpression.cs b/EFCore/src/Query/Expressions/Internal/MySQLColumnAliasReferenceExpression.cs index 49a96f698..269c5386e 100644 --- a/EFCore/src/Query/Expressions/Internal/MySQLColumnAliasReferenceExpression.cs +++ b/EFCore/src/Query/Expressions/Internal/MySQLColumnAliasReferenceExpression.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Query/Expressions/Internal/MySQLComplexFunctionArgumentExpression.cs b/EFCore/src/Query/Expressions/Internal/MySQLComplexFunctionArgumentExpression.cs index 5f176545e..37bbf5420 100644 --- a/EFCore/src/Query/Expressions/Internal/MySQLComplexFunctionArgumentExpression.cs +++ b/EFCore/src/Query/Expressions/Internal/MySQLComplexFunctionArgumentExpression.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Query/Expressions/Internal/MySQLJsonArrayIndexExpression.cs b/EFCore/src/Query/Expressions/Internal/MySQLJsonArrayIndexExpression.cs index 6124ce5eb..79ba35577 100644 --- a/EFCore/src/Query/Expressions/Internal/MySQLJsonArrayIndexExpression.cs +++ b/EFCore/src/Query/Expressions/Internal/MySQLJsonArrayIndexExpression.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Query/Expressions/Internal/MySQLJsonTraversalExpression.cs b/EFCore/src/Query/Expressions/Internal/MySQLJsonTraversalExpression.cs index e3b8430ac..a2771b34d 100644 --- a/EFCore/src/Query/Expressions/Internal/MySQLJsonTraversalExpression.cs +++ b/EFCore/src/Query/Expressions/Internal/MySQLJsonTraversalExpression.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Query/Expressions/Internal/MySQLMatchExpression.cs b/EFCore/src/Query/Expressions/Internal/MySQLMatchExpression.cs index e90f336a8..26f177b81 100644 --- a/EFCore/src/Query/Expressions/Internal/MySQLMatchExpression.cs +++ b/EFCore/src/Query/Expressions/Internal/MySQLMatchExpression.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Query/Expressions/Internal/MySQLRegexpExpression.cs b/EFCore/src/Query/Expressions/Internal/MySQLRegexpExpression.cs index f851e0eaa..3ecedf787 100644 --- a/EFCore/src/Query/Expressions/Internal/MySQLRegexpExpression.cs +++ b/EFCore/src/Query/Expressions/Internal/MySQLRegexpExpression.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Query/Expressions/Internal/MySQLStringComparisonMethodTranslator.cs b/EFCore/src/Query/Expressions/Internal/MySQLStringComparisonMethodTranslator.cs index 32b412960..1af3ac2cb 100644 --- a/EFCore/src/Query/Expressions/Internal/MySQLStringComparisonMethodTranslator.cs +++ b/EFCore/src/Query/Expressions/Internal/MySQLStringComparisonMethodTranslator.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Query/Internal/MySQLCommandParser.cs b/EFCore/src/Query/Internal/MySQLCommandParser.cs index 2b98ff175..9b4a36f4a 100644 --- a/EFCore/src/Query/Internal/MySQLCommandParser.cs +++ b/EFCore/src/Query/Internal/MySQLCommandParser.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Query/Internal/MySQLCompatibilityExpressionVisitor.cs b/EFCore/src/Query/Internal/MySQLCompatibilityExpressionVisitor.cs index d462ea9d6..492ed5957 100644 --- a/EFCore/src/Query/Internal/MySQLCompatibilityExpressionVisitor.cs +++ b/EFCore/src/Query/Internal/MySQLCompatibilityExpressionVisitor.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Query/Internal/MySQLCompiledQueryCacheKeyGenerator.cs b/EFCore/src/Query/Internal/MySQLCompiledQueryCacheKeyGenerator.cs index bac0a49f2..d4658704c 100644 --- a/EFCore/src/Query/Internal/MySQLCompiledQueryCacheKeyGenerator.cs +++ b/EFCore/src/Query/Internal/MySQLCompiledQueryCacheKeyGenerator.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Query/Internal/MySQLConvertTranslator.cs b/EFCore/src/Query/Internal/MySQLConvertTranslator.cs index c959987b6..f600784a9 100644 --- a/EFCore/src/Query/Internal/MySQLConvertTranslator.cs +++ b/EFCore/src/Query/Internal/MySQLConvertTranslator.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Query/Internal/MySQLDateDiffFunctionsTranslator.cs b/EFCore/src/Query/Internal/MySQLDateDiffFunctionsTranslator.cs index cd293d598..439a3f2b3 100644 --- a/EFCore/src/Query/Internal/MySQLDateDiffFunctionsTranslator.cs +++ b/EFCore/src/Query/Internal/MySQLDateDiffFunctionsTranslator.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Query/Internal/MySQLDateTimeMemberTranslator.cs b/EFCore/src/Query/Internal/MySQLDateTimeMemberTranslator.cs index 7f4777754..b2c62c561 100644 --- a/EFCore/src/Query/Internal/MySQLDateTimeMemberTranslator.cs +++ b/EFCore/src/Query/Internal/MySQLDateTimeMemberTranslator.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Query/Internal/MySQLDateTimeMethodTranslator.cs b/EFCore/src/Query/Internal/MySQLDateTimeMethodTranslator.cs index 40fe8c1c6..d967aa091 100644 --- a/EFCore/src/Query/Internal/MySQLDateTimeMethodTranslator.cs +++ b/EFCore/src/Query/Internal/MySQLDateTimeMethodTranslator.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Query/Internal/MySQLEvaluatableExpressionFilter.cs b/EFCore/src/Query/Internal/MySQLEvaluatableExpressionFilter.cs index 2118664fd..50d159ff5 100644 --- a/EFCore/src/Query/Internal/MySQLEvaluatableExpressionFilter.cs +++ b/EFCore/src/Query/Internal/MySQLEvaluatableExpressionFilter.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Query/Internal/MySQLMathTranslator.cs b/EFCore/src/Query/Internal/MySQLMathTranslator.cs index 5704f945b..ba3f30f38 100644 --- a/EFCore/src/Query/Internal/MySQLMathTranslator.cs +++ b/EFCore/src/Query/Internal/MySQLMathTranslator.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Query/Internal/MySQLMemberTranslatorProvider.cs b/EFCore/src/Query/Internal/MySQLMemberTranslatorProvider.cs index d3c2cc9ab..7d51db057 100644 --- a/EFCore/src/Query/Internal/MySQLMemberTranslatorProvider.cs +++ b/EFCore/src/Query/Internal/MySQLMemberTranslatorProvider.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Query/Internal/MySQLMethodCallTranslatorProvider.cs b/EFCore/src/Query/Internal/MySQLMethodCallTranslatorProvider.cs index d059f1170..3538d2342 100644 --- a/EFCore/src/Query/Internal/MySQLMethodCallTranslatorProvider.cs +++ b/EFCore/src/Query/Internal/MySQLMethodCallTranslatorProvider.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Query/Internal/MySQLNewGuidTranslator.cs b/EFCore/src/Query/Internal/MySQLNewGuidTranslator.cs index f71d13bf8..0a2cd57dd 100644 --- a/EFCore/src/Query/Internal/MySQLNewGuidTranslator.cs +++ b/EFCore/src/Query/Internal/MySQLNewGuidTranslator.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Query/Internal/MySQLObjectToStringTranslator.cs b/EFCore/src/Query/Internal/MySQLObjectToStringTranslator.cs index 382f88cca..d8455bff7 100644 --- a/EFCore/src/Query/Internal/MySQLObjectToStringTranslator.cs +++ b/EFCore/src/Query/Internal/MySQLObjectToStringTranslator.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Query/Internal/MySQLParameterBasedSqlProcessor.cs b/EFCore/src/Query/Internal/MySQLParameterBasedSqlProcessor.cs index 6e0cf9b01..e116a3c93 100644 --- a/EFCore/src/Query/Internal/MySQLParameterBasedSqlProcessor.cs +++ b/EFCore/src/Query/Internal/MySQLParameterBasedSqlProcessor.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Query/Internal/MySQLParameterBasedSqlProcessorFactory.cs b/EFCore/src/Query/Internal/MySQLParameterBasedSqlProcessorFactory.cs index aac4cbec9..12f709cda 100644 --- a/EFCore/src/Query/Internal/MySQLParameterBasedSqlProcessorFactory.cs +++ b/EFCore/src/Query/Internal/MySQLParameterBasedSqlProcessorFactory.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Query/Internal/MySQLQueryCompilationContext.cs b/EFCore/src/Query/Internal/MySQLQueryCompilationContext.cs index 14cae9543..821c3ac54 100644 --- a/EFCore/src/Query/Internal/MySQLQueryCompilationContext.cs +++ b/EFCore/src/Query/Internal/MySQLQueryCompilationContext.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Query/Internal/MySQLQueryCompilationContextFactory.cs b/EFCore/src/Query/Internal/MySQLQueryCompilationContextFactory.cs index 0d1557b28..3629a6424 100644 --- a/EFCore/src/Query/Internal/MySQLQueryCompilationContextFactory.cs +++ b/EFCore/src/Query/Internal/MySQLQueryCompilationContextFactory.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Query/Internal/MySQLQueryStringFactory.cs b/EFCore/src/Query/Internal/MySQLQueryStringFactory.cs index d226ef133..caac3d8f1 100644 --- a/EFCore/src/Query/Internal/MySQLQueryStringFactory.cs +++ b/EFCore/src/Query/Internal/MySQLQueryStringFactory.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Query/Internal/MySQLQueryTranslationPostprocessor.cs b/EFCore/src/Query/Internal/MySQLQueryTranslationPostprocessor.cs index 0cd1f61f6..5112c5e0c 100644 --- a/EFCore/src/Query/Internal/MySQLQueryTranslationPostprocessor.cs +++ b/EFCore/src/Query/Internal/MySQLQueryTranslationPostprocessor.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Query/Internal/MySQLQueryTranslationPostprocessorFactory.cs b/EFCore/src/Query/Internal/MySQLQueryTranslationPostprocessorFactory.cs index 70d18e8d6..147a36511 100644 --- a/EFCore/src/Query/Internal/MySQLQueryTranslationPostprocessorFactory.cs +++ b/EFCore/src/Query/Internal/MySQLQueryTranslationPostprocessorFactory.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Query/Internal/MySQLSqlExpressionFactory.cs b/EFCore/src/Query/Internal/MySQLSqlExpressionFactory.cs index 048670b14..df6173fc6 100644 --- a/EFCore/src/Query/Internal/MySQLSqlExpressionFactory.cs +++ b/EFCore/src/Query/Internal/MySQLSqlExpressionFactory.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Query/Internal/MySQLSqlNullabilityProcessor.cs b/EFCore/src/Query/Internal/MySQLSqlNullabilityProcessor.cs index 28a37ed98..4ecd6edd1 100644 --- a/EFCore/src/Query/Internal/MySQLSqlNullabilityProcessor.cs +++ b/EFCore/src/Query/Internal/MySQLSqlNullabilityProcessor.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Query/Internal/MySQLSqlTranslatingExpressionVisitor.cs b/EFCore/src/Query/Internal/MySQLSqlTranslatingExpressionVisitor.cs index 1d0634dcf..6ee7e7c35 100644 --- a/EFCore/src/Query/Internal/MySQLSqlTranslatingExpressionVisitor.cs +++ b/EFCore/src/Query/Internal/MySQLSqlTranslatingExpressionVisitor.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Query/Internal/MySQLSqlTranslatingExpressionVisitorFactory.cs b/EFCore/src/Query/Internal/MySQLSqlTranslatingExpressionVisitorFactory.cs index 2361df0cb..7e476ba9d 100644 --- a/EFCore/src/Query/Internal/MySQLSqlTranslatingExpressionVisitorFactory.cs +++ b/EFCore/src/Query/Internal/MySQLSqlTranslatingExpressionVisitorFactory.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Query/Internal/MySQLStringMemberTranslator.cs b/EFCore/src/Query/Internal/MySQLStringMemberTranslator.cs index c320307c3..1dee350d7 100644 --- a/EFCore/src/Query/Internal/MySQLStringMemberTranslator.cs +++ b/EFCore/src/Query/Internal/MySQLStringMemberTranslator.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Query/Internal/MySQLStringMethodTranslator.cs b/EFCore/src/Query/Internal/MySQLStringMethodTranslator.cs index 5e69861b1..c3697e56c 100644 --- a/EFCore/src/Query/Internal/MySQLStringMethodTranslator.cs +++ b/EFCore/src/Query/Internal/MySQLStringMethodTranslator.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Query/MySQLJsonString.cs b/EFCore/src/Query/MySQLJsonString.cs index 86abded85..809869338 100644 --- a/EFCore/src/Query/MySQLJsonString.cs +++ b/EFCore/src/Query/MySQLJsonString.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Query/Sql/Internal/MySQLQueryGeneratorFactory.cs b/EFCore/src/Query/Sql/Internal/MySQLQueryGeneratorFactory.cs index 20c8752ff..75844a37e 100644 --- a/EFCore/src/Query/Sql/Internal/MySQLQueryGeneratorFactory.cs +++ b/EFCore/src/Query/Sql/Internal/MySQLQueryGeneratorFactory.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Query/Sql/Internal/MySQLQuerySqlGenerator.cs b/EFCore/src/Query/Sql/Internal/MySQLQuerySqlGenerator.cs index 9d529e3ef..e986d1f97 100644 --- a/EFCore/src/Query/Sql/Internal/MySQLQuerySqlGenerator.cs +++ b/EFCore/src/Query/Sql/Internal/MySQLQuerySqlGenerator.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Scaffolding/Internal/MySQLCodeGenerator.cs b/EFCore/src/Scaffolding/Internal/MySQLCodeGenerator.cs index 0e24d85b8..51b081e41 100644 --- a/EFCore/src/Scaffolding/Internal/MySQLCodeGenerator.cs +++ b/EFCore/src/Scaffolding/Internal/MySQLCodeGenerator.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Scaffolding/Internal/MySQLDataReaderExtension.cs b/EFCore/src/Scaffolding/Internal/MySQLDataReaderExtension.cs index eaaac93d4..a68236874 100644 --- a/EFCore/src/Scaffolding/Internal/MySQLDataReaderExtension.cs +++ b/EFCore/src/Scaffolding/Internal/MySQLDataReaderExtension.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Scaffolding/Internal/MySQLDatabaseModelFactory.cs b/EFCore/src/Scaffolding/Internal/MySQLDatabaseModelFactory.cs index 1c43cc806..9818f28dc 100644 --- a/EFCore/src/Scaffolding/Internal/MySQLDatabaseModelFactory.cs +++ b/EFCore/src/Scaffolding/Internal/MySQLDatabaseModelFactory.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Storage/Internal/ByteArrayComparer.cs b/EFCore/src/Storage/Internal/ByteArrayComparer.cs index 72f36aa92..c99fda081 100644 --- a/EFCore/src/Storage/Internal/ByteArrayComparer.cs +++ b/EFCore/src/Storage/Internal/ByteArrayComparer.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Storage/Internal/BytesToDateTimeConverter.cs b/EFCore/src/Storage/Internal/BytesToDateTimeConverter.cs index 704cc911a..d92aefb1d 100644 --- a/EFCore/src/Storage/Internal/BytesToDateTimeConverter.cs +++ b/EFCore/src/Storage/Internal/BytesToDateTimeConverter.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Storage/Internal/IMySQLRelationalConnection.cs b/EFCore/src/Storage/Internal/IMySQLRelationalConnection.cs index ca4d34b15..32a6c4ae9 100644 --- a/EFCore/src/Storage/Internal/IMySQLRelationalConnection.cs +++ b/EFCore/src/Storage/Internal/IMySQLRelationalConnection.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Storage/Internal/MySQLBoolTypeMapping.cs b/EFCore/src/Storage/Internal/MySQLBoolTypeMapping.cs index 918770f7c..f1b7d2148 100644 --- a/EFCore/src/Storage/Internal/MySQLBoolTypeMapping.cs +++ b/EFCore/src/Storage/Internal/MySQLBoolTypeMapping.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Storage/Internal/MySQLByteArrayTypeMapping.cs b/EFCore/src/Storage/Internal/MySQLByteArrayTypeMapping.cs index d9ecd53dd..f95732c81 100644 --- a/EFCore/src/Storage/Internal/MySQLByteArrayTypeMapping.cs +++ b/EFCore/src/Storage/Internal/MySQLByteArrayTypeMapping.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Storage/Internal/MySQLDatabaseCreator.cs b/EFCore/src/Storage/Internal/MySQLDatabaseCreator.cs index a91f1be01..21ef77904 100644 --- a/EFCore/src/Storage/Internal/MySQLDatabaseCreator.cs +++ b/EFCore/src/Storage/Internal/MySQLDatabaseCreator.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Storage/Internal/MySQLDateTimeOffsetTypeMapping.cs b/EFCore/src/Storage/Internal/MySQLDateTimeOffsetTypeMapping.cs index 7c31ad5fd..d63ac03bf 100644 --- a/EFCore/src/Storage/Internal/MySQLDateTimeOffsetTypeMapping.cs +++ b/EFCore/src/Storage/Internal/MySQLDateTimeOffsetTypeMapping.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Storage/Internal/MySQLDateTypeMapping.cs b/EFCore/src/Storage/Internal/MySQLDateTypeMapping.cs index 03b6fd744..68f939a73 100644 --- a/EFCore/src/Storage/Internal/MySQLDateTypeMapping.cs +++ b/EFCore/src/Storage/Internal/MySQLDateTypeMapping.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Storage/Internal/MySQLDatetimeTypeMapping.cs b/EFCore/src/Storage/Internal/MySQLDatetimeTypeMapping.cs index 38df28500..269566f6c 100644 --- a/EFCore/src/Storage/Internal/MySQLDatetimeTypeMapping.cs +++ b/EFCore/src/Storage/Internal/MySQLDatetimeTypeMapping.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Storage/Internal/MySQLDecimalTypeMapping.cs b/EFCore/src/Storage/Internal/MySQLDecimalTypeMapping.cs index 739bd4a75..1520a8164 100644 --- a/EFCore/src/Storage/Internal/MySQLDecimalTypeMapping.cs +++ b/EFCore/src/Storage/Internal/MySQLDecimalTypeMapping.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Storage/Internal/MySQLDoubleTypeMapping.cs b/EFCore/src/Storage/Internal/MySQLDoubleTypeMapping.cs index e5091a087..401846f59 100644 --- a/EFCore/src/Storage/Internal/MySQLDoubleTypeMapping.cs +++ b/EFCore/src/Storage/Internal/MySQLDoubleTypeMapping.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Storage/Internal/MySQLExecutionStrategy.cs b/EFCore/src/Storage/Internal/MySQLExecutionStrategy.cs index cdee7a927..cc0793aa7 100644 --- a/EFCore/src/Storage/Internal/MySQLExecutionStrategy.cs +++ b/EFCore/src/Storage/Internal/MySQLExecutionStrategy.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Storage/Internal/MySQLExecutionStrategyFactory.cs b/EFCore/src/Storage/Internal/MySQLExecutionStrategyFactory.cs index a977b7cf2..b7caac1b4 100644 --- a/EFCore/src/Storage/Internal/MySQLExecutionStrategyFactory.cs +++ b/EFCore/src/Storage/Internal/MySQLExecutionStrategyFactory.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Storage/Internal/MySQLFloatTypeMapping.cs b/EFCore/src/Storage/Internal/MySQLFloatTypeMapping.cs index 0ace2680d..9db0bee5e 100644 --- a/EFCore/src/Storage/Internal/MySQLFloatTypeMapping.cs +++ b/EFCore/src/Storage/Internal/MySQLFloatTypeMapping.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Storage/Internal/MySQLGeometryTypeMapping.cs b/EFCore/src/Storage/Internal/MySQLGeometryTypeMapping.cs index f808990f1..deb61e2c0 100644 --- a/EFCore/src/Storage/Internal/MySQLGeometryTypeMapping.cs +++ b/EFCore/src/Storage/Internal/MySQLGeometryTypeMapping.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Storage/Internal/MySQLGuidTypeMapping.cs b/EFCore/src/Storage/Internal/MySQLGuidTypeMapping.cs index 6f6977b93..3aee65a32 100644 --- a/EFCore/src/Storage/Internal/MySQLGuidTypeMapping.cs +++ b/EFCore/src/Storage/Internal/MySQLGuidTypeMapping.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Storage/Internal/MySQLJsonChangeTrackingOptions.cs b/EFCore/src/Storage/Internal/MySQLJsonChangeTrackingOptions.cs index 5396f175e..2e7ab243c 100644 --- a/EFCore/src/Storage/Internal/MySQLJsonChangeTrackingOptions.cs +++ b/EFCore/src/Storage/Internal/MySQLJsonChangeTrackingOptions.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Storage/Internal/MySQLJsonTypeMapping.cs b/EFCore/src/Storage/Internal/MySQLJsonTypeMapping.cs index 996abd8ae..332ca01ee 100644 --- a/EFCore/src/Storage/Internal/MySQLJsonTypeMapping.cs +++ b/EFCore/src/Storage/Internal/MySQLJsonTypeMapping.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Storage/Internal/MySQLRelationalConnection.cs b/EFCore/src/Storage/Internal/MySQLRelationalConnection.cs index 69dd43bb8..cc1e391e7 100644 --- a/EFCore/src/Storage/Internal/MySQLRelationalConnection.cs +++ b/EFCore/src/Storage/Internal/MySQLRelationalConnection.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Storage/Internal/MySQLScaffoldingConnectionSettings.cs b/EFCore/src/Storage/Internal/MySQLScaffoldingConnectionSettings.cs index fc306bfa1..9f4b301f7 100644 --- a/EFCore/src/Storage/Internal/MySQLScaffoldingConnectionSettings.cs +++ b/EFCore/src/Storage/Internal/MySQLScaffoldingConnectionSettings.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Storage/Internal/MySQLSqlGenerationHelper.cs b/EFCore/src/Storage/Internal/MySQLSqlGenerationHelper.cs index fc5ebe71d..44bdba26f 100644 --- a/EFCore/src/Storage/Internal/MySQLSqlGenerationHelper.cs +++ b/EFCore/src/Storage/Internal/MySQLSqlGenerationHelper.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Storage/Internal/MySQLStringTypeMapping.cs b/EFCore/src/Storage/Internal/MySQLStringTypeMapping.cs index d4b1e6f8d..4979b239f 100644 --- a/EFCore/src/Storage/Internal/MySQLStringTypeMapping.cs +++ b/EFCore/src/Storage/Internal/MySQLStringTypeMapping.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Storage/Internal/MySQLTimeSpanMapping.cs b/EFCore/src/Storage/Internal/MySQLTimeSpanMapping.cs index 354217789..9af35fb0a 100644 --- a/EFCore/src/Storage/Internal/MySQLTimeSpanMapping.cs +++ b/EFCore/src/Storage/Internal/MySQLTimeSpanMapping.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Storage/Internal/MySQLTransientExceptionDetector.cs b/EFCore/src/Storage/Internal/MySQLTransientExceptionDetector.cs index b8ce03b8c..d608ea6c7 100644 --- a/EFCore/src/Storage/Internal/MySQLTransientExceptionDetector.cs +++ b/EFCore/src/Storage/Internal/MySQLTransientExceptionDetector.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Storage/Internal/MySQLTypeMapping.cs b/EFCore/src/Storage/Internal/MySQLTypeMapping.cs index 15c9caecf..94b3ba746 100644 --- a/EFCore/src/Storage/Internal/MySQLTypeMapping.cs +++ b/EFCore/src/Storage/Internal/MySQLTypeMapping.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Storage/Internal/MySQLTypeMappingSource.cs b/EFCore/src/Storage/Internal/MySQLTypeMappingSource.cs index a1b59b05b..831d01a94 100644 --- a/EFCore/src/Storage/Internal/MySQLTypeMappingSource.cs +++ b/EFCore/src/Storage/Internal/MySQLTypeMappingSource.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Update/IMySQLUpdateSqlGenerator.cs b/EFCore/src/Update/IMySQLUpdateSqlGenerator.cs index 905cec451..c27d2f48d 100644 --- a/EFCore/src/Update/IMySQLUpdateSqlGenerator.cs +++ b/EFCore/src/Update/IMySQLUpdateSqlGenerator.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Update/MySQLModificationCommandBatch.cs b/EFCore/src/Update/MySQLModificationCommandBatch.cs index 8e238c2dd..bb93a4762 100644 --- a/EFCore/src/Update/MySQLModificationCommandBatch.cs +++ b/EFCore/src/Update/MySQLModificationCommandBatch.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Update/MySQLModificationCommandBatchFactory.cs b/EFCore/src/Update/MySQLModificationCommandBatchFactory.cs index d104ca6b1..e03dd8e76 100644 --- a/EFCore/src/Update/MySQLModificationCommandBatchFactory.cs +++ b/EFCore/src/Update/MySQLModificationCommandBatchFactory.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Update/MySQLUpdateSqlGenerator.cs b/EFCore/src/Update/MySQLUpdateSqlGenerator.cs index 145b8fe39..7caf477ec 100644 --- a/EFCore/src/Update/MySQLUpdateSqlGenerator.cs +++ b/EFCore/src/Update/MySQLUpdateSqlGenerator.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Utils/Check.cs b/EFCore/src/Utils/Check.cs index 6984e9625..2b6408fdb 100644 --- a/EFCore/src/Utils/Check.cs +++ b/EFCore/src/Utils/Check.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Utils/CodeAnnotations.cs b/EFCore/src/Utils/CodeAnnotations.cs index ea07d310e..1ee0e5880 100644 --- a/EFCore/src/Utils/CodeAnnotations.cs +++ b/EFCore/src/Utils/CodeAnnotations.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Utils/CodeAttributes.cs b/EFCore/src/Utils/CodeAttributes.cs index 95b9ec4ea..dda508d4f 100644 --- a/EFCore/src/Utils/CodeAttributes.cs +++ b/EFCore/src/Utils/CodeAttributes.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Utils/SharedTypeExtensions.cs b/EFCore/src/Utils/SharedTypeExtensions.cs index b1ebef71c..b09c5b396 100644 --- a/EFCore/src/Utils/SharedTypeExtensions.cs +++ b/EFCore/src/Utils/SharedTypeExtensions.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Utils/Static.cs b/EFCore/src/Utils/Static.cs index 484e87a4d..42e67383d 100644 --- a/EFCore/src/Utils/Static.cs +++ b/EFCore/src/Utils/Static.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/Utils/StringBuilderExtensions.cs b/EFCore/src/Utils/StringBuilderExtensions.cs index 8a4785544..1a431a88d 100644 --- a/EFCore/src/Utils/StringBuilderExtensions.cs +++ b/EFCore/src/Utils/StringBuilderExtensions.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/src/ValueGeneration/Internal/MySQLValueGeneratorSelector.cs b/EFCore/src/ValueGeneration/Internal/MySQLValueGeneratorSelector.cs index a332347e1..81137081b 100644 --- a/EFCore/src/ValueGeneration/Internal/MySQLValueGeneratorSelector.cs +++ b/EFCore/src/ValueGeneration/Internal/MySQLValueGeneratorSelector.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/BasicGuidTests.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/BasicGuidTests.cs index 3b0eb6bf3..413d83328 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/BasicGuidTests.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/BasicGuidTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/ConcurrencyTests.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/ConcurrencyTests.cs index 8e21b9acc..feb4024b3 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/ConcurrencyTests.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/ConcurrencyTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/ConnectionTests.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/ConnectionTests.cs index 3f32516bf..1a82a5f62 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/ConnectionTests.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/ConnectionTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/DataTests.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/DataTests.cs index 39db69db3..c8c9f227e 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/DataTests.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/DataTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/DbContextClasses/ConventionsContexts.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/DbContextClasses/ConventionsContexts.cs index aa5b635b1..c5f089188 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/DbContextClasses/ConventionsContexts.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/DbContextClasses/ConventionsContexts.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/DbContextClasses/EFFluentAPIContexts.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/DbContextClasses/EFFluentAPIContexts.cs index 33940a28c..ea30b2019 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/DbContextClasses/EFFluentAPIContexts.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/DbContextClasses/EFFluentAPIContexts.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/DbContextClasses/EntitiesClasses.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/DbContextClasses/EntitiesClasses.cs index 863606a21..d28d32e81 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/DbContextClasses/EntitiesClasses.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/DbContextClasses/EntitiesClasses.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/DbContextClasses/SakilaLiteContext.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/DbContextClasses/SakilaLiteContext.cs index a3141586a..25f240287 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/DbContextClasses/SakilaLiteContext.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/DbContextClasses/SakilaLiteContext.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/DbContextClasses/TestsContexts.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/DbContextClasses/TestsContexts.cs index 2cc62d404..156e905be 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/DbContextClasses/TestsContexts.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/DbContextClasses/TestsContexts.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/DbFunctionsMySQLTest.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/DbFunctionsMySQLTest.cs index 3cab9cf34..645045092 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/DbFunctionsMySQLTest.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/DbFunctionsMySQLTest.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/EFCoreTests.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/EFCoreTests.cs index d062758c1..531dd6025 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/EFCoreTests.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/EFCoreTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/FluentAPITests.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/FluentAPITests.cs index 4a4c79982..37c27ffbb 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/FluentAPITests.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/FluentAPITests.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/FunctionalTests.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/FunctionalTests.cs index ef926a1b6..b12e73b80 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/FunctionalTests.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/FunctionalTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/LoadingRelatedDataTests.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/LoadingRelatedDataTests.cs index c0c67bf8b..c73eb25c1 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/LoadingRelatedDataTests.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/LoadingRelatedDataTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/ModelingTests.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/ModelingTests.cs index 8ba63fd0b..d20647d7b 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/ModelingTests.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/ModelingTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/MultiSchemaTests.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/MultiSchemaTests.cs index 0a4959aed..8a82615aa 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/MultiSchemaTests.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/MultiSchemaTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/MySQLDatabaseFacadeTest.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/MySQLDatabaseFacadeTest.cs index 1ce799ba6..1c203cc07 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/MySQLDatabaseFacadeTest.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/MySQLDatabaseFacadeTest.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/MySQLTypeMapperTests.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/MySQLTypeMapperTests.cs index e94c583c5..03a06aac0 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/MySQLTypeMapperTests.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/MySQLTypeMapperTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/Properties/DatabaseSetup.sql b/EFCore/tests/MySql.EFCore.Basic.Tests/Properties/DatabaseSetup.sql index 4f4d91d2f..6a67848d2 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/Properties/DatabaseSetup.sql +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/Properties/DatabaseSetup.sql @@ -1,5 +1,5 @@ /* -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/ShadowPropertiesTests.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/ShadowPropertiesTests.cs index cbc676c76..faf443047 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/ShadowPropertiesTests.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/ShadowPropertiesTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/UpdateTests.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/UpdateTests.cs index baa1ec466..0a95d864b 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/UpdateTests.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/UpdateTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/Utils/EntityTestsFixtureClass.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/Utils/EntityTestsFixtureClass.cs index 87696ef1b..2903470fa 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/Utils/EntityTestsFixtureClass.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/Utils/EntityTestsFixtureClass.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/Utils/MySqlTestStore.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/Utils/MySqlTestStore.cs index 1cbdf19c8..776026ab7 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/Utils/MySqlTestStore.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/Utils/MySqlTestStore.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/Utils/TestUtils.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/Utils/TestUtils.cs index a09e6ab14..7b9b59314 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/Utils/TestUtils.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/Utils/TestUtils.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/tests/MySql.EFCore.Design.Tests/Extensions.cs b/EFCore/tests/MySql.EFCore.Design.Tests/Extensions.cs index db11322d0..1543ee7ab 100644 --- a/EFCore/tests/MySql.EFCore.Design.Tests/Extensions.cs +++ b/EFCore/tests/MySql.EFCore.Design.Tests/Extensions.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/tests/MySql.EFCore.Design.Tests/MySQLAnnotationCodeGeneratorTest.cs b/EFCore/tests/MySql.EFCore.Design.Tests/MySQLAnnotationCodeGeneratorTest.cs index 6e5e9d6ce..7f0ed3e2a 100644 --- a/EFCore/tests/MySql.EFCore.Design.Tests/MySQLAnnotationCodeGeneratorTest.cs +++ b/EFCore/tests/MySql.EFCore.Design.Tests/MySQLAnnotationCodeGeneratorTest.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/tests/MySql.EFCore.Design.Tests/MySQLCodeGeneratorTest.cs b/EFCore/tests/MySql.EFCore.Design.Tests/MySQLCodeGeneratorTest.cs index b0e83d66f..42f3804c9 100644 --- a/EFCore/tests/MySql.EFCore.Design.Tests/MySQLCodeGeneratorTest.cs +++ b/EFCore/tests/MySql.EFCore.Design.Tests/MySQLCodeGeneratorTest.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/tests/MySql.EFCore.Design.Tests/MySQLDatabaseModelFactoryTest.cs b/EFCore/tests/MySql.EFCore.Design.Tests/MySQLDatabaseModelFactoryTest.cs index a5032f43a..beb0ab423 100644 --- a/EFCore/tests/MySql.EFCore.Design.Tests/MySQLDatabaseModelFactoryTest.cs +++ b/EFCore/tests/MySql.EFCore.Design.Tests/MySQLDatabaseModelFactoryTest.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/tests/MySql.EFCore.Design.Tests/MySQLDatabaseModelFixture.cs b/EFCore/tests/MySql.EFCore.Design.Tests/MySQLDatabaseModelFixture.cs index 3e7365b7b..fc586e967 100644 --- a/EFCore/tests/MySql.EFCore.Design.Tests/MySQLDatabaseModelFixture.cs +++ b/EFCore/tests/MySql.EFCore.Design.Tests/MySQLDatabaseModelFixture.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/tests/MySql.EFCore.Design.Tests/MySQLDesignTimeProviderServicesTest.cs b/EFCore/tests/MySql.EFCore.Design.Tests/MySQLDesignTimeProviderServicesTest.cs index 5331e8b81..8c30712d7 100644 --- a/EFCore/tests/MySql.EFCore.Design.Tests/MySQLDesignTimeProviderServicesTest.cs +++ b/EFCore/tests/MySql.EFCore.Design.Tests/MySQLDesignTimeProviderServicesTest.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/tests/MySql.EFCore.Design.Tests/Properties/sakiladb-schema.sql b/EFCore/tests/MySql.EFCore.Design.Tests/Properties/sakiladb-schema.sql index 5ea9e57d9..33a025602 100644 --- a/EFCore/tests/MySql.EFCore.Design.Tests/Properties/sakiladb-schema.sql +++ b/EFCore/tests/MySql.EFCore.Design.Tests/Properties/sakiladb-schema.sql @@ -1,5 +1,5 @@ /* -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/tests/MySql.EFCore.Design.Tests/Properties/world.sql b/EFCore/tests/MySql.EFCore.Design.Tests/Properties/world.sql index 1251c03f6..9374e9c57 100644 --- a/EFCore/tests/MySql.EFCore.Design.Tests/Properties/world.sql +++ b/EFCore/tests/MySql.EFCore.Design.Tests/Properties/world.sql @@ -1,5 +1,5 @@ /* -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/tests/MySql.EFCore.Migrations.Tests/MySQLHistoryRepositoryTests.cs b/EFCore/tests/MySql.EFCore.Migrations.Tests/MySQLHistoryRepositoryTests.cs index 7ae230162..6421977d3 100644 --- a/EFCore/tests/MySql.EFCore.Migrations.Tests/MySQLHistoryRepositoryTests.cs +++ b/EFCore/tests/MySql.EFCore.Migrations.Tests/MySQLHistoryRepositoryTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/tests/MySql.EFCore.Migrations.Tests/MySQLMigrationsTests.cs b/EFCore/tests/MySql.EFCore.Migrations.Tests/MySQLMigrationsTests.cs index a91f32c00..204076761 100644 --- a/EFCore/tests/MySql.EFCore.Migrations.Tests/MySQLMigrationsTests.cs +++ b/EFCore/tests/MySql.EFCore.Migrations.Tests/MySQLMigrationsTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/tests/MySql.EFCore.Migrations.Tests/MySqlMigrationsGeneratorTest.cs b/EFCore/tests/MySql.EFCore.Migrations.Tests/MySqlMigrationsGeneratorTest.cs index 7be723ae2..53b36fcaa 100644 --- a/EFCore/tests/MySql.EFCore.Migrations.Tests/MySqlMigrationsGeneratorTest.cs +++ b/EFCore/tests/MySql.EFCore.Migrations.Tests/MySqlMigrationsGeneratorTest.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/tests/MySql.EFCore.Migrations.Tests/MySqlMigrationsGeneratorTestBase.cs b/EFCore/tests/MySql.EFCore.Migrations.Tests/MySqlMigrationsGeneratorTestBase.cs index e597dfcee..402723c3e 100644 --- a/EFCore/tests/MySql.EFCore.Migrations.Tests/MySqlMigrationsGeneratorTestBase.cs +++ b/EFCore/tests/MySql.EFCore.Migrations.Tests/MySqlMigrationsGeneratorTestBase.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EFCore/tests/MySql.EFCore.Migrations.Tests/Utilities/ContextUtils.cs b/EFCore/tests/MySql.EFCore.Migrations.Tests/Utilities/ContextUtils.cs index 5f059f6a0..813de5cde 100644 --- a/EFCore/tests/MySql.EFCore.Migrations.Tests/Utilities/ContextUtils.cs +++ b/EFCore/tests/MySql.EFCore.Migrations.Tests/Utilities/ContextUtils.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/src/EFMySqlCommand.cs b/EntityFramework/src/EFMySqlCommand.cs index 0dd6d642c..9fcb1a1c9 100644 --- a/EntityFramework/src/EFMySqlCommand.cs +++ b/EntityFramework/src/EFMySqlCommand.cs @@ -1,4 +1,4 @@ -// Copyright © 2008, 2024, Oracle and/or its affiliates. +// Copyright © 2008, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/src/EFMySqlDataReader.cs b/EntityFramework/src/EFMySqlDataReader.cs index c4342f567..68d923bf4 100644 --- a/EntityFramework/src/EFMySqlDataReader.cs +++ b/EntityFramework/src/EFMySqlDataReader.cs @@ -1,4 +1,4 @@ -// Copyright © 2008, 2024, Oracle and/or its affiliates. +// Copyright © 2008, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/src/Fragments/InputFragment.cs b/EntityFramework/src/Fragments/InputFragment.cs index 80ea10800..f55461249 100644 --- a/EntityFramework/src/Fragments/InputFragment.cs +++ b/EntityFramework/src/Fragments/InputFragment.cs @@ -1,4 +1,4 @@ -// Copyright © 2008, 2024, Oracle and/or its affiliates. +// Copyright © 2008, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/src/Fragments/JoinFragment.cs b/EntityFramework/src/Fragments/JoinFragment.cs index 466c04bc6..dde7a8608 100644 --- a/EntityFramework/src/Fragments/JoinFragment.cs +++ b/EntityFramework/src/Fragments/JoinFragment.cs @@ -1,4 +1,4 @@ -// Copyright © 2008, 2024, Oracle and/or its affiliates. +// Copyright © 2008, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/src/Fragments/SqlFragment.cs b/EntityFramework/src/Fragments/SqlFragment.cs index 97abc6c3b..1e16b734f 100644 --- a/EntityFramework/src/Fragments/SqlFragment.cs +++ b/EntityFramework/src/Fragments/SqlFragment.cs @@ -1,4 +1,4 @@ -// Copyright © 2008, 2024, Oracle and/or its affiliates. +// Copyright © 2008, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/src/Fragments/TableFragment.cs b/EntityFramework/src/Fragments/TableFragment.cs index b9c6653d4..a0371d500 100644 --- a/EntityFramework/src/Fragments/TableFragment.cs +++ b/EntityFramework/src/Fragments/TableFragment.cs @@ -1,4 +1,4 @@ -// Copyright © 2008, 2024, Oracle and/or its affiliates. +// Copyright © 2008, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/src/Generators/DeleteGenerator.cs b/EntityFramework/src/Generators/DeleteGenerator.cs index 7b1cd1408..d23018443 100644 --- a/EntityFramework/src/Generators/DeleteGenerator.cs +++ b/EntityFramework/src/Generators/DeleteGenerator.cs @@ -1,4 +1,4 @@ -// Copyright © 2008, 2024, Oracle and/or its affiliates. +// Copyright © 2008, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/src/Generators/FunctionGenerator.cs b/EntityFramework/src/Generators/FunctionGenerator.cs index 6ec949f79..b5f9f6197 100644 --- a/EntityFramework/src/Generators/FunctionGenerator.cs +++ b/EntityFramework/src/Generators/FunctionGenerator.cs @@ -1,4 +1,4 @@ -// Copyright © 2008, 2024, Oracle and/or its affiliates. +// Copyright © 2008, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/src/Generators/FunctionProcessor.cs b/EntityFramework/src/Generators/FunctionProcessor.cs index 1eaa1eb87..0db93eafa 100644 --- a/EntityFramework/src/Generators/FunctionProcessor.cs +++ b/EntityFramework/src/Generators/FunctionProcessor.cs @@ -1,4 +1,4 @@ -// Copyright © 2008, 2024, Oracle and/or its affiliates. +// Copyright © 2008, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/src/Generators/InsertGenerator.cs b/EntityFramework/src/Generators/InsertGenerator.cs index b1fbb5e34..9dda3075a 100644 --- a/EntityFramework/src/Generators/InsertGenerator.cs +++ b/EntityFramework/src/Generators/InsertGenerator.cs @@ -1,4 +1,4 @@ -// Copyright © 2008, 2024, Oracle and/or its affiliates. +// Copyright © 2008, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/src/Generators/Scope.cs b/EntityFramework/src/Generators/Scope.cs index eabf4d397..cf7b7d873 100644 --- a/EntityFramework/src/Generators/Scope.cs +++ b/EntityFramework/src/Generators/Scope.cs @@ -1,4 +1,4 @@ -// Copyright © 2008, 2024, Oracle and/or its affiliates. +// Copyright © 2008, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/src/Generators/SelectGenerator.cs b/EntityFramework/src/Generators/SelectGenerator.cs index a4da311f4..5ef0362af 100644 --- a/EntityFramework/src/Generators/SelectGenerator.cs +++ b/EntityFramework/src/Generators/SelectGenerator.cs @@ -1,4 +1,4 @@ -// Copyright © 2008, 2024, Oracle and/or its affiliates. +// Copyright © 2008, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/src/Generators/SqlGenerator.cs b/EntityFramework/src/Generators/SqlGenerator.cs index 717d87d5f..a7cf234d3 100644 --- a/EntityFramework/src/Generators/SqlGenerator.cs +++ b/EntityFramework/src/Generators/SqlGenerator.cs @@ -1,4 +1,4 @@ -// Copyright © 2008, 2024, Oracle and/or its affiliates. +// Copyright © 2008, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/src/Generators/UpdateGenerator.cs b/EntityFramework/src/Generators/UpdateGenerator.cs index d4e1169fc..ac8c1aee8 100644 --- a/EntityFramework/src/Generators/UpdateGenerator.cs +++ b/EntityFramework/src/Generators/UpdateGenerator.cs @@ -1,4 +1,4 @@ -// Copyright © 2008, 2024, Oracle and/or its affiliates. +// Copyright © 2008, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/src/Metadata.cs b/EntityFramework/src/Metadata.cs index f4da5682a..414c4726f 100644 --- a/EntityFramework/src/Metadata.cs +++ b/EntityFramework/src/Metadata.cs @@ -1,4 +1,4 @@ -// Copyright © 2008, 2024, Oracle and/or its affiliates. +// Copyright © 2008, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/src/MySql.Data.EntityFramework.csproj b/EntityFramework/src/MySql.Data.EntityFramework.csproj index d5c63d0f2..5ded04f19 100644 --- a/EntityFramework/src/MySql.Data.EntityFramework.csproj +++ b/EntityFramework/src/MySql.Data.EntityFramework.csproj @@ -107,4 +107,4 @@ - \ No newline at end of file + diff --git a/EntityFramework/src/MySqlConnectionFactory.cs b/EntityFramework/src/MySqlConnectionFactory.cs index b8e0fa159..6777c323f 100644 --- a/EntityFramework/src/MySqlConnectionFactory.cs +++ b/EntityFramework/src/MySqlConnectionFactory.cs @@ -1,4 +1,4 @@ -// Copyright © 2008, 2024, Oracle and/or its affiliates. +// Copyright © 2008, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/src/MySqlDependencyResolver.cs b/EntityFramework/src/MySqlDependencyResolver.cs index c4f5eafea..189c23353 100644 --- a/EntityFramework/src/MySqlDependencyResolver.cs +++ b/EntityFramework/src/MySqlDependencyResolver.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/src/MySqlEFConfiguration.cs b/EntityFramework/src/MySqlEFConfiguration.cs index 1f99e6a9a..36ce383f7 100644 --- a/EntityFramework/src/MySqlEFConfiguration.cs +++ b/EntityFramework/src/MySqlEFConfiguration.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/src/MySqlExecutionStrategy.cs b/EntityFramework/src/MySqlExecutionStrategy.cs index 8740d3173..1fa6a8348 100644 --- a/EntityFramework/src/MySqlExecutionStrategy.cs +++ b/EntityFramework/src/MySqlExecutionStrategy.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/src/MySqlHistoryContext.cs b/EntityFramework/src/MySqlHistoryContext.cs index 9235ba7ef..8154745b2 100644 --- a/EntityFramework/src/MySqlHistoryContext.cs +++ b/EntityFramework/src/MySqlHistoryContext.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/src/MySqlLogger.cs b/EntityFramework/src/MySqlLogger.cs index 00624aaa9..9b7863bf3 100644 --- a/EntityFramework/src/MySqlLogger.cs +++ b/EntityFramework/src/MySqlLogger.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/src/MySqlMigrationSqlGenerator.cs b/EntityFramework/src/MySqlMigrationSqlGenerator.cs index 32e3b50ac..5fc83f782 100644 --- a/EntityFramework/src/MySqlMigrationSqlGenerator.cs +++ b/EntityFramework/src/MySqlMigrationSqlGenerator.cs @@ -1,4 +1,4 @@ -// Copyright © 2008, 2024, Oracle and/or its affiliates. +// Copyright © 2008, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/src/MySqlSpatialDataReader.cs b/EntityFramework/src/MySqlSpatialDataReader.cs index 8299b68f0..8425a70da 100644 --- a/EntityFramework/src/MySqlSpatialDataReader.cs +++ b/EntityFramework/src/MySqlSpatialDataReader.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/src/MySqlSpatialServices.cs b/EntityFramework/src/MySqlSpatialServices.cs index f346f2ea6..bd7071d35 100644 --- a/EntityFramework/src/MySqlSpatialServices.cs +++ b/EntityFramework/src/MySqlSpatialServices.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/src/Properties/AssemblyInfo.cs b/EntityFramework/src/Properties/AssemblyInfo.cs index 622e7d7a4..b99934a90 100644 --- a/EntityFramework/src/Properties/AssemblyInfo.cs +++ b/EntityFramework/src/Properties/AssemblyInfo.cs @@ -1,4 +1,4 @@ -// Copyright © 2008, 2024, Oracle and/or its affiliates. +// Copyright © 2008, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/src/Properties/VersionInfo.cs b/EntityFramework/src/Properties/VersionInfo.cs index 0e0ddbb1f..e4c0f01b6 100644 --- a/EntityFramework/src/Properties/VersionInfo.cs +++ b/EntityFramework/src/Properties/VersionInfo.cs @@ -1,4 +1,4 @@ -// Copyright © 2024, Oracle and/or its affiliates. +// Copyright © 2024, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/src/ProviderManifest.cs b/EntityFramework/src/ProviderManifest.cs index 0c3cf868f..e2cf1a83a 100644 --- a/EntityFramework/src/ProviderManifest.cs +++ b/EntityFramework/src/ProviderManifest.cs @@ -1,4 +1,4 @@ -// Copyright © 2008, 2024, Oracle and/or its affiliates. +// Copyright © 2008, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/src/ProviderServices.cs b/EntityFramework/src/ProviderServices.cs index f992126ce..e48803aad 100644 --- a/EntityFramework/src/ProviderServices.cs +++ b/EntityFramework/src/ProviderServices.cs @@ -1,4 +1,4 @@ -// Copyright © 2014, 2024, Oracle and/or its affiliates. +// Copyright © 2014, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/src/Statements/DeleteStatement.cs b/EntityFramework/src/Statements/DeleteStatement.cs index e4f9db157..28dab1486 100644 --- a/EntityFramework/src/Statements/DeleteStatement.cs +++ b/EntityFramework/src/Statements/DeleteStatement.cs @@ -1,4 +1,4 @@ -// Copyright © 2008, 2024, Oracle and/or its affiliates. +// Copyright © 2008, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/src/Statements/InsertStatement.cs b/EntityFramework/src/Statements/InsertStatement.cs index 9a818a170..0b22db824 100644 --- a/EntityFramework/src/Statements/InsertStatement.cs +++ b/EntityFramework/src/Statements/InsertStatement.cs @@ -1,4 +1,4 @@ -// Copyright © 2008, 2024, Oracle and/or its affiliates. +// Copyright © 2008, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/src/Statements/SelectStatement.cs b/EntityFramework/src/Statements/SelectStatement.cs index 74e7b2fef..cf355998e 100644 --- a/EntityFramework/src/Statements/SelectStatement.cs +++ b/EntityFramework/src/Statements/SelectStatement.cs @@ -1,4 +1,4 @@ -// Copyright © 2008, 2024, Oracle and/or its affiliates. +// Copyright © 2008, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/src/Statements/UpdateStatement.cs b/EntityFramework/src/Statements/UpdateStatement.cs index 7ae917d37..110106dd4 100644 --- a/EntityFramework/src/Statements/UpdateStatement.cs +++ b/EntityFramework/src/Statements/UpdateStatement.cs @@ -1,4 +1,4 @@ -// Copyright © 2008, 2024, Oracle and/or its affiliates. +// Copyright © 2008, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/AggregateOperators.cs b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/AggregateOperators.cs index 2692f73d1..2a19d098a 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/AggregateOperators.cs +++ b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/AggregateOperators.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/CanonicalFunctions.cs b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/CanonicalFunctions.cs index cecb039a7..1d9e66635 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/CanonicalFunctions.cs +++ b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/CanonicalFunctions.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/DataTypeTests.cs b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/DataTypeTests.cs index f36994dc8..7e5471d39 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/DataTypeTests.cs +++ b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/DataTypeTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/DatesTypesTests.cs b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/DatesTypesTests.cs index f9b72046e..801858c3c 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/DatesTypesTests.cs +++ b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/DatesTypesTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2011, 2024, Oracle and/or its affiliates. +// Copyright © 2011, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/DefaultContext.cs b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/DefaultContext.cs index 33e99cb62..4c2b5ca82 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/DefaultContext.cs +++ b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/DefaultContext.cs @@ -1,4 +1,4 @@ -// Copyright © 2014, 2024, Oracle and/or its affiliates. +// Copyright © 2014, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/DefaultFixture.cs b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/DefaultFixture.cs index bd36e9c6c..8efdebde4 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/DefaultFixture.cs +++ b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/DefaultFixture.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/DeleteTests.cs b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/DeleteTests.cs index eac1476b9..8429f1f6f 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/DeleteTests.cs +++ b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/DeleteTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/ExpressionTests.cs b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/ExpressionTests.cs index 9b2acc565..44667e099 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/ExpressionTests.cs +++ b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/ExpressionTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2015, 2024, Oracle and/or its affiliates. +// Copyright © 2015, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/GenericListener.cs b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/GenericListener.cs index ac9eb770f..dec000e96 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/GenericListener.cs +++ b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/GenericListener.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/InsertTests.cs b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/InsertTests.cs index 19c198969..2f1174097 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/InsertTests.cs +++ b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/InsertTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/JoinTests.cs b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/JoinTests.cs index 6528be396..bad80f7c0 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/JoinTests.cs +++ b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/JoinTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2014, 2024, Oracle and/or its affiliates. +// Copyright © 2014, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/MySql.EntityFramework.Basic.Tests.csproj b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/MySql.EntityFramework.Basic.Tests.csproj index 92e590f7e..1434a7522 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/MySql.EntityFramework.Basic.Tests.csproj +++ b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/MySql.EntityFramework.Basic.Tests.csproj @@ -2,7 +2,7 @@ MySql.Data.EntityFramework.CodeFirTests - Copyright © 2016, 2024, Oracle and/or its affiliates. + Copyright © 2016, 2025, Oracle and/or its affiliates. en-US 9.3.0 Oracle @@ -62,4 +62,4 @@ - \ No newline at end of file + diff --git a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/OrderingAndGrouping.cs b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/OrderingAndGrouping.cs index 4160653a9..c95c995df 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/OrderingAndGrouping.cs +++ b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/OrderingAndGrouping.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/Paging.cs b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/Paging.cs index 2b04847a1..aab415d67 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/Paging.cs +++ b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/Paging.cs @@ -1,4 +1,4 @@ -// Copyright © 2014, 2024, Oracle and/or its affiliates. +// Copyright © 2014, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/ProceduresAndFunctions.cs b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/ProceduresAndFunctions.cs index fd2b0126a..6a23d1b88 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/ProceduresAndFunctions.cs +++ b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/ProceduresAndFunctions.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/Properties/AssemblyInfo.cs b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/Properties/AssemblyInfo.cs index 0c52fccc9..2bd86ed8d 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/Properties/AssemblyInfo.cs +++ b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/Properties/AssemblyInfo.cs @@ -1,4 +1,4 @@ -// Copyright © 2008, 2024, Oracle and/or its affiliates. +// Copyright © 2008, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as @@ -38,7 +38,7 @@ [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Oracle")] [assembly: AssemblyProduct("MySql.Data.EntityFramework.Tests")] -[assembly: AssemblyCopyright("Copyright © 2008, 2024, Oracle and/or its affiliates.")] +[assembly: AssemblyCopyright("Copyright © 2008, 2025, Oracle and/or its affiliates.")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] diff --git a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/ProviderManifestTests.cs b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/ProviderManifestTests.cs index fb7e0f4cc..aae8e618c 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/ProviderManifestTests.cs +++ b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/ProviderManifestTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/ProviderServicesTests.cs b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/ProviderServicesTests.cs index 6a500f835..c7724fbaa 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/ProviderServicesTests.cs +++ b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/ProviderServicesTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/RelationalOperators.cs b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/RelationalOperators.cs index 63af2ec8f..8d19b5a35 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/RelationalOperators.cs +++ b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/RelationalOperators.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/RestrictionOperators.cs b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/RestrictionOperators.cs index 7e236f3e3..ee2e87f67 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/RestrictionOperators.cs +++ b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/RestrictionOperators.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/SchemaInformation.cs b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/SchemaInformation.cs index 6bf9c7fc6..533520f5d 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/SchemaInformation.cs +++ b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/SchemaInformation.cs @@ -1,4 +1,4 @@ -// Copyright © 2014, 2024, Oracle and/or its affiliates. +// Copyright © 2014, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/SetOperators.cs b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/SetOperators.cs index 3ebc28dbb..831028559 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/SetOperators.cs +++ b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/SetOperators.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/SimpleQuery.cs b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/SimpleQuery.cs index 8ef037ed9..5b5a5f857 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/SimpleQuery.cs +++ b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/SimpleQuery.cs @@ -1,4 +1,4 @@ -// Copyright © 2014, 2024, Oracle and/or its affiliates. +// Copyright © 2014, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/UpdateTests.cs b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/UpdateTests.cs index e47461739..887e14908 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/UpdateTests.cs +++ b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/UpdateTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/Wizard.cs b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/Wizard.cs index 9ed361481..331db08b4 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/Wizard.cs +++ b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/Wizard.cs @@ -1,4 +1,4 @@ -// Copyright © 2014, 2024, Oracle and/or its affiliates. +// Copyright © 2014, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/Blogs.cs b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/Blogs.cs index fb191bfd1..46654e07f 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/Blogs.cs +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/Blogs.cs @@ -1,4 +1,4 @@ -// Copyright © 2020, 2024, Oracle and/or its affiliates. +// Copyright © 2020, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/CodeFirstFixture.cs b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/CodeFirstFixture.cs index e5af704a4..95fe2c649 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/CodeFirstFixture.cs +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/CodeFirstFixture.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as @@ -191,4 +191,4 @@ public override void Fail(string message, string detailMessage) } } } -} \ No newline at end of file +} diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/CodeFirstTests.cs b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/CodeFirstTests.cs index a393ea79d..5796c3e1e 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/CodeFirstTests.cs +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/CodeFirstTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2014, 2024, Oracle and/or its affiliates. +// Copyright © 2014, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/ContextForNormalFk.cs b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/ContextForNormalFk.cs index 6596b2980..4f867370d 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/ContextForNormalFk.cs +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/ContextForNormalFk.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/ContextForString.cs b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/ContextForString.cs index b4aa8c757..131e32d2b 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/ContextForString.cs +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/ContextForString.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/Dinosauria.cs b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/Dinosauria.cs index 88cea952a..fcbd96de0 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/Dinosauria.cs +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/Dinosauria.cs @@ -1,4 +1,4 @@ -// Copyright © 2014, 2024, Oracle and/or its affiliates. +// Copyright © 2014, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/Movie.cs b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/Movie.cs index b9eef7b50..e7a03477e 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/Movie.cs +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/Movie.cs @@ -1,4 +1,4 @@ -// Copyright © 2014, 2024, Oracle and/or its affiliates. +// Copyright © 2014, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/MovieContextCodeBasedConfiguration.cs b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/MovieContextCodeBasedConfiguration.cs index a15080adc..eba30e4e5 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/MovieContextCodeBasedConfiguration.cs +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/MovieContextCodeBasedConfiguration.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/MySql.EntityFramework.CodeFirst.Tests.csproj b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/MySql.EntityFramework.CodeFirst.Tests.csproj index ffe3918ea..93bf4c32a 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/MySql.EntityFramework.CodeFirst.Tests.csproj +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/MySql.EntityFramework.CodeFirst.Tests.csproj @@ -2,7 +2,7 @@ MySql.Data.EntityFramework.CodeFirst.Tests - Copyright © 2016, 2024, Oracle and/or its affiliates. + Copyright © 2016, 2025, Oracle and/or its affiliates. en-US 9.3.0 Oracle @@ -89,4 +89,4 @@ - \ No newline at end of file + diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/PromotionsDB.cs b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/PromotionsDB.cs index 0c828a3c2..9ac820133 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/PromotionsDB.cs +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/PromotionsDB.cs @@ -1,4 +1,4 @@ -// Copyright © 2014, 2024, Oracle and/or its affiliates. +// Copyright © 2014, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/Properties/AssemblyInfo.cs b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/Properties/AssemblyInfo.cs index 04f490d66..deb966b88 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/Properties/AssemblyInfo.cs +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/Properties/AssemblyInfo.cs @@ -1,4 +1,4 @@ -// Copyright © 2014, 2024, Oracle and/or its affiliates. +// Copyright © 2014, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as @@ -38,7 +38,7 @@ [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Oracle")] [assembly: AssemblyProduct("MySql.EntityFramework.CodeFirst.Tests")] -[assembly: AssemblyCopyright("Copyright © 2011, 2024, Oracle and/or its affiliates.")] +[assembly: AssemblyCopyright("Copyright © 2011, 2025, Oracle and/or its affiliates.")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/Properties/sakila-data.sql b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/Properties/sakila-data.sql index e9d80306c..8d8cf971f 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/Properties/sakila-data.sql +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/Properties/sakila-data.sql @@ -1,7 +1,7 @@ -- Sakila Sample Database Data -- Version 1.0 --- Copyright © 2006, 2024, Oracle and/or its affiliates. +-- Copyright © 2006, 2025, Oracle and/or its affiliates. -- Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/Properties/sakila-schema.sql b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/Properties/sakila-schema.sql index 2d4ee1027..27d72af88 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/Properties/sakila-schema.sql +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/Properties/sakila-schema.sql @@ -1,7 +1,7 @@ -- Sakila Sample Database Schema -- Version 1.0 --- Copyright © 2006, 2024, Oracle and/or its affiliates. +-- Copyright © 2006, 2025, Oracle and/or its affiliates. -- Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/SakilaDb.cs b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/SakilaDb.cs index e55e11b2b..f85c5e1aa 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/SakilaDb.cs +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/SakilaDb.cs @@ -1,4 +1,4 @@ -// Copyright © 2015, 2024, Oracle and/or its affiliates. +// Copyright © 2015, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/actor.cs b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/actor.cs index 807687777..593109cba 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/actor.cs +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/actor.cs @@ -1,4 +1,4 @@ -// Copyright © 2014, 2024, Oracle and/or its affiliates. +// Copyright © 2014, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/actor_info.cs b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/actor_info.cs index 5bbca857d..6d67e3e3b 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/actor_info.cs +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/actor_info.cs @@ -1,4 +1,4 @@ -// Copyright © 2014, 2024, Oracle and/or its affiliates. +// Copyright © 2014, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/address.cs b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/address.cs index 468690dd3..57de2b153 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/address.cs +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/address.cs @@ -1,4 +1,4 @@ -// Copyright © 2014, 2024, Oracle and/or its affiliates. +// Copyright © 2014, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/category.cs b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/category.cs index 73427f5a1..ef201da34 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/category.cs +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/category.cs @@ -1,4 +1,4 @@ -// Copyright © 2014, 2024, Oracle and/or its affiliates. +// Copyright © 2014, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/city.cs b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/city.cs index d85e1697b..6df411949 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/city.cs +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/city.cs @@ -1,4 +1,4 @@ -// Copyright © 2014, 2024, Oracle and/or its affiliates. +// Copyright © 2014, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/country.cs b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/country.cs index 976f99ed4..85a4613db 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/country.cs +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/country.cs @@ -1,4 +1,4 @@ -// Copyright © 2014, 2024, Oracle and/or its affiliates. +// Copyright © 2014, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/customer.cs b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/customer.cs index 1e3e91d29..5d6fbbeca 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/customer.cs +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/customer.cs @@ -1,4 +1,4 @@ -// Copyright © 2014, 2024, Oracle and/or its affiliates. +// Copyright © 2014, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/customer_list.cs b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/customer_list.cs index 723dbbaa2..a0440407f 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/customer_list.cs +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/customer_list.cs @@ -1,4 +1,4 @@ -// Copyright © 2014, 2024, Oracle and/or its affiliates. +// Copyright © 2014, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/film.cs b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/film.cs index 0bfd594bf..715aa9f60 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/film.cs +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/film.cs @@ -1,4 +1,4 @@ -// Copyright © 2014, 2024, Oracle and/or its affiliates. +// Copyright © 2014, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/film_actor.cs b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/film_actor.cs index 2c7f0b3ad..572dd915f 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/film_actor.cs +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/film_actor.cs @@ -1,4 +1,4 @@ -// Copyright © 2014, 2024, Oracle and/or its affiliates. +// Copyright © 2014, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/film_category.cs b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/film_category.cs index 141bc32c0..f76371277 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/film_category.cs +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/film_category.cs @@ -1,4 +1,4 @@ -// Copyright © 2014, 2024, Oracle and/or its affiliates. +// Copyright © 2014, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/film_list.cs b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/film_list.cs index 72d666a2f..cfb3c6c80 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/film_list.cs +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/film_list.cs @@ -1,4 +1,4 @@ -// Copyright © 2014, 2024, Oracle and/or its affiliates. +// Copyright © 2014, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/film_text.cs b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/film_text.cs index 4172112a3..327a9b74e 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/film_text.cs +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/film_text.cs @@ -1,4 +1,4 @@ -// Copyright © 2014, 2024, Oracle and/or its affiliates. +// Copyright © 2014, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/inventory.cs b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/inventory.cs index dfe44cc9d..c8506e285 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/inventory.cs +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/inventory.cs @@ -1,4 +1,4 @@ -// Copyright © 2014, 2024, Oracle and/or its affiliates. +// Copyright © 2014, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/language.cs b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/language.cs index 11e03594a..f725d5b97 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/language.cs +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/language.cs @@ -1,4 +1,4 @@ -// Copyright © 2014, 2024, Oracle and/or its affiliates. +// Copyright © 2014, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/nicer_but_slower_film_list.cs b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/nicer_but_slower_film_list.cs index 18a3ba82a..c6bbcc04f 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/nicer_but_slower_film_list.cs +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/nicer_but_slower_film_list.cs @@ -1,4 +1,4 @@ -// Copyright © 2014, 2024, Oracle and/or its affiliates. +// Copyright © 2014, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/payment.cs b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/payment.cs index e5e340e12..5e2f44097 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/payment.cs +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/payment.cs @@ -1,4 +1,4 @@ -// Copyright © 2014, 2024, Oracle and/or its affiliates. +// Copyright © 2014, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/rental.cs b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/rental.cs index 0666386ae..676725c55 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/rental.cs +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/rental.cs @@ -1,4 +1,4 @@ -// Copyright © 2014, 2024, Oracle and/or its affiliates. +// Copyright © 2014, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/sales_by_film_category.cs b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/sales_by_film_category.cs index 3d57e8646..92f6a88a8 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/sales_by_film_category.cs +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/sales_by_film_category.cs @@ -1,4 +1,4 @@ -// Copyright © 2014, 2024, Oracle and/or its affiliates. +// Copyright © 2014, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/sales_by_store.cs b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/sales_by_store.cs index b201072ba..d6c5e81dc 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/sales_by_store.cs +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/sales_by_store.cs @@ -1,4 +1,4 @@ -// Copyright © 2014, 2024, Oracle and/or its affiliates. +// Copyright © 2014, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/staff.cs b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/staff.cs index e6b1de971..d117df6ff 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/staff.cs +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/staff.cs @@ -1,4 +1,4 @@ -// Copyright © 2014, 2024, Oracle and/or its affiliates. +// Copyright © 2014, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/staff_list.cs b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/staff_list.cs index 8178a9b58..3ed986485 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/staff_list.cs +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/staff_list.cs @@ -1,4 +1,4 @@ -// Copyright © 2014, 2024, Oracle and/or its affiliates. +// Copyright © 2014, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/store.cs b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/store.cs index 1e06daa1f..e32a13c0c 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/store.cs +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SakilaModel/store.cs @@ -1,4 +1,4 @@ -// Copyright © 2014, 2024, Oracle and/or its affiliates. +// Copyright © 2014, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/Ship.cs b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/Ship.cs index c84880871..b25950334 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/Ship.cs +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/Ship.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SiteDB.cs b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SiteDB.cs index 0c4ef948f..8e30623d4 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SiteDB.cs +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/SiteDB.cs @@ -1,4 +1,4 @@ -// Copyright © 2014, 2024, Oracle and/or its affiliates. +// Copyright © 2014, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/TransactionTests.cs b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/TransactionTests.cs index ad63970cc..15be38e01 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/TransactionTests.cs +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/TransactionTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2016, 2024, Oracle and/or its affiliates. +// Copyright © 2016, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/Vehicle.cs b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/Vehicle.cs index 4dd1630e7..f95bbbfa1 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/Vehicle.cs +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/Vehicle.cs @@ -1,4 +1,4 @@ -// Copyright © 2014, 2024, Oracle and/or its affiliates. +// Copyright © 2014, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/BlogsModel.cs b/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/BlogsModel.cs index c83ee138e..d2b4b4cf7 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/BlogsModel.cs +++ b/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/BlogsModel.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/MyConfiguration.cs b/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/MyConfiguration.cs index 79e6de550..b316b0781 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/MyConfiguration.cs +++ b/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/MyConfiguration.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/MySql.EntityFramework.Migrations.Tests.csproj b/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/MySql.EntityFramework.Migrations.Tests.csproj index 51d53f219..4aacbcf39 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/MySql.EntityFramework.Migrations.Tests.csproj +++ b/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/MySql.EntityFramework.Migrations.Tests.csproj @@ -2,7 +2,7 @@ MySql.Data.EntityFramework.Migrations.Tests - Copyright © 2016, 2024, Oracle and/or its affiliates. + Copyright © 2016, 2025, Oracle and/or its affiliates. en-US 9.3.0 Oracle @@ -58,4 +58,4 @@ Resources.Designer.cs - \ No newline at end of file + diff --git a/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/MySqlMigrationsTests.cs b/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/MySqlMigrationsTests.cs index e43268894..1fe29388d 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/MySqlMigrationsTests.cs +++ b/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/MySqlMigrationsTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/Properties/AssemblyInfo.cs b/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/Properties/AssemblyInfo.cs index 17dbf24a2..c337fd60a 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/Properties/AssemblyInfo.cs +++ b/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/Properties/AssemblyInfo.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as @@ -39,7 +39,7 @@ [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Oracle")] [assembly: AssemblyProduct("MySql.Data.EntityFramework.Migrations.Tests")] -[assembly: AssemblyCopyright("Copyright © 2013, 2024, Oracle and/or its affiliates.")] +[assembly: AssemblyCopyright("Copyright © 2013, 2025, Oracle and/or its affiliates.")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] diff --git a/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/SetUpMigrationsTests.cs b/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/SetUpMigrationsTests.cs index 1b5599a5f..f39c7375e 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/SetUpMigrationsTests.cs +++ b/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/SetUpMigrationsTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data.OpenTelemetry/src/MySQL.Data.OpenTelemetry.csproj b/MySQL.Data.OpenTelemetry/src/MySQL.Data.OpenTelemetry.csproj index f84a6c2e9..bc38d3e17 100644 --- a/MySQL.Data.OpenTelemetry/src/MySQL.Data.OpenTelemetry.csproj +++ b/MySQL.Data.OpenTelemetry/src/MySQL.Data.OpenTelemetry.csproj @@ -40,4 +40,4 @@ - \ No newline at end of file + diff --git a/MySQL.Data.OpenTelemetry/src/Properties/AssemblyInfo.cs b/MySQL.Data.OpenTelemetry/src/Properties/AssemblyInfo.cs index 37ea42a17..50362f2a6 100644 --- a/MySQL.Data.OpenTelemetry/src/Properties/AssemblyInfo.cs +++ b/MySQL.Data.OpenTelemetry/src/Properties/AssemblyInfo.cs @@ -1,4 +1,4 @@ -// Copyright © 2024, Oracle and/or its affiliates. +// Copyright © 2024, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data.OpenTelemetry/src/Properties/VersionInfo.cs b/MySQL.Data.OpenTelemetry/src/Properties/VersionInfo.cs index c8499687d..10ed39647 100644 --- a/MySQL.Data.OpenTelemetry/src/Properties/VersionInfo.cs +++ b/MySQL.Data.OpenTelemetry/src/Properties/VersionInfo.cs @@ -1,4 +1,4 @@ -// Copyright © 2024, Oracle and/or its affiliates. +// Copyright © 2024, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data.OpenTelemetry/src/TraceProviderBuilderExtension.cs b/MySQL.Data.OpenTelemetry/src/TraceProviderBuilderExtension.cs index 76393c2a3..0844c66db 100644 --- a/MySQL.Data.OpenTelemetry/src/TraceProviderBuilderExtension.cs +++ b/MySQL.Data.OpenTelemetry/src/TraceProviderBuilderExtension.cs @@ -1,4 +1,4 @@ -// Copyright © 2023, 2024, Oracle and/or its affiliates. +// Copyright © 2023, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as @@ -37,4 +37,4 @@ public static class TracerProviderBuilderExtensions public static TracerProviderBuilder AddConnectorNet( this TracerProviderBuilder builder) => builder.AddSource("connector-net"); -} \ No newline at end of file +} diff --git a/MySQL.Data/MySql.Replication.Tests/BaseTest.cs b/MySQL.Data/MySql.Replication.Tests/BaseTest.cs index 12f0220d2..0857d727a 100644 --- a/MySQL.Data/MySql.Replication.Tests/BaseTest.cs +++ b/MySQL.Data/MySql.Replication.Tests/BaseTest.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/MySql.Replication.Tests/Properties/AssemblyInfo.cs b/MySQL.Data/MySql.Replication.Tests/Properties/AssemblyInfo.cs index 0e3b4168c..cc810761b 100644 --- a/MySQL.Data/MySql.Replication.Tests/Properties/AssemblyInfo.cs +++ b/MySQL.Data/MySql.Replication.Tests/Properties/AssemblyInfo.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as @@ -39,7 +39,7 @@ [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Oracle Corporation")] [assembly: AssemblyProduct("MySql.LoadBalancing.Tests")] -[assembly: AssemblyCopyright("Copyright © 2013, 2024, Oracle and/or its affiliates.")] +[assembly: AssemblyCopyright("Copyright © 2013, 2025, Oracle and/or its affiliates.")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] diff --git a/MySQL.Data/MySql.Replication.Tests/ReplicationTest.cs b/MySQL.Data/MySql.Replication.Tests/ReplicationTest.cs index ce9dc5ff1..b6f53f857 100644 --- a/MySQL.Data/MySql.Replication.Tests/ReplicationTest.cs +++ b/MySQL.Data/MySql.Replication.Tests/ReplicationTest.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/MySql.Replication.Tests/SetUp.cs b/MySQL.Data/MySql.Replication.Tests/SetUp.cs index 72bba93ff..88edd19b7 100644 --- a/MySQL.Data/MySql.Replication.Tests/SetUp.cs +++ b/MySQL.Data/MySql.Replication.Tests/SetUp.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Authentication/AuthenticationManager.cs b/MySQL.Data/src/Authentication/AuthenticationManager.cs index cbdcf8adb..92435f652 100644 --- a/MySQL.Data/src/Authentication/AuthenticationManager.cs +++ b/MySQL.Data/src/Authentication/AuthenticationManager.cs @@ -1,4 +1,4 @@ -// Copyright © 2012, 2024, Oracle and/or its affiliates. +// Copyright © 2012, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Authentication/CachingSha2AuthenticationPlugin.cs b/MySQL.Data/src/Authentication/CachingSha2AuthenticationPlugin.cs index f93b060a8..96295a57c 100644 --- a/MySQL.Data/src/Authentication/CachingSha2AuthenticationPlugin.cs +++ b/MySQL.Data/src/Authentication/CachingSha2AuthenticationPlugin.cs @@ -1,4 +1,4 @@ -// Copyright © 2017, 2024, Oracle and/or its affiliates. +// Copyright © 2017, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Authentication/ClearPasswordPlugin.cs b/MySQL.Data/src/Authentication/ClearPasswordPlugin.cs index 6a7c4744a..b42ebda36 100644 --- a/MySQL.Data/src/Authentication/ClearPasswordPlugin.cs +++ b/MySQL.Data/src/Authentication/ClearPasswordPlugin.cs @@ -1,4 +1,4 @@ -// Copyright © 2020, 2024, Oracle and/or its affiliates. +// Copyright © 2020, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Authentication/FIDO/FidoAssertion.cs b/MySQL.Data/src/Authentication/FIDO/FidoAssertion.cs index 9c9f610a3..4df6de4e4 100644 --- a/MySQL.Data/src/Authentication/FIDO/FidoAssertion.cs +++ b/MySQL.Data/src/Authentication/FIDO/FidoAssertion.cs @@ -1,4 +1,4 @@ -// Copyright © 2022, 2024, Oracle and/or its affiliates. +// Copyright © 2022, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Authentication/FIDO/FidoDevice.cs b/MySQL.Data/src/Authentication/FIDO/FidoDevice.cs index 32fde9da4..71a20e1cb 100644 --- a/MySQL.Data/src/Authentication/FIDO/FidoDevice.cs +++ b/MySQL.Data/src/Authentication/FIDO/FidoDevice.cs @@ -1,4 +1,4 @@ -// Copyright © 2022, 2024, Oracle and/or its affiliates. +// Copyright © 2022, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Authentication/FIDO/FidoDeviceInfo.cs b/MySQL.Data/src/Authentication/FIDO/FidoDeviceInfo.cs index ccac1e5a3..d38a265bb 100644 --- a/MySQL.Data/src/Authentication/FIDO/FidoDeviceInfo.cs +++ b/MySQL.Data/src/Authentication/FIDO/FidoDeviceInfo.cs @@ -1,4 +1,4 @@ -// Copyright © 2022, 2024, Oracle and/or its affiliates. +// Copyright © 2022, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Authentication/FIDO/Native/NativeMethods.cs b/MySQL.Data/src/Authentication/FIDO/Native/NativeMethods.cs index 53d00e0ee..2931a61b3 100644 --- a/MySQL.Data/src/Authentication/FIDO/Native/NativeMethods.cs +++ b/MySQL.Data/src/Authentication/FIDO/Native/NativeMethods.cs @@ -1,4 +1,4 @@ -// Copyright © 2022, 2024, Oracle and/or its affiliates. +// Copyright © 2022, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General internal License, version 2.0, as diff --git a/MySQL.Data/src/Authentication/FIDO/Native/Structs.cs b/MySQL.Data/src/Authentication/FIDO/Native/Structs.cs index c56b3570c..29a2a24a6 100644 --- a/MySQL.Data/src/Authentication/FIDO/Native/Structs.cs +++ b/MySQL.Data/src/Authentication/FIDO/Native/Structs.cs @@ -1,4 +1,4 @@ -// Copyright © 2022, 2024, Oracle and/or its affiliates. +// Copyright © 2022, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Authentication/FIDO/Utility/ConstStringMarshaler.cs b/MySQL.Data/src/Authentication/FIDO/Utility/ConstStringMarshaler.cs index c6d7e6317..0129ab241 100644 --- a/MySQL.Data/src/Authentication/FIDO/Utility/ConstStringMarshaler.cs +++ b/MySQL.Data/src/Authentication/FIDO/Utility/ConstStringMarshaler.cs @@ -1,4 +1,4 @@ -// Copyright © 2022, 2024, Oracle and/or its affiliates. +// Copyright © 2022, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Authentication/FIDO/Utility/Enums.cs b/MySQL.Data/src/Authentication/FIDO/Utility/Enums.cs index 68ec522d4..41503cb68 100644 --- a/MySQL.Data/src/Authentication/FIDO/Utility/Enums.cs +++ b/MySQL.Data/src/Authentication/FIDO/Utility/Enums.cs @@ -1,4 +1,4 @@ -// Copyright © 2022, 2024, Oracle and/or its affiliates. +// Copyright © 2022, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Authentication/FIDO/Utility/Extensions.cs b/MySQL.Data/src/Authentication/FIDO/Utility/Extensions.cs index 2e9fd33cf..b141dc1af 100644 --- a/MySQL.Data/src/Authentication/FIDO/Utility/Extensions.cs +++ b/MySQL.Data/src/Authentication/FIDO/Utility/Extensions.cs @@ -1,4 +1,4 @@ -// Copyright © 2022, 2024, Oracle and/or its affiliates. +// Copyright © 2022, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Authentication/FIDO/Utility/FidoExceptions.cs b/MySQL.Data/src/Authentication/FIDO/Utility/FidoExceptions.cs index 4d628afe8..b0d5ce8dc 100644 --- a/MySQL.Data/src/Authentication/FIDO/Utility/FidoExceptions.cs +++ b/MySQL.Data/src/Authentication/FIDO/Utility/FidoExceptions.cs @@ -1,4 +1,4 @@ -// Copyright © 2022, 2024, Oracle and/or its affiliates. +// Copyright © 2022, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Authentication/FIDO/Utility/Init.cs b/MySQL.Data/src/Authentication/FIDO/Utility/Init.cs index 3b359c321..20d5584e5 100644 --- a/MySQL.Data/src/Authentication/FIDO/Utility/Init.cs +++ b/MySQL.Data/src/Authentication/FIDO/Utility/Init.cs @@ -1,4 +1,4 @@ -// Copyright © 2022, 2024, Oracle and/or its affiliates. +// Copyright © 2022, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Authentication/GSSAPI/Const.cs b/MySQL.Data/src/Authentication/GSSAPI/Const.cs index 4f70c4844..8f153be0c 100644 --- a/MySQL.Data/src/Authentication/GSSAPI/Const.cs +++ b/MySQL.Data/src/Authentication/GSSAPI/Const.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as @@ -107,4 +107,4 @@ internal static class Const }; #endregion } -} \ No newline at end of file +} diff --git a/MySQL.Data/src/Authentication/GSSAPI/GssContext.cs b/MySQL.Data/src/Authentication/GSSAPI/GssContext.cs index 70b070323..877656696 100644 --- a/MySQL.Data/src/Authentication/GSSAPI/GssContext.cs +++ b/MySQL.Data/src/Authentication/GSSAPI/GssContext.cs @@ -1,4 +1,4 @@ -// Copyright © 2020, 2024, Oracle and/or its affiliates. +// Copyright © 2020, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Authentication/GSSAPI/GssContextFlags.cs b/MySQL.Data/src/Authentication/GSSAPI/GssContextFlags.cs index d94f00a49..e0bb81172 100644 --- a/MySQL.Data/src/Authentication/GSSAPI/GssContextFlags.cs +++ b/MySQL.Data/src/Authentication/GSSAPI/GssContextFlags.cs @@ -1,4 +1,4 @@ -// Copyright © 2020, 2024, Oracle and/or its affiliates. +// Copyright © 2020, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Authentication/GSSAPI/GssCredentials.cs b/MySQL.Data/src/Authentication/GSSAPI/GssCredentials.cs index 49ca4af7b..ce0908868 100644 --- a/MySQL.Data/src/Authentication/GSSAPI/GssCredentials.cs +++ b/MySQL.Data/src/Authentication/GSSAPI/GssCredentials.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Authentication/GSSAPI/GssapiMechanism.cs b/MySQL.Data/src/Authentication/GSSAPI/GssapiMechanism.cs index 59653a8f7..d786785f8 100644 --- a/MySQL.Data/src/Authentication/GSSAPI/GssapiMechanism.cs +++ b/MySQL.Data/src/Authentication/GSSAPI/GssapiMechanism.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Authentication/GSSAPI/Native/GssBufferDescStruct.cs b/MySQL.Data/src/Authentication/GSSAPI/Native/GssBufferDescStruct.cs index 90dd88441..36932ed2d 100644 --- a/MySQL.Data/src/Authentication/GSSAPI/Native/GssBufferDescStruct.cs +++ b/MySQL.Data/src/Authentication/GSSAPI/Native/GssBufferDescStruct.cs @@ -1,4 +1,4 @@ -// Copyright © 2020, 2024, Oracle and/or its affiliates. +// Copyright © 2020, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Authentication/GSSAPI/Native/GssOidStruct.cs b/MySQL.Data/src/Authentication/GSSAPI/Native/GssOidStruct.cs index 5c1e68877..14165a5f9 100644 --- a/MySQL.Data/src/Authentication/GSSAPI/Native/GssOidStruct.cs +++ b/MySQL.Data/src/Authentication/GSSAPI/Native/GssOidStruct.cs @@ -1,4 +1,4 @@ -// Copyright © 2020, 2024, Oracle and/or its affiliates. +// Copyright © 2020, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Authentication/GSSAPI/Native/NativeMethods.cs b/MySQL.Data/src/Authentication/GSSAPI/Native/NativeMethods.cs index fc4c22001..7f4fe0c39 100644 --- a/MySQL.Data/src/Authentication/GSSAPI/Native/NativeMethods.cs +++ b/MySQL.Data/src/Authentication/GSSAPI/Native/NativeMethods.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Authentication/GSSAPI/Native/NativeMethodsLinux.cs b/MySQL.Data/src/Authentication/GSSAPI/Native/NativeMethodsLinux.cs index 90b3747df..0d8c060e8 100644 --- a/MySQL.Data/src/Authentication/GSSAPI/Native/NativeMethodsLinux.cs +++ b/MySQL.Data/src/Authentication/GSSAPI/Native/NativeMethodsLinux.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Authentication/GSSAPI/Native/NativeMethodsWin64.cs b/MySQL.Data/src/Authentication/GSSAPI/Native/NativeMethodsWin64.cs index 69e4bd2e1..0615eae73 100644 --- a/MySQL.Data/src/Authentication/GSSAPI/Native/NativeMethodsWin64.cs +++ b/MySQL.Data/src/Authentication/GSSAPI/Native/NativeMethodsWin64.cs @@ -1,4 +1,4 @@ -// Copyright © 2022, 2024, Oracle and/or its affiliates. +// Copyright © 2022, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Authentication/GSSAPI/Utility/Disposable.cs b/MySQL.Data/src/Authentication/GSSAPI/Utility/Disposable.cs index f4ad1e83f..45274babe 100644 --- a/MySQL.Data/src/Authentication/GSSAPI/Utility/Disposable.cs +++ b/MySQL.Data/src/Authentication/GSSAPI/Utility/Disposable.cs @@ -1,4 +1,4 @@ -// Copyright © 2020, 2024, Oracle and/or its affiliates. +// Copyright © 2020, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Authentication/GSSAPI/Utility/ExceptionMessages.cs b/MySQL.Data/src/Authentication/GSSAPI/Utility/ExceptionMessages.cs index 3fe8da347..c0947f76c 100644 --- a/MySQL.Data/src/Authentication/GSSAPI/Utility/ExceptionMessages.cs +++ b/MySQL.Data/src/Authentication/GSSAPI/Utility/ExceptionMessages.cs @@ -1,4 +1,4 @@ -// Copyright © 2020, 2024, Oracle and/or its affiliates. +// Copyright © 2020, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Authentication/GSSAPI/Utility/GssType.cs b/MySQL.Data/src/Authentication/GSSAPI/Utility/GssType.cs index ba2b00f56..49943759f 100644 --- a/MySQL.Data/src/Authentication/GSSAPI/Utility/GssType.cs +++ b/MySQL.Data/src/Authentication/GSSAPI/Utility/GssType.cs @@ -1,4 +1,4 @@ -// Copyright © 2020, 2024, Oracle and/or its affiliates. +// Copyright © 2020, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Authentication/GSSAPI/Utility/KerberosConfig.cs b/MySQL.Data/src/Authentication/GSSAPI/Utility/KerberosConfig.cs index b00744684..6d86220e6 100644 --- a/MySQL.Data/src/Authentication/GSSAPI/Utility/KerberosConfig.cs +++ b/MySQL.Data/src/Authentication/GSSAPI/Utility/KerberosConfig.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Authentication/GSSAPI/Utility/Pinned.cs b/MySQL.Data/src/Authentication/GSSAPI/Utility/Pinned.cs index f6f192280..ebfad7e84 100644 --- a/MySQL.Data/src/Authentication/GSSAPI/Utility/Pinned.cs +++ b/MySQL.Data/src/Authentication/GSSAPI/Utility/Pinned.cs @@ -1,4 +1,4 @@ -// Copyright © 2020, 2024, Oracle and/or its affiliates. +// Copyright © 2020, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Authentication/KerberosAuthenticationPlugin.cs b/MySQL.Data/src/Authentication/KerberosAuthenticationPlugin.cs index c85de89ce..57b30c6d4 100644 --- a/MySQL.Data/src/Authentication/KerberosAuthenticationPlugin.cs +++ b/MySQL.Data/src/Authentication/KerberosAuthenticationPlugin.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Authentication/MySQLAuthenticationPlugin.cs b/MySQL.Data/src/Authentication/MySQLAuthenticationPlugin.cs index 9af2e8f3b..48b2d38cc 100644 --- a/MySQL.Data/src/Authentication/MySQLAuthenticationPlugin.cs +++ b/MySQL.Data/src/Authentication/MySQLAuthenticationPlugin.cs @@ -1,4 +1,4 @@ -// Copyright © 2012, 2024, Oracle and/or its affiliates. +// Copyright © 2012, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Authentication/MySqlPemReader.cs b/MySQL.Data/src/Authentication/MySqlPemReader.cs index 22a09ff68..e89272f0e 100644 --- a/MySQL.Data/src/Authentication/MySqlPemReader.cs +++ b/MySQL.Data/src/Authentication/MySqlPemReader.cs @@ -1,4 +1,4 @@ -// Copyright © 2017, 2024, Oracle and/or its affiliates. +// Copyright © 2017, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Authentication/MySqlSASLPlugin.cs b/MySQL.Data/src/Authentication/MySqlSASLPlugin.cs index 12dbdc569..2b8bf0d41 100644 --- a/MySQL.Data/src/Authentication/MySqlSASLPlugin.cs +++ b/MySQL.Data/src/Authentication/MySqlSASLPlugin.cs @@ -1,4 +1,4 @@ -// Copyright © 2020, 2024, Oracle and/or its affiliates. +// Copyright © 2020, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Authentication/NativePasswordPlugins.cs b/MySQL.Data/src/Authentication/NativePasswordPlugins.cs index 53329e090..248a93d02 100644 --- a/MySQL.Data/src/Authentication/NativePasswordPlugins.cs +++ b/MySQL.Data/src/Authentication/NativePasswordPlugins.cs @@ -1,4 +1,4 @@ -// Copyright © 2012, 2024, Oracle and/or its affiliates. +// Copyright © 2012, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Authentication/OciAuthenticationPlugin.cs b/MySQL.Data/src/Authentication/OciAuthenticationPlugin.cs index 66c89dac9..dc3ade5f0 100644 --- a/MySQL.Data/src/Authentication/OciAuthenticationPlugin.cs +++ b/MySQL.Data/src/Authentication/OciAuthenticationPlugin.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Authentication/OpenIdConnectClientAuthentication.cs b/MySQL.Data/src/Authentication/OpenIdConnectClientAuthentication.cs index 44d12ecb4..b4ad5b251 100644 --- a/MySQL.Data/src/Authentication/OpenIdConnectClientAuthentication.cs +++ b/MySQL.Data/src/Authentication/OpenIdConnectClientAuthentication.cs @@ -1,4 +1,4 @@ -// Copyright © 2024, Oracle and/or its affiliates. +// Copyright © 2024, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Authentication/SSPI/Const.cs b/MySQL.Data/src/Authentication/SSPI/Const.cs index ec34d26e7..de84e35ca 100644 --- a/MySQL.Data/src/Authentication/SSPI/Const.cs +++ b/MySQL.Data/src/Authentication/SSPI/Const.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Authentication/SSPI/NativeMethods.cs b/MySQL.Data/src/Authentication/SSPI/NativeMethods.cs index 8c22c275e..3cc1277ca 100644 --- a/MySQL.Data/src/Authentication/SSPI/NativeMethods.cs +++ b/MySQL.Data/src/Authentication/SSPI/NativeMethods.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Authentication/SSPI/SspiCredentials.cs b/MySQL.Data/src/Authentication/SSPI/SspiCredentials.cs index 82674876e..682401d24 100644 --- a/MySQL.Data/src/Authentication/SSPI/SspiCredentials.cs +++ b/MySQL.Data/src/Authentication/SSPI/SspiCredentials.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Authentication/SSPI/SspiSecurityContext.cs b/MySQL.Data/src/Authentication/SSPI/SspiSecurityContext.cs index fb7add722..0f04fd1b0 100644 --- a/MySQL.Data/src/Authentication/SSPI/SspiSecurityContext.cs +++ b/MySQL.Data/src/Authentication/SSPI/SspiSecurityContext.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Authentication/SSPI/Structs.cs b/MySQL.Data/src/Authentication/SSPI/Structs.cs index 4a4d9b2d2..15d329fb4 100644 --- a/MySQL.Data/src/Authentication/SSPI/Structs.cs +++ b/MySQL.Data/src/Authentication/SSPI/Structs.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Authentication/ScramBase.cs b/MySQL.Data/src/Authentication/ScramBase.cs index 5d985667b..1a6a36192 100644 --- a/MySQL.Data/src/Authentication/ScramBase.cs +++ b/MySQL.Data/src/Authentication/ScramBase.cs @@ -1,4 +1,4 @@ -// Copyright © 2020, 2024, Oracle and/or its affiliates. +// Copyright © 2020, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Authentication/ScramSha1Mechanism.cs b/MySQL.Data/src/Authentication/ScramSha1Mechanism.cs index e6c63a7eb..d3e8ca6f8 100644 --- a/MySQL.Data/src/Authentication/ScramSha1Mechanism.cs +++ b/MySQL.Data/src/Authentication/ScramSha1Mechanism.cs @@ -1,4 +1,4 @@ -// Copyright © 2020, 2024, Oracle and/or its affiliates. +// Copyright © 2020, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Authentication/ScramSha256Mechanism.cs b/MySQL.Data/src/Authentication/ScramSha256Mechanism.cs index 367d3ec63..807d81853 100644 --- a/MySQL.Data/src/Authentication/ScramSha256Mechanism.cs +++ b/MySQL.Data/src/Authentication/ScramSha256Mechanism.cs @@ -1,4 +1,4 @@ -// Copyright © 2020, 2024, Oracle and/or its affiliates. +// Copyright © 2020, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Authentication/Sha256AuthenticationPlugin.cs b/MySQL.Data/src/Authentication/Sha256AuthenticationPlugin.cs index 86364bdeb..b6882ea70 100644 --- a/MySQL.Data/src/Authentication/Sha256AuthenticationPlugin.cs +++ b/MySQL.Data/src/Authentication/Sha256AuthenticationPlugin.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Authentication/Sha256MemoryAuthenticationPlugin.cs b/MySQL.Data/src/Authentication/Sha256MemoryAuthenticationPlugin.cs index f278178e9..8c6a6161c 100644 --- a/MySQL.Data/src/Authentication/Sha256MemoryAuthenticationPlugin.cs +++ b/MySQL.Data/src/Authentication/Sha256MemoryAuthenticationPlugin.cs @@ -1,4 +1,4 @@ -// Copyright © 2018, 2024, Oracle and/or its affiliates. +// Copyright © 2018, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Authentication/WebAuthnAuthenticationPlugin.cs b/MySQL.Data/src/Authentication/WebAuthnAuthenticationPlugin.cs index 2e3487a02..08375cae9 100644 --- a/MySQL.Data/src/Authentication/WebAuthnAuthenticationPlugin.cs +++ b/MySQL.Data/src/Authentication/WebAuthnAuthenticationPlugin.cs @@ -1,4 +1,4 @@ -// Copyright © 2023, 2024, Oracle and/or its affiliates. +// Copyright © 2023, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Authentication/WindowsAuthenticationPlugin.cs b/MySQL.Data/src/Authentication/WindowsAuthenticationPlugin.cs index af668f091..393c52967 100644 --- a/MySQL.Data/src/Authentication/WindowsAuthenticationPlugin.cs +++ b/MySQL.Data/src/Authentication/WindowsAuthenticationPlugin.cs @@ -1,4 +1,4 @@ -// Copyright © 2012, 2024, Oracle and/or its affiliates. +// Copyright © 2012, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/BulkLoader.cs b/MySQL.Data/src/BulkLoader.cs index c211d53e4..3d9d80359 100644 --- a/MySQL.Data/src/BulkLoader.cs +++ b/MySQL.Data/src/BulkLoader.cs @@ -1,4 +1,4 @@ -// Copyright © 2006, 2024, Oracle and/or its affiliates. +// Copyright © 2006, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/CharSetMap.cs b/MySQL.Data/src/CharSetMap.cs index 52bbc3e02..2d4f18e7d 100644 --- a/MySQL.Data/src/CharSetMap.cs +++ b/MySQL.Data/src/CharSetMap.cs @@ -1,4 +1,4 @@ -// Copyright © 2004, 2024, Oracle and/or its affiliates. +// Copyright © 2004, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/CompressedStream.cs b/MySQL.Data/src/CompressedStream.cs index 5a100569d..631cbe975 100644 --- a/MySQL.Data/src/CompressedStream.cs +++ b/MySQL.Data/src/CompressedStream.cs @@ -1,4 +1,4 @@ -// Copyright © 2004, 2024, Oracle and/or its affiliates. +// Copyright © 2004, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Crypt.cs b/MySQL.Data/src/Crypt.cs index ab13a858c..3f897479e 100644 --- a/MySQL.Data/src/Crypt.cs +++ b/MySQL.Data/src/Crypt.cs @@ -1,4 +1,4 @@ -// Copyright © 2004, 2024, Oracle and/or its affiliates. +// Copyright © 2004, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Driver.cs b/MySQL.Data/src/Driver.cs index 51db1aeb8..3ae102d32 100644 --- a/MySQL.Data/src/Driver.cs +++ b/MySQL.Data/src/Driver.cs @@ -1,4 +1,4 @@ -// Copyright © 2004, 2024, Oracle and/or its affiliates. +// Copyright © 2004, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Exception.cs b/MySQL.Data/src/Exception.cs index 121d8cf58..701ca4bd0 100644 --- a/MySQL.Data/src/Exception.cs +++ b/MySQL.Data/src/Exception.cs @@ -1,4 +1,4 @@ -// Copyright © 2004, 2024, Oracle and/or its affiliates. +// Copyright © 2004, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Failover/FailoverGroup.cs b/MySQL.Data/src/Failover/FailoverGroup.cs index f708ce12b..34d8765f8 100644 --- a/MySQL.Data/src/Failover/FailoverGroup.cs +++ b/MySQL.Data/src/Failover/FailoverGroup.cs @@ -1,4 +1,4 @@ -// Copyright © 2017, 2024, Oracle and/or its affiliates. +// Copyright © 2017, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Failover/FailoverManager.cs b/MySQL.Data/src/Failover/FailoverManager.cs index 236a52f26..faba5ad35 100644 --- a/MySQL.Data/src/Failover/FailoverManager.cs +++ b/MySQL.Data/src/Failover/FailoverManager.cs @@ -1,4 +1,4 @@ -// Copyright © 2017, 2024, Oracle and/or its affiliates. +// Copyright © 2017, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Failover/FailoverServer.cs b/MySQL.Data/src/Failover/FailoverServer.cs index 6081159f3..b0e7a7fb2 100644 --- a/MySQL.Data/src/Failover/FailoverServer.cs +++ b/MySQL.Data/src/Failover/FailoverServer.cs @@ -1,4 +1,4 @@ -// Copyright © 2017, 2024, Oracle and/or its affiliates. +// Copyright © 2017, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Failover/RandomFailoverGroup.cs b/MySQL.Data/src/Failover/RandomFailoverGroup.cs index e2af1ebc4..66db9d1ef 100644 --- a/MySQL.Data/src/Failover/RandomFailoverGroup.cs +++ b/MySQL.Data/src/Failover/RandomFailoverGroup.cs @@ -1,4 +1,4 @@ -// Copyright © 2019, 2024, Oracle and/or its affiliates. +// Copyright © 2019, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Failover/SequentialFailoverGroup.cs b/MySQL.Data/src/Failover/SequentialFailoverGroup.cs index 3214fcbf4..998b077c5 100644 --- a/MySQL.Data/src/Failover/SequentialFailoverGroup.cs +++ b/MySQL.Data/src/Failover/SequentialFailoverGroup.cs @@ -1,4 +1,4 @@ -// Copyright © 2017, 2024, Oracle and/or its affiliates. +// Copyright © 2017, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Field.cs b/MySQL.Data/src/Field.cs index 6f2e92a1c..29966d31b 100644 --- a/MySQL.Data/src/Field.cs +++ b/MySQL.Data/src/Field.cs @@ -1,4 +1,4 @@ -// Copyright © 2004, 2024, Oracle and/or its affiliates. +// Copyright © 2004, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Framework/net462/SystemPerformanceMonitor.cs b/MySQL.Data/src/Framework/net462/SystemPerformanceMonitor.cs index 8795311f6..736383f6d 100644 --- a/MySQL.Data/src/Framework/net462/SystemPerformanceMonitor.cs +++ b/MySQL.Data/src/Framework/net462/SystemPerformanceMonitor.cs @@ -1,4 +1,4 @@ -// Copyright © 2004, 2024, Oracle and/or its affiliates. +// Copyright © 2004, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Framework/netstandard2_0/AuthenticationManager.cs b/MySQL.Data/src/Framework/netstandard2_0/AuthenticationManager.cs index f1672c2a3..75d6356e9 100644 --- a/MySQL.Data/src/Framework/netstandard2_0/AuthenticationManager.cs +++ b/MySQL.Data/src/Framework/netstandard2_0/AuthenticationManager.cs @@ -1,4 +1,4 @@ -// Copyright © 2012, 2024, Oracle and/or its affiliates. +// Copyright © 2012, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Framework/netstandard2_0/CommandBuilder.cs b/MySQL.Data/src/Framework/netstandard2_0/CommandBuilder.cs index 1d3c2fb5b..64a00b0df 100644 --- a/MySQL.Data/src/Framework/netstandard2_0/CommandBuilder.cs +++ b/MySQL.Data/src/Framework/netstandard2_0/CommandBuilder.cs @@ -1,4 +1,4 @@ -// Copyright © 2004, 2024, Oracle and/or its affiliates. +// Copyright © 2004, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Framework/netstandard2_0/MySqlClientPermission.cs b/MySQL.Data/src/Framework/netstandard2_0/MySqlClientPermission.cs index c2892661c..8284cc347 100644 --- a/MySQL.Data/src/Framework/netstandard2_0/MySqlClientPermission.cs +++ b/MySQL.Data/src/Framework/netstandard2_0/MySqlClientPermission.cs @@ -1,4 +1,4 @@ -// Copyright © 2004, 2024, Oracle and/or its affiliates. +// Copyright © 2004, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Framework/netstandard2_0/MySqlClientPermissionAttribute.cs b/MySQL.Data/src/Framework/netstandard2_0/MySqlClientPermissionAttribute.cs index 9ebcf2a96..e2ee73a4a 100644 --- a/MySQL.Data/src/Framework/netstandard2_0/MySqlClientPermissionAttribute.cs +++ b/MySQL.Data/src/Framework/netstandard2_0/MySqlClientPermissionAttribute.cs @@ -1,4 +1,4 @@ -// Copyright © 2004, 2024, Oracle and/or its affiliates. +// Copyright © 2004, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Framework/netstandard2_0/MySqlConfiguration.cs b/MySQL.Data/src/Framework/netstandard2_0/MySqlConfiguration.cs index 8a2882b6f..af38bb5f9 100644 --- a/MySQL.Data/src/Framework/netstandard2_0/MySqlConfiguration.cs +++ b/MySQL.Data/src/Framework/netstandard2_0/MySqlConfiguration.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Framework/netstandard2_0/MySqlHelper.cs b/MySQL.Data/src/Framework/netstandard2_0/MySqlHelper.cs index 8049e040c..4b88132c7 100644 --- a/MySQL.Data/src/Framework/netstandard2_0/MySqlHelper.cs +++ b/MySQL.Data/src/Framework/netstandard2_0/MySqlHelper.cs @@ -1,4 +1,4 @@ -// Copyright © 2004, 2024, Oracle and/or its affiliates. +// Copyright © 2004, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Framework/netstandard2_0/MySqlPromotableTransaction.cs b/MySQL.Data/src/Framework/netstandard2_0/MySqlPromotableTransaction.cs index fcb67ee3f..c5e304829 100644 --- a/MySQL.Data/src/Framework/netstandard2_0/MySqlPromotableTransaction.cs +++ b/MySQL.Data/src/Framework/netstandard2_0/MySqlPromotableTransaction.cs @@ -1,4 +1,4 @@ -// Copyright © 2004, 2024, Oracle and/or its affiliates. +// Copyright © 2004, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Framework/netstandard2_0/MySqlSecurityPermission.cs b/MySQL.Data/src/Framework/netstandard2_0/MySqlSecurityPermission.cs index 17c20ded6..3319eb2cd 100644 --- a/MySQL.Data/src/Framework/netstandard2_0/MySqlSecurityPermission.cs +++ b/MySQL.Data/src/Framework/netstandard2_0/MySqlSecurityPermission.cs @@ -1,4 +1,4 @@ -// Copyright © 2011, 2024, Oracle and/or its affiliates. +// Copyright © 2011, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Framework/netstandard2_0/dataadapter.cs b/MySQL.Data/src/Framework/netstandard2_0/dataadapter.cs index e704af69f..402fcb3a9 100644 --- a/MySQL.Data/src/Framework/netstandard2_0/dataadapter.cs +++ b/MySQL.Data/src/Framework/netstandard2_0/dataadapter.cs @@ -1,4 +1,4 @@ -// Copyright © 2004, 2024, Oracle and/or its affiliates. +// Copyright © 2004, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/ISSchemaProvider.cs b/MySQL.Data/src/ISSchemaProvider.cs index decfa7016..545466a28 100644 --- a/MySQL.Data/src/ISSchemaProvider.cs +++ b/MySQL.Data/src/ISSchemaProvider.cs @@ -1,4 +1,4 @@ -// Copyright © 2004, 2024, Oracle and/or its affiliates. +// Copyright © 2004, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Interceptors/CommandInterceptor.cs b/MySQL.Data/src/Interceptors/CommandInterceptor.cs index 655801fef..34e0ebb32 100644 --- a/MySQL.Data/src/Interceptors/CommandInterceptor.cs +++ b/MySQL.Data/src/Interceptors/CommandInterceptor.cs @@ -1,4 +1,4 @@ -// Copyright © 2004, 2024, Oracle and/or its affiliates. +// Copyright © 2004, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Interceptors/ExceptionInterceptor.cs b/MySQL.Data/src/Interceptors/ExceptionInterceptor.cs index 332283c35..475c6dc30 100644 --- a/MySQL.Data/src/Interceptors/ExceptionInterceptor.cs +++ b/MySQL.Data/src/Interceptors/ExceptionInterceptor.cs @@ -1,4 +1,4 @@ -// Copyright © 2004, 2024, Oracle and/or its affiliates. +// Copyright © 2004, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Interceptors/Interceptor.cs b/MySQL.Data/src/Interceptors/Interceptor.cs index 1c4f99843..87dd0c572 100644 --- a/MySQL.Data/src/Interceptors/Interceptor.cs +++ b/MySQL.Data/src/Interceptors/Interceptor.cs @@ -1,4 +1,4 @@ -// Copyright © 2004, 2024, Oracle and/or its affiliates. +// Copyright © 2004, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/MySQLActivitySource.cs b/MySQL.Data/src/MySQLActivitySource.cs index 15e9cc665..739bcee09 100644 --- a/MySQL.Data/src/MySQLActivitySource.cs +++ b/MySQL.Data/src/MySQLActivitySource.cs @@ -1,4 +1,4 @@ -// Copyright © 2023, 2024, Oracle and/or its affiliates. +// Copyright © 2023, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/MySql.Data.csproj b/MySQL.Data/src/MySql.Data.csproj index ad5a5506c..c14166c20 100644 --- a/MySQL.Data/src/MySql.Data.csproj +++ b/MySQL.Data/src/MySql.Data.csproj @@ -128,4 +128,4 @@ - \ No newline at end of file + diff --git a/MySQL.Data/src/MySqlAttribute.cs b/MySQL.Data/src/MySqlAttribute.cs index f37930b3e..370b7c16a 100644 --- a/MySQL.Data/src/MySqlAttribute.cs +++ b/MySQL.Data/src/MySqlAttribute.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/MySqlAttributeCollection.cs b/MySQL.Data/src/MySqlAttributeCollection.cs index a98bed023..4c66ca4b9 100644 --- a/MySQL.Data/src/MySqlAttributeCollection.cs +++ b/MySQL.Data/src/MySqlAttributeCollection.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/MySqlBaseConnectionStringBuilder.cs b/MySQL.Data/src/MySqlBaseConnectionStringBuilder.cs index e3cf80f6d..278cbcf16 100644 --- a/MySQL.Data/src/MySqlBaseConnectionStringBuilder.cs +++ b/MySQL.Data/src/MySqlBaseConnectionStringBuilder.cs @@ -1,4 +1,4 @@ -// Copyright © 2018, 2024, Oracle and/or its affiliates. +// Copyright © 2018, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/MySqlClientFactory.cs b/MySQL.Data/src/MySqlClientFactory.cs index 236f77b24..29006a5b9 100644 --- a/MySQL.Data/src/MySqlClientFactory.cs +++ b/MySQL.Data/src/MySqlClientFactory.cs @@ -1,4 +1,4 @@ -// Copyright © 2004, 2024, Oracle and/or its affiliates. +// Copyright © 2004, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/MySqlCommand.cs b/MySQL.Data/src/MySqlCommand.cs index 9d389fb70..f6f93f415 100644 --- a/MySQL.Data/src/MySqlCommand.cs +++ b/MySQL.Data/src/MySqlCommand.cs @@ -1,4 +1,4 @@ -// Copyright © 2004, 2024, Oracle and/or its affiliates. +// Copyright © 2004, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/MySqlConnection.cs b/MySQL.Data/src/MySqlConnection.cs index 4f633f83b..e68debbf1 100644 --- a/MySQL.Data/src/MySqlConnection.cs +++ b/MySQL.Data/src/MySqlConnection.cs @@ -1,4 +1,4 @@ -// Copyright © 2004, 2024, Oracle and/or its affiliates. +// Copyright © 2004, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/MySqlConnectionStringBuilder.cs b/MySQL.Data/src/MySqlConnectionStringBuilder.cs index f371e6c51..c61949777 100644 --- a/MySQL.Data/src/MySqlConnectionStringBuilder.cs +++ b/MySQL.Data/src/MySqlConnectionStringBuilder.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/MySqlDataReader.cs b/MySQL.Data/src/MySqlDataReader.cs index ff86e4368..380dd648a 100644 --- a/MySQL.Data/src/MySqlDataReader.cs +++ b/MySQL.Data/src/MySqlDataReader.cs @@ -1,4 +1,4 @@ -// Copyright © 2004, 2024, Oracle and/or its affiliates. +// Copyright © 2004, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/MySqlError.cs b/MySQL.Data/src/MySqlError.cs index 219b14854..518aa70b0 100644 --- a/MySQL.Data/src/MySqlError.cs +++ b/MySQL.Data/src/MySqlError.cs @@ -1,4 +1,4 @@ -// Copyright © 2004, 2024, Oracle and/or its affiliates. +// Copyright © 2004, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/MySqlHelper.cs b/MySQL.Data/src/MySqlHelper.cs index 052ba4e6b..06447877c 100644 --- a/MySQL.Data/src/MySqlHelper.cs +++ b/MySQL.Data/src/MySqlHelper.cs @@ -1,4 +1,4 @@ -// Copyright © 2004, 2024, Oracle and/or its affiliates. +// Copyright © 2004, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/MySqlPacket.cs b/MySQL.Data/src/MySqlPacket.cs index 513a04be7..db939cca3 100644 --- a/MySQL.Data/src/MySqlPacket.cs +++ b/MySQL.Data/src/MySqlPacket.cs @@ -1,4 +1,4 @@ -// Copyright © 2004, 2024, Oracle and/or its affiliates. +// Copyright © 2004, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/MySqlParameter.cs b/MySQL.Data/src/MySqlParameter.cs index 5e9b95c88..4377aeb69 100644 --- a/MySQL.Data/src/MySqlParameter.cs +++ b/MySQL.Data/src/MySqlParameter.cs @@ -1,4 +1,4 @@ -// Copyright © 2004, 2024, Oracle and/or its affiliates. +// Copyright © 2004, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/MySqlParameterCollection.cs b/MySQL.Data/src/MySqlParameterCollection.cs index 54a1792a3..530ea93d6 100644 --- a/MySQL.Data/src/MySqlParameterCollection.cs +++ b/MySQL.Data/src/MySqlParameterCollection.cs @@ -1,4 +1,4 @@ -// Copyright © 2004, 2024, Oracle and/or its affiliates. +// Copyright © 2004, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/MySqlPool.cs b/MySQL.Data/src/MySqlPool.cs index e8efab95f..c8c9b5cec 100644 --- a/MySQL.Data/src/MySqlPool.cs +++ b/MySQL.Data/src/MySqlPool.cs @@ -1,4 +1,4 @@ -// Copyright © 2004, 2024, Oracle and/or its affiliates. +// Copyright © 2004, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/MySqlPoolManager.cs b/MySQL.Data/src/MySqlPoolManager.cs index 3e624340a..e3dea7676 100644 --- a/MySQL.Data/src/MySqlPoolManager.cs +++ b/MySQL.Data/src/MySqlPoolManager.cs @@ -1,4 +1,4 @@ -// Copyright © 2004, 2024, Oracle and/or its affiliates. +// Copyright © 2004, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/MySqlScript.cs b/MySQL.Data/src/MySqlScript.cs index ec116addf..d36b8ff02 100644 --- a/MySQL.Data/src/MySqlScript.cs +++ b/MySQL.Data/src/MySqlScript.cs @@ -1,4 +1,4 @@ -// Copyright © 2004, 2024, Oracle and/or its affiliates. +// Copyright © 2004, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/MySqlStream.cs b/MySQL.Data/src/MySqlStream.cs index f8de9c65d..60f79c199 100644 --- a/MySQL.Data/src/MySqlStream.cs +++ b/MySQL.Data/src/MySqlStream.cs @@ -1,4 +1,4 @@ -// Copyright © 2004, 2024, Oracle and/or its affiliates. +// Copyright © 2004, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/MySqlTrace.cs b/MySQL.Data/src/MySqlTrace.cs index bd35cdff9..f3282e5d4 100644 --- a/MySQL.Data/src/MySqlTrace.cs +++ b/MySQL.Data/src/MySqlTrace.cs @@ -1,4 +1,4 @@ -// Copyright © 2009, 2024, Oracle and/or its affiliates. +// Copyright © 2009, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/MySqlTransaction.cs b/MySQL.Data/src/MySqlTransaction.cs index d550763dc..a8b0c0c29 100644 --- a/MySQL.Data/src/MySqlTransaction.cs +++ b/MySQL.Data/src/MySqlTransaction.cs @@ -1,4 +1,4 @@ -// Copyright © 2004, 2024, Oracle and/or its affiliates. +// Copyright © 2004, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/MysqlDefs.cs b/MySQL.Data/src/MysqlDefs.cs index 82e54f2aa..e2d54081d 100644 --- a/MySQL.Data/src/MysqlDefs.cs +++ b/MySQL.Data/src/MysqlDefs.cs @@ -1,4 +1,4 @@ -// Copyright © 2004, 2024, Oracle and/or its affiliates. +// Copyright © 2004, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/NativeDriver.cs b/MySQL.Data/src/NativeDriver.cs index 0afe4712e..a726c2376 100644 --- a/MySQL.Data/src/NativeDriver.cs +++ b/MySQL.Data/src/NativeDriver.cs @@ -1,4 +1,4 @@ -// Copyright © 2004, 2024, Oracle and/or its affiliates. +// Copyright © 2004, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/OkPacket.cs b/MySQL.Data/src/OkPacket.cs index 57e07a360..45a05f8ff 100644 --- a/MySQL.Data/src/OkPacket.cs +++ b/MySQL.Data/src/OkPacket.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/PacketBitConverter.cs b/MySQL.Data/src/PacketBitConverter.cs index dc185ba94..9c20ae703 100644 --- a/MySQL.Data/src/PacketBitConverter.cs +++ b/MySQL.Data/src/PacketBitConverter.cs @@ -1,4 +1,4 @@ -// Copyright © 2004, 2024, Oracle and/or its affiliates. +// Copyright © 2004, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/PerformanceMonitor.cs b/MySQL.Data/src/PerformanceMonitor.cs index b4d93afc6..3f786dfc7 100644 --- a/MySQL.Data/src/PerformanceMonitor.cs +++ b/MySQL.Data/src/PerformanceMonitor.cs @@ -1,4 +1,4 @@ -// Copyright © 2004, 2024, Oracle and/or its affiliates. +// Copyright © 2004, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/PreparableStatement.cs b/MySQL.Data/src/PreparableStatement.cs index 02a7762e8..0f67d6413 100644 --- a/MySQL.Data/src/PreparableStatement.cs +++ b/MySQL.Data/src/PreparableStatement.cs @@ -1,4 +1,4 @@ -// Copyright © 2004, 2024, Oracle and/or its affiliates. +// Copyright © 2004, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/ProcedureCache.cs b/MySQL.Data/src/ProcedureCache.cs index 0a5662f41..0e9aada5c 100644 --- a/MySQL.Data/src/ProcedureCache.cs +++ b/MySQL.Data/src/ProcedureCache.cs @@ -1,4 +1,4 @@ -// Copyright © 2004, 2024, Oracle and/or its affiliates. +// Copyright © 2004, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Properties/AssemblyInfo.cs b/MySQL.Data/src/Properties/AssemblyInfo.cs index 7dcf1fca6..402af246b 100644 --- a/MySQL.Data/src/Properties/AssemblyInfo.cs +++ b/MySQL.Data/src/Properties/AssemblyInfo.cs @@ -1,4 +1,4 @@ -// Copyright © 2004, 2024, Oracle and/or its affiliates. +// Copyright © 2004, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Properties/VersionInfo.cs b/MySQL.Data/src/Properties/VersionInfo.cs index 2812dd600..d259e153d 100644 --- a/MySQL.Data/src/Properties/VersionInfo.cs +++ b/MySQL.Data/src/Properties/VersionInfo.cs @@ -1,4 +1,4 @@ -// Copyright © 2004, 2024, Oracle and/or its affiliates. +// Copyright © 2004, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Replication/ReplicationConfiguration.cs b/MySQL.Data/src/Replication/ReplicationConfiguration.cs index 767d1b179..8cbd52523 100644 --- a/MySQL.Data/src/Replication/ReplicationConfiguration.cs +++ b/MySQL.Data/src/Replication/ReplicationConfiguration.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Replication/ReplicationManager.cs b/MySQL.Data/src/Replication/ReplicationManager.cs index 48d0e3186..bd6f696ed 100644 --- a/MySQL.Data/src/Replication/ReplicationManager.cs +++ b/MySQL.Data/src/Replication/ReplicationManager.cs @@ -1,4 +1,4 @@ -// Copyright © 2014, 2024, Oracle and/or its affiliates. +// Copyright © 2014, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Replication/ReplicationRoundRobinServerGroup.cs b/MySQL.Data/src/Replication/ReplicationRoundRobinServerGroup.cs index b66a7a2e7..6fae451fc 100644 --- a/MySQL.Data/src/Replication/ReplicationRoundRobinServerGroup.cs +++ b/MySQL.Data/src/Replication/ReplicationRoundRobinServerGroup.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Replication/ReplicationServer.cs b/MySQL.Data/src/Replication/ReplicationServer.cs index 23b616853..c1b14506c 100644 --- a/MySQL.Data/src/Replication/ReplicationServer.cs +++ b/MySQL.Data/src/Replication/ReplicationServer.cs @@ -1,4 +1,4 @@ -// Copyright © 2014, 2024, Oracle and/or its affiliates. +// Copyright © 2014, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Replication/ReplicationServerGroup.cs b/MySQL.Data/src/Replication/ReplicationServerGroup.cs index cb3e843a5..237348ba6 100644 --- a/MySQL.Data/src/Replication/ReplicationServerGroup.cs +++ b/MySQL.Data/src/Replication/ReplicationServerGroup.cs @@ -1,4 +1,4 @@ -// Copyright © 2014, 2024, Oracle and/or its affiliates. +// Copyright © 2014, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/ResultSet.cs b/MySQL.Data/src/ResultSet.cs index 0de428e0e..3b7fa890f 100644 --- a/MySQL.Data/src/ResultSet.cs +++ b/MySQL.Data/src/ResultSet.cs @@ -1,4 +1,4 @@ -// Copyright © 2009, 2024, Oracle and/or its affiliates. +// Copyright © 2009, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Runtime.cs b/MySQL.Data/src/Runtime.cs index 089f1ec05..beb65869b 100644 --- a/MySQL.Data/src/Runtime.cs +++ b/MySQL.Data/src/Runtime.cs @@ -1,4 +1,4 @@ -// Copyright © 2014, 2024, Oracle and/or its affiliates. +// Copyright © 2014, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Schema.cs b/MySQL.Data/src/Schema.cs index 4401cfec4..d63a28d86 100644 --- a/MySQL.Data/src/Schema.cs +++ b/MySQL.Data/src/Schema.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/SchemaProvider.cs b/MySQL.Data/src/SchemaProvider.cs index f56b8a78d..5141f383e 100644 --- a/MySQL.Data/src/SchemaProvider.cs +++ b/MySQL.Data/src/SchemaProvider.cs @@ -1,4 +1,4 @@ -// Copyright © 2004, 2024, Oracle and/or its affiliates. +// Copyright © 2004, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Statement.cs b/MySQL.Data/src/Statement.cs index 5e559af42..2b3c81d54 100644 --- a/MySQL.Data/src/Statement.cs +++ b/MySQL.Data/src/Statement.cs @@ -1,4 +1,4 @@ -// Copyright © 2004, 2024, Oracle and/or its affiliates. +// Copyright © 2004, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/StoredProcedure.cs b/MySQL.Data/src/StoredProcedure.cs index 96da29eda..4a7cc52bc 100644 --- a/MySQL.Data/src/StoredProcedure.cs +++ b/MySQL.Data/src/StoredProcedure.cs @@ -1,4 +1,4 @@ -// Copyright © 2004, 2024, Oracle and/or its affiliates. +// Copyright © 2004, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/TableCache.cs b/MySQL.Data/src/TableCache.cs index 3928a3ec3..2944cb380 100644 --- a/MySQL.Data/src/TableCache.cs +++ b/MySQL.Data/src/TableCache.cs @@ -1,4 +1,4 @@ -// Copyright © 2016, 2024, Oracle and/or its affiliates. +// Copyright © 2016, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as @@ -161,4 +161,4 @@ private struct CacheEntry } } -} \ No newline at end of file +} diff --git a/MySQL.Data/src/TimedStream.cs b/MySQL.Data/src/TimedStream.cs index d622c4126..4d788cdb3 100644 --- a/MySQL.Data/src/TimedStream.cs +++ b/MySQL.Data/src/TimedStream.cs @@ -1,4 +1,4 @@ -// Copyright © 2009, 2024, Oracle and/or its affiliates. +// Copyright © 2009, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/TracingDriver.cs b/MySQL.Data/src/TracingDriver.cs index 22fb996cd..308b767cd 100644 --- a/MySQL.Data/src/TracingDriver.cs +++ b/MySQL.Data/src/TracingDriver.cs @@ -1,4 +1,4 @@ -// Copyright © 2009, 2024, Oracle and/or its affiliates. +// Copyright © 2009, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Types/IMySqlValue.cs b/MySQL.Data/src/Types/IMySqlValue.cs index 891e62bb1..2b3df6aca 100644 --- a/MySQL.Data/src/Types/IMySqlValue.cs +++ b/MySQL.Data/src/Types/IMySqlValue.cs @@ -1,4 +1,4 @@ -// Copyright © 2004, 2024, Oracle and/or its affiliates. +// Copyright © 2004, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Types/MetaData.cs b/MySQL.Data/src/Types/MetaData.cs index 9d3df15a6..61fbb28de 100644 --- a/MySQL.Data/src/Types/MetaData.cs +++ b/MySQL.Data/src/Types/MetaData.cs @@ -1,4 +1,4 @@ -// Copyright © 2004, 2024, Oracle and/or its affiliates. +// Copyright © 2004, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Types/MySqlBinary.cs b/MySQL.Data/src/Types/MySqlBinary.cs index 21d398eba..29faae119 100644 --- a/MySQL.Data/src/Types/MySqlBinary.cs +++ b/MySQL.Data/src/Types/MySqlBinary.cs @@ -1,4 +1,4 @@ -// Copyright © 2004, 2024, Oracle and/or its affiliates. +// Copyright © 2004, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Types/MySqlBit.cs b/MySQL.Data/src/Types/MySqlBit.cs index 9ca6fbfcc..31fd94db8 100644 --- a/MySQL.Data/src/Types/MySqlBit.cs +++ b/MySQL.Data/src/Types/MySqlBit.cs @@ -1,4 +1,4 @@ -// Copyright © 2004, 2024, Oracle and/or its affiliates. +// Copyright © 2004, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Types/MySqlByte.cs b/MySQL.Data/src/Types/MySqlByte.cs index 35fcbb28b..38b62bf8a 100644 --- a/MySQL.Data/src/Types/MySqlByte.cs +++ b/MySQL.Data/src/Types/MySqlByte.cs @@ -1,4 +1,4 @@ -// Copyright © 2004, 2024, Oracle and/or its affiliates. +// Copyright © 2004, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Types/MySqlConversionException.cs b/MySQL.Data/src/Types/MySqlConversionException.cs index 3ca0deaa8..727fcd07a 100644 --- a/MySQL.Data/src/Types/MySqlConversionException.cs +++ b/MySQL.Data/src/Types/MySqlConversionException.cs @@ -1,4 +1,4 @@ -// Copyright © 2004, 2024, Oracle and/or its affiliates. +// Copyright © 2004, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Types/MySqlDateTime.cs b/MySQL.Data/src/Types/MySqlDateTime.cs index e8984f0da..e7d1ff9a1 100644 --- a/MySQL.Data/src/Types/MySqlDateTime.cs +++ b/MySQL.Data/src/Types/MySqlDateTime.cs @@ -1,4 +1,4 @@ -// Copyright © 2004, 2024, Oracle and/or its affiliates. +// Copyright © 2004, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Types/MySqlDecimal.cs b/MySQL.Data/src/Types/MySqlDecimal.cs index fa679f63e..13780c88c 100644 --- a/MySQL.Data/src/Types/MySqlDecimal.cs +++ b/MySQL.Data/src/Types/MySqlDecimal.cs @@ -1,4 +1,4 @@ -// Copyright © 2004, 2024, Oracle and/or its affiliates. +// Copyright © 2004, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Types/MySqlDouble.cs b/MySQL.Data/src/Types/MySqlDouble.cs index 9b342b6ba..de72338fe 100644 --- a/MySQL.Data/src/Types/MySqlDouble.cs +++ b/MySQL.Data/src/Types/MySqlDouble.cs @@ -1,4 +1,4 @@ -// Copyright © 2004, 2024, Oracle and/or its affiliates. +// Copyright © 2004, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Types/MySqlGeometry.cs b/MySQL.Data/src/Types/MySqlGeometry.cs index 963ee3837..9472e4b51 100644 --- a/MySQL.Data/src/Types/MySqlGeometry.cs +++ b/MySQL.Data/src/Types/MySqlGeometry.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Types/MySqlGuid.cs b/MySQL.Data/src/Types/MySqlGuid.cs index 7e2fa5129..5651a7501 100644 --- a/MySQL.Data/src/Types/MySqlGuid.cs +++ b/MySQL.Data/src/Types/MySqlGuid.cs @@ -1,4 +1,4 @@ -// Copyright © 2004, 2024, Oracle and/or its affiliates. +// Copyright © 2004, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Types/MySqlInt16.cs b/MySQL.Data/src/Types/MySqlInt16.cs index 805e296b1..96a9577e0 100644 --- a/MySQL.Data/src/Types/MySqlInt16.cs +++ b/MySQL.Data/src/Types/MySqlInt16.cs @@ -1,4 +1,4 @@ -// Copyright © 2004, 2024, Oracle and/or its affiliates. +// Copyright © 2004, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Types/MySqlInt32.cs b/MySQL.Data/src/Types/MySqlInt32.cs index 6cda1fa52..81aaba5af 100644 --- a/MySQL.Data/src/Types/MySqlInt32.cs +++ b/MySQL.Data/src/Types/MySqlInt32.cs @@ -1,4 +1,4 @@ -// Copyright © 2004, 2024, Oracle and/or its affiliates. +// Copyright © 2004, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Types/MySqlInt64.cs b/MySQL.Data/src/Types/MySqlInt64.cs index 8fea63889..b0bae03ed 100644 --- a/MySQL.Data/src/Types/MySqlInt64.cs +++ b/MySQL.Data/src/Types/MySqlInt64.cs @@ -1,4 +1,4 @@ -// Copyright © 2004, 2024, Oracle and/or its affiliates. +// Copyright © 2004, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Types/MySqlSingle.cs b/MySQL.Data/src/Types/MySqlSingle.cs index 9dc777912..5973d4542 100644 --- a/MySQL.Data/src/Types/MySqlSingle.cs +++ b/MySQL.Data/src/Types/MySqlSingle.cs @@ -1,4 +1,4 @@ -// Copyright © 2004, 2024, Oracle and/or its affiliates. +// Copyright © 2004, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Types/MySqlString.cs b/MySQL.Data/src/Types/MySqlString.cs index f9bd06d6d..d7b2a8b2b 100644 --- a/MySQL.Data/src/Types/MySqlString.cs +++ b/MySQL.Data/src/Types/MySqlString.cs @@ -1,4 +1,4 @@ -// Copyright © 2004, 2024, Oracle and/or its affiliates. +// Copyright © 2004, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Types/MySqlTime.cs b/MySQL.Data/src/Types/MySqlTime.cs index 8ef8fb77e..bd0969023 100644 --- a/MySQL.Data/src/Types/MySqlTime.cs +++ b/MySQL.Data/src/Types/MySqlTime.cs @@ -1,4 +1,4 @@ -// Copyright © 2004, 2024, Oracle and/or its affiliates. +// Copyright © 2004, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Types/MySqlUByte.cs b/MySQL.Data/src/Types/MySqlUByte.cs index e773d6d03..5db414eed 100644 --- a/MySQL.Data/src/Types/MySqlUByte.cs +++ b/MySQL.Data/src/Types/MySqlUByte.cs @@ -1,4 +1,4 @@ -// Copyright © 2004, 2024, Oracle and/or its affiliates. +// Copyright © 2004, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Types/MySqlUInt16.cs b/MySQL.Data/src/Types/MySqlUInt16.cs index e407f95cd..183b66f77 100644 --- a/MySQL.Data/src/Types/MySqlUInt16.cs +++ b/MySQL.Data/src/Types/MySqlUInt16.cs @@ -1,4 +1,4 @@ -// Copyright © 2004, 2024, Oracle and/or its affiliates. +// Copyright © 2004, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Types/MySqlUInt32.cs b/MySQL.Data/src/Types/MySqlUInt32.cs index 612ec6383..a5d9af68d 100644 --- a/MySQL.Data/src/Types/MySqlUInt32.cs +++ b/MySQL.Data/src/Types/MySqlUInt32.cs @@ -1,4 +1,4 @@ -// Copyright © 2004, 2024, Oracle and/or its affiliates. +// Copyright © 2004, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Types/MySqlUInt64.cs b/MySQL.Data/src/Types/MySqlUInt64.cs index 15ebc5146..d19033180 100644 --- a/MySQL.Data/src/Types/MySqlUInt64.cs +++ b/MySQL.Data/src/Types/MySqlUInt64.cs @@ -1,4 +1,4 @@ -// Copyright © 2004, 2024, Oracle and/or its affiliates. +// Copyright © 2004, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/Utils.cs b/MySQL.Data/src/Utils.cs index e023de66b..329c3a3f7 100644 --- a/MySQL.Data/src/Utils.cs +++ b/MySQL.Data/src/Utils.cs @@ -1,4 +1,4 @@ -// Copyright © 2004, 2024, Oracle and/or its affiliates. +// Copyright © 2004, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/Authentication/ExternalAuthenticationPlugin.cs b/MySQL.Data/src/X/Authentication/ExternalAuthenticationPlugin.cs index ef7916205..6417a9ad2 100644 --- a/MySQL.Data/src/X/Authentication/ExternalAuthenticationPlugin.cs +++ b/MySQL.Data/src/X/Authentication/ExternalAuthenticationPlugin.cs @@ -1,4 +1,4 @@ -// Copyright © 2017, 2024, Oracle and/or its affiliates. +// Copyright © 2017, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/Authentication/MySQL41AuthenticationPlugin.cs b/MySQL.Data/src/X/Authentication/MySQL41AuthenticationPlugin.cs index a64f8cbf3..c4ef053d3 100644 --- a/MySQL.Data/src/X/Authentication/MySQL41AuthenticationPlugin.cs +++ b/MySQL.Data/src/X/Authentication/MySQL41AuthenticationPlugin.cs @@ -1,4 +1,4 @@ -// Copyright © 2015, 2024, Oracle and/or its affiliates. +// Copyright © 2015, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/Authentication/PlainAuthenticationPlugin.cs b/MySQL.Data/src/X/Authentication/PlainAuthenticationPlugin.cs index f0ca78138..824768ec1 100644 --- a/MySQL.Data/src/X/Authentication/PlainAuthenticationPlugin.cs +++ b/MySQL.Data/src/X/Authentication/PlainAuthenticationPlugin.cs @@ -1,4 +1,4 @@ -// Copyright © 2017, 2024, Oracle and/or its affiliates. +// Copyright © 2017, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/Common/Tools.cs b/MySQL.Data/src/X/Common/Tools.cs index b74fab9e4..814b5ab18 100644 --- a/MySQL.Data/src/X/Common/Tools.cs +++ b/MySQL.Data/src/X/Common/Tools.cs @@ -1,4 +1,4 @@ -// Copyright © 2014, 2024, Oracle and/or its affiliates. +// Copyright © 2014, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/Common/UnmanagedLibraryLoader.cs b/MySQL.Data/src/X/Common/UnmanagedLibraryLoader.cs index 8f0f6e419..a15352bee 100644 --- a/MySQL.Data/src/X/Common/UnmanagedLibraryLoader.cs +++ b/MySQL.Data/src/X/Common/UnmanagedLibraryLoader.cs @@ -1,4 +1,4 @@ -// Copyright © 2022, 2024, Oracle and/or its affiliates. +// Copyright © 2022, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/Communication/CommunicationPacket.cs b/MySQL.Data/src/X/Communication/CommunicationPacket.cs index 930593c45..76ab9ef25 100644 --- a/MySQL.Data/src/X/Communication/CommunicationPacket.cs +++ b/MySQL.Data/src/X/Communication/CommunicationPacket.cs @@ -1,4 +1,4 @@ -// Copyright © 2015, 2024, Oracle and/or its affiliates. +// Copyright © 2015, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/Communication/XCompressionController.cs b/MySQL.Data/src/X/Communication/XCompressionController.cs index fd55c5dc9..7dc6485f0 100644 --- a/MySQL.Data/src/X/Communication/XCompressionController.cs +++ b/MySQL.Data/src/X/Communication/XCompressionController.cs @@ -1,4 +1,4 @@ -// Copyright © 2019, 2024, Oracle and/or its affiliates. +// Copyright © 2019, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/Communication/XPacketProcessor.cs b/MySQL.Data/src/X/Communication/XPacketProcessor.cs index df411e154..4da0c79e3 100644 --- a/MySQL.Data/src/X/Communication/XPacketProcessor.cs +++ b/MySQL.Data/src/X/Communication/XPacketProcessor.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/Communication/XPacketReaderWriter.cs b/MySQL.Data/src/X/Communication/XPacketReaderWriter.cs index 4002b7f36..a9ead2a58 100644 --- a/MySQL.Data/src/X/Communication/XPacketReaderWriter.cs +++ b/MySQL.Data/src/X/Communication/XPacketReaderWriter.cs @@ -1,4 +1,4 @@ -// Copyright © 2015, 2024, Oracle and/or its affiliates. +// Copyright © 2015, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/Data/CollationMap.cs b/MySQL.Data/src/X/Data/CollationMap.cs index 7f717f079..11b694d94 100644 --- a/MySQL.Data/src/X/Data/CollationMap.cs +++ b/MySQL.Data/src/X/Data/CollationMap.cs @@ -1,4 +1,4 @@ -// Copyright © 2016, 2024, Oracle and/or its affiliates. +// Copyright © 2016, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/Data/Enums.cs b/MySQL.Data/src/X/Data/Enums.cs index 2cb0f2f56..7eea5cfee 100644 --- a/MySQL.Data/src/X/Data/Enums.cs +++ b/MySQL.Data/src/X/Data/Enums.cs @@ -1,4 +1,4 @@ -// Copyright © 2015, 2024, Oracle and/or its affiliates. +// Copyright © 2015, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/Protocol/ProtocolBase.cs b/MySQL.Data/src/X/Protocol/ProtocolBase.cs index cf96b6a9b..e8e469313 100644 --- a/MySQL.Data/src/X/Protocol/ProtocolBase.cs +++ b/MySQL.Data/src/X/Protocol/ProtocolBase.cs @@ -1,4 +1,4 @@ -// Copyright © 2015, 2024, Oracle and/or its affiliates. +// Copyright © 2015, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/Protocol/ValueDecoder.cs b/MySQL.Data/src/X/Protocol/ValueDecoder.cs index aff72fb26..5ec439f9f 100644 --- a/MySQL.Data/src/X/Protocol/ValueDecoder.cs +++ b/MySQL.Data/src/X/Protocol/ValueDecoder.cs @@ -1,4 +1,4 @@ -// Copyright © 2015, 2024, Oracle and/or its affiliates. +// Copyright © 2015, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/Protocol/X/BitDecoder.cs b/MySQL.Data/src/X/Protocol/X/BitDecoder.cs index 55796cb1f..cc8971581 100644 --- a/MySQL.Data/src/X/Protocol/X/BitDecoder.cs +++ b/MySQL.Data/src/X/Protocol/X/BitDecoder.cs @@ -1,4 +1,4 @@ -// Copyright © 2016, 2024, Oracle and/or its affiliates. +// Copyright © 2016, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/Protocol/X/ByteDecoder.cs b/MySQL.Data/src/X/Protocol/X/ByteDecoder.cs index c85f49668..af7e0f8ba 100644 --- a/MySQL.Data/src/X/Protocol/X/ByteDecoder.cs +++ b/MySQL.Data/src/X/Protocol/X/ByteDecoder.cs @@ -1,4 +1,4 @@ -// Copyright © 2015, 2024, Oracle and/or its affiliates. +// Copyright © 2015, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/Protocol/X/DecimalDecoder.cs b/MySQL.Data/src/X/Protocol/X/DecimalDecoder.cs index a064eb2e1..1b4360db5 100644 --- a/MySQL.Data/src/X/Protocol/X/DecimalDecoder.cs +++ b/MySQL.Data/src/X/Protocol/X/DecimalDecoder.cs @@ -1,4 +1,4 @@ -// Copyright © 2016, 2024, Oracle and/or its affiliates. +// Copyright © 2016, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/Protocol/X/Enum.cs b/MySQL.Data/src/X/Protocol/X/Enum.cs index 1cffe1f21..371c10f38 100644 --- a/MySQL.Data/src/X/Protocol/X/Enum.cs +++ b/MySQL.Data/src/X/Protocol/X/Enum.cs @@ -1,4 +1,4 @@ -// Copyright © 2015, 2024, Oracle and/or its affiliates. +// Copyright © 2015, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/Protocol/X/ExpUnparser.cs b/MySQL.Data/src/X/Protocol/X/ExpUnparser.cs index cbcad148e..35d8ddac4 100644 --- a/MySQL.Data/src/X/Protocol/X/ExpUnparser.cs +++ b/MySQL.Data/src/X/Protocol/X/ExpUnparser.cs @@ -1,4 +1,4 @@ -// Copyright © 2015, 2024, Oracle and/or its affiliates. +// Copyright © 2015, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/Protocol/X/ExprParser.cs b/MySQL.Data/src/X/Protocol/X/ExprParser.cs index fa4aab5ec..72df42454 100644 --- a/MySQL.Data/src/X/Protocol/X/ExprParser.cs +++ b/MySQL.Data/src/X/Protocol/X/ExprParser.cs @@ -1,4 +1,4 @@ -// Copyright © 2015, 2024, Oracle and/or its affiliates. +// Copyright © 2015, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/Protocol/X/ExprUtil.cs b/MySQL.Data/src/X/Protocol/X/ExprUtil.cs index 101e1704c..1753cfb36 100644 --- a/MySQL.Data/src/X/Protocol/X/ExprUtil.cs +++ b/MySQL.Data/src/X/Protocol/X/ExprUtil.cs @@ -1,4 +1,4 @@ -// Copyright © 2015, 2024, Oracle and/or its affiliates. +// Copyright © 2015, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/Protocol/X/FloatDecoder.cs b/MySQL.Data/src/X/Protocol/X/FloatDecoder.cs index 40cee7549..8c792f475 100644 --- a/MySQL.Data/src/X/Protocol/X/FloatDecoder.cs +++ b/MySQL.Data/src/X/Protocol/X/FloatDecoder.cs @@ -1,4 +1,4 @@ -// Copyright © 2015, 2024, Oracle and/or its affiliates. +// Copyright © 2015, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/Protocol/X/IntegerDecoder.cs b/MySQL.Data/src/X/Protocol/X/IntegerDecoder.cs index d3a2f4d66..6ac733faf 100644 --- a/MySQL.Data/src/X/Protocol/X/IntegerDecoder.cs +++ b/MySQL.Data/src/X/Protocol/X/IntegerDecoder.cs @@ -1,4 +1,4 @@ -// Copyright © 2015, 2024, Oracle and/or its affiliates. +// Copyright © 2015, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/Protocol/X/Protobuf/Mysqlx.cs b/MySQL.Data/src/X/Protocol/X/Protobuf/Mysqlx.cs index 2a79fe230..4886b7196 100644 --- a/MySQL.Data/src/X/Protocol/X/Protobuf/Mysqlx.cs +++ b/MySQL.Data/src/X/Protocol/X/Protobuf/Mysqlx.cs @@ -1,4 +1,4 @@ -// Copyright © 2022, 2024, Oracle and/or its affiliates. +// Copyright © 2022, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxConnection.cs b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxConnection.cs index 5c62c39a0..8a72ed424 100644 --- a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxConnection.cs +++ b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxConnection.cs @@ -1,4 +1,4 @@ -// Copyright © 2022, 2024, Oracle and/or its affiliates. +// Copyright © 2022, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxCrud.cs b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxCrud.cs index ba35a32d0..84c2a818e 100644 --- a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxCrud.cs +++ b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxCrud.cs @@ -1,4 +1,4 @@ -// Copyright © 2022, 2024, Oracle and/or its affiliates. +// Copyright © 2022, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxCursor.cs b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxCursor.cs index 45c40d3ce..7bbd2d0fb 100644 --- a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxCursor.cs +++ b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxCursor.cs @@ -1,4 +1,4 @@ -// Copyright © 2022, 2024, Oracle and/or its affiliates. +// Copyright © 2022, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxDatatypes.cs b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxDatatypes.cs index aa77ee2e9..014465646 100644 --- a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxDatatypes.cs +++ b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxDatatypes.cs @@ -1,4 +1,4 @@ -// Copyright © 2022, 2024, Oracle and/or its affiliates. +// Copyright © 2022, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxExpect.cs b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxExpect.cs index 0bb7e9458..f94ce7ad9 100644 --- a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxExpect.cs +++ b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxExpect.cs @@ -1,4 +1,4 @@ -// Copyright © 2022, 2024, Oracle and/or its affiliates. +// Copyright © 2022, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxExpr.cs b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxExpr.cs index 1542e6819..f3a9d024b 100644 --- a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxExpr.cs +++ b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxExpr.cs @@ -1,4 +1,4 @@ -// Copyright © 2022, 2024, Oracle and/or its affiliates. +// Copyright © 2022, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxNotice.cs b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxNotice.cs index b6aaf703c..887934d05 100644 --- a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxNotice.cs +++ b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxNotice.cs @@ -1,4 +1,4 @@ -// Copyright © 2022, 2024, Oracle and/or its affiliates. +// Copyright © 2022, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxPrepare.cs b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxPrepare.cs index c912575cc..ff9dfb598 100644 --- a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxPrepare.cs +++ b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxPrepare.cs @@ -1,4 +1,4 @@ -// Copyright © 2022, 2024, Oracle and/or its affiliates. +// Copyright © 2022, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxResultset.cs b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxResultset.cs index 602775ded..be579784d 100644 --- a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxResultset.cs +++ b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxResultset.cs @@ -1,4 +1,4 @@ -// Copyright © 2022, 2024, Oracle and/or its affiliates. +// Copyright © 2022, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxSession.cs b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxSession.cs index a049421f7..d844266ff 100644 --- a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxSession.cs +++ b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxSession.cs @@ -1,4 +1,4 @@ -// Copyright © 2022, 2024, Oracle and/or its affiliates. +// Copyright © 2022, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxSql.cs b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxSql.cs index db509cb32..87ff8feb8 100644 --- a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxSql.cs +++ b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxSql.cs @@ -1,4 +1,4 @@ -// Copyright © 2022, 2023, Oracle and/or its affiliates. +// Copyright © 2022, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/Protocol/X/SetDecoder.cs b/MySQL.Data/src/X/Protocol/X/SetDecoder.cs index c0435ce74..e2262e6ca 100644 --- a/MySQL.Data/src/X/Protocol/X/SetDecoder.cs +++ b/MySQL.Data/src/X/Protocol/X/SetDecoder.cs @@ -1,4 +1,4 @@ -// Copyright © 2015, 2024, Oracle and/or its affiliates. +// Copyright © 2015, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/Protocol/X/XDateTimeDecoder.cs b/MySQL.Data/src/X/Protocol/X/XDateTimeDecoder.cs index fb8d10677..2189fbe78 100644 --- a/MySQL.Data/src/X/Protocol/X/XDateTimeDecoder.cs +++ b/MySQL.Data/src/X/Protocol/X/XDateTimeDecoder.cs @@ -1,4 +1,4 @@ -// Copyright © 2015, 2024, Oracle and/or its affiliates. +// Copyright © 2015, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/Protocol/X/XProtocol.cs b/MySQL.Data/src/X/Protocol/X/XProtocol.cs index 41a5f95ba..4cd9cad42 100644 --- a/MySQL.Data/src/X/Protocol/X/XProtocol.cs +++ b/MySQL.Data/src/X/Protocol/X/XProtocol.cs @@ -1,4 +1,4 @@ -// Copyright © 2015, 2024, Oracle and/or its affiliates. +// Copyright © 2015, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/Protocol/X/XTimeDecoder.cs b/MySQL.Data/src/X/Protocol/X/XTimeDecoder.cs index 0addea64b..390460438 100644 --- a/MySQL.Data/src/X/Protocol/X/XTimeDecoder.cs +++ b/MySQL.Data/src/X/Protocol/X/XTimeDecoder.cs @@ -1,4 +1,4 @@ -// Copyright © 2015, 2024, Oracle and/or its affiliates. +// Copyright © 2015, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/Protocol/X/XValueDecoderFactory.cs b/MySQL.Data/src/X/Protocol/X/XValueDecoderFactory.cs index c96fc1776..634ce78b1 100644 --- a/MySQL.Data/src/X/Protocol/X/XValueDecoderFactory.cs +++ b/MySQL.Data/src/X/Protocol/X/XValueDecoderFactory.cs @@ -1,4 +1,4 @@ -// Copyright © 2015, 2024, Oracle and/or its affiliates. +// Copyright © 2015, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/RoutingServices/DefaultRoutingService.cs b/MySQL.Data/src/X/RoutingServices/DefaultRoutingService.cs index c4f36483c..cf1a6ac14 100644 --- a/MySQL.Data/src/X/RoutingServices/DefaultRoutingService.cs +++ b/MySQL.Data/src/X/RoutingServices/DefaultRoutingService.cs @@ -1,4 +1,4 @@ -// Copyright © 2015, 2024, Oracle and/or its affiliates. +// Copyright © 2015, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/RoutingServices/RoutingServiceBase.cs b/MySQL.Data/src/X/RoutingServices/RoutingServiceBase.cs index 026d8b17f..6d463413e 100644 --- a/MySQL.Data/src/X/RoutingServices/RoutingServiceBase.cs +++ b/MySQL.Data/src/X/RoutingServices/RoutingServiceBase.cs @@ -1,4 +1,4 @@ -// Copyright © 2015, 2024, Oracle and/or its affiliates. +// Copyright © 2015, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/Serialization/JsonParser.cs b/MySQL.Data/src/X/Serialization/JsonParser.cs index cba5307de..769d68afd 100644 --- a/MySQL.Data/src/X/Serialization/JsonParser.cs +++ b/MySQL.Data/src/X/Serialization/JsonParser.cs @@ -1,4 +1,4 @@ -// Copyright © 2015, 2024, Oracle and/or its affiliates. +// Copyright © 2015, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/Sessions/InternalSession.cs b/MySQL.Data/src/X/Sessions/InternalSession.cs index f04de1f48..bc58494da 100644 --- a/MySQL.Data/src/X/Sessions/InternalSession.cs +++ b/MySQL.Data/src/X/Sessions/InternalSession.cs @@ -1,4 +1,4 @@ -// Copyright © 2015, 2024, Oracle and/or its affiliates. +// Copyright © 2015, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/Sessions/QueueTaskScheduler.cs b/MySQL.Data/src/X/Sessions/QueueTaskScheduler.cs index 10054750b..adee17560 100644 --- a/MySQL.Data/src/X/Sessions/QueueTaskScheduler.cs +++ b/MySQL.Data/src/X/Sessions/QueueTaskScheduler.cs @@ -1,4 +1,4 @@ -// Copyright © 2015, 2024, Oracle and/or its affiliates. +// Copyright © 2015, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/Sessions/XInternalSession.cs b/MySQL.Data/src/X/Sessions/XInternalSession.cs index 9b7322515..2bf7e8f15 100644 --- a/MySQL.Data/src/X/Sessions/XInternalSession.cs +++ b/MySQL.Data/src/X/Sessions/XInternalSession.cs @@ -1,4 +1,4 @@ -// Copyright © 2015, 2024, Oracle and/or its affiliates. +// Copyright © 2015, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/XDevAPI/BaseSession.cs b/MySQL.Data/src/X/XDevAPI/BaseSession.cs index e7804c907..8be04de67 100644 --- a/MySQL.Data/src/X/XDevAPI/BaseSession.cs +++ b/MySQL.Data/src/X/XDevAPI/BaseSession.cs @@ -1,4 +1,4 @@ -// Copyright © 2015, 2024, Oracle and/or its affiliates. +// Copyright © 2015, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/XDevAPI/CRUD/AddStatement.cs b/MySQL.Data/src/X/XDevAPI/CRUD/AddStatement.cs index f200f0556..4b0a12ebe 100644 --- a/MySQL.Data/src/X/XDevAPI/CRUD/AddStatement.cs +++ b/MySQL.Data/src/X/XDevAPI/CRUD/AddStatement.cs @@ -1,4 +1,4 @@ -// Copyright © 2015, 2024, Oracle and/or its affiliates. +// Copyright © 2015, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/XDevAPI/CRUD/CreateCollectionIndexStatement.cs b/MySQL.Data/src/X/XDevAPI/CRUD/CreateCollectionIndexStatement.cs index 40bd6ab9f..b30f144c1 100644 --- a/MySQL.Data/src/X/XDevAPI/CRUD/CreateCollectionIndexStatement.cs +++ b/MySQL.Data/src/X/XDevAPI/CRUD/CreateCollectionIndexStatement.cs @@ -1,4 +1,4 @@ -// Copyright © 2015, 2024, Oracle and/or its affiliates. +// Copyright © 2015, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/XDevAPI/CRUD/CreateIndexParams.cs b/MySQL.Data/src/X/XDevAPI/CRUD/CreateIndexParams.cs index 7039bcd67..af518edb6 100644 --- a/MySQL.Data/src/X/XDevAPI/CRUD/CreateIndexParams.cs +++ b/MySQL.Data/src/X/XDevAPI/CRUD/CreateIndexParams.cs @@ -1,4 +1,4 @@ -// Copyright © 2015, 2024, Oracle and/or its affiliates. +// Copyright © 2015, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/XDevAPI/CRUD/CrudStatement.cs b/MySQL.Data/src/X/XDevAPI/CRUD/CrudStatement.cs index f27d75b37..df71f408e 100644 --- a/MySQL.Data/src/X/XDevAPI/CRUD/CrudStatement.cs +++ b/MySQL.Data/src/X/XDevAPI/CRUD/CrudStatement.cs @@ -1,4 +1,4 @@ -// Copyright © 2015, 2024, Oracle and/or its affiliates. +// Copyright © 2015, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/XDevAPI/CRUD/DocResult.cs b/MySQL.Data/src/X/XDevAPI/CRUD/DocResult.cs index 5ee41f76c..1808659a6 100644 --- a/MySQL.Data/src/X/XDevAPI/CRUD/DocResult.cs +++ b/MySQL.Data/src/X/XDevAPI/CRUD/DocResult.cs @@ -1,4 +1,4 @@ -// Copyright © 2015, 2024, Oracle and/or its affiliates. +// Copyright © 2015, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/XDevAPI/CRUD/FindParams.cs b/MySQL.Data/src/X/XDevAPI/CRUD/FindParams.cs index b658b1380..3616ca7fb 100644 --- a/MySQL.Data/src/X/XDevAPI/CRUD/FindParams.cs +++ b/MySQL.Data/src/X/XDevAPI/CRUD/FindParams.cs @@ -1,4 +1,4 @@ -// Copyright © 2015, 2024, Oracle and/or its affiliates. +// Copyright © 2015, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/XDevAPI/CRUD/FindStatement.cs b/MySQL.Data/src/X/XDevAPI/CRUD/FindStatement.cs index 813edad1f..7df9b0714 100644 --- a/MySQL.Data/src/X/XDevAPI/CRUD/FindStatement.cs +++ b/MySQL.Data/src/X/XDevAPI/CRUD/FindStatement.cs @@ -1,4 +1,4 @@ -// Copyright © 2015, 2024, Oracle and/or its affiliates. +// Copyright © 2015, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/XDevAPI/CRUD/ModifyStatement.cs b/MySQL.Data/src/X/XDevAPI/CRUD/ModifyStatement.cs index dc21975cf..4e6265476 100644 --- a/MySQL.Data/src/X/XDevAPI/CRUD/ModifyStatement.cs +++ b/MySQL.Data/src/X/XDevAPI/CRUD/ModifyStatement.cs @@ -1,4 +1,4 @@ -// Copyright © 2015, 2024, Oracle and/or its affiliates. +// Copyright © 2015, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/XDevAPI/CRUD/RemoveStatement.cs b/MySQL.Data/src/X/XDevAPI/CRUD/RemoveStatement.cs index de06ca276..4d9867384 100644 --- a/MySQL.Data/src/X/XDevAPI/CRUD/RemoveStatement.cs +++ b/MySQL.Data/src/X/XDevAPI/CRUD/RemoveStatement.cs @@ -1,4 +1,4 @@ -// Copyright © 2015, 2024, Oracle and/or its affiliates. +// Copyright © 2015, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/XDevAPI/CRUD/UpdateSpec.cs b/MySQL.Data/src/X/XDevAPI/CRUD/UpdateSpec.cs index d6c76c627..86e127bd2 100644 --- a/MySQL.Data/src/X/XDevAPI/CRUD/UpdateSpec.cs +++ b/MySQL.Data/src/X/XDevAPI/CRUD/UpdateSpec.cs @@ -1,4 +1,4 @@ -// Copyright © 2015, 2024, Oracle and/or its affiliates. +// Copyright © 2015, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/XDevAPI/Client.cs b/MySQL.Data/src/X/XDevAPI/Client.cs index 69d5e2749..fc4518dfb 100644 --- a/MySQL.Data/src/X/XDevAPI/Client.cs +++ b/MySQL.Data/src/X/XDevAPI/Client.cs @@ -1,4 +1,4 @@ -// Copyright © 2018, 2024, Oracle and/or its affiliates. +// Copyright © 2018, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/XDevAPI/Collection.cs b/MySQL.Data/src/X/XDevAPI/Collection.cs index fd9da2702..34afde110 100644 --- a/MySQL.Data/src/X/XDevAPI/Collection.cs +++ b/MySQL.Data/src/X/XDevAPI/Collection.cs @@ -1,4 +1,4 @@ -// Copyright © 2015, 2024, Oracle and/or its affiliates. +// Copyright © 2015, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/XDevAPI/Common/BaseResult.cs b/MySQL.Data/src/X/XDevAPI/Common/BaseResult.cs index af7a8faf3..7d13a8193 100644 --- a/MySQL.Data/src/X/XDevAPI/Common/BaseResult.cs +++ b/MySQL.Data/src/X/XDevAPI/Common/BaseResult.cs @@ -1,4 +1,4 @@ -// Copyright © 2015, 2024, Oracle and/or its affiliates. +// Copyright © 2015, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/XDevAPI/Common/BaseStatement.cs b/MySQL.Data/src/X/XDevAPI/Common/BaseStatement.cs index 8ead4959a..a56018d88 100644 --- a/MySQL.Data/src/X/XDevAPI/Common/BaseStatement.cs +++ b/MySQL.Data/src/X/XDevAPI/Common/BaseStatement.cs @@ -1,4 +1,4 @@ -// Copyright © 2015, 2024, Oracle and/or its affiliates. +// Copyright © 2015, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/XDevAPI/Common/BufferingResult.cs b/MySQL.Data/src/X/XDevAPI/Common/BufferingResult.cs index ae7c87bca..58a206a8d 100644 --- a/MySQL.Data/src/X/XDevAPI/Common/BufferingResult.cs +++ b/MySQL.Data/src/X/XDevAPI/Common/BufferingResult.cs @@ -1,4 +1,4 @@ -// Copyright © 2015, 2024, Oracle and/or its affiliates. +// Copyright © 2015, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/XDevAPI/Common/CollectionOptions.cs b/MySQL.Data/src/X/XDevAPI/Common/CollectionOptions.cs index a08a391ea..845ae395d 100644 --- a/MySQL.Data/src/X/XDevAPI/Common/CollectionOptions.cs +++ b/MySQL.Data/src/X/XDevAPI/Common/CollectionOptions.cs @@ -1,4 +1,4 @@ -// Copyright © 2019, 2024, Oracle and/or its affiliates. +// Copyright © 2019, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/XDevAPI/Common/ColumnType.cs b/MySQL.Data/src/X/XDevAPI/Common/ColumnType.cs index c850f65d4..ddd964286 100644 --- a/MySQL.Data/src/X/XDevAPI/Common/ColumnType.cs +++ b/MySQL.Data/src/X/XDevAPI/Common/ColumnType.cs @@ -1,4 +1,4 @@ -// Copyright © 2016, 2024, Oracle and/or its affiliates. +// Copyright © 2016, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/XDevAPI/Common/ErrorInfo.cs b/MySQL.Data/src/X/XDevAPI/Common/ErrorInfo.cs index af22db16c..ca31f42fb 100644 --- a/MySQL.Data/src/X/XDevAPI/Common/ErrorInfo.cs +++ b/MySQL.Data/src/X/XDevAPI/Common/ErrorInfo.cs @@ -1,4 +1,4 @@ -// Copyright © 2015, 2024, Oracle and/or its affiliates. +// Copyright © 2015, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/XDevAPI/Common/FilterParams.cs b/MySQL.Data/src/X/XDevAPI/Common/FilterParams.cs index 9d5ad512f..35348362e 100644 --- a/MySQL.Data/src/X/XDevAPI/Common/FilterParams.cs +++ b/MySQL.Data/src/X/XDevAPI/Common/FilterParams.cs @@ -1,4 +1,4 @@ -// Copyright © 2015, 2024, Oracle and/or its affiliates. +// Copyright © 2015, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/XDevAPI/Common/FilterableStatement.cs b/MySQL.Data/src/X/XDevAPI/Common/FilterableStatement.cs index e1ab2cfbf..fa80d991a 100644 --- a/MySQL.Data/src/X/XDevAPI/Common/FilterableStatement.cs +++ b/MySQL.Data/src/X/XDevAPI/Common/FilterableStatement.cs @@ -1,4 +1,4 @@ -// Copyright © 2015, 2024, Oracle and/or its affiliates. +// Copyright © 2015, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/XDevAPI/Common/QueryStatement.cs b/MySQL.Data/src/X/XDevAPI/Common/QueryStatement.cs index 1fb41938e..9286523f7 100644 --- a/MySQL.Data/src/X/XDevAPI/Common/QueryStatement.cs +++ b/MySQL.Data/src/X/XDevAPI/Common/QueryStatement.cs @@ -1,4 +1,4 @@ -// Copyright © 2017, 2024, Oracle and/or its affiliates. +// Copyright © 2017, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/XDevAPI/Common/Result.cs b/MySQL.Data/src/X/XDevAPI/Common/Result.cs index 7312573b7..50ce51f96 100644 --- a/MySQL.Data/src/X/XDevAPI/Common/Result.cs +++ b/MySQL.Data/src/X/XDevAPI/Common/Result.cs @@ -1,4 +1,4 @@ -// Copyright © 2015, 2024, Oracle and/or its affiliates. +// Copyright © 2015, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/XDevAPI/Common/TargetedBaseStatement.cs b/MySQL.Data/src/X/XDevAPI/Common/TargetedBaseStatement.cs index bf9cdac85..ec83f3dd9 100644 --- a/MySQL.Data/src/X/XDevAPI/Common/TargetedBaseStatement.cs +++ b/MySQL.Data/src/X/XDevAPI/Common/TargetedBaseStatement.cs @@ -1,4 +1,4 @@ -// Copyright © 2015, 2024, Oracle and/or its affiliates. +// Copyright © 2015, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/XDevAPI/Common/WarningInfo.cs b/MySQL.Data/src/X/XDevAPI/Common/WarningInfo.cs index 6d2306895..2e6877358 100644 --- a/MySQL.Data/src/X/XDevAPI/Common/WarningInfo.cs +++ b/MySQL.Data/src/X/XDevAPI/Common/WarningInfo.cs @@ -1,4 +1,4 @@ -// Copyright © 2015, 2024, Oracle and/or its affiliates. +// Copyright © 2015, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/XDevAPI/DatabaseObject.cs b/MySQL.Data/src/X/XDevAPI/DatabaseObject.cs index b2b279f0a..8d550665e 100644 --- a/MySQL.Data/src/X/XDevAPI/DatabaseObject.cs +++ b/MySQL.Data/src/X/XDevAPI/DatabaseObject.cs @@ -1,4 +1,4 @@ -// Copyright © 2015, 2024, Oracle and/or its affiliates. +// Copyright © 2015, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/XDevAPI/DbDoc.cs b/MySQL.Data/src/X/XDevAPI/DbDoc.cs index ce84cc844..fe5fbc16b 100644 --- a/MySQL.Data/src/X/XDevAPI/DbDoc.cs +++ b/MySQL.Data/src/X/XDevAPI/DbDoc.cs @@ -1,4 +1,4 @@ -// Copyright © 2015, 2024, Oracle and/or its affiliates. +// Copyright © 2015, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/XDevAPI/GenericCollection.cs b/MySQL.Data/src/X/XDevAPI/GenericCollection.cs index e46c5a82f..16443acfc 100644 --- a/MySQL.Data/src/X/XDevAPI/GenericCollection.cs +++ b/MySQL.Data/src/X/XDevAPI/GenericCollection.cs @@ -1,4 +1,4 @@ -// Copyright © 2015, 2024, Oracle and/or its affiliates. +// Copyright © 2015, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/XDevAPI/Iterator.cs b/MySQL.Data/src/X/XDevAPI/Iterator.cs index 208425359..e4b2d1fd8 100644 --- a/MySQL.Data/src/X/XDevAPI/Iterator.cs +++ b/MySQL.Data/src/X/XDevAPI/Iterator.cs @@ -1,4 +1,4 @@ -// Copyright © 2015, 2024, Oracle and/or its affiliates. +// Copyright © 2015, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/XDevAPI/MySqlExpression.cs b/MySQL.Data/src/X/XDevAPI/MySqlExpression.cs index e3f433348..0b7167c0f 100644 --- a/MySQL.Data/src/X/XDevAPI/MySqlExpression.cs +++ b/MySQL.Data/src/X/XDevAPI/MySqlExpression.cs @@ -1,4 +1,4 @@ -// Copyright © 2017, 2024, Oracle and/or its affiliates. +// Copyright © 2017, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/XDevAPI/MySqlX.cs b/MySQL.Data/src/X/XDevAPI/MySqlX.cs index 9dc53bc73..a395cf4a0 100644 --- a/MySQL.Data/src/X/XDevAPI/MySqlX.cs +++ b/MySQL.Data/src/X/XDevAPI/MySqlX.cs @@ -1,4 +1,4 @@ -// Copyright © 2015, 2024, Oracle and/or its affiliates. +// Copyright © 2015, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/XDevAPI/MySqlXConnectionStringBuilder.cs b/MySQL.Data/src/X/XDevAPI/MySqlXConnectionStringBuilder.cs index edd0959b3..7e4177f2f 100644 --- a/MySQL.Data/src/X/XDevAPI/MySqlXConnectionStringBuilder.cs +++ b/MySQL.Data/src/X/XDevAPI/MySqlXConnectionStringBuilder.cs @@ -1,4 +1,4 @@ -// Copyright © 2019, 2024, Oracle and/or its affiliates. +// Copyright © 2019, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/XDevAPI/Relational/Column.cs b/MySQL.Data/src/X/XDevAPI/Relational/Column.cs index 08ac7a2d6..d9a550478 100644 --- a/MySQL.Data/src/X/XDevAPI/Relational/Column.cs +++ b/MySQL.Data/src/X/XDevAPI/Relational/Column.cs @@ -1,4 +1,4 @@ -// Copyright © 2015, 2024, Oracle and/or its affiliates. +// Copyright © 2015, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/XDevAPI/Relational/InternalRowResult.cs b/MySQL.Data/src/X/XDevAPI/Relational/InternalRowResult.cs index ae6c99928..fe66dcf40 100644 --- a/MySQL.Data/src/X/XDevAPI/Relational/InternalRowResult.cs +++ b/MySQL.Data/src/X/XDevAPI/Relational/InternalRowResult.cs @@ -1,4 +1,4 @@ -// Copyright © 2015, 2024, Oracle and/or its affiliates. +// Copyright © 2015, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/XDevAPI/Relational/Row.cs b/MySQL.Data/src/X/XDevAPI/Relational/Row.cs index 719303b1f..f54157d5b 100644 --- a/MySQL.Data/src/X/XDevAPI/Relational/Row.cs +++ b/MySQL.Data/src/X/XDevAPI/Relational/Row.cs @@ -1,4 +1,4 @@ -// Copyright © 2015, 2024, Oracle and/or its affiliates. +// Copyright © 2015, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/XDevAPI/Relational/RowResult.cs b/MySQL.Data/src/X/XDevAPI/Relational/RowResult.cs index d8e7cede2..968307fa1 100644 --- a/MySQL.Data/src/X/XDevAPI/Relational/RowResult.cs +++ b/MySQL.Data/src/X/XDevAPI/Relational/RowResult.cs @@ -1,4 +1,4 @@ -// Copyright © 2015, 2024, Oracle and/or its affiliates. +// Copyright © 2015, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/XDevAPI/Relational/SqlResult.cs b/MySQL.Data/src/X/XDevAPI/Relational/SqlResult.cs index c02d7ca6d..2e29f1255 100644 --- a/MySQL.Data/src/X/XDevAPI/Relational/SqlResult.cs +++ b/MySQL.Data/src/X/XDevAPI/Relational/SqlResult.cs @@ -1,4 +1,4 @@ -// Copyright © 2015, 2024, Oracle and/or its affiliates. +// Copyright © 2015, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/XDevAPI/Relational/SqlStatement.cs b/MySQL.Data/src/X/XDevAPI/Relational/SqlStatement.cs index 18b83c872..39b617ef9 100644 --- a/MySQL.Data/src/X/XDevAPI/Relational/SqlStatement.cs +++ b/MySQL.Data/src/X/XDevAPI/Relational/SqlStatement.cs @@ -1,4 +1,4 @@ -// Copyright © 2015, 2024, Oracle and/or its affiliates. +// Copyright © 2015, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/XDevAPI/Relational/Table.cs b/MySQL.Data/src/X/XDevAPI/Relational/Table.cs index 48f22d541..940ce10f0 100644 --- a/MySQL.Data/src/X/XDevAPI/Relational/Table.cs +++ b/MySQL.Data/src/X/XDevAPI/Relational/Table.cs @@ -1,4 +1,4 @@ -// Copyright © 2015, 2024, Oracle and/or its affiliates. +// Copyright © 2015, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/XDevAPI/Relational/TableDeleteStatement.cs b/MySQL.Data/src/X/XDevAPI/Relational/TableDeleteStatement.cs index 74dbbcb96..bbfaef2cb 100644 --- a/MySQL.Data/src/X/XDevAPI/Relational/TableDeleteStatement.cs +++ b/MySQL.Data/src/X/XDevAPI/Relational/TableDeleteStatement.cs @@ -1,4 +1,4 @@ -// Copyright © 2015, 2024, Oracle and/or its affiliates. +// Copyright © 2015, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/XDevAPI/Relational/TableInsertStatement.cs b/MySQL.Data/src/X/XDevAPI/Relational/TableInsertStatement.cs index fcd5706c3..bfd63743d 100644 --- a/MySQL.Data/src/X/XDevAPI/Relational/TableInsertStatement.cs +++ b/MySQL.Data/src/X/XDevAPI/Relational/TableInsertStatement.cs @@ -1,4 +1,4 @@ -// Copyright © 2015, 2024, Oracle and/or its affiliates. +// Copyright © 2015, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/XDevAPI/Relational/TableSelectStatement.cs b/MySQL.Data/src/X/XDevAPI/Relational/TableSelectStatement.cs index b32f39fb1..eabf3e900 100644 --- a/MySQL.Data/src/X/XDevAPI/Relational/TableSelectStatement.cs +++ b/MySQL.Data/src/X/XDevAPI/Relational/TableSelectStatement.cs @@ -1,4 +1,4 @@ -// Copyright © 2015, 2024, Oracle and/or its affiliates. +// Copyright © 2015, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/XDevAPI/Relational/TableUpdateStatement.cs b/MySQL.Data/src/X/XDevAPI/Relational/TableUpdateStatement.cs index f87e94347..f4aa6ecd1 100644 --- a/MySQL.Data/src/X/XDevAPI/Relational/TableUpdateStatement.cs +++ b/MySQL.Data/src/X/XDevAPI/Relational/TableUpdateStatement.cs @@ -1,4 +1,4 @@ -// Copyright © 2015, 2024, Oracle and/or its affiliates. +// Copyright © 2015, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/XDevAPI/Schema.cs b/MySQL.Data/src/X/XDevAPI/Schema.cs index f333ce894..a09f782a3 100644 --- a/MySQL.Data/src/X/XDevAPI/Schema.cs +++ b/MySQL.Data/src/X/XDevAPI/Schema.cs @@ -1,4 +1,4 @@ -// Copyright © 2015, 2024, Oracle and/or its affiliates. +// Copyright © 2015, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/X/XDevAPI/Session.cs b/MySQL.Data/src/X/XDevAPI/Session.cs index 8a78297d3..784f2c9ad 100644 --- a/MySQL.Data/src/X/XDevAPI/Session.cs +++ b/MySQL.Data/src/X/XDevAPI/Session.cs @@ -1,4 +1,4 @@ -// Copyright © 2015, 2024, Oracle and/or its affiliates. +// Copyright © 2015, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/common/Cache.cs b/MySQL.Data/src/common/Cache.cs index ae74c0771..3535ece0c 100644 --- a/MySQL.Data/src/common/Cache.cs +++ b/MySQL.Data/src/common/Cache.cs @@ -1,4 +1,4 @@ -// Copyright © 2004, 2024, Oracle and/or its affiliates. +// Copyright © 2004, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/common/ContextString.cs b/MySQL.Data/src/common/ContextString.cs index e91d49a6a..1108dc87b 100644 --- a/MySQL.Data/src/common/ContextString.cs +++ b/MySQL.Data/src/common/ContextString.cs @@ -1,4 +1,4 @@ -// Copyright © 2004, 2024, Oracle and/or its affiliates. +// Copyright © 2004, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/common/Dns/DnsEnums.cs b/MySQL.Data/src/common/Dns/DnsEnums.cs index 733c7d574..0291bda64 100644 --- a/MySQL.Data/src/common/Dns/DnsEnums.cs +++ b/MySQL.Data/src/common/Dns/DnsEnums.cs @@ -1,4 +1,4 @@ -// Copyright © 2022, 2024, Oracle and/or its affiliates. +// Copyright © 2022, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/common/Dns/DnsQuestion.cs b/MySQL.Data/src/common/Dns/DnsQuestion.cs index bde33a80d..89861c146 100644 --- a/MySQL.Data/src/common/Dns/DnsQuestion.cs +++ b/MySQL.Data/src/common/Dns/DnsQuestion.cs @@ -1,4 +1,4 @@ -// Copyright © 2022, 2024, Oracle and/or its affiliates. +// Copyright © 2022, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/common/Dns/DnsRecordHeader.cs b/MySQL.Data/src/common/Dns/DnsRecordHeader.cs index 424d665d6..8db53aa42 100644 --- a/MySQL.Data/src/common/Dns/DnsRecordHeader.cs +++ b/MySQL.Data/src/common/Dns/DnsRecordHeader.cs @@ -1,4 +1,4 @@ -// Copyright © 2022, 2024, Oracle and/or its affiliates. +// Copyright © 2022, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/common/Dns/DnsRecordReader.cs b/MySQL.Data/src/common/Dns/DnsRecordReader.cs index 430b06427..2e35895bd 100644 --- a/MySQL.Data/src/common/Dns/DnsRecordReader.cs +++ b/MySQL.Data/src/common/Dns/DnsRecordReader.cs @@ -1,4 +1,4 @@ -// Copyright © 2022, 2024, Oracle and/or its affiliates. +// Copyright © 2022, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/common/Dns/DnsRecordUnknown.cs b/MySQL.Data/src/common/Dns/DnsRecordUnknown.cs index fc29994a0..8c2bfaf3f 100644 --- a/MySQL.Data/src/common/Dns/DnsRecordUnknown.cs +++ b/MySQL.Data/src/common/Dns/DnsRecordUnknown.cs @@ -1,4 +1,4 @@ -// Copyright © 2022, 2024, Oracle and/or its affiliates. +// Copyright © 2022, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/common/Dns/DnsRequest.cs b/MySQL.Data/src/common/Dns/DnsRequest.cs index 5b201b89d..2a9372a40 100644 --- a/MySQL.Data/src/common/Dns/DnsRequest.cs +++ b/MySQL.Data/src/common/Dns/DnsRequest.cs @@ -1,4 +1,4 @@ -// Copyright © 2022, 2024, Oracle and/or its affiliates. +// Copyright © 2022, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/common/Dns/DnsResolver.cs b/MySQL.Data/src/common/Dns/DnsResolver.cs index 7f0cfee23..a82d579a2 100644 --- a/MySQL.Data/src/common/Dns/DnsResolver.cs +++ b/MySQL.Data/src/common/Dns/DnsResolver.cs @@ -1,4 +1,4 @@ -// Copyright © 2022, 2024, Oracle and/or its affiliates. +// Copyright © 2022, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/common/Dns/DnsResourceRecord.cs b/MySQL.Data/src/common/Dns/DnsResourceRecord.cs index 4b78af5a3..a0b8dcafd 100644 --- a/MySQL.Data/src/common/Dns/DnsResourceRecord.cs +++ b/MySQL.Data/src/common/Dns/DnsResourceRecord.cs @@ -1,4 +1,4 @@ -// Copyright © 2022, 2024, Oracle and/or its affiliates. +// Copyright © 2022, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/common/Dns/DnsResponse.cs b/MySQL.Data/src/common/Dns/DnsResponse.cs index d1b9e0433..1667744e1 100644 --- a/MySQL.Data/src/common/Dns/DnsResponse.cs +++ b/MySQL.Data/src/common/Dns/DnsResponse.cs @@ -1,4 +1,4 @@ -// Copyright © 2022, 2024, Oracle and/or its affiliates. +// Copyright © 2022, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/common/Dns/DnsSrvRecord.cs b/MySQL.Data/src/common/Dns/DnsSrvRecord.cs index c153b4b16..3d8b1d62a 100644 --- a/MySQL.Data/src/common/Dns/DnsSrvRecord.cs +++ b/MySQL.Data/src/common/Dns/DnsSrvRecord.cs @@ -1,4 +1,4 @@ -// Copyright © 2019, 2024, Oracle and/or its affiliates. +// Copyright © 2019, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/common/DnsSrv.cs b/MySQL.Data/src/common/DnsSrv.cs index b0539894b..429199688 100644 --- a/MySQL.Data/src/common/DnsSrv.cs +++ b/MySQL.Data/src/common/DnsSrv.cs @@ -1,4 +1,4 @@ -// Copyright © 2019, 2024, Oracle and/or its affiliates. +// Copyright © 2019, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/common/LowResolutionStopwatch.cs b/MySQL.Data/src/common/LowResolutionStopwatch.cs index 208ee4669..11cddb077 100644 --- a/MySQL.Data/src/common/LowResolutionStopwatch.cs +++ b/MySQL.Data/src/common/LowResolutionStopwatch.cs @@ -1,4 +1,4 @@ -// Copyright © 2009, 2024, Oracle and/or its affiliates. +// Copyright © 2009, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/common/MyNetworkStream.cs b/MySQL.Data/src/common/MyNetworkStream.cs index 6223a5d11..2af7d1c01 100644 --- a/MySQL.Data/src/common/MyNetworkStream.cs +++ b/MySQL.Data/src/common/MyNetworkStream.cs @@ -1,4 +1,4 @@ -// Copyright © 2009, 2024, Oracle and/or its affiliates. +// Copyright © 2009, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/common/MySqlConnectionStringOption.cs b/MySQL.Data/src/common/MySqlConnectionStringOption.cs index b05ea84fc..64ec4d6d5 100644 --- a/MySQL.Data/src/common/MySqlConnectionStringOption.cs +++ b/MySQL.Data/src/common/MySqlConnectionStringOption.cs @@ -1,4 +1,4 @@ -// Copyright © 2019, 2024, Oracle and/or its affiliates. +// Copyright © 2019, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/common/MySqlConnectionStringOptionCollection.cs b/MySQL.Data/src/common/MySqlConnectionStringOptionCollection.cs index 81ba80bf3..00609df8e 100644 --- a/MySQL.Data/src/common/MySqlConnectionStringOptionCollection.cs +++ b/MySQL.Data/src/common/MySqlConnectionStringOptionCollection.cs @@ -1,4 +1,4 @@ -// Copyright © 2019, 2024, Oracle and/or its affiliates. +// Copyright © 2019, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/common/MySqlTokenizer.cs b/MySQL.Data/src/common/MySqlTokenizer.cs index 5191d54b9..6bf9c226c 100644 --- a/MySQL.Data/src/common/MySqlTokenizer.cs +++ b/MySQL.Data/src/common/MySqlTokenizer.cs @@ -1,4 +1,4 @@ -// Copyright © 2004, 2024, Oracle and/or its affiliates. +// Copyright © 2004, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/common/NativeMethods.cs b/MySQL.Data/src/common/NativeMethods.cs index b6fa9fae8..6501e7a41 100644 --- a/MySQL.Data/src/common/NativeMethods.cs +++ b/MySQL.Data/src/common/NativeMethods.cs @@ -1,4 +1,4 @@ -// Copyright © 2009, 2024, Oracle and/or its affiliates. +// Copyright © 2009, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/common/Platform.cs b/MySQL.Data/src/common/Platform.cs index 49203adbb..c4bed02dc 100644 --- a/MySQL.Data/src/common/Platform.cs +++ b/MySQL.Data/src/common/Platform.cs @@ -1,4 +1,4 @@ -// Copyright © 2004, 2024, Oracle and/or its affiliates. +// Copyright © 2004, 2025, Oracle and/or its affiliates. // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/common/QueryNormalizer.cs b/MySQL.Data/src/common/QueryNormalizer.cs index 881a14874..d99b23224 100644 --- a/MySQL.Data/src/common/QueryNormalizer.cs +++ b/MySQL.Data/src/common/QueryNormalizer.cs @@ -1,4 +1,4 @@ -// Copyright © 2009, 2024, Oracle and/or its affiliates. +// Copyright © 2009, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/common/Ssl.cs b/MySQL.Data/src/common/Ssl.cs index 00a782459..394a7ac7e 100644 --- a/MySQL.Data/src/common/Ssl.cs +++ b/MySQL.Data/src/common/Ssl.cs @@ -1,4 +1,4 @@ -// Copyright © 2004, 2024, Oracle and/or its affiliates. +// Copyright © 2004, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/common/SslPemCertificateValidator.cs b/MySQL.Data/src/common/SslPemCertificateValidator.cs index d29b26689..8186ea6b6 100644 --- a/MySQL.Data/src/common/SslPemCertificateValidator.cs +++ b/MySQL.Data/src/common/SslPemCertificateValidator.cs @@ -1,4 +1,4 @@ -// Copyright © 2019, 2024, Oracle and/or its affiliates. +// Copyright © 2019, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/common/StreamCreator.cs b/MySQL.Data/src/common/StreamCreator.cs index 1305ec867..84f015e87 100644 --- a/MySQL.Data/src/common/StreamCreator.cs +++ b/MySQL.Data/src/common/StreamCreator.cs @@ -1,4 +1,4 @@ -// Copyright © 2004, 2024, Oracle and/or its affiliates. +// Copyright © 2004, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/common/StringUtility.cs b/MySQL.Data/src/common/StringUtility.cs index 8e1359378..041397427 100644 --- a/MySQL.Data/src/common/StringUtility.cs +++ b/MySQL.Data/src/common/StringUtility.cs @@ -1,4 +1,4 @@ -// Copyright © 2014, 2024, Oracle and/or its affiliates. +// Copyright © 2014, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/common/UnixEndPoint.cs b/MySQL.Data/src/common/UnixEndPoint.cs index b05c2baa8..71ea2cba7 100644 --- a/MySQL.Data/src/common/UnixEndPoint.cs +++ b/MySQL.Data/src/common/UnixEndPoint.cs @@ -1,4 +1,4 @@ -// Copyright © 2017, 2024, Oracle and/or its affiliates. +// Copyright © 2017, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/common/Version.cs b/MySQL.Data/src/common/Version.cs index b524e5d2a..e80dd3398 100644 --- a/MySQL.Data/src/common/Version.cs +++ b/MySQL.Data/src/common/Version.cs @@ -1,4 +1,4 @@ -// Copyright © 2004, 2024, Oracle and/or its affiliates. +// Copyright © 2004, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/common/netstandard2_0/NamedPipeStream.cs b/MySQL.Data/src/common/netstandard2_0/NamedPipeStream.cs index 57302c11a..a3698477f 100644 --- a/MySQL.Data/src/common/netstandard2_0/NamedPipeStream.cs +++ b/MySQL.Data/src/common/netstandard2_0/NamedPipeStream.cs @@ -1,4 +1,4 @@ -// Copyright © 2009, 2024, Oracle and/or its affiliates. +// Copyright © 2009, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/src/common/netstandard2_0/SharedMemoryStream.cs b/MySQL.Data/src/common/netstandard2_0/SharedMemoryStream.cs index 4c4ad2e78..02431ca56 100644 --- a/MySQL.Data/src/common/netstandard2_0/SharedMemoryStream.cs +++ b/MySQL.Data/src/common/netstandard2_0/SharedMemoryStream.cs @@ -1,4 +1,4 @@ -// Copyright © 2014, 2024, Oracle and/or its affiliates. +// Copyright © 2014, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySql.Data.Tests/AttributeTests.cs b/MySQL.Data/tests/MySql.Data.Tests/AttributeTests.cs index 3ec9b1aff..c6f69757d 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/AttributeTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/AttributeTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySql.Data.Tests/AuthTests.cs b/MySQL.Data/tests/MySql.Data.Tests/AuthTests.cs index ab6f94bca..cdf8d8971 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/AuthTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/AuthTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2016, 2024, Oracle and/or its affiliates. +// Copyright © 2016, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySql.Data.Tests/BlobTests.cs b/MySQL.Data/tests/MySql.Data.Tests/BlobTests.cs index eaba3d20f..31458255e 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/BlobTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/BlobTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySql.Data.Tests/BlobTestsCompressed.cs b/MySQL.Data/tests/MySql.Data.Tests/BlobTestsCompressed.cs index fcb85a1f4..b27875d3e 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/BlobTestsCompressed.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/BlobTestsCompressed.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySql.Data.Tests/CharSetTests.cs b/MySQL.Data/tests/MySql.Data.Tests/CharSetTests.cs index d3021e26d..90c0db97c 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/CharSetTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/CharSetTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySql.Data.Tests/CharSetUTF8Tests.cs b/MySQL.Data/tests/MySql.Data.Tests/CharSetUTF8Tests.cs index 7202be6cf..2e34ef818 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/CharSetUTF8Tests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/CharSetUTF8Tests.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySql.Data.Tests/ClientSideFailoverTests.cs b/MySQL.Data/tests/MySql.Data.Tests/ClientSideFailoverTests.cs index e62d39e50..b5b95b247 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/ClientSideFailoverTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/ClientSideFailoverTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2019, 2024, Oracle and/or its affiliates. +// Copyright © 2019, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySql.Data.Tests/CmdTests.cs b/MySQL.Data/tests/MySql.Data.Tests/CmdTests.cs index 171d6630e..e932704e3 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/CmdTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/CmdTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySql.Data.Tests/CmdTestsCompressed.cs b/MySQL.Data/tests/MySql.Data.Tests/CmdTestsCompressed.cs index d18aecbcb..7ce26eb36 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/CmdTestsCompressed.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/CmdTestsCompressed.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySql.Data.Tests/ConnectionStringBuilderTests.cs b/MySQL.Data/tests/MySql.Data.Tests/ConnectionStringBuilderTests.cs index 5973f4a9f..e399e076e 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/ConnectionStringBuilderTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/ConnectionStringBuilderTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySql.Data.Tests/ConnectionTests.cs b/MySQL.Data/tests/MySql.Data.Tests/ConnectionTests.cs index bb0664c28..3a44eea9a 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/ConnectionTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/ConnectionTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySql.Data.Tests/DataTypeTests.cs b/MySQL.Data/tests/MySql.Data.Tests/DataTypeTests.cs index 784409462..e3048f459 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/DataTypeTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/DataTypeTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySql.Data.Tests/DateTimeTests.cs b/MySQL.Data/tests/MySql.Data.Tests/DateTimeTests.cs index 2b48c1816..a2ded784e 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/DateTimeTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/DateTimeTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySql.Data.Tests/DnsSrvTests.cs b/MySQL.Data/tests/MySql.Data.Tests/DnsSrvTests.cs index 0aa3f84b6..e17739ae7 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/DnsSrvTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/DnsSrvTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2019, 2024, Oracle and/or its affiliates. +// Copyright © 2019, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySql.Data.Tests/EventTests.cs b/MySQL.Data/tests/MySql.Data.Tests/EventTests.cs index 78d6e0df9..81e95eb60 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/EventTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/EventTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySql.Data.Tests/ExceptionTests.cs b/MySQL.Data/tests/MySql.Data.Tests/ExceptionTests.cs index af753b7da..cd3059b6d 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/ExceptionTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/ExceptionTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/BlobTestsPipe.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/BlobTestsPipe.cs index 36a9281a9..56fd2cee3 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/BlobTestsPipe.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/BlobTestsPipe.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/BlobTestsPipeCompressed.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/BlobTestsPipeCompressed.cs index bd69d5086..0f9d7fd81 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/BlobTestsPipeCompressed.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/BlobTestsPipeCompressed.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/BlobTestsSharedMem.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/BlobTestsSharedMem.cs index c70b45b11..f2f3af134 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/BlobTestsSharedMem.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/BlobTestsSharedMem.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/BlobTestsSharedMemCompressed.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/BlobTestsSharedMemCompressed.cs index bd6193578..af916620c 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/BlobTestsSharedMemCompressed.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/BlobTestsSharedMemCompressed.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/CmdTestsPipe.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/CmdTestsPipe.cs index d5e732c1b..d805b0efd 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/CmdTestsPipe.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/CmdTestsPipe.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/CmdTestsPipeCompressed.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/CmdTestsPipeCompressed.cs index 3e00525f3..98e341eac 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/CmdTestsPipeCompressed.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/CmdTestsPipeCompressed.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/CmdTestsSharedMem.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/CmdTestsSharedMem.cs index 17945408a..99144722e 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/CmdTestsSharedMem.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/CmdTestsSharedMem.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/CmdTestsSharedmemCompressed.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/CmdTestsSharedmemCompressed.cs index f92501fdd..94954727c 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/CmdTestsSharedmemCompressed.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/CmdTestsSharedmemCompressed.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/CultureTests.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/CultureTests.cs index b2b136626..4fde4772e 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/CultureTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/CultureTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/DataTypeTests.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/DataTypeTests.cs index 223ab385a..cf9c4a195 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/DataTypeTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/DataTypeTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/DateTimeTests.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/DateTimeTests.cs index cba2a0718..de1d3a3a2 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/DateTimeTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/DateTimeTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/GetSchemaTests.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/GetSchemaTests.cs index c36c31488..0ea3316d0 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/GetSchemaTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/GetSchemaTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/InstallerTests.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/InstallerTests.cs index a8fcbe190..06223a189 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/InstallerTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/InstallerTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MediumTrust/MediumTrustDomain.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MediumTrust/MediumTrustDomain.cs index 614b000b0..7fe63735e 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MediumTrust/MediumTrustDomain.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MediumTrust/MediumTrustDomain.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MediumTrust/MediumTrustFixtureAttribute.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MediumTrust/MediumTrustFixtureAttribute.cs index 8a320dba1..d2c7c873f 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MediumTrust/MediumTrustFixtureAttribute.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MediumTrust/MediumTrustFixtureAttribute.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MediumTrust/MediumTrustTestClassCommand.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MediumTrust/MediumTrustTestClassCommand.cs index 3275ea3b1..da37668da 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MediumTrust/MediumTrustTestClassCommand.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MediumTrust/MediumTrustTestClassCommand.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MediumTrust/MediumTrustTestCommand.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MediumTrust/MediumTrustTestCommand.cs index 2d8064ae1..79ce8fc83 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MediumTrust/MediumTrustTestCommand.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MediumTrust/MediumTrustTestCommand.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MediumTrust/MySql.MediumTrustsTests.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MediumTrust/MySql.MediumTrustsTests.cs index 7c40953bb..a75c63762 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MediumTrust/MySql.MediumTrustsTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MediumTrust/MySql.MediumTrustsTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MediumTrust/MySqlClientPermissionTests.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MediumTrust/MySqlClientPermissionTests.cs index 6fed750b1..e25a0f97d 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MediumTrust/MySqlClientPermissionTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MediumTrust/MySqlClientPermissionTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2004, 2024, Oracle and/or its affiliates. +// Copyright © 2004, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MySQLHelperTests.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MySQLHelperTests.cs index 02ead71d3..31cd89da4 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MySQLHelperTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MySQLHelperTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MySqlCommandBuilderTests.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MySqlCommandBuilderTests.cs index ae2b38de7..0901d9b69 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MySqlCommandBuilderTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MySqlCommandBuilderTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MySqlDataAdapterTests.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MySqlDataAdapterTests.cs index 2ecdde630..df80661ab 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MySqlDataAdapterTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MySqlDataAdapterTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MySqlDataReaderTests.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MySqlDataReaderTests.cs index 0843a85a3..4d738a60c 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MySqlDataReaderTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MySqlDataReaderTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/NETCore20Tests.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/NETCore20Tests.cs index c559a33e5..43ef07643 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/NETCore20Tests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/NETCore20Tests.cs @@ -1,4 +1,4 @@ -// Copyright © 2018, 2024, Oracle and/or its affiliates. +// Copyright © 2018, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as @@ -166,4 +166,4 @@ public void SchemaColumnTest() Assert.That(!parentDt.Columns[1].AutoIncrement); } } -} \ No newline at end of file +} diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/OutputParametersBatchPrepared.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/OutputParametersBatchPrepared.cs index 4e2a243c6..144987844 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/OutputParametersBatchPrepared.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/OutputParametersBatchPrepared.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/OutputParametersNoBatch.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/OutputParametersNoBatch.cs index 16733d657..facd8f010 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/OutputParametersNoBatch.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/OutputParametersNoBatch.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/OutputParametersNoBatchPrepared.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/OutputParametersNoBatchPrepared.cs index c32f42b8f..664faf15a 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/OutputParametersNoBatchPrepared.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/OutputParametersNoBatchPrepared.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/PSPipe.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/PSPipe.cs index 310dbc630..fa8d58015 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/PSPipe.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/PSPipe.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/PSPipeCompressed.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/PSPipeCompressed.cs index c67b92fe1..a673f8a88 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/PSPipeCompressed.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/PSPipeCompressed.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/PSSharedMemory.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/PSSharedMemory.cs index 3c9bcb2d6..a0c85b501 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/PSSharedMemory.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/PSSharedMemory.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/PSSharedMemoryCompressed.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/PSSharedMemoryCompressed.cs index ae6452fb4..adff43f9f 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/PSSharedMemoryCompressed.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/PSSharedMemoryCompressed.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/PartialTrustSandbox.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/PartialTrustSandbox.cs index c590ff8cf..b62cbd27d 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/PartialTrustSandbox.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/PartialTrustSandbox.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/PerfMonTests.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/PerfMonTests.cs index cdb6c0230..248ca2ad3 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/PerfMonTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/PerfMonTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/ProcedureParameterTests.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/ProcedureParameterTests.cs index 928091759..d9d74515c 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/ProcedureParameterTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/ProcedureParameterTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/ReplicationTests.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/ReplicationTests.cs index 67c647fa6..c599595f0 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/ReplicationTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/ReplicationTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/StressTestsPipe.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/StressTestsPipe.cs index 0e5345faa..b5f0e5fc0 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/StressTestsPipe.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/StressTestsPipe.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/StressTestsPipeCompressed.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/StressTestsPipeCompressed.cs index 5c64fedf6..2642e165b 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/StressTestsPipeCompressed.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/StressTestsPipeCompressed.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/StressTestsSharedMemory.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/StressTestsSharedMemory.cs index 6944ff02e..533a47399 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/StressTestsSharedMemory.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/StressTestsSharedMemory.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/StressTestsSharedMemoryCompressed.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/StressTestsSharedMemoryCompressed.cs index 681d90af5..853ee4daa 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/StressTestsSharedMemoryCompressed.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/StressTestsSharedMemoryCompressed.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/ThreadingTests.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/ThreadingTests.cs index 825615432..36fe37067 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/ThreadingTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/ThreadingTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/TimeoutAndCancel.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/TimeoutAndCancel.cs index 5d3fb086b..96cc83ac2 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/TimeoutAndCancel.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/TimeoutAndCancel.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/TimeoutAndCancelCompressed.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/TimeoutAndCancelCompressed.cs index 621effb45..3c02ba9af 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/TimeoutAndCancelCompressed.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/TimeoutAndCancelCompressed.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/TimeoutAndCancelPipe.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/TimeoutAndCancelPipe.cs index 403617770..00e010872 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/TimeoutAndCancelPipe.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/TimeoutAndCancelPipe.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/TimeoutAndCancelSharedMemory.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/TimeoutAndCancelSharedMemory.cs index eee7c5c24..622a9bf1a 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/TimeoutAndCancelSharedMemory.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/TimeoutAndCancelSharedMemory.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/TypeTests.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/TypeTests.cs index 290638392..71c861b44 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/TypeTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/TypeTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/UsageAdvisorTests.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/UsageAdvisorTests.cs index ec5eb62e6..b8d746a6e 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/UsageAdvisorTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/UsageAdvisorTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySql.Data.Tests/GenericListener.cs b/MySQL.Data/tests/MySql.Data.Tests/GenericListener.cs index ff2f5c444..46fb9a42d 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/GenericListener.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/GenericListener.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySql.Data.Tests/LoggingTests.cs b/MySQL.Data/tests/MySql.Data.Tests/LoggingTests.cs index 152b6a5a7..691199865 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/LoggingTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/LoggingTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySql.Data.Tests/MySql.Data.Tests.csproj b/MySQL.Data/tests/MySql.Data.Tests/MySql.Data.Tests.csproj index abc240e49..965a80589 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/MySql.Data.Tests.csproj +++ b/MySQL.Data/tests/MySql.Data.Tests/MySql.Data.Tests.csproj @@ -3,7 +3,7 @@ MySql.Data.Tests MySql.Data.Tests Class Library - Copyright © 2016, 2024, Oracle and/or its affiliates. + Copyright © 2016, 2025, Oracle and/or its affiliates. 9.3.0 Oracle Oracle @@ -138,4 +138,4 @@ - \ No newline at end of file + diff --git a/MySQL.Data/tests/MySql.Data.Tests/MySqlBulkLoaderTests.cs b/MySQL.Data/tests/MySql.Data.Tests/MySqlBulkLoaderTests.cs index 8432c7a44..4eace9b66 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/MySqlBulkLoaderTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/MySqlBulkLoaderTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySql.Data.Tests/MySqlDataReaderTests.cs b/MySQL.Data/tests/MySql.Data.Tests/MySqlDataReaderTests.cs index 29f4647b5..ec1ca03ed 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/MySqlDataReaderTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/MySqlDataReaderTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySql.Data.Tests/OutputParametersBatch.cs b/MySQL.Data/tests/MySql.Data.Tests/OutputParametersBatch.cs index 9fb16057c..9e264e4b6 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/OutputParametersBatch.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/OutputParametersBatch.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySql.Data.Tests/ParameterTests.cs b/MySQL.Data/tests/MySql.Data.Tests/ParameterTests.cs index bca23970c..c2a6b7d69 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/ParameterTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/ParameterTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySql.Data.Tests/PoolingTests.cs b/MySQL.Data/tests/MySql.Data.Tests/PoolingTests.cs index 46b466f8d..decb80db6 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/PoolingTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/PoolingTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySql.Data.Tests/PreparedStatementCompressed.cs b/MySQL.Data/tests/MySql.Data.Tests/PreparedStatementCompressed.cs index 76a937054..049abdd9a 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/PreparedStatementCompressed.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/PreparedStatementCompressed.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySql.Data.Tests/PreparedStatements.cs b/MySQL.Data/tests/MySql.Data.Tests/PreparedStatements.cs index 53166d748..a58dbeb53 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/PreparedStatements.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/PreparedStatements.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySql.Data.Tests/Properties/AssemblyInfo.cs b/MySQL.Data/tests/MySql.Data.Tests/Properties/AssemblyInfo.cs index 24d6ecb8c..9a48da313 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Properties/AssemblyInfo.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Properties/AssemblyInfo.cs @@ -1,4 +1,4 @@ -// Copyright © 2004, 2024, Oracle and/or its affiliates. +// Copyright © 2004, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as @@ -40,7 +40,7 @@ [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Oracle")] [assembly: AssemblyProduct("MySql.Data.Tests")] -[assembly: AssemblyCopyright("Copyright © 2004, 2024, Oracle and/or its affiliates.")] +[assembly: AssemblyCopyright("Copyright © 2004, 2025, Oracle and/or its affiliates.")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] diff --git a/MySQL.Data/tests/MySql.Data.Tests/ScriptExecution.cs b/MySQL.Data/tests/MySql.Data.Tests/ScriptExecution.cs index 2baad18ac..8df02c17a 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/ScriptExecution.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/ScriptExecution.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySql.Data.Tests/SimpleTransactions.cs b/MySQL.Data/tests/MySql.Data.Tests/SimpleTransactions.cs index f71fce02c..00d1d4148 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/SimpleTransactions.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/SimpleTransactions.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySql.Data.Tests/SqlServerMode.cs b/MySQL.Data/tests/MySql.Data.Tests/SqlServerMode.cs index a6579225c..bbf289029 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/SqlServerMode.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/SqlServerMode.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySql.Data.Tests/SqlTokenizer.cs b/MySQL.Data/tests/MySql.Data.Tests/SqlTokenizer.cs index 9e0a3e9a8..a512bfb2f 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/SqlTokenizer.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/SqlTokenizer.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySql.Data.Tests/SslTests.cs b/MySQL.Data/tests/MySql.Data.Tests/SslTests.cs index 4ff7c7a36..54276c39d 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/SslTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/SslTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2018, 2024, Oracle and/or its affiliates. +// Copyright © 2018, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySql.Data.Tests/StoredProcedure.cs b/MySQL.Data/tests/MySql.Data.Tests/StoredProcedure.cs index bb02fef1a..87bda77c9 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/StoredProcedure.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/StoredProcedure.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySql.Data.Tests/StoredProcedureWithAccess.cs b/MySQL.Data/tests/MySql.Data.Tests/StoredProcedureWithAccess.cs index e0d2b4fa2..6b6d3f171 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/StoredProcedureWithAccess.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/StoredProcedureWithAccess.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySql.Data.Tests/StressTests.cs b/MySQL.Data/tests/MySql.Data.Tests/StressTests.cs index bb46478ba..1746e11bc 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/StressTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/StressTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySql.Data.Tests/StressTestsCompressed.cs b/MySQL.Data/tests/MySql.Data.Tests/StressTestsCompressed.cs index 6bd2d7fcc..15be16ca4 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/StressTestsCompressed.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/StressTestsCompressed.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySql.Data.Tests/Syntax.cs b/MySQL.Data/tests/MySql.Data.Tests/Syntax.cs index 282317497..646cace02 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Syntax.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Syntax.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySql.Data.Tests/Syntax2.cs b/MySQL.Data/tests/MySql.Data.Tests/Syntax2.cs index 453e707c5..5f8180d24 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Syntax2.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Syntax2.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySql.Data.Tests/TableCaching.cs b/MySQL.Data/tests/MySql.Data.Tests/TableCaching.cs index 828a75ef7..656843ff2 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/TableCaching.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/TableCaching.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySql.Data.Tests/TestBase.cs b/MySQL.Data/tests/MySql.Data.Tests/TestBase.cs index 8e6894567..49109a360 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/TestBase.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/TestBase.cs @@ -1,4 +1,4 @@ -// Copyright © 2016, 2024, Oracle and/or its affiliates. +// Copyright © 2016, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySql.Data.Tests/Tokenizer.cs b/MySQL.Data/tests/MySql.Data.Tests/Tokenizer.cs index fcaa8b25e..76b01d3cf 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Tokenizer.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Tokenizer.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySql.Data.Tests/Transactions.cs b/MySQL.Data/tests/MySql.Data.Tests/Transactions.cs index 83c264d3b..7b0c331ce 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Transactions.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Transactions.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySql.Data.Tests/UnixSockets.cs b/MySQL.Data/tests/MySql.Data.Tests/UnixSockets.cs index 7d70267cd..1ab79fb24 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/UnixSockets.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/UnixSockets.cs @@ -1,4 +1,4 @@ -// Copyright © 2017, 2024, Oracle and/or its affiliates. +// Copyright © 2017, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySql.Data.Tests/Utils.cs b/MySQL.Data/tests/MySql.Data.Tests/Utils.cs index fedcd785b..16b0cc5bc 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Utils.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Utils.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/BaseTest.cs b/MySQL.Data/tests/MySqlX.Data.Tests/BaseTest.cs index 9f2055353..f5fc415f0 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/BaseTest.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/BaseTest.cs @@ -1,4 +1,4 @@ -// Copyright © 2015, 2024, Oracle and/or its affiliates. +// Copyright © 2015, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/BasicFindTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/BasicFindTests.cs index 55208117a..89549ee2a 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/BasicFindTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/BasicFindTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2015, 2024, Oracle and/or its affiliates. +// Copyright © 2015, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/BasicSelectTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/BasicSelectTests.cs index 20b6a73c0..60709a8b8 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/BasicSelectTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/BasicSelectTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2015, 2024, Oracle and/or its affiliates. +// Copyright © 2015, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/CharsetAndCollationTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/CharsetAndCollationTests.cs index 3bb644245..06bdfd0c1 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/CharsetAndCollationTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/CharsetAndCollationTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2017, 2024, Oracle and/or its affiliates. +// Copyright © 2017, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/ClientSideFailoverTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/ClientSideFailoverTests.cs index d66254a17..492b43d00 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/ClientSideFailoverTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/ClientSideFailoverTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2017, 2024, Oracle and/or its affiliates. +// Copyright © 2017, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/ClientTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/ClientTests.cs index bc5a2b17c..e0256f29a 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/ClientTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/ClientTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2018, 2024, Oracle and/or its affiliates. +// Copyright © 2018, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/CloseConnectionTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/CloseConnectionTests.cs index c98ac4f0e..7f906380c 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/CloseConnectionTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/CloseConnectionTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2020, 2024, Oracle and/or its affiliates. +// Copyright © 2020, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/CollectionAsyncTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/CollectionAsyncTests.cs index 4e8fec078..47c992ffc 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/CollectionAsyncTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/CollectionAsyncTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2015, 2024, Oracle and/or its affiliates. +// Copyright © 2015, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/CollectionIndexTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/CollectionIndexTests.cs index f8c5f6736..1994f681c 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/CollectionIndexTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/CollectionIndexTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2017, 2024, Oracle and/or its affiliates. +// Copyright © 2017, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/CollectionTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/CollectionTests.cs index 6a03fdf4b..ba00db91f 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/CollectionTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/CollectionTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2015, 2024, Oracle and/or its affiliates. +// Copyright © 2015, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/CompressionTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/CompressionTests.cs index 88212c2e3..d0a3df97f 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/CompressionTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/CompressionTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2019, 2024, Oracle and/or its affiliates. +// Copyright © 2019, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/CrudInsertTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/CrudInsertTests.cs index b849e0bb6..80e1d31ef 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/CrudInsertTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/CrudInsertTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2015, 2024, Oracle and/or its affiliates. +// Copyright © 2015, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/CrudRemoveTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/CrudRemoveTests.cs index 741cb7a92..a35f65908 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/CrudRemoveTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/CrudRemoveTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2015, 2024, Oracle and/or its affiliates. +// Copyright © 2015, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/CrudTests/CrudGCTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/CrudTests/CrudGCTests.cs index 96aa89cd5..add461b08 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/CrudTests/CrudGCTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/CrudTests/CrudGCTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2015, 2024, Oracle and/or its affiliates. +// Copyright © 2015, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/CrudTests/DocBufferingTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/CrudTests/DocBufferingTests.cs index b9d5b74d9..1913d0ea9 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/CrudTests/DocBufferingTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/CrudTests/DocBufferingTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2015, 2024, Oracle and/or its affiliates. +// Copyright © 2015, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/CrudUpdateTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/CrudUpdateTests.cs index fab5a0f31..e60869b05 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/CrudUpdateTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/CrudUpdateTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2015, 2024, Oracle and/or its affiliates. +// Copyright © 2015, 2025, Oracle and/or its affiliates. // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/CustomTypeTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/CustomTypeTests.cs index 90cc1ee73..675529fbc 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/CustomTypeTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/CustomTypeTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2023, 2024, Oracle and/or its affiliates. +// Copyright © 2023, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/DbDocTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/DbDocTests.cs index 27f54b1d7..05f944bae 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/DbDocTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/DbDocTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2015, 2024, Oracle and/or its affiliates. +// Copyright © 2015, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/DnsSrvTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/DnsSrvTests.cs index d6ebc34c8..0dfaee5e2 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/DnsSrvTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/DnsSrvTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2019, 2024, Oracle and/or its affiliates. +// Copyright © 2019, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/ExprParserTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/ExprParserTests.cs index d31c6bfcc..8553d1d55 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/ExprParserTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/ExprParserTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2015, 2024, Oracle and/or its affiliates. +// Copyright © 2015, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/GenericListener.cs b/MySQL.Data/tests/MySqlX.Data.Tests/GenericListener.cs index a359f5455..b12077da7 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/GenericListener.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/GenericListener.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/JsonParserTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/JsonParserTests.cs index 07fb51ff3..c9ee9d1fb 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/JsonParserTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/JsonParserTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2017, 2024, Oracle and/or its affiliates. +// Copyright © 2017, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/MergePatch.cs b/MySQL.Data/tests/MySqlX.Data.Tests/MergePatch.cs index 85d2f494b..63d3093e9 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/MergePatch.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/MergePatch.cs @@ -1,4 +1,4 @@ -// Copyright © 2017, 2024, Oracle and/or its affiliates. +// Copyright © 2017, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/MySqlX.Data.Tests.csproj b/MySQL.Data/tests/MySqlX.Data.Tests/MySqlX.Data.Tests.csproj index bda016d41..3475a9104 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/MySqlX.Data.Tests.csproj +++ b/MySQL.Data/tests/MySqlX.Data.Tests/MySqlX.Data.Tests.csproj @@ -3,7 +3,7 @@ MySql.Data.Tests MySql.Data.Tests Class Library - Copyright © 2016, 2024, Oracle and/or its affiliates. + Copyright © 2016, 2025, Oracle and/or its affiliates. 9.3.0 Oracle Oracle @@ -117,4 +117,4 @@ Always - \ No newline at end of file + diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/PerformanceTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/PerformanceTests.cs index 6390cb8a3..b35491dff 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/PerformanceTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/PerformanceTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2018, 2024, Oracle and/or its affiliates. +// Copyright © 2018, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/PreparedStatementsTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/PreparedStatementsTests.cs index 56fb53c8b..c33e85059 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/PreparedStatementsTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/PreparedStatementsTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2018, 2024, Oracle and/or its affiliates. +// Copyright © 2018, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/Properties/AssemblyInfo.cs b/MySQL.Data/tests/MySqlX.Data.Tests/Properties/AssemblyInfo.cs index 7503c029b..20a236993 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/Properties/AssemblyInfo.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/Properties/AssemblyInfo.cs @@ -1,4 +1,4 @@ -// Copyright © 2015, 2024, Oracle and/or its affiliates. +// Copyright © 2015, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as @@ -38,7 +38,7 @@ [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("MySQL Connector/NET")] -[assembly: AssemblyCopyright("Copyright © 2016, 2024, Oracle and/or its affiliates.")] +[assembly: AssemblyCopyright("Copyright © 2016, 2025, Oracle and/or its affiliates.")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/ColumnMetadataTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/ColumnMetadataTests.cs index 5d4a7b5eb..aae0a3684 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/ColumnMetadataTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/ColumnMetadataTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2016, 2024, Oracle and/or its affiliates. +// Copyright © 2016, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/DataTypeTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/DataTypeTests.cs index 81806cf7e..b13a25a79 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/DataTypeTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/DataTypeTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2015, 2024, Oracle and/or its affiliates. +// Copyright © 2015, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/DateTimeTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/DateTimeTests.cs index cfaefd5f7..fdd9ca112 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/DateTimeTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/DateTimeTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2015, 2024, Oracle and/or its affiliates. +// Copyright © 2015, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/RelationalGCTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/RelationalGCTests.cs index f5e731796..553f9ec47 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/RelationalGCTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/RelationalGCTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2015, 2024, Oracle and/or its affiliates. +// Copyright © 2015, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/RowBufferingTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/RowBufferingTests.cs index 7724b265b..f0d8790a6 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/RowBufferingTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/RowBufferingTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2015, 2024, Oracle and/or its affiliates. +// Copyright © 2015, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/SqlTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/SqlTests.cs index 7ce44ed11..3ebe3e995 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/SqlTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/SqlTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2015, 2024, Oracle and/or its affiliates. +// Copyright © 2015, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/TableAsyncTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/TableAsyncTests.cs index 7cfcd16d1..cc1b90324 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/TableAsyncTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/TableAsyncTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2015, 2024, Oracle and/or its affiliates. +// Copyright © 2015, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/TableDeleteTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/TableDeleteTests.cs index a423a0723..01f4660ce 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/TableDeleteTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/TableDeleteTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2015, 2024, Oracle and/or its affiliates. +// Copyright © 2015, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/TableInsertTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/TableInsertTests.cs index 206563e21..1f9f379ea 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/TableInsertTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/TableInsertTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2015, 2024, Oracle and/or its affiliates. +// Copyright © 2015, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/TableSelectTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/TableSelectTests.cs index 5e26dc418..970cf6090 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/TableSelectTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/TableSelectTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2015, 2024, Oracle and/or its affiliates. +// Copyright © 2015, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/TableUpdateTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/TableUpdateTests.cs index b8713cea6..9129143e4 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/TableUpdateTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/TableUpdateTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2015, 2024, Oracle and/or its affiliates. +// Copyright © 2015, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/ViewTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/ViewTests.cs index 9548fdd96..40903ff04 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/ViewTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/RelationalTests/ViewTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2016, 2024, Oracle and/or its affiliates. +// Copyright © 2016, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/SchemaTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/SchemaTests.cs index 07145c044..601db8a74 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/SchemaTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/SchemaTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2015, 2024, Oracle and/or its affiliates. +// Copyright © 2015, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/SessionTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/SessionTests.cs index 2cb9c748b..b8487b464 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/SessionTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/SessionTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2015, 2024, Oracle and/or its affiliates. +// Copyright © 2015, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/SslTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/SslTests.cs index d8d9f225b..f424c85d4 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/SslTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/SslTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2018, 2024, Oracle and/or its affiliates. +// Copyright © 2018, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/TransactionTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/TransactionTests.cs index 41975b6eb..778a06428 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/TransactionTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/TransactionTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2015, 2024, Oracle and/or its affiliates. +// Copyright © 2015, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/UnixSocketsTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/UnixSocketsTests.cs index 17c083be1..58ff81014 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/UnixSocketsTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/UnixSocketsTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2017, 2024, Oracle and/or its affiliates. +// Copyright © 2017, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/XAuth.cs b/MySQL.Data/tests/MySqlX.Data.Tests/XAuth.cs index b9cccf21e..71d5c655f 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/XAuth.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/XAuth.cs @@ -1,4 +1,4 @@ -// Copyright © 2021, 2024, Oracle and/or its affiliates. +// Copyright © 2021, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/XConnectionStringBuilderTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/XConnectionStringBuilderTests.cs index 7b949d01c..616f67d33 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/XConnectionStringBuilderTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/XConnectionStringBuilderTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2018, 2024, Oracle and/or its affiliates. +// Copyright © 2018, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySql.Web/src/Application.cs b/MySql.Web/src/Application.cs index 65c923e7a..fcfc033ea 100644 --- a/MySql.Web/src/Application.cs +++ b/MySql.Web/src/Application.cs @@ -1,4 +1,4 @@ -// Copyright © 2009, 2024, Oracle and/or its affiliates. +// Copyright © 2009, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySql.Web/src/ConfigUtility.cs b/MySql.Web/src/ConfigUtility.cs index 5c03f1fa7..6bb236523 100644 --- a/MySql.Web/src/ConfigUtility.cs +++ b/MySql.Web/src/ConfigUtility.cs @@ -1,4 +1,4 @@ -// Copyright © 2017, 2024, Oracle and/or its affiliates. +// Copyright © 2017, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySql.Web/src/MembershipProvider.cs b/MySql.Web/src/MembershipProvider.cs index 3f77544f8..d3b82785a 100644 --- a/MySql.Web/src/MembershipProvider.cs +++ b/MySql.Web/src/MembershipProvider.cs @@ -1,4 +1,4 @@ -// Copyright © 2004, 2024, Oracle and/or its affiliates. +// Copyright © 2004, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySql.Web/src/MySql.Web.csproj b/MySql.Web/src/MySql.Web.csproj index 78ebb7da5..97f4d0a68 100644 --- a/MySql.Web/src/MySql.Web.csproj +++ b/MySql.Web/src/MySql.Web.csproj @@ -86,4 +86,4 @@ - \ No newline at end of file + diff --git a/MySql.Web/src/MySqlDatabaseWrapper.cs b/MySql.Web/src/MySqlDatabaseWrapper.cs index 99dfadc59..5fa161e80 100644 --- a/MySql.Web/src/MySqlDatabaseWrapper.cs +++ b/MySql.Web/src/MySqlDatabaseWrapper.cs @@ -1,4 +1,4 @@ -// Copyright © 2014, 2024, Oracle and/or its affiliates. +// Copyright © 2014, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySql.Web/src/MySqlWebSecurity.cs b/MySql.Web/src/MySqlWebSecurity.cs index ced44eeeb..4b5939251 100644 --- a/MySql.Web/src/MySqlWebSecurity.cs +++ b/MySql.Web/src/MySqlWebSecurity.cs @@ -1,4 +1,4 @@ -// Copyright © 2014, 2024, Oracle and/or its affiliates. +// Copyright © 2014, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySql.Web/src/PersonalizationConnectionHelper.cs b/MySql.Web/src/PersonalizationConnectionHelper.cs index f8363d7bb..027113ded 100644 --- a/MySql.Web/src/PersonalizationConnectionHelper.cs +++ b/MySql.Web/src/PersonalizationConnectionHelper.cs @@ -1,4 +1,4 @@ -// Copyright © 2014, 2024, Oracle and/or its affiliates. +// Copyright © 2014, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySql.Web/src/PersonalizationProvider.cs b/MySql.Web/src/PersonalizationProvider.cs index f98a96859..6c80f47f4 100644 --- a/MySql.Web/src/PersonalizationProvider.cs +++ b/MySql.Web/src/PersonalizationProvider.cs @@ -1,4 +1,4 @@ -// Copyright © 2014, 2024, Oracle and/or its affiliates. +// Copyright © 2014, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySql.Web/src/PersonalizationProviderProcedures.cs b/MySql.Web/src/PersonalizationProviderProcedures.cs index 1e5750d18..7a150871a 100644 --- a/MySql.Web/src/PersonalizationProviderProcedures.cs +++ b/MySql.Web/src/PersonalizationProviderProcedures.cs @@ -1,4 +1,4 @@ -// Copyright © 2014, 2024, Oracle and/or its affiliates. +// Copyright © 2014, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySql.Web/src/ProfileProvider.cs b/MySql.Web/src/ProfileProvider.cs index 25fad6a50..778ae9a5c 100644 --- a/MySql.Web/src/ProfileProvider.cs +++ b/MySql.Web/src/ProfileProvider.cs @@ -1,4 +1,4 @@ -// Copyright © 2004, 2024, Oracle and/or its affiliates. +// Copyright © 2004, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySql.Web/src/Properties/AssemblyInfo.cs b/MySql.Web/src/Properties/AssemblyInfo.cs index a621f8972..fa38956fc 100644 --- a/MySql.Web/src/Properties/AssemblyInfo.cs +++ b/MySql.Web/src/Properties/AssemblyInfo.cs @@ -1,4 +1,4 @@ -// Copyright © 2004, 2024, Oracle and/or its affiliates. +// Copyright © 2004, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySql.Web/src/Properties/VersionInfo.cs b/MySql.Web/src/Properties/VersionInfo.cs index 0e0ddbb1f..e4c0f01b6 100644 --- a/MySql.Web/src/Properties/VersionInfo.cs +++ b/MySql.Web/src/Properties/VersionInfo.cs @@ -1,4 +1,4 @@ -// Copyright © 2024, Oracle and/or its affiliates. +// Copyright © 2024, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySql.Web/src/RoleProvider.cs b/MySql.Web/src/RoleProvider.cs index 2cd289d55..ef8177e1d 100644 --- a/MySql.Web/src/RoleProvider.cs +++ b/MySql.Web/src/RoleProvider.cs @@ -1,4 +1,4 @@ -// Copyright © 2004, 2024, Oracle and/or its affiliates. +// Copyright © 2004, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySql.Web/src/Runtime.cs b/MySql.Web/src/Runtime.cs index 162ef29cf..78214fe94 100644 --- a/MySql.Web/src/Runtime.cs +++ b/MySql.Web/src/Runtime.cs @@ -1,4 +1,4 @@ -// Copyright © 2004, 2024, Oracle and/or its affiliates. +// Copyright © 2004, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySql.Web/src/SchemaManager.cs b/MySql.Web/src/SchemaManager.cs index d83afbeb2..ed0632e3c 100644 --- a/MySql.Web/src/SchemaManager.cs +++ b/MySql.Web/src/SchemaManager.cs @@ -1,4 +1,4 @@ -// Copyright © 2004, 2024, Oracle and/or its affiliates. +// Copyright © 2004, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySql.Web/src/SessionProvider.cs b/MySql.Web/src/SessionProvider.cs index 68e140eee..c24f741f1 100644 --- a/MySql.Web/src/SessionProvider.cs +++ b/MySql.Web/src/SessionProvider.cs @@ -1,4 +1,4 @@ -// Copyright © 2004, 2024, Oracle and/or its affiliates. +// Copyright © 2004, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySql.Web/src/SimpleMembershipProvider.cs b/MySql.Web/src/SimpleMembershipProvider.cs index ff2924ec6..a2d1d6735 100644 --- a/MySql.Web/src/SimpleMembershipProvider.cs +++ b/MySql.Web/src/SimpleMembershipProvider.cs @@ -1,4 +1,4 @@ -// Copyright © 2014, 2024, Oracle and/or its affiliates. +// Copyright © 2014, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySql.Web/src/SimpleRoleProvider.cs b/MySql.Web/src/SimpleRoleProvider.cs index 649402452..f75e7f193 100644 --- a/MySql.Web/src/SimpleRoleProvider.cs +++ b/MySql.Web/src/SimpleRoleProvider.cs @@ -1,4 +1,4 @@ -// Copyright © 2014, 2024, Oracle and/or its affiliates. +// Copyright © 2014, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySql.Web/src/SiteMapProvider.cs b/MySql.Web/src/SiteMapProvider.cs index 3fdd5a90b..257ad7991 100644 --- a/MySql.Web/src/SiteMapProvider.cs +++ b/MySql.Web/src/SiteMapProvider.cs @@ -1,4 +1,4 @@ -// Copyright © 2004, 2024, Oracle and/or its affiliates. +// Copyright © 2004, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySql.Web/tests/MySql.Web.Tests.csproj b/MySql.Web/tests/MySql.Web.Tests.csproj index aa64682dd..27dcb3dd2 100644 --- a/MySql.Web/tests/MySql.Web.Tests.csproj +++ b/MySql.Web/tests/MySql.Web.Tests.csproj @@ -2,7 +2,7 @@ MySql.Web.Tests - Copyright © 2016, 2024, Oracle and/or its affiliates. + Copyright © 2016, 2025, Oracle and/or its affiliates. en-US 9.3.0 Oracle @@ -64,4 +64,4 @@ - \ No newline at end of file + diff --git a/MySql.Web/tests/PersonalizationTests.cs b/MySql.Web/tests/PersonalizationTests.cs index d90553ce9..1ed8622c8 100644 --- a/MySql.Web/tests/PersonalizationTests.cs +++ b/MySql.Web/tests/PersonalizationTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2014, 2024, Oracle and/or its affiliates. +// Copyright © 2014, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySql.Web/tests/ProfileTests.cs b/MySql.Web/tests/ProfileTests.cs index 2de577133..dbceae9cb 100644 --- a/MySql.Web/tests/ProfileTests.cs +++ b/MySql.Web/tests/ProfileTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySql.Web/tests/Properties/AssemblyInfo.cs b/MySql.Web/tests/Properties/AssemblyInfo.cs index f492e56f2..e4cc0a0e5 100644 --- a/MySql.Web/tests/Properties/AssemblyInfo.cs +++ b/MySql.Web/tests/Properties/AssemblyInfo.cs @@ -1,4 +1,4 @@ -// Copyright © 2004, 2024, Oracle and/or its affiliates. +// Copyright © 2004, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as @@ -38,7 +38,7 @@ [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Oracle")] [assembly: AssemblyProduct("MySql.Web.Tests")] -[assembly: AssemblyCopyright("Copyright © 2004, 2024, Oracle and/or its affiliates.")] +[assembly: AssemblyCopyright("Copyright © 2004, 2025, Oracle and/or its affiliates.")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] [assembly: NonParallelizable] diff --git a/MySql.Web/tests/RoleManagement.cs b/MySql.Web/tests/RoleManagement.cs index 225919241..7a1d56fcc 100644 --- a/MySql.Web/tests/RoleManagement.cs +++ b/MySql.Web/tests/RoleManagement.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySql.Web/tests/SchemaManagerTests.cs b/MySql.Web/tests/SchemaManagerTests.cs index a4f1f68d2..2b089c4c3 100644 --- a/MySql.Web/tests/SchemaManagerTests.cs +++ b/MySql.Web/tests/SchemaManagerTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySql.Web/tests/SchemaTests.cs b/MySql.Web/tests/SchemaTests.cs index f1217ae8f..6f8558474 100644 --- a/MySql.Web/tests/SchemaTests.cs +++ b/MySql.Web/tests/SchemaTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySql.Web/tests/SessionLocking/Global.asax.cs b/MySql.Web/tests/SessionLocking/Global.asax.cs index 270c7b09a..934ba143b 100644 --- a/MySql.Web/tests/SessionLocking/Global.asax.cs +++ b/MySql.Web/tests/SessionLocking/Global.asax.cs @@ -1,4 +1,4 @@ -// Copyright © 2004, 2024, Oracle and/or its affiliates. +// Copyright © 2004, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySql.Web/tests/SessionLocking/InitSessionLocking.aspx.cs b/MySql.Web/tests/SessionLocking/InitSessionLocking.aspx.cs index 7760aa845..b4ab197ad 100644 --- a/MySql.Web/tests/SessionLocking/InitSessionLocking.aspx.cs +++ b/MySql.Web/tests/SessionLocking/InitSessionLocking.aspx.cs @@ -1,4 +1,4 @@ -// Copyright © 2004, 2024, Oracle and/or its affiliates. +// Copyright © 2004, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySql.Web/tests/SessionLocking/read.aspx.cs b/MySql.Web/tests/SessionLocking/read.aspx.cs index 890444b96..fe2865af1 100644 --- a/MySql.Web/tests/SessionLocking/read.aspx.cs +++ b/MySql.Web/tests/SessionLocking/read.aspx.cs @@ -1,4 +1,4 @@ -// Copyright © 2004, 2024, Oracle and/or its affiliates. +// Copyright © 2004, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySql.Web/tests/SessionLocking/write.aspx.cs b/MySql.Web/tests/SessionLocking/write.aspx.cs index 1ef9fe54d..0d0b2bc1a 100644 --- a/MySql.Web/tests/SessionLocking/write.aspx.cs +++ b/MySql.Web/tests/SessionLocking/write.aspx.cs @@ -1,4 +1,4 @@ -// Copyright © 2004, 2024, Oracle and/or its affiliates. +// Copyright © 2004, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySql.Web/tests/SessionLocking/write2.aspx.cs b/MySql.Web/tests/SessionLocking/write2.aspx.cs index 9098345f1..54a33c439 100644 --- a/MySql.Web/tests/SessionLocking/write2.aspx.cs +++ b/MySql.Web/tests/SessionLocking/write2.aspx.cs @@ -1,4 +1,4 @@ -// Copyright © 2004, 2024, Oracle and/or its affiliates. +// Copyright © 2004, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySql.Web/tests/SessionTests.cs b/MySql.Web/tests/SessionTests.cs index 8ee91b96b..b147fea74 100644 --- a/MySql.Web/tests/SessionTests.cs +++ b/MySql.Web/tests/SessionTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySql.Web/tests/SimpleMembership.cs b/MySql.Web/tests/SimpleMembership.cs index cb13ccc79..da2b09a37 100644 --- a/MySql.Web/tests/SimpleMembership.cs +++ b/MySql.Web/tests/SimpleMembership.cs @@ -1,4 +1,4 @@ -// Copyright © 2014, 2024, Oracle and/or its affiliates. +// Copyright © 2014, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySql.Web/tests/SiteMapTests.cs b/MySql.Web/tests/SiteMapTests.cs index 18e9d94a0..1cde4f895 100644 --- a/MySql.Web/tests/SiteMapTests.cs +++ b/MySql.Web/tests/SiteMapTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2014, 2024, Oracle and/or its affiliates. +// Copyright © 2014, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySql.Web/tests/TestProfile.cs b/MySql.Web/tests/TestProfile.cs index 1b2a54a2e..92a352b2b 100644 --- a/MySql.Web/tests/TestProfile.cs +++ b/MySql.Web/tests/TestProfile.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySql.Web/tests/UserManagement.cs b/MySql.Web/tests/UserManagement.cs index a022e2045..cd79da523 100644 --- a/MySql.Web/tests/UserManagement.cs +++ b/MySql.Web/tests/UserManagement.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as diff --git a/MySql.Web/tests/WebTestBase.cs b/MySql.Web/tests/WebTestBase.cs index 9b8d09355..c7e06a723 100644 --- a/MySql.Web/tests/WebTestBase.cs +++ b/MySql.Web/tests/WebTestBase.cs @@ -1,4 +1,4 @@ -// Copyright © 2013, 2024, Oracle and/or its affiliates. +// Copyright © 2013, 2025, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as From be3e9b6671990dfa7762bd6f653750966ad2d70c Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Tue, 21 Jan 2025 15:07:09 -0700 Subject: [PATCH 102/125] Bug#37503859 [MySql.EntityFrameworkCore.dll in NuGet packages is not signed] Change-Id: I0be1afa8a0b55e457dded79bd86f21e9c5b185d4 --- CHANGES | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES b/CHANGES index 9b519c42d..3319ada4a 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,5 @@ 9.3.0 +- Fixed bug MySql.EntityFrameworkCore.dll in NuGet packages is not signed (Oracle Bug #37503859). 9.2.0 From 5ebea1e1084d1032b6dc403587e999d935934027 Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Thu, 22 Feb 2024 21:09:17 -0700 Subject: [PATCH 103/125] WL#16033 [Fix timeout tests] Change-Id: I7c6fdf95cb45b32832f01bfa7d04da6b80bac574 --- CHANGES | 1 + MySQL.Data/src/common/MyNetworkStream.cs | 24 +- .../tests/MySql.Data.Tests/ConnectionTests.cs | 16 +- .../tests/MySql.Data.Tests/MockServer.cs | 138 +++++++++ .../CharsetAndCollationTests.cs | 2 +- .../ClientSideFailoverTests.cs | 4 +- .../tests/MySqlX.Data.Tests/ClientTests.cs | 24 +- .../tests/MySqlX.Data.Tests/MockServer.cs | 138 +++++++++ .../tests/MySqlX.Data.Tests/SessionTests.cs | 265 +++++++++++++----- 9 files changed, 519 insertions(+), 93 deletions(-) create mode 100644 MySQL.Data/tests/MySql.Data.Tests/MockServer.cs create mode 100644 MySQL.Data/tests/MySqlX.Data.Tests/MockServer.cs diff --git a/CHANGES b/CHANGES index 3319ada4a..410886323 100644 --- a/CHANGES +++ b/CHANGES @@ -1,5 +1,6 @@ 9.3.0 - Fixed bug MySql.EntityFrameworkCore.dll in NuGet packages is not signed (Oracle Bug #37503859). +- Fixed some tests due to incorrect implementation (WL16033). 9.2.0 diff --git a/MySQL.Data/src/common/MyNetworkStream.cs b/MySQL.Data/src/common/MyNetworkStream.cs index 2af7d1c01..c8b5e2ed2 100644 --- a/MySQL.Data/src/common/MyNetworkStream.cs +++ b/MySQL.Data/src/common/MyNetworkStream.cs @@ -116,8 +116,7 @@ private void HandleOrRethrowException(Exception e) } if (IsTimeoutException(socketException)) { - return; - //throw new TimeoutException(socketException.Message, e); + throw new TimeoutException(socketException.Message, e); } } currentException = currentException.InnerException; @@ -137,16 +136,30 @@ private async Task ReadAsync(byte[] buffer, int offset, int count, Cancella { try { + //if (execAsync) + // return await base.ReadAsync(buffer, offset, count, cancellationToken).ConfigureAwait(false); + //else + // return base.Read(buffer, offset, count); + if (execAsync) - return await base.ReadAsync(buffer, offset, count, cancellationToken).ConfigureAwait(false); + { + int readasync= await base.ReadAsync(buffer, offset, count, cancellationToken).ConfigureAwait(false); + _socket.ReceiveTimeout = 0; + return readasync; + } else - return base.Read(buffer, offset, count); + { + int read = base.Read(buffer, offset, count); + _socket.ReceiveTimeout = 0; + return read; + } } catch (Exception e) { exception = e; HandleOrRethrowException(e); } + } while (++retry < MaxRetryCount); if (exception.GetBaseException() is SocketException @@ -296,6 +309,9 @@ private static MyNetworkStream CreateSocketStream(uint port, uint keepAlive, uin new Socket(AddressFamily.Unix, SocketType.Stream, ProtocolType.IP) : new Socket(ip.AddressFamily, SocketType.Stream, ProtocolType.Tcp); + if (connectionTimeout > 0) + socket.ReceiveTimeout = (int)connectionTimeout; + socket.NoDelay = true; if (keepAlive > 0) diff --git a/MySQL.Data/tests/MySql.Data.Tests/ConnectionTests.cs b/MySQL.Data/tests/MySql.Data.Tests/ConnectionTests.cs index 3a44eea9a..c5725768d 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/ConnectionTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/ConnectionTests.cs @@ -27,12 +27,14 @@ // 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA using MySql.Data.Common; +using MySql.Data.Tests; using NUnit.Framework; using NUnit.Framework.Legacy; using System; using System.Collections.Generic; using System.Data; using System.Diagnostics; +using System.Net.Sockets; using System.Text; using System.Threading; using System.Threading.Tasks; @@ -553,17 +555,21 @@ public void CloneConnectionDisclosePassword() [Property("Category", "Security")] public void ConnectionTimeout() { + MockServer mServer=new MockServer(false); + mServer.StartServer(); + MySqlConnectionStringBuilder connStr = new MySqlConnectionStringBuilder(Connection.ConnectionString); - connStr.Server = "10.20.30.40"; - connStr.Port = 3000; + connStr.Server = mServer.Address.ToString(); + connStr.Port = (uint)mServer.Port; connStr.ConnectionTimeout = 5; MySqlConnection c = new MySqlConnection(connStr.GetConnectionString(true)); - DateTime start = DateTime.Now; var ex = Assert.Throws(() => c.Open()); - Assert.That(ex.InnerException.InnerException is TimeoutException); TimeSpan diff = DateTime.Now.Subtract(start); - Assert.That(diff.TotalSeconds < 6, $"Timeout exceeded: {diff.TotalSeconds}"); + Assert.That(diff.TotalSeconds < 8, $"Timeout exceeded: {diff.TotalSeconds}"); + + mServer.StopServer(); + mServer.DisposeListener(); } [Test] diff --git a/MySQL.Data/tests/MySql.Data.Tests/MockServer.cs b/MySQL.Data/tests/MySql.Data.Tests/MockServer.cs new file mode 100644 index 000000000..991052127 --- /dev/null +++ b/MySQL.Data/tests/MySql.Data.Tests/MockServer.cs @@ -0,0 +1,138 @@ +// Copyright © 2025, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using System; +using System.Net; +using System.Net.Sockets; +using System.Threading; +using System.Threading.Tasks; + +namespace MySql.Data.Tests +{ + public class MockServer + { + private TcpListener listener; + + private int _port; + + private IPAddress _address; + + private ManualResetEvent _stopserver = new ManualResetEvent(false); + + private CancellationTokenSource cts; + + private bool _usetimeout; + + public int Port + { + get => _port; + set => _port = value; + } + + public IPAddress Address + { + get => _address; + set => _address = value; + } + + public MockServer(bool usetimeout) + { + GetMockServerInfo(); + _stopserver.Reset(); + _usetimeout = usetimeout; + cts = new CancellationTokenSource(TimeSpan.FromSeconds(12)); + } + + public void GetMockServerInfo() + { + TcpListener loopback = new TcpListener(IPAddress.Loopback, 0); + loopback.Start(); + _port = ((IPEndPoint)loopback.LocalEndpoint).Port; + loopback.Stop(); + _address = Dns.GetHostEntry("localhost").AddressList[0]; + } + + public void StopServer() + { + _stopserver.Set(); + } + public void DisposeListener() + { + if (listener != null) + { + listener.Stop(); + } + } + + public async Task ServerWorker(CancellationToken ct) + { + await Task.Run(() => + { + IPEndPoint endpoint = new IPEndPoint(IPAddress.Loopback, Port); + listener = new(endpoint); + + try + { + listener.Start(); + while (!_stopserver.WaitOne(1)) + { + listener.BeginAcceptSocket(new AsyncCallback(beginConnection), null); + } + } + catch (Exception) + { + } + finally + { + listener.Stop(); + } + }, ct).ConfigureAwait(false); + } + + public void StartServer() + { + ServerWorker(cts.Token).ConfigureAwait(false); + } + + private void beginConnection(IAsyncResult iar) + { + try + { + Socket client = listener.EndAcceptSocket(iar); + if (_usetimeout) + { + Task.Delay(500).Wait(); + client.Close(); + } + } + catch (Exception) + { + } + } + } +} \ No newline at end of file diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/CharsetAndCollationTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/CharsetAndCollationTests.cs index 06bdfd0c1..226d722f5 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/CharsetAndCollationTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/CharsetAndCollationTests.cs @@ -1127,7 +1127,7 @@ public void Utf8mb4BinaryNopadCollationTable() mysqlx0.Password = session.Settings.Password; mysqlx0.CharacterSet = "utf8mb4"; mysqlx0.SslMode = MySqlSslMode.Required; - mysqlx0.ConnectTimeout = 10; + mysqlx0.ConnectTimeout = 1000; mysqlx0.Keepalive = 10; mysqlx0.CertificateFile = sslCa; mysqlx0.CertificatePassword = sslCertificatePassword; diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/ClientSideFailoverTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/ClientSideFailoverTests.cs index 492b43d00..13fb2e74b 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/ClientSideFailoverTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/ClientSideFailoverTests.cs @@ -466,7 +466,6 @@ public void ManyInvalidHost() { Assume.That(session.Version.isAtLeast(5, 7, 0), "This test is for MySql 5.7 or higher"); - var connectionTimeout = 1; MySqlXConnectionStringBuilder sb = new MySqlXConnectionStringBuilder(ConnectionString); // Automatically set priority if no priority is given. @@ -479,8 +478,7 @@ public void ManyInvalidHost() } using (var session1 = MySQLX.GetSession("server=" + hostList + ";port=" + sb.Port + ";uid=" + - sb.UserID + ";password=" + sb.Password + ";connect-timeout=" + - connectionTimeout + ";ssl-mode=Required")) + sb.UserID + ";password=" + sb.Password + ";connect-timeout=1000;ssl-mode=Required")) { Assert.That(session1.InternalSession.SessionState, Is.EqualTo(SessionState.Open)); var schema = session1.GetSchema("test"); diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/ClientTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/ClientTests.cs index e0256f29a..f50aa09fe 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/ClientTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/ClientTests.cs @@ -1773,7 +1773,7 @@ public void ConnectionAttributesInvalidCombinations() mysqlx0.Database = schemaName; mysqlx0.CharacterSet = "utf8mb4"; mysqlx0.SslMode = MySqlSslMode.Required; - mysqlx0.ConnectTimeout = 10; + mysqlx0.ConnectTimeout = 1000; mysqlx0.Keepalive = 10; mysqlx0.CertificateFile = sslCa; mysqlx0.CertificatePassword = sslCertificatePassword; @@ -1801,7 +1801,7 @@ public void ConnectionAttributesInvalidCombinations() mysqlx0.Database = schemaName; mysqlx0.CharacterSet = "utf8mb4"; mysqlx0.SslMode = MySqlSslMode.Required; - mysqlx0.ConnectTimeout = 10; + mysqlx0.ConnectTimeout = 1000; mysqlx0.Keepalive = 10; mysqlx0.CertificateFile = sslCa; mysqlx0.CertificatePassword = sslCertificatePassword; @@ -1852,7 +1852,7 @@ public void ConnectionAttributesValidCombinations() mysqlx0.Database = schemaName; mysqlx0.CharacterSet = "utf8mb4"; mysqlx0.SslMode = MySqlSslMode.Required; - mysqlx0.ConnectTimeout = 10; + mysqlx0.ConnectTimeout = 1000; mysqlx0.Keepalive = 10; mysqlx0.CertificateFile = sslCa; mysqlx0.CertificatePassword = sslCertificatePassword; @@ -1887,7 +1887,7 @@ public void ConnectionAttributesValidCombinations() mysqlx0.Database = schemaName; mysqlx0.CharacterSet = "utf8mb4"; mysqlx0.SslMode = MySqlSslMode.Required; - mysqlx0.ConnectTimeout = 10; + mysqlx0.ConnectTimeout = 1000; mysqlx0.Keepalive = 10; mysqlx0.CertificateFile = sslCa; mysqlx0.CertificatePassword = sslCertificatePassword; @@ -1943,7 +1943,7 @@ public void ConnectionAttributesKeySpecialChars() mysqlx0.Database = schemaName; mysqlx0.CharacterSet = "utf8mb4"; mysqlx0.SslMode = MySqlSslMode.Required; - mysqlx0.ConnectTimeout = 10; + mysqlx0.ConnectTimeout = 1000; mysqlx0.Keepalive = 10; mysqlx0.CertificateFile = sslCa; mysqlx0.CertificatePassword = sslCertificatePassword; @@ -1972,7 +1972,7 @@ public void ConnectionAttributesKeySpecialChars() mysqlx0.Database = schemaName; mysqlx0.CharacterSet = "utf8mb4"; mysqlx0.SslMode = MySqlSslMode.Required; - mysqlx0.ConnectTimeout = 10; + mysqlx0.ConnectTimeout = 1000; mysqlx0.Keepalive = 10; mysqlx0.CertificateFile = sslCa; mysqlx0.CertificatePassword = sslCertificatePassword; @@ -2016,7 +2016,7 @@ public void ConnectionAttributesKeyWithUnderLineChars() mysqlx0.Database = schemaName; mysqlx0.CharacterSet = "utf8mb4"; mysqlx0.SslMode = MySqlSslMode.Required; - mysqlx0.ConnectTimeout = 10; + mysqlx0.ConnectTimeout = 1000; mysqlx0.Keepalive = 10; mysqlx0.CertificateFile = sslCa; mysqlx0.CertificatePassword = sslCertificatePassword; @@ -2043,7 +2043,7 @@ public void ConnectionAttributesKeyWithUnderLineChars() mysqlx0.Database = schemaName; mysqlx0.CharacterSet = "utf8mb4"; mysqlx0.SslMode = MySqlSslMode.Required; - mysqlx0.ConnectTimeout = 10; + mysqlx0.ConnectTimeout = 1000; mysqlx0.Keepalive = 10; mysqlx0.CertificateFile = sslCa; mysqlx0.CertificatePassword = sslCertificatePassword; @@ -2088,7 +2088,7 @@ public void ConnectionAttributesKeyBlankChars() mysqlx0.Database = schemaName; mysqlx0.CharacterSet = "utf8mb4"; mysqlx0.SslMode = MySqlSslMode.Required; - mysqlx0.ConnectTimeout = 10; + mysqlx0.ConnectTimeout = 1000; mysqlx0.Keepalive = 10; mysqlx0.CertificateFile = sslCa; mysqlx0.CertificatePassword = sslCertificatePassword; @@ -2115,7 +2115,7 @@ public void ConnectionAttributesKeyBlankChars() mysqlx0.Database = schemaName; mysqlx0.CharacterSet = "utf8mb4"; mysqlx0.SslMode = MySqlSslMode.Required; - mysqlx0.ConnectTimeout = 10; + mysqlx0.ConnectTimeout = 1000; mysqlx0.Keepalive = 10; mysqlx0.CertificateFile = sslCa; mysqlx0.CertificatePassword = sslCertificatePassword; @@ -2159,7 +2159,7 @@ public void ConnectionAttributesValue1025Chars() mysqlx0.Database = schemaName; mysqlx0.CharacterSet = "utf8mb4"; mysqlx0.SslMode = MySqlSslMode.Required; - mysqlx0.ConnectTimeout = 10; + mysqlx0.ConnectTimeout = 1000; mysqlx0.Keepalive = 10; mysqlx0.CertificateFile = sslCa; mysqlx0.CertificatePassword = sslCertificatePassword; @@ -2185,7 +2185,7 @@ public void ConnectionAttributesValue1025Chars() mysqlx0.Database = schemaName; mysqlx0.CharacterSet = "utf8mb4"; mysqlx0.SslMode = MySqlSslMode.Required; - mysqlx0.ConnectTimeout = 10; + mysqlx0.ConnectTimeout = 1000; mysqlx0.Keepalive = 10; mysqlx0.CertificateFile = sslCa; mysqlx0.CertificatePassword = sslCertificatePassword; diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/MockServer.cs b/MySQL.Data/tests/MySqlX.Data.Tests/MockServer.cs new file mode 100644 index 000000000..d600576b6 --- /dev/null +++ b/MySQL.Data/tests/MySqlX.Data.Tests/MockServer.cs @@ -0,0 +1,138 @@ +// Copyright © 2025, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using System; +using System.Net; +using System.Net.Sockets; +using System.Threading; +using System.Threading.Tasks; + +namespace MySqlX.Data.Tests +{ + public class MockServer + { + private TcpListener listener; + + private int _port; + + private IPAddress _address; + + private ManualResetEvent _stopserver = new ManualResetEvent(false); + + private CancellationTokenSource cts; + + private bool _usetimeout; + + public int Port + { + get => _port; + set => _port = value; + } + + public IPAddress Address + { + get => _address; + set => _address = value; + } + + public MockServer(bool usetimeout) + { + GetMockServerInfo(); + _stopserver.Reset(); + _usetimeout = usetimeout; + cts = new CancellationTokenSource(TimeSpan.FromSeconds(12)); + } + + public void GetMockServerInfo() + { + TcpListener loopback = new TcpListener(IPAddress.Loopback, 0); + loopback.Start(); + _port = ((IPEndPoint)loopback.LocalEndpoint).Port; + loopback.Stop(); + _address = Dns.GetHostEntry("localhost").AddressList[0]; + } + + public void StopServer() + { + _stopserver.Set(); + } + public void DisposeListener() + { + if (listener != null) + { + listener.Stop(); + } + } + + public async Task ServerWorker(CancellationToken ct) + { + await Task.Run(() => + { + IPEndPoint endpoint = new IPEndPoint(IPAddress.Loopback, Port); + listener = new(endpoint); + + try + { + listener.Start(); + while (!_stopserver.WaitOne(1)) + { + listener.BeginAcceptSocket(new AsyncCallback(beginConnection), null); + } + } + catch (Exception) + { + } + finally + { + listener.Stop(); + } + }, ct).ConfigureAwait(false); + } + + public void StartServer() + { + ServerWorker(cts.Token).ConfigureAwait(false); + } + + private void beginConnection(IAsyncResult iar) + { + try + { + Socket client = listener.EndAcceptSocket(iar); + if (_usetimeout) + { + Task.Delay(500).Wait(); + client.Close(); + } + } + catch (Exception) + { + } + } + } +} \ No newline at end of file diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/SessionTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/SessionTests.cs index b8487b464..d4bdfe89a 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/SessionTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/SessionTests.cs @@ -32,7 +32,6 @@ using MySqlX.XDevAPI; using MySqlX.XDevAPI.Relational; using NUnit.Framework; -using NUnit.Framework.Legacy; using System; using System.Collections.Generic; using System.Data; @@ -476,12 +475,56 @@ public void GetUri() } } + /// + /// WL #16033 Fix timeout tests + /// + [Test] + [Property("Category", "Security")] + [TestCase($"server=_server;user=test;password=test;port=_port;connect-timeout=0;", 0, 1000, true, true)] + [TestCase($"server=_server;user=test;password=test;port=_port;", 8, 25, true)] + [TestCase($"server=_server,server_;port=port_;user=test;password=test;", 0, 25, false)] + [TestCase($"server=_server;user=test;password=test;port=_port;connect-timeout=5000;", 3, 15, true)] + [TestCase($"mysqlx://test:test@[_server:_port]", 0, 25, true, false, true)] + public void ConnectionTimeout(string connstring,int min,int max,bool failure, bool usemockservertimeout=false, bool isUri=false) + { + MockServer mServer = new MockServer(usemockservertimeout); + mServer.StartServer(); + + if (failure) + { + if (isUri) + { + if (Uri.TryCreate(connstring, UriKind.Absolute, out _)) + { + TestConnectTimeoutFailureTimeout(connstring.Replace("_server", mServer.Address.ToString()).Replace("_port", mServer.Port.ToString()), min, max, "default timeout", usemockservertimeout); + } + else + { + mServer.StopServer(); + mServer.DisposeListener(); + Assert.Ignore("not parseable Uri: "+ connstring); + } + } + else + { + TestConnectTimeoutFailureTimeout(connstring.Replace("_server", mServer.Address.ToString()).Replace("_port", mServer.Port.ToString()), min, max, "default timeout", usemockservertimeout); + } + } + else + { + connstring = connstring.Replace("_server", mServer.Address.ToString()).Replace("_port", mServer.Port.ToString()).Replace("server_", Host).Replace("port_", XPort); + TestConnectTimeoutSuccessTimeout(connstring, min, max, "Fail over success"); + } + mServer.StopServer(); + mServer.DisposeListener(); + } + /// /// WL #12177 Implement connect timeout /// [Test] [Property("Category", "Security")] - public void ConnectTimeout() + public void ConnectTimeoutParameterValidation() { Assume.That(!Platform.IsMacOSX(), "Check failure on MacOS: (() => MySQLX.GetSession(conn)); TimeSpan diff = DateTime.Now.Subtract(start); - Assert.That(diff.TotalSeconds > 19 && diff.TotalSeconds < 21, String.Format("Timeout exceeded ({0}). Actual time: {1}", "Fail over failure", diff)); + Assert.That(diff.TotalSeconds > 1 && diff.TotalSeconds < 45, String.Format("Timeout exceeded ({0}). Actual time: {1}", "Fail over failure", diff)); + mServer1.StopServer(); + mServer1.DisposeListener(); + mServer2.StopServer(); + mServer2.DisposeListener(); // Valid session no time out start = DateTime.Now; - using (Session session = MySQLX.GetSession(ConnectionStringUri + "?connecttimeout=2000")) + using (Session session = MySQLX.GetSession(ConnectionStringUri+ "?connecttimeout=0")) session.SQL("SELECT SLEEP(10)").Execute(); diff = DateTime.Now.Subtract(start); Assert.That(diff.TotalSeconds > 10); @@ -579,10 +646,13 @@ public void ConnectTimeout() Assert.That(exception, Is.Not.Null); } - private void TestConnectTimeoutFailureTimeout(String connString, int minTime, int maxTime, string test) + private void TestConnectTimeoutFailureTimeout(String connString, int minTime, int maxTime, string test, bool usingmocktimeout) { DateTime start = DateTime.Now; - Assert.Throws(() => MySQLX.GetSession(connString)); + if(usingmocktimeout) + Assert.Throws(() => MySQLX.GetSession(connString)); + else + Assert.Throws(() => MySQLX.GetSession(connString)); TimeSpan diff = DateTime.Now.Subtract(start); Assert.That(diff.TotalSeconds > minTime && diff.TotalSeconds < maxTime, String.Format("Timeout exceeded ({0}). Actual time: {1}", test, diff)); } @@ -1572,15 +1642,25 @@ public void TimeoutReachingMaxSizePool() [Test, Description("scenario 0(connectionString,connectionUri,Anonymous Object)-Without connect timeout and max timeout should be 10s")] public void TimeoutWithWrongHost() { - string serverName = "vigdis07.no.oracle.com"; - string connStr = "server=" + serverName + ";user=" + session.Settings.UserID + ";port=" + XPort + ";password=" - + session.Settings.Password + ";"; - TestConnectStringTimeoutFailureTimeout(connStr, 0, 11, "Timeout value between 9 and 11 seconds"); - connStr = "mysqlx://" + session.Settings.UserID + ":" + session.Settings.Password + "@" + serverName + ":" + XPort; - TestConnectStringTimeoutFailureTimeout(connStr, 0, 11, "Timeout value between 9 and 11 seconds"); - var connObj = new { server = serverName, port = XPort, user = session.Settings.UserID, password = session.Settings.Password }; - TestConnectObjTimeoutFailureTimeout(connObj, 0, 11, "Timeout value between 9 and 11 seconds"); + MockServer mServer= new MockServer(false); + mServer.StartServer(); + string connStr = $"server={mServer.Address.ToString()};user={session.Settings.UserID};port={mServer.Port.ToString()};password={ session.Settings.Password};"; + TestConnectStringTimeoutFailureTimeout(connStr, 9, 20, "Timeout value between 9 and 20 seconds"); + mServer.StopServer(); + mServer.DisposeListener(); + + mServer = new MockServer(false); + mServer.StartServer(); + connStr = $"mysqlx://{session.Settings.UserID}:{ session.Settings.Password}@{mServer.Address.ToString()}:{mServer.Port.ToString()}"; + if(Uri.TryCreate(connStr, UriKind.Absolute, out _)) + TestConnectStringTimeoutFailureTimeout(connStr, 9, 20, "Timeout value between 9 and 20 seconds"); + + var connObj = new { server = mServer.Address.ToString(), port = mServer.Port.ToString(), user = session.Settings.UserID, password = session.Settings.Password }; + TestConnectObjTimeoutFailureTimeout(connObj, 9, 20, "Timeout value between 9 and 20 seconds"); + + mServer.StopServer(); + mServer.DisposeListener(); } [Test, Description("scenario 1(connectionString,connectionUri,Anonymous Object)")] @@ -1632,7 +1712,7 @@ public void NoTimeoutWithManyOptions() public void TimeoutSuccessWithStringBuilder() { var connStrBuilder = new MySqlXConnectionStringBuilder(); - connStrBuilder.ConnectTimeout = 9000; + connStrBuilder.ConnectTimeout = 2000; connStrBuilder.UserID = session.Settings.UserID; connStrBuilder.Password = session.Settings.Password; connStrBuilder.Port = Convert.ToUInt32(XPort); @@ -1689,7 +1769,7 @@ public void TimeoutIncreasingUntilConnect() "database=" + schemaName + ";characterset=utf8mb4;sslmode=VerifyCA;ssl-ca=" + sslCa + $";certificatepassword={sslCertificatePassword};certificatestorelocation=LocalMachine;" + ";auth=PLAIN;certificatethumbprint=;" - + "connect-timeout=" + i; + + "connect-timeout=" + (i * 1000); mysqlx0 = new MySqlXConnectionStringBuilder(connStr); using (var conn = MySQLX.GetSession(mysqlx0.ConnectionString)) { @@ -1714,7 +1794,7 @@ public void TimeoutIncreasingUntilConnect() mysqlx0.CertificateStoreLocation = MySqlCertificateStoreLocation.LocalMachine; mysqlx0.Auth = MySqlAuthenticationMode.PLAIN; mysqlx0.CertificateThumbprint = ""; - mysqlx0.ConnectTimeout = (uint)i; + mysqlx0.ConnectTimeout = (uint)(i * 1000); using (var conn = MySQLX.GetSession(mysqlx0.ConnectionString)) { @@ -1727,7 +1807,7 @@ public void TimeoutIncreasingUntilConnect() [Test, Description("scenario 1(connectionString,connectionUri,Anonymous Object with default timeout)")] public void ValidateDefaultTimeoutParameter() { - uint defaultTimeout = 1; + uint defaultTimeout = 1000; string connStr = ConnectionString + ";" + "connect-timeout=" + defaultTimeout; for (int i = 0; i < 10; i++) { @@ -1757,7 +1837,7 @@ public void ValidateDefaultTimeoutParameter() [Test, Description("scenario 2(MysqlxStringBuilder with default timeout)")] public void ValidateDefaultTimeoutParameterWithStringBuilder() { - uint defaultTimeout = 1; + uint defaultTimeout = 1000; var connStrBuilder = new MySqlXConnectionStringBuilder(); connStrBuilder.ConnectTimeout = defaultTimeout; connStrBuilder.UserID = session.Settings.UserID; @@ -1785,26 +1865,34 @@ public void ValidateDefaultTimeoutParameterWithStringBuilder() [Test, Description("scenario 1(MysqlxStringBuilder with connect timeout option for offline server)")] public void TimeoutOfflineServerWithStringBuilder() { + MockServer mServer = new MockServer(false); + mServer.StartServer(); + int connectionTimeout = 2000; - string serverName = "vigdis07.no.oracle.com"; var connStrBuilder = new MySqlXConnectionStringBuilder(); connStrBuilder.ConnectTimeout = (uint)connectionTimeout; connStrBuilder.UserID = session.Settings.UserID; connStrBuilder.Password = session.Settings.Password; - connStrBuilder.Port = Convert.ToUInt32(XPort); - connStrBuilder.Server = serverName; + connStrBuilder.Port = Convert.ToUInt32(mServer.Port); + connStrBuilder.Server = mServer.Address.ToString(); TestConnectStringTimeoutFailureTimeout(connStrBuilder.ConnectionString, 0, 21, "Offline host timeout value in between 1 and 21 seconds"); + mServer.StopServer(); + mServer.DisposeListener(); - string connStr = "server=" + serverName + ";user=" + session.Settings.UserID + ";port=" + XPort + ";password=" - + session.Settings.Password + ";" + "connect-timeout=" + connectionTimeout; + mServer = new MockServer(false); + mServer.StartServer(); + string connStr = $"server={mServer.Address.ToString()};user={session.Settings.UserID}; port={mServer.Port.ToString()};password={session.Settings.Password};connect-timeout={connectionTimeout}"; connStrBuilder = new MySqlXConnectionStringBuilder(connStr); TestConnectStringTimeoutFailureTimeout(connStrBuilder.ConnectionString, 0, 21, "Offline host timeout value in between 1 and 21 seconds"); + + mServer.StopServer(); + mServer.DisposeListener(); } [Test, Description("scenario 1(connectionString,connectionUri,Anonymous Object,MysqlxStringBuilder with connect timeout option=1 for online server)")] public void TimeoutSuccessConnectOptionOne() { - int connectionTimeout = 1; + int connectionTimeout = 2000; string connStr = ConnectionString + ";" + "connect-timeout=" + connectionTimeout; TestConnectStringTimeoutSuccessTimeout(connStr, 0, 5, "Checking the timeout between 0 to 5 seconds"); connStr = ConnectionStringUri + "?connect-timeout=" + connectionTimeout; @@ -1829,32 +1917,52 @@ public void TimeoutSuccessConnectOptionOne() [Test, Description("scenario 1(connectionString,connectionUri,Anonymous Object,MysqlxStringBuilder with connect timeout option=0 for offline server)")] public void TimeoutOfflineServerConnectOptionZero() { + //, Ignore("Disabling the connection timeout will wait until the OS closes the socket, which can take several time.") + MockServer mServer = new MockServer(true); + mServer.StartServer(); int connectionTimeout = 0; - string serverName = "vigdis07.no.oracle.com"; - - string connStr = "server=" + serverName + ";user=" + session.Settings.UserID + ";port=" + XPort + ";password=" - + session.Settings.Password + ";" + "connect-timeout=" + connectionTimeout; - TestConnectStringTimeoutFailureTimeout(connStr, 0, 50000, "Checking the timeout between 0 to 50000 milliseconds"); - - connStr = "mysqlx://" + session.Settings.UserID + ":" + session.Settings.Password + "@" + serverName + ":" + XPort + "?connect-timeout=" + connectionTimeout; - TestConnectStringTimeoutFailureTimeout(connStr, 0, 50000, "Checking the timeout between 0 to 50000 milliseconds"); - - var connObj = new { server = serverName, port = XPort, user = session.Settings.UserID, password = session.Settings.Password, connecttimeout = connectionTimeout }; - TestConnectObjTimeoutFailureTimeout(connObj, 0, 50000, "Checking the timeout between 0 to 50000 milliseconds"); + string connStr = $"server={mServer.Address.ToString()};user={session.Settings.UserID};port={mServer.Port.ToString()};password={session.Settings.Password};connect-timeout={connectionTimeout}"; + TestConnectStringTimeoutFailureNoConnectTimeout(connStr, 0, 50000, "Checking the timeout between 0 to 50000 milliseconds"); + mServer.StopServer(); + mServer.DisposeListener(); + + mServer = new MockServer(true); + mServer.StartServer(); + connStr = $"mysqlx://{session.Settings.UserID}:{session.Settings.Password}@[{mServer.Address.ToString()}:{mServer.Port.ToString()}]/?connect-timeout=" + connectionTimeout; + if (Uri.TryCreate(connStr,UriKind.Absolute, out _)) + TestConnectStringTimeoutFailureNoConnectTimeout(connStr, 0, 50000, "Checking the timeout between 0 to 50000 milliseconds"); + + mServer.StopServer(); + mServer.DisposeListener(); + + mServer = new MockServer(true); + mServer.StartServer(); + var connObj = new { server = mServer.Address.ToString(), port = mServer.Port.ToString(), user = session.Settings.UserID, password = session.Settings.Password, connecttimeout = connectionTimeout }; + TestConnectObjTimeoutFailureNoTimeout(connObj, 0, 50000, "Checking the timeout between 0 to 50000 milliseconds"); + mServer.StopServer(); + mServer.DisposeListener(); + + mServer = new MockServer(true); + mServer.StartServer(); var connStrBuilder = new MySqlXConnectionStringBuilder(); connStrBuilder.ConnectTimeout = (uint)connectionTimeout; connStrBuilder.UserID = session.Settings.UserID; connStrBuilder.Password = session.Settings.Password; - connStrBuilder.Port = Convert.ToUInt32(XPort); - connStrBuilder.Server = serverName; - TestConnectStringTimeoutFailureTimeout(connStr, 0, 50000, "Checking the timeout between 0 to 50000 milliseconds"); - - connStr = "server=" + serverName + ";user=" + session.Settings.UserID + ";port=" + XPort + ";password=" - + session.Settings.Password + ";" + "connect-timeout=" + connectionTimeout; + connStrBuilder.Port = (uint)mServer.Port; + connStrBuilder.Server = mServer.Address.ToString(); + TestConnectStringTimeoutFailureNoConnectTimeout(connStrBuilder.ConnectionString, 0, 50000, "Checking the timeout between 0 to 50000 milliseconds"); + mServer.StopServer(); + mServer.DisposeListener(); + + mServer = new MockServer(true); + mServer.StartServer(); + connStr = $"server={mServer.Address.ToString()};user={session.Settings.UserID};port={mServer.Port.ToString()};password={session.Settings.Password};connect-timeout={connectionTimeout}"; connStrBuilder = new MySqlXConnectionStringBuilder(connStr); - TestConnectStringTimeoutFailureTimeout(connStr, 0, 50000, "Checking the timeout between 0 to 50000 milliseconds"); + TestConnectStringTimeoutFailureNoConnectTimeout(connStr, 0, 50000, "Checking the timeout between 0 to 50000 milliseconds"); + mServer.StopServer(); + mServer.DisposeListener(); } [Test, Description("(connectionString,connectionUri,Anonymous Object.Test that the timeout will be reset for each connection attempt in a failover scenario")] @@ -2093,33 +2201,36 @@ public void WrongPasswordException() } } - [Test, Description("Test the default connect timeout with offline server with concurrent connections")] - [Ignore("Test its not well implemented")] // TO DO + [Test, Description("Test the default connect timeout with mock server with concurrent connections")] public async Task ConnectTimeoutConcurrentConnections() { - await Task.Run(() => SubThread1()); - await Task.Run(() => SubThread2()); + MockServer mServer = new MockServer(false); + mServer.StartServer(); + + await Task.Run(() => SubThread1(mServer.Address.ToString(), mServer.Port.ToString())); + await Task.Run(() => SubThread2(mServer.Address.ToString(), mServer.Port.ToString())); + + mServer.StopServer(); + mServer.DisposeListener(); } - private void SubThread1() + private void SubThread1(string address, string port) { - string serverName = "vigdis07.no.oracle.com"; for (int i = 0; i < 5; i++) { - string connStr = "server=" + serverName + ";user=" + session.Settings.UserID + ";port=" + XPort + ";password=" + string connStr = "server=" + address + ";user=" + session.Settings.UserID + ";port=" + port + ";password=" + session.Settings.Password + ";" + "connect-timeout=2000;"; - TestConnectStringTimeoutFailureTimeout(connStr, 0, 5, "Timeout value between 1 and 3 second"); + TestConnectStringTimeoutFailureTimeout(connStr, 1, 5, "Timeout value between 1 and 3 second"); } } - private void SubThread2() + private void SubThread2(string address, string port) { - string serverName = "vigdis07.no.oracle.com"; for (int i = 0; i < 5; i++) { - string connStr = "server=" + serverName + ";user=" + session.Settings.UserID + ";port=" + XPort + ";password=" + string connStr = "server=" + address + ";user=" + session.Settings.UserID + ";port=" + port + ";password=" + session.Settings.Password + ";" + "connect-timeout=2000;"; - TestConnectStringTimeoutFailureTimeout(connStr, 0, 5, "Timeout value between 1 and 3 second"); + TestConnectStringTimeoutFailureTimeout(connStr, 1, 5, "Timeout value between 1 and 3 second"); } } @@ -2256,7 +2367,16 @@ public void TestConnectObjTimeoutFailureTimeout(object connString, int minTime, { Stopwatch sw = new Stopwatch(); sw.Start(); - Assert.Catch(() => MySQLX.GetSession(connString)); + Assert.Throws(() => MySQLX.GetSession(connString)); + sw.Stop(); + Assert.That(sw.Elapsed.Seconds >= minTime && sw.Elapsed.Seconds < maxTime, String.Format("Timeout exceeded ({0}). Actual time: {1}", test, sw.Elapsed)); + } + + public void TestConnectObjTimeoutFailureNoTimeout(object connString, int minTime, int maxTime, string test) + { + Stopwatch sw = new Stopwatch(); + sw.Start(); + Assert.Throws(() => MySQLX.GetSession(connString)); sw.Stop(); Assert.That(sw.Elapsed.Seconds >= minTime && sw.Elapsed.Seconds < maxTime, String.Format("Timeout exceeded ({0}). Actual time: {1}", test, sw.Elapsed)); } @@ -2265,7 +2385,16 @@ public void TestConnectStringTimeoutFailureTimeout(String connString, int minTim { Stopwatch sw = new Stopwatch(); sw.Start(); - Assert.Catch(() => MySQLX.GetSession(connString)); + Assert.Throws(() => MySQLX.GetSession(connString)); + sw.Stop(); + Assert.That(sw.Elapsed.Seconds >= minTime && sw.Elapsed.Seconds < maxTime, String.Format("Timeout exceeded ({0}). Actual time: {1}", test, sw.Elapsed)); + } + + public void TestConnectStringTimeoutFailureNoConnectTimeout(String connString, int minTime, int maxTime, string test) + { + Stopwatch sw = new Stopwatch(); + sw.Start(); + Assert.Throws(() => MySQLX.GetSession(connString)); sw.Stop(); Assert.That(sw.Elapsed.Seconds >= minTime && sw.Elapsed.Seconds < maxTime, String.Format("Timeout exceeded ({0}). Actual time: {1}", test, sw.Elapsed)); } From f206d3a55aeabc01cb2a95f01649296028caf0f3 Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Sat, 8 Mar 2025 14:26:00 -0700 Subject: [PATCH 104/125] WL#16852 [Update 3rd party libraries and remove references in Connector/NET bundles] Change-Id: I9a933ad84826892b1b01d79e0949e62ef3d7cd11 --- CHANGES | 1 + Dependencies/MITLibs/comerr64.dll | Bin 26184 -> 26176 bytes Dependencies/MITLibs/gssapi64.dll | Bin 400456 -> 403016 bytes Dependencies/MITLibs/k5sprt64.dll | Bin 74312 -> 69184 bytes Dependencies/MITLibs/krb5_64.dll | Bin 1233480 -> 1224256 bytes Dependencies/MITLibs/krbcc64.dll | Bin 122440 -> 121920 bytes .../src/MySQL.Data.OpenTelemetry.csproj | 2 +- MySQL.Data/src/MySql.Data.csproj | 8 +- .../src/X/Protocol/X/Protobuf/Mysqlx.cs | 44 ++++- .../X/Protocol/X/Protobuf/MysqlxConnection.cs | 67 ++++++- .../src/X/Protocol/X/Protobuf/MysqlxCrud.cs | 166 ++++++++++++++++-- .../src/X/Protocol/X/Protobuf/MysqlxCursor.cs | 45 ++++- .../X/Protocol/X/Protobuf/MysqlxDatatypes.cs | 78 +++++++- .../src/X/Protocol/X/Protobuf/MysqlxExpect.cs | 34 +++- .../src/X/Protocol/X/Protobuf/MysqlxExpr.cs | 102 +++++++++-- .../src/X/Protocol/X/Protobuf/MysqlxNotice.cs | 66 ++++++- .../X/Protocol/X/Protobuf/MysqlxPrepare.cs | 45 ++++- .../X/Protocol/X/Protobuf/MysqlxResultset.cs | 67 ++++++- .../X/Protocol/X/Protobuf/MysqlxSession.cs | 56 +++++- .../src/X/Protocol/X/Protobuf/MysqlxSql.cs | 23 ++- 20 files changed, 727 insertions(+), 77 deletions(-) diff --git a/CHANGES b/CHANGES index 410886323..93ada122e 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,7 @@ 9.3.0 - Fixed bug MySql.EntityFrameworkCore.dll in NuGet packages is not signed (Oracle Bug #37503859). - Fixed some tests due to incorrect implementation (WL16033). +- Updated third party dependencies (WL16852). 9.2.0 diff --git a/Dependencies/MITLibs/comerr64.dll b/Dependencies/MITLibs/comerr64.dll index 0a48cb5b62db1a835b18620e3ff69042dc4d5753..70753cc798da972b571d882f069716284d9df20a 100644 GIT binary patch delta 3282 zcmZWq2T)V#7QQzLA(V*pE?pw5kkAoDsx%P@9abR11w%KDfJkUkL0etfkI0g221Xy z@kC;E_&;BUC_7@DZ)b>BMcnz0brF+%ya$?w-{)f)So57%6s`HrPbAiaf9CUwKjIZd ztH0+fiUx+S*HIL${chulq5Ic0fFIA@9st6!kODw^&&CL*D7YJ5HvupML2Gd<1V6+b z0A7Q9v;+VvP7??RK`TxR%ndBWqAnr?l;Hd%4odYE41CIYs~&-fNC2Wp`;3XPlwdN2 z6df9$2si*y#_I+|BE^w{NkH_^h$tvAm;^--$rOkL0DeFD2#7+CheCd8wp0=cilw-d;zIcj zr!YW|8HG_4%Y^-ivx%cy1Hl{?1_Gr&An=rETS7dAN`h?TV)?=pV3jGRBQK2*;CpT7t9?xiUQRFo)Cp;sUyF|;NNnNJT+ zKZgG^#Q))ACc#7>4F?dw`qaK7^R!7QXvqXkH9!T9mZ>%fHv)v2Zf0s|Ltrbg4}bs) zKmc&eTr)1*jPHps*ZMzCjkzai#91~+!I&H2avX5`8mMB0;n#=30BkzO2q~nK<(Tye z4GO}l(lJ_mN{y*viC5+E2rEwWt`&jX`{BK8n!!wWQU~OBtY|Amu55z~m&z%$Y(@+4 zOUQra*zFbt8IpI{W0P}fQ-RRP&hy#dltv8~fb6AP$@FZ)4~9 zBZ!9V@*97B&hiqbLrw|0pW0sjVe}-)kzria{obMVmOM$w_2{eoX5oodi+Q@v`^)>c z+ep4=loEhXUYz|bWBiK@nc&=~WA{zx6Lxi&72uZ`Q%{UPI4i|<^5hXCO_+@K%uT{$ z((mV4#h8)%&DxJNyId6Z?6=I^W^p08ebF&lw@nVa*3{Eq`ucX}3cGDEk7IM~h(5z^ z*jok5rJZ5kUc7qSIr~0OQAe!#wKbzd(E@TFmg|w==<-+f_`>!g8 zY{6-J)!vFXK>f~4>^+dGm#bJhd!7-i(3zFHbL%<0`dz$#Dk0?Hxz!Ek9vAD`<=x+2 zy}{AZSKr>^Y0^5fvaL@)H5?$8B^H=HE@P+5nq$*tjgi8-NDu+0o5JBBE?t(t2eN8E z=e52XvJ!l10}O=Y#MUPnlH~|Oa0HA$No)dAL??^6+YQU$NjOy)&k~U20qy0?x5a8B zKFU@Xdv@9~O5)Eh)-HL$HhNu9E>-NCBF%7F)0^0@d*#Foum(mrEY1{bYGhz!7EqNg z3CE@*yRhkq>MA%4guyn7G>3NubTC-i*OqyR=Z1)1H%WxAABq#f3L)X%2Ek0IUs@?yjb)irusx4VRR)BSsKyAreK^ix>luDTJ7K zRen26k05nMcO<#;BTKE}B(@_k=7s+st*=%KRpbV8EFw#v*YvFlV^wV>x={m^T?svT z3r)DW#26<(f^M^6-gt$`coNIO*U-h{w(TkVB}A_(KH7v*$^-RA{{4b|0*%cyQI9=i#5< zz1#EcXc<@alHbkb%;Ap7X^(MCfN%G)Ec&O{I5}5_2Yos@Go$2S&fLqr&Jre?$hIrLz{f(9cA;A%>C#NUQ5T2Ti_N>HFy;Y7ttgB zDp~e}0E4JN9V@D{d-j)OWr4K}HANTx*6t2kx89E#-RiG?wxe53^O1ysvx0H3+OR4- z_t1g%?ao9p^&VY(Ww4p$dV0Z(9F&`TZ#hWg4(-Nr_C|Wz(V0tX^9-aGtwI1bq`PD&%ZFvpM0>sDt98J9YI=&x7pjdpo1OMD4pG8wagSHlLr~WAf6(Kx!n< zRL$6i=k5&f0w27&>WfloJ+H{s**AYEe`HnLdp=smO`A1*lCjxkM5c6n_>}nFv|Q4+ z)3#ZNOw8Oe^9jCCs?zs2c)|vZbU}DcXwahD2^CsZAScrk4l;H$ZBn6?20k~-lyJCj zTli6&TfPUSJb`f=n|gRK&1G{?1AQ{DusAVvWk8+nqw^TErJu8e4By-Aofc=kRKLUM zlvi;&q$~Od-iFPjm0Z8@wR>xAjcbgKkHu}Itl)^G-la|1qr4#Mh5nJ>Zx5$PM{-_v z9d4)(P}Oxl`VPh*WUrkQwL(#rZWd-Y>TBNFmQGLH)|tN3OA7V@-^=zWJG zkGQX62}}8MuJf{`cm8)h?fS@tXFu4&XLbs6MCLp4Vx1l{o4!7yg1~}fmJg2tSoU_SGWzw1G;hi@QJVTSis@^Hzq+E8Q*)5o&j@orxcus(*%_3j4B_b~Fcl-UGdqqxlp*v4r}#gLO`< zPi88SA%Yo~I)*=GFpFf?NjjU3J_!-tzyDsbcpns?bS$!n_5qf!e|3=JQT5mMkeG(J z0Ay&n`$D_L+!v}#@Brq8<+0S>t~qK;P2Eii2CfRGZZ4o4)Lj&OZ-r z4%zp-HhoHAQFU&PQ0VWFRKeY#_COoiMsvbFZ9#2i^o`Bv>&&t9L+YphK2g}BuYoT@ zGrGD?ThRPk`le|Q2R<|OH@(aU9BLMqdmJj8d|D=1ysf!MB$TrE2F*q$X!p{(j+=YA z_Vp<}_!@MthgY$kw{~MxNwMMONvQC6UI*%PSSY=I>w>ThL$bVT0In`vd_;~&=|p{ zR5~*-n#qVDABhL>0L^s6ff$S^Mj!*AePhs|_&^3kp+++y1_1bc!zmCm`Upg(hEmA@ z^BWrd9U9K-(9<^l8L*FtiiVs>^pFS$V8R?BrYk9$>98RL0KEuLC;}oyLvArlhy?&J z-WGj%hhe~;0g;&h1?>P}3ho+3CPm;G5CpV<_$WpsiRlJKN0TU!;M8yrXE&y)QM7ZZ^Gu7WoZ3)$)RBmp7Ur2WOk5%wn$%_J{?vbJrpYK8F>Rta-)x z(=QbATJ081i@Gp=6!fbw)pb=P=IlkH`9-v7+3zCM3XY;RhNEaHEM_PSB0!Eg91dbR zih_HfsPnB~8&^Y7K>%%qfpDz!Mkj;PoInVUfC)N@i4zt_rSV+dF>IjB{;rZ++ZyBD z)^zE2&c-b}>mEJ3;OEm>+-?9T7Tkr&z@+zPB;hCO=P%9z%_Hu{HV{d%_WS-Oi3{|}SaA$e819AO zt-1%P;xLvtEM{~0DN34{V6iwX&cxKx)Y1=w=dnCAb#`F1HrR04?fa<|sy)PDY7nWB zP&AVic|=1{4o(BDf#dxUpvitXQ>|;&b77v=mUBz8uPY`qq!ZKU^Whp^)I0T&)xRvNQY_O*DDjchSu_S6%OV zf1TX8MQHj#QQ9iO-ttk%iuc2jPht~tks++M;;;GL(V7d!T}B#DQ|sAJ=0pZYZ$9^T zp=0w6vL@`Rp#085)1VACn6OtVi~N|JIH0r zKF^7N82sDJXu^#?imXVS6izQ=NUJ}mA`O!)a;NakGQ?UqSGK%iHD zl9GWh{D&3)w+_)N$CIBvK)fEXisQZX%##Z~@#iDb+DWY3`y%oC)~I~BVb3yt3IPtX zy)L4Z7w`)#A9KuF%p3PXuJ+v8mjcUDor%wk6UE(e10iejt7cu!2Y0eE$X-aiC9p;v zxLazlTDiBg7bulgZ79whV$I)A5sw!QhZCqt`!)Ob zs&tmVPjqT}c1j}8eNSlq6@M7v-Rak-$DXLCfgxo;*R&rqM$&pTKBGegEb3KaYo|Ol z^9w9gXe3MY;B9w5@HZXswXrYRcDcLvUiWILY+!iv?;{IB-M+(m!G?d@^%8EZ?~EenL{yMxbKQ*6IUN4r_<060HNpY@2kV(pj_Mgk}swD@<@dqvNeU4LhW=G>LeLXi- z#QeeNg_>%%-yOA*Ke}dnv})Z;Z$4wIlpMTmT(T5cqgT{gXvFpD44Pzlv%^1j6_mJa zf!*Ph^(qS`wjOQ%;iq3BK24n-@GHJ^rX#0q+hO~~N2saS!5>(Nmp31;{wP*^Bzd;z zIO~ll+~090xmL%b2<+c$^Pxgjk9L zv-!uouS@)EOz{qoZQ0+CHjLrMpxk_Hkuop|tO`aMvkjwwkXuOCa!WJeoHD(T|Le_@ zh0}kjBt~P5zl~oc0;`44C{9Q=&yF!&Tud3hK6{Wr5b?<+trOk{IGUPFWnc!+V9dYI zZj9B(=wf!TF@nh7KaIBI^fNW;Uh7)5E8kvopJ1t=Lms)N#Q2=mZoani{XE@#nPGsv zlLaCD`86n|dEnJRmNufe=GuET?EaIIuy|hVuI%ONA+4Iid9Je;{jnp28)TL|G^Q{&i>c7STPUv(BY6x{>W-qjKAA z)A5hL5nh|pJI_Ps|$*eSq zpB13+48Oa&25-)}Frr6rNpVrt5?dP{`wi`Fr$HGxINo=_usv#LAB{#{W~H^1`K6vb zO(MqVk(cT7U(FU)`Bq^KQ4O)esFG*PPG5F$GlLl8bA9t&wUW;dHDhBejs~O}Mn?=- z@3=7xboDGa5XPs<~4hzr!0oEB2_=*{!%rUXrr&bgr&s8al(bVqfHg`<#f^d!@EDup&N47}Phd zbt!eoLpcgAP1ReUpQ~`;req}ZnSZv`j|Sdv&{K(8ZO#s<{9 diff --git a/Dependencies/MITLibs/gssapi64.dll b/Dependencies/MITLibs/gssapi64.dll index 1628e3842faa02d29fc6e038f8c2d03bf5b53d64..21d6feb388ac6ff5caef6b101a22ac4003d430e0 100644 GIT binary patch delta 124767 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
Ed@$y>~&n3GohxKu5l!?ocKV^YBu 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

7tPRT-II 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

{{__global.namespace}}: {{{namespace.specName.0.value}}}
{{__global.assembly}}: {{assemblies.0}}.dll
-
Version: 9.3.0
+
Version: 9.4.0
{{__global.syntax}}
{{syntax.content.0.value}}
diff --git a/EFCore/src/Properties/VersionInfo.cs b/EFCore/src/Properties/VersionInfo.cs index 9833fee26..b2645c712 100644 --- a/EFCore/src/Properties/VersionInfo.cs +++ b/EFCore/src/Properties/VersionInfo.cs @@ -41,13 +41,13 @@ // by using the '*' as shown below: #if NET8_0 -[assembly: AssemblyVersion("9.3.0")] -[assembly: AssemblyInformationalVersion("8.0.11.0+MySQL9.3.0")] -[assembly: AssemblyFileVersion("9.3.0.0")] +[assembly: AssemblyVersion("9.4.0")] +[assembly: AssemblyInformationalVersion("8.0.11.0+MySQL9.4.0")] +[assembly: AssemblyFileVersion("9.4.0.0")] [assembly: NeutralResourcesLanguage("en-US")] #elif NET9_0 -[assembly: AssemblyVersion("9.3.0")] -[assembly: AssemblyInformationalVersion("9.0.0.0-preview+MySQL9.3.0")] -[assembly: AssemblyFileVersion("9.3.0.0")] +[assembly: AssemblyVersion("9.4.0")] +[assembly: AssemblyInformationalVersion("9.0.0.0-preview+MySQL9.4.0")] +[assembly: AssemblyFileVersion("9.4.0.0")] [assembly: NeutralResourcesLanguage("en-US")] #endif diff --git a/EntityFramework/src/MySql.Data.EntityFramework.csproj b/EntityFramework/src/MySql.Data.EntityFramework.csproj index 5ded04f19..572565996 100644 --- a/EntityFramework/src/MySql.Data.EntityFramework.csproj +++ b/EntityFramework/src/MySql.Data.EntityFramework.csproj @@ -4,7 +4,7 @@ MySql.Data.EntityFramework Copyright © 2008, 2025, Oracle and/or its affiliates. en-US - 9.3.0 + 9.4.0 Oracle Corporation net462;net48; $(NoWarn);CS1591 @@ -107,4 +107,4 @@ - + \ No newline at end of file diff --git a/EntityFramework/src/Properties/VersionInfo.cs b/EntityFramework/src/Properties/VersionInfo.cs index e4c0f01b6..e577111b1 100644 --- a/EntityFramework/src/Properties/VersionInfo.cs +++ b/EntityFramework/src/Properties/VersionInfo.cs @@ -40,7 +40,7 @@ // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("9.3.0")] -[assembly: AssemblyInformationalVersion("9.3.0.0")] -[assembly: AssemblyFileVersion("9.3.0.0")] +[assembly: AssemblyVersion("9.4.0")] +[assembly: AssemblyInformationalVersion("9.4.0.0")] +[assembly: AssemblyFileVersion("9.4.0.0")] [assembly: NeutralResourcesLanguage("en-US")] diff --git a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/MySql.EntityFramework.Basic.Tests.csproj b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/MySql.EntityFramework.Basic.Tests.csproj index 1434a7522..a30f506f9 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/MySql.EntityFramework.Basic.Tests.csproj +++ b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/MySql.EntityFramework.Basic.Tests.csproj @@ -4,7 +4,7 @@ MySql.Data.EntityFramework.CodeFirTests Copyright © 2016, 2025, Oracle and/or its affiliates. en-US - 9.3.0 + 9.4.0 Oracle net462;net48; MySql.EntityFramework.Basic.Tests @@ -62,4 +62,4 @@ - + \ No newline at end of file diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/MySql.EntityFramework.CodeFirst.Tests.csproj b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/MySql.EntityFramework.CodeFirst.Tests.csproj index 93bf4c32a..0568555ca 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/MySql.EntityFramework.CodeFirst.Tests.csproj +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/MySql.EntityFramework.CodeFirst.Tests.csproj @@ -4,7 +4,7 @@ MySql.Data.EntityFramework.CodeFirst.Tests Copyright © 2016, 2025, Oracle and/or its affiliates. en-US - 9.3.0 + 9.4.0 Oracle net462;net48; MySql.EntityFramework.CodeFirst.Tests @@ -89,4 +89,4 @@ - + \ No newline at end of file diff --git a/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/MySql.EntityFramework.Migrations.Tests.csproj b/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/MySql.EntityFramework.Migrations.Tests.csproj index 4aacbcf39..ae0dcd99f 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/MySql.EntityFramework.Migrations.Tests.csproj +++ b/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/MySql.EntityFramework.Migrations.Tests.csproj @@ -4,7 +4,7 @@ MySql.Data.EntityFramework.Migrations.Tests Copyright © 2016, 2025, Oracle and/or its affiliates. en-US - 9.3.0 + 9.4.0 Oracle net462;net48; MySql.EntityFramework.Migrations.Tests @@ -58,4 +58,4 @@ Resources.Designer.cs - + \ No newline at end of file diff --git a/MySQL.Data.OpenTelemetry/src/MySQL.Data.OpenTelemetry.csproj b/MySQL.Data.OpenTelemetry/src/MySQL.Data.OpenTelemetry.csproj index 766c12ffe..589d41210 100644 --- a/MySQL.Data.OpenTelemetry/src/MySQL.Data.OpenTelemetry.csproj +++ b/MySQL.Data.OpenTelemetry/src/MySQL.Data.OpenTelemetry.csproj @@ -4,7 +4,7 @@ MySql.Data.OpenTelemetry Copyright © 2023, 2025, Oracle and/or its affiliates. en-US - 9.3.0 + 9.4.0 Oracle Corporation netstandard2.0 MySql.Data.OpenTelemetry @@ -40,4 +40,4 @@ - + \ No newline at end of file diff --git a/MySQL.Data.OpenTelemetry/src/Properties/VersionInfo.cs b/MySQL.Data.OpenTelemetry/src/Properties/VersionInfo.cs index 10ed39647..05488fcf7 100644 --- a/MySQL.Data.OpenTelemetry/src/Properties/VersionInfo.cs +++ b/MySQL.Data.OpenTelemetry/src/Properties/VersionInfo.cs @@ -40,8 +40,8 @@ // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("9.3.0")] -[assembly: AssemblyInformationalVersion("9.3.0.0")] -[assembly: AssemblyFileVersion("9.3.0.0")] +[assembly: AssemblyVersion("9.4.0")] +[assembly: AssemblyInformationalVersion("9.4.0.0")] +[assembly: AssemblyFileVersion("9.4.0.0")] [assembly: NeutralResourcesLanguage("en-US")] diff --git a/MySQL.Data/src/MySql.Data.csproj b/MySQL.Data/src/MySql.Data.csproj index 088019be2..99c82ff89 100644 --- a/MySQL.Data/src/MySql.Data.csproj +++ b/MySQL.Data/src/MySql.Data.csproj @@ -5,7 +5,7 @@ MySql.Data.MySqlClient .Net Core Class Library Copyright © 2004, 2025, Oracle and/or its affiliates. en-US - 9.3.0 + 9.4.0 Oracle Corporation MySql.Data netstandard2.0;netstandard2.1;net9.0;net8.0; @@ -27,7 +27,7 @@ - + @@ -128,4 +128,4 @@ - + \ No newline at end of file diff --git a/MySQL.Data/src/Properties/VersionInfo.cs b/MySQL.Data/src/Properties/VersionInfo.cs index d259e153d..e26c5117d 100644 --- a/MySQL.Data/src/Properties/VersionInfo.cs +++ b/MySQL.Data/src/Properties/VersionInfo.cs @@ -40,7 +40,7 @@ // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("9.3.0")] -[assembly: AssemblyInformationalVersion("9.3.0.0")] -[assembly: AssemblyFileVersion("9.3.0.0")] +[assembly: AssemblyVersion("9.4.0")] +[assembly: AssemblyInformationalVersion("9.4.0.0")] +[assembly: AssemblyFileVersion("9.4.0.0")] [assembly: NeutralResourcesLanguage("en-US")] diff --git a/MySQL.Data/tests/MySql.Data.Tests/MySql.Data.Tests.csproj b/MySQL.Data/tests/MySql.Data.Tests/MySql.Data.Tests.csproj index 965a80589..9455959c7 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/MySql.Data.Tests.csproj +++ b/MySQL.Data/tests/MySql.Data.Tests/MySql.Data.Tests.csproj @@ -4,7 +4,7 @@ MySql.Data.Tests MySql.Data.Tests Class Library Copyright © 2016, 2025, Oracle and/or its affiliates. - 9.3.0 + 9.4.0 Oracle Oracle MySql.Data.Tests @@ -29,7 +29,7 @@ - + @@ -138,4 +138,4 @@ - + \ No newline at end of file diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/MySqlX.Data.Tests.csproj b/MySQL.Data/tests/MySqlX.Data.Tests/MySqlX.Data.Tests.csproj index 3475a9104..111476d40 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/MySqlX.Data.Tests.csproj +++ b/MySQL.Data/tests/MySqlX.Data.Tests/MySqlX.Data.Tests.csproj @@ -4,7 +4,7 @@ MySql.Data.Tests MySql.Data.Tests Class Library Copyright © 2016, 2025, Oracle and/or its affiliates. - 9.3.0 + 9.4.0 Oracle Oracle MySql.Data.Tests @@ -29,7 +29,7 @@ - + @@ -117,4 +117,4 @@ Always - + \ No newline at end of file diff --git a/MySql.Web/src/MySql.Web.csproj b/MySql.Web/src/MySql.Web.csproj index 97f4d0a68..ed1ebd6ba 100644 --- a/MySql.Web/src/MySql.Web.csproj +++ b/MySql.Web/src/MySql.Web.csproj @@ -4,7 +4,7 @@ MySql.Web Copyright © 2004, 2025, Oracle and/or its affiliates. en-US - 9.3.0 + 9.4.0 Oracle Corporation net462;net48; $(NoWarn);CS1591 @@ -86,4 +86,4 @@ - + \ No newline at end of file diff --git a/MySql.Web/src/Properties/VersionInfo.cs b/MySql.Web/src/Properties/VersionInfo.cs index e4c0f01b6..e577111b1 100644 --- a/MySql.Web/src/Properties/VersionInfo.cs +++ b/MySql.Web/src/Properties/VersionInfo.cs @@ -40,7 +40,7 @@ // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("9.3.0")] -[assembly: AssemblyInformationalVersion("9.3.0.0")] -[assembly: AssemblyFileVersion("9.3.0.0")] +[assembly: AssemblyVersion("9.4.0")] +[assembly: AssemblyInformationalVersion("9.4.0.0")] +[assembly: AssemblyFileVersion("9.4.0.0")] [assembly: NeutralResourcesLanguage("en-US")] diff --git a/MySql.Web/tests/MySql.Web.Tests.csproj b/MySql.Web/tests/MySql.Web.Tests.csproj index 27dcb3dd2..600a45c0d 100644 --- a/MySql.Web/tests/MySql.Web.Tests.csproj +++ b/MySql.Web/tests/MySql.Web.Tests.csproj @@ -4,7 +4,7 @@ MySql.Web.Tests Copyright © 2016, 2025, Oracle and/or its affiliates. en-US - 9.3.0 + 9.4.0 Oracle net462;net48; MySql.Web.Tests @@ -64,4 +64,4 @@ - + \ No newline at end of file From 44a455eb637167ad311bf008b86308dd21c5ac28 Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Tue, 25 Mar 2025 12:12:06 -0600 Subject: [PATCH 111/125] Bug#35474099 [OpenAsync throws unhandled exception from thread pool] Change-Id: I047114a5dddb4c862869d24f2c3e6213b947af4a --- CHANGES | 1 + MySQL.Data/src/common/StreamCreator.cs | 22 ++++++++++++++++--- .../tests/MySql.Data.Tests/ConnectionTests.cs | 13 +++++++++++ 3 files changed, 33 insertions(+), 3 deletions(-) diff --git a/CHANGES b/CHANGES index 29be8eec6..51aa0b7f4 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,5 @@ 9.4.0 +- Fixed bug OpenAsync throws unhandled exception from thread pool (MySQL Bug #110789, Oracle Bug #35474099). 9.3.0 diff --git a/MySQL.Data/src/common/StreamCreator.cs b/MySQL.Data/src/common/StreamCreator.cs index 84f015e87..4b77c7c7b 100644 --- a/MySQL.Data/src/common/StreamCreator.cs +++ b/MySQL.Data/src/common/StreamCreator.cs @@ -33,6 +33,7 @@ using System.Linq; using System.Net; using System.Net.Sockets; +using System.Runtime.CompilerServices; using System.Threading; using System.Threading.Tasks; @@ -108,11 +109,26 @@ private static async Task> GetTcpStreamAsync(MySq TcpClient tcpClient = new TcpClient(addr.AddressFamily); if (execAsync) - using (cancellationToken.Register(() => throw new MySqlException(Resources.Timeout, new TimeoutException()))) - await tcpClient.ConnectAsync(settings.Server, (int)settings.Port).ConfigureAwait(false); + { + try + { + using (cancellationToken.Register(() => tcpClient.Dispose())) + { +#if NETFRAMEWORK || NETSTANDARD2_1 || NETSTANDARD2_0 + await tcpClient.ConnectAsync(settings.Server, (int)settings.Port).ConfigureAwait(false); +#else + await tcpClient.ConnectAsync(settings.Server, (int)settings.Port, cancellationToken).ConfigureAwait(false); +#endif + } + } + catch (Exception ex) when (ex is SocketException or ObjectDisposedException && cancellationToken.IsCancellationRequested) + { + throw new MySqlException(Resources.Timeout, new TimeoutException()); + } + } else if (!tcpClient.ConnectAsync(settings.Server, (int)settings.Port).Wait((int)settings.ConnectionTimeout * 1000)) - throw new MySqlException(Resources.Timeout, new TimeoutException()); + throw new MySqlException(Resources.Timeout, new TimeoutException()); if (settings.Keepalive > 0) SetKeepAlive(tcpClient.Client, settings.Keepalive); diff --git a/MySQL.Data/tests/MySql.Data.Tests/ConnectionTests.cs b/MySQL.Data/tests/MySql.Data.Tests/ConnectionTests.cs index c5725768d..9b5858a5e 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/ConnectionTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/ConnectionTests.cs @@ -172,6 +172,19 @@ public void ReOpenDisposedConnection() } } + /// + /// Bug#35474099 OpenAsync throws unhandled exception from thread pool. + /// + [Test] + public async Task OpenAsyncCatchException() + { + MockServer mockServer = new MockServer(false); + mockServer.StartServer(); + using var connection = new MySqlConnection($"server={mockServer.Address};port={mockServer.Port};user={Settings.UserID};connectiontimeout = 1"); + Assert.ThrowsAsync(async () => await connection.OpenAsync()); + mockServer.StopServer(); + } + [Test] public void ConnectingAsUTF8() { From ddef33f956e1bea321c36c092b1beb061989d664 Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Mon, 14 Apr 2025 15:54:35 -0600 Subject: [PATCH 112/125] Bug#37837374 [Entity Framework 6 from NET9 is deprecated due to Nunit4 Upgrade] Change-Id: I41a4ae377c8cc0064b89880b89bd42b85506ae8a --- CHANGES | 1 + EntityFramework/src/MySql.Data.EntityFramework.csproj | 2 +- .../MySql.EntityFramework.Basic.Tests.csproj | 2 +- .../MySql.EntityFramework.CodeFirst.Tests.csproj | 2 +- .../MySql.EntityFramework.Migrations.Tests.csproj | 2 +- 5 files changed, 5 insertions(+), 4 deletions(-) diff --git a/CHANGES b/CHANGES index 51aa0b7f4..1653bc69e 100644 --- a/CHANGES +++ b/CHANGES @@ -1,5 +1,6 @@ 9.4.0 - Fixed bug OpenAsync throws unhandled exception from thread pool (MySQL Bug #110789, Oracle Bug #35474099). +- Fixed Entity Framework 6 from NET9 is deprecated due to Nunit4 Upgrade (MySQL Bug #117976, Oracle Bug #37837374). 9.3.0 diff --git a/EntityFramework/src/MySql.Data.EntityFramework.csproj b/EntityFramework/src/MySql.Data.EntityFramework.csproj index 572565996..8f33df2a4 100644 --- a/EntityFramework/src/MySql.Data.EntityFramework.csproj +++ b/EntityFramework/src/MySql.Data.EntityFramework.csproj @@ -6,7 +6,7 @@ en-US 9.4.0 Oracle Corporation - net462;net48; + net462;net48;netstandard2.1 $(NoWarn);CS1591 MySql.Data.EntityFramework MySql.Data.EntityFramework diff --git a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/MySql.EntityFramework.Basic.Tests.csproj b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/MySql.EntityFramework.Basic.Tests.csproj index a30f506f9..74db78daf 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/MySql.EntityFramework.Basic.Tests.csproj +++ b/EntityFramework/tests/MySql.EntityFramework.Basic.Tests/MySql.EntityFramework.Basic.Tests.csproj @@ -6,7 +6,7 @@ en-US 9.4.0 Oracle - net462;net48; + net462;net48;net9.0 MySql.EntityFramework.Basic.Tests MySql.EntityFramework.Basic.Tests MySql;.NET Connector;MySql Connector/NET diff --git a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/MySql.EntityFramework.CodeFirst.Tests.csproj b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/MySql.EntityFramework.CodeFirst.Tests.csproj index 0568555ca..f1a6065cc 100644 --- a/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/MySql.EntityFramework.CodeFirst.Tests.csproj +++ b/EntityFramework/tests/MySql.EntityFramework.CodeFirst.Tests/MySql.EntityFramework.CodeFirst.Tests.csproj @@ -6,7 +6,7 @@ en-US 9.4.0 Oracle - net462;net48; + net462;net48;net9.0 MySql.EntityFramework.CodeFirst.Tests MySql.EntityFramework.CodeFirst.Tests MySql;.NET Connector;MySql Connector/NET diff --git a/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/MySql.EntityFramework.Migrations.Tests.csproj b/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/MySql.EntityFramework.Migrations.Tests.csproj index ae0dcd99f..dacd09bc8 100644 --- a/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/MySql.EntityFramework.Migrations.Tests.csproj +++ b/EntityFramework/tests/MySql.EntityFramework.Migrations.Tests/MySql.EntityFramework.Migrations.Tests.csproj @@ -6,7 +6,7 @@ en-US 9.4.0 Oracle - net462;net48; + net462;net48;net9.0 MySql.EntityFramework.Migrations.Tests MySql.EntityFramework.Migrations.Tests MySql;.NET Connector;MySql Connector/NET From 4ca9c603ca024615bb08160e64c4766f20d9d8cf Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Wed, 2 Apr 2025 16:44:40 -0600 Subject: [PATCH 113/125] WL#15984 [Support GSSAPI/Kerberos authentication on Windows using authentication_ldap_sasl_client plug-in] Change-Id: I1aa05eb357ab7a66076b2faf5f61df0bbcabc985 --- CHANGES | 1 + .../src/Authentication/MySqlSASLPlugin.cs | 3 - .../tests/MySql.Data.Tests/AuthTests.cs | 10 +-- .../Resources/KerberosConfig.txt | 68 ------------------ .../MySql.Data.Tests/Resources/mtr.keytab | Bin 0 -> 407 bytes .../tests/MySql.Data.Tests/Resources/my.ini | 8 +-- .../MySql.Data.Tests/Resources/mysql.keytab | Bin 178 -> 0 bytes 7 files changed, 10 insertions(+), 80 deletions(-) delete mode 100644 MySQL.Data/tests/MySql.Data.Tests/Resources/KerberosConfig.txt create mode 100644 MySQL.Data/tests/MySql.Data.Tests/Resources/mtr.keytab delete mode 100644 MySQL.Data/tests/MySql.Data.Tests/Resources/mysql.keytab diff --git a/CHANGES b/CHANGES index 1653bc69e..d98374809 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,7 @@ 9.4.0 - Fixed bug OpenAsync throws unhandled exception from thread pool (MySQL Bug #110789, Oracle Bug #35474099). - Fixed Entity Framework 6 from NET9 is deprecated due to Nunit4 Upgrade (MySQL Bug #117976, Oracle Bug #37837374). +- Added support for GSSAPI/Kerberos authentication on Windows using authentication_ldap_sasl_client plug-in (WL15984). 9.3.0 diff --git a/MySQL.Data/src/Authentication/MySqlSASLPlugin.cs b/MySQL.Data/src/Authentication/MySqlSASLPlugin.cs index 2b8bf0d41..db8532905 100644 --- a/MySQL.Data/src/Authentication/MySqlSASLPlugin.cs +++ b/MySQL.Data/src/Authentication/MySqlSASLPlugin.cs @@ -49,7 +49,6 @@ internal class MySqlSASLPlugin : MySqlAuthenticationPlugin protected override void SetAuthData(byte[] data) { _mechanismName = Encoding.UTF8.GetString(data); - switch (_mechanismName) { case "SCRAM-SHA-1": @@ -59,8 +58,6 @@ protected override void SetAuthData(byte[] data) scramMechanism = new ScramSha256Mechanism(GetUsername(), GetMFAPassword(), Settings.Server); break; case "GSSAPI": - if (Platform.IsWindows()) - throw new PlatformNotSupportedException(string.Format(Resources.AuthenticationPluginNotSupported, "GSSAPI/Kerberos")); gssapiMechanism = new GssapiMechanism(GetUsername(), GetMFAPassword()); break; } diff --git a/MySQL.Data/tests/MySql.Data.Tests/AuthTests.cs b/MySQL.Data/tests/MySql.Data.Tests/AuthTests.cs index cdf8d8971..c80c4fdea 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/AuthTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/AuthTests.cs @@ -1167,9 +1167,9 @@ public void AssertScramSha256() /// It uses preconfigured LDAP servers present in the labs. /// For configuration of the server, theres a quick guide in Resources/KerberosConfig.txt to setup the environment. ///

1{{Tm?|7pE7a&1!jN^#bS5XDu&5l6f| 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 LtQ+JGEsuXN%{k_p{(>yYc6WH$^#Jv~T=IuHSWe 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 diff --git a/Dependencies/MITLibs/k5sprt64.dll b/Dependencies/MITLibs/k5sprt64.dll index 9237ce9d76f38f00f0a29a308d251ad0a1e61e81..ff77f1a3bca1b66761cc7129dcad5aa59c089d75 100644 GIT binary patch delta 18952 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 delta 24077 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 LeprgLoAAE?*e5EO diff --git a/Dependencies/MITLibs/krb5_64.dll b/Dependencies/MITLibs/krb5_64.dll index 582f680f8ae964fdcf51c9611715855a7575bcf1..42db6f7b1700dc31c7ee051aa85a1d662d1fa374 100644 GIT binary patch delta 261894 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 q+X=v(`A`}q*6xP)4AW4K4Cn(( zQj1jds6|N{mMWWwgf6r@6(eWU$Y++U5VUhI12dLXD zS;^85DD>u`Rw(hm@eRv*cjQ-Zy5tm|L7K&6c$&eYUJ3V$@3`F=Y$| z&B4q^)L@Pb6W;r%>l_*ByMLc2J5VkH0gk3!8eJISwY`05>m1osK7Ivf#&I%;yywbZ zqIxC`ohuv5NI;bv@y7W+!D%0zvC7|GTIt+;pEB~7m)5l9XUbYS?t$VMwg7@Sex7_H zSN&t9MrpEtn5DI15O%AKbmL2wlupM^0S9Z+u{1eIOlU>X^Rc&7xh8d-FSpAT{;$cp zK(>$_{9k8uTp)LAV$9AAUy_wH(W5@qT_gvKU+dAjMRKI=QDIOe)z3YMH!z>Rps2;@ z{Xb1Jx-OP4govw6?Z1>0#Hm=i{H5$94#rT$W!O@g5JN+jNr$)^L$j92h?*Zle88K+ z3O03=HN6v{te1Ue3>CJxi>aUH=0Gwt&Yq2wy-ePZIQ^I4$qlXpaMxw`%v3Cn;9`q@ zDtCf-{psI=UM!c9V*e8=u|hTri+QQCm?{{8b*UpKd}?{b6G~bkYg%*sxIe!~vxG?ixoc_E$ZBCb!gY1tD$Ml?F*0u&fbISFlr|J0gKHNa{SHj>>!Iu(O%9>*D zV_LUTb`?R7$zzpVQTW{)gE*17b|-!!w*xo!xR;=YT zV|_}|)`3v5qgKm3^2>ij#)H+er6#xPR;aH-G7uObP!kV&(l=jY#Wv(F{qwafEsxzd zIdaQt4=<{>R{F@#mv}0VTak93daRXkUW?a&p`i&JrDs(Uqx#%h=`GIJpzCY#VP0IE z;kQnPX+b3x1BrW&@GC!~@hP}2GVSol5`58vw@t;EHlwh7{IgY^BAB*bmeVfLw)NP! zdrb86dYR~#xSA&hWs{kEk3EZ5C!9Ec!gqQ5Bz!&);K_rkZj>!W zRuP)8QQp^%QQu86Qw&>9B{$3dc%8agc5pujrqa@4-VdceH_IYkxF*wRAq{&fN_yR4 z@8lWoA9kijTOfoQ-JZC8xpWS&aUy$~@ePs>uJ>{|qFSLq!P=-dqWbQJqi z2@q~o4>RH#ZrZ^(|8O(Ixea5QcD_O(d1SFCwSA^lgB$G!GUI~kH*}9AjbY` z&W1cm$z+BSwn@3N{NzV*UnJ${0kQ z=xa0}B@6w!7?*@xiTdlOuXx%wr8rhYL~jcO8e?cZOaGMSKHzs;o&GG$XyWG*es zlq0LIo&yw=Q;)fbRXk?~}ZdB19SVD7p^HTKF%A^+ec2uRsgS$+7t0t=bqf6%9Uq3=JS zy?ddSG`>vN_sVL%)1MpEbLwAAqL6*Ee(``=Ohv4!Dl7Rn$%tQ|t~Z=`k%sNV`XgJX z)BB)@{c?f)_G8g09^l$TOt$G4Y3zPEL@fW6^!>0lH~y8H9+2%TbT&`ELRhsme?ne2 zRX^2fY*S7g%%-dZGF~KJph5@bb20Y|az7-y`ZamX%%N78VdrV+Az5EcK1Z7m$)di8 z&nh3a=v;e`b9Cj9{6mJERYFh5X*Bh)oSfeUlr0;}9vWpO>QPsy+z}ZiKAk`vkD%7- zr|Ih>vRm0}*^GgprQ;Mk;cNo92&cqO!I85+^Qf|yQ2C>>X3Ru|%Uu89(rd#%bTfYn zru)Jwd@^$H4r;tONpFtI#8wR^8$80{(OFq! z)^_N>jP+EfVLG7)p}H|-4*f2mya-OfDL~dG5|H}lfh+asSlW9G%bpcuF>~J$5g|MB zlKOK-Rq)413>+@Q(q1PbF4b|FEA||xm=m&+sER9FPsom9=Ly<<0*V{>XN!eGNK1MB0$@0OMOS<&xnc<11oAC}fBA$|AmaFh7Neir6 zl1fhV2?!mA^V8roPjwb8CobnC)=0-)82+bWcdl@Z9H(WtoPW&9uG?Lx!IvI|Gj^Sp z4>a+j4lO?`BgEvpbo?w7%<<#N{hZtwwC;|dn~FRZmuehi&_|D=W9Og@R2ZKT@GaCT z(XtlBU66f!&;Dre0-{!bnz84C{6Q0$LutV!8RIj243pM~hJtHO%cNcS(RblxSxoNQ zW2ohYqYYab2HUB4Q?LICHM=Y~%UhYI^5k^|M)H26Gs3ROL`^o$Fch5CS7jIRaQDJ% zvUqW+M#L`+k6iox-B!3Yt4S%>zIZnZNfw2v^) zl^8NSBlvq+$K4itiAUY99UeHgvXy$=ltpX_2Jlk_oUxUr-jr=^jSXNI1+27{ez_@! z*yx(dz6}rDL$f6#;YZdHhihPF0zP2hPy1 zrQd&+yKBBatAN1@*y(GghcR(*Oh3fLDhrhWJYLqw+fbp!d`)+MkvAI6GV-p)BiG*I zD_7nzDX|{okTurGnrUENQdngaR<7N6(#K6LrRdo+96btuARpMeoluP#jR%fKa!$=Zk1Nao1@vC+sv2P|jAo~^Bu%wDjJ&lK+Pzg&C0q8e2?JP6 z0Y|N(W!ZAD?YdFmb3AhGFIQ5?L%F~<$p9`>zzgWoK&mR35K%^{6W0 zF&?@0+@(gBa8!+lBQiID^`cl)Fz#7OG0$X(O*gV=$2iNrr8Mj}S(pYrlaaPRj1-$n z8Mc&GK9gfCxl5p~Z-3-ol(HIt0-?oJ0ukxTMx0sIp zDx26YA6AXa!2?#aMP&a?R*zh<$j~wnKy8dwamz2pke@fOA1LgVi@04MVc#I*&Tq1w zW(zu~%BqA%uKmG6iuzp+vpqVXfbI&|e__VP-(_`8)LuY$|B!##{xnhpRBDC!8Ty~{ zXHB%4mvR1Y-Xp6zm-K&N`YLCX>{Mv;=1}rWxx{wD$a@=M`zvS2Ma&Fbkp)B+vEh@dcs zO3ic+rl!Jjn6I<*l$IVMs5uRgmgymX;&c`m0s`>u8S84zJ!w-NYdNZ7v3QEkf?_R} zZ*9f4tIkx%1Gmagp&)n5RNL`w3U~_-c(hNU4epjowz~%K9|f#9h3>msR@i13z%>du zVKUA4ur#&JF@Wn8FlsVA@UUdt^sTB)O#!P-%DC-m@t3wTn-#Pv9=Z15iS)|bQZ#nB z0i2YSYpEeMGQi#Wrsf~}NXnEZLYFoI-r7E}U$>h*^ z?#60neFK{7V`*i3*JxKCJYeNWrbj*&hrF6(rRXeJe#-b-Vr>xyN&|(mE-7P>ujNzC ztHuPiZtiq6Ezl=~rq$GZ$>wjdi5=s~;csaz_9fHD{+9A0Xkx|^f6I7HEJ&gv0hYi0 zf|HD;u_M=hb}W?)v_vEgfEFK)hVddVj-R})F;wNZ`(((bb_7{{WL@U}G4|eZQ6JC$ zIQP2U0|f+>qpPO^f>=;dv17-My~Khs8tfRc#R3L9qQ*AHUSo-|yFcW9*^ITKX~11U%Rujv$M0av$H!k9_Oj{J)i|I1~~G^c@)L( zaKs5)hoAcTP^mpC>v$-jye4}K!kBai2tAlhlpF5W9_UC80XP2wqiQF|K47|@CrLkO5Y9mJ3wCwr*-QXfk-i%YyuBde-kVu~&jtC$L7A;FcE3XMPf} zr_&Mz_i?#Ie}&>bm@E_==ocw`y61`(QY%+ALoWLZe5#MTohk*_j`5S>I{FOHHr#6N zI_l6%1gEFqjbBrZXBt15uH*C{`jSXzihtfx>wY)JcSD;JOA zulyrk{lKE-mP+6^qtijE1d!FRI}cjra_!sbs!R!31){lUFac(>&SqT*xKo>Lm1r!IH+s}k1W!uVpN-MA0GV@TgIcSFv(*<@{rBm zyse5}G7#&qR%Z)viIGCJIK{A5IQBow@I6?zHb_=f&$bo;AZL*cIPIy9fE`oVrST2U zw*2CW(GJ3(Fs^8ZO@NE2{(}JMTSE!hTr{fh!VaqfDfOBrirdG$u_nGc#zWteuJYKk zn18a%QF%4XCfOI$uBlpyfNubWX@CX0GK})Fcgr*KDn9J>)06IdcF?OwcWz*ac5o9_-n?gi6?ZyZ? z6(YLW%$d6Jm@&gzt2he?5Y{Nvr3y6)6+znFX7o;|7^Ph>(Ya6&647WFz`!MwF^ob&Vz#l1UF@Y{XwG)T zG&71mLs7j%gzHtVs zONx8un?rcLJ)D;GF_$HeVBzO$Ud0XfNX$~(CV#9X&_9gUmKImzdF;ET`D0G?TEWCH z(405Q7+IIlEfw%(pW3-{e7>@fzOacFg?&|U-65`QvI$utt4r%`hry@i~elixkgPd@jAXT^GPyON0r<8pZqr>a#ACO#pJ&v{B2O*gwyQuqK;OP=)3ZwG%j|fyX8f^ zyNSGUahi=HqeN-6ZSkC+cao>vqfRlRqtz21oJ4Tr#`UniqJ1%< zzqarIm98kd)m>8hKeR>)Up!*;Q!uR6s4Xck)?L4l#7H+Cz}?-VlD6bax>Zqx`uqI{ zP{Y#XQ%NLi9eUHqN}`Paho#=GYI7<2v=XRtDwJ+i5{+$9la(M%LbQYpN)jLzjDBjh zz&f=T)`R`Z3#)%l$+zL$DM^DWV{mWiM+Ym5*4m4A$g_$Fjr=o2&soTIm%`pItCgfS zRlwPE{_|yD7%i$IMur0-qZHDc|2nNiC#zFujV!$eYoF%2gHRBEK`*P&lssHc|@9Yz?BJRYemm zdI0UJDnio}{!?c7f69ahp)HsXauw4VojMPRsyRngs^K%B#_QjK$d6ejl{0xQWez|-{+zCZYFYUOdt+jWMaPRv2@N#i|>q`X8_ZCJUi-Sv6MaTzSOW?WHv z7bxxV0y=sATqX#=aN}1u5Bk2EsOjy`2=i2q>kYe+cXg4WRqsags*4U@u~wyXvCLDO z?f#fnF3iCo0(hm_C)oQ(Q;9e+%~X^=i4&!26xDq@fTxXTi(06U?R&7}S{r0@LFgj( zaz-wGi?`$M#rtuhtf>h3)DR&dp$a}{J5|KhQDjdMYEnZ)A=^;SHayD#ZNwYd-YG(B zYKXv&Mxu_0mXCPE46-7U9qWnK3W8Ew*sy=RysmR|#sq|Lz-e+IZo>^ds^nu2DpFHq zl&YmpnX67@U!y4X3bhW#H~gdrb_4-^U^W$l*O9xrhOeui?x30eg%-KWz;KJT)i$Tr(P3`*A6r>UNop{ z!G&$QwNGs}Jn2yQiY2Vw<<+;qdR4tDZSYJ7wa*<+*>yyb#=l9H*@bGPyE^!rkE@*6 zj{ZM<)g67@^;>+^wXQb%UM|JEIx{*ND&@G^Vy{V(UtLkI_*PNap;7iFc*7RBsT?)* zLXLTLga-l;EUhC-2H*>}cMQ-7=EPOb7Id->6bRg$Rab=jnq5KV;H>5O$rk^GljizZ zxSxM8)9|`txb`xWZqyYOwI4IdtDcC_c4boSdZMiMNhbBKC+chOX3~m!5Y7!V>0~_- zrIpO2f9i=ivk9mnqMb-W)6&pFf`=V;OCoJH-LHKO!_Y5TPM1 zrDE;X@uqWWw3|C!uZ%0-|7;-q%WZG1iv^hSjObkxFdmiZu}xMk;1-!e5e-F*=j{v~ zeuDi|n%7VS(8z|Ogmxf5wYu#H?&qgA& zIOi?MHGB@iOffBKMk7&PyEd72HWH1?^LMxz#*XU6f=DgF;_Y!p4N5L0+JAm&q2R`% zxrS%I#v--!gBCmvz#IkE+s4lXdx@78wvA(#b>W&LWyr6Ih^&qz*B%a3B;y`i|Dv#g z>|mxZAhWGelW1@g@s4(RA{}c2CM!OX{%#_o&0{Su$<|aPYR@e+xT&a*3#m3Y6?KAF zEjLyvKt7)5vkVZ;9wuMXi>9Jgbh%s*jcpgoAShopcXVQwOkl*3jwVa57Bsw>h&5@n zx|vAV9&2Q4F5Uy1PHQeYYFF3N)#jp^wqPyUT3}_gRB*@3Vr)y*?IL`c4bM|asGN-+ z%8rF+g7MyzpUkSs_AUQ{;MvyT@hGekRw2QWHJ_tkB`Al21P;rdz%61U7orv&c1s(k zzNY8G$xcK0rdhdwPcV0|_*d=f^pAxn9k4K%g1^GIN0I0Cri@TGTN=$JngjTBMk(H1t@w_Mkr?a3Y%A(So*TtTB6|EoHMVr` zu}NjXLOAuNb6JA@0e#U{v^1Y^e@U;~is9yzdiq9RW;@Z!G=t8x6YYYI*Tr2X*|Nh2 z(AV{)En8GR96)jHq0SDdOHM6ps z?*`C;o+84-9Ba7Kt^J=z*@ZizE#&u(2o19jWZLm8-upKTruK=^Jo0S7hrcN0abFBo>?>mZHg^TQnB_UcWGx|;os|$8|&j-NV1v7h%*&yPqZ_91#CX+{(7mNFAGzXoT(nK3RAl~ zQ$y~NEm`=di+hD%Q=DJ_%qvVyb*6em;3$ky>o{j>StpKJ^D~^OUM{IKovHs8IN-{q zDlz4pj{0k7g>tj{V5I+En7+p~{ntVQ%zTOu_OdrH>~!2_s#Uw6N>FYlr=!vNRbp_+ zl&`vP&`;p1`x2DYPjnE}6}QukTwju%Cq3zOKk>KL@C6-xSHx*WUeGf<%`INNqS*eT zy4epu2KE<~#LvIID4??)yrSq(e-TuMd&W2~vza?7+gdJ}Wt<@p+Qrh-{^BET`ZJpN zo~UR3vc8Gttd^w_PY2?&L=P%40Cv&INfbXo4E9^lhl`^1M(N^|J5W@hp9hF`#e?7a zHmeUE9w?$|;6Tx`_{QFE7L@Aa7nL9NdNX}Dj&Q-U)PRZAJy9+#WUFNR%1m1OK9sKt z<>N7|z z(B_w;$Ad)m;(dF*iQv4RRBNzksNLvC;|4=x`tlz-GFa?u5Y+<)o%26ArK@)>PRQj1 zhyDSX{J1-yAwmMiQya)&{DRW#{jxjl8-mG6Ork%BKrP#Jl|qM#DrT+yOKOWS^xEq# zG<2vyIFnLzbEwGHHkfGmFi};L^=a)esGHj!)Az$fa~N>^hNHK_Dv{}XQvkIYE}{cw z!N`M7kLPy4Ujz?CJr1L+;UZEy`iTBF97eePr|H3PVJ+>8uaFov#xBXeteL*rhYrWD zzg?$tBSd${CFHE}CjoG)E=(Za#n~BdSW{K79;`Fp4>KG=4vY|9T39H3KSGoex69y6 zXht+Vh;c2WAg@#?>`TL_U8<;3ti)eD0zs7mYcC9j!cg{~T(+n+>XOSAb%>DHsM@DL z()N)e%e*{@4bsNRyzC$7(Fd?m#i(Zqy5VjqPUA+2pa3Z19%I@1pcdbl<5`EP z&nQULhwhf`@Sydjj%i|w_UH-ykS59o>tlzF*CX0-D-8v>Xle2tjnUEU2OOmlb;RzS zXi=YSGN5w?c+P(B5*h(>O0u)S6{O_dWv?)0#CO0sY-CJwX58_gqAM@aqtRk^$oNp4 z{0YeS*U64fQmcnp`^FFsh!;r(U*k}~#WA9yY5bD0qK9_*3B5B`G%+op)nhSL2GJj5 zG5^LjrFP>)$r>A*Ij$m3w4ZSK{fEnMzveiF1>vQ7H_=|LIjtEds+hLWxpATg4t`V^ zFKk|C+UvcaYX2sLx{eo-<+|TiM-dX7mX}of=q3zA`TeoJHjq}27frR5jp@#K5nX*c z>STp875j$V_o?=6aE6ACVk}+#+1=E}@F*!`MOqYp(3tzI*l{hfj+#TKL4 z6UD=r@0u~0oDQ>@EmTdq3a@XCC%BCUpUK_LXyYUi=e@kCPFD#icZ5B;weaZ3aBGx}^&r|J%ncuvxO%jF$iqG4>0`>BDr`tj^KObP?j) zud&X@Ymmj>+5Z(CONU{+zXv@@ht)RpE>+18wJXP;;9*#Jizza@r3G_8@Q6Rs$OXo< z60c}U1`HK5o727wu~++{292H~IHcLvQ$$7Ic?m9=%i>Jwvnk?N2R2_cboprYGq4Gl zR5KHb=FQ(|NG3Ec+|fHTQ%p0LsP&S3r$UIAXh1PjVFP(JpSnyHwM`dj-c&3bmeBvE zigv9-gIy1P_;OD`qgg8vQ%kpL@Yn%ulIzin3*L%9xY>GYNhAx3nWVoa@(?n?0 z`1-(-`H}sfc}9XR)`Qc~q51-diP@=28iSj5&J+PTQ)fb7 z4(ynxxH1k4NVH6yt4X!rxk;~Pi7i^?i?n$*SmfUebZa)Ip7ya+A`6D_t0tP1g(;+8 zHtpI1_peh~!dmL`YnXY^#uT@-GAyu?nN%s<6G`@)1F0ZO^b3yLtJ47|Ea7}_7)O%q zCHK@c#WUtna(wi z!>X09&F2F`-5c%kz)zQPcVxp09^poO1Kl`%S7lKvaE=yujlj*|iv^uC?|O9Eb@ z4amkdbasnE@7pXYub!n1qLn(bH)YEMCKIE&!9CsF0t#EkehNwOQvmFlwEd_#Xkl28 zH$9sx%4i+$QrJ8ZX<9{1=81SLk|xfBY>B;1U(6G+TF7m>Jr6dT-8E>yeDt#a9*X@$ zgjxqw_lEH>!Nx62&|5fgARV7C!UB?h#k8hc0(6q}Z-4Kl=krA=^O|Sw6#B8KX+HK0 zrsbeuDs@3xXw=8TA3+&rek`J+MpR?Kyp+whw#RQSpKKr2U0;3kTS9@gF~D5?Sak2X z{EXf!7)?%PKEXcCCDozKC)h{0q#jpPFb6jI!5~!i=JBM5(-=*Y>BPeqJrqz zm3e4;dsbnc?H}AXp*zRIJY$^RFT*Svg^c0AvRxSlEUH=r}QbhTns+E8)SOA3K( zw$tP%8=4lk?)An(Zo*!D5-#7+;pzd|Yv}zr6uESxu%DjL4+;8~0qpv!U0{MlD!L3N zj-eZ=+cId{bvM$)Wgv02%R1qnR#1csd~V=x5U%b+_z%TAU;6iauF6dZlV&xHW!ijY&#Zohu-xpN2`{L54COQC}ah^UUpOb3K&L8 zY^S~}&?)C8(_ADM$0j@^ms8dF4rR-%10!BsAwpcvrhglyvq`Fb!V_AxTGXWmE8$~U z{Tph(5*#q-C=FVPUG0YQ-u&kv@1tDv;*4yI})L@<1=s)@a2cLyLFc6&*t_J3(^kkjbC(^Nd zzR)i(jt-tRd3ZYoTCDxj0eZb&z}5y)&Q6)-a@1G~R zdTiTIU~Z42oQ)zpy=@tE4X6v-a1;=%hejb74Oo}eH%#h=BU6TiaTxkb9vd!@9Y@e) z-Zt)5Y}K#9N4K<+py?1B(;usSq}Y3|W7P)vrmF7e3zhMSA=%U8RJX=wrYp@x=Dmw7 zs4EUNH?_AqtrHjZ)I)$}z3+>{6EHTTP7${;GB3`kcs^H*3fRfB(H=LWnq&Zpv!5TL zHY4;{?678?q%>#9DHQtY6WXvzG%E7RS_@mz$4N@wkAuEdMtQiWA7$%Fb!@c2 z6wfrlyl&?wM=k`l4xw%62p*L7_@DTcb(%M_@H?|~ekDhNteN+b)$Xt7f%~5hCo6-K zRaPy3bfdi)cvEbJCh#&SJ^Y#is^#}!GADq{-Bs3Zzxe4)%5F)a3U!&p-l(&CyO(}=Q zfpM9~4y%kHSJ@^j;|d-)m+86@wl>jqmXdkA#fs509}l;*#);WHBLYVoc9ecC$u&8F z-9io?ictTI+OM{I6V`U*Xk!#8%$bf<`=&pfqY0BEM&tjPm2>{^z%{3q-`jzLZm?Cl ztSb^fB)KA?GvqD4@0Mze_E1k4_b^2280u1c`E^G2yC=V34I^uBELf@z6bw8r?Po~#bN?eLlw!~lgl}LrdEUeai(U?*R@GwKjih7 ztb7_JvgRL00q#BSZTqk4TP@?`u?+smf6n~JG8onyNzwrUQJc1iQU>z#b%VA6_x+3d zxOBAlm4^$=tc+X$g!YHFK(OnTXYS!)12_GT@!ydM_SGwMV*f@hzaSdTv^WH9=lt9r zr-I3*uiHGT91Wd!*O*x^DcH1QD*|_H{#WyEd;7NDHF^8Yg%umvjP8vF#08D+>Od%S z4+|%^(ajtQ$1*Ot(uZuH3I85?cN(M^yla?N8F=vMWIVvk2!Q7xnj$w-VkvdlCIa59WFU6x z60_c_dE`G7woOF%8hn|HY6{C69d0!5i3($&SCuuNsiShDg#G@0SCvWTO~#_ofz>gk ziXoRX1%0Qu4>9H5M(2O}ZencSZh+6E-?s_BA`TiaUGllG>L?YmZ{A4GI1yvhXDT~L zIchb=7*>Qqg-ON+kG%$k*}$kh^67Ov+N+Lhewt#<0l9a^n~>r>Vw z3~Y~OIM__3P{MY&t~dy&>hJoCJ_z!w=-d;kXB@j7M{!&Lp^uW#0(EBX5%*@cH6jpg z&h~DA2h4`o^tGOGoHhE7NkhE{95h5!#jNvAA@Rk@H}RdxkkSjg+!a(-LinsH z=Uk9Kmhm@}27iUk(JM!byXz_#e(5S$v+5_ngsA+jfmdnAn?uIk?3V6?m$_#?*N`^Z zS%I!sW&Ou650P#F)k)^jv}3;2?>fC+1A#s)tBPxbJJ1%*NNE({lPj( z6#s%k3+==KrA^k%6qkPZ|KO?D2xW=V&Y5`g8%1a8_&B)}+)_yYtoe$54#J+tU81g# z`no_$H0}jEUWnw|oUSvX(Mdm?eG`_tOH!v2>Q}qeie+*g@Gw+#R1E+%etZ)E=3h5n zIANvpRu{E5gsI-6LC}ed_!pXJ70cwRU1pzptCV(&kdkd| zVyTq(kOFudXJIC&a+HUn2QH*hK6{XrYAqjYKe_M{Caq9izm!hHPkxOhh#<`(WrxxyN7D#csMWYgZk(mEIFSZk43-&0m zw!1_#cZ;6hk1ry(N^9_AR1`a({%WN2(9$=6dHodB6##= zC1QW{E)pECaO1h6Ue&(Q=~FpHz7`KPpG*%0@HQR=)_+fsN3JMqUWd@!yM8hGQ=?qi zZfAT?V{>7PdiQ%;kqfI_AR?FN!j{`?6+Oxo@5S77S0J9^QD9wm++jtu0S8pt4+&~X zTVS1hf-(+^_F9+9bpEiYCe9yoxV^&s5Jg*$2=AP}N5oR0oj#KD>^p23mQ z|LNB&t=s2Ljdq$}Q1`PUv`-$cT+<~cMtW3%T1L73YP(U>HJwy+B>W;snK3~g=*9Nx!Pm$1oi>> z4?n*%emW{Xf_L`X<2v{7c44+W%a2)dCx5|8!3~6GRP?Xbjq0nv$?=H;Bdz4LV*>3# z?rhnIUo&xKR}P(n2eWo7hi;q~*R(IwXx|0#KdoRCjkqZ4xAFa#8+T#1PMQR^Hzi=N z2d%Ti+y+po07gY*kzgBJ)@7LPj(tm;E{n$g z^sNzD1{EZ+VWL8+g$_p*^`}aQL{SR8BEHuMhvKe?$QHYR{!(2?gBZ4g(cT5tzjngx z>z20;`GO^Vf6J?IEK_1PLHl)!?S+{ z3cZFM(VD|3{+cKg@E;gO3#^-V(1>dyFz~A#Z&!ei<9E=?Yw+EBe;6IQCi-Z7qp9?D z(I)Wlc1Px9?#pDiNkD(mcKYZ#_Sw@n)5+_iQee~nE0gS@)JpMCka8u0J{{529-9(S(ZlTvV zMF(x=Zd`~1!li7<8GcJNGHKS$IhY$-n#>=(XIVI9XW&Ag3zE`*MGVkVzroSw=l=BZ zZ`hDIu^u;60PfcH20W{mYqbfUeqdQG0h8r2ae(32%);nz2q|M z*5Dcyh~iUyX~kV}$lPzOJ3Hcfe*x*THwvW-tPR&vx?Kc#HeBoOrptwCw8k!)N7Nas zE{wCOFu#&pa``=)5s1tCnAxmgm8xfjQ*zMMKY+)hL_}<%tRn z?yQE)hmisz12ZdLSgJr&B>LjSjCxhj5Asjgg%~}(8i+sKyfD&IGNWbZr3?nREB6*Kc%0G${=kAb{vYz z8k*Zis_ZEzm=4lbPdQu*+ejf^vTESR8+CA*PfepsIx0i_?RULoMQzMRn(rlpO<&Vi zFF8;9YaP|~mUZOUUT*edRH~?qqwU_PqQM5v7Ucfr0epA|@malKyq3jekZs2VwfU9G z>L*i-1!;b5HTl9@1vkWZ=x+-1oEVNPT-g48Z9lzNOvXipZz!q){Y`46Pv@*dWP6`k zUlcvr+2p}Jn*bk;iIiImEnT;sekvy0nOpsXljuIOjn-m4P4JO1TI71#>?4!3i4*9# zj~r{RWpShAb*2!S>nqC#xvw)SspVS9uC;X9R|aZJ*V6C4GD^#@NWOluzPbEgUXn}t8&#EfN&_jP|Gk-J2or8A=(yDqUi}_2} zH*Mk=>S&dt13n+EPCHdoL&=Cr@X6?$pRIDcraf9l*+H_Q>3?)ue|QIjL5 zpzL7TSUdg+o#$uvCu9wgeTLQi1Qar3bq8<$61m9?vZ^!NH%I7RAEw7j~ZE#Ln897z6-U3T;m#Hxm zlsIdq9SPKE7cOFYP)-(!c=-1Br$~6?!qIi_85(g?gdB#w-GdP_DB)9PPJKs19Z_!l zpfG_Kq&A3sK5l}oS-H%}%nM1CIpBd81w_ia#rOjR1Dgr$XNOYXNZBZu)3U8y)u*ZI z6XbTRy~ttO8!2~dXZBEPd0EDEix!lZwF9{|4iH=~gDRMRi+(LHYieKiqmU^1lWl|2 z7LpzL>~m-Hgkb=OHJSpVWrsj+xFd_>Yr*`7G&x#UD7K!l^8OSLT*jMBUq#DC+7Er{ zS+pFb#eYS^E6BhK=K#PhO@%9PZT{SQI%(KesG5Iv9qp(f0}|J{wEmqG!_c{!c^vC| zgDSO30oCk9;cHOXnYd0R8kZ@Q{EEC|h;)Bz;W~V8<%U1zMGg^iCDo*YpwXuOergno!RwG8sGLn_}f)Ev7n^s490A z{U%xk1=sRFq4u$|n-*A&%2&fAvMgtPHL00=8+PHz72A!BAK$aEySgk}Y_;ApPPDh| zOLwZvL13KraWbInDwj|D`xuRe3}EG)Lr$;mOf%vjM!mbx;W$}ayU>|l#>w*DTRQ7X zL2`k0RcDH=AscFKJJZM-GN#%RFBnASc07!;c$ggQFZR4dqz5dt@M-y*pBC+=Gc{yY z$5oMRC$TZhA(xt1?Ebweq^7Ly73-nA`Jg)Q?nFIm%5~cLjybPt$_ZwzhM*7Y$TC`S zK`Z(Bz?_p?M_$xKhzWDd_8IK_Q(yXP_uc4deN3bW-Etn)m(@+$nwAvVQ2uIaN<|W6 z8FOXJ3#ybLJ2mjao+hN94PxBpmZky|U}a^v`oOxv^uf)o#*H<(!1u%X4t!HP(!m5w z!^OhrN`jmpp);b5`z1s5OKy~In7lquFOq6s+kvth$&T8$&FPm$G7h~H&{&o!;rxCd zn}N#kev}&R_6RUd#py(usC8_=fK)E zmz{#DH`WiHD!NSS$b?XIp}oyzsqicZ3EH$V@coXZb$1>_;3sB;d-S5Y9AL6jzZNpk zG?d1-z}q>x*+K?*&UO^9+PR(LatkK~#vpxB>q==RnM&I6}k6X&V=CoIm{%R@9ww&SlqF@h-xaIfc z?5WN!4pF7mrb@PT*GwHT+%t+@X4MZcusiSOY78K%TP&%?;Zc=KlNW0dw7Qk7ZJz#8 z()CvIy)qFmr5c!tL z>f1(!dS8CX)i4THpfID2tX1sSm(P`jG726&U0>#$Y9qflX*KK8(snXO8&*dd>P&O! z{q}OCdCn71pgpYdO(`u&MiraH6?osnqrlpxHf>Fkqdb1PFWvGMqf4hug!M7LgN%r+ zxtDhWag;Ki<;)zl@sI0~c?_{urtWrxPbEA*3am|#hd$~c$58v_mLf|!$|c%`U9_~L zY}u|qY%=fyh(#Bhp-!WvNx1A;V{c#mr&}7kBGfC)hWl|G1=M!+P{kd*T|HEz*Bxa! z9GxxONglVDaGi5rI6dqnM+6^vtdlVbn{b$h7Xd?{)*T`E#&wp}{Kt=lEQETEmcugy zPkXt1I@no;#nv|V5`39$9pXh@k)6~AVNkNIE5MB3b9zUT+U8R4?vv(x#)8pLqoNzTQW7Tkg*<#8!9wu5_%gaU&+eml! z6u1Z5Pu`{W-5_(SQc5>j&i9XAMcwvI9w;)P2*P!^DlP9OOEx}$)JA(UfW*Fn0!9qq zHpg;THw{mA5<+!Y3d>ntULG97#Ngp_zYaa`Cd0$NLm5y)w^pQevtPh&SLV~yG%x${ zlT@d>tgNNQ(%|kgUHhvF{nS&2lBI{N81ybSL<@_lYlT&<)T)OJv89f7R5J$N*=o3- zV8l|?jM&ovw7Q3^>*|WZdG4zhN zfzF+6J!wP`PPUJXcZkozdSMAx4cO3AhWmH_Ngd6CGm!%=O?_?}eCig?rod|w=~=#9 z$2j|xn+0eE`Gw<5BccrAWcxdEnk(u!@a!OQvJoFS$$q0IdGrG66)6^vA`aBoQgScI zWFKd~0X1n#FIhi*3HySg+IVJyws1t|6|BBId9y>~3v1iw3@2)@VYK*+4nv`yVE+Th zE>(ge{r(u8L*j8m8#r74ax4K?$3u41?=2I3kpcZ`Y=rsPhtlHSa&bU4WB`5Fb0ENM z?*n*Xu^K}OePs238v3_=`nQYfTZH;nnl|^5egW}%hEsZmJ1WD?3S78!5nH|mH>y{F z_!;r97A0|1zUW2@?<*@|@!zqpY>e9?7x#raQtboU(^p1n0Uyw4|jmw>?H z3WGCaJNavUXCM616t2?xd7(sm^evX7DqzK&vh;kQ?4bQoE2r)I@(+{w*Po@jt%G{c z^ssp!ddgFfG8=i=X!0O=*X&c8wQS?$ndv7gIYf5RrUy~l5cxWA!!>Exec9uAjtbUf zpLdOB4VC4}hj)Gf|A^5=_bhRTxWjH@@0;gj22I zvZ0>_pU6UT%Dh~fFw({kE2Qr0mg)7_C!3ZGNk z4`dV5ZTk2FXo{z3%LmeCnnd4!Ag6jM@zA}%S~&n?ul*<)VsfLwqhv2Q6dxM}X1_&$ zj)K7{*-D{lvPSx(OUx~Wh8;!c6qVQ+^9>I)Zdq3&1%?eHWy3waATJi3iRSZ2#3C?> ziQ~w*%qW}aOi8<_v*@^jBGxVb`XHbkH7ud@dX&Y7>VFkJz9>?{tPDHF|wp7ohpx!O|+9KG-`|t*Vb;MPsYer@p)_Y zUg0qUI?XQ5azdRKF?5MFXY@v}LdqzEQQYjcE>P%LS<2f}ZAvS1ZG3TRK31ObapQ>7 zu-xE*Gpl}7Zk()O8i5mxG9EU!8T>d$x#Q#%pQG=noR{z@uy*yOr13H=@|>QSrxIg) zdE>M20D`XG*(aZ-1>g;?C%e~Y4QX)PSc9e(+RRcsHMNlAQ@eP1rpXKERe!-I!u(&CeulpFiA#+ zUI1~RIN{6`G)3c%N`*wgNjfk|1}A>6XMkh3S}CB{*_i#Yr!I~m_NJ?!@aY9MiI}7C zKvN)_3#>!%2?L)u@2}9VIv%)bV6xn(o!dsgPnLbO`!}h1x{QkYbdi3gEf$)51IXwy zSUPv?22C;u1DUC^1|aP_tJ9Kn*$4sUuB5{b^Bp};mz%Uv3u%3ZOx4zICF>MfHu36K z6_U(`5{eHLm#)E!{pQcirH13FN;z>>ZyPodRpS$!b!B}+=~HA|&8r5TnIil9UPm-@ z6piI}CEI0HYV;8lzf9`+k!;bvG&W|PBYiZ7s)1X3Nft!LDY}o|D4iDjLcc51XWDFq zB(KJ@lGH#?w!?b=@FUq(yLX)uGi43aX_}lV1KhuTuDl@VP^edEk-dyP_S_`<0ECN} zqY?pbqj8i!q)8wJPn7`(JQO<>y30v!v10B@k~&P4t^5ZiK$!rtiYyrbV~?puJEqFY zrS(bDDX5d%>kO&#{O0|VUQWfB-1LfSO_LGY{l3&^nk*lD7g6U~w1aZ49=(5$pjFeP zEkuXO?wnt$@bre)u{*%^m@Xsf^)%_z=IHYRrWJ5OhZ%}M`G&gM3ea(xw@h#?Z_RTG zBjcP?80-*Nu+zO1*b$Y&kgE5VQDJB$7_-nX|8*0dG+3Q})LMT{J~L!u`eB_TQs8{uW?Pr;En37tWHS>9BVCP# zLKZprHT^wH_R|i{qHeS0cx_xyx-eU&lwHPwuw4oAiHeME9M(&=w+f|RSu(WkB-ea= zBkn{aANZaL;T@_I&gdd_FcUKqfBJNfK4`&U{5s*lb6RuOBZ9I!$|72|ar8F=XK9D` zQTsXAF|odnQ=GC&!XoTm0WDoQ9zBFPhlReAb8Or-2~f^K<6ID9QFEObYG!zXd#3Dj zWHoHogl0pd-BynpWXp2t)j1O%z|h?Q;#3*Kn@JTc8|>Qs%IWxxTAf3yh--D>(xClW z*K2WC;VLbrELITAwYY+uZs9VRN_%x`B=JB|m7d@f~*n|tWWM*OADBry=gZQ8x+LK9QdwM(2ax@l=_UO> zUsmVM&d`r#S#x>ZN0jif>|QI;(}k32R&dOPrj8-aCF_+nM5sQqB_w9URl?qt&VDQ_ z`>uW?Ywa@Ry+BqqH+W*9Mhm2W@TSvFiYZ1@oRwTSMGLZT&k_|(4aJu7q zS3a?26j-%`4lI)Gv?aaBYq4yuT^LTC7t4-;DZ5x#3IY*zUFiyb**oo`uNTXMlta>& zvX;meF4}{wkjmX6kr82uHeKk!Z~}*515uS@@;6kGU?u(hXWB~;A=gUN zOOjn(03L7X0&vuG8nRT5)W$WW8%tp*ZT=J4J^|YQHlWl`>H_N|DawgFw&aP zhbyq^?6{Sdt&p`Vc#cC;VI$j&qC7-X^-ZbQb@b$&NLITtx5v_}6|!D>e%-elHf0@e z7lGjs$>F|^2alryYmo7#V^tJyd4IqvhDwt8XwElWBN&c}>=b%DU2aAdPU=_3eN4*a zbBWtNllH8XS^i}%J2+c+OD?dM&!=vyWOT*3o0%z@@H$hTLli^%cqArf7cLM~w-(<_ z+g8b-O1BSy@4*kew6d34rB?09T>Ux53*zQ3m!9&C9j`~}5u!VKK*kqX7vx*Wv`_d` z^lG`YSoUC`fg3V?LmyUq;YGpi|{G!UMp>p?yjHe1n3$P<_9HKAu(BPezbvJtd&tg z$2Kq{=JJ3_;AsT&6r5A8Z=kyCWE;~`nz>GvD&4$>OILD7+x=JSU71v1-TOOzyH36b zcB!ylHq~A?q15%*Yfam)pMnBR=d}|+ai5+|%`6V+YBfsRE*T6j=E(GdkSG zQj+3s;Vu~8O<2=ZTtIy`$-P?1)fBv0wz26Gg9>7i!f>%wVBHV$F=$*=m`~F-%R}06 zZ)(0pzN=lb(AF&=+PnXwhg)FuxO|OTY?bBwwKy;R5ROwBJJp&dZ3>Z@(%<_WA~!HpSnIyMo-=a0 zY^j-#6uhFZcgnajr5EW%FgJ`% z>OG3o?Z9&vN!l?|%r6naEA85)wp8k{OmtNlSQ?ZM*2k%8WAO_#^|0JxE;we$`=&?aNa3^c zWdWVH9=YMXM>#3+Uld z=}$L~LdpbH&T0IO3^!>`(ZO%AS6ON*-TzkB^e+C5&P2&PyHb_!WU$u; ze;sJDz42-4{GI$u8~L1C9+NRH*9vSeq321pd!3@$$6&P>UV>g8lR>V?Vt}|J+uT{E z7xsCM%a7k?t$W2CKzDvmzaN+NwY9G(;si`1DU;~T2`psJ;a)ais5vvHo}kF@WvMdX zq!*4!981gfFvet*J|_DurUBo}VOpPTy7WEzC&QNxo&*(IO<=f{DdZH4#0Ky|J`OB) zd`EXr$p@OH7F{`w@$`cyScfAFoVrWqv_|Mo53+`-#J;{YyDUU1gH-q?}?IB^t?n! zgmx5j9_r{HMS)Vbx5bm!E$8;o-19O(n=?J<)AR5nsHL-qT9spMZ(UJD$3MaTQLe%7 zSd}X~iE-wZXF5w-PV7Z&jK002fKyBABvQ6@oCm|16P^L)vxgp{372Fitti5!T>|3R z91%arKed5j^!E<{bB=<3lwm%%EG}g_eN9b%l(ig#fCWe_@cW-@p4SIx>5p>y+j&~J z=IMEW>RpB%sZ}LfbXoqOg{IPwE11|i*lFz*IAvBFNms7O@G8frE49PMjfKi%_Z`2BC6z4qd$_t7@h4$m_anuQkh|-q+zE6ZRFYx-Q3R zhh|gYPY^DrvT{EB2{vu*i_Ns+XKWAk+(zI04A#o5K-F)^nxMqs8?u>?)lH|wL#E!9 zFX`Y7dC_!{7TlBxwzAj=gD^?b<%^czfQ8?<#BAfV;zD|S6L#>xtyKD!?5}-+Yd3CT z+Mm9KcHV+gK6e0}yCuuEy)+O!gZ{}y4F%S?Ef~iD*xfA+_pv~2fp37ZNuzWaXm;yW z0pqQ}s&NU-SgQG$z=PdjM?wS=lRZ`|!j3#9{G|ZTX z2P#t@QjNWSsB2pW&@WGA6vc*_+-d%7X;~QikEFogFcLb#IsZ585#aR6Z?a|Bw=i!y zO&e)J3_70iNw#nLl}g{10oCXI%JTxB&1TVyMU)Lqg>rNPYp0XXJy{jL%?~s;8FOH) z{hpwd+cM31e~ZJA?lj>1@C!Y<4eIUwh5YVd@)-RYHM)btaWClk9a(1KgY%MBcQ$*q z#f*;1fC%r!CJ06l^560d)i{vACW)#u757PbaK=>ShynZ|@EHGdCa6J~@PejCLxqh_ z{4V#Fo?X&OS{|>?Stpy9``wah?Oo{kUN7jtT@0gbPmJnNHGb3GyYP-Zap5@y*dYXe zqLy|!sL2<7^jR~B$*UJN4BV($|EJi;cc;UTWP|tCaLO!ZLB&$p zxO_yVD4sIns5zJlu;78G`y;}$KwsLV*w@unq9Pghtt7926~JfO3idQ(3wZF zYST3e?*G4rRs%%La+O@<%GpLUIEuW8n$J4Z3Lg z;CnqLjlE}QT_~}RGOLl`r91z`NMdi1ua=PcFIn4P*%6FSyyz^jV!4_0m$W85KZi?D z3^LgF!V-{}y-0T+QWcl($~=z!W{wkXW5)0RhoWC7OcNPn zyQw4Uz%DI}qkJR#7zC4nr3c^i+U#%m2V?;`&*#tm6<>>3VHY`KPOuZj^5HF@Fn z6~4vtA!xik?|VX+%f*IDh>#j#3yY@vQ@dT}kIWw>8H|yX2R2uafk7 zp4lH4T++jTF(K|aP350Ro96eLT0Vj2LhA`M;fYKz&8GuTux?F$PDP)})>?_@)a@xg zFK$b-p2{lG@3lpfFa%&VR||4%i0z%H7UU3zx*ovP{iiKU_}1Ff7de%mVG~!I|D0Mq zhk1ERe;W2&#)yQrP(eSA^D03*p38UA_x;Mk%p-5QL04|(K|Kxk`hgUj@U@Wu2GbM1 zF%mjC5-u7EjU5RWjD)I=gsVn^&5>Z|gc7qnV4E_a-qf>D#vF4+I{reI*X|srM=xa6 zkeYD6dc(&rK^GArHmdhh)~VBOjEf;&w?ZZ`Rpz5r_GYd1J*~Xes+ZNIV|=R6ns&aF zv8F8g?XRGIG)$zMuh3;ZT9N5Bw2I!dDf+eStF0JD zvtP@W0iVOo7b6Z$Gk7<_UZMGO>X71ro31NK#OLZL-Pw~itN=6Z>3?#16v!}5>;D&x zHCdW#Gmg!1JuhIr4E(<+JV+sL*wmjMr*}0=b*;%` zBF$1;`*ILn&@2(!te*5tv&2N5%4RWSSQC6v(q0y@07~%+3n%84*-fa8*%IZo?HYOl z+#hS77Ec*wOUa_T2#_-iJgM(V5yqDr>_j1qxl+ozZ!8N}BT=oh_13ew=fa-_1q1O4 z5yceA%+*-F+I(`5gfYmzfx3$xXU;=rd`)xY6)G>|VzZytzd?F6t)c+Ae%z&hocMng zln-dGu!N*DkUPldaN~F6RXPOv%7~q(n+Zy(lPqb7k-LcroozjO6-3GQzJy1C^~X#V zo+O*qfzVpYz&KIgF65mCH>RKZCh-kpG|g>H!^Cuz(o&Djnr0f!E7gXa6Ag}6E7d`c zH#S;>2CQPKLMLk~Ffgb$)Dz4)lyN!~N4W$AWw`-G-GByaF@H0ZK>IX+;rq^JqU+q! zhVrb%_ScotQlV**eGUR`0M{rT<_89pLE9%V z=^BgkGU#3G=V3}=_F{H|T*+6mDz?B{?;}OQEPdcH_kEZEQ2GgF+BHK9;j2!+GymK` zx6AZvpxb5osP`y@J+?G7X_Lp3t%#*0)c6KPEWss$uP{0FepDvzFR#$xB9>}CGx-DR zx&>71F*E72B9?Vp>tt$Q)Y4sR8%$e@T83#iN>PxfrIvPjBz5q#)D9d|Tc5s`D*TPY zTk6qTPfL*2qBiaKv>fU^85iksBN?)D6{GGBP6a1i`oX2%D$|Sw-r2-##7}XBIS51%1M6{JvmUrUZ= zIZqybmde`f?G*24>8+)oBjWcLpXVI&vne@nQwXB2Js zx70Unr2GDs8gQa1YqiuU`7PqKVz4!gO<1e4Kpi@>$71Iaw(rQ_teUwJ?11vFGmo)l1z*5Tmtl%ZxK!Rx`6%Dk6`qqkN z+Nmvds7{SWQjI`MSFOfo$_}(t)Z91I{y+;K7Pt{;DeYDMgrok`H z(!M)RD}pRTwdCVeG}!X2WZP&REQ?fKg5_Ui{GbPP9iC$gu}m?UM^=zDf2YT0n!iEo zVLmiO*F!#wa_AwI$D4iVWm|-9TUOFCLEHZw1(vdOFuxpRQ6Xj0O98&)}f(hquW6WR*?KyzL%2}#t=WkNma+dYlii7mH97vvYh+2hP;!5|| zSJDtd_wf@=vT?!gEQ4aof;6~k+(y1O%|b`REn~Ep{!}-@a!hM*kVK?qhW2e3Wk&*h zKMT!|^YW*Ibv*(pd7{ZZ=V7E}jY+%Imli}>hG_0Js36KRUYip~A4Xfsdl{#?v4B6( zhdz(C9QV0c5`*lR(P@u+6FM!5lK${?&-q^kOA(W{vlktVu>_iW<@^|9xoI}{4$x)c zFIHU^-mvm}6!~n>u9;)HaqkYNK4UdMx>?I2DYvS{UF&k5PE@r_(e8afZK_!wX-`H{ z!|Ij=K6Q73=Goqz@hGq!>`b?+L-K9OqTo2oU~N|_O^dUXF`w~$PFvzE{j~48kyj1q z6`l4|iyD?H=GQ*YX?zV!serxSg^So^9!?-)upfP1!%|JFf0}-&Vad`u&!XWqEoHQ3 zx9H=VmK|EgOln-qQp^0p`#DXlWr+-k^wkwI7B0CgH~^%W5ACT1ji%~J`lFWRwzgwD zU5vN%(XvKU_1cz==5a-y)AiaIh11EijwQ_8*7G@4sDokHkf$G`2O7P-QL`RfC>nRG!Yxs zhNv_vcI;iTcg5b@H^vfsFg}e9d++6pv0yYNny6^hM2$5@u|Fqt6{LM8&89(X*-qp`nD1Ye5zS*rXGm^kZPvm zi5RSmX0j$}5k>ab6a%1mDj0n)x~>SR3KW}%4++}Ot2goomscO9(MeiSC2u8B5&}71 zqccfb5C5d!O(7LQ_&Oo?K0%Qz_`Hw^PWyx>n48sR`BM?mQWe zM?{F#FuzBdcbRHc*Gd-7$`X}*gP%O_;mRF2$^NB$g;7P z%u+-1V*G)3IM`kH3e(EQZmM*YDW(cu~w&Wt2MP`W$LdK zR7>ln#MYqcwJ^iCeMc{AX~ppgrGVOqtwE!xNo|ePGI>UNP#Yt|v-d{6YO%r{;t{$B zMIYc;IV{g+q(?32&7BlyP?cdZ3z`g-}_^h7cB+bcb)C)(Fg!qWa1G`2BlDv?1K8f)Ro_XFu&W6bkwGpT)= zwp;1;oC-D3x+`@D(5NOFZmXWr2b*GKE0#@9o5JxGZ}Ovq3R8n- zTCkxa^>3zCF4p;PBcD^kJoe`XV6hRFI*Z=}&T0@AmOJ!k`mUK)yh!6CV#5>DPX6s- z4w^>kT~&W-wA)lzdA60xHrG;>Q*&rob5Ni0)JTh(Yt_rONfS3n7z6ax&kdl??ev#G zD@KNF-VC5U{1kJr{`hNfX4Yae4#GDvs@6jD#EW7LTVP1|t~X`0(0l{4gw=p?4^AR0xp^a3g_on!k7(iBUwvBG7RWT?vd(qxjT80ue(^jgr zR^E`{_Ygc`F``4eEh}sPwo?58G+QmG1YbV0$f?W!@K_ zVDxm5f-efiX>Q6lYi-@zYXg+PJ?Ua;%+E6$|G8K`r*l($Zz{K8GkV$)H_^A!$+r_4 zobWld>7;d0`oE`xowTo%fA3QBbUXqw?%f;uB3-MmEWb^^rfYi*;WWE5R&2Q)=yGSQ zVrt(ZV;3!4z5E7mzIMUNVQ3lZ*hQ-};l?fL6ETtqlc)6*+_vc;7T%B{YwuMeTe~+h zaT@2^p0hR*5qJWBvhL5*e~6~HhT5s)(FWoeX9OkQif2s1u#8OBWYeA&9APm<#ctPQp3bC zsp21N9@CGzyv_SCWd*YHs!PeB|NA;R;}=KNa0$z&)p{!>4$}0#S{bE9FzxB9 zH3;#j;B?=EN1wQhdHcm3dund(0SfJhMc}i}G^d{y9%%0DeCts}HxHWmGYDJp+KU#4 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 delta 270776 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≷GeC(HIh4ZvSvCkMYxpTk6_1+<6 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 delta 32142 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 - + diff --git a/MySQL.Data/src/MySql.Data.csproj b/MySQL.Data/src/MySql.Data.csproj index c14166c20..088019be2 100644 --- a/MySQL.Data/src/MySql.Data.csproj +++ b/MySQL.Data/src/MySql.Data.csproj @@ -52,15 +52,15 @@ - - + + - + - + diff --git a/MySQL.Data/src/X/Protocol/X/Protobuf/Mysqlx.cs b/MySQL.Data/src/X/Protocol/X/Protobuf/Mysqlx.cs index 4886b7196..be76ea51a 100644 --- a/MySQL.Data/src/X/Protocol/X/Protobuf/Mysqlx.cs +++ b/MySQL.Data/src/X/Protocol/X/Protobuf/Mysqlx.cs @@ -264,7 +264,11 @@ public void MergeFrom(pb::CodedInputStream input) #else uint tag; while ((tag = input.ReadTag()) != 0) { - switch(tag) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; @@ -281,6 +285,11 @@ public void MergeFrom(pb::CodedInputStream input) uint tag; while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) + { + // Abort on any end group tag. + return; + } switch (tag) { default: @@ -486,7 +495,11 @@ public void MergeFrom(pb::CodedInputStream input) #else uint tag; while ((tag = input.ReadTag()) != 0) { - switch(tag) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; @@ -503,6 +516,11 @@ public void MergeFrom(pb::CodedInputStream input) uint tag; while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) + { + // Abort on any end group tag. + return; + } switch (tag) { default: @@ -742,7 +760,11 @@ public void MergeFrom(pb::CodedInputStream input) #else uint tag; while ((tag = input.ReadTag()) != 0) { - switch(tag) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; @@ -763,6 +785,11 @@ public void MergeFrom(pb::CodedInputStream input) uint tag; while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) + { + // Abort on any end group tag. + return; + } switch (tag) { default: @@ -1143,7 +1170,11 @@ public void MergeFrom(pb::CodedInputStream input) #else uint tag; while ((tag = input.ReadTag()) != 0) { - switch(tag) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; @@ -1176,6 +1207,11 @@ public void MergeFrom(pb::CodedInputStream input) uint tag; while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) + { + // Abort on any end group tag. + return; + } switch (tag) { default: diff --git a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxConnection.cs b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxConnection.cs index 8a72ed424..b5f4aec39 100644 --- a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxConnection.cs +++ b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxConnection.cs @@ -325,7 +325,11 @@ public void MergeFrom(pb::CodedInputStream input) #else uint tag; while ((tag = input.ReadTag()) != 0) { - switch(tag) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; @@ -353,6 +357,11 @@ public void MergeFrom(pb::CodedInputStream input) uint tag; while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) + { + // Abort on any end group tag. + return; + } switch (tag) { default: @@ -551,7 +560,11 @@ public void MergeFrom(pb::CodedInputStream input) #else uint tag; while ((tag = input.ReadTag()) != 0) { - switch(tag) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; @@ -572,6 +585,11 @@ public void MergeFrom(pb::CodedInputStream input) uint tag; while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) + { + // Abort on any end group tag. + return; + } switch (tag) { default: @@ -742,7 +760,11 @@ public void MergeFrom(pb::CodedInputStream input) #else uint tag; while ((tag = input.ReadTag()) != 0) { - switch(tag) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; @@ -759,6 +781,11 @@ public void MergeFrom(pb::CodedInputStream input) uint tag; while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) + { + // Abort on any end group tag. + return; + } switch (tag) { default: @@ -967,7 +994,11 @@ public void MergeFrom(pb::CodedInputStream input) #else uint tag; while ((tag = input.ReadTag()) != 0) { - switch(tag) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; @@ -991,6 +1022,11 @@ public void MergeFrom(pb::CodedInputStream input) uint tag; while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) + { + // Abort on any end group tag. + return; + } switch (tag) { default: @@ -1167,7 +1203,11 @@ public void MergeFrom(pb::CodedInputStream input) #else uint tag; while ((tag = input.ReadTag()) != 0) { - switch(tag) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; @@ -1184,6 +1224,11 @@ public void MergeFrom(pb::CodedInputStream input) uint tag; while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) + { + // Abort on any end group tag. + return; + } switch (tag) { default: @@ -1548,7 +1593,11 @@ public void MergeFrom(pb::CodedInputStream input) #else uint tag; while ((tag = input.ReadTag()) != 0) { - switch(tag) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; @@ -1581,6 +1630,11 @@ public void MergeFrom(pb::CodedInputStream input) uint tag; while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) + { + // Abort on any end group tag. + return; + } switch (tag) { default: @@ -1618,3 +1672,4 @@ public void MergeFrom(pb::CodedInputStream input) } #endregion Designer generated code + diff --git a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxCrud.cs b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxCrud.cs index 84c2a818e..75e212cd8 100644 --- a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxCrud.cs +++ b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxCrud.cs @@ -489,7 +489,11 @@ public void MergeFrom(pb::CodedInputStream input) #else uint tag; while ((tag = input.ReadTag()) != 0) { - switch(tag) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; @@ -518,6 +522,11 @@ public void MergeFrom(pb::CodedInputStream input) uint tag; while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) + { + // Abort on any end group tag. + return; + } switch (tag) { default: @@ -788,7 +797,11 @@ public void MergeFrom(pb::CodedInputStream input) #else uint tag; while ((tag = input.ReadTag()) != 0) { - switch(tag) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; @@ -816,6 +829,11 @@ public void MergeFrom(pb::CodedInputStream input) uint tag; while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) + { + // Abort on any end group tag. + return; + } switch (tag) { default: @@ -1089,7 +1107,11 @@ public void MergeFrom(pb::CodedInputStream input) #else uint tag; while ((tag = input.ReadTag()) != 0) { - switch(tag) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; @@ -1114,6 +1136,11 @@ public void MergeFrom(pb::CodedInputStream input) uint tag; while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) + { + // Abort on any end group tag. + return; + } switch (tag) { default: @@ -1393,7 +1420,11 @@ public void MergeFrom(pb::CodedInputStream input) #else uint tag; while ((tag = input.ReadTag()) != 0) { - switch(tag) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; @@ -1418,6 +1449,11 @@ public void MergeFrom(pb::CodedInputStream input) uint tag; while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) + { + // Abort on any end group tag. + return; + } switch (tag) { default: @@ -1676,7 +1712,11 @@ public void MergeFrom(pb::CodedInputStream input) #else uint tag; while ((tag = input.ReadTag()) != 0) { - switch(tag) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; @@ -1707,6 +1747,11 @@ public void MergeFrom(pb::CodedInputStream input) uint tag; while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) + { + // Abort on any end group tag. + return; + } switch (tag) { default: @@ -1979,7 +2024,11 @@ public void MergeFrom(pb::CodedInputStream input) #else uint tag; while ((tag = input.ReadTag()) != 0) { - switch(tag) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; @@ -2007,6 +2056,11 @@ public void MergeFrom(pb::CodedInputStream input) uint tag; while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) + { + // Abort on any end group tag. + return; + } switch (tag) { default: @@ -2338,7 +2392,11 @@ public void MergeFrom(pb::CodedInputStream input) #else uint tag; while ((tag = input.ReadTag()) != 0) { - switch(tag) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; @@ -2373,6 +2431,11 @@ public void MergeFrom(pb::CodedInputStream input) uint tag; while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) + { + // Abort on any end group tag. + return; + } switch (tag) { default: @@ -3070,7 +3133,11 @@ public void MergeFrom(pb::CodedInputStream input) #else uint tag; while ((tag = input.ReadTag()) != 0) { - switch(tag) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; @@ -3150,6 +3217,11 @@ public void MergeFrom(pb::CodedInputStream input) uint tag; while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) + { + // Abort on any end group tag. + return; + } switch (tag) { default: @@ -3650,7 +3722,11 @@ public void MergeFrom(pb::CodedInputStream input) #else uint tag; while ((tag = input.ReadTag()) != 0) { - switch(tag) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; @@ -3694,6 +3770,11 @@ public void MergeFrom(pb::CodedInputStream input) uint tag; while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) + { + // Abort on any end group tag. + return; + } switch (tag) { default: @@ -3913,7 +3994,11 @@ public void MergeFrom(pb::CodedInputStream input) #else uint tag; while ((tag = input.ReadTag()) != 0) { - switch(tag) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; @@ -3934,6 +4019,11 @@ public void MergeFrom(pb::CodedInputStream input) uint tag; while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) + { + // Abort on any end group tag. + return; + } switch (tag) { default: @@ -4398,7 +4488,11 @@ public void MergeFrom(pb::CodedInputStream input) #else uint tag; while ((tag = input.ReadTag()) != 0) { - switch(tag) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; @@ -4459,6 +4553,11 @@ public void MergeFrom(pb::CodedInputStream input) uint tag; while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) + { + // Abort on any end group tag. + return; + } switch (tag) { default: @@ -4946,7 +5045,11 @@ public void MergeFrom(pb::CodedInputStream input) #else uint tag; while ((tag = input.ReadTag()) != 0) { - switch(tag) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; @@ -5003,6 +5106,11 @@ public void MergeFrom(pb::CodedInputStream input) uint tag; while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) + { + // Abort on any end group tag. + return; + } switch (tag) { default: @@ -5595,7 +5703,11 @@ public void MergeFrom(pb::CodedInputStream input) #else uint tag; while ((tag = input.ReadTag()) != 0) { - switch(tag) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; @@ -5650,6 +5762,11 @@ public void MergeFrom(pb::CodedInputStream input) uint tag; while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) + { + // Abort on any end group tag. + return; + } switch (tag) { default: @@ -6185,7 +6302,11 @@ public void MergeFrom(pb::CodedInputStream input) #else uint tag; while ((tag = input.ReadTag()) != 0) { - switch(tag) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; @@ -6236,6 +6357,11 @@ public void MergeFrom(pb::CodedInputStream input) uint tag; while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) + { + // Abort on any end group tag. + return; + } switch (tag) { default: @@ -6539,7 +6665,11 @@ public void MergeFrom(pb::CodedInputStream input) #else uint tag; while ((tag = input.ReadTag()) != 0) { - switch(tag) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; @@ -6567,6 +6697,11 @@ public void MergeFrom(pb::CodedInputStream input) uint tag; while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) + { + // Abort on any end group tag. + return; + } switch (tag) { default: @@ -6598,3 +6733,4 @@ public void MergeFrom(pb::CodedInputStream input) } #endregion Designer generated code + diff --git a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxCursor.cs b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxCursor.cs index 7bbd2d0fb..235ec14bb 100644 --- a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxCursor.cs +++ b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxCursor.cs @@ -393,7 +393,11 @@ public void MergeFrom(pb::CodedInputStream input) #else uint tag; while ((tag = input.ReadTag()) != 0) { - switch(tag) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; @@ -425,6 +429,11 @@ public void MergeFrom(pb::CodedInputStream input) uint tag; while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) + { + // Abort on any end group tag. + return; + } switch (tag) { default: @@ -698,7 +707,11 @@ public void MergeFrom(pb::CodedInputStream input) #else uint tag; while ((tag = input.ReadTag()) != 0) { - switch(tag) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; @@ -726,6 +739,11 @@ public void MergeFrom(pb::CodedInputStream input) uint tag; while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) + { + // Abort on any end group tag. + return; + } switch (tag) { default: @@ -1042,7 +1060,11 @@ public void MergeFrom(pb::CodedInputStream input) #else uint tag; while ((tag = input.ReadTag()) != 0) { - switch(tag) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; @@ -1067,6 +1089,11 @@ public void MergeFrom(pb::CodedInputStream input) uint tag; while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) + { + // Abort on any end group tag. + return; + } switch (tag) { default: @@ -1307,7 +1334,11 @@ public void MergeFrom(pb::CodedInputStream input) #else uint tag; while ((tag = input.ReadTag()) != 0) { - switch(tag) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; @@ -1328,6 +1359,11 @@ public void MergeFrom(pb::CodedInputStream input) uint tag; while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) + { + // Abort on any end group tag. + return; + } switch (tag) { default: @@ -1350,3 +1386,4 @@ public void MergeFrom(pb::CodedInputStream input) } #endregion Designer generated code + diff --git a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxDatatypes.cs b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxDatatypes.cs index 014465646..bdf38ad39 100644 --- a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxDatatypes.cs +++ b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxDatatypes.cs @@ -628,7 +628,11 @@ public void MergeFrom(pb::CodedInputStream input) #else uint tag; while ((tag = input.ReadTag()) != 0) { - switch(tag) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; @@ -683,6 +687,11 @@ public void MergeFrom(pb::CodedInputStream input) uint tag; while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) + { + // Abort on any end group tag. + return; + } switch (tag) { default: @@ -1012,7 +1021,11 @@ public void MergeFrom(pb::CodedInputStream input) #else uint tag; while ((tag = input.ReadTag()) != 0) { - switch(tag) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; @@ -1037,6 +1050,11 @@ public void MergeFrom(pb::CodedInputStream input) uint tag; while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) + { + // Abort on any end group tag. + return; + } switch (tag) { default: @@ -1313,7 +1331,11 @@ public void MergeFrom(pb::CodedInputStream input) #else uint tag; while ((tag = input.ReadTag()) != 0) { - switch(tag) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; @@ -1338,6 +1360,11 @@ public void MergeFrom(pb::CodedInputStream input) uint tag; while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) + { + // Abort on any end group tag. + return; + } switch (tag) { default: @@ -1535,7 +1562,11 @@ public void MergeFrom(pb::CodedInputStream input) #else uint tag; while ((tag = input.ReadTag()) != 0) { - switch(tag) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; @@ -1556,6 +1587,11 @@ public void MergeFrom(pb::CodedInputStream input) uint tag; while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) + { + // Abort on any end group tag. + return; + } switch (tag) { default: @@ -1812,7 +1848,11 @@ public void MergeFrom(pb::CodedInputStream input) #else uint tag; while ((tag = input.ReadTag()) != 0) { - switch(tag) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; @@ -1840,6 +1880,11 @@ public void MergeFrom(pb::CodedInputStream input) uint tag; while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) + { + // Abort on any end group tag. + return; + } switch (tag) { default: @@ -2041,7 +2086,11 @@ public void MergeFrom(pb::CodedInputStream input) #else uint tag; while ((tag = input.ReadTag()) != 0) { - switch(tag) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; @@ -2062,6 +2111,11 @@ public void MergeFrom(pb::CodedInputStream input) uint tag; while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) + { + // Abort on any end group tag. + return; + } switch (tag) { default: @@ -2397,7 +2451,11 @@ public void MergeFrom(pb::CodedInputStream input) #else uint tag; while ((tag = input.ReadTag()) != 0) { - switch(tag) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; @@ -2439,6 +2497,11 @@ public void MergeFrom(pb::CodedInputStream input) uint tag; while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) + { + // Abort on any end group tag. + return; + } switch (tag) { default: @@ -2504,3 +2567,4 @@ public enum Type } #endregion Designer generated code + diff --git a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxExpect.cs b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxExpect.cs index f94ce7ad9..0c92b140e 100644 --- a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxExpect.cs +++ b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxExpect.cs @@ -309,7 +309,11 @@ public void MergeFrom(pb::CodedInputStream input) #else uint tag; while ((tag = input.ReadTag()) != 0) { - switch(tag) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; @@ -334,6 +338,11 @@ public void MergeFrom(pb::CodedInputStream input) uint tag; while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) + { + // Abort on any end group tag. + return; + } switch (tag) { default: @@ -673,7 +682,11 @@ public void MergeFrom(pb::CodedInputStream input) #else uint tag; while ((tag = input.ReadTag()) != 0) { - switch(tag) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; @@ -702,6 +715,11 @@ public void MergeFrom(pb::CodedInputStream input) uint tag; while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) + { + // Abort on any end group tag. + return; + } switch (tag) { default: @@ -927,7 +945,11 @@ public void MergeFrom(pb::CodedInputStream input) #else uint tag; while ((tag = input.ReadTag()) != 0) { - switch(tag) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; @@ -944,6 +966,11 @@ public void MergeFrom(pb::CodedInputStream input) uint tag; while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) + { + // Abort on any end group tag. + return; + } switch (tag) { default: @@ -961,3 +988,4 @@ public void MergeFrom(pb::CodedInputStream input) } #endregion Designer generated code + diff --git a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxExpr.cs b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxExpr.cs index f3a9d024b..dcb51f823 100644 --- a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxExpr.cs +++ b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxExpr.cs @@ -652,7 +652,11 @@ public void MergeFrom(pb::CodedInputStream input) #else uint tag; while ((tag = input.ReadTag()) != 0) { - switch(tag) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; @@ -723,6 +727,11 @@ public void MergeFrom(pb::CodedInputStream input) uint tag; while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) + { + // Abort on any end group tag. + return; + } switch (tag) { default: @@ -1082,7 +1091,11 @@ public void MergeFrom(pb::CodedInputStream input) #else uint tag; while ((tag = input.ReadTag()) != 0) { - switch(tag) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; @@ -1107,6 +1120,11 @@ public void MergeFrom(pb::CodedInputStream input) uint tag; while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) + { + // Abort on any end group tag. + return; + } switch (tag) { default: @@ -1445,7 +1463,11 @@ public void MergeFrom(pb::CodedInputStream input) #else uint tag; while ((tag = input.ReadTag()) != 0) { - switch(tag) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; @@ -1474,6 +1496,11 @@ public void MergeFrom(pb::CodedInputStream input) uint tag; while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) + { + // Abort on any end group tag. + return; + } switch (tag) { default: @@ -1540,7 +1567,7 @@ public enum Type /// ///for table: col\@doc_path, tbl.col\@doc_path col, tbl.col, schema.tbl.col ///for document collection: doc_path - ///// + ///// ///@par production list ///@code{unparsed} ///col_identifier: string "." string "." string | @@ -1884,7 +1911,11 @@ public void MergeFrom(pb::CodedInputStream input) #else uint tag; while ((tag = input.ReadTag()) != 0) { - switch(tag) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; @@ -1917,6 +1948,11 @@ public void MergeFrom(pb::CodedInputStream input) uint tag; while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) + { + // Abort on any end group tag. + return; + } switch (tag) { default: @@ -2168,7 +2204,11 @@ public void MergeFrom(pb::CodedInputStream input) #else uint tag; while ((tag = input.ReadTag()) != 0) { - switch(tag) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; @@ -2196,6 +2236,11 @@ public void MergeFrom(pb::CodedInputStream input) uint tag; while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) + { + // Abort on any end group tag. + return; + } switch (tag) { default: @@ -2444,7 +2489,11 @@ public void MergeFrom(pb::CodedInputStream input) #else uint tag; while ((tag = input.ReadTag()) != 0) { - switch(tag) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; @@ -2469,6 +2518,11 @@ public void MergeFrom(pb::CodedInputStream input) uint tag; while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) + { + // Abort on any end group tag. + return; + } switch (tag) { default: @@ -2664,7 +2718,11 @@ public void MergeFrom(pb::CodedInputStream input) #else uint tag; while ((tag = input.ReadTag()) != 0) { - switch(tag) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; @@ -2685,6 +2743,11 @@ public void MergeFrom(pb::CodedInputStream input) uint tag; while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) + { + // Abort on any end group tag. + return; + } switch (tag) { default: @@ -2947,7 +3010,11 @@ public void MergeFrom(pb::CodedInputStream input) #else uint tag; while ((tag = input.ReadTag()) != 0) { - switch(tag) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; @@ -2975,6 +3042,11 @@ public void MergeFrom(pb::CodedInputStream input) uint tag; while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) + { + // Abort on any end group tag. + return; + } switch (tag) { default: @@ -3179,7 +3251,11 @@ public void MergeFrom(pb::CodedInputStream input) #else uint tag; while ((tag = input.ReadTag()) != 0) { - switch(tag) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; @@ -3200,6 +3276,11 @@ public void MergeFrom(pb::CodedInputStream input) uint tag; while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) + { + // Abort on any end group tag. + return; + } switch (tag) { default: @@ -3222,3 +3303,4 @@ public void MergeFrom(pb::CodedInputStream input) } #endregion Designer generated code + diff --git a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxNotice.cs b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxNotice.cs index 887934d05..39a8bdee1 100644 --- a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxNotice.cs +++ b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxNotice.cs @@ -419,7 +419,11 @@ public void MergeFrom(pb::CodedInputStream input) #else uint tag; while ((tag = input.ReadTag()) != 0) { - switch(tag) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; @@ -448,6 +452,11 @@ public void MergeFrom(pb::CodedInputStream input) uint tag; while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) + { + // Abort on any end group tag. + return; + } switch (tag) { default: @@ -836,7 +845,11 @@ public void MergeFrom(pb::CodedInputStream input) #else uint tag; while ((tag = input.ReadTag()) != 0) { - switch(tag) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; @@ -865,6 +878,11 @@ public void MergeFrom(pb::CodedInputStream input) uint tag; while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) + { + // Abort on any end group tag. + return; + } switch (tag) { default: @@ -1164,7 +1182,11 @@ public void MergeFrom(pb::CodedInputStream input) #else uint tag; while ((tag = input.ReadTag()) != 0) { - switch(tag) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; @@ -1192,6 +1214,11 @@ public void MergeFrom(pb::CodedInputStream input) uint tag; while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) + { + // Abort on any end group tag. + return; + } switch (tag) { default: @@ -1443,7 +1470,11 @@ public void MergeFrom(pb::CodedInputStream input) #else uint tag; while ((tag = input.ReadTag()) != 0) { - switch(tag) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; @@ -1468,6 +1499,11 @@ public void MergeFrom(pb::CodedInputStream input) uint tag; while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) + { + // Abort on any end group tag. + return; + } switch (tag) { default: @@ -1782,7 +1818,11 @@ public void MergeFrom(pb::CodedInputStream input) #else uint tag; while ((tag = input.ReadTag()) != 0) { - switch(tag) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; @@ -1807,6 +1847,11 @@ public void MergeFrom(pb::CodedInputStream input) uint tag; while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) + { + // Abort on any end group tag. + return; + } switch (tag) { default: @@ -2002,7 +2047,11 @@ public void MergeFrom(pb::CodedInputStream input) #else uint tag; while ((tag = input.ReadTag()) != 0) { - switch(tag) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; @@ -2019,6 +2068,11 @@ public void MergeFrom(pb::CodedInputStream input) uint tag; while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) + { + // Abort on any end group tag. + return; + } switch (tag) { default: diff --git a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxPrepare.cs b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxPrepare.cs index ff9dfb598..aec5a7492 100644 --- a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxPrepare.cs +++ b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxPrepare.cs @@ -345,7 +345,11 @@ public void MergeFrom(pb::CodedInputStream input) #else uint tag; while ((tag = input.ReadTag()) != 0) { - switch(tag) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; @@ -373,6 +377,11 @@ public void MergeFrom(pb::CodedInputStream input) uint tag; while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) + { + // Abort on any end group tag. + return; + } switch (tag) { default: @@ -793,7 +802,11 @@ public void MergeFrom(pb::CodedInputStream input) #else uint tag; while ((tag = input.ReadTag()) != 0) { - switch(tag) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; @@ -849,6 +862,11 @@ public void MergeFrom(pb::CodedInputStream input) uint tag; while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) + { + // Abort on any end group tag. + return; + } switch (tag) { default: @@ -1234,7 +1252,11 @@ public void MergeFrom(pb::CodedInputStream input) #else uint tag; while ((tag = input.ReadTag()) != 0) { - switch(tag) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; @@ -1263,6 +1285,11 @@ public void MergeFrom(pb::CodedInputStream input) uint tag; while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) + { + // Abort on any end group tag. + return; + } switch (tag) { default: @@ -1508,7 +1535,11 @@ public void MergeFrom(pb::CodedInputStream input) #else uint tag; while ((tag = input.ReadTag()) != 0) { - switch(tag) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; @@ -1529,6 +1560,11 @@ public void MergeFrom(pb::CodedInputStream input) uint tag; while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) + { + // Abort on any end group tag. + return; + } switch (tag) { default: @@ -1551,3 +1587,4 @@ public void MergeFrom(pb::CodedInputStream input) } #endregion Designer generated code + diff --git a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxResultset.cs b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxResultset.cs index be579784d..909bf01e1 100644 --- a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxResultset.cs +++ b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxResultset.cs @@ -281,7 +281,11 @@ public void MergeFrom(pb::CodedInputStream input) #else uint tag; while ((tag = input.ReadTag()) != 0) { - switch(tag) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; @@ -298,6 +302,11 @@ public void MergeFrom(pb::CodedInputStream input) uint tag; while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) + { + // Abort on any end group tag. + return; + } switch (tag) { default: @@ -461,7 +470,11 @@ public void MergeFrom(pb::CodedInputStream input) #else uint tag; while ((tag = input.ReadTag()) != 0) { - switch(tag) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; @@ -478,6 +491,11 @@ public void MergeFrom(pb::CodedInputStream input) uint tag; while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) + { + // Abort on any end group tag. + return; + } switch (tag) { default: @@ -641,7 +659,11 @@ public void MergeFrom(pb::CodedInputStream input) #else uint tag; while ((tag = input.ReadTag()) != 0) { - switch(tag) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; @@ -658,6 +680,11 @@ public void MergeFrom(pb::CodedInputStream input) uint tag; while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) + { + // Abort on any end group tag. + return; + } switch (tag) { default: @@ -821,7 +848,11 @@ public void MergeFrom(pb::CodedInputStream input) #else uint tag; while ((tag = input.ReadTag()) != 0) { - switch(tag) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; @@ -838,6 +869,11 @@ public void MergeFrom(pb::CodedInputStream input) uint tag; while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) + { + // Abort on any end group tag. + return; + } switch (tag) { default: @@ -1999,7 +2035,11 @@ public void MergeFrom(pb::CodedInputStream input) #else uint tag; while ((tag = input.ReadTag()) != 0) { - switch(tag) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; @@ -2064,6 +2104,11 @@ public void MergeFrom(pb::CodedInputStream input) uint tag; while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) + { + // Abort on any end group tag. + return; + } switch (tag) { default: @@ -2336,7 +2381,11 @@ public void MergeFrom(pb::CodedInputStream input) #else uint tag; while ((tag = input.ReadTag()) != 0) { - switch(tag) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; @@ -2357,6 +2406,11 @@ public void MergeFrom(pb::CodedInputStream input) uint tag; while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) + { + // Abort on any end group tag. + return; + } switch (tag) { default: @@ -2379,3 +2433,4 @@ public void MergeFrom(pb::CodedInputStream input) } #endregion Designer generated code + diff --git a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxSession.cs b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxSession.cs index d844266ff..6a3c0f640 100644 --- a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxSession.cs +++ b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxSession.cs @@ -391,7 +391,11 @@ public void MergeFrom(pb::CodedInputStream input) #else uint tag; while ((tag = input.ReadTag()) != 0) { - switch(tag) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; @@ -420,6 +424,11 @@ public void MergeFrom(pb::CodedInputStream input) uint tag; while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) + { + // Abort on any end group tag. + return; + } switch (tag) { default: @@ -654,7 +663,11 @@ public void MergeFrom(pb::CodedInputStream input) #else uint tag; while ((tag = input.ReadTag()) != 0) { - switch(tag) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; @@ -675,6 +688,11 @@ public void MergeFrom(pb::CodedInputStream input) uint tag; while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) + { + // Abort on any end group tag. + return; + } switch (tag) { default: @@ -896,7 +914,11 @@ public void MergeFrom(pb::CodedInputStream input) #else uint tag; while ((tag = input.ReadTag()) != 0) { - switch(tag) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; @@ -917,6 +939,11 @@ public void MergeFrom(pb::CodedInputStream input) uint tag; while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) + { + // Abort on any end group tag. + return; + } switch (tag) { default: @@ -1144,7 +1171,11 @@ public void MergeFrom(pb::CodedInputStream input) #else uint tag; while ((tag = input.ReadTag()) != 0) { - switch(tag) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; @@ -1165,6 +1196,11 @@ public void MergeFrom(pb::CodedInputStream input) uint tag; while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) + { + // Abort on any end group tag. + return; + } switch (tag) { default: @@ -1335,7 +1371,11 @@ public void MergeFrom(pb::CodedInputStream input) #else uint tag; while ((tag = input.ReadTag()) != 0) { - switch(tag) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; @@ -1352,6 +1392,11 @@ public void MergeFrom(pb::CodedInputStream input) uint tag; while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) + { + // Abort on any end group tag. + return; + } switch (tag) { default: @@ -1369,3 +1414,4 @@ public void MergeFrom(pb::CodedInputStream input) } #endregion Designer generated code + diff --git a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxSql.cs b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxSql.cs index 87ff8feb8..825b21188 100644 --- a/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxSql.cs +++ b/MySQL.Data/src/X/Protocol/X/Protobuf/MysqlxSql.cs @@ -421,7 +421,11 @@ public void MergeFrom(pb::CodedInputStream input) #else uint tag; while ((tag = input.ReadTag()) != 0) { - switch(tag) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; @@ -454,6 +458,11 @@ public void MergeFrom(pb::CodedInputStream input) uint tag; while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) + { + // Abort on any end group tag. + return; + } switch (tag) { default: @@ -637,7 +646,11 @@ public void MergeFrom(pb::CodedInputStream input) #else uint tag; while ((tag = input.ReadTag()) != 0) { - switch(tag) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; @@ -654,6 +667,11 @@ public void MergeFrom(pb::CodedInputStream input) uint tag; while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) + { + // Abort on any end group tag. + return; + } switch (tag) { default: @@ -671,3 +689,4 @@ public void MergeFrom(pb::CodedInputStream input) } #endregion Designer generated code + From 0e32937dfef265fa6fd6d6f615860a98147699ee Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Wed, 12 Mar 2025 18:26:50 -0600 Subject: [PATCH 105/125] Updated EFCore dependencies Change-Id: I6003e5afae5538c62fdb12ccc3b2511fed23baac --- EFCore/src/MySql.EntityFrameworkCore.csproj | 8 ++++---- .../MySql.EntityFrameworkCore.Basic.Tests.csproj | 4 ++-- .../MySql.EntityFrameworkCore.Design.Tests.csproj | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/EFCore/src/MySql.EntityFrameworkCore.csproj b/EFCore/src/MySql.EntityFrameworkCore.csproj index 4c6eb9507..65aadc533 100644 --- a/EFCore/src/MySql.EntityFrameworkCore.csproj +++ b/EFCore/src/MySql.EntityFrameworkCore.csproj @@ -27,13 +27,13 @@ - - + + - - + + diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/MySql.EntityFrameworkCore.Basic.Tests.csproj b/EFCore/tests/MySql.EFCore.Basic.Tests/MySql.EntityFrameworkCore.Basic.Tests.csproj index 061239671..b650e7248 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/MySql.EntityFrameworkCore.Basic.Tests.csproj +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/MySql.EntityFrameworkCore.Basic.Tests.csproj @@ -18,11 +18,11 @@ - + - + diff --git a/EFCore/tests/MySql.EFCore.Design.Tests/MySql.EntityFrameworkCore.Design.Tests.csproj b/EFCore/tests/MySql.EFCore.Design.Tests/MySql.EntityFrameworkCore.Design.Tests.csproj index b63438b20..f163da6c3 100644 --- a/EFCore/tests/MySql.EFCore.Design.Tests/MySql.EntityFrameworkCore.Design.Tests.csproj +++ b/EFCore/tests/MySql.EFCore.Design.Tests/MySql.EntityFrameworkCore.Design.Tests.csproj @@ -34,11 +34,11 @@ - + - + From 1d14eae501085abac5f1a269b28992e27d20d50f Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Thu, 13 Mar 2025 13:05:50 -0600 Subject: [PATCH 106/125] Updated Documentation. Change-Id: I74756de74018067fc563d8ac36199246f6b29d2e --- Documentation/index.md | 4 ++-- README.md | 2 ++ Release Notes.txt | 8 ++++---- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/Documentation/index.md b/Documentation/index.md index 2e7520959..36f5c177e 100644 --- a/Documentation/index.md +++ b/Documentation/index.md @@ -1,6 +1,6 @@ ## MySQL Connector/NET and X DevAPI -MySQL Connector/NET 9.2 supports X Protocol, which enables you to use X DevAPI with the .NET language of choice to develop applications that communicate with a MySQL server functioning as a document store, relational database, or both. +MySQL Connector/NET 9.3 supports X Protocol, which enables you to use X DevAPI with the .NET language of choice to develop applications that communicate with a MySQL server functioning as a document store, relational database, or both. To get started, review the following main classes: @@ -16,7 +16,7 @@ For an introduction to X DevAPI concepts, see the [X DevAPI User Guide](https:// ## MySQL Connector/NET -MySQL Connector/NET 9.2 also supports the development of .NET, .NET Core and .NET Framework applications that require secure, high-performance data connectivity with MySQL through the classic protocol. It supports ADO.NET, Entity Framework and various web providers. +MySQL Connector/NET 9.3 also supports the development of .NET, .NET Core and .NET Framework applications that require secure, high-performance data connectivity with MySQL through the classic protocol. It supports ADO.NET, Entity Framework and various web providers. To get started, review the following main classes: diff --git a/README.md b/README.md index 8529fdb9a..3be431d7c 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,8 @@ From MySQL Connector/NET 9.2, the driver adds support for [.NET 9](https://learn From MySQL Connector/NET 9.2, the driver removes support for .NET 6 and EF Core 6. +From MySQL Connector/NET 9.3, the driver adds fixes to test suite and support for newest versions of EF Core 8 and EF Core 9. + For detailed information please visit the official [MySQL Connector/NET documentation](https://dev.mysql.com/doc/connector-net/en/). ## Licensing diff --git a/Release Notes.txt b/Release Notes.txt index 7d478a2ef..ccee1223a 100644 --- a/Release Notes.txt +++ b/Release Notes.txt @@ -1,9 +1,9 @@ -Connector/NET 9.2 Release Notes +Connector/NET 9.3 Release Notes ------------------------------------ Welcome to the release notes for Connector/NET 9.1 -What's new in 9.2 +What's new in 9.3 -------------------- -Connector/NET adds support for .NET 9 and EF Core 9 GA versions. -Connector/NET removes support for .NET6 and EFCore 6. \ No newline at end of file +Connector/NET now supports the newest version of EFCore 8 and EFCore 9. +Connector/NET added fixes to testsuite. \ No newline at end of file From bd4a3918c23b5dfc9e7e939b2cc26137deb3cbf6 Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Thu, 13 Mar 2025 13:09:02 -0600 Subject: [PATCH 107/125] Updated the LICENSE files. Change-Id: Ifc7000e917ce668b066cd258454465a01ea6f5d9 --- LICENSE | 1399 ++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 1323 insertions(+), 76 deletions(-) diff --git a/LICENSE b/LICENSE index bebd4dbf0..b1ca05180 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ Licensing Information User Manual -MySQL Connector/NET 9.2.0 Community +MySQL Connector/NET 9.3.0 Community __________________________________________________________________ Introduction @@ -8,18 +8,18 @@ Introduction This License Information User Manual contains Oracle's product license and other licensing information, including licensing information for third-party software which may be included in this distribution of - MySQL Connector/NET 9.2.0 Community. + MySQL Connector/NET 9.3.0 Community. - Last updated: November 2024 + Last updated: March 2025 Licensing Information - This release of MySQL Connector/NET 9.2.0 Community is brought to you + This release of MySQL Connector/NET 9.3.0 Community is brought to you by the MySQL team at Oracle. This software is released under version 2 of the GNU General Public License (GPLv2), as set forth below, with the following additional permissions: - This distribution of MySQL Connector/NET 9.2.0 Community is designed to + This distribution of MySQL Connector/NET 9.3.0 Community is designed to work with certain software (including but not limited to OpenSSL) that is licensed under separate terms, as designated in a particular file or component or in the license documentation. Without limiting your rights @@ -34,7 +34,7 @@ Licensing Information a copy of which is reproduced below and can also be found along with its FAQ at http://oss.oracle.com/licenses/universal-foss-exception. - Copyright (c) 2004, 2024, Oracle and/or its affiliates. + Copyright (c) 2004, 2025, Oracle and/or its affiliates. Election of GPLv2 @@ -519,58 +519,1333 @@ support library is itself covered by the above license. ====================================================================== ====================================================================== -K4os.Compression.LZ4.Streams +Kerberos5 -LICENSE file: -======== -MIT License +You may be receiving a copy of the kerberos documentation as part of this +product. The terms of the Oracle license do NOT apply to Kerberos documentation. -Copyright (c) 2017 Milosz Krajewski +Kerberos documentation is licensed under the CC-BY-SA 3.0 license, separate from -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +the Oracle product. +If you do not wish to install this library, you may remove it, but +the Oracle program might not operate properly or at all without it. -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. +Copyright (C) 1985-2019 by the Massachusetts Institute of Technology. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +All rights reserved. ------------------------------------------------------------------------------- -4th party dependency -(https://github.com/MiloszKrajewski/K4os.Hash.xxHash/archive/master.zip): -LICENSE File (same copyright): +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: -MIT License +* Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. -Copyright (c) 2017 Milosz Krajewski +* Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. +Downloading of this software may constitute an export of cryptographic +software from the United States of America that is subject to the +United States Export Administration Regulations (EAR), 15 CFR 730-774. +Additional laws or regulations may apply. It is the responsibility of +the person or entity contemplating export to comply with all +applicable export laws and regulations, including obtaining any +required license from the U.S. government. + +The U.S. government prohibits export of encryption source code to +certain countries and individuals, including, but not limited to, the +countries of Cuba, Iran, North Korea, Sudan, Syria, and residents and +nationals of those countries. + +Documentation components of this software distribution are licensed +under a Creative Commons Attribution-ShareAlike 3.0 Unported License. +(http://creativecommons.org/licenses/by-sa/3.0/) + +Individual source code files are copyright MIT, Cygnus Support, +Novell, OpenVision Technologies, Oracle, Red Hat, Sun Microsystems, +FundsXpress, and others. + +Project Athena, Athena, Athena MUSE, Discuss, Hesiod, Kerberos, Moira, +and Zephyr are trademarks of the Massachusetts Institute of Technology +(MIT). No commercial use of these trademarks may be made without +prior written permission of MIT. + +"Commercial use" means use of a name in a product or other for-profit +manner. It does NOT prevent a commercial firm from referring to the +MIT trademarks in order to convey information (although in doing so, +recognition of their trademark status should be given). + +====================================================================== + +The following copyright and permission notice applies to the +OpenVision Kerberos Administration system located in "kadmin/create", +"kadmin/dbutil", "kadmin/passwd", "kadmin/server", "lib/kadm5", and +portions of "lib/rpc": -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. + Copyright, OpenVision Technologies, Inc., 1993-1996, All Rights + Reserved + + WARNING: Retrieving the OpenVision Kerberos Administration system + source code, as described below, indicates your acceptance of the + following terms. If you do not agree to the following terms, do + not retrieve the OpenVision Kerberos administration system. + + You may freely use and distribute the Source Code and Object Code + compiled from it, with or without modification, but this Source + Code is provided to you "AS IS" EXCLUSIVE OF ANY WARRANTY, + INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY OR + FITNESS FOR A PARTICULAR PURPOSE, OR ANY OTHER WARRANTY, WHETHER + EXPRESS OR IMPLIED. IN NO EVENT WILL OPENVISION HAVE ANY LIABILITY + FOR ANY LOST PROFITS, LOSS OF DATA OR COSTS OF PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES, OR FOR ANY SPECIAL, INDIRECT, OR + CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, INCLUDING, + WITHOUT LIMITATION, THOSE RESULTING FROM THE USE OF THE SOURCE + CODE, OR THE FAILURE OF THE SOURCE CODE TO PERFORM, OR FOR ANY + OTHER REASON. + + OpenVision retains all copyrights in the donated Source Code. + OpenVision also retains copyright to derivative works of the Source + Code, whether created by OpenVision or by a third party. The + OpenVision copyright notice must be preserved if derivative works + are made based on the donated Source Code. + + OpenVision Technologies, Inc. has donated this Kerberos + Administration system to MIT for inclusion in the standard Kerberos + 5 distribution. This donation underscores our commitment to + continuing Kerberos technology development and our gratitude for + the valuable work which has been performed by MIT and the Kerberos + community. + +====================================================================== + + Portions contributed by Matt Crawford "crawdad@fnal.gov" were work +performed at Fermi National Accelerator Laboratory, which is + operated by Universities Research Association, Inc., under contract + DE-AC02-76CHO3000 with the U.S. Department of Energy. + +====================================================================== + +Portions of "src/lib/crypto" have the following copyright: + + Copyright (C) 1998 by the FundsXpress, INC. + + All rights reserved. + + Export of this software from the United States of America may + require a specific license from the United States Government. + It is the responsibility of any person or organization + contemplating export to obtain such a license before exporting. + + WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + distribute this software and its documentation for any purpose and + without fee is hereby granted, provided that the above copyright + notice appear in all copies and that both that copyright notice and + this permission notice appear in supporting documentation, and that + the name of FundsXpress. not be used in advertising or publicity + pertaining to distribution of the software without specific, + written prior permission. FundsXpress makes no representations + about the suitability of this software for any purpose. It is + provided "as is" without express or implied warranty. + + THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + +====================================================================== + +The implementation of the AES encryption algorithm in +"src/lib/crypto/builtin/aes" has the following copyright: + + Copyright (C) 2001, Dr Brian Gladman "brg@gladman.uk.net", Worcester, UK. + All rights reserved. + + LICENSE TERMS + + The free distribution and use of this software in both source and + binary form is allowed (with or without changes) provided that: + + 1. distributions of this source code include the above copyright + notice, this list of conditions and the following disclaimer; + + 2. distributions in binary form include the above copyright notice, + this list of conditions and the following disclaimer in the + documentation and/or other associated materials; + + 3. the copyright holder's name is not used to endorse products + built using this software without specific written permission. + + DISCLAIMER + + This software is provided 'as is' with no explcit or implied + warranties in respect of any properties, including, but not limited + to, correctness and fitness for purpose. + +====================================================================== + +Portions contributed by Red Hat, including the pre-authentication +plug-in framework and the NSS crypto implementation, contain the +following copyright: + + Copyright (C) 2006 Red Hat, Inc. + Portions copyright (C) 2006 Massachusetts Institute of Technology + All Rights Reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + * Neither the name of Red Hat, Inc., nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + OF THE POSSIBILITY OF SUCH DAMAGE. + +====================================================================== + +The bundled verto source code is subject to the following license: + + Copyright 2011 Red Hat, Inc. + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, copy, + modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + +====================================================================== + +The MS-KKDCP client implementation has the following copyright: + + Copyright 2013,2014 Red Hat, Inc. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + disclaimer. + + 2. Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + OF THE POSSIBILITY OF SUCH DAMAGE. + +====================================================================== + +The implementations of GSSAPI mechglue in GSSAPI-SPNEGO in +"src/lib/gssapi", including the following files: + + lib/gssapi/generic/gssapi_err_generic.et + lib/gssapi/mechglue/g_accept_sec_context.c + lib/gssapi/mechglue/g_acquire_cred.c + lib/gssapi/mechglue/g_canon_name.c + lib/gssapi/mechglue/g_compare_name.c + lib/gssapi/mechglue/g_context_time.c + lib/gssapi/mechglue/g_delete_sec_context.c + lib/gssapi/mechglue/g_dsp_name.c + lib/gssapi/mechglue/g_dsp_status.c + lib/gssapi/mechglue/g_dup_name.c + lib/gssapi/mechglue/g_exp_sec_context.c + lib/gssapi/mechglue/g_export_name.c + lib/gssapi/mechglue/g_glue.c + lib/gssapi/mechglue/g_imp_name.c + lib/gssapi/mechglue/g_imp_sec_context.c + lib/gssapi/mechglue/g_init_sec_context.c + lib/gssapi/mechglue/g_initialize.c + lib/gssapi/mechglue/g_inquire_context.c + lib/gssapi/mechglue/g_inquire_cred.c + lib/gssapi/mechglue/g_inquire_names.c + lib/gssapi/mechglue/g_process_context.c + lib/gssapi/mechglue/g_rel_buffer.c + lib/gssapi/mechglue/g_rel_cred.c + lib/gssapi/mechglue/g_rel_name.c + lib/gssapi/mechglue/g_rel_oid_set.c + lib/gssapi/mechglue/g_seal.c + lib/gssapi/mechglue/g_sign.c + lib/gssapi/mechglue/g_store_cred.c + lib/gssapi/mechglue/g_unseal.c + lib/gssapi/mechglue/g_userok.c + lib/gssapi/mechglue/g_utils.c + lib/gssapi/mechglue/g_verify.c + lib/gssapi/mechglue/gssd_pname_to_uid.c + lib/gssapi/mechglue/mglueP.h + lib/gssapi/mechglue/oid_ops.c + lib/gssapi/spnego/gssapiP_spnego.h + lib/gssapi/spnego/spnego_mech.c + +and the initial implementation of incremental propagation, including +the following new or changed files: + + include/iprop_hdr.h + kadmin/server/ipropd_svc.c + lib/kdb/iprop.x + lib/kdb/kdb_convert.c + lib/kdb/kdb_log.c + lib/kdb/kdb_log.h + lib/krb5/error_tables/kdb5_err.et + slave/kpropd_rpc.c + slave/kproplog.c + +are subject to the following license: + + Copyright (C) 2004 Sun Microsystems, Inc. + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, copy, + modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + +====================================================================== + +Kerberos V5 includes documentation and software developed at the +University of California at Berkeley, which includes this copyright +notice: + + Copyright (C) 1983 Regents of the University of California. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + + 3. Neither the name of the University nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS + OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + +====================================================================== + +Portions contributed by Novell, Inc., including the LDAP database +backend, are subject to the following license: + + Copyright (C) 2004-2005, Novell, Inc. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + * The copyright holder's name is not used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + OF THE POSSIBILITY OF SUCH DAMAGE. + +====================================================================== + +Portions funded by Sandia National Laboratory and developed by the +University of Michigan's Center for Information Technology +Integration, including the PKINIT implementation, are subject to the +following license: + + COPYRIGHT (C) 2006-2007 + THE REGENTS OF THE UNIVERSITY OF MICHIGAN + ALL RIGHTS RESERVED + + Permission is granted to use, copy, create derivative works and + redistribute this software and such derivative works for any + purpose, so long as the name of The University of Michigan is not + used in any advertising or publicity pertaining to the use of + distribution of this software without specific, written prior + authorization. If the above copyright notice or any other + identification of the University of Michigan is included in any + copy of any portion of this software, then the disclaimer below + must also be included. + + THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION FROM THE + UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY PURPOSE, AND + WITHOUT WARRANTY BY THE UNIVERSITY OF MICHIGAN OF ANY KIND, EITHER + EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + THE REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE FOR + ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR + CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING OUT OF OR + IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN IF IT HAS BEEN OR + IS HEREAFTER ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + +====================================================================== + +The pkcs11.h file included in the PKINIT code has the following +license: + + Copyright 2006 g10 Code GmbH + Copyright 2006 Andreas Jellinghaus + + This file is free software; as a special exception the author gives + unlimited permission to copy and/or distribute it, with or without + modifications, as long as this notice is preserved. + + This file is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY, to the extent permitted by law; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. + +====================================================================== + +Portions contributed by Apple Inc. are subject to the following +license: + + Copyright 2004-2008 Apple Inc. All Rights Reserved. + + Export of this software from the United States of America may + require a specific license from the United States Government. + It is the responsibility of any person or organization + contemplating export to obtain such a license before exporting. + + WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + distribute this software and its documentation for any purpose and + without fee is hereby granted, provided that the above copyright + notice appear in all copies and that both that copyright notice and + this permission notice appear in supporting documentation, and that + the name of Apple Inc. not be used in advertising or publicity + pertaining to distribution of the software without specific, + written prior permission. Apple Inc. makes no representations + about the suitability of this software for any purpose. It is + provided "as is" without express or implied warranty. + + THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + +====================================================================== + +The implementations of UTF-8 string handling in src/util/support and +src/lib/krb5/unicode are subject to the following copyright and +permission notice: + + The OpenLDAP Public License + Version 2.8, 17 August 2003 + + Redistribution and use of this software and associated + documentation ("Software"), with or without modification, are + permitted provided that the following conditions are met: + + 1. Redistributions in source form must retain copyright statements + and notices, + + 2. Redistributions in binary form must reproduce applicable + copyright statements and notices, this list of conditions, and + the following disclaimer in the documentation and/or other + materials provided with the distribution, and + + 3. Redistributions must contain a verbatim copy of this document. + + The OpenLDAP Foundation may revise this license from time to time. + Each revision is distinguished by a version number. You may use + this Software under terms of this license revision or under the + terms of any subsequent revision of the license. + + THIS SOFTWARE IS PROVIDED BY THE OPENLDAP FOUNDATION AND ITS + CONTRIBUTORS "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE OPENLDAP FOUNDATION, ITS + CONTRIBUTORS, OR THE AUTHOR(S) OR OWNER(S) OF THE SOFTWARE BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + DAMAGE. + + The names of the authors and copyright holders must not be used in + advertising or otherwise to promote the sale, use or other dealing + in this Software without specific, written prior permission. Title + to copyright in this Software shall at all times remain with + copyright holders. + + OpenLDAP is a registered trademark of the OpenLDAP Foundation. + + Copyright 1999-2003 The OpenLDAP Foundation, Redwood City, + California, USA. All Rights Reserved. Permission to copy and + distribute verbatim copies of this document is granted. + +Marked test programs in src/lib/krb5/krb have the following copyright: + + + Copyright (C) 2006 Kungliga Tekniska Högskolan + (Royal Institute of Technology, Stockholm, Sweden). + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + + 3. Neither the name of KTH nor the names of its contributors may be + used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + +====================================================================== + +The KCM Mach RPC definition file used on macOS has the following +copyright: + + Copyright (C) 2009 Kungliga Tekniska Högskolan + (Royal Institute of Technology, Stockholm, Sweden). + All rights reserved. + + Portions Copyright (C) 2009 Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + disclaimer. + + 2. Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + + 3. Neither the name of the Institute nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE + OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + +====================================================================== + +Portions of the RPC implementation in src/lib/rpc and +src/include/gssrpc have the following copyright and permission notice: + + Copyright (C) 2010, Oracle America, Inc. + + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + + 3. Neither the name of the "Oracle America, Inc." nor the names of + its contributors may be used to endorse or promote products + derived from this software without specific prior written + permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + OF THE POSSIBILITY OF SUCH DAMAGE. + +====================================================================== + + Copyright (C) 2006,2007,2009 NTT (Nippon Telegraph and Telephone + Corporation). All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer as + the first lines of this file unmodified. + + 2. Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + + THIS SOFTWARE IS PROVIDED BY NTT "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL NTT BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + OF THE POSSIBILITY OF SUCH DAMAGE. + +====================================================================== + + Copyright 2000 by Carnegie Mellon University + + All Rights Reserved + + Permission to use, copy, modify, and distribute this software and + its documentation for any purpose and without fee is hereby + granted, provided that the above copyright notice appear in all + copies and that both that copyright notice and this permission + notice appear in supporting documentation, and that the name of + Carnegie Mellon University not be used in advertising or publicity + pertaining to distribution of the software without specific, + written prior permission. + + CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO + THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE + FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + SOFTWARE. + +====================================================================== + + Copyright (C) 2002 Naval Research Laboratory (NRL/CCS) + + Permission to use, copy, modify and distribute this software and + its documentation is hereby granted, provided that both the + copyright notice and this permission notice appear in all copies of + the software, derivative works or modified versions, and any + portions thereof. + + NRL ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION AND + DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER + RESULTING FROM THE USE OF THIS SOFTWARE. + +====================================================================== + +Portions extracted from Internet RFCs have the following copyright +notice: + + Copyright (C) The Internet Society (2006). + + This document is subject to the rights, licenses and restrictions + contained in BCP 78, and except as set forth therein, the authors + retain all their rights. + + This document and the information contained herein are provided on + an "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE + REPRESENTS OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND + THE INTERNET ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT + THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR + ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A + PARTICULAR PURPOSE. + +====================================================================== + + Copyright (C) 1991, 1992, 1994 by Cygnus Support. + + Permission to use, copy, modify, and distribute this software and + its documentation for any purpose and without fee is hereby + granted, provided that the above copyright notice appear in all + copies and that both that copyright notice and this permission + notice appear in supporting documentation. Cygnus Support makes no + representations about the suitability of this software for any + purpose. It is provided "as is" without express or implied + warranty. + +====================================================================== + + Copyright (C) 2006 Secure Endpoints Inc. + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, copy, + modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + +====================================================================== + +Portions of the implementation of the Fortuna-like PRNG are subject to +the following notice: + + + Copyright (C) 2005 Marko Kreen + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + + Copyright (C) 1994 by the University of Southern California + + EXPORT OF THIS SOFTWARE from the United States of America may + require a specific license from the United States Government. It + is the responsibility of any person or organization + contemplating export to obtain such a license before exporting. + + WITHIN THAT CONSTRAINT, permission to copy, modify, and distribute + this software and its documentation in source and binary forms is + hereby granted, provided that any documentation or other materials + related to such distribution or use acknowledge that the software + was developed by the University of Southern California. + + DISCLAIMER OF WARRANTY. THIS SOFTWARE IS PROVIDED "AS IS". The + University of Southern California MAKES NO REPRESENTATIONS OR + WARRANTIES, EXPRESS OR IMPLIED. By way of example, but not + limitation, the University of Southern California MAKES NO + REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY + PARTICULAR PURPOSE. The University of Southern California shall not + be held liable for any liability nor for any direct, indirect, or + consequential damages with respect to any claim by the user or + distributor of the ksu software. + +====================================================================== + + Copyright (C) 1995 + The President and Fellows of Harvard University + + This code is derived from software contributed to Harvard by Jeremy + Rassen. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + + 3. All advertising materials mentioning features or use of this + software must display the following acknowledgement: + + This product includes software developed by the University of + California, Berkeley and its contributors. + + 4. Neither the name of the University nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS + OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + +====================================================================== + + Copyright (C) 2008 by the Massachusetts Institute of Technology. + Copyright 1995 by Richard P. Basch. All Rights Reserved. + Copyright 1995 by Lehman Brothers, Inc. All Rights Reserved. + + Export of this software from the United States of America may + require a specific license from the United States Government. It + is the responsibility of any person or organization + contemplating export to obtain such a license before exporting. + + WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + distribute this software and its documentation for any purpose and + without fee is hereby granted, provided that the above copyright + notice appear in all copies and that both that copyright notice and + this permission notice appear in supporting documentation, and that + the name of Richard P. Basch, Lehman Brothers and M.I.T. not be + used in advertising or publicity pertaining to distribution of the + software without specific, written prior permission. Richard P. + Basch, Lehman Brothers and M.I.T. make no representations about the + suitability of this software for any purpose. It is provided "as + is" without express or implied warranty. + +====================================================================== + +The following notice applies to "src/lib/krb5/krb/strptime.c" and +"src/include/k5-queue.h". + + Copyright (C) 1997, 1998 The NetBSD Foundation, Inc. + All rights reserved. + + This code was contributed to The NetBSD Foundation by Klaus Klein. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + + 3. All advertising materials mentioning features or use of this + software must display the following acknowledgement: + + This product includes software developed by the NetBSD + Foundation, Inc. and its contributors. + + 4. Neither the name of The NetBSD Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND + CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + DAMAGE. + +====================================================================== + +The following notice applies to Unicode library files in +"src/lib/krb5/unicode": + + Copyright 1997, 1998, 1999 Computing Research Labs, + New Mexico State University + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, copy, + modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE COMPUTING RESEARCH LAB OR + NEW MEXICO STATE UNIVERSITY BE LIABLE FOR ANY CLAIM, DAMAGES OR + OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +====================================================================== + +The following notice applies to "src/util/support/strlcpy.c": + + Copyright (C) 1998 Todd C. Miller "Todd.Miller@courtesan.com" + + Permission to use, copy, modify, and distribute this software for + any purpose with or without fee is hereby granted, provided that + the above copyright notice and this permission notice appear in all + copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR + CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS + OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +====================================================================== + +The following notice applies to "src/util/profile/argv_parse.c" and +"src/util/profile/argv_parse.h": + + Copyright 1999 by Theodore Ts'o. + + Permission to use, copy, modify, and distribute this software for + any purpose with or without fee is hereby granted, provided that + the above copyright notice and this permission notice appear in all + copies. THE SOFTWARE IS PROVIDED "AS IS" AND THEODORE TS'O (THE + AUTHOR) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, + INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR + IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. (Isn't + it sick that the U.S. culture of lawsuit-happy lawyers requires + this kind of disclaimer?) + +====================================================================== + +The following notice applies to SWIG-generated code in +"src/util/profile/profile_tcl.c": + + Copyright (C) 1999-2000, The University of Chicago + + This file may be freely redistributed without license or fee + provided this copyright message remains intact. + +====================================================================== + +The following notice applies to portiions of "src/lib/rpc" and +"src/include/gssrpc": + + Copyright (C) 2000 The Regents of the University of Michigan. All + rights reserved. + + Copyright (C) 2000 Dug Song "dugsong@UMICH.EDU". All rights + reserved, all wrongs reversed. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + + 3. Neither the name of the University nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + DAMAGE. + +Implementations of the MD4 algorithm are subject to the following +notice: + + Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. + + License to copy and use this software is granted provided that it + is identified as the "RSA Data Security, Inc. MD4 Message Digest + Algorithm" in all material mentioning or referencing this software + or this function. + + License is also granted to make and use derivative works provided + that such works are identified as "derived from the RSA Data + Security, Inc. MD4 Message Digest Algorithm" in all material + mentioning or referencing the derived work. + + RSA Data Security, Inc. makes no representations concerning either + the merchantability of this software or the suitability of this + software for any particular purpose. It is provided "as is" + without express or implied warranty of any kind. + + These notices must be retained in any copies of any part of this + documentation and/or software. + +====================================================================== + +Implementations of the MD5 algorithm are subject to the following +notice: + + Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. + + License to copy and use this software is granted provided that it + is identified as the "RSA Data Security, Inc. MD5 Message- Digest + Algorithm" in all material mentioning or referencing this software + or this function. + + License is also granted to make and use derivative works provided + that such works are identified as "derived from the RSA Data + Security, Inc. MD5 Message-Digest Algorithm" in all material + mentioning or referencing the derived work. + + RSA Data Security, Inc. makes no representations concerning either + the merchantability of this software or the suitability of this + software for any particular purpose. It is provided "as is" + without express or implied warranty of any kind. + + These notices must be retained in any copies of any part of this + documentation and/or software. + +====================================================================== + +The following notice applies to +"src/lib/crypto/crypto_tests/t_mddriver.c": + + Copyright (C) 1990-2, RSA Data Security, Inc. Created 1990. All + rights reserved. + + RSA Data Security, Inc. makes no representations concerning either + the merchantability of this software or the suitability of this + software for any particular purpose. It is provided "as is" without + express or implied warranty of any kind. + + These notices must be retained in any copies of any part of this + documentation and/or software. + +====================================================================== + +Portions of "src/lib/krb5" are subject to the following notice: + + Copyright (C) 1994 CyberSAFE Corporation. + Copyright 1990,1991,2007,2008 by the Massachusetts Institute of +Technology. + All Rights Reserved. + + Export of this software from the United States of America may + require a specific license from the United States Government. It + is the responsibility of any person or organization + contemplating export to obtain such a license before exporting. + + WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + distribute this software and its documentation for any purpose and + without fee is hereby granted, provided that the above copyright + notice appear in all copies and that both that copyright notice and + this permission notice appear in supporting documentation, and that + the name of M.I.T. not be used in advertising or publicity + pertaining to distribution of the software without specific, + written prior permission. Furthermore if you modify this software + you must label your software as modified software and not + distribute it in such a fashion that it might be confused with the + original M.I.T. software. Neither M.I.T., the Open Computing + Security Group, nor CyberSAFE Corporation make any representations + about the suitability of this software for any purpose. It is + provided "as is" without express or implied warranty. + +====================================================================== + +Portions contributed by PADL Software are subject to the following +license: + + Copyright (c) 2011, PADL Software Pty Ltd. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + + 3. Neither the name of PADL Software nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE + OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + +====================================================================== + +The bundled libev source code is subject to the following license: + + All files in libev are Copyright (C)2007,2008,2009 Marc Alexander + Lehmann. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + OF THE POSSIBILITY OF SUCH DAMAGE. + + Alternatively, the contents of this package may be used under the + terms of the GNU General Public License ("GPL") version 2 or any + later version, in which case the provisions of the GPL are + applicable instead of the above. If you wish to allow the use of + your version of this package only under the terms of the GPL and + not to allow others to use your version of this file under the BSD + license, indicate your decision by deleting the provisions above + and replace them with the notice and other provisions required by + the GPL in this and the other files of this package. If you do not + delete the provisions above, a recipient may use your version of + this file under either the BSD or the GPL. + +====================================================================== + +Files copied from the Intel AESNI Sample Library are subject to the +following license: + + Copyright (C) 2010, Intel Corporation + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + + * Neither the name of Intel Corporation nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior written + permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + OF THE POSSIBILITY OF SUCH DAMAGE. + +====================================================================== + +The following notice applies to +"src/ccapi/common/win/OldCC/autolock.hxx": + + Copyright (C) 1998 by Danilo Almeida. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + OF THE POSSIBILITY OF SUCH DAMAGE. ====================================================================== ====================================================================== @@ -728,34 +2003,6 @@ See Apache License v2.0, January 2004 in the 'Standard Licenses' section. ====================================================================== ====================================================================== -ZstdSharp.Port - -MIT License - -Copyright (c) 2021 Oleg Stepanischev - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - - ====================================================================== - ====================================================================== - Standard Licenses Apache License v2.0, January 2004 @@ -1017,4 +2264,4 @@ Written Offer for Source Code that included the binary that is the subject of your request, or b. in the case of code licensed under the GPL v3 for as long as Oracle - offers spare parts or customer support for that product model. + offers spare parts or customer support for that product model. \ No newline at end of file From 528449175f6f983fb54d19576f64ec78702eb11a Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Wed, 12 Mar 2025 16:54:25 -0600 Subject: [PATCH 108/125] Bug#37513445 [Cannot Perform Database Migration using MySql.EntityFrameworkCore 9.0.0] Change-Id: Iecdde3c6322d169ce74b0d5339dd85813eb14c73 --- CHANGES | 1 + .../Internal/MySQLHistoryRepository.cs | 8 ++++---- .../MySQLMigrationsTests.cs | 19 ++++++++++++++++++- 3 files changed, 23 insertions(+), 5 deletions(-) diff --git a/CHANGES b/CHANGES index 93ada122e..fb76880a5 100644 --- a/CHANGES +++ b/CHANGES @@ -2,6 +2,7 @@ - Fixed bug MySql.EntityFrameworkCore.dll in NuGet packages is not signed (Oracle Bug #37503859). - Fixed some tests due to incorrect implementation (WL16033). - Updated third party dependencies (WL16852). +- Fixed bug Cannot Perform Database Migration using MySql.EntityFrameworkCore 9.0.0 (MySQL Bug #117258, Oracle Bug #37513445). 9.2.0 diff --git a/EFCore/src/Migrations/Internal/MySQLHistoryRepository.cs b/EFCore/src/Migrations/Internal/MySQLHistoryRepository.cs index c5c86ebb6..7c7e982a8 100644 --- a/EFCore/src/Migrations/Internal/MySQLHistoryRepository.cs +++ b/EFCore/src/Migrations/Internal/MySQLHistoryRepository.cs @@ -61,10 +61,10 @@ public override IMigrationsDatabaseLock AcquireDatabaseLock() Dependencies.MigrationsLogger.AcquiringMigrationLock(); var dbLock = CreateMigrationDatabaseLock(); - int result; + Int64 result; try { - result = (int)CreateGetLockCommand().ExecuteScalar(CreateRelationalCommandParameters())!; + result = (Int64)CreateGetLockCommand().ExecuteScalar(CreateRelationalCommandParameters())!; } catch { @@ -120,11 +120,11 @@ public override async Task AcquireDatabaseLockAsync(Can } private IRelationalCommand CreateGetLockCommand() - => Dependencies.RawSqlCommandBuilder.Build("DECLARE @result int;EXEC @result = sp_getapplock @Resource = '__EFMigrationsLock', @LockOwner = 'Session', @LockMode = 'Exclusive';SELECT @result", []).RelationalCommand; + => Dependencies.RawSqlCommandBuilder.Build("SELECT GET_LOCK('__EFMigrationsLock',-1);", []).RelationalCommand; private MySQLMigrationDatabaseLock CreateMigrationDatabaseLock() => new( - Dependencies.RawSqlCommandBuilder.Build("DECLARE @result int;EXEC @result = sp_releaseapplock @Resource = '__EFMigrationsLock', @LockOwner = 'Session';SELECT @result"), + Dependencies.RawSqlCommandBuilder.Build("SELECT RELEASE_LOCK('__EFMigrationsLock');"), CreateRelationalCommandParameters(), this); diff --git a/EFCore/tests/MySql.EFCore.Migrations.Tests/MySQLMigrationsTests.cs b/EFCore/tests/MySql.EFCore.Migrations.Tests/MySQLMigrationsTests.cs index 204076761..5b9ab9574 100644 --- a/EFCore/tests/MySql.EFCore.Migrations.Tests/MySQLMigrationsTests.cs +++ b/EFCore/tests/MySql.EFCore.Migrations.Tests/MySQLMigrationsTests.cs @@ -32,7 +32,6 @@ using Microsoft.Extensions.DependencyInjection; using MySql.EntityFrameworkCore.Basic.Tests.Utils; using NUnit.Framework; -using NUnit.Framework.Legacy; namespace MySql.EntityFrameworkCore.Migrations.Tests { @@ -52,5 +51,23 @@ public void Can_generate_migration_from_initial_database_to_initial() migrator.GenerateScript(fromMigration: Migration.InitialDatabase, toMigration: Migration.InitialDatabase); } } + + //Bug #37513445 Cannot Perform Database Migration using MySql.EntityFrameworkCore 9.0.0 + [Test] + public void TryPerformMigration() + { + var optionsBuilder = new DbContextOptionsBuilder(); + optionsBuilder.UseMySQL(MySQLTestStore.RootConnectionString + "database=test;"); + + using (var mytestContext = new MyTestContext(optionsBuilder.Options)) + { + mytestContext.Database.EnsureCreated(); + mytestContext.Database.EnsureDeleted(); + mytestContext.Database.Migrate(); + + Assert.That(mytestContext.Database.CanConnect(), Is.True); + mytestContext.Database.EnsureDeleted(); + } + } } } From e06e563add3ad67c9288bb3abd93ea9f9a10d9c9 Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Thu, 13 Mar 2025 17:02:19 -0600 Subject: [PATCH 109/125] Bug#37705281 [Fix failing tests due to server changes] Change-Id: I1cae3fc70461cb272efd8629a42dd57bfe25c8e2 --- CHANGES | 1 + MySQL.Data/src/SchemaProvider.cs | 4 +--- .../Framework/netstandard2_0/GetSchemaTests.cs | 5 ++++- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/CHANGES b/CHANGES index fb76880a5..d20a88c34 100644 --- a/CHANGES +++ b/CHANGES @@ -3,6 +3,7 @@ - Fixed some tests due to incorrect implementation (WL16033). - Updated third party dependencies (WL16852). - Fixed bug Cannot Perform Database Migration using MySql.EntityFrameworkCore 9.0.0 (MySQL Bug #117258, Oracle Bug #37513445). +- Fixed failing tests due to server changes (Oracle Bug #37705281). 9.2.0 diff --git a/MySQL.Data/src/SchemaProvider.cs b/MySQL.Data/src/SchemaProvider.cs index 5141f383e..468521d66 100644 --- a/MySQL.Data/src/SchemaProvider.cs +++ b/MySQL.Data/src/SchemaProvider.cs @@ -295,9 +295,7 @@ public virtual async Task GetIndexesAsync(string[] restri foreach (MySqlSchemaRow index in indexes.Rows) { - if (1 != (connection.driver.Version.isAtLeast(8, 0, 1) ? - (uint)index["SEQ_IN_INDEX"] : - (long)index["SEQ_IN_INDEX"])) + if (!index["SEQ_IN_INDEX"].Equals(Convert.ChangeType(1, index["SEQ_IN_INDEX"].GetType()))) continue; if (restrictions != null && restrictions.Length == 4 && restrictions[3] != null && diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/GetSchemaTests.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/GetSchemaTests.cs index 0ea3316d0..d0928792e 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/GetSchemaTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/GetSchemaTests.cs @@ -764,7 +764,10 @@ c2 double GENERATED ALWAYS AS(c1 * 101 / 102) Stored COMMENT 'First Gen Col', { Assert.That(reader.Read(), "Matching the values"); Assert.That(reader.GetInt32(0).Equals(1000), "Matching the values"); - Assert.That(reader.GetDouble(1).Equals(990.196078431), "Matching the values"); + if (Version >= new Version(9, 3, 0)) + Assert.That(reader.GetDouble(1).Equals(990.1961), "Matching the values"); + else + Assert.That(reader.GetDouble(1).Equals(990.196078431), "Matching the values"); Assert.That(reader.GetInt64(2).Equals(10000000), "Matching the values"); } From 7d3121645784aa316ac1641a9cadf0bee7df90da Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Tue, 25 Mar 2025 11:52:16 -0600 Subject: [PATCH 110/125] Bump Up version to 9.4.0 Change-Id: I145322e5a14a9be801e5b8c628446c9391e88274 --- CHANGES | 3 +++ .../custom/partials/class.header.tmpl.partial | 2 +- EFCore/src/Properties/VersionInfo.cs | 12 ++++++------ .../src/MySql.Data.EntityFramework.csproj | 4 ++-- EntityFramework/src/Properties/VersionInfo.cs | 6 +++--- .../MySql.EntityFramework.Basic.Tests.csproj | 4 ++-- .../MySql.EntityFramework.CodeFirst.Tests.csproj | 4 ++-- .../MySql.EntityFramework.Migrations.Tests.csproj | 4 ++-- .../src/MySQL.Data.OpenTelemetry.csproj | 4 ++-- .../src/Properties/VersionInfo.cs | 6 +++--- MySQL.Data/src/MySql.Data.csproj | 6 +++--- MySQL.Data/src/Properties/VersionInfo.cs | 6 +++--- .../tests/MySql.Data.Tests/MySql.Data.Tests.csproj | 6 +++--- .../tests/MySqlX.Data.Tests/MySqlX.Data.Tests.csproj | 6 +++--- MySql.Web/src/MySql.Web.csproj | 4 ++-- MySql.Web/src/Properties/VersionInfo.cs | 6 +++--- MySql.Web/tests/MySql.Web.Tests.csproj | 4 ++-- 17 files changed, 45 insertions(+), 42 deletions(-) diff --git a/CHANGES b/CHANGES index d20a88c34..29be8eec6 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,6 @@ +9.4.0 + + 9.3.0 - Fixed bug MySql.EntityFrameworkCore.dll in NuGet packages is not signed (Oracle Bug #37503859). - Fixed some tests due to incorrect implementation (WL16033). diff --git a/Documentation/templates/custom/partials/class.header.tmpl.partial b/Documentation/templates/custom/partials/class.header.tmpl.partial index 15ce5e483..f545c2864 100644 --- a/Documentation/templates/custom/partials/class.header.tmpl.partial +++ b/Documentation/templates/custom/partials/class.header.tmpl.partial @@ -25,7 +25,7 @@ {{/implements.0}}

- [TestCase("test1@MYSQL.LOCAL", "Testpw1", "authentication_ldap_sasl", true)] - [TestCase("invalidUser@MYSQL.LOCAL", "Testpw1", "authentication_ldap_sasl", false)] - [TestCase("test1@MYSQL.LOCAL", "wrongPassword", "authentication_ldap_sasl", false)] + [TestCase("test1@MTR.LOCAL", "Testpw1", "authentication_ldap_sasl", true)] + [TestCase("invalidUser@MTR.LOCAL", "Testpw1", "authentication_ldap_sasl", false)] + [TestCase("test1@MTR.LOCAL", "wrongPassword", "authentication_ldap_sasl", false)] [Ignore("This test require to start MySQL Commercial Server with the configuration specified in file Resources/my.ini")] [Property("Category", "Security")] public void ConnectUsingMySqlSASLPluginGSSAPI(string userName, string password, string pluginName, bool shouldPass) @@ -1182,7 +1182,7 @@ public void ConnectUsingMySqlSASLPluginGSSAPI(string userName, string password, SslMode = MySqlSslMode.Disabled }; - ExecuteSQL("CREATE USER 'test1@MYSQL.LOCAL' IDENTIFIED WITH authentication_ldap_sasl; GRANT ALL ON *.* to 'test1@MYSQL.LOCAL';", true); + ExecuteSQL("CREATE USER 'test1@MTR.LOCAL' IDENTIFIED WITH authentication_ldap_sasl; GRANT ALL ON *.* to 'test1@MTR.LOCAL';", true); using (MySqlConnection connection = new MySqlConnection(settings.ConnectionString)) { @@ -1370,7 +1370,7 @@ public void ConnectUsingMySqlPluginKerberosGSSAPI(bool shouldPass, string userNa private void TestKerberosConnection(bool shouldPass, string username, MySqlConnectionStringBuilder settings, KerberosAuthMode mode) { - ExecuteSQL("CREATE USER IF NOT EXISTS 'test1'@'%' IDENTIFIED WITH authentication_kerberos BY 'MYSQL.LOCAL'; " + + ExecuteSQL("CREATE USER IF NOT EXISTS 'test1'@'%' IDENTIFIED WITH authentication_kerberos BY 'MTR.LOCAL'; " + "GRANT ALL ON *.* to 'test1'@'%';", true); using (MySqlConnection conn = new MySqlConnection(settings.ConnectionString)) diff --git a/MySQL.Data/tests/MySql.Data.Tests/Resources/KerberosConfig.txt b/MySQL.Data/tests/MySql.Data.Tests/Resources/KerberosConfig.txt deleted file mode 100644 index d5e2dd534..000000000 --- a/MySQL.Data/tests/MySql.Data.Tests/Resources/KerberosConfig.txt +++ /dev/null @@ -1,68 +0,0 @@ - -------- CLIENT -------- -Linux prerequisites: -libsasl2.4-2 -libsasl2-modules-gssapi-mit -krb5-config -krb5-user - -Windows prerequisites: -There's a quick guide to follow: https://confluence.oraclecorp.com/confluence/display/MYSQL/MySQL+windows+client+support+for+kerberos -Step 3 is really important for this to work. - --------- SERVER -------- -krb5.conf structure: -[libdefaults] - default_realm = MYSQL.LOCAL - dns_lookup_realm = false - dns_lookup_kdc = false - dns_fallback = false - -[realms] - MYSQL.LOCAL = { - kdc = ldapauth.appad3iad.mysql2iad.oraclevcn.com - admin_server = ldapauth.appad3iad.mysql2iad.oraclevcn.com - default_domain = MYSQL.LOCAL - } - -[domain_realm] - .no.oracle.com = MYSQL.LOCAL - - -Add following line to /etc/hosts: -100.103.18.98 ldapauth ldapauth.appad3iad.mysql2iad.oraclevcn.com - - --------------------------- GSSAPI -------------------------- - -In case my.ini is not working, start server as follow: -sudo ./bin/mysqld --port=3306 --bind-address=localhost --user=mysql --basedir=/usr --datadir=/var/lib/mysql --plugin_dir=/usr/local/mysql/lib/plugin ---plugin-load=authentication_ldap_sasl.so --authentication_ldap_sasl_server_host=ldapauth.appad3iad.mysql2iad.oraclevcn.com ---authentication_ldap_sasl_group_search_attr='cn' --authentication_ldap_sasl_auth_method_name='GSSAPI' --authentication_ldap_sasl_log_status=5 ---log_error_verbosity=3 --authentication_ldap_sasl_bind_root_pwd="Testpw1" --authentication_ldap_sasl_bind_root_dn="CN=test2,CN=Users,DC=mysql,DC=local" ---authentication_ldap_sasl_bind_base_dn='CN=Users,DC=mysql,DC=local' - - -Create LDAP SASL User: -INSTALL PLUGIN authentication_ldap_sasl SONAME 'authentication_ldap_sasl.so'; -CREATE USER 'test1@MYSQL.LOCAL' IDENTIFIED WITH authentication_ldap_sasl; - -sudo AUTHENTICATION_LDAP_CLIENT_LOG=5 ./bin/mysql --user=test1@MYSQL.LOCAL --password=Testpw1 --port 3306 - --------------------------- KERBEROS -------------------------- - -sudo ./bin/mysqld --port=3306 --user=mysql --basedir=/usr --datadir=/var/lib/mysql --plugin_dir=/usr/local/mysql/lib/plugin --log_error_verbosity=3 ---plugin-load=authentication_kerberos.so --authentication_kerberos_service_principal='mysql_service/kerberos_auth_host@MYSQL.LOCAL' ---authentication_kerberos_service_key_tab=/usr/local/mysql/mysql.keytab - -Create the following MySQL accounts: - -CREATE USER 'test1'@'%' IDENTIFIED WITH authentication_kerberos BY 'MYSQL.LOCAL'; -GRANT ALL ON *.* to 'test1'@'%'; - -CREATE USER 'test2'@'%' IDENTIFIED WITH authentication_kerberos BY 'MYSQL.LOCAL'; -GRANT ALL ON *.* to 'test2'@'%'; - -CREATE USER 'test3'@'%' IDENTIFIED WITH authentication_kerberos BY 'MYSQL.LOCAL'; -GRANT ALL ON *.* to 'test3'@'%'; - -sudo AUTHENTICATION_KERBEROS_CLIENT_LOG=5 ./bin/mysql --user=test1 --password=Testpw1 \ No newline at end of file diff --git a/MySQL.Data/tests/MySql.Data.Tests/Resources/mtr.keytab b/MySQL.Data/tests/MySql.Data.Tests/Resources/mtr.keytab new file mode 100644 index 0000000000000000000000000000000000000000..e62515972e0552a5c3143426045e990e98ba5928 GIT binary patch literal 407 zcmZQ&Vqjo!Wng09^bHBp^YM3f^kLx5tt>9gi7!qqD$7hxWf00vElNr)$}f&jEG@~1 z&&V$>0qS7{Vg_a)#o<#n#qjjOi5Zj`#EfE)FZnJKXApR^H_j|WFY#LK;`Px&k1DnU zT^38efkF%ly$hMARi$-SKYpw5e#>&MQ(Sfb=Edzu@SDkd{WqItb{x$6MXmhd~^i>l$d%Y literal 0 HcmV?d00001 diff --git a/MySQL.Data/tests/MySql.Data.Tests/Resources/my.ini b/MySQL.Data/tests/MySql.Data.Tests/Resources/my.ini index 82e5f7670..b226f0fe7 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Resources/my.ini +++ b/MySQL.Data/tests/MySql.Data.Tests/Resources/my.ini @@ -32,15 +32,15 @@ authentication_ldap_sasl_user_search_attr='cn' ### GSSAPI plugin-load-add=authentication_ldap_sasl.so -authentication_ldap_sasl_server_host='ldapauth.appad3iad.mysql2iad.oraclevcn.com' -authentication_ldap_sasl_bind_base_dn='CN=Users,DC=mysql,DC=local' +authentication_ldap_sasl_server_host='winmtr01.regionaliad02.mysql2iad.oraclevcn.com' +authentication_ldap_sasl_bind_base_dn='CN=Users,DC=mtr,DC=local' authentication_ldap_sasl_auth_method_name='GSSAPI' -authentication_ldap_sasl_bind_root_dn='CN=test2,CN=Users,DC=mysql,DC=local' +authentication_ldap_sasl_bind_root_dn='CN=test1,CN=Users,DC=mtr,DC=local' authentication_ldap_sasl_log_status=6 authentication_ldap_sasl_group_search_attr='cn' authentication_ldap_sasl_bind_root_pwd='Testpw1' ### KERBEROS plugin-load-add = authentication_kerberos.so -authentication_kerberos_service_principal = "mysql_service/kerberos_auth_host@MYSQL.LOCAL" +authentication_kerberos_service_principal = "mysql_service/kerberos_auth_host@MTR.LOCAL" authentication_kerberos_service_key_tab = "{full_path_to:mysql.keytab}" \ No newline at end of file diff --git a/MySQL.Data/tests/MySql.Data.Tests/Resources/mysql.keytab b/MySQL.Data/tests/MySql.Data.Tests/Resources/mysql.keytab deleted file mode 100644 index 91ab57a936f3ae1e69034a2bcaaa1ae88c6b0764..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 178 zcmZQ&VqjnhW?*9A_Kge<^wIP2cXsq);LWWpF3gE9PAw|SOipDG%1$jxN-fGSj!!Ht z$%xO$FD?P Date: Sat, 29 Mar 2025 15:32:40 -0600 Subject: [PATCH 114/125] WL#16900 [Add support for .NET 10 and EF Core 10 preview versions] Change-Id: I88fe42227d9485f632706060b0ab2f2329f19550 --- CHANGES | 1 + .../Internal/MySQLHistoryRepository.cs | 2 +- .../Internal/MySQLMigrationDatabaseLockcs.cs | 2 +- .../Internal/MySQLMigrationsModelDiffer.cs | 2 +- .../src/Migrations/Internal/MySQLMigrator.cs | 2 +- EFCore/src/MySql.EntityFrameworkCore.csproj | 7 +++- EFCore/src/Properties/VersionInfo.cs | 7 +++- .../Internal/MySQLBinaryExpression.cs | 4 +-- .../Internal/MySQLCollateExpression.cs | 8 ++--- .../MySQLColumnAliasReferenceExpression.cs | 4 +-- .../MySQLComplexFunctionArgumentExpression.cs | 4 +-- .../Internal/MySQLJsonArrayIndexExpression.cs | 4 +-- .../Internal/MySQLJsonTraversalExpression.cs | 4 +-- .../Internal/MySQLMatchExpression.cs | 4 +-- .../Internal/MySQLRegexpExpression.cs | 4 +-- .../Internal/MySQLDateTimeMethodTranslator.cs | 2 +- .../MySQLParameterBasedSqlProcessor.cs | 4 +-- .../MySQLParameterBasedSqlProcessorFactory.cs | 2 +- .../Internal/MySQLSqlExpressionFactory.cs | 4 +-- .../Internal/MySQLSqlNullabilityProcessor.cs | 2 +- .../ConnectionTests.cs | 34 ++++++++++++++++++- ...Sql.EntityFrameworkCore.Basic.Tests.csproj | 6 +++- .../Utils/MySqlTestStore.cs | 6 ++-- ...ql.EntityFrameworkCore.Design.Tests.csproj | 6 +++- ...ntityFrameworkCore.Migrations.Tests.csproj | 2 +- MySQL.Data/src/MySql.Data.csproj | 4 +-- .../MySql.Data.Tests/MySql.Data.Tests.csproj | 2 +- .../MySqlX.Data.Tests.csproj | 2 +- 28 files changed, 93 insertions(+), 42 deletions(-) diff --git a/CHANGES b/CHANGES index d98374809..3e541c719 100644 --- a/CHANGES +++ b/CHANGES @@ -2,6 +2,7 @@ - Fixed bug OpenAsync throws unhandled exception from thread pool (MySQL Bug #110789, Oracle Bug #35474099). - Fixed Entity Framework 6 from NET9 is deprecated due to Nunit4 Upgrade (MySQL Bug #117976, Oracle Bug #37837374). - Added support for GSSAPI/Kerberos authentication on Windows using authentication_ldap_sasl_client plug-in (WL15984). +- Added support for .NET 10 and EF Core 10 preview versions (WL16900). 9.3.0 diff --git a/EFCore/src/Migrations/Internal/MySQLHistoryRepository.cs b/EFCore/src/Migrations/Internal/MySQLHistoryRepository.cs index 7c7e982a8..d155c14be 100644 --- a/EFCore/src/Migrations/Internal/MySQLHistoryRepository.cs +++ b/EFCore/src/Migrations/Internal/MySQLHistoryRepository.cs @@ -53,7 +53,7 @@ public MySQLHistoryRepository([NotNull] HistoryRepositoryDependencies dependenci : base(dependencies) { } -#if NET9_0 +#if NET9_0_OR_GREATER public override LockReleaseBehavior LockReleaseBehavior => LockReleaseBehavior.Connection; public override IMigrationsDatabaseLock AcquireDatabaseLock() diff --git a/EFCore/src/Migrations/Internal/MySQLMigrationDatabaseLockcs.cs b/EFCore/src/Migrations/Internal/MySQLMigrationDatabaseLockcs.cs index ccd651a16..668e43971 100644 --- a/EFCore/src/Migrations/Internal/MySQLMigrationDatabaseLockcs.cs +++ b/EFCore/src/Migrations/Internal/MySQLMigrationDatabaseLockcs.cs @@ -33,7 +33,7 @@ namespace MySql.EntityFrameworkCore.Migrations.Internal { -#if NET9_0 +#if NET9_0_OR_GREATER internal class MySQLMigrationDatabaseLock( IRelationalCommand releaseLockCommand, RelationalCommandParameterObject relationalCommandParameters, diff --git a/EFCore/src/Migrations/Internal/MySQLMigrationsModelDiffer.cs b/EFCore/src/Migrations/Internal/MySQLMigrationsModelDiffer.cs index ac7fc3e4f..63ad27fb2 100644 --- a/EFCore/src/Migrations/Internal/MySQLMigrationsModelDiffer.cs +++ b/EFCore/src/Migrations/Internal/MySQLMigrationsModelDiffer.cs @@ -79,7 +79,7 @@ protected override IEnumerable Add(IColumn target, DiffConte return base.Add(target, diffContext, inline); } -#elif NET9_0 +#elif NET9_0_OR_GREATER public MySQLMigrationsModelDiffer( [NotNull] IRelationalTypeMappingSource typeMappingSource, [NotNull] IMigrationsAnnotationProvider migrationsAnnotations, diff --git a/EFCore/src/Migrations/Internal/MySQLMigrator.cs b/EFCore/src/Migrations/Internal/MySQLMigrator.cs index 3534d9152..416ba9ef5 100644 --- a/EFCore/src/Migrations/Internal/MySQLMigrator.cs +++ b/EFCore/src/Migrations/Internal/MySQLMigrator.cs @@ -47,7 +47,7 @@ namespace MySql.EntityFrameworkCore.Migrations.Internal { -#if NET9_0 +#if NET9_0_OR_GREATER public class MySQLMigrator : IMigrator { private readonly IMigrationsAssembly _migrationsAssembly; diff --git a/EFCore/src/MySql.EntityFrameworkCore.csproj b/EFCore/src/MySql.EntityFrameworkCore.csproj index 65aadc533..5ba39ee3e 100644 --- a/EFCore/src/MySql.EntityFrameworkCore.csproj +++ b/EFCore/src/MySql.EntityFrameworkCore.csproj @@ -23,7 +23,7 @@ - + $(TargetFrameworks);net10.0 @@ -36,6 +36,11 @@ + + + + + diff --git a/EFCore/src/Properties/VersionInfo.cs b/EFCore/src/Properties/VersionInfo.cs index b2645c712..2613c8c80 100644 --- a/EFCore/src/Properties/VersionInfo.cs +++ b/EFCore/src/Properties/VersionInfo.cs @@ -47,7 +47,12 @@ [assembly: NeutralResourcesLanguage("en-US")] #elif NET9_0 [assembly: AssemblyVersion("9.4.0")] -[assembly: AssemblyInformationalVersion("9.0.0.0-preview+MySQL9.4.0")] +[assembly: AssemblyInformationalVersion("9.0.3.0+MySQL9.4.0")] +[assembly: AssemblyFileVersion("9.4.0.0")] +[assembly: NeutralResourcesLanguage("en-US")] +#elif NET10_0 +[assembly: AssemblyVersion("9.4.0")] +[assembly: AssemblyInformationalVersion("10.0.0.0-preview+MySQL9.4.0")] [assembly: AssemblyFileVersion("9.4.0.0")] [assembly: NeutralResourcesLanguage("en-US")] #endif diff --git a/EFCore/src/Query/Expressions/Internal/MySQLBinaryExpression.cs b/EFCore/src/Query/Expressions/Internal/MySQLBinaryExpression.cs index 6b07143ad..9a3e30f10 100644 --- a/EFCore/src/Query/Expressions/Internal/MySQLBinaryExpression.cs +++ b/EFCore/src/Query/Expressions/Internal/MySQLBinaryExpression.cs @@ -61,7 +61,7 @@ public MySQLBinaryExpression( Right = right; } -#if NET9_0 +#if NET9_0_OR_GREATER private static ConstructorInfo? _quotingConstructor; #endif public virtual MySQLBinaryExpressionOperatorType OperatorType { get; } @@ -81,7 +81,7 @@ protected override Expression VisitChildren(ExpressionVisitor visitor) return Update(left, right); } -#if NET9_0 +#if NET9_0_OR_GREATER /// public override Expression Quote() => New( _quotingConstructor ??= typeof(MySQLBinaryExpression).GetConstructor( diff --git a/EFCore/src/Query/Expressions/Internal/MySQLCollateExpression.cs b/EFCore/src/Query/Expressions/Internal/MySQLCollateExpression.cs index bbb59165a..123249735 100644 --- a/EFCore/src/Query/Expressions/Internal/MySQLCollateExpression.cs +++ b/EFCore/src/Query/Expressions/Internal/MySQLCollateExpression.cs @@ -45,11 +45,11 @@ internal class MySQLCollateExpression : SqlExpression private readonly string _charset; private readonly string _collation; -#if NET9_0 +#if NET9_0_OR_GREATER private static ConstructorInfo? _quotingConstructor; #endif -#if NET9_0 +#if NET9_0_OR_GREATER public MySQLCollateExpression(SqlExpression operand, string collation) : base(operand.Type, operand.TypeMapping) { @@ -81,7 +81,7 @@ public MySQLCollateExpression( ///
public virtual string Charset => _charset; -#if NET9_0 +#if NET9_0_OR_GREATER /// /// The expression on which collation is applied. /// @@ -126,7 +126,7 @@ protected override Expression VisitChildren(ExpressionVisitor visitor) } -#if NET9_0 +#if NET9_0_OR_GREATER public virtual MySQLCollateExpression Update(SqlExpression operand) => operand != Operand ? new MySQLCollateExpression(operand, Collation) diff --git a/EFCore/src/Query/Expressions/Internal/MySQLColumnAliasReferenceExpression.cs b/EFCore/src/Query/Expressions/Internal/MySQLColumnAliasReferenceExpression.cs index 269c5386e..50cfadc82 100644 --- a/EFCore/src/Query/Expressions/Internal/MySQLColumnAliasReferenceExpression.cs +++ b/EFCore/src/Query/Expressions/Internal/MySQLColumnAliasReferenceExpression.cs @@ -40,7 +40,7 @@ namespace MySql.EntityFrameworkCore.Query.Expressions.Internal ///
internal class MySQLColumnAliasReferenceExpression : SqlExpression, IEquatable { -#if NET9_0 +#if NET9_0_OR_GREATER private static ConstructorInfo? _quotingConstructor; #endif @@ -72,7 +72,7 @@ public virtual MySQLColumnAliasReferenceExpression Update( ? this : new MySQLColumnAliasReferenceExpression(alias, expression, Type, TypeMapping!); -#if NET9_0 +#if NET9_0_OR_GREATER public override Expression Quote() => New( _quotingConstructor ??= typeof(MySQLColumnAliasReferenceExpression).GetConstructor([typeof(SqlExpression), typeof(string)])!, Constant(Alias), diff --git a/EFCore/src/Query/Expressions/Internal/MySQLComplexFunctionArgumentExpression.cs b/EFCore/src/Query/Expressions/Internal/MySQLComplexFunctionArgumentExpression.cs index 37bbf5420..2290f0b86 100644 --- a/EFCore/src/Query/Expressions/Internal/MySQLComplexFunctionArgumentExpression.cs +++ b/EFCore/src/Query/Expressions/Internal/MySQLComplexFunctionArgumentExpression.cs @@ -40,7 +40,7 @@ namespace MySql.EntityFrameworkCore.Query.Expressions.Internal internal class MySQLComplexFunctionArgumentExpression : SqlExpression { -#if NET9_0 +#if NET9_0_OR_GREATER private static ConstructorInfo? _quotingConstructor; #endif @@ -80,7 +80,7 @@ protected override Expression VisitChildren(ExpressionVisitor visitor) return Update(argumentParts, Delimiter); } -#if NET9_0 +#if NET9_0_OR_GREATER public override Expression Quote() => New( _quotingConstructor ??= typeof(MySQLComplexFunctionArgumentExpression).GetConstructor([typeof(SqlExpression), typeof(string)])!, Constant(ArgumentParts), diff --git a/EFCore/src/Query/Expressions/Internal/MySQLJsonArrayIndexExpression.cs b/EFCore/src/Query/Expressions/Internal/MySQLJsonArrayIndexExpression.cs index 79ba35577..a1f5f5ba2 100644 --- a/EFCore/src/Query/Expressions/Internal/MySQLJsonArrayIndexExpression.cs +++ b/EFCore/src/Query/Expressions/Internal/MySQLJsonArrayIndexExpression.cs @@ -41,7 +41,7 @@ namespace MySql.EntityFrameworkCore.Query.Expressions.Internal internal class MySQLJsonArrayIndexExpression : SqlExpression, IEquatable { -#if NET9_0 +#if NET9_0_OR_GREATER private static ConstructorInfo? _quotingConstructor; #endif @@ -60,7 +60,7 @@ public MySQLJsonArrayIndexExpression( protected override Expression VisitChildren(ExpressionVisitor visitor) => Update((SqlExpression)visitor.Visit(Expression)); -#if NET9_0 +#if NET9_0_OR_GREATER public override Expression Quote() => New( _quotingConstructor ??= typeof(MySQLJsonArrayIndexExpression).GetConstructor([typeof(SqlExpression), typeof(string)])!, Expression.Quote(), diff --git a/EFCore/src/Query/Expressions/Internal/MySQLJsonTraversalExpression.cs b/EFCore/src/Query/Expressions/Internal/MySQLJsonTraversalExpression.cs index a2771b34d..2b31cc35a 100644 --- a/EFCore/src/Query/Expressions/Internal/MySQLJsonTraversalExpression.cs +++ b/EFCore/src/Query/Expressions/Internal/MySQLJsonTraversalExpression.cs @@ -44,7 +44,7 @@ namespace MySql.EntityFrameworkCore.Query.Expressions.Internal internal class MySQLJsonTraversalExpression : SqlExpression, IEquatable { -#if NET9_0 +#if NET9_0_OR_GREATER private static ConstructorInfo? _quotingConstructor; #endif /// @@ -96,7 +96,7 @@ protected override Expression VisitChildren(ExpressionVisitor visitor) => Update((SqlExpression)visitor.Visit(Expression), Path.Select(p => (SqlExpression)visitor.Visit(p)).ToArray()); -#if NET9_0 +#if NET9_0_OR_GREATER public override Expression Quote() => New( _quotingConstructor ??= typeof(MySQLJsonTraversalExpression).GetConstructor([typeof(SqlExpression), typeof(string)])!, Expression.Quote(), diff --git a/EFCore/src/Query/Expressions/Internal/MySQLMatchExpression.cs b/EFCore/src/Query/Expressions/Internal/MySQLMatchExpression.cs index 26f177b81..6ada3a8d7 100644 --- a/EFCore/src/Query/Expressions/Internal/MySQLMatchExpression.cs +++ b/EFCore/src/Query/Expressions/Internal/MySQLMatchExpression.cs @@ -40,7 +40,7 @@ namespace MySql.EntityFrameworkCore.Query.Expressions.Internal internal class MySQLMatchExpression : SqlExpression { -#if NET9_0 +#if NET9_0_OR_GREATER private static ConstructorInfo? _quotingConstructor; #endif @@ -81,7 +81,7 @@ protected override Expression VisitChildren(ExpressionVisitor visitor) return Update(match, against); } -#if NET9_0 +#if NET9_0_OR_GREATER public override Expression Quote() => New( _quotingConstructor ??= typeof(MySQLMatchExpression).GetConstructor([typeof(SqlExpression), typeof(string)])!, Match.Quote(), diff --git a/EFCore/src/Query/Expressions/Internal/MySQLRegexpExpression.cs b/EFCore/src/Query/Expressions/Internal/MySQLRegexpExpression.cs index 3ecedf787..e0e19feb6 100644 --- a/EFCore/src/Query/Expressions/Internal/MySQLRegexpExpression.cs +++ b/EFCore/src/Query/Expressions/Internal/MySQLRegexpExpression.cs @@ -38,7 +38,7 @@ namespace MySql.EntityFrameworkCore.Query.Expressions.Internal internal class MySQLRegexpExpression : SqlExpression { -#if NET9_0 +#if NET9_0_OR_GREATER private static ConstructorInfo? _quotingConstructor; #endif @@ -75,7 +75,7 @@ protected override Expression VisitChildren(ExpressionVisitor visitor) return Update(match, pattern); } -#if NET9_0 +#if NET9_0_OR_GREATER public override Expression Quote() => New( _quotingConstructor ??= typeof(MySQLMatchExpression).GetConstructor([typeof(SqlExpression), typeof(string)])!, Match.Quote(), diff --git a/EFCore/src/Query/Internal/MySQLDateTimeMethodTranslator.cs b/EFCore/src/Query/Internal/MySQLDateTimeMethodTranslator.cs index d967aa091..dfb87f08c 100644 --- a/EFCore/src/Query/Internal/MySQLDateTimeMethodTranslator.cs +++ b/EFCore/src/Query/Internal/MySQLDateTimeMethodTranslator.cs @@ -100,7 +100,7 @@ public MySQLDateTimeMethodTranslator(ISqlExpressionFactory sqlExpressionFactory) typeof(string)) }, nullable: true, -#if !NET9_0 +#if !NET9_0_OR_GREATER argumentsPropagateNullability: TrueArrays[1], #else argumentsPropagateNullability: new[] { true, false }, diff --git a/EFCore/src/Query/Internal/MySQLParameterBasedSqlProcessor.cs b/EFCore/src/Query/Internal/MySQLParameterBasedSqlProcessor.cs index e116a3c93..18633c334 100644 --- a/EFCore/src/Query/Internal/MySQLParameterBasedSqlProcessor.cs +++ b/EFCore/src/Query/Internal/MySQLParameterBasedSqlProcessor.cs @@ -39,7 +39,7 @@ internal class MySQLParameterBasedSqlProcessor : RelationalParameterBasedSqlProc { private readonly IMySQLOptions _options; -#if !NET9_0 +#if !NET9_0_OR_GREATER public MySQLParameterBasedSqlProcessor( RelationalParameterBasedSqlProcessorDependencies dependencies, bool useRelationalNulls, @@ -69,7 +69,7 @@ protected override Expression ProcessSqlNullability( return new MySQLSqlNullabilityProcessor(Dependencies, UseRelationalNulls).Process(selectExpression, parametersValues, out canCache); } -#elif NET9_0 +#elif NET9_0_OR_GREATER protected override Expression ProcessSqlNullability( Expression selectExpression, IReadOnlyDictionary parametersValues, out bool canCache) { diff --git a/EFCore/src/Query/Internal/MySQLParameterBasedSqlProcessorFactory.cs b/EFCore/src/Query/Internal/MySQLParameterBasedSqlProcessorFactory.cs index 12f709cda..de50f63d1 100644 --- a/EFCore/src/Query/Internal/MySQLParameterBasedSqlProcessorFactory.cs +++ b/EFCore/src/Query/Internal/MySQLParameterBasedSqlProcessorFactory.cs @@ -42,7 +42,7 @@ public MySQLParameterBasedSqlProcessorFactory(RelationalParameterBasedSqlProcess _options = options; } -#if NET9_0 +#if NET9_0_OR_GREATER public RelationalParameterBasedSqlProcessor Create(RelationalParameterBasedSqlProcessorParameters parameters) => new MySQLParameterBasedSqlProcessor(_dependencies, parameters, _options); #else diff --git a/EFCore/src/Query/Internal/MySQLSqlExpressionFactory.cs b/EFCore/src/Query/Internal/MySQLSqlExpressionFactory.cs index df6173fc6..da1883b17 100644 --- a/EFCore/src/Query/Internal/MySQLSqlExpressionFactory.cs +++ b/EFCore/src/Query/Internal/MySQLSqlExpressionFactory.cs @@ -141,7 +141,7 @@ public MySQLCollateExpression Collate( string charset, string collation) => (MySQLCollateExpression)ApplyDefaultTypeMapping( -#if NET9_0 +#if NET9_0_OR_GREATER new MySQLCollateExpression( valueExpression, collation) @@ -294,7 +294,7 @@ private MySQLCollateExpression ApplyTypeMappingOnCollate(MySQLCollateExpression var inferredTypeMapping = ExpressionExtensions.InferTypeMapping(collateExpression.ValueExpression) ?? _typeMappingSource.FindMapping(collateExpression.ValueExpression.Type); -#if NET9_0 +#if NET9_0_OR_GREATER return new MySQLCollateExpression(collateExpression.ValueExpression, collateExpression.Collation); #else return new MySQLCollateExpression( diff --git a/EFCore/src/Query/Internal/MySQLSqlNullabilityProcessor.cs b/EFCore/src/Query/Internal/MySQLSqlNullabilityProcessor.cs index 4ecd6edd1..351fba69f 100644 --- a/EFCore/src/Query/Internal/MySQLSqlNullabilityProcessor.cs +++ b/EFCore/src/Query/Internal/MySQLSqlNullabilityProcessor.cs @@ -38,7 +38,7 @@ internal class MySQLSqlNullabilityProcessor : SqlNullabilityProcessor private readonly ISqlExpressionFactory _sqlExpressionFactory; -#if !NET9_0 +#if !NET9_0_OR_GREATER /// /// Creates a new instance of the . /// diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/ConnectionTests.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/ConnectionTests.cs index 1a82a5f62..ef30d7d57 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/ConnectionTests.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/ConnectionTests.cs @@ -85,7 +85,7 @@ public static RelationalConnectionDependencies CreateDependencies(DbContextOptio TestServiceFactory.Instance.Create(), new MySQLOptions())))); } -#elif NET8_0_OR_GREATER +#elif NET8_0 || NET9_0 public static RelationalConnectionDependencies CreateDependencies(DbContextOptions? options = null) { options ??= new DbContextOptionsBuilder() @@ -116,6 +116,38 @@ public static RelationalConnectionDependencies CreateDependencies(DbContextOptio TestServiceFactory.Instance.Create(), new MySQLOptions()), new ExceptionDetector()))); } +#elif NET10_0_OR_GREATER + public static RelationalConnectionDependencies CreateDependencies(DbContextOptions? options = null) + { + options ??= new DbContextOptionsBuilder() + .UseMySQL(MySQLTestStore.BaseConnectionString + "database=test;") + .Options; + + return new RelationalConnectionDependencies( + options, + new DiagnosticsLogger( + new LoggerFactory(), + new LoggingOptions(), + new DiagnosticListener("FakeDiagnosticListener"), + new MySQLLoggingDefinitions(), new NullDbContextLogger()), + new RelationalConnectionDiagnosticsLogger( + new LoggerFactory(), + new LoggingOptions(), + new DiagnosticListener("FakeDiagnosticListener"), + new TestRelationalLoggingDefinitions(), + new NullDbContextLogger(), + CreateOptions()), + new NamedConnectionStringResolver(options), + new RelationalTransactionFactory(new RelationalTransactionFactoryDependencies( + new RelationalSqlGenerationHelper(new RelationalSqlGenerationHelperDependencies()))), + new CurrentDbContext(new FakeDbContext()), + new RelationalCommandBuilderFactory(new RelationalCommandBuilderDependencies( + new MySQLTypeMappingSource( + TestServiceFactory.Instance.Create(), + TestServiceFactory.Instance.Create(), + new MySQLOptions()), new ExceptionDetector(), new LoggingOptions())), + new ExceptionDetector()); + } #endif diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/MySql.EntityFrameworkCore.Basic.Tests.csproj b/EFCore/tests/MySql.EFCore.Basic.Tests/MySql.EntityFrameworkCore.Basic.Tests.csproj index b650e7248..f4f0ada6e 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/MySql.EntityFrameworkCore.Basic.Tests.csproj +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/MySql.EntityFrameworkCore.Basic.Tests.csproj @@ -14,7 +14,7 @@ - + $(TargetFrameworks);net10.0 @@ -25,6 +25,10 @@ + + + + diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/Utils/MySqlTestStore.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/Utils/MySqlTestStore.cs index 776026ab7..4601e4c5b 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/Utils/MySqlTestStore.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/Utils/MySqlTestStore.cs @@ -226,7 +226,7 @@ public static void DeleteDatabase(string name) public override DbContextOptionsBuilder AddProviderOptions(DbContextOptionsBuilder builder) => builder.UseMySQL(GetContextConnectionString()); -#if NET9_0 +#if NET9_0_OR_GREATER public virtual void Clean(DbContext context) => context.Database.EnsureDeleted(); #else @@ -236,7 +236,7 @@ public override void Clean(DbContext context) -#if NET9_0 +#if NET9_0_OR_GREATER private MySQLTestStore(string name, DbConnection connection) : base(name, true, connection) { @@ -272,7 +272,7 @@ protected MySQLTestStoreFactory() { } -#if NET9_0 +#if NET9_0_OR_GREATER public override TestStore Create(string storeName) => MySQLTestStore.Create(storeName, new MySqlConnection(MySQLTestStore.RootConnectionString)); diff --git a/EFCore/tests/MySql.EFCore.Design.Tests/MySql.EntityFrameworkCore.Design.Tests.csproj b/EFCore/tests/MySql.EFCore.Design.Tests/MySql.EntityFrameworkCore.Design.Tests.csproj index f163da6c3..49afddd2f 100644 --- a/EFCore/tests/MySql.EFCore.Design.Tests/MySql.EntityFrameworkCore.Design.Tests.csproj +++ b/EFCore/tests/MySql.EFCore.Design.Tests/MySql.EntityFrameworkCore.Design.Tests.csproj @@ -14,7 +14,7 @@ - + $(TargetFrameworks);net10.0 @@ -41,6 +41,10 @@ + + + + diff --git a/EFCore/tests/MySql.EFCore.Migrations.Tests/MySql.EntityFrameworkCore.Migrations.Tests.csproj b/EFCore/tests/MySql.EFCore.Migrations.Tests/MySql.EntityFrameworkCore.Migrations.Tests.csproj index 06039067f..dca0d5bed 100644 --- a/EFCore/tests/MySql.EFCore.Migrations.Tests/MySql.EntityFrameworkCore.Migrations.Tests.csproj +++ b/EFCore/tests/MySql.EFCore.Migrations.Tests/MySql.EntityFrameworkCore.Migrations.Tests.csproj @@ -14,7 +14,7 @@ - + $(TargetFrameworks);net10.0 diff --git a/MySQL.Data/src/MySql.Data.csproj b/MySQL.Data/src/MySql.Data.csproj index 99c82ff89..e8d4a0b3c 100644 --- a/MySQL.Data/src/MySql.Data.csproj +++ b/MySQL.Data/src/MySql.Data.csproj @@ -27,7 +27,7 @@ - + $(TargetFrameworks);net10.0 @@ -72,7 +72,7 @@ - + diff --git a/MySQL.Data/tests/MySql.Data.Tests/MySql.Data.Tests.csproj b/MySQL.Data/tests/MySql.Data.Tests/MySql.Data.Tests.csproj index 9455959c7..48a44cec0 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/MySql.Data.Tests.csproj +++ b/MySQL.Data/tests/MySql.Data.Tests/MySql.Data.Tests.csproj @@ -29,7 +29,7 @@ - + $(TargetFrameworks);net10.0 diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/MySqlX.Data.Tests.csproj b/MySQL.Data/tests/MySqlX.Data.Tests/MySqlX.Data.Tests.csproj index 111476d40..0835199a7 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/MySqlX.Data.Tests.csproj +++ b/MySQL.Data/tests/MySqlX.Data.Tests/MySqlX.Data.Tests.csproj @@ -29,7 +29,7 @@ - + $(TargetFrameworks);net10.0 From b0f807545dfdf6a25f41c5c0981af085bb7911f5 Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Sun, 18 May 2025 18:07:11 -0600 Subject: [PATCH 115/125] Bug#37462099 Bug#38001821 [MySql.EntityFrameworkCore 8.0.8 rename bug] [Contribution: fix: invalid cast exception] This patch contains the fix of 2 bugs, one of which is a contribution and also that is partial fix for the other bug. Change-Id: I85856447880b4f805b136a5fbd696a82c8a3a9a1 --- CHANGES | 2 + .../Internal/MySQLHistoryRepository.cs | 4 +- .../Migrations/MySQLMigrationsSqlGenerator.cs | 2 +- .../MySQLMigrationsTests.cs | 14 ++++ .../TestData/Bug37462099Context.cs | 74 ++++++++++++++++++ .../Bug37462099ContextModelSnapshot.cs | 68 ++++++++++++++++ .../Bug37462099Migrations.Designer.cs | 71 +++++++++++++++++ .../TestData/Bug37462099Migrations.cs | 78 +++++++++++++++++++ 8 files changed, 310 insertions(+), 3 deletions(-) create mode 100644 EFCore/tests/MySql.EFCore.Migrations.Tests/TestData/Bug37462099Context.cs create mode 100644 EFCore/tests/MySql.EFCore.Migrations.Tests/TestData/Bug37462099ContextModelSnapshot.cs create mode 100644 EFCore/tests/MySql.EFCore.Migrations.Tests/TestData/Bug37462099Migrations.Designer.cs create mode 100644 EFCore/tests/MySql.EFCore.Migrations.Tests/TestData/Bug37462099Migrations.cs diff --git a/CHANGES b/CHANGES index 3e541c719..cf7768e47 100644 --- a/CHANGES +++ b/CHANGES @@ -3,6 +3,8 @@ - Fixed Entity Framework 6 from NET9 is deprecated due to Nunit4 Upgrade (MySQL Bug #117976, Oracle Bug #37837374). - Added support for GSSAPI/Kerberos authentication on Windows using authentication_ldap_sasl_client plug-in (WL15984). - Added support for .NET 10 and EF Core 10 preview versions (WL16900). +- Fixed MySql.EntityFrameworkCore 8.0.8 rename bug (MySQL Bug #116704, Oracle Bug #37462099). +- Fixed Invalid cast exception (MySQL Bug #118282, Oracle Bug #38001821). Thanks to Dev Nullinside for the contribution. 9.3.0 diff --git a/EFCore/src/Migrations/Internal/MySQLHistoryRepository.cs b/EFCore/src/Migrations/Internal/MySQLHistoryRepository.cs index d155c14be..ce1c8d1f0 100644 --- a/EFCore/src/Migrations/Internal/MySQLHistoryRepository.cs +++ b/EFCore/src/Migrations/Internal/MySQLHistoryRepository.cs @@ -95,10 +95,10 @@ public override async Task AcquireDatabaseLockAsync(Can Dependencies.MigrationsLogger.AcquiringMigrationLock(); var dbLock = CreateMigrationDatabaseLock(); - int result; + Int64 result; try { - result = (int)(await CreateGetLockCommand().ExecuteScalarAsync(CreateRelationalCommandParameters(), cancellationToken) + result = (Int64)(await CreateGetLockCommand().ExecuteScalarAsync(CreateRelationalCommandParameters(), cancellationToken) .ConfigureAwait(false))!; } catch diff --git a/EFCore/src/Migrations/MySQLMigrationsSqlGenerator.cs b/EFCore/src/Migrations/MySQLMigrationsSqlGenerator.cs index 239ff6753..e8e73db2f 100644 --- a/EFCore/src/Migrations/MySQLMigrationsSqlGenerator.cs +++ b/EFCore/src/Migrations/MySQLMigrationsSqlGenerator.cs @@ -128,7 +128,7 @@ protected override void Generate(RenameColumnOperation operation, IModel? model, var typeMapping = column.PropertyMappings.FirstOrDefault()?.TypeMapping; var converter = typeMapping?.Converter; - var clrType = (converter!.ProviderClrType ?? typeMapping!.ClrType).UnwrapNullableType(); + var clrType = (converter?.ProviderClrType ?? typeMapping!.ClrType).UnwrapNullableType(); var columnType = (string)(operation[RelationalAnnotationNames.ColumnType] ?? column[RelationalAnnotationNames.ColumnType])!; var isNullable = column.IsNullable; diff --git a/EFCore/tests/MySql.EFCore.Migrations.Tests/MySQLMigrationsTests.cs b/EFCore/tests/MySql.EFCore.Migrations.Tests/MySQLMigrationsTests.cs index 5b9ab9574..c19d102ca 100644 --- a/EFCore/tests/MySql.EFCore.Migrations.Tests/MySQLMigrationsTests.cs +++ b/EFCore/tests/MySql.EFCore.Migrations.Tests/MySQLMigrationsTests.cs @@ -31,7 +31,9 @@ using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.Extensions.DependencyInjection; using MySql.EntityFrameworkCore.Basic.Tests.Utils; +using MySql.EntityFrameworkCore.Migrations.Tests.TestData; using NUnit.Framework; +using System.Threading.Tasks; namespace MySql.EntityFrameworkCore.Migrations.Tests { @@ -69,5 +71,17 @@ public void TryPerformMigration() mytestContext.Database.EnsureDeleted(); } } + + //Bug#37462099 MySql.EntityFrameworkCore 8.0.8 rename bug + [Test] + public async Task MigrationFailsWIthRenameColumn() + { + Bug37462099Context context = new Bug37462099Context(); + + context.Database.EnsureCreated(); + context.Database.EnsureDeleted(); + await context.Database.MigrateAsync(); + context.Database.EnsureDeleted(); + } } } diff --git a/EFCore/tests/MySql.EFCore.Migrations.Tests/TestData/Bug37462099Context.cs b/EFCore/tests/MySql.EFCore.Migrations.Tests/TestData/Bug37462099Context.cs new file mode 100644 index 000000000..f01d4eb3a --- /dev/null +++ b/EFCore/tests/MySql.EFCore.Migrations.Tests/TestData/Bug37462099Context.cs @@ -0,0 +1,74 @@ +// Copyright © 2025, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using Microsoft.EntityFrameworkCore; +using System; +using System.ComponentModel.DataAnnotations; +using MySql.EntityFrameworkCore.Basic.Tests.Utils; + +namespace MySql.EntityFrameworkCore.Migrations.Tests.TestData +{ + public class Bug37462099Context : DbContext + { + public DbSet Entity { get; set; } + + public Bug37462099Context() : base() + { + } + + public Bug37462099Context(DbContextOptions options) : base(options) + { + } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + modelBuilder.Entity(builder => + { + builder.ToTable("Bug37462099"); + + builder.HasKey(p => p.Id); + + builder.Property(p => p.Name); + + builder.Property(p => p.Created); + }); + } + + protected override void OnConfiguring(DbContextOptionsBuilder options) + => options.UseMySQL(MySQLTestStore.RootConnectionString + "database=test;"); + } + + public class Bug37462099 + { + [Key] + public int Id { get; set; } + public string? Name { get; set; } + public DateTimeOffset Created { get; set; } + + } +} diff --git a/EFCore/tests/MySql.EFCore.Migrations.Tests/TestData/Bug37462099ContextModelSnapshot.cs b/EFCore/tests/MySql.EFCore.Migrations.Tests/TestData/Bug37462099ContextModelSnapshot.cs new file mode 100644 index 000000000..41a49b529 --- /dev/null +++ b/EFCore/tests/MySql.EFCore.Migrations.Tests/TestData/Bug37462099ContextModelSnapshot.cs @@ -0,0 +1,68 @@ +// Copyright © 2025, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace MySql.EntityFrameworkCore.Migrations.Tests.TestData +{ + [DbContext(typeof(Bug37462099Context))] + partial class Bug37462099ContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "9.0.3") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + modelBuilder.Entity("MySql.EntityFrameworkCore.Migrations.Tests.TestData.Bug37462099", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Created") + .HasColumnType("datetime"); + + b.Property("Name") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Bug37462099", (string)null); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/EFCore/tests/MySql.EFCore.Migrations.Tests/TestData/Bug37462099Migrations.Designer.cs b/EFCore/tests/MySql.EFCore.Migrations.Tests/TestData/Bug37462099Migrations.Designer.cs new file mode 100644 index 000000000..898193d40 --- /dev/null +++ b/EFCore/tests/MySql.EFCore.Migrations.Tests/TestData/Bug37462099Migrations.Designer.cs @@ -0,0 +1,71 @@ +// Copyright © 2025, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace MySql.EntityFrameworkCore.Migrations.Tests.TestData +{ + [DbContext(typeof(Bug37462099Context))] + [Migration("Bug37462099Migrations")] + partial class Bug37462099Migrations + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "9.0.3") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + modelBuilder.Entity("MySql.EntityFrameworkCore.Migrations.Tests.TestData.Bug37462099", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Created") + .HasColumnType("datetime"); + + b.Property("Name") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Bug37462099", (string)null); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/EFCore/tests/MySql.EFCore.Migrations.Tests/TestData/Bug37462099Migrations.cs b/EFCore/tests/MySql.EFCore.Migrations.Tests/TestData/Bug37462099Migrations.cs new file mode 100644 index 000000000..9e85e86ac --- /dev/null +++ b/EFCore/tests/MySql.EFCore.Migrations.Tests/TestData/Bug37462099Migrations.cs @@ -0,0 +1,78 @@ +// Copyright © 2025, Oracle and/or its affiliates. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, version 2.0, as +// published by the Free Software Foundation. +// +// This program is designed to work with certain software (including +// but not limited to OpenSSL) that is licensed under separate terms, as +// designated in a particular file or component or in included license +// documentation. The authors of MySQL hereby grant you an additional +// permission to link the program and your derivative works with the +// separately licensed software that they have either included with +// the program or referenced in the documentation. +// +// Without limiting anything contained in the foregoing, this file, +// which is part of MySQL Connector/NET, is also subject to the +// Universal FOSS Exception, version 1.0, a copy of which can be found at +// http://oss.oracle.com/licenses/universal-foss-exception. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License, version 2.0, for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +using System; +using Microsoft.EntityFrameworkCore.Migrations; +using MySql.EntityFrameworkCore.Metadata; + +#nullable disable + +namespace MySql.EntityFrameworkCore.Migrations.Tests.TestData +{ + /// + public partial class Bug37462099Migrations : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterDatabase() + .Annotation("MySQL:Charset", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "Bug37462099", + columns: table => new + { + Id = table.Column(type: "int", nullable: false).Annotation("MySQL:ValueGenerationStrategy", MySQLValueGenerationStrategy.IdentityColumn), + Name = table.Column(type: "longtext", nullable: true), + Created = table.Column(type: "datetime", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Bug37462099", x => x.Id); + }) + .Annotation("MySQL:Charset", "utf8mb4"); + + migrationBuilder.RenameColumn( + name: "Name", + table: "Bug37462099", + newName: "ChangedName").Annotation("Relational:ColumnType", "LONGTEXT;"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "Bug37462099"); + + migrationBuilder.RenameColumn( + name: "ChangedName", + table: "Bug37462099", + newName: "Name").Annotation("Relational:ColumnType", "LONGTEXT;"); + } + } +} From e59c0ebc8a2332a7b4fc8b64e41f0a0110551532 Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Thu, 5 Jun 2025 14:18:47 -0600 Subject: [PATCH 116/125] Bug#36303124 [MySqlHelper.ExecuteReaderAsync causes stack overflow] Change-Id: I852cdeb674af71b84cfc12104f9cacb67237e83f --- CHANGES | 1 + MySQL.Data/src/MySqlHelper.cs | 2 +- MySQL.Data/tests/MySql.Data.Tests/CmdTests.cs | 13 +++++++++++++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index cf7768e47..c5e5d96f6 100644 --- a/CHANGES +++ b/CHANGES @@ -5,6 +5,7 @@ - Added support for .NET 10 and EF Core 10 preview versions (WL16900). - Fixed MySql.EntityFrameworkCore 8.0.8 rename bug (MySQL Bug #116704, Oracle Bug #37462099). - Fixed Invalid cast exception (MySQL Bug #118282, Oracle Bug #38001821). Thanks to Dev Nullinside for the contribution. +- Fixed MySqlHelper.ExecuteReaderAsync causes stack overflow (MySQL Bug #114006, Oracle Bug #36303124). 9.3.0 diff --git a/MySQL.Data/src/MySqlHelper.cs b/MySQL.Data/src/MySqlHelper.cs index 06447877c..9d33fa16d 100644 --- a/MySQL.Data/src/MySqlHelper.cs +++ b/MySQL.Data/src/MySqlHelper.cs @@ -263,7 +263,7 @@ private static async Task ExecuteReaderAsync(bool execAsync, st /// Command text to use. /// An array of objects to use with the command. /// object ready to read the results of the command. - public static Task ExecuteReaderAsync(string connectionString, string commandText, params MySqlParameter[] commandParameters) => ExecuteReaderAsync(connectionString, commandText, commandParameters: commandParameters); + public static Task ExecuteReaderAsync(string connectionString, string commandText, params MySqlParameter[] commandParameters) => ExecuteReaderAsync(true, connectionString, commandText, commandParameters: commandParameters); public static Task ExecuteReaderAsync(string connectionString, string commandText, CancellationToken cancellationToken, params MySqlParameter[] commandParameters) => ExecuteReaderAsync(true, connectionString, commandText, cancellationToken, commandParameters); diff --git a/MySQL.Data/tests/MySql.Data.Tests/CmdTests.cs b/MySQL.Data/tests/MySql.Data.Tests/CmdTests.cs index e932704e3..b90b0d318 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/CmdTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/CmdTests.cs @@ -529,6 +529,19 @@ public void HelperTest() } } + /// + /// Bug #36303124 MySqlHelper.ExecuteReaderAsync causes stack overflow + /// + [Test] + public async Task MySqlHelper_ExecuteReader() + { + ExecuteSQL("CREATE TABLE Test (`id` int NOT NULL); INSERT INTO Test (id) VALUES (1);"); + + var reader = await MySqlHelper.ExecuteReaderAsync(Connection.ConnectionString, "SELECT * FROM Test WHERE id = @id", new MySqlParameter("@id", 1)); + + Assert.DoesNotThrowAsync(async () => await MySqlHelper.ExecuteReaderAsync(Connection.ConnectionString, "SELECT * FROM Test WHERE id = @id", new MySqlParameter("@id", 1))); + } + /// /// Bug #58652 ExecuteReader throws NullReferenceException when using CommandBehavior.Close /// From 7f37ef794e4fc86a3f340662dc2d7439d9d0aa59 Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Sat, 31 May 2025 20:28:13 -0600 Subject: [PATCH 117/125] Bug#37462116 [Connector/Net Not honouring MinPoolSize Configuration] Change-Id: I90f2d597e4aa28da84c7473eca06efaf7c27cb56 --- CHANGES | 1 + MySQL.Data/src/MySqlPool.cs | 4 +- .../tests/MySql.Data.Tests/PoolingTests.cs | 81 +++++++++++++++++++ 3 files changed, 84 insertions(+), 2 deletions(-) diff --git a/CHANGES b/CHANGES index c5e5d96f6..9efb43dc6 100644 --- a/CHANGES +++ b/CHANGES @@ -6,6 +6,7 @@ - Fixed MySql.EntityFrameworkCore 8.0.8 rename bug (MySQL Bug #116704, Oracle Bug #37462099). - Fixed Invalid cast exception (MySQL Bug #118282, Oracle Bug #38001821). Thanks to Dev Nullinside for the contribution. - Fixed MySqlHelper.ExecuteReaderAsync causes stack overflow (MySQL Bug #114006, Oracle Bug #36303124). +- Fixed bug Connector/Net Not honouring MinPoolSize Configuration (MySQL Bug #117020, Oracle Bug #37462116). 9.3.0 diff --git a/MySQL.Data/src/MySqlPool.cs b/MySQL.Data/src/MySqlPool.cs index c8c9b5cec..01826550d 100644 --- a/MySQL.Data/src/MySqlPool.cs +++ b/MySQL.Data/src/MySqlPool.cs @@ -132,8 +132,8 @@ private async Task GetPooledConnectionAsync(bool execAsync, Cancellation { if (HasIdleConnections) { - driver = _idlePool.Last.Value; - _idlePool.RemoveLast(); + driver = _idlePool.First.Value; + _idlePool.RemoveFirst(); } } finally diff --git a/MySQL.Data/tests/MySql.Data.Tests/PoolingTests.cs b/MySQL.Data/tests/MySql.Data.Tests/PoolingTests.cs index decb80db6..2db1373ce 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/PoolingTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/PoolingTests.cs @@ -35,6 +35,7 @@ using System.Net.NetworkInformation; using System.Reflection; using System.Threading; +using System.Threading.Tasks; namespace MySql.Data.MySqlClient.Tests { @@ -612,6 +613,86 @@ void InsertSmallBlobInTestTableUsingPoolingConnection() } } + /// + /// Bug #37462116 + /// Connector/Net Not honouring MinPoolSize Configuration + /// + [Test] + public async Task MinPoolSizeNotCorrect() + { + int minPoolSize = 5; + var connectionString = $"server={Host};user={Settings.UserID};password={Settings.Password};port={Port};Max Pool Size=10;Min Pool Size={minPoolSize};sslmode=none;"; + + try + { + //change wait_timeout to force idle connections to close faster + using (var connection = new MySqlConnection(connectionString)) + { + connection.Open(); + using (var command = new MySqlCommand("SET GLOBAL wait_timeout = 10;", connection)) + { + command.ExecuteNonQuery(); + } + } + + //create connection pool using Min Pool Size of 5 + for (int i = 0; i < minPoolSize; i++) // Match MinPoolSize + { + using (var connection = new MySqlConnection(connectionString)) + { + connection.Open(); + using (var command = new MySqlCommand("SELECT CONNECTION_ID();", connection)) + { + command.ExecuteNonQuery(); + } + } + } + + //check that connection pool maintains the Min Pool Size + int cycleCounter = 0; + while (cycleCounter < minPoolSize * 2) + { + using (var connection = new MySqlConnection(connectionString)) + { + await connection.OpenAsync(); + + // Query all active connections + using (var command = new MySqlCommand("SHOW PROCESSLIST;", connection)) + using (var reader = await command.ExecuteReaderAsync()) + { + int connectionCount = 0; + + while (await reader.ReadAsync()) + { + //count the connections tied to the test user + string user = reader["User"].ToString(); + if (user == Settings.UserID) + { + connectionCount++; + } + } + // check that the ConnectionCount is equal or greater than the Min Pool Size + Assert.That(connectionCount, Is.GreaterThanOrEqualTo(minPoolSize)); + } + } + cycleCounter++; + await Task.Delay(2000); + } + } + finally + { + //change wait_timeout to default value; + using (var connection = new MySqlConnection(connectionString)) + { + connection.Open(); + using (var command = new MySqlCommand("SET GLOBAL wait_timeout = 28800;", connection)) + { + command.ExecuteNonQuery(); + } + } + } + } + #region WL14389 [Test, Description("Check Pooling Connection works correctly")] From f7bb533887efb1c304b209c9c06f16d5ce7e81bf Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Sat, 28 Sep 2024 17:07:21 -0600 Subject: [PATCH 118/125] Bug#35392218 [bugfix schema name (specially usefull when use multiple schema)] Change-Id: If76fae263de12827bd427c44887447059e46f762 --- CHANGES | 1 + .../Internal/MySQLSqlGenerationHelper.cs | 2 +- .../DbContextClasses/EntitiesClasses.cs | 14 +++ .../DbContextClasses/TestsContexts.cs | 47 ++++++++++ .../MySql.EFCore.Basic.Tests/EFCoreTests.cs | 85 ++++++++++++++++++- .../Utils/MySqlTestStore.cs | 5 ++ 6 files changed, 152 insertions(+), 2 deletions(-) diff --git a/CHANGES b/CHANGES index 9efb43dc6..de11be873 100644 --- a/CHANGES +++ b/CHANGES @@ -7,6 +7,7 @@ - Fixed Invalid cast exception (MySQL Bug #118282, Oracle Bug #38001821). Thanks to Dev Nullinside for the contribution. - Fixed MySqlHelper.ExecuteReaderAsync causes stack overflow (MySQL Bug #114006, Oracle Bug #36303124). - Fixed bug Connector/Net Not honouring MinPoolSize Configuration (MySQL Bug #117020, Oracle Bug #37462116). +- Fixed bug bugfix schema name (specially usefull when use multiple schema) (MySQL Bug #111030, Oracle Bug #35392218). Thanks to Stéphane Graziano for the contribution. 9.3.0 diff --git a/EFCore/src/Storage/Internal/MySQLSqlGenerationHelper.cs b/EFCore/src/Storage/Internal/MySQLSqlGenerationHelper.cs index 44bdba26f..4bcb445f6 100644 --- a/EFCore/src/Storage/Internal/MySQLSqlGenerationHelper.cs +++ b/EFCore/src/Storage/Internal/MySQLSqlGenerationHelper.cs @@ -83,6 +83,6 @@ protected virtual string GetObjectName(string name, string schema) ? _options.SchemaNameTranslator(schema, name) : name; - protected virtual string? GetSchemaName(string name, string schema) => null; + protected virtual string? GetSchemaName(string name, string schema) => schema; } } diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/DbContextClasses/EntitiesClasses.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/DbContextClasses/EntitiesClasses.cs index d28d32e81..e63c36c4c 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/DbContextClasses/EntitiesClasses.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/DbContextClasses/EntitiesClasses.cs @@ -171,6 +171,20 @@ public class Person public string? Name { get; set; } } + public class Bug35392218_1 + { + public int Id { get; set; } + + public string? Name { get; set; } + } + + public class Bug35392218_2 + { + public int Id { get; set; } + + public string? Name { get; set; } + } + public class Guest { [Key] diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/DbContextClasses/TestsContexts.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/DbContextClasses/TestsContexts.cs index 156e905be..549919bb0 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/DbContextClasses/TestsContexts.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/DbContextClasses/TestsContexts.cs @@ -57,6 +57,53 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) } } + public class Bug35392218Context : DbContext + { + public Bug35392218Context() : base() + { + } + + public Bug35392218Context(DbContextOptions options) : base(options) + { + } + + public virtual DbSet NameList { get; set; } + + private string schemaName = "schemaBug35392218_1"; + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + base.OnModelCreating(modelBuilder); + + modelBuilder.Entity(entity => + { + entity.ToTable("Bug35392218_table1", "schemaBug35392218_1"); + + entity.HasKey(e => e.Id).HasName("id"); + + entity.Property(e => e.Name) + .HasColumnType("varchar(40)") + .HasColumnName("name"); + }); + + modelBuilder.Entity(entity => + { + entity.ToTable("Bug35392218_table2", "schemaBug35392218_2"); + + entity.HasKey(e => e.Id).HasName("id"); + + entity.Property(e => e.Name) + .HasColumnType("varchar(40)") + .HasColumnName("name"); + }); + } + + protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) + { + optionsBuilder.UseMySQL(MySQLTestStore.GetContextConnectionStringWithName(schemaName)); + } + } + public class NoConfigurationContext : DbContext { public DbSet Blogs { get; set; } diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/EFCoreTests.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/EFCoreTests.cs index 531dd6025..785c8c665 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/EFCoreTests.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/EFCoreTests.cs @@ -31,7 +31,6 @@ using MySql.EntityFrameworkCore.Basic.Tests.DbContextClasses; using MySql.EntityFrameworkCore.Basic.Tests.Utils; using NUnit.Framework; -using NUnit.Framework.Legacy; using System; using System.Linq; using System.Transactions; @@ -201,5 +200,89 @@ public void DateTimeEqualityCheck() Assert.That(test.Count, Is.EqualTo(1)); } } + + /// + /// Bug#35392218 [bugfix schema name (specially usefull when use multiple schema..] + /// + [Test] + public void MultipleSchemaContext() + { + using (Bug35392218Context context = new Bug35392218Context()) + { + context.Database.EnsureDeleted(); + context.Database.EnsureCreated(); + + using (MySqlConnection connection = new MySqlConnection(MySQLTestStore.BaseConnectionString)) + { + connection.Open(); + + MySqlCommand command = connection.CreateCommand(); + command.CommandText = "SHOW DATABASES LIKE '%bug35392218%';"; + + MySqlDataReader reader = command.ExecuteReader(); + int rowCount = 0; + while (reader.Read()) + { + rowCount++; + } + + //Checking if 2 databases related to the bug number are created in the server; + Assert.That(rowCount, Is.EqualTo(2)); + reader.Close(); + } + + context.Add(new Bug35392218_1 { Id = 1, Name = "John Doe" }); + context.Add(new Bug35392218_2 { Id = 1, Name = "John Doe" }); + context.SaveChanges(); + + using (MySqlConnection connection = new MySqlConnection(MySQLTestStore.BaseConnectionString + "database=schemaBug35392218_1;")) + { + connection.Open(); + + MySqlCommand command = connection.CreateCommand(); + command.CommandText = "SELECT * FROM Bug35392218_table1"; + + MySqlDataReader reader = command.ExecuteReader(); + int rowCount = 0; + while (reader.Read()) + { + rowCount++; + } + + //Checking if the data is available in 'schemaBug35392218_1' as its the default database definded in the context configuration. + Assert.That(rowCount, Is.EqualTo(1)); + Assert.That(reader.GetString(1), Is.EqualTo("John Doe")); + + reader.Close(); + + command.CommandText = "DROP DATABASE IF EXISTS schemaBug35392218_1;"; + command.ExecuteNonQuery(); + } + + using (MySqlConnection connection = new MySqlConnection(MySQLTestStore.BaseConnectionString + "database=schemaBug35392218_2;")) + { + connection.Open(); + + MySqlCommand command = connection.CreateCommand(); + command.CommandText = "SELECT * FROM Bug35392218_table2"; + + MySqlDataReader reader = command.ExecuteReader(); + int rowCount = 0; + while (reader.Read()) + { + rowCount++; + } + + //Checking if the same data is also inserted into 'schemaBug35392218_2' which is the other database defined in model creation. + Assert.That(rowCount, Is.EqualTo(1)); + Assert.That(reader.GetString(1), Is.EqualTo("John Doe")); + + reader.Close(); + + command.CommandText = "DROP DATABASE IF EXISTS schemaBug35392218_2;"; + command.ExecuteNonQuery(); + } + } + } } } diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/Utils/MySqlTestStore.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/Utils/MySqlTestStore.cs index 4601e4c5b..59b4bf5a7 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/Utils/MySqlTestStore.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/Utils/MySqlTestStore.cs @@ -89,6 +89,11 @@ internal static string GetContextConnectionString(Type type) return MySQLTestStore.RootConnectionString + $";database={name};"; } + internal static string GetContextConnectionStringWithName(string name) + { + return MySQLTestStore.RootConnectionString + $";database={name};"; + } + public static string Port() { var port = Environment.GetEnvironmentVariable("MYSQL_PORT"); From f2c5fd97df26c2ca25c7e032c1197a8f3f771c41 Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Wed, 4 Jun 2025 11:15:19 -0600 Subject: [PATCH 119/125] Bug#38029691 [Reorganize Test Suite] Change-Id: Ib868de3951d12f1acc79eb5825f49cf219006678 --- CHANGES | 1 + .../tests/MySql.Data.Tests/AuthTests.cs | 157 ------------------ .../tests/MySql.Data.Tests/Resources/my.ini | 15 -- 3 files changed, 1 insertion(+), 172 deletions(-) diff --git a/CHANGES b/CHANGES index de11be873..5de140640 100644 --- a/CHANGES +++ b/CHANGES @@ -8,6 +8,7 @@ - Fixed MySqlHelper.ExecuteReaderAsync causes stack overflow (MySQL Bug #114006, Oracle Bug #36303124). - Fixed bug Connector/Net Not honouring MinPoolSize Configuration (MySQL Bug #117020, Oracle Bug #37462116). - Fixed bug bugfix schema name (specially usefull when use multiple schema) (MySQL Bug #111030, Oracle Bug #35392218). Thanks to Stéphane Graziano for the contribution. +- Fixed bug reorganize test suite (Oracle Bug #38029691). 9.3.0 diff --git a/MySQL.Data/tests/MySql.Data.Tests/AuthTests.cs b/MySQL.Data/tests/MySql.Data.Tests/AuthTests.cs index c80c4fdea..952e044db 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/AuthTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/AuthTests.cs @@ -1160,49 +1160,6 @@ public void AssertScramSha256() } #endregion - #region GSSAPI/Kerberos Mechanism - /// - /// WL14210 - [Classic] Add LDAP kerberos support (GSSAPI) - /// This test require to start MySQL Commercial Server with the configuration specified in file Resources/my.ini - /// It uses preconfigured LDAP servers present in the labs. - /// For configuration of the server, theres a quick guide in Resources/KerberosConfig.txt to setup the environment. - /// - [TestCase("test1@MTR.LOCAL", "Testpw1", "authentication_ldap_sasl", true)] - [TestCase("invalidUser@MTR.LOCAL", "Testpw1", "authentication_ldap_sasl", false)] - [TestCase("test1@MTR.LOCAL", "wrongPassword", "authentication_ldap_sasl", false)] - [Ignore("This test require to start MySQL Commercial Server with the configuration specified in file Resources/my.ini")] - [Property("Category", "Security")] - public void ConnectUsingMySqlSASLPluginGSSAPI(string userName, string password, string pluginName, bool shouldPass) - { - MySqlConnectionStringBuilder settings = new MySqlConnectionStringBuilder(Settings.ConnectionString) - { - UserID = userName, - Password = password, - Database = string.Empty, - SslMode = MySqlSslMode.Disabled - }; - - ExecuteSQL("CREATE USER 'test1@MTR.LOCAL' IDENTIFIED WITH authentication_ldap_sasl; GRANT ALL ON *.* to 'test1@MTR.LOCAL';", true); - - using (MySqlConnection connection = new MySqlConnection(settings.ConnectionString)) - { - if (shouldPass) - { - connection.Open(); - MySqlCommand command = new MySqlCommand($"SELECT user();", connection); - using (MySqlDataReader reader = command.ExecuteReader()) - { - Assert.That(MySqlSASLPlugin.gssapiMechanism.MechanismName, Is.EqualTo("GSSAPI").IgnoreCase); - Assert.That(reader.Read(), Is.True); - Assert.That(reader.GetString(0), Does.Contain(userName)); - } - } - else - Assert.Throws(() => connection.Open()); - } - } - #endregion - [Test] public void AssertSaslPrep() { @@ -1279,120 +1236,6 @@ public void AssertSaslPrep() } #endregion - #region PureKerberos Mechanism - /// - /// WL14429 - [Classic] Support for authentication_kerberos_client authentication plugin - /// WL14654 - [Classic] Integrate new SSPI kerberos library - /// WL15341 - [Classic] Support MIT Kerberos library on Windows - /// These tests require to start MySQL Commercial Server with the configuration specified in file Resources/my.ini - /// It uses preconfigured LDAP servers present in the labs. - /// For configuration of the server, there's a quick guide in Resources/KerberosConfig.txt to setup the environment. - /// For SSPI, Windows client should be part of Windows server domain. - /// Please refer to the WLs to check the specifications for each case. - /// - - [TestCase(false, "invalidUser", "", "", null)] - [TestCase(false, "invalidUser", "fakePassword", "", null)] - [TestCase(false, "", "", "caching_sha2_password", null)] - [TestCase(true, "", "", "authentication_kerberos_client", KerberosAuthMode.GSSAPI)] // TRUE: if there's a TGT in cache or the login user is in KDC. 'AUTO' if logged-in user is properly configured - [TestCase(true, "", "falsePassword", "authentication_kerberos_client", KerberosAuthMode.GSSAPI)] - [TestCase(true, "", "Testpw1", "authentication_kerberos_client", KerberosAuthMode.GSSAPI)] - [TestCase(true, "test1", "Testpw1", "authentication_kerberos_client", KerberosAuthMode.AUTO)] - [TestCase(true, "test1", "Testpw1", "sha256_password", KerberosAuthMode.AUTO)] - [TestCase(true, "test1", "Testpw1", "", KerberosAuthMode.AUTO)] - [TestCase(true, "test1", "wrongPassword", "", KerberosAuthMode.GSSAPI)] // TRUE: if there's a TGT in cache. - [TestCase(true, "test1", "", "", KerberosAuthMode.GSSAPI)] - [Ignore("This test require to start MySQL Commercial Server with the configuration specified in file Resources/my.ini")] - [Property("Category", "Security")] - public void ConnectUsingMySqlPluginKerberosAUTO(bool shouldPass, string userName, string password, string pluginName, KerberosAuthMode mode) - { - MySqlConnectionStringBuilder settings = new MySqlConnectionStringBuilder(Settings.ConnectionString) - { - UserID = userName, - Password = password, - DefaultAuthenticationPlugin = pluginName - }; - - TestKerberosConnection(shouldPass, userName, settings, mode); - } - - [TestCase(false, "invalidUser", "", "", null)] - [TestCase(false, "invalidUser", "fakePassword", "", null)] - [TestCase(false, "", "", "caching_sha2_password", null)] - [TestCase(false, "", "", "authentication_kerberos_client", null)] // TRUE if logged-in user is properly configured in MySQL Server - [TestCase(false, "", "falsePassword", "authentication_kerberos_client", null)] // SSPI will use the logged-in user and the password provided - [TestCase(false, "test1", "wrongPassword", "", null)] - [TestCase(true, "", "Testpw1", "authentication_kerberos_client", KerberosAuthMode.SSPI)] // logged-in user should be properly configured in MySQL server - [TestCase(true, "test1", "Testpw1", "authentication_kerberos_client", KerberosAuthMode.SSPI)] - [TestCase(true, "test1", "Testpw1", "sha256_password", KerberosAuthMode.SSPI)] - [TestCase(true, "test1", "Testpw1", "", KerberosAuthMode.SSPI)] - [TestCase(true, "test1", "", "", KerberosAuthMode.SSPI)] // MySQL user should match with logged-in Windows user - [Ignore("This test require to start MySQL Commercial Server with the configuration specified in file Resources/my.ini")] - [Property("Category", "Security")] - public void ConnectUsingMySqlPluginKerberosSSPI(bool shouldPass, string userName, string password, string pluginName, KerberosAuthMode mode) - { - MySqlConnectionStringBuilder settings = new MySqlConnectionStringBuilder(Settings.ConnectionString) - { - UserID = userName, - Password = password, - DefaultAuthenticationPlugin = pluginName, - KerberosAuthMode = KerberosAuthMode.SSPI - }; - - TestKerberosConnection(shouldPass, userName, settings, mode); - } - - [TestCase(false, "invalidUser", "", "", null)] - [TestCase(false, "invalidUser", "fakePassword", "", null)] - [TestCase(false, "", "", "caching_sha2_password", null)] - [TestCase(true, "", "", "authentication_kerberos_client", KerberosAuthMode.GSSAPI)] // TRUE: if there's a TGT in cache or the login user is in KDC. - [TestCase(true, "", "falsePassword", "authentication_kerberos_client", KerberosAuthMode.GSSAPI)] // TRUE: if there's a TGT in cache or the login user is in KDC. - [TestCase(true, "", "Testpw1", "authentication_kerberos_client", KerberosAuthMode.GSSAPI)] // TRUE: if there's a TGT in cache or the login user is in KDC. - [TestCase(true, "test1", "Testpw1", "authentication_kerberos_client", KerberosAuthMode.GSSAPI)] - [TestCase(true, "test1", "Testpw1", "sha256_password", KerberosAuthMode.GSSAPI)] - [TestCase(true, "test1", "Testpw1", "", KerberosAuthMode.GSSAPI)] - [TestCase(true, "test1", "wrongPassword", "", KerberosAuthMode.GSSAPI)] // TRUE: if there's a TGT in cache - [TestCase(true, "test1", "", "", KerberosAuthMode.GSSAPI)] // TRUE: if there's a TGT in cache - [Ignore("This test require to start MySQL Commercial Server with the configuration specified in file Resources/my.ini")] - [Property("Category", "Security")] - public void ConnectUsingMySqlPluginKerberosGSSAPI(bool shouldPass, string userName, string password, string pluginName, KerberosAuthMode mode) - { - MySqlConnectionStringBuilder settings = new MySqlConnectionStringBuilder(Settings.ConnectionString) - { - UserID = userName, - Password = password, - DefaultAuthenticationPlugin = pluginName, - KerberosAuthMode = KerberosAuthMode.GSSAPI - }; - - TestKerberosConnection(shouldPass, userName, settings, mode); - } - - private void TestKerberosConnection(bool shouldPass, string username, MySqlConnectionStringBuilder settings, KerberosAuthMode mode) - { - ExecuteSQL("CREATE USER IF NOT EXISTS 'test1'@'%' IDENTIFIED WITH authentication_kerberos BY 'MTR.LOCAL'; " + - "GRANT ALL ON *.* to 'test1'@'%';", true); - - using (MySqlConnection conn = new MySqlConnection(settings.ConnectionString)) - { - if (shouldPass) - { - conn.Open(); - MySqlCommand command = new MySqlCommand($"SELECT user();", conn); - using (MySqlDataReader reader = command.ExecuteReader()) - { - Assert.That(reader.Read(), Is.True); - Assert.That(reader.GetString(0), Does.Contain(username)); - } - - Assert.That(conn.Settings.KerberosAuthMode == mode); - } - else - Assert.Throws(() => conn.Open()); - } - } - #endregion - #region OCI IAM Authentication /// /// WL14708 - Support OCI IAM authentication diff --git a/MySQL.Data/tests/MySql.Data.Tests/Resources/my.ini b/MySQL.Data/tests/MySql.Data.Tests/Resources/my.ini index b226f0fe7..9cc75dd70 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Resources/my.ini +++ b/MySQL.Data/tests/MySql.Data.Tests/Resources/my.ini @@ -29,18 +29,3 @@ authentication_ldap_sasl_auth_method_name='SCRAM-SHA-256' authentication_ldap_sasl_log_status=6 authentication_ldap_sasl_group_search_attr='' authentication_ldap_sasl_user_search_attr='cn' - -### GSSAPI -plugin-load-add=authentication_ldap_sasl.so -authentication_ldap_sasl_server_host='winmtr01.regionaliad02.mysql2iad.oraclevcn.com' -authentication_ldap_sasl_bind_base_dn='CN=Users,DC=mtr,DC=local' -authentication_ldap_sasl_auth_method_name='GSSAPI' -authentication_ldap_sasl_bind_root_dn='CN=test1,CN=Users,DC=mtr,DC=local' -authentication_ldap_sasl_log_status=6 -authentication_ldap_sasl_group_search_attr='cn' -authentication_ldap_sasl_bind_root_pwd='Testpw1' - -### KERBEROS -plugin-load-add = authentication_kerberos.so -authentication_kerberos_service_principal = "mysql_service/kerberos_auth_host@MTR.LOCAL" -authentication_kerberos_service_key_tab = "{full_path_to:mysql.keytab}" \ No newline at end of file From f436ce42d20f2fdc9d296d6d17e0a7a69e66196f Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Tue, 10 Jun 2025 11:20:12 -0600 Subject: [PATCH 120/125] Fix failing tests Change-Id: Ib8f8a724337dd55b7d5c1ea5643fa313b950b18c --- MySQL.Data/tests/MySql.Data.Tests/CmdTests.cs | 13 ------------ .../netstandard2_0/MySQLHelperTests.cs | 20 +++++++++++++++++++ 2 files changed, 20 insertions(+), 13 deletions(-) diff --git a/MySQL.Data/tests/MySql.Data.Tests/CmdTests.cs b/MySQL.Data/tests/MySql.Data.Tests/CmdTests.cs index b90b0d318..e932704e3 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/CmdTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/CmdTests.cs @@ -529,19 +529,6 @@ public void HelperTest() } } - /// - /// Bug #36303124 MySqlHelper.ExecuteReaderAsync causes stack overflow - /// - [Test] - public async Task MySqlHelper_ExecuteReader() - { - ExecuteSQL("CREATE TABLE Test (`id` int NOT NULL); INSERT INTO Test (id) VALUES (1);"); - - var reader = await MySqlHelper.ExecuteReaderAsync(Connection.ConnectionString, "SELECT * FROM Test WHERE id = @id", new MySqlParameter("@id", 1)); - - Assert.DoesNotThrowAsync(async () => await MySqlHelper.ExecuteReaderAsync(Connection.ConnectionString, "SELECT * FROM Test WHERE id = @id", new MySqlParameter("@id", 1))); - } - /// /// Bug #58652 ExecuteReader throws NullReferenceException when using CommandBehavior.Close /// diff --git a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MySQLHelperTests.cs b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MySQLHelperTests.cs index 31cd89da4..2dba3548a 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MySQLHelperTests.cs +++ b/MySQL.Data/tests/MySql.Data.Tests/Framework/netstandard2_0/MySQLHelperTests.cs @@ -167,6 +167,26 @@ public async Task ExecuteReaderAsync() } } + /// + /// Bug #36303124 MySqlHelper.ExecuteReaderAsync causes stack overflow + /// + [Test] + public async Task MySqlHelper_ExecuteReader() + { + try + { + ExecuteSQL("CREATE TABLE Test (`id` int NOT NULL); INSERT INTO Test (id) VALUES (1);"); + + var reader = await MySqlHelper.ExecuteReaderAsync(Connection.ConnectionString, "SELECT * FROM Test WHERE id = @id", new MySqlParameter("@id", 1)); + + Assert.DoesNotThrowAsync(async () => await MySqlHelper.ExecuteReaderAsync(Connection.ConnectionString, "SELECT * FROM Test WHERE id = @id", new MySqlParameter("@id", 1))); + } + finally + { + ExecuteSQL("DROP TABLE Test;"); + } + } + [Test] public async Task ExecuteScalarAsync() { From 1dcbeb1f107ae4ef2b0a881f6009607bb993d6c3 Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Wed, 11 Jun 2025 12:32:08 -0600 Subject: [PATCH 121/125] Fix failing tests - continuation Change-Id: Ife25896cdba6579a2cdf60746bc361d45d9bd125 --- .../DbContextClasses/TestsContexts.cs | 6 +- .../MySql.EFCore.Basic.Tests/EFCoreTests.cs | 114 ++++++++++-------- .../MySql.Data.Tests/MySql.Data.Tests.csproj | 2 +- .../tests/MySqlX.Data.Tests/SessionTests.cs | 10 +- 4 files changed, 70 insertions(+), 62 deletions(-) diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/DbContextClasses/TestsContexts.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/DbContextClasses/TestsContexts.cs index 549919bb0..2bed1347e 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/DbContextClasses/TestsContexts.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/DbContextClasses/TestsContexts.cs @@ -69,7 +69,7 @@ public Bug35392218Context(DbContextOptions options) : base(options) public virtual DbSet NameList { get; set; } - private string schemaName = "schemaBug35392218_1"; + private string schemaName = "schema_bug35392218_1"; protected override void OnModelCreating(ModelBuilder modelBuilder) { @@ -77,7 +77,7 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) modelBuilder.Entity(entity => { - entity.ToTable("Bug35392218_table1", "schemaBug35392218_1"); + entity.ToTable("bug35392218_table1", "schema_bug35392218_1"); entity.HasKey(e => e.Id).HasName("id"); @@ -88,7 +88,7 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) modelBuilder.Entity(entity => { - entity.ToTable("Bug35392218_table2", "schemaBug35392218_2"); + entity.ToTable("bug35392218_table2", "schema_bug35392218_2"); entity.HasKey(e => e.Id).HasName("id"); diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/EFCoreTests.cs b/EFCore/tests/MySql.EFCore.Basic.Tests/EFCoreTests.cs index 785c8c665..35a7593a5 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/EFCoreTests.cs +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/EFCoreTests.cs @@ -207,79 +207,87 @@ public void DateTimeEqualityCheck() [Test] public void MultipleSchemaContext() { - using (Bug35392218Context context = new Bug35392218Context()) + try { - context.Database.EnsureDeleted(); - context.Database.EnsureCreated(); - - using (MySqlConnection connection = new MySqlConnection(MySQLTestStore.BaseConnectionString)) + using (Bug35392218Context context = new Bug35392218Context()) { - connection.Open(); + context.Database.EnsureDeleted(); + context.Database.EnsureCreated(); - MySqlCommand command = connection.CreateCommand(); - command.CommandText = "SHOW DATABASES LIKE '%bug35392218%';"; + context.Add(new Bug35392218_1 { Id = 1, Name = "John Doe" }); + context.Add(new Bug35392218_2 { Id = 1, Name = "John Doe" }); + context.SaveChanges(); - MySqlDataReader reader = command.ExecuteReader(); - int rowCount = 0; - while (reader.Read()) + using (MySqlConnection connection = new MySqlConnection(MySQLTestStore.BaseConnectionString)) { - rowCount++; + connection.Open(); + + MySqlCommand command = connection.CreateCommand(); + command.CommandText = "SHOW DATABASES LIKE '%bug35392218%';"; + + MySqlDataReader reader = command.ExecuteReader(); + int rowCount = 0; + while (reader.Read()) + { + rowCount++; + } + + //Checking if 2 databases related to the bug number are created in the server; + Assert.That(rowCount, Is.EqualTo(2)); + reader.Close(); } - //Checking if 2 databases related to the bug number are created in the server; - Assert.That(rowCount, Is.EqualTo(2)); - reader.Close(); - } + using (MySqlConnection connection = new MySqlConnection(MySQLTestStore.BaseConnectionString + "database=schema_bug35392218_1;")) + { + connection.Open(); - context.Add(new Bug35392218_1 { Id = 1, Name = "John Doe" }); - context.Add(new Bug35392218_2 { Id = 1, Name = "John Doe" }); - context.SaveChanges(); + MySqlCommand command = connection.CreateCommand(); + command.CommandText = "SELECT * FROM bug35392218_table1"; - using (MySqlConnection connection = new MySqlConnection(MySQLTestStore.BaseConnectionString + "database=schemaBug35392218_1;")) - { - connection.Open(); + MySqlDataReader reader = command.ExecuteReader(); + int rowCount = 0; + while (reader.Read()) + { + rowCount++; + } - MySqlCommand command = connection.CreateCommand(); - command.CommandText = "SELECT * FROM Bug35392218_table1"; + //Checking if the data is available in 'schemaBug35392218_1' as its the default database definded in the context configuration. + Assert.That(rowCount, Is.EqualTo(1)); + Assert.That(reader.GetString(1), Is.EqualTo("John Doe")); - MySqlDataReader reader = command.ExecuteReader(); - int rowCount = 0; - while (reader.Read()) - { - rowCount++; + reader.Close(); } - //Checking if the data is available in 'schemaBug35392218_1' as its the default database definded in the context configuration. - Assert.That(rowCount, Is.EqualTo(1)); - Assert.That(reader.GetString(1), Is.EqualTo("John Doe")); + using (MySqlConnection connection = new MySqlConnection(MySQLTestStore.BaseConnectionString + "database=schema_bug35392218_2;")) + { + connection.Open(); - reader.Close(); + MySqlCommand command = connection.CreateCommand(); + command.CommandText = "SELECT * FROM bug35392218_table2"; - command.CommandText = "DROP DATABASE IF EXISTS schemaBug35392218_1;"; - command.ExecuteNonQuery(); - } + MySqlDataReader reader = command.ExecuteReader(); + int rowCount = 0; + while (reader.Read()) + { + rowCount++; + } + + //Checking if the same data is also inserted into 'schemaBug35392218_2' which is the other database defined in model creation. + Assert.That(rowCount, Is.EqualTo(1)); + Assert.That(reader.GetString(1), Is.EqualTo("John Doe")); - using (MySqlConnection connection = new MySqlConnection(MySQLTestStore.BaseConnectionString + "database=schemaBug35392218_2;")) + reader.Close(); + } + } + } + finally + { + using (MySqlConnection connection = new MySqlConnection(MySQLTestStore.BaseConnectionString)) { connection.Open(); MySqlCommand command = connection.CreateCommand(); - command.CommandText = "SELECT * FROM Bug35392218_table2"; - - MySqlDataReader reader = command.ExecuteReader(); - int rowCount = 0; - while (reader.Read()) - { - rowCount++; - } - - //Checking if the same data is also inserted into 'schemaBug35392218_2' which is the other database defined in model creation. - Assert.That(rowCount, Is.EqualTo(1)); - Assert.That(reader.GetString(1), Is.EqualTo("John Doe")); - - reader.Close(); - - command.CommandText = "DROP DATABASE IF EXISTS schemaBug35392218_2;"; + command.CommandText = "DROP DATABASE IF EXISTS schema_bug35392218_2;DROP DATABASE IF EXISTS schema_bug35392218_1;"; command.ExecuteNonQuery(); } } diff --git a/MySQL.Data/tests/MySql.Data.Tests/MySql.Data.Tests.csproj b/MySQL.Data/tests/MySql.Data.Tests/MySql.Data.Tests.csproj index 48a44cec0..4ec3a5c15 100644 --- a/MySQL.Data/tests/MySql.Data.Tests/MySql.Data.Tests.csproj +++ b/MySQL.Data/tests/MySql.Data.Tests/MySql.Data.Tests.csproj @@ -36,7 +36,7 @@ net462;net48;$(TargetFrameworks) - + diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/SessionTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/SessionTests.cs index d4bdfe89a..beb46edb7 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/SessionTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/SessionTests.cs @@ -563,7 +563,7 @@ public void ConnectTimeoutParameterValidation() MockServer mServer1 = new MockServer(false); mServer1.StartServer(); var conn = $"server={mServer1.Address},{Host};user=test;password=test;port={XPort};connecttimeout=2000;"; - TestConnectTimeoutSuccessTimeout(conn, 0, 10, "Fail over success"); + TestConnectTimeoutSuccessTimeout(conn, 0, 100, "Fail over success"); mServer1.StopServer(); mServer1.DisposeListener(); @@ -571,7 +571,7 @@ public void ConnectTimeoutParameterValidation() mServer1 = new MockServer(false); mServer1.StartServer(); conn = $"server={mServer1.Address};user=test;password=test;port={mServer1.Port};"; - TestConnectTimeoutFailureTimeout(conn, 9, 25, "Offline host default value", false); + TestConnectTimeoutFailureTimeout(conn, 9, 100, "Offline host default value", false); mServer1.StopServer(); mServer1.DisposeListener(); @@ -579,7 +579,7 @@ public void ConnectTimeoutParameterValidation() mServer1 = new MockServer(false); mServer1.StartServer(); conn = $"server={mServer1.Address} ;user=test;password=test;port= {mServer1.Port};connecttimeout=15000"; - TestConnectTimeoutFailureTimeout(conn, 14, 35, "Offline host 15000ms", false); + TestConnectTimeoutFailureTimeout(conn, 14, 100, "Offline host 15000ms", false); mServer1.StopServer(); mServer1.DisposeListener(); @@ -1654,10 +1654,10 @@ public void TimeoutWithWrongHost() mServer.StartServer(); connStr = $"mysqlx://{session.Settings.UserID}:{ session.Settings.Password}@{mServer.Address.ToString()}:{mServer.Port.ToString()}"; if(Uri.TryCreate(connStr, UriKind.Absolute, out _)) - TestConnectStringTimeoutFailureTimeout(connStr, 9, 20, "Timeout value between 9 and 20 seconds"); + TestConnectStringTimeoutFailureTimeout(connStr, 9, 100, "Timeout value between 9 and 20 seconds"); var connObj = new { server = mServer.Address.ToString(), port = mServer.Port.ToString(), user = session.Settings.UserID, password = session.Settings.Password }; - TestConnectObjTimeoutFailureTimeout(connObj, 9, 20, "Timeout value between 9 and 20 seconds"); + TestConnectObjTimeoutFailureTimeout(connObj, 9, 100, "Timeout value between 9 and 20 seconds"); mServer.StopServer(); mServer.DisposeListener(); From ddac85bd8a362c53fb52b20f858f3629f263ea70 Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Wed, 11 Jun 2025 20:18:58 -0600 Subject: [PATCH 122/125] Update EF Core versions Change-Id: If4a607ee8885ac5cc439a4a143fc76c9cd1378d1 --- EFCore/src/MySql.EntityFrameworkCore.csproj | 8 ++++---- .../MySql.EntityFrameworkCore.Basic.Tests.csproj | 4 ++-- .../MySql.EntityFrameworkCore.Design.Tests.csproj | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/EFCore/src/MySql.EntityFrameworkCore.csproj b/EFCore/src/MySql.EntityFrameworkCore.csproj index 5ba39ee3e..8a96c4f35 100644 --- a/EFCore/src/MySql.EntityFrameworkCore.csproj +++ b/EFCore/src/MySql.EntityFrameworkCore.csproj @@ -27,13 +27,13 @@ - - + + - - + + diff --git a/EFCore/tests/MySql.EFCore.Basic.Tests/MySql.EntityFrameworkCore.Basic.Tests.csproj b/EFCore/tests/MySql.EFCore.Basic.Tests/MySql.EntityFrameworkCore.Basic.Tests.csproj index f4f0ada6e..f3c7b8036 100644 --- a/EFCore/tests/MySql.EFCore.Basic.Tests/MySql.EntityFrameworkCore.Basic.Tests.csproj +++ b/EFCore/tests/MySql.EFCore.Basic.Tests/MySql.EntityFrameworkCore.Basic.Tests.csproj @@ -18,11 +18,11 @@ - + - + diff --git a/EFCore/tests/MySql.EFCore.Design.Tests/MySql.EntityFrameworkCore.Design.Tests.csproj b/EFCore/tests/MySql.EFCore.Design.Tests/MySql.EntityFrameworkCore.Design.Tests.csproj index 49afddd2f..632c8baa4 100644 --- a/EFCore/tests/MySql.EFCore.Design.Tests/MySql.EntityFrameworkCore.Design.Tests.csproj +++ b/EFCore/tests/MySql.EFCore.Design.Tests/MySql.EntityFrameworkCore.Design.Tests.csproj @@ -34,11 +34,11 @@ - + - + From 17fa1621dd5a67895ac14c10a73dcf4bc728eb15 Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Wed, 11 Jun 2025 20:32:05 -0600 Subject: [PATCH 123/125] Updated Documentation Change-Id: I98f28b1960f56e7a4a2c080328e054800d90b51f --- Documentation/docfx.json | 2 +- Documentation/index.md | 4 ++-- README.md | 2 ++ Release Notes.txt | 9 +++++---- 4 files changed, 10 insertions(+), 7 deletions(-) diff --git a/Documentation/docfx.json b/Documentation/docfx.json index d01f8fce2..f194fe7e3 100644 --- a/Documentation/docfx.json +++ b/Documentation/docfx.json @@ -28,7 +28,7 @@ } ], "dest": "api/efcore_api", - "properties": { "TargetFramework": "net8.0" } + "properties": { "TargetFramework": "net9.0" } }, { "src": [ diff --git a/Documentation/index.md b/Documentation/index.md index 36f5c177e..8fed932d0 100644 --- a/Documentation/index.md +++ b/Documentation/index.md @@ -1,6 +1,6 @@ ## MySQL Connector/NET and X DevAPI -MySQL Connector/NET 9.3 supports X Protocol, which enables you to use X DevAPI with the .NET language of choice to develop applications that communicate with a MySQL server functioning as a document store, relational database, or both. +MySQL Connector/NET 9.4 supports X Protocol, which enables you to use X DevAPI with the .NET language of choice to develop applications that communicate with a MySQL server functioning as a document store, relational database, or both. To get started, review the following main classes: @@ -16,7 +16,7 @@ For an introduction to X DevAPI concepts, see the [X DevAPI User Guide](https:// ## MySQL Connector/NET -MySQL Connector/NET 9.3 also supports the development of .NET, .NET Core and .NET Framework applications that require secure, high-performance data connectivity with MySQL through the classic protocol. It supports ADO.NET, Entity Framework and various web providers. +MySQL Connector/NET 9.4 also supports the development of .NET, .NET Core and .NET Framework applications that require secure, high-performance data connectivity with MySQL through the classic protocol. It supports ADO.NET, Entity Framework and various web providers. To get started, review the following main classes: diff --git a/README.md b/README.md index 3be431d7c..c9d28945f 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,8 @@ From MySQL Connector/NET 9.2, the driver removes support for .NET 6 and EF Core From MySQL Connector/NET 9.3, the driver adds fixes to test suite and support for newest versions of EF Core 8 and EF Core 9. +From MySQL Connector/NET 9.4, the driver adds fixes to test suite and support for preview versions of [EF Core 10](https://learn.microsoft.com/en-us/ef/core/what-is-new/ef-core-10.0/whatsnew) and [.NET 10](https://learn.microsoft.com/en-us/dotnet/core/whats-new/dotnet-10/overview). + For detailed information please visit the official [MySQL Connector/NET documentation](https://dev.mysql.com/doc/connector-net/en/). ## Licensing diff --git a/Release Notes.txt b/Release Notes.txt index ccee1223a..bb3cd1af3 100644 --- a/Release Notes.txt +++ b/Release Notes.txt @@ -1,9 +1,10 @@ -Connector/NET 9.3 Release Notes +Connector/NET 9.4 Release Notes ------------------------------------ -Welcome to the release notes for Connector/NET 9.1 +Welcome to the release notes for Connector/NET 9.4 -What's new in 9.3 +What's new in 9.4 -------------------- -Connector/NET now supports the newest version of EFCore 8 and EFCore 9. +Connector/NET now supports the preview version of .NET 10 and EF Core 10. +Connector/NET now supports GSSAPI/Kerberos authentication on windows through authentication_ldap_sasl_client plug-in. Connector/NET added fixes to testsuite. \ No newline at end of file From fae1b641b4dac047b490b682d35b276fecb3dcbd Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Wed, 11 Jun 2025 20:35:15 -0600 Subject: [PATCH 124/125] Updated the LICENSE files. Change-Id: Iedfcfd54c341121481bb77d21d5f105a2b0036eb --- LICENSE | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/LICENSE b/LICENSE index b1ca05180..5bd685ccc 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ Licensing Information User Manual -MySQL Connector/NET 9.3.0 Community +MySQL Connector/NET 9.4.0 Community __________________________________________________________________ Introduction @@ -8,18 +8,18 @@ Introduction This License Information User Manual contains Oracle's product license and other licensing information, including licensing information for third-party software which may be included in this distribution of - MySQL Connector/NET 9.3.0 Community. + MySQL Connector/NET 9.4.0 Community. - Last updated: March 2025 + Last updated: June 2025 Licensing Information - This release of MySQL Connector/NET 9.3.0 Community is brought to you + This release of MySQL Connector/NET 9.4.0 Community is brought to you by the MySQL team at Oracle. This software is released under version 2 of the GNU General Public License (GPLv2), as set forth below, with the following additional permissions: - This distribution of MySQL Connector/NET 9.3.0 Community is designed to + This distribution of MySQL Connector/NET 9.4.0 Community is designed to work with certain software (including but not limited to OpenSSL) that is licensed under separate terms, as designated in a particular file or component or in the license documentation. Without limiting your rights From 07b692810f368a9009e74bb462670015c37727be Mon Sep 17 00:00:00 2001 From: Omar Chavez Date: Thu, 19 Jun 2025 10:04:22 -0600 Subject: [PATCH 125/125] Fix failing tests Change-Id: I66f2e12b74f1390965ec4037999c91b1bf70d779 --- MySQL.Data/tests/MySqlX.Data.Tests/SessionTests.cs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/MySQL.Data/tests/MySqlX.Data.Tests/SessionTests.cs b/MySQL.Data/tests/MySqlX.Data.Tests/SessionTests.cs index beb46edb7..d1fe27a25 100644 --- a/MySQL.Data/tests/MySqlX.Data.Tests/SessionTests.cs +++ b/MySQL.Data/tests/MySqlX.Data.Tests/SessionTests.cs @@ -1514,19 +1514,19 @@ public void TimeoutUsingClientAndPooling_S1() var connectionpooling = "{ \"pooling\": { \"maxSize\": 1, \"queueTimeout\": 2000 , \"maxIdleTime\":1000, \"enabled\": true} }"; var connectionpoolingObject = new { pooling = new { enabled = true, maxSize = 1, queueTimeout = 2000, maxIdleTime = 1000 } }; Client client = MySQLX.GetClient(connStr, connectionpoolingObject); - TestFailureTimeout(client, 9, 11, "Timeout value between 9 and 11 seconds"); + TestFailureTimeout(client, 1, 11, "Timeout value between 9 and 11 seconds"); var connStrUri = "mysqlx://" + sb.UserID + ":" + sb.Password + "@" + serverName + ":" + XPort; client = MySQLX.GetClient(connStrUri, connectionpoolingObject); - TestFailureTimeout(client, 9, 11, "Timeout value between 9 and 11 seconds"); + TestFailureTimeout(client, 1, 11, "Timeout value between 9 and 11 seconds"); var connObj = new { server = serverName, port = XPort, user = sb.UserID, password = sb.Password }; client = MySQLX.GetClient(connObj, connectionpoolingObject); - TestFailureTimeout(client, 9, 11, "Timeout value between 9 and 11 seconds"); + TestFailureTimeout(client, 1, 11, "Timeout value between 9 and 11 seconds"); client = MySQLX.GetClient(connStr, connectionpooling); - TestFailureTimeout(client, 9, 11, "Timeout value between 9 and 11 seconds"); + TestFailureTimeout(client, 1, 11, "Timeout value between 9 and 11 seconds"); client = MySQLX.GetClient(connStrUri, connectionpooling); - TestFailureTimeout(client, 9, 11, "Timeout value between 9 and 11 seconds"); + TestFailureTimeout(client, 1, 11, "Timeout value between 9 and 11 seconds"); client = MySQLX.GetClient(connObj, connectionpooling); - TestFailureTimeout(client, 9, 11, "Timeout value between 9 and 11 seconds"); + TestFailureTimeout(client, 1, 11, "Timeout value between 9 and 11 seconds"); } [Test, Description("failover connection string with one offline host and one online host and disable connect - timeout parameter(set to 0) " + @@ -1646,7 +1646,7 @@ public void TimeoutWithWrongHost() mServer.StartServer(); string connStr = $"server={mServer.Address.ToString()};user={session.Settings.UserID};port={mServer.Port.ToString()};password={ session.Settings.Password};"; - TestConnectStringTimeoutFailureTimeout(connStr, 9, 20, "Timeout value between 9 and 20 seconds"); + TestConnectStringTimeoutFailureTimeout(connStr, 9, 100, "Timeout value between 9 and 20 seconds"); mServer.StopServer(); mServer.DisposeListener();