diff --git a/Orm/Xtensive.Orm.Tests/Linq/WhereByEnumTest.cs b/Orm/Xtensive.Orm.Tests/Linq/WhereByEnumTest.cs new file mode 100644 index 0000000000..aaa8e72cf2 --- /dev/null +++ b/Orm/Xtensive.Orm.Tests/Linq/WhereByEnumTest.cs @@ -0,0 +1,737 @@ +// Copyright (C) 2021 Xtensive LLC. +// This code is distributed under MIT license terms. +// See the License.txt file in the project root for more information. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using NUnit.Framework; +using Xtensive.Core; +using Xtensive.Orm.Configuration; +using Xtensive.Orm.Services; +using Xtensive.Orm.Tests.Linq.WhereByEnumTestModel; + +namespace Xtensive.Orm.Tests.Linq.WhereByEnumTestModel +{ + public enum ByteEnum : byte + { + Zero = 0, + One = 1, + Two = 2, + Max = byte.MaxValue + } + + public enum SByteEnum : sbyte + { + Zero = 0, + One = 1, + Two = 2, + Max = sbyte.MaxValue + } + + public enum ShortEnum : short + { + Zero = 0, + One = 1, + Two = 2, + Max = short.MaxValue + } + + public enum UShortEnum : ushort + { + Zero = 0, + One = 1, + Two = 2, + Max = ushort.MaxValue + } + + public enum IntEnum : int + { + Zero = 0, + One = 1, + Two = 2, + Max = int.MaxValue + } + + public enum UIntEnum : uint + { + Zero = 0, + One = 1, + Two = 2, + Max = uint.MaxValue + } + + public enum LongEnum : long + { + Zero = 0, + One = 1, + Two = 2, + Max = long.MaxValue + } + + public enum ULongEnum : ulong + { + Zero = 0, + One = 1, + Two = 2, + Max = ulong.MaxValue + } + + [HierarchyRoot] + public class EnumContainer : Entity + { + public const string Zero = "Zero"; + public const string One = "One"; + public const string Two = "Two"; + public const string Max = "Max"; + + [Field, Key] + public int Id { get; private set; } + + [Field] + public ByteEnum ByteEnumField { get; set; } + + [Field] + public SByteEnum SByteEnumField { get; set; } + + [Field] + public ShortEnum ShortEnumField { get; set; } + + [Field] + public UShortEnum UShortEnumField { get; set; } + + [Field] + public IntEnum IntEnumField { get; set; } + + [Field] + public UIntEnum UIntEnumField { get; set; } + + [Field] + public LongEnum LongEnumField { get; set; } + + [Field] + public ULongEnum ULongEnumField { get; set; } + + [Field] + public ByteEnum? NByteEnumField { get; set; } + + [Field] + public SByteEnum? NSByteEnumField { get; set; } + + [Field] + public ShortEnum? NShortEnumField { get; set; } + + [Field] + public UShortEnum? NUShortEnumField { get; set; } + + [Field] + public IntEnum? NIntEnumField { get; set; } + + [Field] + public UIntEnum? NUIntEnumField { get; set; } + + [Field] + public LongEnum? NLongEnumField { get; set; } + + [Field] + public ULongEnum? NULongEnumField { get; set; } + + public EnumContainer(Session session, string enumValue) + : base(session) + { + ByteEnumField = (ByteEnum) Enum.Parse(typeof(ByteEnum), enumValue); + SByteEnumField = (SByteEnum) Enum.Parse(typeof(SByteEnum), enumValue); + ShortEnumField = (ShortEnum) Enum.Parse(typeof(ShortEnum), enumValue); + UShortEnumField = (UShortEnum) Enum.Parse(typeof(UShortEnum), enumValue); + IntEnumField = (IntEnum) Enum.Parse(typeof(IntEnum), enumValue); + UIntEnumField = (UIntEnum) Enum.Parse(typeof(UIntEnum), enumValue); + LongEnumField = (LongEnum) Enum.Parse(typeof(LongEnum), enumValue); + ULongEnumField = (ULongEnum) Enum.Parse(typeof(ULongEnum), enumValue); + + NByteEnumField = (ByteEnum) Enum.Parse(typeof(ByteEnum), enumValue); + NSByteEnumField = (SByteEnum) Enum.Parse(typeof(SByteEnum), enumValue); + NShortEnumField = (ShortEnum) Enum.Parse(typeof(ShortEnum), enumValue); + NUShortEnumField = (UShortEnum) Enum.Parse(typeof(UShortEnum), enumValue); + NIntEnumField = (IntEnum) Enum.Parse(typeof(IntEnum), enumValue); + NUIntEnumField = (UIntEnum) Enum.Parse(typeof(UIntEnum), enumValue); + NLongEnumField = (LongEnum) Enum.Parse(typeof(LongEnum), enumValue); + NULongEnumField = (ULongEnum) Enum.Parse(typeof(ULongEnum), enumValue); + } + } +} + +namespace Xtensive.Orm.Tests.Linq +{ + public class WhereByEnumTest : AutoBuildTest + { + private Session sharedSession; + private string castSign; + + public override void TestFixtureSetUp() + { + base.TestFixtureSetUp(); + CreateSessionAndTransaction(); + sharedSession = Session.Current; + castSign = StorageProviderInfo.Instance.CheckProviderIs(StorageProvider.PostgreSql) + ? "::" + : "CAST"; + } + + public override void TestFixtureTearDown() + { + sharedSession = null; + base.TestFixtureTearDown(); + } + + protected override DomainConfiguration BuildConfiguration() + { + var config = base.BuildConfiguration(); + config.Types.Register(typeof(EnumContainer)); + config.UpgradeMode = DomainUpgradeMode.Recreate; + return config; + } + + protected override void PopulateData() + { + using (var session = Domain.OpenSession()) + using (var tx = session.OpenTransaction()) { + _ = new EnumContainer(session, EnumContainer.Zero); + _ = new EnumContainer(session, EnumContainer.One); + _ = new EnumContainer(session, EnumContainer.Two); + _ = new EnumContainer(session, EnumContainer.Max); + tx.Complete(); + } + } + + [Test] + public void ByteTest() + { + var queryFormatter = sharedSession.Services.Demand(); + + var query = sharedSession.Query.All().Where(e => e.ByteEnumField != ByteEnum.Zero); + var queryString = queryFormatter.ToSqlString(query); + Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); + Assert.That(query.Count(), Is.EqualTo(3)); + + query = sharedSession.Query.All().Where(e => e.ByteEnumField > ByteEnum.One); + queryString = queryFormatter.ToSqlString(query); + Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); + Assert.That(query.Count(), Is.EqualTo(2)); + + query = sharedSession.Query.All().Where(e => e.ByteEnumField >= ByteEnum.One); + queryString = queryFormatter.ToSqlString(query); + Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); + Assert.That(query.Count(), Is.EqualTo(3)); + + query = sharedSession.Query.All().Where(e => e.ByteEnumField < ByteEnum.Two); + queryString = queryFormatter.ToSqlString(query); + Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); + Assert.That(query.Count(), Is.EqualTo(2)); + + query = sharedSession.Query.All().Where(e => e.ByteEnumField <= ByteEnum.Two); + queryString = queryFormatter.ToSqlString(query); + Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); + Assert.That(query.Count(), Is.EqualTo(3)); + + query = sharedSession.Query.All().Where(e => e.ByteEnumField == ByteEnum.Max); + queryString = queryFormatter.ToSqlString(query); + Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); + Assert.That(query.Count(), Is.EqualTo(1)); + + + query = sharedSession.Query.All().Where(e => e.NByteEnumField != ByteEnum.Zero); + queryString = queryFormatter.ToSqlString(query); + Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); + Assert.That(query.Count(), Is.EqualTo(3)); + + query = sharedSession.Query.All().Where(e => e.NByteEnumField > ByteEnum.One); + queryString = queryFormatter.ToSqlString(query); + Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); + Assert.That(query.Count(), Is.EqualTo(2)); + + query = sharedSession.Query.All().Where(e => e.NByteEnumField >= ByteEnum.One); + queryString = queryFormatter.ToSqlString(query); + Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); + Assert.That(query.Count(), Is.EqualTo(3)); + + query = sharedSession.Query.All().Where(e => e.NByteEnumField < ByteEnum.Two); + queryString = queryFormatter.ToSqlString(query); + Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); + Assert.That(query.Count(), Is.EqualTo(2)); + + query = sharedSession.Query.All().Where(e => e.NByteEnumField <= ByteEnum.Two); + queryString = queryFormatter.ToSqlString(query); + Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); + Assert.That(query.Count(), Is.EqualTo(3)); + + query = sharedSession.Query.All().Where(e => e.NByteEnumField == ByteEnum.Max); + queryString = queryFormatter.ToSqlString(query); + Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); + Assert.That(query.Count(), Is.EqualTo(1)); + } + + [Test] + public void SByteTest() + { + var queryFormatter = sharedSession.Services.Demand(); + + var query = sharedSession.Query.All().Where(e => e.SByteEnumField != SByteEnum.Zero); + var queryString = queryFormatter.ToSqlString(query); + Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); + Assert.That(query.Count(), Is.EqualTo(3)); + + query = sharedSession.Query.All().Where(e => e.SByteEnumField > SByteEnum.One); + queryString = queryFormatter.ToSqlString(query); + Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); + Assert.That(query.Count(), Is.EqualTo(2)); + + query = sharedSession.Query.All().Where(e => e.SByteEnumField >= SByteEnum.One); + queryString = queryFormatter.ToSqlString(query); + Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); + Assert.That(query.Count(), Is.EqualTo(3)); + + query = sharedSession.Query.All().Where(e => e.SByteEnumField < SByteEnum.Two); + queryString = queryFormatter.ToSqlString(query); + Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); + Assert.That(query.Count(), Is.EqualTo(2)); + + query = sharedSession.Query.All().Where(e => e.SByteEnumField <= SByteEnum.Two); + queryString = queryFormatter.ToSqlString(query); + Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); + Assert.That(query.Count(), Is.EqualTo(3)); + + query = sharedSession.Query.All().Where(e => e.SByteEnumField == SByteEnum.Max); + queryString = queryFormatter.ToSqlString(query); + Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); + Assert.That(query.Count(), Is.EqualTo(1)); + + + query = sharedSession.Query.All().Where(e => e.NSByteEnumField != SByteEnum.Zero); + queryString = queryFormatter.ToSqlString(query); + Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); + Assert.That(query.Count(), Is.EqualTo(3)); + + query = sharedSession.Query.All().Where(e => e.NSByteEnumField > SByteEnum.One); + queryString = queryFormatter.ToSqlString(query); + Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); + Assert.That(query.Count(), Is.EqualTo(2)); + + query = sharedSession.Query.All().Where(e => e.NSByteEnumField >= SByteEnum.One); + queryString = queryFormatter.ToSqlString(query); + Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); + Assert.That(query.Count(), Is.EqualTo(3)); + + query = sharedSession.Query.All().Where(e => e.NSByteEnumField < SByteEnum.Two); + queryString = queryFormatter.ToSqlString(query); + Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); + Assert.That(query.Count(), Is.EqualTo(2)); + + query = sharedSession.Query.All().Where(e => e.NSByteEnumField <= SByteEnum.Two); + queryString = queryFormatter.ToSqlString(query); + Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); + Assert.That(query.Count(), Is.EqualTo(3)); + + query = sharedSession.Query.All().Where(e => e.NSByteEnumField == SByteEnum.Max); + queryString = queryFormatter.ToSqlString(query); + Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); + Assert.That(query.Count(), Is.EqualTo(1)); + } + + [Test] + public void ShortTest() + { + var queryFormatter = sharedSession.Services.Demand(); + + var query = sharedSession.Query.All().Where(e => e.ShortEnumField == ShortEnum.Zero); + var queryString = queryFormatter.ToSqlString(query); + Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); + Assert.That(query.Count(), Is.EqualTo(1)); + + query = sharedSession.Query.All().Where(e => e.ShortEnumField == ShortEnum.One); + queryString = queryFormatter.ToSqlString(query); + Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); + Assert.That(query.Count(), Is.EqualTo(1)); + + query = sharedSession.Query.All().Where(e => e.ShortEnumField == ShortEnum.Two); + queryString = queryFormatter.ToSqlString(query); + Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); + Assert.That(query.Count(), Is.EqualTo(1)); + + query = sharedSession.Query.All().Where(e => e.ShortEnumField == ShortEnum.Max); + queryString = queryFormatter.ToSqlString(query); + Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); + Assert.That(query.Count(), Is.EqualTo(1)); + + + query = sharedSession.Query.All().Where(e => e.NShortEnumField != ShortEnum.Zero); + queryString = queryFormatter.ToSqlString(query); + Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); + Assert.That(query.Count(), Is.EqualTo(3)); + + query = sharedSession.Query.All().Where(e => e.NShortEnumField > ShortEnum.One); + queryString = queryFormatter.ToSqlString(query); + Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); + Assert.That(query.Count(), Is.EqualTo(2)); + + query = sharedSession.Query.All().Where(e => e.NShortEnumField >= ShortEnum.One); + queryString = queryFormatter.ToSqlString(query); + Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); + Assert.That(query.Count(), Is.EqualTo(3)); + + query = sharedSession.Query.All().Where(e => e.ShortEnumField < ShortEnum.Two); + queryString = queryFormatter.ToSqlString(query); + Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); + Assert.That(query.Count(), Is.EqualTo(2)); + + query = sharedSession.Query.All().Where(e => e.ShortEnumField <= ShortEnum.Two); + queryString = queryFormatter.ToSqlString(query); + Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); + Assert.That(query.Count(), Is.EqualTo(3)); + + query = sharedSession.Query.All().Where(e => e.ShortEnumField == ShortEnum.Max); + queryString = queryFormatter.ToSqlString(query); + Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); + Assert.That(query.Count(), Is.EqualTo(1)); + } + + [Test] + public void UShortTest() + { + var queryFormatter = sharedSession.Services.Demand(); + + var query = sharedSession.Query.All().Where(e => e.UShortEnumField != UShortEnum.Zero); + var queryString = queryFormatter.ToSqlString(query); + Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); + Assert.That(query.Count(), Is.EqualTo(3)); + + query = sharedSession.Query.All().Where(e => e.UShortEnumField > UShortEnum.One); + queryString = queryFormatter.ToSqlString(query); + Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); + Assert.That(query.Count(), Is.EqualTo(2)); + + query = sharedSession.Query.All().Where(e => e.UShortEnumField >= UShortEnum.One); + queryString = queryFormatter.ToSqlString(query); + Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); + Assert.That(query.Count(), Is.EqualTo(3)); + + query = sharedSession.Query.All().Where(e => e.UShortEnumField < UShortEnum.Two); + queryString = queryFormatter.ToSqlString(query); + Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); + Assert.That(query.Count(), Is.EqualTo(2)); + + query = sharedSession.Query.All().Where(e => e.UShortEnumField <= UShortEnum.Two); + queryString = queryFormatter.ToSqlString(query); + Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); + Assert.That(query.Count(), Is.EqualTo(3)); + + query = sharedSession.Query.All().Where(e => e.UShortEnumField == UShortEnum.Max); + queryString = queryFormatter.ToSqlString(query); + Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); + Assert.That(query.Count(), Is.EqualTo(1)); + + + query = sharedSession.Query.All().Where(e => e.NUShortEnumField != UShortEnum.Zero); + queryString = queryFormatter.ToSqlString(query); + Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); + Assert.That(query.Count(), Is.EqualTo(3)); + + query = sharedSession.Query.All().Where(e => e.NUShortEnumField > UShortEnum.One); + queryString = queryFormatter.ToSqlString(query); + Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); + Assert.That(query.Count(), Is.EqualTo(2)); + + query = sharedSession.Query.All().Where(e => e.NUShortEnumField >= UShortEnum.One); + queryString = queryFormatter.ToSqlString(query); + Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); + Assert.That(query.Count(), Is.EqualTo(3)); + + query = sharedSession.Query.All().Where(e => e.NUShortEnumField < UShortEnum.Two); + queryString = queryFormatter.ToSqlString(query); + Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); + Assert.That(query.Count(), Is.EqualTo(2)); + + query = sharedSession.Query.All().Where(e => e.NUShortEnumField <= UShortEnum.Two); + queryString = queryFormatter.ToSqlString(query); + Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); + Assert.That(query.Count(), Is.EqualTo(3)); + + query = sharedSession.Query.All().Where(e => e.UShortEnumField == UShortEnum.Max); + queryString = queryFormatter.ToSqlString(query); + Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); + Assert.That(query.Count(), Is.EqualTo(1)); + } + + [Test] + public void IntTest() + { + var queryFormatter = sharedSession.Services.Demand(); + + var query = sharedSession.Query.All().Where(e => e.IntEnumField != IntEnum.Zero); + var queryString = queryFormatter.ToSqlString(query); + Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); + Assert.That(query.Count(), Is.EqualTo(3)); + + query = sharedSession.Query.All().Where(e => e.IntEnumField > IntEnum.One); + queryString = queryFormatter.ToSqlString(query); + Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); + Assert.That(query.Count(), Is.EqualTo(2)); + + query = sharedSession.Query.All().Where(e => e.IntEnumField >= IntEnum.One); + queryString = queryFormatter.ToSqlString(query); + Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); + Assert.That(query.Count(), Is.EqualTo(3)); + + query = sharedSession.Query.All().Where(e => e.IntEnumField < IntEnum.Two); + queryString = queryFormatter.ToSqlString(query); + Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); + Assert.That(query.Count(), Is.EqualTo(2)); + + query = sharedSession.Query.All().Where(e => e.IntEnumField <= IntEnum.Two); + queryString = queryFormatter.ToSqlString(query); + Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); + Assert.That(query.Count(), Is.EqualTo(3)); + + query = sharedSession.Query.All().Where(e => e.IntEnumField == IntEnum.Max); + queryString = queryFormatter.ToSqlString(query); + Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); + Assert.That(query.Count(), Is.EqualTo(1)); + + + query = sharedSession.Query.All().Where(e => e.NIntEnumField != IntEnum.Zero); + queryString = queryFormatter.ToSqlString(query); + Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); + Assert.That(query.Count(), Is.EqualTo(3)); + + query = sharedSession.Query.All().Where(e => e.NIntEnumField > IntEnum.One); + queryString = queryFormatter.ToSqlString(query); + Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); + Assert.That(query.Count(), Is.EqualTo(2)); + + query = sharedSession.Query.All().Where(e => e.NIntEnumField >= IntEnum.One); + queryString = queryFormatter.ToSqlString(query); + Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); + Assert.That(query.Count(), Is.EqualTo(3)); + + query = sharedSession.Query.All().Where(e => e.NIntEnumField < IntEnum.Two); + queryString = queryFormatter.ToSqlString(query); + Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); + Assert.That(query.Count(), Is.EqualTo(2)); + + query = sharedSession.Query.All().Where(e => e.NIntEnumField <= IntEnum.Two); + queryString = queryFormatter.ToSqlString(query); + Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); + Assert.That(query.Count(), Is.EqualTo(3)); + + query = sharedSession.Query.All().Where(e => e.NIntEnumField == IntEnum.Max); + queryString = queryFormatter.ToSqlString(query); + Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); + Assert.That(query.Count(), Is.EqualTo(1)); + } + + [Test] + public void UIntTest() + { + var queryFormatter = sharedSession.Services.Demand(); + + var query = sharedSession.Query.All().Where(e => e.UIntEnumField != UIntEnum.Zero); + var queryString = queryFormatter.ToSqlString(query); + Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); + Assert.That(query.Count(), Is.EqualTo(3)); + + query = sharedSession.Query.All().Where(e => e.UIntEnumField > UIntEnum.One); + queryString = queryFormatter.ToSqlString(query); + Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); + Assert.That(query.Count(), Is.EqualTo(2)); + + query = sharedSession.Query.All().Where(e => e.UIntEnumField >= UIntEnum.One); + queryString = queryFormatter.ToSqlString(query); + Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); + Assert.That(query.Count(), Is.EqualTo(3)); + + query = sharedSession.Query.All().Where(e => e.UIntEnumField < UIntEnum.Two); + queryString = queryFormatter.ToSqlString(query); + Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); + Assert.That(query.Count(), Is.EqualTo(2)); + + query = sharedSession.Query.All().Where(e => e.UIntEnumField <= UIntEnum.Two); + queryString = queryFormatter.ToSqlString(query); + Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); + Assert.That(query.Count(), Is.EqualTo(3)); + + query = sharedSession.Query.All().Where(e => e.UIntEnumField == UIntEnum.Max); + queryString = queryFormatter.ToSqlString(query); + Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); + Assert.That(query.Count(), Is.EqualTo(1)); + + + query = sharedSession.Query.All().Where(e => e.NUIntEnumField != UIntEnum.Zero); + queryString = queryFormatter.ToSqlString(query); + Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); + Assert.That(query.Count(), Is.EqualTo(3)); + + query = sharedSession.Query.All().Where(e => e.NUIntEnumField > UIntEnum.One); + queryString = queryFormatter.ToSqlString(query); + Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); + Assert.That(query.Count(), Is.EqualTo(2)); + + query = sharedSession.Query.All().Where(e => e.NUIntEnumField >= UIntEnum.One); + queryString = queryFormatter.ToSqlString(query); + Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); + Assert.That(query.Count(), Is.EqualTo(3)); + + query = sharedSession.Query.All().Where(e => e.NUIntEnumField < UIntEnum.Two); + queryString = queryFormatter.ToSqlString(query); + Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); + Assert.That(query.Count(), Is.EqualTo(2)); + + query = sharedSession.Query.All().Where(e => e.NUIntEnumField <= UIntEnum.Two); + queryString = queryFormatter.ToSqlString(query); + Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); + Assert.That(query.Count(), Is.EqualTo(3)); + + query = sharedSession.Query.All().Where(e => e.NUIntEnumField == UIntEnum.Max); + queryString = queryFormatter.ToSqlString(query); + Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); + Assert.That(query.Count(), Is.EqualTo(1)); + } + + [Test] + public void LongTest() + { + var queryFormatter = sharedSession.Services.Demand(); + + var substractValue = StorageProviderInfo.Instance.CheckProviderIs(StorageProvider.SqlServer) + ? castSign.Length + : 0; + + var query = sharedSession.Query.All().Where(e => e.LongEnumField != LongEnum.Zero); + var queryString = queryFormatter.ToSqlString(query); + Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length - substractValue)); + Assert.That(query.Count(), Is.EqualTo(3)); + + query = sharedSession.Query.All().Where(e => e.LongEnumField > LongEnum.One); + queryString = queryFormatter.ToSqlString(query); + Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length - substractValue)); + Assert.That(query.Count(), Is.EqualTo(2)); + + query = sharedSession.Query.All().Where(e => e.LongEnumField >= LongEnum.One); + queryString = queryFormatter.ToSqlString(query); + Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length - substractValue)); + Assert.That(query.Count(), Is.EqualTo(3)); + + query = sharedSession.Query.All().Where(e => e.LongEnumField < LongEnum.Two); + queryString = queryFormatter.ToSqlString(query); + Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length - substractValue)); + Assert.That(query.Count(), Is.EqualTo(2)); + + query = sharedSession.Query.All().Where(e => e.LongEnumField <= LongEnum.Two); + queryString = queryFormatter.ToSqlString(query); + Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length - substractValue)); + Assert.That(query.Count(), Is.EqualTo(3)); + + query = sharedSession.Query.All().Where(e => e.LongEnumField == LongEnum.Max); + queryString = queryFormatter.ToSqlString(query); + Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length - substractValue)); + Assert.That(query.Count(), Is.EqualTo(1)); + + + query = sharedSession.Query.All().Where(e => e.NLongEnumField != LongEnum.Zero); + queryString = queryFormatter.ToSqlString(query); + Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length - substractValue)); + Assert.That(query.Count(), Is.EqualTo(3)); + + query = sharedSession.Query.All().Where(e => e.NLongEnumField > LongEnum.One); + queryString = queryFormatter.ToSqlString(query); + Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length - substractValue)); + Assert.That(query.Count(), Is.EqualTo(2)); + + query = sharedSession.Query.All().Where(e => e.NLongEnumField >= LongEnum.One); + queryString = queryFormatter.ToSqlString(query); + Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length - substractValue)); + Assert.That(query.Count(), Is.EqualTo(3)); + + query = sharedSession.Query.All().Where(e => e.NLongEnumField < LongEnum.Two); + queryString = queryFormatter.ToSqlString(query); + Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length - substractValue)); + Assert.That(query.Count(), Is.EqualTo(2)); + + query = sharedSession.Query.All().Where(e => e.NLongEnumField <= LongEnum.Two); + queryString = queryFormatter.ToSqlString(query); + Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length - substractValue)); + Assert.That(query.Count(), Is.EqualTo(3)); + + query = sharedSession.Query.All().Where(e => e.NLongEnumField == LongEnum.Max); + queryString = queryFormatter.ToSqlString(query); + Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length - substractValue)); + Assert.That(query.Count(), Is.EqualTo(1)); + } + + [Test] + public void ULongTest() + { + var queryFormatter = sharedSession.Services.Demand(); + + var query = sharedSession.Query.All().Where(e => e.ULongEnumField != ULongEnum.Zero); + var queryString = queryFormatter.ToSqlString(query); + Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); + Assert.That(query.Count(), Is.EqualTo(3)); + + query = sharedSession.Query.All().Where(e => e.ULongEnumField > ULongEnum.One); + queryString = queryFormatter.ToSqlString(query); + Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); + Assert.That(query.Count(), Is.EqualTo(2)); + + query = sharedSession.Query.All().Where(e => e.ULongEnumField >= ULongEnum.One); + queryString = queryFormatter.ToSqlString(query); + Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); + Assert.That(query.Count(), Is.EqualTo(3)); + + query = sharedSession.Query.All().Where(e => e.ULongEnumField < ULongEnum.Two); + queryString = queryFormatter.ToSqlString(query); + Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); + Assert.That(query.Count(), Is.EqualTo(2)); + + query = sharedSession.Query.All().Where(e => e.ULongEnumField <= ULongEnum.Two); + queryString = queryFormatter.ToSqlString(query); + Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); + Assert.That(query.Count(), Is.EqualTo(3)); + + query = sharedSession.Query.All().Where(e => e.ULongEnumField == ULongEnum.Max); + queryString = queryFormatter.ToSqlString(query); + Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); + Assert.That(query.Count(), Is.EqualTo(1)); + + + query = sharedSession.Query.All().Where(e => e.NULongEnumField != ULongEnum.Zero); + queryString = queryFormatter.ToSqlString(query); + Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); + Assert.That(query.Count(), Is.EqualTo(3)); + + query = sharedSession.Query.All().Where(e => e.NULongEnumField > ULongEnum.One); + queryString = queryFormatter.ToSqlString(query); + Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); + Assert.That(query.Count(), Is.EqualTo(2)); + + query = sharedSession.Query.All().Where(e => e.NULongEnumField >= ULongEnum.One); + queryString = queryFormatter.ToSqlString(query); + Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); + Assert.That(query.Count(), Is.EqualTo(3)); + + query = sharedSession.Query.All().Where(e => e.NULongEnumField < ULongEnum.Two); + queryString = queryFormatter.ToSqlString(query); + Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); + Assert.That(query.Count(), Is.EqualTo(2)); + + query = sharedSession.Query.All().Where(e => e.NULongEnumField <= ULongEnum.Two); + queryString = queryFormatter.ToSqlString(query); + Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); + Assert.That(query.Count(), Is.EqualTo(3)); + + query = sharedSession.Query.All().Where(e => e.NULongEnumField == ULongEnum.Max); + queryString = queryFormatter.ToSqlString(query); + Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); + Assert.That(query.Count(), Is.EqualTo(1)); + } + } +} \ No newline at end of file diff --git a/Orm/Xtensive.Orm.Tests/Storage/PartialIndexTest.cs b/Orm/Xtensive.Orm.Tests/Storage/PartialIndexTest.cs index b54b8a787b..2a8bf8cbd5 100644 --- a/Orm/Xtensive.Orm.Tests/Storage/PartialIndexTest.cs +++ b/Orm/Xtensive.Orm.Tests/Storage/PartialIndexTest.cs @@ -1,6 +1,6 @@ -// Copyright (C) 2011 Xtensive LLC. -// All rights reserved. -// For conditions of distribution and use, see license. +// Copyright (C) 2011-2021 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: 2011.10.06 @@ -49,73 +49,61 @@ public interface ITestInterface : IEntity string TestField { get; set; } } - [HierarchyRoot, Index("TestField", Filter = "Index")] + [HierarchyRoot, Index(nameof(TestField), Filter = nameof(Index))] public class SimpleFilterWithMethod : TestBase { - public static Expression> Index() - { - return test => test.TestField.GreaterThan("hello world"); - } + public static Expression> Index() => + test => test.TestField.GreaterThan("hello world"); [Field] public string TestField { get; set; } } - [HierarchyRoot, Index("TestField", Filter = "Index")] + [HierarchyRoot, Index(nameof(TestField), Filter = nameof(Index))] public class SimpleFilterWithProperty : TestBase { - public static Expression> Index - { - get { return test => test.TestField.GreaterThan("hello world"); } - } + public static Expression> Index => + test => test.TestField.GreaterThan("hello world"); [Field] public string TestField { get; set; } } - [HierarchyRoot, Index("Target", Filter = "Index")] + [HierarchyRoot, Index(nameof(Target), Filter = nameof(Index))] public class FilterOnReferenceField : TestBase { - public static Expression> Index() - { - return test => test.Target!=null; - } + public static Expression> Index() => + test => test.Target != null; [Field] public TargetEntity Target { get; set; } } - [HierarchyRoot, Index("Target", Filter = "Index")] + [HierarchyRoot, Index(nameof(Target), Filter = nameof(Index))] public class FilterOnComplexReferenceField : TestBase { - public static Expression> Index() - { - return test => test.Target!=null; - } + public static Expression> Index() => + test => test.Target != null; [Field] public ComplexTargetEntity Target { get; set; } } - [HierarchyRoot, Index("Target", Filter = "Index")] + [HierarchyRoot, Index(nameof(Target), Filter = nameof(Index))] public class FilterOnReferenceIdField : TestBase { - public static Expression> Index() - { - return test => test.Target.Id > 0; - } + public static Expression> Index() => + test => test.Target.Id > 0; [Field] public TargetEntity Target { get; set; } } - [HierarchyRoot, Index("TestField1", Filter = "Index")] + [HierarchyRoot, Index(nameof(TestField1), Filter = nameof(Index))] public class FilterOnAlienField : TestBase { - public static Expression> Index - { - get { return test => test.TestField2.GreaterThan("hello world"); } - } + public static Expression> Index => + test => test.TestField2.GreaterThan("hello world"); [Field] public string TestField1 { get; set; } @@ -124,103 +112,83 @@ public static Expression> Index public string TestField2 { get; set; } } - [HierarchyRoot, Index("TestField", Filter = "Index")] + [HierarchyRoot, Index(nameof(TestField), Filter = nameof(Index))] public class MultipleFieldUses : TestBase { - public static Expression> Index - { - get { return test => test.TestField.GreaterThan("hello") && test.TestField.LessThan("world"); } - } + public static Expression> Index => + test => test.TestField.GreaterThan("hello") && test.TestField.LessThan("world"); [Field] public string TestField { get; set; } } - [HierarchyRoot, Index("TestField", Filter = "Index")] + [HierarchyRoot, Index(nameof(TestField), Filter = nameof(Index))] public class InterfaceSupport : TestBase, ITestInterface { - public static Expression> Index - { - get { return test => test.TestField.LessThan("bye world"); } - } + public static Expression> Index => + test => test.TestField.LessThan("bye world"); [Field] public string TestField { get; set; } } - [HierarchyRoot, Index("TestField", Filter = "Index")] + [HierarchyRoot, Index(nameof(TestField), Filter = nameof(Index))] public class InOperatorSupport : TestBase { - public static Expression> Index - { - get { return test => test.TestField.In("1", "2", "3"); } - } + public static Expression> Index => + test => test.TestField.In("1", "2", "3"); [Field] public string TestField { get; set; } } - [HierarchyRoot, Index("TestField", Filter = "Index")] + [HierarchyRoot, Index(nameof(TestField), Filter = nameof(Index))] public class InOperatorSupport2 : TestBase { - public static Expression> Index - { - get { - return test => test.TestField.In( - new Guid("{D27F71D7-D4FC-446C-8C7E-E89DC2209863}"), - new Guid("{94ED80D9-6749-41E2-B60D-BEDE1CDCA237}")); - } - } + public static Expression> Index => + test => test.TestField.In( + new Guid("{D27F71D7-D4FC-446C-8C7E-E89DC2209863}"), + new Guid("{94ED80D9-6749-41E2-B60D-BEDE1CDCA237}")); [Field] public Guid TestField { get; set; } } - [HierarchyRoot, Index("TestField", Filter = "Index")] + [HierarchyRoot, Index(nameof(TestField), Filter = nameof(Index))] public class ContainsOperatorSupport : TestBase { - public static Expression> Index - { - get { return test => new[] {"1", "2", "3"}.Contains(test.TestField); } - } + public static Expression> Index => + test => new[] { "1", "2", "3" }.Contains(test.TestField); [Field] public string TestField { get; set; } } [HierarchyRoot, - Index("TestField", Filter = "More", Name = "MoreIndex"), - Index("TestField", Filter = "Less", Name = "LessIndex")] + Index(nameof(TestField), Filter = nameof(More), Name = "MoreIndex"), + Index(nameof(TestField), Filter = nameof(Less), Name = "LessIndex")] public class DoubleIndexWithName : TestBase { - public static Expression> More() - { - return test => test.TestField > 1000; - } + public static Expression> More() => + test => test.TestField > 1000; - public static Expression> Less() - { - return test => test.TestField < 100; - } + public static Expression> Less() => + test => test.TestField < 100; [Field] public int TestField { get; set; } } [HierarchyRoot, - Index("TestField", Filter = "More"), - Index("TestField", Filter = "Less")] + Index(nameof(TestField), Filter = nameof(More)), + Index(nameof(TestField), Filter = nameof(Less))] public class DoubleIndexWithoutName : TestBase { - public static Expression> More() - { - return test => test.TestField > 1000; - } + public static Expression> More() => + test => test.TestField > 1000; - public static Expression> Less() - { - return test => test.TestField < 100; - } + public static Expression> Less() => + test => test.TestField < 100; [Field] public int TestField { get; set; } @@ -233,13 +201,11 @@ public class InheritanceClassTableBase : TestBase public int BaseField { get; set; } } - [Index("TestField", Filter = "Index")] + [Index(nameof(TestField), Filter = nameof(Index))] public class InheritanceClassTable : InheritanceClassTableBase { - public static Expression> Index() - { - return test => test.BaseField > 0; - } + public static Expression> Index() => + test => test.BaseField > 0; [Field] public int TestField { get; set; } @@ -252,13 +218,11 @@ public class InheritanceSingleTableBase : TestBase public int BaseField { get; set; } } - [Index("TestField", Filter = "Index")] + [Index(nameof(TestField), Filter = nameof(Index))] public class InheritanceSingleTable : InheritanceSingleTableBase { - public static Expression> Index() - { - return test => test.BaseField > 0; - } + public static Expression> Index() => + test => test.BaseField > 0; [Field] public int TestField { get; set; } @@ -271,17 +235,230 @@ public class InheritanceConcreteTableBase : TestBase public int BaseField { get; set; } } - [Index("TestField", Filter = "Index")] + [Index(nameof(TestField), Filter = nameof(Index))] public class InheritanceConcreteTable : InheritanceConcreteTableBase { - public static Expression> Index() - { - return test => test.BaseField > 0; - } + public static Expression> Index() => + test => test.BaseField > 0; [Field] public int TestField { get; set; } } + + #region Enums + public enum ByteEnum : byte + { + Zero = 0, + One = 1, + Two = 2, + Max = byte.MaxValue + } + + public enum SByteEnum : sbyte + { + Zero = 0, + One = 1, + Two = 2, + Max = sbyte.MaxValue + } + + public enum ShortEnum : short + { + Zero = 0, + One = 1, + Two = 2, + Max = short.MaxValue + } + + public enum UShortEnum : ushort + { + Zero = 0, + One = 1, + Two = 2, + Max = ushort.MaxValue + } + + public enum IntEnum : int + { + Zero = 0, + One = 1, + Two = 2, + Max = int.MaxValue + } + + public enum UIntEnum : uint + { + Zero = 0, + One = 1, + Two = 2, + Max = uint.MaxValue + } + + public enum LongEnum : long + { + Zero = 0, + One = 1, + Two = 2, + Max = long.MaxValue + } + + public enum ULongEnum : ulong + { + Zero = 0, + One = 1, + Two = 2, + Max = ulong.MaxValue + } + #endregion + + [HierarchyRoot] + [Index(nameof(ByteEnumField), Filter = nameof(ByteIndex))] + [Index(nameof(NByteEnumField), Filter = nameof(NByteIndex))] + [Index(nameof(SByteEnumField), Filter = nameof(SByteIndex))] + [Index(nameof(NSByteEnumField), Filter = nameof(SNByteIndex))] + [Index(nameof(ShortEnumField), Filter = nameof(ShortIndex))] + [Index(nameof(NShortEnumField), Filter = nameof(NShortIndex))] + [Index(nameof(UShortEnumField), Filter = nameof(UShortIndex))] + [Index(nameof(NUShortEnumField), Filter = nameof(NUShortIndex))] + [Index(nameof(IntEnumField), Filter = nameof(IntIndex))] + [Index(nameof(NIntEnumField), Filter = nameof(NIntIndex))] + [Index(nameof(UIntEnumField), Filter = nameof(UIntIndex))] + [Index(nameof(NUIntEnumField), Filter = nameof(NUIntIndex))] + [Index(nameof(LongEnumField), Filter = nameof(LongIndex))] + [Index(nameof(NLongEnumField), Filter = nameof(NLongIndex))] + [Index(nameof(ULongEnumField), Filter = nameof(ULongIndex))] + [Index(nameof(NULongEnumField), Filter = nameof(NULongIndex))] + public class EnumFieldFilter : Entity + { + public const string Zero = "Zero"; + public const string One = "One"; + public const string Two = "Two"; + public const string Max = "Max"; + + #region Filters + public static Expression> ByteIndex() => + test => test.ByteEnumField > ByteEnum.Two; + + public static Expression> NByteIndex() => + test => test.NByteEnumField > ByteEnum.Two; + + public static Expression> SByteIndex() => + test => test.ByteEnumField > ByteEnum.Two; + + public static Expression> SNByteIndex() => + test => test.ByteEnumField > ByteEnum.Two; + + public static Expression> ShortIndex() => + test => test.ShortEnumField > ShortEnum.Two; + + public static Expression> NShortIndex() => + test => test.NShortEnumField > ShortEnum.Two; + + public static Expression> UShortIndex() => + test => test.UShortEnumField > UShortEnum.Two; + + public static Expression> NUShortIndex() => + test => test.NUShortEnumField > UShortEnum.Two; + + public static Expression> IntIndex() => + test => test.IntEnumField > IntEnum.Two; + + public static Expression> NIntIndex() => + test => test.NIntEnumField > IntEnum.Two; + + public static Expression> UIntIndex() => + test => test.UIntEnumField > UIntEnum.Two; + + public static Expression> NUIntIndex() => + test => test.NUIntEnumField > UIntEnum.Two; + + public static Expression> LongIndex() => + test => test.LongEnumField > LongEnum.Two; + + public static Expression> NLongIndex() => + test => test.NLongEnumField > LongEnum.Two; + + public static Expression> ULongIndex() => + test => test.ULongEnumField > ULongEnum.Two; + + public static Expression> NULongIndex() => + test => test.NULongEnumField > ULongEnum.Two; + + #endregion + + [Field, Key] + public int Id { get; private set; } + + [Field] + public ByteEnum ByteEnumField { get; set; } + + [Field] + public SByteEnum SByteEnumField { get; set; } + + [Field] + public ShortEnum ShortEnumField { get; set; } + + [Field] + public UShortEnum UShortEnumField { get; set; } + + [Field] + public IntEnum IntEnumField { get; set; } + + [Field] + public UIntEnum UIntEnumField { get; set; } + + [Field] + public LongEnum LongEnumField { get; set; } + + [Field] + public ULongEnum ULongEnumField { get; set; } + + [Field] + public ByteEnum? NByteEnumField { get; set; } + + [Field] + public SByteEnum? NSByteEnumField { get; set; } + + [Field] + public ShortEnum? NShortEnumField { get; set; } + + [Field] + public UShortEnum? NUShortEnumField { get; set; } + + [Field] + public IntEnum? NIntEnumField { get; set; } + + [Field] + public UIntEnum? NUIntEnumField { get; set; } + + [Field] + public LongEnum? NLongEnumField { get; set; } + + [Field] + public ULongEnum? NULongEnumField { get; set; } + + public EnumFieldFilter(Session session, string enumValue) + : base(session) + { + ByteEnumField = (ByteEnum) Enum.Parse(typeof(ByteEnum), enumValue); + SByteEnumField = (SByteEnum) Enum.Parse(typeof(SByteEnum), enumValue); + ShortEnumField = (ShortEnum) Enum.Parse(typeof(ShortEnum), enumValue); + UShortEnumField = (UShortEnum) Enum.Parse(typeof(UShortEnum), enumValue); + IntEnumField = (IntEnum) Enum.Parse(typeof(IntEnum), enumValue); + UIntEnumField = (UIntEnum) Enum.Parse(typeof(UIntEnum), enumValue); + LongEnumField = (LongEnum) Enum.Parse(typeof(LongEnum), enumValue); + ULongEnumField = (ULongEnum) Enum.Parse(typeof(ULongEnum), enumValue); + + NByteEnumField = (ByteEnum) Enum.Parse(typeof(ByteEnum), enumValue); + NSByteEnumField = (SByteEnum) Enum.Parse(typeof(SByteEnum), enumValue); + NShortEnumField = (ShortEnum) Enum.Parse(typeof(ShortEnum), enumValue); + NUShortEnumField = (UShortEnum) Enum.Parse(typeof(UShortEnum), enumValue); + NIntEnumField = (IntEnum) Enum.Parse(typeof(IntEnum), enumValue); + NUIntEnumField = (UIntEnum) Enum.Parse(typeof(UIntEnum), enumValue); + NLongEnumField = (LongEnum) Enum.Parse(typeof(LongEnum), enumValue); + NULongEnumField = (ULongEnum) Enum.Parse(typeof(ULongEnum), enumValue); + } + } } namespace Xtensive.Orm.Tests.Storage @@ -292,16 +469,11 @@ public class PartialIndexTest private Domain domain; [OneTimeSetUp] - public void TestFixtureSetUp() - { + public void TestFixtureSetUp() => Require.AllFeaturesSupported(ProviderFeatures.PartialIndexes); - } [TearDown] - public void TearDown() - { - CleanDomain(); - } + public void TearDown() => CleanDomain(); private void CleanDomain() { @@ -319,8 +491,10 @@ private void BuildDomain(IEnumerable entities, DomainUpgradeMode mode) { CleanDomain(); var config = DomainConfigurationFactory.Create(); - foreach (var entity in entities) + foreach (var entity in entities) { config.Types.Register(entity); + } + config.UpgradeMode = mode; domain = Domain.Build(config); } @@ -329,7 +503,7 @@ private void AssertBuildSuccess(params Type[] entities) { BuildDomain(entities, DomainUpgradeMode.Recreate); var partialIndexes = domain.Model.RealIndexes - .Where(index => index.IsPartial && index.FilterExpression!=null && index.Filter!=null) + .Where(index => index.IsPartial && index.FilterExpression != null && index.Filter != null) .ToList(); Assert.IsNotEmpty(partialIndexes); } @@ -340,107 +514,62 @@ private void AssertBuildFailure(params Type[] entities) } [Test] - public void SimpleFilterWithMethodTest() - { - AssertBuildSuccess(typeof (SimpleFilterWithMethod)); - } + public void SimpleFilterWithMethodTest() => AssertBuildSuccess(typeof(SimpleFilterWithMethod)); [Test] - public void SimpleFilterWithPropertyTest() - { - AssertBuildSuccess(typeof (SimpleFilterWithProperty)); - } + public void SimpleFilterWithPropertyTest() => AssertBuildSuccess(typeof(SimpleFilterWithProperty)); [Test] - public void FilterOnReferenceFieldTest() - { - AssertBuildSuccess(typeof (FilterOnReferenceField)); - } + public void FilterOnReferenceFieldTest() => AssertBuildSuccess(typeof(FilterOnReferenceField)); [Test] - public void FilterOnComplexReferenceFieldTest() - { - AssertBuildSuccess(typeof (FilterOnComplexReferenceField)); - } + public void FilterOnComplexReferenceFieldTest() => AssertBuildSuccess(typeof(FilterOnComplexReferenceField)); [Test] - public void FilterOnReferenceFieldIdTest() - { - AssertBuildSuccess(typeof (FilterOnReferenceIdField)); - } + public void FilterOnReferenceFieldIdTest() => AssertBuildSuccess(typeof(FilterOnReferenceIdField)); [Test] - public void FilterOnAlienFieldTest() - { - AssertBuildSuccess(typeof (FilterOnAlienField)); - } + public void FilterOnAlienFieldTest() => AssertBuildSuccess(typeof(FilterOnAlienField)); [Test] - public void MultipleFieldUsesTest() - { - AssertBuildSuccess(typeof(MultipleFieldUses)); - } + public void MultipleFieldUsesTest() => AssertBuildSuccess(typeof(MultipleFieldUses)); [Test] - public void InOperatorSupportTest() - { - AssertBuildSuccess(typeof (InOperatorSupport)); - } + public void InOperatorSupportTest() => AssertBuildSuccess(typeof(InOperatorSupport)); [Test] - public void InOperatorSupport2Test() - { - AssertBuildSuccess(typeof(InOperatorSupport2)); - } + public void InOperatorSupport2Test() => AssertBuildSuccess(typeof(InOperatorSupport2)); [Test] - public void ContainsOperatorSupportTest() - { - AssertBuildSuccess(typeof(ContainsOperatorSupport)); - } + public void ContainsOperatorSupportTest() => AssertBuildSuccess(typeof(ContainsOperatorSupport)); [Test] - public void DoubleIndexWithNameTest() - { - AssertBuildSuccess(typeof (DoubleIndexWithName)); - } - + public void DoubleIndexWithNameTest() => AssertBuildSuccess(typeof(DoubleIndexWithName)); + [Test] - public void DoubleIndexWithoutNameTest() - { - AssertBuildSuccess(typeof (DoubleIndexWithoutName)); - } + public void DoubleIndexWithoutNameTest() => AssertBuildSuccess(typeof(DoubleIndexWithoutName)); [Test] - public void InterfaceSupportTest() - { - AssertBuildSuccess(typeof(InterfaceSupport)); - } + public void InterfaceSupportTest() => AssertBuildSuccess(typeof(InterfaceSupport)); [Test] - public void InheritanceClassTableTest() - { - AssertBuildFailure(typeof (InheritanceClassTable)); - } + public void InheritanceClassTableTest() => AssertBuildFailure(typeof(InheritanceClassTable)); [Test] - public void InheritanceSingleTableTest() - { - AssertBuildSuccess(typeof(InheritanceSingleTable)); - } + public void InheritanceSingleTableTest() => AssertBuildSuccess(typeof(InheritanceSingleTable)); [Test] - public void InheritanceConcreteTableTest() - { - AssertBuildSuccess(typeof(InheritanceConcreteTable)); - } + public void InheritanceConcreteTableTest() => AssertBuildSuccess(typeof(InheritanceConcreteTable)); + + [Test] + public void EnumFieldFilterTest() => AssertBuildSuccess(typeof(EnumFieldFilter)); [Test] public void ValidateTest() { - var types = typeof (TestBase).Assembly + var types = typeof(TestBase).Assembly .GetTypes() - .Where(type => type.Namespace==typeof (TestBase).Namespace && type!=typeof (InheritanceClassTable)) + .Where(type => type.Namespace == typeof(TestBase).Namespace && type != typeof(InheritanceClassTable)) .ToList(); BuildDomain(types, DomainUpgradeMode.Recreate); BuildDomain(types, DomainUpgradeMode.Validate); diff --git a/Orm/Xtensive.Orm/Orm/Building/Builders/PartialIndexFilterBuilder.cs b/Orm/Xtensive.Orm/Orm/Building/Builders/PartialIndexFilterBuilder.cs index b34df0de81..fd08eededc 100644 --- a/Orm/Xtensive.Orm/Orm/Building/Builders/PartialIndexFilterBuilder.cs +++ b/Orm/Xtensive.Orm/Orm/Building/Builders/PartialIndexFilterBuilder.cs @@ -1,6 +1,6 @@ -// Copyright (C) 2011 Xtensive LLC. -// All rights reserved. -// For conditions of distribution and use, see license. +// Copyright (C) 2011-2021 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: 2011.10.07 @@ -46,6 +46,36 @@ public static void BuildFilter(IndexInfo index) protected override Expression VisitBinary(BinaryExpression b) { + if (EnumRewritableOperations(b)) { + var leftNoCasts = b.Left.StripCasts(); + var leftNoCastsType = leftNoCasts.Type; + var bareLeftType = leftNoCastsType.StripNullable(); + var rightNoCasts = b.Right.StripCasts(); + var rightNoCastsType = rightNoCasts.Type; + var bareRightType = rightNoCastsType.StripNullable(); + + if (bareLeftType.IsEnum && rightNoCasts.NodeType == ExpressionType.Constant) { + var typeToCast = leftNoCastsType.IsNullable() + ? bareLeftType.GetEnumUnderlyingType().ToNullable() + : leftNoCastsType.GetEnumUnderlyingType(); + + return base.VisitBinary(Expression.MakeBinary( + b.NodeType, + Expression.Convert(leftNoCasts, typeToCast), + Expression.Convert(b.Right, typeToCast))); + } + else if (bareRightType.IsEnum && leftNoCasts.NodeType == ExpressionType.Constant) { + var typeToCast = rightNoCastsType.IsNullable() + ? bareRightType.GetEnumUnderlyingType().ToNullable() + : rightNoCastsType.GetEnumUnderlyingType(); + + return base.VisitBinary(Expression.MakeBinary( + b.NodeType, + Expression.Convert(rightNoCasts, typeToCast), + Expression.Convert(b.Left, typeToCast))); + } + } + // Detect f!=null and f==null for entity fields if (!b.NodeType.In(ExpressionType.Equal, ExpressionType.NotEqual)) @@ -54,13 +84,20 @@ protected override Expression VisitBinary(BinaryExpression b) var left = Visit(b.Left); var right = Visit(b.Right); - FieldInfo field; - if (entityAccessMap.TryGetValue(left, out field) && IsNull(right)) + if (entityAccessMap.TryGetValue(left, out var field) && IsNull(right)) return BuildEntityCheck(field, b.NodeType); if (entityAccessMap.TryGetValue(right, out field) && IsNull(left)) return BuildEntityCheck(field, b.NodeType); return base.VisitBinary(b); + + static bool EnumRewritableOperations(BinaryExpression b) + { + var nt = b.NodeType; + return nt == ExpressionType.Equal || nt == ExpressionType.NotEqual + || nt == ExpressionType.GreaterThan || nt == ExpressionType.GreaterThanOrEqual + || nt == ExpressionType.LessThan || nt == ExpressionType.LessThanOrEqual; + } } protected override Expression VisitMemberAccess(MemberExpression originalMemberAccess) diff --git a/Orm/Xtensive.Orm/Orm/Linq/Translator.Expressions.cs b/Orm/Xtensive.Orm/Orm/Linq/Translator.Expressions.cs index 9abfe86672..5f6f4ac0a3 100644 --- a/Orm/Xtensive.Orm/Orm/Linq/Translator.Expressions.cs +++ b/Orm/Xtensive.Orm/Orm/Linq/Translator.Expressions.cs @@ -1,4 +1,4 @@ -// Copyright (C) 2009-2020 Xtensive LLC. +// Copyright (C) 2009-2021 Xtensive LLC. // This code is distributed under MIT license terms. // See the License.txt file in the project root for more information. // Created by: Alexis Kochetov @@ -207,6 +207,35 @@ protected override Expression VisitBinary(BinaryExpression binaryExpression) right = Visit(binaryExpression.Right); } } + else if (EnumRewritableOperations(binaryExpression)) { + // Following two checks for enums are here to improve result query + // performance because they let not to cast columns to integer. + var leftNoCasts = binaryExpression.Left.StripCasts(); + var leftNoCastsType = leftNoCasts.Type; + var bareLeftType = leftNoCastsType.StripNullable(); + var rightNoCasts = binaryExpression.Right.StripCasts(); + var rightNoCastsType = rightNoCasts.Type; + var bareRightType = rightNoCastsType.StripNullable(); + + if (bareLeftType.IsEnum && rightNoCasts.NodeType == ExpressionType.Constant) { + var typeToCast = leftNoCastsType.IsNullable() + ? bareLeftType.GetEnumUnderlyingType().ToNullable() + : leftNoCastsType.GetEnumUnderlyingType(); + left = Visit(Expression.Convert(leftNoCasts, typeToCast)); + right = Visit(Expression.Convert(binaryExpression.Right, typeToCast)); + } + else if (bareRightType.IsEnum && leftNoCasts.NodeType == ExpressionType.Constant) { + var typeToCast = rightNoCastsType.IsNullable() + ? bareRightType.GetEnumUnderlyingType().ToNullable() + : rightNoCastsType.GetEnumUnderlyingType(); + left = Visit(Expression.Convert(rightNoCasts, typeToCast)); + right = Visit(Expression.Convert(binaryExpression.Left, typeToCast)); + } + else { + left = Visit(binaryExpression.Left); + right = Visit(binaryExpression.Right); + } + } else { left = Visit(binaryExpression.Left); right = Visit(binaryExpression.Right); @@ -231,6 +260,14 @@ protected override Expression VisitBinary(BinaryExpression binaryExpression) } return resultBinaryExpression; + + static bool EnumRewritableOperations(BinaryExpression b) + { + var nt = b.NodeType; + return nt == ExpressionType.Equal || nt == ExpressionType.NotEqual + || nt == ExpressionType.GreaterThan || nt == ExpressionType.GreaterThanOrEqual + || nt == ExpressionType.LessThan || nt == ExpressionType.LessThanOrEqual; + } } protected override Expression VisitConditional(ConditionalExpression c)