diff --git a/src/NHibernate.Test/Async/NHSpecificTest/GH1180/FixtureByCode.cs b/src/NHibernate.Test/Async/NHSpecificTest/GH1180/FixtureByCode.cs index baf5bbacdbb..31c755286f4 100644 --- a/src/NHibernate.Test/Async/NHSpecificTest/GH1180/FixtureByCode.cs +++ b/src/NHibernate.Test/Async/NHSpecificTest/GH1180/FixtureByCode.cs @@ -10,13 +10,14 @@ using NHibernate.Cfg.MappingSchema; using NHibernate.Criterion; +using NHibernate.Dialect; using NHibernate.Mapping.ByCode; using NUnit.Framework; namespace NHibernate.Test.NHSpecificTest.GH1180 { using System.Threading.Tasks; - [KnownBug("NH-3847 (GH-1180)")] + //NH-3847 [TestFixture] public class ByCodeFixtureAsync : TestCaseMappingByCode { @@ -27,7 +28,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,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()) { @@ -58,7 +65,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 +73,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 + whenFalse, 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,30 +92,32 @@ public async Task StringTypesAsync() var conditionalProjection = Projections.Conditional( Restrictions.Like(nameof(Entity.Name), "B%"), Projections.Property(nameof(Entity.Name)), - Projections.Constant("other")); + whenFalse); 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"})); } } [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()); } - // 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 +125,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, propertyResult, 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 +144,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, propertyResult, 20.123m})); } } } diff --git a/src/NHibernate.Test/NHSpecificTest/GH1180/FixtureByCode.cs b/src/NHibernate.Test/NHSpecificTest/GH1180/FixtureByCode.cs index a7590840459..59f87a543ca 100644 --- a/src/NHibernate.Test/NHSpecificTest/GH1180/FixtureByCode.cs +++ b/src/NHibernate.Test/NHSpecificTest/GH1180/FixtureByCode.cs @@ -1,11 +1,12 @@ using NHibernate.Cfg.MappingSchema; using NHibernate.Criterion; +using NHibernate.Dialect; using NHibernate.Mapping.ByCode; using NUnit.Framework; namespace NHibernate.Test.NHSpecificTest.GH1180 { - [KnownBug("NH-3847 (GH-1180)")] + //NH-3847 [TestFixture] public class ByCodeFixture : TestCaseMappingByCode { @@ -16,7 +17,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); }); }); @@ -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()) { @@ -47,7 +54,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 +62,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 + whenFalse, 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,30 +81,32 @@ public void StringTypes() var conditionalProjection = Projections.Conditional( Restrictions.Like(nameof(Entity.Name), "B%"), Projections.Property(nameof(Entity.Name)), - Projections.Constant("other")); + whenFalse); 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"})); } } [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(); } - // 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 +114,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, propertyResult, 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 +133,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, propertyResult, 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;