diff --git a/Orm/Xtensive.Orm.MySql/Sql.Drivers.MySql/DriverFactory.cs b/Orm/Xtensive.Orm.MySql/Sql.Drivers.MySql/DriverFactory.cs
index dd3c5e24c4..8be25beb36 100644
--- a/Orm/Xtensive.Orm.MySql/Sql.Drivers.MySql/DriverFactory.cs
+++ b/Orm/Xtensive.Orm.MySql/Sql.Drivers.MySql/DriverFactory.cs
@@ -1,4 +1,4 @@
-// Copyright (C) 2011-2021 Xtensive LLC.
+// Copyright (C) 2011-2022 Xtensive LLC.
// This code is distributed under MIT license terms.
// See the License.txt file in the project root for more information.
// Created by: Malisa Ncube
@@ -122,7 +122,10 @@ private static SqlDriver CreateDriverInstance(string connectionString, Version v
5 when version.Minor == 1 => new v5_1.Driver(coreServerInfo),
5 when version.Minor == 5 => new v5_5.Driver(coreServerInfo),
5 when version.Minor == 6 => new v5_6.Driver(coreServerInfo),
- _ => new v5_6.Driver(coreServerInfo)
+ 5 when version.Minor == 7 => new v5_7.Driver(coreServerInfo),
+ 6 or 7 => throw new NotSupportedException(string.Format(Strings.ExVersionXOfMySQLIsNotSupported, version)),
+ 8 => new v8_0.Driver(coreServerInfo),
+ _ => new v8_0.Driver(coreServerInfo)
};
}
diff --git a/Orm/Xtensive.Orm.MySql/Sql.Drivers.MySql/Resources/Strings.Designer.cs b/Orm/Xtensive.Orm.MySql/Sql.Drivers.MySql/Resources/Strings.Designer.cs
index ee0df2c30d..82f4da2092 100644
--- a/Orm/Xtensive.Orm.MySql/Sql.Drivers.MySql/Resources/Strings.Designer.cs
+++ b/Orm/Xtensive.Orm.MySql/Sql.Drivers.MySql/Resources/Strings.Designer.cs
@@ -19,7 +19,7 @@ namespace Xtensive.Sql.Drivers.MySql.Resources {
// 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", "15.0.0.0")]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Strings {
@@ -113,5 +113,14 @@ internal static string ExUserNameRequired {
return ResourceManager.GetString("ExUserNameRequired", resourceCulture);
}
}
+
+ ///
+ /// Looks up a localized string similar to Version {0} of MySQL is not supported..
+ ///
+ internal static string ExVersionXOfMySQLIsNotSupported {
+ get {
+ return ResourceManager.GetString("ExVersionXOfMySQLIsNotSupported", resourceCulture);
+ }
+ }
}
}
diff --git a/Orm/Xtensive.Orm.MySql/Sql.Drivers.MySql/Resources/Strings.resx b/Orm/Xtensive.Orm.MySql/Sql.Drivers.MySql/Resources/Strings.resx
index b8e8b5ec35..aec58aa70e 100644
--- a/Orm/Xtensive.Orm.MySql/Sql.Drivers.MySql/Resources/Strings.resx
+++ b/Orm/Xtensive.Orm.MySql/Sql.Drivers.MySql/Resources/Strings.resx
@@ -135,4 +135,7 @@
MySQL Username is required.
+
+ Version {0} of MySQL is not supported.
+
\ No newline at end of file
diff --git a/Orm/Xtensive.Orm.MySql/Sql.Drivers.MySql/v5_0/Extractor.cs b/Orm/Xtensive.Orm.MySql/Sql.Drivers.MySql/v5_0/Extractor.cs
index e908319bd3..4a4a2aa5ae 100644
--- a/Orm/Xtensive.Orm.MySql/Sql.Drivers.MySql/v5_0/Extractor.cs
+++ b/Orm/Xtensive.Orm.MySql/Sql.Drivers.MySql/v5_0/Extractor.cs
@@ -1,4 +1,4 @@
-// Copyright (C) 2011-2020 Xtensive LLC.
+// Copyright (C) 2011-2022 Xtensive LLC.
// This code is distributed under MIT license terms.
// See the License.txt file in the project root for more information.
// Created by: Malisa Ncube
@@ -400,7 +400,7 @@ private static void ReadTableData(DbDataReader reader, Catalog catalog)
var schemaName = reader.GetString(0);
var schema = catalog.Schemas[schemaName];
var tableName = reader.GetString(1);
- schema.CreateTable(tableName);
+ _ = schema.CreateTable(tableName);
}
// ---- ReadTableColumnData
@@ -451,8 +451,8 @@ private void ReadTableColumnData(DbDataReader reader, ref ColumnReaderState true,
+ "N" or "NO" or "DISABLED" or "NONUNIQUE" => false,
+ _ => throw new ArgumentOutOfRangeException(string.Format(Strings.ExInvalidBooleanStringX, value)),
+ };
}
- private static bool IsFullTextIndex(IDataRecord row, int index)
- {
- var value = ReadStringOrNull(row, index);
- if (!string.IsNullOrEmpty(value)) {
- value = value.ToUpperInvariant();
- return value == "FULLTEXT";
- }
- return false;
- }
+ private static bool IsFullTextIndex(IDataRecord row, int index) =>
+ ReadStringOrNull(row, index).Equals("FULLTEXT", StringComparison.OrdinalIgnoreCase);
- private static bool ReadAutoIncrement(IDataRecord row, int index)
- {
- var value = ReadStringOrNull(row, index);
- if (!string.IsNullOrEmpty(value)) {
- value = value.ToUpperInvariant();
- return value == "AUTO_INCREMENT";
- }
- return false;
- }
+ private static bool ReadIfAutoIncrement(IDataRecord row, int index) =>
+ ReadStringOrNull(row, index).Equals("AUTO_INCREMENT", StringComparison.OrdinalIgnoreCase);
- private static long ReadLong(IDataRecord row, int index)
- {
- var value = row.GetDecimal(index);
- return value > long.MaxValue ? long.MaxValue : (long) value;
- }
+ private static int ReadAutoIncrementValue(IDataRecord row, int index) =>
+ row.IsDBNull(index) ? 1 : ReadInt(row, index);
private static int ReadInt(IDataRecord row, int index)
{
diff --git a/Orm/Xtensive.Orm.MySql/Sql.Drivers.MySql/v5_7/Compiler.cs b/Orm/Xtensive.Orm.MySql/Sql.Drivers.MySql/v5_7/Compiler.cs
new file mode 100644
index 0000000000..383b42888b
--- /dev/null
+++ b/Orm/Xtensive.Orm.MySql/Sql.Drivers.MySql/v5_7/Compiler.cs
@@ -0,0 +1,55 @@
+// Copyright (C) 2022 Xtensive LLC.
+// This code is distributed under MIT license terms.
+// See the License.txt file in the project root for more information.
+// Created by: Alexey Kulakov
+// Created: 2022.02.03
+
+using Xtensive.Sql.Compiler;
+using Xtensive.Sql.Dml;
+
+namespace Xtensive.Sql.Drivers.MySql.v5_7
+{
+ internal class Compiler : v5_6.Compiler
+ {
+ ///
+ public override void Visit(SqlQueryExpression node)
+ {
+ using (context.EnterScope(node)) {
+ var wrapLeft = node.Left is SqlSelect sL
+ && (sL.OrderBy.Count > 0 || sL.HasLimit || sL.Lock != SqlLockType.Empty);
+ var wrapRight = node.Left is SqlSelect sR
+ && (sR.OrderBy.Count > 0 || sR.HasLimit || sR.Lock != SqlLockType.Empty);
+
+ AppendTranslatedEntry(node);
+ if (wrapLeft) {
+ _ = context.Output.Append("(");
+ node.Left.AcceptVisitor(this);
+ _ = context.Output.Append(")");
+ }
+ else {
+ node.Left.AcceptVisitor(this);
+ }
+
+ AppendTranslated(node.NodeType);
+ AppendTranslated(node, QueryExpressionSection.All);
+
+ if (wrapRight) {
+ _ = context.Output.Append("(");
+ node.Right.AcceptVisitor(this);
+ _ = context.Output.Append(")");
+ }
+ else {
+ node.Right.AcceptVisitor(this);
+ }
+ AppendTranslatedExit(node);
+ }
+ }
+
+ // Constructors
+
+ public Compiler(SqlDriver driver)
+ : base(driver)
+ {
+ }
+ }
+}
diff --git a/Orm/Xtensive.Orm.MySql/Sql.Drivers.MySql/v5_7/Driver.cs b/Orm/Xtensive.Orm.MySql/Sql.Drivers.MySql/v5_7/Driver.cs
new file mode 100644
index 0000000000..7719d0cafd
--- /dev/null
+++ b/Orm/Xtensive.Orm.MySql/Sql.Drivers.MySql/v5_7/Driver.cs
@@ -0,0 +1,46 @@
+// Copyright (C) 2022 Xtensive LLC.
+// This code is distributed under MIT license terms.
+// See the License.txt file in the project root for more information.
+// Created by: Alexey Kulakov
+// Created: 2022.02.03
+
+using Xtensive.Sql.Compiler;
+using Xtensive.Sql.Info;
+
+namespace Xtensive.Sql.Drivers.MySql.v5_7
+{
+ internal class Driver : MySql.Driver
+ {
+ protected override Sql.TypeMapper CreateTypeMapper()
+ {
+ return new TypeMapper(this);
+ }
+
+ protected override SqlCompiler CreateCompiler()
+ {
+ return new Compiler(this);
+ }
+
+ protected override SqlTranslator CreateTranslator()
+ {
+ return new Translator(this);
+ }
+
+ protected override Model.Extractor CreateExtractor()
+ {
+ return new Extractor(this);
+ }
+
+ protected override Info.ServerInfoProvider CreateServerInfoProvider()
+ {
+ return new ServerInfoProvider(this);
+ }
+
+ // Constructors
+
+ public Driver(CoreServerInfo coreServerInfo)
+ : base(coreServerInfo)
+ {
+ }
+ }
+}
diff --git a/Orm/Xtensive.Orm.MySql/Sql.Drivers.MySql/v5_7/Extractor.cs b/Orm/Xtensive.Orm.MySql/Sql.Drivers.MySql/v5_7/Extractor.cs
new file mode 100644
index 0000000000..512dd5e064
--- /dev/null
+++ b/Orm/Xtensive.Orm.MySql/Sql.Drivers.MySql/v5_7/Extractor.cs
@@ -0,0 +1,18 @@
+// Copyright (C) 2022 Xtensive LLC.
+// This code is distributed under MIT license terms.
+// See the License.txt file in the project root for more information.
+// Created by: Alexey Kulakov
+// Created: 2022.02.03
+
+namespace Xtensive.Sql.Drivers.MySql.v5_7
+{
+ internal class Extractor : v5_6.Extractor
+ {
+ // Constructors
+
+ public Extractor(SqlDriver driver)
+ : base(driver)
+ {
+ }
+ }
+}
\ No newline at end of file
diff --git a/Orm/Xtensive.Orm.MySql/Sql.Drivers.MySql/v5_7/ServerInfoProvider.cs b/Orm/Xtensive.Orm.MySql/Sql.Drivers.MySql/v5_7/ServerInfoProvider.cs
new file mode 100644
index 0000000000..7e1b076b64
--- /dev/null
+++ b/Orm/Xtensive.Orm.MySql/Sql.Drivers.MySql/v5_7/ServerInfoProvider.cs
@@ -0,0 +1,18 @@
+// Copyright (C) 2022 Xtensive LLC.
+// This code is distributed under MIT license terms.
+// See the License.txt file in the project root for more information.
+// Created by: Alexey Kulakov
+// Created: 2022.02.03
+
+namespace Xtensive.Sql.Drivers.MySql.v5_7
+{
+ internal class ServerInfoProvider : v5_6.ServerInfoProvider
+ {
+ // Constructors
+
+ public ServerInfoProvider(SqlDriver driver)
+ : base(driver)
+ {
+ }
+ }
+}
\ No newline at end of file
diff --git a/Orm/Xtensive.Orm.MySql/Sql.Drivers.MySql/v5_7/Translator.cs b/Orm/Xtensive.Orm.MySql/Sql.Drivers.MySql/v5_7/Translator.cs
new file mode 100644
index 0000000000..9ea62b6741
--- /dev/null
+++ b/Orm/Xtensive.Orm.MySql/Sql.Drivers.MySql/v5_7/Translator.cs
@@ -0,0 +1,38 @@
+// Copyright (C) 2022 Xtensive LLC.
+// This code is distributed under MIT license terms.
+// See the License.txt file in the project root for more information.
+// Created by: Alexey Kulakov
+// Created: 2022.02.03
+
+using System;
+using Xtensive.Sql.Compiler;
+using Xtensive.Sql.Dml;
+
+namespace Xtensive.Sql.Drivers.MySql.v5_7
+{
+ internal class Translator : v5_6.Translator
+ {
+ ///
+ public override void Translate(SqlCompilerContext context, SqlCast node, NodeSection section)
+ {
+ if (node.Type.Type == SqlType.DateTime) {
+ var output = context.Output;
+ _ = section switch {
+ NodeSection.Entry => output.AppendOpeningPunctuation("CAST("),
+ NodeSection.Exit => output.Append("AS ")
+ .Append(Translate(node.Type))
+ .AppendClosingPunctuation("(6))"),
+ _ => throw new ArgumentOutOfRangeException(nameof(section)),
+ };
+ }
+ base.Translate(context, node, section);
+ }
+
+ // Constructors
+
+ public Translator(SqlDriver driver)
+ : base(driver)
+ {
+ }
+ }
+}
\ No newline at end of file
diff --git a/Orm/Xtensive.Orm.MySql/Sql.Drivers.MySql/v5_7/TypeMapper.cs b/Orm/Xtensive.Orm.MySql/Sql.Drivers.MySql/v5_7/TypeMapper.cs
new file mode 100644
index 0000000000..2a0d6f655a
--- /dev/null
+++ b/Orm/Xtensive.Orm.MySql/Sql.Drivers.MySql/v5_7/TypeMapper.cs
@@ -0,0 +1,18 @@
+// Copyright (C) 2022 Xtensive LLC.
+// This code is distributed under MIT license terms.
+// See the License.txt file in the project root for more information.
+// Created by: Alexey Kulakov
+// Created: 2022.02.03
+
+namespace Xtensive.Sql.Drivers.MySql.v5_7
+{
+ internal class TypeMapper : v5_6.TypeMapper
+ {
+ // Constructors
+
+ public TypeMapper(SqlDriver driver)
+ : base(driver)
+ {
+ }
+ }
+}
diff --git a/Orm/Xtensive.Orm.MySql/Sql.Drivers.MySql/v8_0/Compiler.cs b/Orm/Xtensive.Orm.MySql/Sql.Drivers.MySql/v8_0/Compiler.cs
new file mode 100644
index 0000000000..d67a0840b1
--- /dev/null
+++ b/Orm/Xtensive.Orm.MySql/Sql.Drivers.MySql/v8_0/Compiler.cs
@@ -0,0 +1,19 @@
+// Copyright (C) 2022 Xtensive LLC.
+// This code is distributed under MIT license terms.
+// See the License.txt file in the project root for more information.
+// Created by: Alexey Kulakov
+// Created: 2022.02.03
+
+namespace Xtensive.Sql.Drivers.MySql.v8_0
+{
+ internal class Compiler : v5_7.Compiler
+ {
+
+ // Constructors
+
+ public Compiler(SqlDriver driver)
+ : base(driver)
+ {
+ }
+ }
+}
diff --git a/Orm/Xtensive.Orm.MySql/Sql.Drivers.MySql/v8_0/Driver.cs b/Orm/Xtensive.Orm.MySql/Sql.Drivers.MySql/v8_0/Driver.cs
new file mode 100644
index 0000000000..4e508f6309
--- /dev/null
+++ b/Orm/Xtensive.Orm.MySql/Sql.Drivers.MySql/v8_0/Driver.cs
@@ -0,0 +1,46 @@
+// Copyright (C) 2022 Xtensive LLC.
+// This code is distributed under MIT license terms.
+// See the License.txt file in the project root for more information.
+// Created by: Alexey Kulakov
+// Created: 2022.02.03
+
+using Xtensive.Sql.Compiler;
+using Xtensive.Sql.Info;
+
+namespace Xtensive.Sql.Drivers.MySql.v8_0
+{
+ internal class Driver : MySql.Driver
+ {
+ protected override Sql.TypeMapper CreateTypeMapper()
+ {
+ return new TypeMapper(this);
+ }
+
+ protected override SqlCompiler CreateCompiler()
+ {
+ return new Compiler(this);
+ }
+
+ protected override SqlTranslator CreateTranslator()
+ {
+ return new Translator(this);
+ }
+
+ protected override Model.Extractor CreateExtractor()
+ {
+ return new Extractor(this);
+ }
+
+ protected override Info.ServerInfoProvider CreateServerInfoProvider()
+ {
+ return new ServerInfoProvider(this);
+ }
+
+ // Constructors
+
+ public Driver(CoreServerInfo coreServerInfo)
+ : base(coreServerInfo)
+ {
+ }
+ }
+}
diff --git a/Orm/Xtensive.Orm.MySql/Sql.Drivers.MySql/v8_0/Extractor.cs b/Orm/Xtensive.Orm.MySql/Sql.Drivers.MySql/v8_0/Extractor.cs
new file mode 100644
index 0000000000..9c34206d51
--- /dev/null
+++ b/Orm/Xtensive.Orm.MySql/Sql.Drivers.MySql/v8_0/Extractor.cs
@@ -0,0 +1,18 @@
+// Copyright (C) 2022 Xtensive LLC.
+// This code is distributed under MIT license terms.
+// See the License.txt file in the project root for more information.
+// Created by: Alexey Kulakov
+// Created: 2022.02.03
+
+namespace Xtensive.Sql.Drivers.MySql.v8_0
+{
+ internal class Extractor : v5_7.Extractor
+ {
+ // Constructors
+
+ public Extractor(SqlDriver driver)
+ : base(driver)
+ {
+ }
+ }
+}
\ No newline at end of file
diff --git a/Orm/Xtensive.Orm.MySql/Sql.Drivers.MySql/v8_0/ServerInfoProvider.cs b/Orm/Xtensive.Orm.MySql/Sql.Drivers.MySql/v8_0/ServerInfoProvider.cs
new file mode 100644
index 0000000000..ddc9d1f1ab
--- /dev/null
+++ b/Orm/Xtensive.Orm.MySql/Sql.Drivers.MySql/v8_0/ServerInfoProvider.cs
@@ -0,0 +1,18 @@
+// Copyright (C) 2022 Xtensive LLC.
+// This code is distributed under MIT license terms.
+// See the License.txt file in the project root for more information.
+// Created by: Alexey Kulakov
+// Created: 2022.02.03
+
+namespace Xtensive.Sql.Drivers.MySql.v8_0
+{
+ internal class ServerInfoProvider : v5_7.ServerInfoProvider
+ {
+ // Constructors
+
+ public ServerInfoProvider(SqlDriver driver)
+ : base(driver)
+ {
+ }
+ }
+}
\ No newline at end of file
diff --git a/Orm/Xtensive.Orm.MySql/Sql.Drivers.MySql/v8_0/Translator.cs b/Orm/Xtensive.Orm.MySql/Sql.Drivers.MySql/v8_0/Translator.cs
new file mode 100644
index 0000000000..e69cd1edbc
--- /dev/null
+++ b/Orm/Xtensive.Orm.MySql/Sql.Drivers.MySql/v8_0/Translator.cs
@@ -0,0 +1,41 @@
+// Copyright (C) 2022 Xtensive LLC.
+// This code is distributed under MIT license terms.
+// See the License.txt file in the project root for more information.
+// Created by: Alexey Kulakov
+// Created: 2022.02.03
+
+using System;
+using Xtensive.Sql.Compiler;
+using Xtensive.Sql.Dml;
+
+namespace Xtensive.Sql.Drivers.MySql.v8_0
+{
+ internal class Translator : v5_7.Translator
+ {
+ ///
+ public override void Translate(IOutput output, SqlLockType lockType)
+ {
+ var forShare = lockType.Supports(SqlLockType.Shared);
+ var forUpdate = lockType.SupportsAny(SqlLockType.Update | SqlLockType.Exclusive);
+
+ if (!forShare && !forUpdate) {
+ throw new NotSupportedException($"Lock '{lockType.ToString(true)}' is not supported.");
+ }
+
+ _ = output
+ .Append(forShare ? "FOR SHARE" : "FOR UPDATE")
+ .Append(lockType.Supports(SqlLockType.SkipLocked)
+ ? " SKIP LOCKED"
+ : lockType.Supports(SqlLockType.ThrowIfLocked)
+ ? " NOWAIT"
+ : string.Empty);
+ }
+
+ // Constructors
+
+ public Translator(SqlDriver driver)
+ : base(driver)
+ {
+ }
+ }
+}
\ No newline at end of file
diff --git a/Orm/Xtensive.Orm.MySql/Sql.Drivers.MySql/v8_0/TypeMapper.cs b/Orm/Xtensive.Orm.MySql/Sql.Drivers.MySql/v8_0/TypeMapper.cs
new file mode 100644
index 0000000000..ce4bb1815a
--- /dev/null
+++ b/Orm/Xtensive.Orm.MySql/Sql.Drivers.MySql/v8_0/TypeMapper.cs
@@ -0,0 +1,18 @@
+// Copyright (C) 2022 Xtensive LLC.
+// This code is distributed under MIT license terms.
+// See the License.txt file in the project root for more information.
+// Created by: Alexey Kulakov
+// Created: 2022.02.03
+
+namespace Xtensive.Sql.Drivers.MySql.v8_0
+{
+ internal class TypeMapper : v5_7.TypeMapper
+ {
+ // Constructors
+
+ public TypeMapper(SqlDriver driver)
+ : base(driver)
+ {
+ }
+ }
+}
diff --git a/Orm/Xtensive.Orm.MySql/Xtensive.Orm.MySql.csproj b/Orm/Xtensive.Orm.MySql/Xtensive.Orm.MySql.csproj
index d2b6fc6ca7..68c6b51e0c 100644
--- a/Orm/Xtensive.Orm.MySql/Xtensive.Orm.MySql.csproj
+++ b/Orm/Xtensive.Orm.MySql/Xtensive.Orm.MySql.csproj
@@ -1,4 +1,4 @@
-
+
true
$(OutputPath)$(TargetFramework)\$(AssemblyName).xml
@@ -23,15 +23,21 @@
-
- True
- True
- Strings.resx
-
+
+ ResXFileCodeGenerator
+ Strings.Designer.cs
+
+
+
+ True
+ True
+ Strings.resx
+
+
diff --git a/Orm/Xtensive.Orm.Tests.Sql/MySQL/ChinookTest.cs b/Orm/Xtensive.Orm.Tests.Sql/MySQL/ChinookTest.cs
index 1695460888..41ee3c306b 100644
--- a/Orm/Xtensive.Orm.Tests.Sql/MySQL/ChinookTest.cs
+++ b/Orm/Xtensive.Orm.Tests.Sql/MySQL/ChinookTest.cs
@@ -957,5 +957,262 @@ public void Test052()
Assert.IsTrue(CompareExecuteNonQuery(nativeSql, select));
}
+
+ [Test]
+ public void Test053()
+ {
+ Require.ProviderVersionAtLeast(new Version(8, 0));
+
+ var nativeSql =
+ "SELECT `a`.`ArtistId` FROM ((SELECT ArtistId FROM dotest.album where AlbumId >= 0 and AlbumId < 50 LIMIT 10)"
+ + " UNION (SELECT ArtistId FROM dotest.album where AlbumId >= 50 and AlbumId < 100 LIMIT 10)"
+ + " UNION (SELECT ArtistId FROM dotest.album where AlbumId >= 100 and AlbumId < 200 LIMIT 10)"
+ + " UNION (SELECT ArtistId FROM dotest.album where AlbumId >= 20 and AlbumId < 300 LIMIT 10)) `a`;";
+
+ var albums = SqlDml.TableRef(schema.Tables["album"]);
+
+ var s1 = SqlDml.Select(albums);
+ s1.Columns.Add(albums.Columns["ArtistId"]);
+ s1.Where = albums.Columns["AlbumId"] >= 0 && albums.Columns["AlbumId"] < 50;
+ s1.Limit = 10;
+
+ albums = SqlDml.TableRef(schema.Tables["album"]);
+ var s2 = SqlDml.Select(albums);
+ s2.Columns.Add(albums.Columns["ArtistId"]);
+ s2.Where = albums.Columns["AlbumId"] >= 50 && albums.Columns["AlbumId"] < 100;
+ s2.Limit = 10;
+
+ albums = SqlDml.TableRef(schema.Tables["album"]);
+ var s3 = SqlDml.Select(albums);
+ s3.Columns.Add(albums.Columns["ArtistId"]);
+ s3.Where = albums.Columns["AlbumId"] >= 100 && albums.Columns["AlbumId"] < 200;
+ s3.Limit = 10;
+
+ albums = SqlDml.TableRef(schema.Tables["album"]);
+ var s4 = SqlDml.Select(albums);
+ s4.Columns.Add(albums.Columns["ArtistId"]);
+ s4.Where = albums.Columns["AlbumId"] >= 200 && albums.Columns["AlbumId"] < 300;
+ s4.Limit = 10;
+
+ var qr = SqlDml.QueryRef(s1.Union(s2).Union(s3.Union(s4)), "a");
+ var select = SqlDml.Select(qr);
+ select.Columns.Add(qr["ArtistId"]);
+
+ Assert.IsTrue(CompareExecuteNonQuery(nativeSql, select));
+ }
+
+ [Test]
+ public void Test054()
+ {
+ Require.ProviderVersionAtLeast(new Version(8, 0));
+
+ var nativeSql =
+ "SELECT `a`.`ArtistId` FROM ((SELECT ArtistId FROM dotest.album where AlbumId >= 0 and AlbumId < 50 LIMIT 10 OFFSET 10)"
+ + " UNION (SELECT ArtistId FROM dotest.album where AlbumId >= 50 and AlbumId < 100 LIMIT 10 OFFSET 10)"
+ + " UNION (SELECT ArtistId FROM dotest.album where AlbumId >= 100 and AlbumId < 200 LIMIT 10 OFFSET 10)"
+ + " UNION (SELECT ArtistId FROM dotest.album where AlbumId >= 20 and AlbumId < 300 LIMIT 10 OFFSET 10)) `a`;";
+
+ var albums = SqlDml.TableRef(schema.Tables["album"]);
+
+ var s1 = SqlDml.Select(albums);
+ s1.Columns.Add(albums.Columns["ArtistId"]);
+ s1.Where = albums.Columns["AlbumId"] >= 0 && albums.Columns["AlbumId"] < 50;
+ s1.Limit = 10;
+ s1.Offset = 10;
+
+ albums = SqlDml.TableRef(schema.Tables["album"]);
+ var s2 = SqlDml.Select(albums);
+ s2.Columns.Add(albums.Columns["ArtistId"]);
+ s2.Where = albums.Columns["AlbumId"] >= 50 && albums.Columns["AlbumId"] < 100;
+ s2.Limit = 10;
+ s2.Offset = 10;
+
+ albums = SqlDml.TableRef(schema.Tables["album"]);
+ var s3 = SqlDml.Select(albums);
+ s3.Columns.Add(albums.Columns["ArtistId"]);
+ s3.Where = albums.Columns["AlbumId"] >= 100 && albums.Columns["AlbumId"] < 200;
+ s3.Limit = 10;
+ s3.Offset = 10;
+
+ albums = SqlDml.TableRef(schema.Tables["album"]);
+ var s4 = SqlDml.Select(albums);
+ s4.Columns.Add(albums.Columns["ArtistId"]);
+ s4.Where = albums.Columns["AlbumId"] >= 200 && albums.Columns["AlbumId"] < 300;
+ s4.Limit = 10;
+ s4.Offset = 10;
+
+ var qr = SqlDml.QueryRef(s1.Union(s2).Union(s3.Union(s4)), "a");
+ var select = SqlDml.Select(qr);
+ select.Columns.Add(qr["ArtistId"]);
+
+ Assert.IsTrue(CompareExecuteNonQuery(nativeSql, select));
+ }
+
+ [Test]
+ public void Test055()
+ {
+ Require.ProviderVersionAtLeast(new Version(8, 0));
+
+ var nativeSql =
+ "SELECT `a`.`ArtistId` FROM ((SELECT ArtistId FROM dotest.album where AlbumId >= 0 and AlbumId < 50 FOR SHARE)"
+ + " UNION (SELECT ArtistId FROM dotest.album where AlbumId >= 50 and AlbumId < 100 FOR SHARE)"
+ + " UNION (SELECT ArtistId FROM dotest.album where AlbumId >= 100 and AlbumId < 200 FOR SHARE)"
+ + " UNION (SELECT ArtistId FROM dotest.album where AlbumId >= 20 and AlbumId < 300 FOR SHARE)) `a`;";
+
+ var albums = SqlDml.TableRef(schema.Tables["album"]);
+
+ var s1 = SqlDml.Select(albums);
+ s1.Columns.Add(albums.Columns["ArtistId"]);
+ s1.Where = albums.Columns["AlbumId"] >= 0 && albums.Columns["AlbumId"] < 50;
+ s1.Lock = SqlLockType.Shared;
+
+ albums = SqlDml.TableRef(schema.Tables["album"]);
+ var s2 = SqlDml.Select(albums);
+ s2.Columns.Add(albums.Columns["ArtistId"]);
+ s2.Where = albums.Columns["AlbumId"] >= 50 && albums.Columns["AlbumId"] < 100;
+ s2.Lock = SqlLockType.Shared;
+
+ albums = SqlDml.TableRef(schema.Tables["album"]);
+ var s3 = SqlDml.Select(albums);
+ s3.Columns.Add(albums.Columns["ArtistId"]);
+ s3.Where = albums.Columns["AlbumId"] >= 100 && albums.Columns["AlbumId"] < 200;
+ s3.Lock = SqlLockType.Shared;
+
+ albums = SqlDml.TableRef(schema.Tables["album"]);
+ var s4 = SqlDml.Select(albums);
+ s4.Columns.Add(albums.Columns["ArtistId"]);
+ s4.Where = albums.Columns["AlbumId"] >= 200 && albums.Columns["AlbumId"] < 300;
+ s4.Lock = SqlLockType.Shared;
+
+ var qr = SqlDml.QueryRef(s1.Union(s2).Union(s3.Union(s4)), "a");
+ var select = SqlDml.Select(qr);
+ select.Columns.Add(qr["ArtistId"]);
+
+ Assert.IsTrue(CompareExecuteNonQuery(nativeSql, select));
+ }
+
+ [Test]
+ public void Test056()
+ {
+ Require.ProviderVersionAtLeast(new Version(8, 0));
+
+ var nativeSql =
+ "SELECT `a`.`ArtistId` FROM ((SELECT ArtistId FROM dotest.album where AlbumId >= 0 and AlbumId < 50 ORDER BY ArtistId)"
+ + " UNION (SELECT ArtistId FROM dotest.album where AlbumId >= 50 and AlbumId < 100 ORDER BY ArtistId)"
+ + " UNION (SELECT ArtistId FROM dotest.album where AlbumId >= 100 and AlbumId < 200 ORDER BY ArtistId)"
+ + " UNION (SELECT ArtistId FROM dotest.album where AlbumId >= 20 and AlbumId < 300 ORDER BY ArtistId)) `a`;";
+
+ var albums = SqlDml.TableRef(schema.Tables["album"]);
+
+ var s1 = SqlDml.Select(albums);
+ s1.Columns.Add(albums.Columns["ArtistId"]);
+ s1.Where = albums.Columns["AlbumId"] >= 0 && albums.Columns["AlbumId"] < 50;
+ s1.OrderBy.Add(albums.Columns["ArtistId"]);
+
+ albums = SqlDml.TableRef(schema.Tables["album"]);
+ var s2 = SqlDml.Select(albums);
+ s2.Columns.Add(albums.Columns["ArtistId"]);
+ s2.Where = albums.Columns["AlbumId"] >= 50 && albums.Columns["AlbumId"] < 100;
+ s2.OrderBy.Add(albums.Columns["ArtistId"]);
+
+ albums = SqlDml.TableRef(schema.Tables["album"]);
+ var s3 = SqlDml.Select(albums);
+ s3.Columns.Add(albums.Columns["ArtistId"]);
+ s3.Where = albums.Columns["AlbumId"] >= 100 && albums.Columns["AlbumId"] < 200;
+ s3.OrderBy.Add(albums.Columns["ArtistId"]);
+
+ albums = SqlDml.TableRef(schema.Tables["album"]);
+ var s4 = SqlDml.Select(albums);
+ s4.Columns.Add(albums.Columns["ArtistId"]);
+ s4.Where = albums.Columns["AlbumId"] >= 200 && albums.Columns["AlbumId"] < 300;
+ s4.OrderBy.Add(albums.Columns["ArtistId"]);
+
+ var qr = SqlDml.QueryRef(s1.Union(s2).Union(s3.Union(s4)), "a");
+ var select = SqlDml.Select(qr);
+ select.Columns.Add(qr["ArtistId"]);
+
+ Assert.IsTrue(CompareExecuteNonQuery(nativeSql, select));
+ }
+
+
+ [Test]
+ public void Test057()
+ {
+ Require.ProviderVersionAtLeast(new Version(8, 0));
+
+ var nativeSql =
+ "SELECT `a`.`ArtistId` FROM (SELECT ArtistId FROM dotest.album where AlbumId >= 0 and AlbumId < 50 GROUP BY ArtistId"
+ + " UNION SELECT ArtistId FROM dotest.album where AlbumId >= 50 and AlbumId < 100 GROUP BY ArtistId"
+ + " UNION SELECT ArtistId FROM dotest.album where AlbumId >= 100 and AlbumId < 200 GROUP BY ArtistId"
+ + " UNION SELECT ArtistId FROM dotest.album where AlbumId >= 20 and AlbumId < 300 GROUP BY ArtistId) `a`;";
+
+ var albums = SqlDml.TableRef(schema.Tables["album"]);
+
+ var s1 = SqlDml.Select(albums);
+ s1.Columns.Add(albums.Columns["ArtistId"]);
+ s1.Where = albums.Columns["AlbumId"] >= 0 && albums.Columns["AlbumId"] < 50;
+ s1.GroupBy.Add(albums.Columns["ArtistId"]);
+
+ albums = SqlDml.TableRef(schema.Tables["album"]);
+ var s2 = SqlDml.Select(albums);
+ s2.Columns.Add(albums.Columns["ArtistId"]);
+ s2.Where = albums.Columns["AlbumId"] >= 50 && albums.Columns["AlbumId"] < 100;
+ s2.GroupBy.Add(albums.Columns["ArtistId"]);
+
+ albums = SqlDml.TableRef(schema.Tables["album"]);
+ var s3 = SqlDml.Select(albums);
+ s3.Columns.Add(albums.Columns["ArtistId"]);
+ s3.Where = albums.Columns["AlbumId"] >= 100 && albums.Columns["AlbumId"] < 200;
+ s3.GroupBy.Add(albums.Columns["ArtistId"]);
+
+ albums = SqlDml.TableRef(schema.Tables["album"]);
+ var s4 = SqlDml.Select(albums);
+ s4.Columns.Add(albums.Columns["ArtistId"]);
+ s4.Where = albums.Columns["AlbumId"] >= 200 && albums.Columns["AlbumId"] < 300;
+ s4.GroupBy.Add(albums.Columns["ArtistId"]);
+
+ var qr = SqlDml.QueryRef(s1.Union(s2).Union(s3.Union(s4)), "a");
+ var select = SqlDml.Select(qr);
+ select.Columns.Add(qr["ArtistId"]);
+
+ Assert.IsTrue(CompareExecuteNonQuery(nativeSql, select));
+ }
+
+ [Test]
+ public void Test058()
+ {
+ var nativeSql =
+ "SELECT `a`.`AlbumId` FROM (SELECT AlbumId FROM dotest.album where AlbumId >= 0 and AlbumId < 50"
+ + " UNION SELECT AlbumId FROM dotest.album where AlbumId >= 50 and AlbumId< 100"
+ + " UNION SELECT AlbumId FROM dotest.album where AlbumId >= 100 and AlbumId< 200"
+ + " UNION SELECT AlbumId FROM dotest.album where AlbumId >= 20 and AlbumId< 300) `a`;";
+
+ var albums = SqlDml.TableRef(schema.Tables["album"]);
+
+ var s1 = SqlDml.Select(albums);
+ s1.Columns.Add(albums.Columns["AlbumId"]);
+ s1.Where = albums.Columns["AlbumId"] >= 0 && albums.Columns["AlbumId"] < 50;
+
+ albums = SqlDml.TableRef(schema.Tables["album"]);
+ var s2 = SqlDml.Select(albums);
+ s2.Columns.Add(albums.Columns["AlbumId"]);
+ s2.Where = albums.Columns["AlbumId"] >= 50 && albums.Columns["AlbumId"] < 100;
+
+ albums = SqlDml.TableRef(schema.Tables["album"]);
+ var s3 = SqlDml.Select(albums);
+ s3.Columns.Add(albums.Columns["AlbumId"]);
+ s3.Where = albums.Columns["AlbumId"] >= 100 && albums.Columns["AlbumId"] < 200;
+
+ albums = SqlDml.TableRef(schema.Tables["album"]);
+ var s4 = SqlDml.Select(albums);
+ s4.Columns.Add(albums.Columns["AlbumId"]);
+ s4.Where = albums.Columns["AlbumId"] >= 200 && albums.Columns["AlbumId"] < 300;
+
+ var qr = SqlDml.QueryRef(s1.Union(s2).Union(s3.Union(s4)), "a");
+ var select = SqlDml.Select(qr);
+ select.Columns.Add(qr["AlbumId"]);
+
+ Assert.IsTrue(CompareExecuteNonQuery(nativeSql, select));
+ }
}
}
diff --git a/Orm/Xtensive.Orm.Tests/Linq/TagTest.cs b/Orm/Xtensive.Orm.Tests/Linq/TagTest.cs
index 012756c3ae..e85294b920 100644
--- a/Orm/Xtensive.Orm.Tests/Linq/TagTest.cs
+++ b/Orm/Xtensive.Orm.Tests/Linq/TagTest.cs
@@ -678,8 +678,9 @@ void SqlCapturer(object sender, DbCommandEventArgs args)
[Test]
public void SessionTagSingle()
{
- var allCommands = new List();
+ Require.ProviderIsNot(StorageProvider.MySql);
+ var allCommands = new List();
var id = 0L;
using (var populateSession = Domain.OpenSession())
@@ -751,6 +752,8 @@ void SqlCapturer(object sender, DbCommandEventArgs args)
[Test]
public void SessionTagSingleOrDefault()
{
+ Require.ProviderIsNot(StorageProvider.MySql);
+
var allCommands = new List();
var id = 0L;
@@ -822,6 +825,7 @@ void SqlCapturer(object sender, DbCommandEventArgs args)
[Test]
public void SessionTagPrefetchEntity()
{
+ Require.ProviderIsNot(StorageProvider.MySql);
var allCommands = new List();
using (var populateSession = Domain.OpenSession())
diff --git a/Orm/Xtensive.Orm/Sql/Dml/Extensions.cs b/Orm/Xtensive.Orm/Sql/Dml/Extensions.cs
index f08ceb74d5..be14016706 100644
--- a/Orm/Xtensive.Orm/Sql/Dml/Extensions.cs
+++ b/Orm/Xtensive.Orm/Sql/Dml/Extensions.cs
@@ -1,6 +1,6 @@
-// Copyright (C) 2003-2010 Xtensive LLC.
-// All rights reserved.
-// For conditions of distribution and use, see license.
+// Copyright (C) 2009-2022 Xtensive LLC.
+// This code is distributed under MIT license terms.
+// See the License.txt file in the project root for more information.
// Created by: Denis Krjuchkov
// Created: 2009.08.24
@@ -28,11 +28,34 @@ public static bool IsNullReference(this SqlExpression expression)
return ReferenceEquals(expression, null);
}
+ ///
+ /// Checks whether contains all flags of given .
+ ///
+ /// All flags.
+ /// Flags to check existance.
+ ///
+ /// if contains all flags of ,
+ /// otherwise, .
+ ///
public static bool Supports(this SqlLockType available, SqlLockType required)
{
return (available & required)==required;
}
+ ///
+ /// Checks whether contains any flag of given .
+ ///
+ /// All flags.
+ /// Flags to check existance.
+ ///
+ /// if contains any flag of ,
+ /// otherwise, .
+ ///
+ public static bool SupportsAny(this SqlLockType available, SqlLockType required)
+ {
+ return (available | required) == required;
+ }
+
public static string ToString(this SqlLockType lockType, bool humanReadable)
{
if (!humanReadable)
diff --git a/ReadMe.md b/ReadMe.md
index 5d50d06e25..51a3c362c9 100644
--- a/ReadMe.md
+++ b/ReadMe.md
@@ -7,7 +7,7 @@ Supported databases:
- MS Azure SQL Database
- Oracle 10g, 11g
- PostgreSQL 8.3, 8.4, 9.0, 9.1, 9.2, 10, 11
-- MySQL 5.5, 5.6
+- MySQL 5.5, 5.6, 5.7, 8.0
- Firebird 2.5
- Sqlite 3