From 75b615d2f712cc6be169e731b574e33de99264d0 Mon Sep 17 00:00:00 2001 From: Roman Artiukhin Date: Mon, 14 Sep 2020 11:10:59 +0300 Subject: [PATCH 1/3] Simplify type check in ConditionalProjection --- .../NHSpecificTest/GH1180/FixtureByCode.cs | 36 ++++++++++--------- .../NHSpecificTest/GH1180/FixtureByCode.cs | 36 ++++++++++--------- .../Criterion/ConditionalProjection.cs | 5 ++- 3 files changed, 40 insertions(+), 37 deletions(-) diff --git a/src/NHibernate.Test/Async/NHSpecificTest/GH1180/FixtureByCode.cs b/src/NHibernate.Test/Async/NHSpecificTest/GH1180/FixtureByCode.cs index baf5bbacdbb..32d7dc50904 100644 --- a/src/NHibernate.Test/Async/NHSpecificTest/GH1180/FixtureByCode.cs +++ b/src/NHibernate.Test/Async/NHSpecificTest/GH1180/FixtureByCode.cs @@ -16,7 +16,7 @@ namespace NHibernate.Test.NHSpecificTest.GH1180 { using System.Threading.Tasks; - [KnownBug("NH-3847 (GH-1180)")] + //NH-3847 (GH-1180) [TestFixture] public class ByCodeFixtureAsync : TestCaseMappingByCode { @@ -27,7 +27,7 @@ protected override HbmMapping GetMappings() mapper.Class(rc => { rc.Id(x => x.Id, m => m.Generator(Generators.GuidComb)); - rc.Property(x => x.Name, m => { m.Length(10); }); + rc.Property(x => x.Name, m => {m.Type(NHibernateUtil.AnsiString); m.Length(5); }); rc.Property(x => x.Amount, m => { m.Precision(8); m.Scale(2); }); }); @@ -58,7 +58,7 @@ public async Task StringTypesAsync() await (transaction.CommitAsync()); } - // whenTrue is constant, whenFalse is property -> works even before the fix + // whenTrue is constant, whenFalse is property using (var session = OpenSession()) { ICriteria tagCriteria = session.CreateCriteria(typeof(Entity)); @@ -66,17 +66,18 @@ public async Task StringTypesAsync() var conditionalProjection = Projections.Conditional( Restrictions.Not( Restrictions.Like(nameof(Entity.Name), "B%")), - Projections.Constant("other"), + //Property - ansi string length 5; contstant - string, length 10 + Projections.Constant("otherstring"), Projections.Property(nameof(Entity.Name))); tagCriteria.SetProjection(conditionalProjection); // run query var results = await (tagCriteria.ListAsync()); - Assert.That(results, Is.EquivalentTo(new[] {"other", "Beta", "other"})); + Assert.That(results, Is.EquivalentTo(new[] {"otherstring", "Beta", "otherstring"})); } - // whenTrue is property, whenFalse is constant -> fails before the fix + // whenTrue is property, whenFalse is constant using (var session = OpenSession()) { ICriteria tagCriteria = session.CreateCriteria(typeof(Entity)); @@ -84,13 +85,13 @@ public async Task StringTypesAsync() var conditionalProjection = Projections.Conditional( Restrictions.Like(nameof(Entity.Name), "B%"), Projections.Property(nameof(Entity.Name)), - Projections.Constant("other")); + Projections.Constant("otherstring")); tagCriteria.SetProjection(conditionalProjection); // run query var results = await (tagCriteria.ListAsync()); - Assert.That(results, Is.EquivalentTo(new[] {"other", "Beta", "other"})); + Assert.That(results, Is.EquivalentTo(new[] {"otherstring", "Beta", "otherstring"})); } } @@ -100,14 +101,14 @@ public async Task DecimalTypesAsync() using (var session = OpenSession()) using (var transaction = session.BeginTransaction()) { - await (session.SaveAsync(new Entity {Amount = 3.14m})); - await (session.SaveAsync(new Entity {Amount = 42.13m})); - await (session.SaveAsync(new Entity {Amount = 17.99m})); + await (session.SaveAsync(new Entity {Amount = 3.141m})); + await (session.SaveAsync(new Entity {Amount = 42.131m})); + await (session.SaveAsync(new Entity {Amount = 17.991m})); await (transaction.CommitAsync()); } - // whenTrue is constant, whenFalse is property -> works even before the fix + // whenTrue is constant, whenFalse is property using (var session = OpenSession()) { ICriteria tagCriteria = session.CreateCriteria(typeof(Entity)); @@ -115,17 +116,18 @@ public async Task DecimalTypesAsync() var conditionalProjection = Projections.Conditional( Restrictions.Not( Restrictions.Ge(nameof(Entity.Amount), 20m)), - Projections.Constant(20m), + //Property scale is 2, make sure constant scale 3 is not lost + Projections.Constant(20.123m), Projections.Property(nameof(Entity.Amount))); tagCriteria.SetProjection(conditionalProjection); // run query var results = await (tagCriteria.ListAsync()); - Assert.That(results, Is.EquivalentTo(new[] {20m, 42.13m, 20m})); + Assert.That(results, Is.EquivalentTo(new[] {20.123m, 42.13m, 20.123m})); } - // whenTrue is property, whenFalse is constant -> fails before the fix + // whenTrue is property, whenFalse is constant using (var session = OpenSession()) { ICriteria tagCriteria = session.CreateCriteria(typeof(Entity)); @@ -133,13 +135,13 @@ public async Task DecimalTypesAsync() var conditionalProjection = Projections.Conditional( Restrictions.Ge(nameof(Entity.Amount), 20m), Projections.Property(nameof(Entity.Amount)), - Projections.Constant(20m)); + Projections.Constant(20.123m)); tagCriteria.SetProjection(conditionalProjection); // run query var results = await (tagCriteria.ListAsync()); - Assert.That(results, Is.EquivalentTo(new[] {20m, 42.13m, 20m})); + Assert.That(results, Is.EquivalentTo(new[] {20.123m, 42.13m, 20.123m})); } } } diff --git a/src/NHibernate.Test/NHSpecificTest/GH1180/FixtureByCode.cs b/src/NHibernate.Test/NHSpecificTest/GH1180/FixtureByCode.cs index a7590840459..fea585a6c9b 100644 --- a/src/NHibernate.Test/NHSpecificTest/GH1180/FixtureByCode.cs +++ b/src/NHibernate.Test/NHSpecificTest/GH1180/FixtureByCode.cs @@ -5,7 +5,7 @@ namespace NHibernate.Test.NHSpecificTest.GH1180 { - [KnownBug("NH-3847 (GH-1180)")] + //NH-3847 (GH-1180) [TestFixture] public class ByCodeFixture : TestCaseMappingByCode { @@ -16,7 +16,7 @@ protected override HbmMapping GetMappings() mapper.Class(rc => { rc.Id(x => x.Id, m => m.Generator(Generators.GuidComb)); - rc.Property(x => x.Name, m => { m.Length(10); }); + rc.Property(x => x.Name, m => {m.Type(NHibernateUtil.AnsiString); m.Length(5); }); rc.Property(x => x.Amount, m => { m.Precision(8); m.Scale(2); }); }); @@ -47,7 +47,7 @@ public void StringTypes() transaction.Commit(); } - // whenTrue is constant, whenFalse is property -> works even before the fix + // whenTrue is constant, whenFalse is property using (var session = OpenSession()) { ICriteria tagCriteria = session.CreateCriteria(typeof(Entity)); @@ -55,17 +55,18 @@ public void StringTypes() var conditionalProjection = Projections.Conditional( Restrictions.Not( Restrictions.Like(nameof(Entity.Name), "B%")), - Projections.Constant("other"), + //Property - ansi string length 5; contstant - string, length 10 + Projections.Constant("otherstring"), Projections.Property(nameof(Entity.Name))); tagCriteria.SetProjection(conditionalProjection); // run query var results = tagCriteria.List(); - Assert.That(results, Is.EquivalentTo(new[] {"other", "Beta", "other"})); + Assert.That(results, Is.EquivalentTo(new[] {"otherstring", "Beta", "otherstring"})); } - // whenTrue is property, whenFalse is constant -> fails before the fix + // whenTrue is property, whenFalse is constant using (var session = OpenSession()) { ICriteria tagCriteria = session.CreateCriteria(typeof(Entity)); @@ -73,13 +74,13 @@ public void StringTypes() var conditionalProjection = Projections.Conditional( Restrictions.Like(nameof(Entity.Name), "B%"), Projections.Property(nameof(Entity.Name)), - Projections.Constant("other")); + Projections.Constant("otherstring")); tagCriteria.SetProjection(conditionalProjection); // run query var results = tagCriteria.List(); - Assert.That(results, Is.EquivalentTo(new[] {"other", "Beta", "other"})); + Assert.That(results, Is.EquivalentTo(new[] {"otherstring", "Beta", "otherstring"})); } } @@ -89,14 +90,14 @@ public void DecimalTypes() using (var session = OpenSession()) using (var transaction = session.BeginTransaction()) { - session.Save(new Entity {Amount = 3.14m}); - session.Save(new Entity {Amount = 42.13m}); - session.Save(new Entity {Amount = 17.99m}); + session.Save(new Entity {Amount = 3.141m}); + session.Save(new Entity {Amount = 42.131m}); + session.Save(new Entity {Amount = 17.991m}); transaction.Commit(); } - // whenTrue is constant, whenFalse is property -> works even before the fix + // whenTrue is constant, whenFalse is property using (var session = OpenSession()) { ICriteria tagCriteria = session.CreateCriteria(typeof(Entity)); @@ -104,17 +105,18 @@ public void DecimalTypes() var conditionalProjection = Projections.Conditional( Restrictions.Not( Restrictions.Ge(nameof(Entity.Amount), 20m)), - Projections.Constant(20m), + //Property scale is 2, make sure constant scale 3 is not lost + Projections.Constant(20.123m), Projections.Property(nameof(Entity.Amount))); tagCriteria.SetProjection(conditionalProjection); // run query var results = tagCriteria.List(); - Assert.That(results, Is.EquivalentTo(new[] {20m, 42.13m, 20m})); + Assert.That(results, Is.EquivalentTo(new[] {20.123m, 42.13m, 20.123m})); } - // whenTrue is property, whenFalse is constant -> fails before the fix + // whenTrue is property, whenFalse is constant using (var session = OpenSession()) { ICriteria tagCriteria = session.CreateCriteria(typeof(Entity)); @@ -122,13 +124,13 @@ public void DecimalTypes() var conditionalProjection = Projections.Conditional( Restrictions.Ge(nameof(Entity.Amount), 20m), Projections.Property(nameof(Entity.Amount)), - Projections.Constant(20m)); + Projections.Constant(20.123m)); tagCriteria.SetProjection(conditionalProjection); // run query var results = tagCriteria.List(); - Assert.That(results, Is.EquivalentTo(new[] {20m, 42.13m, 20m})); + Assert.That(results, Is.EquivalentTo(new[] {20.123m, 42.13m, 20.123m})); } } } diff --git a/src/NHibernate/Criterion/ConditionalProjection.cs b/src/NHibernate/Criterion/ConditionalProjection.cs index 417d67b26ba..1ff3a95a185 100644 --- a/src/NHibernate/Criterion/ConditionalProjection.cs +++ b/src/NHibernate/Criterion/ConditionalProjection.cs @@ -5,7 +5,6 @@ namespace NHibernate.Criterion using Engine; using SqlCommand; using Type; - using Util; [Serializable] public class ConditionalProjection : SimpleProjection @@ -57,11 +56,11 @@ public override IType[] GetTypes(ICriteria criteria, ICriteriaQuery criteriaQuer IType[] falseTypes = whenFalse.GetTypes(criteria, criteriaQuery); bool areEqual = trueTypes.Length == falseTypes.Length; - if (trueTypes.Length == falseTypes.Length) + if (areEqual) { for (int i = 0; i < trueTypes.Length; i++) { - if(trueTypes[i].Equals(falseTypes[i]) == false) + if(trueTypes[i].ReturnedClass != falseTypes[i].ReturnedClass) { areEqual = false; break; From 14c96cbc38f08204957cf1824682c8dbe3e7e59f Mon Sep 17 00:00:00 2001 From: Roman Artiukhin Date: Mon, 14 Sep 2020 12:47:01 +0300 Subject: [PATCH 2/3] Code review and fix SQLite --- .../Async/NHSpecificTest/GH1180/FixtureByCode.cs | 8 ++++---- .../NHSpecificTest/GH1180/FixtureByCode.cs | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/NHibernate.Test/Async/NHSpecificTest/GH1180/FixtureByCode.cs b/src/NHibernate.Test/Async/NHSpecificTest/GH1180/FixtureByCode.cs index 32d7dc50904..89e756ff700 100644 --- a/src/NHibernate.Test/Async/NHSpecificTest/GH1180/FixtureByCode.cs +++ b/src/NHibernate.Test/Async/NHSpecificTest/GH1180/FixtureByCode.cs @@ -16,7 +16,7 @@ namespace NHibernate.Test.NHSpecificTest.GH1180 { using System.Threading.Tasks; - //NH-3847 (GH-1180) + //NH-3847 [TestFixture] public class ByCodeFixtureAsync : TestCaseMappingByCode { @@ -101,9 +101,9 @@ public async Task DecimalTypesAsync() using (var session = OpenSession()) using (var transaction = session.BeginTransaction()) { - await (session.SaveAsync(new Entity {Amount = 3.141m})); - await (session.SaveAsync(new Entity {Amount = 42.131m})); - await (session.SaveAsync(new Entity {Amount = 17.991m})); + await (session.SaveAsync(new Entity {Amount = 3.14m})); + await (session.SaveAsync(new Entity {Amount = 42.13m})); + await (session.SaveAsync(new Entity {Amount = 17.99m})); await (transaction.CommitAsync()); } diff --git a/src/NHibernate.Test/NHSpecificTest/GH1180/FixtureByCode.cs b/src/NHibernate.Test/NHSpecificTest/GH1180/FixtureByCode.cs index fea585a6c9b..7d1a42cf7af 100644 --- a/src/NHibernate.Test/NHSpecificTest/GH1180/FixtureByCode.cs +++ b/src/NHibernate.Test/NHSpecificTest/GH1180/FixtureByCode.cs @@ -5,7 +5,7 @@ namespace NHibernate.Test.NHSpecificTest.GH1180 { - //NH-3847 (GH-1180) + //NH-3847 [TestFixture] public class ByCodeFixture : TestCaseMappingByCode { @@ -90,9 +90,9 @@ public void DecimalTypes() using (var session = OpenSession()) using (var transaction = session.BeginTransaction()) { - session.Save(new Entity {Amount = 3.141m}); - session.Save(new Entity {Amount = 42.131m}); - session.Save(new Entity {Amount = 17.991m}); + session.Save(new Entity {Amount = 3.14m}); + session.Save(new Entity {Amount = 42.13m}); + session.Save(new Entity {Amount = 17.99m}); transaction.Commit(); } From 7756193ef213f7aad67d11f496a05b009289ce9e Mon Sep 17 00:00:00 2001 From: Roman Artiukhin Date: Mon, 14 Sep 2020 19:09:48 +0300 Subject: [PATCH 3/3] Fix tests for Oracle and SQLite --- .../NHSpecificTest/GH1180/FixtureByCode.cs | 23 +++++++++++++------ .../NHSpecificTest/GH1180/FixtureByCode.cs | 23 +++++++++++++------ 2 files changed, 32 insertions(+), 14 deletions(-) diff --git a/src/NHibernate.Test/Async/NHSpecificTest/GH1180/FixtureByCode.cs b/src/NHibernate.Test/Async/NHSpecificTest/GH1180/FixtureByCode.cs index 89e756ff700..31c755286f4 100644 --- a/src/NHibernate.Test/Async/NHSpecificTest/GH1180/FixtureByCode.cs +++ b/src/NHibernate.Test/Async/NHSpecificTest/GH1180/FixtureByCode.cs @@ -10,6 +10,7 @@ using NHibernate.Cfg.MappingSchema; using NHibernate.Criterion; +using NHibernate.Dialect; using NHibernate.Mapping.ByCode; using NUnit.Framework; @@ -47,6 +48,12 @@ protected override void OnTearDown() [Test] public async Task StringTypesAsync() { + var whenFalse = + Dialect is Oracle8iDialect + //Most dialects allow to return DbType.String and DbType.AnsiString in case statement + //But Oracle throws 'ORA-12704: character set mismatch' + ? Projections.Constant("otherstring", NHibernateUtil.AnsiString) + : Projections.Constant("otherstring"); using (var session = OpenSession()) using (var transaction = session.BeginTransaction()) { @@ -67,7 +74,7 @@ public async Task StringTypesAsync() Restrictions.Not( Restrictions.Like(nameof(Entity.Name), "B%")), //Property - ansi string length 5; contstant - string, length 10 - Projections.Constant("otherstring"), + whenFalse, Projections.Property(nameof(Entity.Name))); tagCriteria.SetProjection(conditionalProjection); @@ -85,7 +92,7 @@ public async Task StringTypesAsync() var conditionalProjection = Projections.Conditional( Restrictions.Like(nameof(Entity.Name), "B%"), Projections.Property(nameof(Entity.Name)), - Projections.Constant("otherstring")); + whenFalse); tagCriteria.SetProjection(conditionalProjection); // run query @@ -98,12 +105,14 @@ public async Task StringTypesAsync() [Test] public async Task DecimalTypesAsync() { + //On some dialects (SQLite) Scale mapping is ignored + var propertyResult = TestDialect.HasBrokenDecimalType ? 42.131m : 42.13m; using (var session = OpenSession()) using (var transaction = session.BeginTransaction()) { - await (session.SaveAsync(new Entity {Amount = 3.14m})); - await (session.SaveAsync(new Entity {Amount = 42.13m})); - await (session.SaveAsync(new Entity {Amount = 17.99m})); + await (session.SaveAsync(new Entity {Amount = 3.141m})); + await (session.SaveAsync(new Entity {Amount = 42.131m})); + await (session.SaveAsync(new Entity {Amount = 17.991m})); await (transaction.CommitAsync()); } @@ -124,7 +133,7 @@ public async Task DecimalTypesAsync() // run query var results = await (tagCriteria.ListAsync()); - Assert.That(results, Is.EquivalentTo(new[] {20.123m, 42.13m, 20.123m})); + Assert.That(results, Is.EquivalentTo(new[] {20.123m, propertyResult, 20.123m})); } // whenTrue is property, whenFalse is constant @@ -141,7 +150,7 @@ public async Task DecimalTypesAsync() // run query var results = await (tagCriteria.ListAsync()); - Assert.That(results, Is.EquivalentTo(new[] {20.123m, 42.13m, 20.123m})); + Assert.That(results, Is.EquivalentTo(new[] {20.123m, propertyResult, 20.123m})); } } } diff --git a/src/NHibernate.Test/NHSpecificTest/GH1180/FixtureByCode.cs b/src/NHibernate.Test/NHSpecificTest/GH1180/FixtureByCode.cs index 7d1a42cf7af..59f87a543ca 100644 --- a/src/NHibernate.Test/NHSpecificTest/GH1180/FixtureByCode.cs +++ b/src/NHibernate.Test/NHSpecificTest/GH1180/FixtureByCode.cs @@ -1,5 +1,6 @@ using NHibernate.Cfg.MappingSchema; using NHibernate.Criterion; +using NHibernate.Dialect; using NHibernate.Mapping.ByCode; using NUnit.Framework; @@ -36,6 +37,12 @@ protected override void OnTearDown() [Test] public void StringTypes() { + var whenFalse = + Dialect is Oracle8iDialect + //Most dialects allow to return DbType.String and DbType.AnsiString in case statement + //But Oracle throws 'ORA-12704: character set mismatch' + ? Projections.Constant("otherstring", NHibernateUtil.AnsiString) + : Projections.Constant("otherstring"); using (var session = OpenSession()) using (var transaction = session.BeginTransaction()) { @@ -56,7 +63,7 @@ public void StringTypes() Restrictions.Not( Restrictions.Like(nameof(Entity.Name), "B%")), //Property - ansi string length 5; contstant - string, length 10 - Projections.Constant("otherstring"), + whenFalse, Projections.Property(nameof(Entity.Name))); tagCriteria.SetProjection(conditionalProjection); @@ -74,7 +81,7 @@ public void StringTypes() var conditionalProjection = Projections.Conditional( Restrictions.Like(nameof(Entity.Name), "B%"), Projections.Property(nameof(Entity.Name)), - Projections.Constant("otherstring")); + whenFalse); tagCriteria.SetProjection(conditionalProjection); // run query @@ -87,12 +94,14 @@ public void StringTypes() [Test] public void DecimalTypes() { + //On some dialects (SQLite) Scale mapping is ignored + var propertyResult = TestDialect.HasBrokenDecimalType ? 42.131m : 42.13m; using (var session = OpenSession()) using (var transaction = session.BeginTransaction()) { - session.Save(new Entity {Amount = 3.14m}); - session.Save(new Entity {Amount = 42.13m}); - session.Save(new Entity {Amount = 17.99m}); + session.Save(new Entity {Amount = 3.141m}); + session.Save(new Entity {Amount = 42.131m}); + session.Save(new Entity {Amount = 17.991m}); transaction.Commit(); } @@ -113,7 +122,7 @@ public void DecimalTypes() // run query var results = tagCriteria.List(); - Assert.That(results, Is.EquivalentTo(new[] {20.123m, 42.13m, 20.123m})); + Assert.That(results, Is.EquivalentTo(new[] {20.123m, propertyResult, 20.123m})); } // whenTrue is property, whenFalse is constant @@ -130,7 +139,7 @@ public void DecimalTypes() // run query var results = tagCriteria.List(); - Assert.That(results, Is.EquivalentTo(new[] {20.123m, 42.13m, 20.123m})); + Assert.That(results, Is.EquivalentTo(new[] {20.123m, propertyResult, 20.123m})); } } }