diff --git a/ShowBuildMenu.bat b/ShowBuildMenu.bat index dfa71036ecf..2e7d4e10380 100644 --- a/ShowBuildMenu.bat +++ b/ShowBuildMenu.bat @@ -51,12 +51,14 @@ echo E. Add a test configuration for Oracle. echo F. Add a test configuration for Oracle with managed driver. echo G. Add a test configuration for SQL Server Compact. echo H. Add a test configuration for MySql. +echo I. Add a test configuration for SAP HANA. echo. echo X. Exit to main menu. echo. -%BUILDTOOL% prompt ABCDEFGHX -if errorlevel 8 goto main-menu +%BUILDTOOL% prompt ABCDEFGHIX +if errorlevel 9 goto main-menu +if errorlevel 8 goto test-setup-hana if errorlevel 7 goto test-setup-mysql if errorlevel 6 goto test-setup-sqlserverce if errorlevel 5 goto test-setup-oracle-managed @@ -122,6 +124,13 @@ set LIB_FILES= set LIB_FILES2= goto test-setup-generic +:test-setup-hana +set CONFIG_NAME=HANA +set TEST_PLATFORM=AnyCPU +set LIB_FILES= +set LIB_FILES2= +goto test-setup-generic + :test-setup-generic set CFGNAME= set /p CFGNAME=Enter a name for your test configuration or press enter to use default name: diff --git a/src/NHibernate.Config.Templates/HANA.cfg.xml b/src/NHibernate.Config.Templates/HANA.cfg.xml new file mode 100644 index 00000000000..f2131496105 --- /dev/null +++ b/src/NHibernate.Config.Templates/HANA.cfg.xml @@ -0,0 +1,18 @@ + + + + + NHibernate.Driver.HanaColumnStoreDriver + + + Server=localhost:39015;UserID=nhibernate;Password=; + Enlist=false; + + NHibernate.Dialect.HanaColumnStoreDialect + + diff --git a/src/NHibernate.Test/Ado/GenericBatchingBatcherFixture.cs b/src/NHibernate.Test/Ado/GenericBatchingBatcherFixture.cs index a8b66b34f7e..de94a8f86a8 100644 --- a/src/NHibernate.Test/Ado/GenericBatchingBatcherFixture.cs +++ b/src/NHibernate.Test/Ado/GenericBatchingBatcherFixture.cs @@ -28,7 +28,8 @@ protected override bool AppliesTo(Dialect.Dialect dialect) { return !(dialect is FirebirdDialect) && !(dialect is Oracle8iDialect) && - !(dialect is MsSqlCeDialect); + !(dialect is MsSqlCeDialect) && + !(dialect is HanaDialectBase); } [Test] diff --git a/src/NHibernate.Test/Async/Ado/GenericBatchingBatcherFixture.cs b/src/NHibernate.Test/Async/Ado/GenericBatchingBatcherFixture.cs index 8392263894f..f2889d53c44 100644 --- a/src/NHibernate.Test/Async/Ado/GenericBatchingBatcherFixture.cs +++ b/src/NHibernate.Test/Async/Ado/GenericBatchingBatcherFixture.cs @@ -41,7 +41,8 @@ protected override bool AppliesTo(Dialect.Dialect dialect) { return !(dialect is FirebirdDialect) && !(dialect is Oracle8iDialect) && - !(dialect is MsSqlCeDialect); + !(dialect is MsSqlCeDialect) && + !(dialect is HanaDialectBase); } [Test] diff --git a/src/NHibernate.Test/Async/Criteria/Lambda/IntegrationFixture.cs b/src/NHibernate.Test/Async/Criteria/Lambda/IntegrationFixture.cs index 5e6e76b5884..434563e7856 100644 --- a/src/NHibernate.Test/Async/Criteria/Lambda/IntegrationFixture.cs +++ b/src/NHibernate.Test/Async/Criteria/Lambda/IntegrationFixture.cs @@ -264,6 +264,9 @@ public async Task IsTypeAsync() [Test] public async Task OverrideEagerJoinAsync() { + if (!TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator) + Assert.Ignore("Support of empty inserts is required"); + using (ISession s = OpenSession()) using (ITransaction t = s.BeginTransaction()) { @@ -455,4 +458,4 @@ public async Task StatelessSessionAsync() } } } -} \ No newline at end of file +} diff --git a/src/NHibernate.Test/Async/Events/Collections/AbstractCollectionEventFixture.cs b/src/NHibernate.Test/Async/Events/Collections/AbstractCollectionEventFixture.cs index d5c4a55210b..9f6e691d52c 100644 --- a/src/NHibernate.Test/Async/Events/Collections/AbstractCollectionEventFixture.cs +++ b/src/NHibernate.Test/Async/Events/Collections/AbstractCollectionEventFixture.cs @@ -12,7 +12,6 @@ using System.Collections.Generic; using NHibernate.Collection; using NHibernate.Collection.Generic; -using NHibernate.Event; using NHibernate.Test.Events.Collections.Association.Bidirectional.ManyToMany; using NUnit.Framework; @@ -23,6 +22,11 @@ namespace NHibernate.Test.Events.Collections [TestFixture] public abstract class AbstractCollectionEventFixtureAsync : TestCase { + protected override bool AppliesTo(Dialect.Dialect dialect) + { + return TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator; + } + protected override string MappingsAssembly { get { return "NHibernate.Test"; } diff --git a/src/NHibernate.Test/Async/Generatedkeys/Seqidentity/SequenceIdentityFixture.cs b/src/NHibernate.Test/Async/Generatedkeys/Seqidentity/SequenceIdentityFixture.cs index e753de8f0f7..3a6e766c567 100644 --- a/src/NHibernate.Test/Async/Generatedkeys/Seqidentity/SequenceIdentityFixture.cs +++ b/src/NHibernate.Test/Async/Generatedkeys/Seqidentity/SequenceIdentityFixture.cs @@ -29,7 +29,9 @@ protected override string MappingsAssembly protected override bool AppliesTo(Dialect.Dialect dialect) { - return dialect.SupportsSequences && !(dialect is Dialect.MsSql2012Dialect); + return dialect.SupportsSequences && + !(dialect is Dialect.MsSql2012Dialect) && + !(dialect is Dialect.HanaDialectBase); // SAP HANA does not support a syntax allowing to return the inserted id as an output parameter or a return value } [Test] @@ -49,4 +51,4 @@ public async Task SequenceIdentityGeneratorAsync() session.Close(); } } -} \ No newline at end of file +} diff --git a/src/NHibernate.Test/Async/GenericTest/Overall/Fixture.cs b/src/NHibernate.Test/Async/GenericTest/Overall/Fixture.cs index 9c6cbd4816d..4293af51d2a 100644 --- a/src/NHibernate.Test/Async/GenericTest/Overall/Fixture.cs +++ b/src/NHibernate.Test/Async/GenericTest/Overall/Fixture.cs @@ -53,6 +53,9 @@ public async Task CRUDAsync() [Test] public async Task CRUDABAsync() { + if (!TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator) + Assert.Ignore("Support of empty inserts is required"); + var entity = new A { Property = new B { Prop = 2 }, diff --git a/src/NHibernate.Test/Async/Hql/HQLFunctions.cs b/src/NHibernate.Test/Async/Hql/HQLFunctions.cs index c7212067625..b1f3c6daea4 100644 --- a/src/NHibernate.Test/Async/Hql/HQLFunctions.cs +++ b/src/NHibernate.Test/Async/Hql/HQLFunctions.cs @@ -947,6 +947,13 @@ public async Task CastAsync() throw; } } + else if (Dialect is HanaDialectBase) + { + string msgToCheck = + "not a GROUP BY expression: 'ANIMAL0_.BODYWEIGHT' must be in group by clause"; + if (!ex.InnerException.Message.Contains(msgToCheck)) + throw; + } else { string msgToCheck = @@ -1144,7 +1151,7 @@ public async Task StrAsync() [Test] public async Task IifAsync() { - AssumeFunctionSupported("Iif"); + AssumeFunctionSupported("iif"); using (ISession s = OpenSession()) { await (s.SaveAsync(new MaterialResource("Flash card 512MB", "A001/07", MaterialResource.MaterialState.Available))); diff --git a/src/NHibernate.Test/Async/Insertordering/FamilyModel/Fixture.cs b/src/NHibernate.Test/Async/Insertordering/FamilyModel/Fixture.cs index 44441799c8d..759d0621f85 100644 --- a/src/NHibernate.Test/Async/Insertordering/FamilyModel/Fixture.cs +++ b/src/NHibernate.Test/Async/Insertordering/FamilyModel/Fixture.cs @@ -29,6 +29,11 @@ protected override string MappingsAssembly get { return "NHibernate.Test"; } } + protected override bool AppliesTo(Dialect.Dialect dialect) + { + return TestDialect.SupportsBatchingDependentDML; + } + protected override void Configure(Configuration configuration) { configuration.DataBaseIntegration(x => @@ -105,4 +110,4 @@ public async System.Threading.Tasks.Task CircularReferencesAsync() } } } -} \ No newline at end of file +} diff --git a/src/NHibernate.Test/Async/Legacy/FooBarTest.cs b/src/NHibernate.Test/Async/Legacy/FooBarTest.cs index d148a732bf6..4af220a1377 100644 --- a/src/NHibernate.Test/Async/Legacy/FooBarTest.cs +++ b/src/NHibernate.Test/Async/Legacy/FooBarTest.cs @@ -2490,7 +2490,7 @@ public async Task CollectionsInSelectAsync() // probably the conversion ProxyArray.id (to_number ensuring a not null value) // Indeed, ProxyArray.id is Glarch.tha_key which is a string filled with a Guid. It does // not fail with most engine likely because there are no results thanks to other conditions. - if (!(Dialect is Oracle8iDialect) && !(Dialect is MsSqlCeDialect)) + if (!(Dialect is Oracle8iDialect) && !(Dialect is MsSqlCeDialect) && !(Dialect is HanaDialectBase)) { await (s.CreateQuery( "select count(*) from Bar as bar join bar.Component.Glarch.ProxyArray as g where cast(g.id as Int32) in indices(bar.Baz.FooArray)"). @@ -4103,6 +4103,9 @@ public async Task UpdateOrderAsync() [Test] public async Task UpdateFromTransientAsync() { + if (!TestDialect.SupportsBatchingDependentDML) + Assert.Ignore($"Dialect {Dialect} does not support batching of dependent DML (fee update on related fee)"); + ISession s = OpenSession(); Fee fee1 = new Fee(); await (s.SaveAsync(fee1)); diff --git a/src/NHibernate.Test/Async/Legacy/FumTest.cs b/src/NHibernate.Test/Async/Legacy/FumTest.cs index 779c374d42d..a947a8a1229 100644 --- a/src/NHibernate.Test/Async/Legacy/FumTest.cs +++ b/src/NHibernate.Test/Async/Legacy/FumTest.cs @@ -727,4 +727,4 @@ private ISession SpoofSerialization(ISession session) return (ISession) formatter.Deserialize(stream); } } -} \ No newline at end of file +} diff --git a/src/NHibernate.Test/Async/Legacy/MasterDetailTest.cs b/src/NHibernate.Test/Async/Legacy/MasterDetailTest.cs index 3639e821c88..4482ecdf91d 100644 --- a/src/NHibernate.Test/Async/Legacy/MasterDetailTest.cs +++ b/src/NHibernate.Test/Async/Legacy/MasterDetailTest.cs @@ -52,6 +52,9 @@ protected override IList Mappings [Test] public async Task ParentChildrenAsync() { + if (!TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator) + Assert.Ignore("Support of empty inserts is required"); + ISession session = OpenSession(); M parent = new M(); @@ -842,6 +845,9 @@ public async Task MixNativeAssignedAsync() [Test] public async Task CollectionReplaceOnUpdateAsync() { + if (!TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator) + Assert.Ignore("Support of empty inserts is required"); + ISession s = OpenSession(); ITransaction t = s.BeginTransaction(); Category c = new Category(); @@ -887,6 +893,9 @@ public async Task CollectionReplaceOnUpdateAsync() [Test] public async Task CollectionReplace2Async() { + if (!TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator) + Assert.Ignore("Support of empty inserts is required"); + ISession s = OpenSession(); ITransaction t = s.BeginTransaction(); Category c = new Category(); @@ -926,6 +935,9 @@ public async Task CollectionReplace2Async() [Test] public async Task CollectionReplaceAsync() { + if (!TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator) + Assert.Ignore("Support of empty inserts is required"); + ISession s = OpenSession(); ITransaction t = s.BeginTransaction(); Category c = new Category(); @@ -971,6 +983,9 @@ public async Task CollectionReplaceAsync() [Test] public async Task CategoriesAsync() { + if (!TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator) + Assert.Ignore("Support of empty inserts is required"); + Category c = new Category(); c.Name = Category.RootCategory; Category c1 = new Category(); @@ -1012,6 +1027,9 @@ public async Task CategoriesAsync() [Test] public async Task CollectionRefreshAsync() { + if (!TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator) + Assert.Ignore("Support of empty inserts is required"); + ISession s = OpenSession(); Category c = new Category(); IList list = new List(); @@ -1055,6 +1073,9 @@ public async Task CollectionRefreshAsync() [Test] public async Task CachedCollectionRefreshAsync() { + if (!TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator) + Assert.Ignore("Support of empty inserts is required"); + ISession s = OpenSession(); Category c = new Category(); IList list = new List(); @@ -1240,6 +1261,9 @@ public async Task QueuedBagAddsAsync() [Test] public async Task PolymorphicCriteriaAsync() { + if (!TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator) + Assert.Ignore("Support of empty inserts is required"); + ISession s = OpenSession(); ITransaction txn = s.BeginTransaction(); Category f = new Category(); diff --git a/src/NHibernate.Test/Async/Legacy/MultiTableTest.cs b/src/NHibernate.Test/Async/Legacy/MultiTableTest.cs index 0a2abcd1882..6eed8f4564f 100644 --- a/src/NHibernate.Test/Async/Legacy/MultiTableTest.cs +++ b/src/NHibernate.Test/Async/Legacy/MultiTableTest.cs @@ -148,7 +148,7 @@ public async Task QueriesAsync() ISession s = OpenSession(); long id = 1L; - if (Dialect is MsSql2000Dialect) + if (TestDialect.HasIdentityNativeGenerator) { id = (long) await (s.SaveAsync(new TrivialClass())); } @@ -184,7 +184,7 @@ public async Task ConstraintsAsync() ITransaction t = s.BeginTransaction(); SubMulti sm = new SubMulti(); sm.Amount = 66.5f; - if (Dialect is MsSql2000Dialect) + if (TestDialect.HasIdentityNativeGenerator) { await (s.SaveAsync(sm)); } @@ -215,7 +215,7 @@ public async Task MultiTableAsync() simp.Name = "simp"; object mid; object sid; - if (Dialect is MsSql2000Dialect) + if (TestDialect.HasIdentityNativeGenerator) { mid = await (s.SaveAsync(multi)); sid = await (s.SaveAsync(simp)); @@ -230,7 +230,7 @@ public async Task MultiTableAsync() SubMulti sm = new SubMulti(); sm.Amount = 66.5f; object smid; - if (Dialect is MsSql2000Dialect) + if (TestDialect.HasIdentityNativeGenerator) { smid = await (s.SaveAsync(sm)); } @@ -464,7 +464,7 @@ public async Task MultiTableCollectionsAsync() simp.Name = "simp"; object mid; object sid; - if (Dialect is MsSql2000Dialect) + if (TestDialect.HasIdentityNativeGenerator) { mid = await (s.SaveAsync(multi)); sid = await (s.SaveAsync(simp)); @@ -484,7 +484,7 @@ public async Task MultiTableCollectionsAsync() ls.Set = new HashSet { multi, simp }; object id; - if (Dialect is MsSql2000Dialect) + if (TestDialect.HasIdentityNativeGenerator) { id = await (s.SaveAsync(ls)); } @@ -541,7 +541,7 @@ public async Task MultiTableManyToOneAsync() simp.Name = "simp"; object mid; - if (Dialect is MsSql2000Dialect) + if (TestDialect.HasIdentityNativeGenerator) { mid = await (s.SaveAsync(multi)); } @@ -556,7 +556,7 @@ public async Task MultiTableManyToOneAsync() ls.YetAnother = ls; ls.Name = "Less Simple"; object id; - if (Dialect is MsSql2000Dialect) + if (TestDialect.HasIdentityNativeGenerator) { id = await (s.SaveAsync(ls)); } @@ -602,6 +602,9 @@ public async Task MultiTableNativeIdAsync() [Test] public async Task CollectionAsync() { + if (!TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator) + Assert.Ignore("Support of empty inserts is required"); + ISession s = OpenSession(); ITransaction t = s.BeginTransaction(); Multi multi1 = new Multi(); @@ -701,4 +704,4 @@ public async Task DynamicUpdateAsync() } } } -} \ No newline at end of file +} diff --git a/src/NHibernate.Test/Async/Legacy/ParentChildTest.cs b/src/NHibernate.Test/Async/Legacy/ParentChildTest.cs index 543391b7136..5a6f6b6fd10 100644 --- a/src/NHibernate.Test/Async/Legacy/ParentChildTest.cs +++ b/src/NHibernate.Test/Async/Legacy/ParentChildTest.cs @@ -55,6 +55,9 @@ protected override IList Mappings [Test] public async Task ReplicateAsync() { + if (!TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator) + Assert.Ignore("Support of empty inserts is required"); + ISession s = OpenSession(); Container baz = new Container(); Contained f = new Contained(); @@ -353,6 +356,9 @@ public async Task ClassWhereAsync() [Test] public async Task CollectionQueryAsync() { + if (!TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator) + Assert.Ignore("Support of empty inserts is required"); + ISession s = OpenSession(); ITransaction t = s.BeginTransaction(); @@ -510,6 +516,9 @@ public async Task ParentNullChildAsync() [Test] public async Task ManyToManyAsync() { + if (!TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator) + Assert.Ignore("Support of empty inserts is required"); + // if( dialect is Dialect.HSQLDialect) return; ISession s = OpenSession(); @@ -567,6 +576,9 @@ public async Task ManyToManyAsync() [Test] public async Task ContainerAsync() { + if (!TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator) + Assert.Ignore("Support of empty inserts is required"); + ISession s = OpenSession(); ITransaction t = s.BeginTransaction(); Container c = new Container(); @@ -699,6 +711,9 @@ public async Task ContainerAsync() [Test] public async Task CascadeCompositeElementsAsync() { + if (!TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator) + Assert.Ignore("Support of empty inserts is required"); + Container c = new Container(); c.Cascades = new List(); @@ -760,6 +775,9 @@ public async Task CascadeCompositeElementsAsync() [Test] public async Task BagAsync() { + if (!TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator) + Assert.Ignore("Support of empty inserts is required"); + //if( dialect is Dialect.HSQLDialect ) return; ISession s = OpenSession(); diff --git a/src/NHibernate.Test/Async/Linq/ByMethod/OrderByTests.cs b/src/NHibernate.Test/Async/Linq/ByMethod/OrderByTests.cs index 207f713d47f..9a959e1865b 100644 --- a/src/NHibernate.Test/Async/Linq/ByMethod/OrderByTests.cs +++ b/src/NHibernate.Test/Async/Linq/ByMethod/OrderByTests.cs @@ -72,8 +72,8 @@ orderby c.CustomerId descending [Test] public async Task OrderByCalculatedAggregatedSubselectPropertyAsync() { - if (!Dialect.SupportsScalarSubSelects) - Assert.Ignore("Dialect does not support scalar sub-selects"); + if (!TestDialect.SupportsAggregatingScalarSubSelectsInOrderBy) + Assert.Ignore("Dialect does not support aggregating scalar sub-selects in order by"); //NH-2781 var result = await (db.Orders @@ -93,8 +93,8 @@ public async Task OrderByCalculatedAggregatedSubselectPropertyAsync() [Test] public async Task AggregateAscendingOrderByClauseAsync() { - if (!Dialect.SupportsScalarSubSelects) - Assert.Ignore("Dialect does not support scalar sub-selects"); + if (!TestDialect.SupportsAggregatingScalarSubSelectsInOrderBy) + Assert.Ignore("Dialect does not support aggregating scalar sub-selects in order by"); var query = from c in db.Customers orderby c.Orders.Count @@ -109,8 +109,8 @@ orderby c.Orders.Count [Test] public async Task AggregateDescendingOrderByClauseAsync() { - if (!Dialect.SupportsScalarSubSelects) - Assert.Ignore("Dialect does not support scalar sub-selects"); + if (!TestDialect.SupportsAggregatingScalarSubSelectsInOrderBy) + Assert.Ignore("Dialect does not support aggregating scalar sub-selects in order by"); var query = from c in db.Customers orderby c.Orders.Count descending @@ -191,6 +191,9 @@ public async Task OrderByWithSelfReferencedSubquery1Async() if (!Dialect.SupportsScalarSubSelects) Assert.Ignore("Dialect does not support scalar sub-selects"); + if (!TestDialect.SupportsOrderByAndLimitInSubQueries) + Assert.Ignore("Dialect does not support sub-selects with order by or limit/top"); + if (Dialect is Oracle8iDialect) Assert.Ignore("On Oracle this generates a correlated subquery two levels deep which isn't supported until Oracle 10g."); @@ -209,6 +212,9 @@ public async Task OrderByWithSelfReferencedSubquery2Async() if (!Dialect.SupportsScalarSubSelects) Assert.Ignore("Dialect does not support scalar sub-selects"); + if (!TestDialect.SupportsOrderByAndLimitInSubQueries) + Assert.Ignore("Dialect does not support sub-selects with order by or limit/top"); + if (Dialect is Oracle8iDialect) Assert.Ignore("On Oracle this generates a correlated subquery two levels deep which isn't supported until Oracle 10g."); @@ -251,4 +257,4 @@ public Task OrderByWithSelectDistinctAndTakeAsync() } } } -} \ No newline at end of file +} diff --git a/src/NHibernate.Test/Async/Linq/PropertyMethodMappingTests.cs b/src/NHibernate.Test/Async/Linq/PropertyMethodMappingTests.cs index 9a5d5ec73ba..127593a0ec4 100644 --- a/src/NHibernate.Test/Async/Linq/PropertyMethodMappingTests.cs +++ b/src/NHibernate.Test/Async/Linq/PropertyMethodMappingTests.cs @@ -27,7 +27,7 @@ protected override bool AppliesTo(Dialect.Dialect dialect) public async Task CanExecuteCountInSelectClauseAsync() { var results = await (db.Timesheets - .Select(t => t.Entries.Count).ToListAsync()); + .Select(t => t.Entries.Count).OrderBy(s => s).ToListAsync()); Assert.AreEqual(3, results.Count); Assert.AreEqual(0, results[0]); @@ -44,4 +44,4 @@ public async Task CanExecuteCountInWhereClauseAsync() Assert.AreEqual(2, results.Count); } } -} \ No newline at end of file +} diff --git a/src/NHibernate.Test/Async/Linq/WhereSubqueryTests.cs b/src/NHibernate.Test/Async/Linq/WhereSubqueryTests.cs index 6c980702a96..7ec1685319a 100644 --- a/src/NHibernate.Test/Async/Linq/WhereSubqueryTests.cs +++ b/src/NHibernate.Test/Async/Linq/WhereSubqueryTests.cs @@ -613,6 +613,9 @@ public async Task SubqueryWhereFailingTestAsync() if (!Dialect.SupportsScalarSubSelects) Assert.Ignore(Dialect.GetType().Name + " does not support subquery in select clause"); + if (!TestDialect.SupportsOrderByAndLimitInSubQueries) + Assert.Ignore("Dialect does not support sub-selects with order by or limit/top"); + var list = await ((db.OrderLines .Select(ol => new { @@ -632,6 +635,9 @@ public async Task SubqueryWhereFailingTest2Async() if (!Dialect.SupportsScalarSubSelects) Assert.Ignore(Dialect.GetType().Name + " does not support subquery in select clause"); + if (!TestDialect.SupportsOrderByAndLimitInSubQueries) + Assert.Ignore("Dialect does not support sub-selects with order by or limit/top"); + var list = await (db.OrderLines .Select(ol => new { @@ -651,6 +657,9 @@ public async Task SubqueryWhereFailingTest3Async() if (!Dialect.SupportsScalarSubSelects) Assert.Ignore(Dialect.GetType().Name + " does not support subquery in select clause"); + if (!TestDialect.SupportsOrderByAndLimitInSubQueries) + Assert.Ignore("Dialect does not support sub-selects with order by or limit/top"); + var list = await (db.OrderLines .Select(ol => new { @@ -670,6 +679,9 @@ public async Task ProductsWithSubqueryReturningBoolFirstOrDefaultEqAsync() if (!Dialect.SupportsScalarSubSelects) Assert.Ignore(Dialect.GetType().Name + " does not support scalar sub-queries"); + if (!TestDialect.SupportsOrderByAndLimitInSubQueries) + Assert.Ignore("Dialect does not support sub-selects with order by or limit/top"); + var result = await ((from p in db.Products where (from c in db.Categories where c.Name == "Confections" @@ -687,6 +699,9 @@ public async Task SubselectCanHaveBoolResultAsync() if (!Dialect.SupportsScalarSubSelects) Assert.Ignore(Dialect.GetType().Name + " does not support scalar sub-queries"); + if (!TestDialect.SupportsOrderByAndLimitInSubQueries) + Assert.Ignore("Dialect does not support sub-selects with order by or limit/top"); + var result = await ((from c in db.Categories where c.Products.OrderBy(p => p.ProductId).Select(p => p.Discontinued).FirstOrDefault() == false select c).ToListAsync()); @@ -701,6 +716,9 @@ public async Task ProductsWithSubqueryReturningProjectionBoolFirstOrDefaultEqAsy if (!Dialect.SupportsScalarSubSelects) Assert.Ignore(Dialect.GetType().Name + " does not support scalar sub-queries"); + if (!TestDialect.SupportsOrderByAndLimitInSubQueries) + Assert.Ignore("Dialect does not support sub-selects with order by or limit/top"); + //NH-3190 var result = await ((from p in db.Products where (from c in db.Categories @@ -719,6 +737,9 @@ public async Task ProductsWithSubqueryReturningStringFirstOrDefaultEqAsync() if (!Dialect.SupportsScalarSubSelects) Assert.Ignore(Dialect.GetType().Name + " does not support scalar sub-queries"); + if (!TestDialect.SupportsOrderByAndLimitInSubQueries) + Assert.Ignore("Dialect does not support sub-selects with order by or limit/top"); + var result = await ((from p in db.Products where (from c in db.Categories where c.Name == "Confections" diff --git a/src/NHibernate.Test/Async/NHSpecificTest/CollectionFixture.cs b/src/NHibernate.Test/Async/NHSpecificTest/CollectionFixture.cs index 53b47cad6c5..6f03d76326d 100644 --- a/src/NHibernate.Test/Async/NHSpecificTest/CollectionFixture.cs +++ b/src/NHibernate.Test/Async/NHSpecificTest/CollectionFixture.cs @@ -8,7 +8,6 @@ //------------------------------------------------------------------------------ -using System; using System.Collections; using NHibernate.DomainModel.NHSpecific; using NUnit.Framework; @@ -36,6 +35,11 @@ protected override void OnTearDown() } } + protected override bool AppliesTo(Dialect.Dialect dialect) + { + return TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator; + } + [Test] public async Task TestLoadParentFirstAsync() { @@ -96,4 +100,4 @@ public async Task TestLoadChildFirstAsync() } } } -} \ No newline at end of file +} diff --git a/src/NHibernate.Test/Async/NHSpecificTest/Docs/Associations/BiM21/Fixture.cs b/src/NHibernate.Test/Async/NHSpecificTest/Docs/Associations/BiM21/Fixture.cs index bd04b885705..5da8738d3f0 100644 --- a/src/NHibernate.Test/Async/NHSpecificTest/Docs/Associations/BiM21/Fixture.cs +++ b/src/NHibernate.Test/Async/NHSpecificTest/Docs/Associations/BiM21/Fixture.cs @@ -8,7 +8,6 @@ //------------------------------------------------------------------------------ -using System; using System.Collections; using NUnit.Framework; @@ -28,6 +27,11 @@ protected override IList Mappings get { return new string[] {"NHSpecificTest.Docs.Associations.BiM21.Mappings.hbm.xml"}; } } + protected override bool AppliesTo(Dialect.Dialect dialect) + { + return TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator; + } + [Test] public async Task TestCorrectUseAsync() { @@ -73,4 +77,4 @@ public void TestErrorUsageAsync() } } } -} \ No newline at end of file +} diff --git a/src/NHibernate.Test/Async/NHSpecificTest/Docs/ExampleParentChild/UpdateFixture.cs b/src/NHibernate.Test/Async/NHSpecificTest/Docs/ExampleParentChild/UpdateFixture.cs index 03b397df003..a08fa8b4b13 100644 --- a/src/NHibernate.Test/Async/NHSpecificTest/Docs/ExampleParentChild/UpdateFixture.cs +++ b/src/NHibernate.Test/Async/NHSpecificTest/Docs/ExampleParentChild/UpdateFixture.cs @@ -8,7 +8,6 @@ //------------------------------------------------------------------------------ -using System; using System.Collections; using NUnit.Framework; @@ -28,6 +27,11 @@ protected override IList Mappings get { return new string[] {"NHSpecificTest.Docs.ExampleParentChild.Mappings.hbm.xml"}; } } + protected override bool AppliesTo(Dialect.Dialect dialect) + { + return TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator; + } + [Test] public async Task UpdateAsync() { @@ -64,4 +68,4 @@ public async Task UpdateAsync() } } } -} \ No newline at end of file +} diff --git a/src/NHibernate.Test/Async/NHSpecificTest/GH1565/LockEntityWithOuterJoinTest.cs b/src/NHibernate.Test/Async/NHSpecificTest/GH1565/LockEntityWithOuterJoinTest.cs index 56e189e798f..48d02c3df07 100644 --- a/src/NHibernate.Test/Async/NHSpecificTest/GH1565/LockEntityWithOuterJoinTest.cs +++ b/src/NHibernate.Test/Async/NHSpecificTest/GH1565/LockEntityWithOuterJoinTest.cs @@ -55,5 +55,10 @@ protected override void OnTearDown() session.CreateSQLQuery("delete from MainEntity").ExecuteUpdate(); } } + + protected override bool AppliesTo(Dialect.Dialect dialect) + { + return TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator; + } } } diff --git a/src/NHibernate.Test/Async/NHSpecificTest/LazyLoadBugTest.cs b/src/NHibernate.Test/Async/NHSpecificTest/LazyLoadBugTest.cs index 4c92593e0bf..4c1540df513 100644 --- a/src/NHibernate.Test/Async/NHSpecificTest/LazyLoadBugTest.cs +++ b/src/NHibernate.Test/Async/NHSpecificTest/LazyLoadBugTest.cs @@ -8,7 +8,6 @@ //------------------------------------------------------------------------------ -using System; using System.Collections; using NHibernate.DomainModel.NHSpecific; using NUnit.Framework; @@ -24,6 +23,11 @@ protected override IList Mappings get { return new string[] {"NHSpecific.LazyLoadBug.hbm.xml"}; } } + protected override bool AppliesTo(Dialect.Dialect dialect) + { + return TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator; + } + [Test] public async Task TestLazyLoadAsync() { @@ -102,4 +106,4 @@ public async Task TestLazyLoadNoAddAsync() } } } -} \ No newline at end of file +} diff --git a/src/NHibernate.Test/Async/NHSpecificTest/ListsWithHoles/Fixture.cs b/src/NHibernate.Test/Async/NHSpecificTest/ListsWithHoles/Fixture.cs index a1d00969f4a..160622f9b90 100644 --- a/src/NHibernate.Test/Async/NHSpecificTest/ListsWithHoles/Fixture.cs +++ b/src/NHibernate.Test/Async/NHSpecificTest/ListsWithHoles/Fixture.cs @@ -8,12 +8,6 @@ //------------------------------------------------------------------------------ -using System; -using System.Collections.Generic; -using System.Text; -using log4net.Appender; -using log4net.Core; -using log4net.Repository.Hierarchy; using NUnit.Framework; namespace NHibernate.Test.NHSpecificTest.ListsWithHoles @@ -24,6 +18,10 @@ namespace NHibernate.Test.NHSpecificTest.ListsWithHoles [TestFixture] public class FixtureAsync : TestCase { + protected override bool AppliesTo(Dialect.Dialect dialect) + { + return TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator; + } protected override IList Mappings { diff --git a/src/NHibernate.Test/Async/NHSpecificTest/LoadingNullEntityInSet/Fixture.cs b/src/NHibernate.Test/Async/NHSpecificTest/LoadingNullEntityInSet/Fixture.cs index caf304b69ec..58e5c02b4b0 100644 --- a/src/NHibernate.Test/Async/NHSpecificTest/LoadingNullEntityInSet/Fixture.cs +++ b/src/NHibernate.Test/Async/NHSpecificTest/LoadingNullEntityInSet/Fixture.cs @@ -32,6 +32,11 @@ protected override string MappingsAssembly get { return "NHibernate.Test"; } } + protected override bool AppliesTo(Dialect.Dialect dialect) + { + return TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator; + } + protected override DebugSessionFactory BuildSessionFactory() { cfg.GetCollectionMapping(typeof (Employee).FullName + ".Primaries") diff --git a/src/NHibernate.Test/Async/NHSpecificTest/Logs/LogsFixture.cs b/src/NHibernate.Test/Async/NHSpecificTest/Logs/LogsFixture.cs index 71ada7ac57e..928af230f23 100644 --- a/src/NHibernate.Test/Async/NHSpecificTest/Logs/LogsFixture.cs +++ b/src/NHibernate.Test/Async/NHSpecificTest/Logs/LogsFixture.cs @@ -147,6 +147,11 @@ public async Task WillGetSessionIdFromInterlacedSessionsLogsAsync() [Test] public async Task WillGetSessionIdFromSessionLogsConcurrentAsync() { + if (!TestDialect.SupportsConcurrencyTests) + { + Assert.Ignore($"Dialect {Dialect} does not supports concurrency tests"); + } + GlobalContext.Properties["sessionId"] = new SessionIdCapturer(); // Do not use a ManualResetEventSlim, it does not support async and exhausts the task thread pool in the diff --git a/src/NHibernate.Test/Async/NHSpecificTest/NH1274ExportExclude/NH1274ExportExcludeFixture.cs b/src/NHibernate.Test/Async/NHSpecificTest/NH1274ExportExclude/NH1274ExportExcludeFixture.cs index 66480289864..bb8093267c8 100644 --- a/src/NHibernate.Test/Async/NHSpecificTest/NH1274ExportExclude/NH1274ExportExcludeFixture.cs +++ b/src/NHibernate.Test/Async/NHSpecificTest/NH1274ExportExclude/NH1274ExportExcludeFixture.cs @@ -69,8 +69,8 @@ public async Task SchemaExport_Export_CreatesExportScriptAsync() Assert.IsTrue(s.Contains("drop table Home_All")); } - Assert.IsTrue(s.Contains("create table Home_All")); - Assert.IsTrue(s.Contains("create table Home_Export")); + Assert.That(s, Does.Match("create ((column|row) )?table Home_All")); + Assert.That(s, Does.Match("create ((column|row) )?table Home_Export")); } [Test] @@ -82,8 +82,8 @@ public async Task SchemaExport_Update_CreatesUpdateScriptAsync() await (update.ExecuteAsync(tw.WriteLine, false)); string s = tw.ToString(); - Assert.IsTrue(s.Contains("create table Home_Update")); - Assert.IsTrue(s.Contains("create table Home_All")); + Assert.That(s, Does.Match("create ((column|row) )?table Home_Update")); + Assert.That(s, Does.Match("create ((column|row) )?table Home_All")); } [Test] diff --git a/src/NHibernate.Test/Async/NHSpecificTest/NH1301/Fixture.cs b/src/NHibernate.Test/Async/NHSpecificTest/NH1301/Fixture.cs index 32e7d3b1d68..273ca58ad53 100644 --- a/src/NHibernate.Test/Async/NHSpecificTest/NH1301/Fixture.cs +++ b/src/NHibernate.Test/Async/NHSpecificTest/NH1301/Fixture.cs @@ -21,6 +21,11 @@ public override string BugNumber get { return "NH1301"; } } + protected override bool AppliesTo(Dialect.Dialect dialect) + { + return TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator; + } + [Test] public async Task TestAsync() { diff --git a/src/NHibernate.Test/Async/NHSpecificTest/NH1388/Fixture.cs b/src/NHibernate.Test/Async/NHSpecificTest/NH1388/Fixture.cs index 73bea822439..fe29f63e407 100644 --- a/src/NHibernate.Test/Async/NHSpecificTest/NH1388/Fixture.cs +++ b/src/NHibernate.Test/Async/NHSpecificTest/NH1388/Fixture.cs @@ -18,6 +18,11 @@ namespace NHibernate.Test.NHSpecificTest.NH1388 [TestFixture] public class FixtureAsync : BugTestCase { + protected override bool AppliesTo(Dialect.Dialect dialect) + { + return TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator; + } + [Test] public async Task BagTestAsync() { @@ -110,4 +115,4 @@ protected override string CacheConcurrencyStrategy get { return null; } } } -} \ No newline at end of file +} diff --git a/src/NHibernate.Test/Async/NHSpecificTest/NH1394/Fixture.cs b/src/NHibernate.Test/Async/NHSpecificTest/NH1394/Fixture.cs index 6429fd501f0..641113b1e29 100644 --- a/src/NHibernate.Test/Async/NHSpecificTest/NH1394/Fixture.cs +++ b/src/NHibernate.Test/Async/NHSpecificTest/NH1394/Fixture.cs @@ -85,8 +85,8 @@ public async Task CanOrderByPropertyProjectionAsync() [Test] public async Task CanOrderBySubqueryProjectionAsync() { - if (!Dialect.SupportsScalarSubSelects) - Assert.Ignore(Dialect.GetType().Name + " does not support scalar sub-queries"); + if (!TestDialect.SupportsAggregatingScalarSubSelectsInOrderBy) + Assert.Ignore("Dialect does not support aggregating scalar sub-selects in order by"); using (ISession s = OpenSession()) { @@ -115,8 +115,8 @@ public async Task CanOrderBySubqueryProjectionAsync() [Test] public async Task CanOrderBySubqueryProjectionDescAsync() { - if (!Dialect.SupportsScalarSubSelects) - Assert.Ignore(Dialect.GetType().Name + " does not support scalar sub-queries"); + if (!TestDialect.SupportsAggregatingScalarSubSelectsInOrderBy) + Assert.Ignore("Dialect does not support aggregating scalar sub-selects in order by"); using (ISession s = OpenSession()) { @@ -177,4 +177,4 @@ public async Task CanOrderBySqlProjectionDescAsync() } } } -} \ No newline at end of file +} diff --git a/src/NHibernate.Test/Async/NHSpecificTest/NH1443/Fixture.cs b/src/NHibernate.Test/Async/NHSpecificTest/NH1443/Fixture.cs index ff1267b5d3a..39b677047e1 100644 --- a/src/NHibernate.Test/Async/NHSpecificTest/NH1443/Fixture.cs +++ b/src/NHibernate.Test/Async/NHSpecificTest/NH1443/Fixture.cs @@ -33,7 +33,7 @@ public class FixtureAsync else Assert.That(script, Does.Match("drop table nhibernate.dbo.Aclass")); - Assert.That(script, Does.Match("create table nhibernate.dbo.Aclass")); + Assert.That(script, Does.Match("create ((column|row) )?table nhibernate.dbo.Aclass")); } diff --git a/src/NHibernate.Test/Async/NHSpecificTest/NH1601/Fixture1.cs b/src/NHibernate.Test/Async/NHSpecificTest/NH1601/Fixture1.cs index 06fe6fbf288..d249389ec0a 100644 --- a/src/NHibernate.Test/Async/NHSpecificTest/NH1601/Fixture1.cs +++ b/src/NHibernate.Test/Async/NHSpecificTest/NH1601/Fixture1.cs @@ -8,7 +8,6 @@ //------------------------------------------------------------------------------ -using System.Collections.Generic; using NUnit.Framework; namespace NHibernate.Test.NHSpecificTest.NH1601 @@ -18,6 +17,11 @@ namespace NHibernate.Test.NHSpecificTest.NH1601 [TestFixture] public class Fixture1Async : BugTestCase { + protected override bool AppliesTo(Dialect.Dialect dialect) + { + return TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator; + } + /// /// Loads the project do not call Count on the list assigned. /// diff --git a/src/NHibernate.Test/Async/NHSpecificTest/NH1601/Fixture2.cs b/src/NHibernate.Test/Async/NHSpecificTest/NH1601/Fixture2.cs index 9eae4b87fc6..d5c4d00461b 100644 --- a/src/NHibernate.Test/Async/NHSpecificTest/NH1601/Fixture2.cs +++ b/src/NHibernate.Test/Async/NHSpecificTest/NH1601/Fixture2.cs @@ -8,7 +8,6 @@ //------------------------------------------------------------------------------ -using System.Collections.Generic; using NUnit.Framework; namespace NHibernate.Test.NHSpecificTest.NH1601 @@ -18,6 +17,11 @@ namespace NHibernate.Test.NHSpecificTest.NH1601 [TestFixture] public class Fixture2Async : BugTestCase { + protected override bool AppliesTo(Dialect.Dialect dialect) + { + return TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator; + } + /// /// Loads the project and when Scenario2 and Scenario3 are set calls Count on the list assigned. /// diff --git a/src/NHibernate.Test/Async/NHSpecificTest/NH1609/Fixture.cs b/src/NHibernate.Test/Async/NHSpecificTest/NH1609/Fixture.cs index 403b3d74483..f64a4444dbd 100644 --- a/src/NHibernate.Test/Async/NHSpecificTest/NH1609/Fixture.cs +++ b/src/NHibernate.Test/Async/NHSpecificTest/NH1609/Fixture.cs @@ -83,4 +83,4 @@ public async Task TestAsync() return b; } } -} \ No newline at end of file +} diff --git a/src/NHibernate.Test/Async/NHSpecificTest/NH1691/Fixture.cs b/src/NHibernate.Test/Async/NHSpecificTest/NH1691/Fixture.cs index dae60e7b972..cdc7387a376 100644 --- a/src/NHibernate.Test/Async/NHSpecificTest/NH1691/Fixture.cs +++ b/src/NHibernate.Test/Async/NHSpecificTest/NH1691/Fixture.cs @@ -17,6 +17,11 @@ namespace NHibernate.Test.NHSpecificTest.NH1691 [TestFixture] public class FixtureAsync : BugTestCase { + protected override bool AppliesTo(Dialect.Dialect dialect) + { + return TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator; + } + private static Component GetInitializedComponent() { var component = new Component(); @@ -123,4 +128,4 @@ public async Task NestedComponentCollectionAsync() } } } -} \ No newline at end of file +} diff --git a/src/NHibernate.Test/Async/NHSpecificTest/NH1869/Fixture.cs b/src/NHibernate.Test/Async/NHSpecificTest/NH1869/Fixture.cs index bed8bab3850..0137e1fcc94 100644 --- a/src/NHibernate.Test/Async/NHSpecificTest/NH1869/Fixture.cs +++ b/src/NHibernate.Test/Async/NHSpecificTest/NH1869/Fixture.cs @@ -83,4 +83,4 @@ public async Task TestAsync() } } } -} \ No newline at end of file +} diff --git a/src/NHibernate.Test/Async/NHSpecificTest/NH1914/Fixture.cs b/src/NHibernate.Test/Async/NHSpecificTest/NH1914/Fixture.cs index 053ba28dd26..d6fcf07b29a 100644 --- a/src/NHibernate.Test/Async/NHSpecificTest/NH1914/Fixture.cs +++ b/src/NHibernate.Test/Async/NHSpecificTest/NH1914/Fixture.cs @@ -18,6 +18,10 @@ namespace NHibernate.Test.NHSpecificTest.NH1914 [TestFixture] public class FixtureAsync : BugTestCase { + protected override bool AppliesTo(Dialect.Dialect dialect) + { + return TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator; + } [Test] public async Task CascadeInsertAssignedAsync() diff --git a/src/NHibernate.Test/Async/NHSpecificTest/NH2328/Fixture.cs b/src/NHibernate.Test/Async/NHSpecificTest/NH2328/Fixture.cs index a0b90579258..ecc820d6547 100644 --- a/src/NHibernate.Test/Async/NHSpecificTest/NH2328/Fixture.cs +++ b/src/NHibernate.Test/Async/NHSpecificTest/NH2328/Fixture.cs @@ -9,8 +9,8 @@ using System.Linq; -using NHibernate.Linq; using NUnit.Framework; +using NHibernate.Linq; namespace NHibernate.Test.NHSpecificTest.NH2328 { @@ -18,6 +18,11 @@ namespace NHibernate.Test.NHSpecificTest.NH2328 [TestFixture] public class FixtureAsync : BugTestCase { + protected override bool AppliesTo(Dialect.Dialect dialect) + { + return TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator; + } + protected override void OnSetUp() { base.OnSetUp(); @@ -109,4 +114,4 @@ public async Task AnyIs_HqlWorksWithClassNameInTheLeftAsync() } } } -} \ No newline at end of file +} diff --git a/src/NHibernate.Test/Async/NHSpecificTest/NH2409/Fixture.cs b/src/NHibernate.Test/Async/NHSpecificTest/NH2409/Fixture.cs index 3c2b8f2e190..4318e325157 100644 --- a/src/NHibernate.Test/Async/NHSpecificTest/NH2409/Fixture.cs +++ b/src/NHibernate.Test/Async/NHSpecificTest/NH2409/Fixture.cs @@ -8,7 +8,6 @@ //------------------------------------------------------------------------------ -using System; using System.Linq; using NHibernate.Criterion; using NHibernate.SqlCommand; @@ -20,6 +19,11 @@ namespace NHibernate.Test.NHSpecificTest.NH2409 [TestFixture] public class FixtureAsync : BugTestCase { + protected override bool AppliesTo(Dialect.Dialect dialect) + { + return TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator; + } + [Test] public async Task BugAsync() { diff --git a/src/NHibernate.Test/Async/NHSpecificTest/NH2703/Fixture.cs b/src/NHibernate.Test/Async/NHSpecificTest/NH2703/Fixture.cs index 011d0b4c6ec..43e122587e8 100644 --- a/src/NHibernate.Test/Async/NHSpecificTest/NH2703/Fixture.cs +++ b/src/NHibernate.Test/Async/NHSpecificTest/NH2703/Fixture.cs @@ -18,6 +18,11 @@ public class FixtureAsync : BugTestCase { Parent RootElement = null; + protected override bool AppliesTo(Dialect.Dialect dialect) + { + return TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator; + } + protected override void OnSetUp() { using (ISession session = Sfi.OpenSession()) diff --git a/src/NHibernate.Test/Async/NHSpecificTest/NH2705/Test.cs b/src/NHibernate.Test/Async/NHSpecificTest/NH2705/Test.cs index 6159e3b0515..f81135448a8 100644 --- a/src/NHibernate.Test/Async/NHSpecificTest/NH2705/Test.cs +++ b/src/NHibernate.Test/Async/NHSpecificTest/NH2705/Test.cs @@ -94,4 +94,4 @@ public void LinqQueryWithFetch_WhenDerivedClassesUseComponentAndEagerFetchManyTo } } } -} \ No newline at end of file +} diff --git a/src/NHibernate.Test/Async/NHSpecificTest/NH2760/Fixture.cs b/src/NHibernate.Test/Async/NHSpecificTest/NH2760/Fixture.cs index c56740a391d..8c5a23a67ec 100644 --- a/src/NHibernate.Test/Async/NHSpecificTest/NH2760/Fixture.cs +++ b/src/NHibernate.Test/Async/NHSpecificTest/NH2760/Fixture.cs @@ -68,6 +68,9 @@ protected override void OnTearDown() [Test] public async Task ShouldBeAbleToSelectUserGroupAndOrderByUserCountAsync() { + if (!TestDialect.SupportsAggregatingScalarSubSelectsInOrderBy) + Assert.Ignore("Dialect does not support aggregating scalar sub-selects in order by"); + using (ISession session = base.OpenSession()) using (ITransaction transaction = session.BeginTransaction()) { @@ -136,6 +139,9 @@ from ug in session.Query() [Test] public async Task ShouldBeAbleToSelectUserGroupAndOrderByUserCountWithHqlAsync() { + if (!TestDialect.SupportsAggregatingScalarSubSelectsInOrderBy) + Assert.Ignore("Dialect does not support aggregating scalar sub-selects in order by"); + using (ISession session = base.OpenSession()) using (ITransaction transaction = session.BeginTransaction()) { @@ -151,4 +157,4 @@ public async Task ShouldBeAbleToSelectUserGroupAndOrderByUserCountWithHqlAsync() } } } -} \ No newline at end of file +} diff --git a/src/NHibernate.Test/Async/NHSpecificTest/NH280/Fixture.cs b/src/NHibernate.Test/Async/NHSpecificTest/NH280/Fixture.cs index b91759d98e4..28733b03c12 100644 --- a/src/NHibernate.Test/Async/NHSpecificTest/NH280/Fixture.cs +++ b/src/NHibernate.Test/Async/NHSpecificTest/NH280/Fixture.cs @@ -37,16 +37,21 @@ public async Task ConstInSelectAsync() await (s.SaveAsync(f)); await (s.FlushAsync()); - IList l = await (s.CreateQuery("select 'TextConst', 123, 123.5, .5 from Foo").ListAsync()); - IList result = l[0] as IList; - Assert.AreEqual(typeof(string), result[0].GetType()); - Assert.AreEqual(typeof(Int32), result[1].GetType()); - Assert.AreEqual(typeof(Double), result[2].GetType()); - Assert.AreEqual(typeof(Double), result[3].GetType()); - Assert.AreEqual("TextConst", result[0]); - Assert.AreEqual(123, result[1]); - Assert.AreEqual(123.5D, result[2]); - Assert.AreEqual(0.5D, result[3]); + IList l; + IList result; + if (TestDialect.SupportsSelectingDoubleLiteral) + { + l = await (s.CreateQuery("select 'TextConst', 123, 123.5, .5 from Foo").ListAsync()); + result = l[0] as IList; + Assert.AreEqual(typeof(string), result[0].GetType()); + Assert.AreEqual(typeof(Int32), result[1].GetType()); + Assert.AreEqual(typeof(Double), result[2].GetType()); + Assert.AreEqual(typeof(Double), result[3].GetType()); + Assert.AreEqual("TextConst", result[0]); + Assert.AreEqual(123, result[1]); + Assert.AreEqual(123.5D, result[2]); + Assert.AreEqual(0.5D, result[3]); + } l = await (s.CreateQuery("select 123, f from Foo f").ListAsync()); result = l[0] as IList; diff --git a/src/NHibernate.Test/Async/NHSpecificTest/NH3141/ProxyIdFixture.cs b/src/NHibernate.Test/Async/NHSpecificTest/NH3141/ProxyIdFixture.cs index 122f3a27e82..933db3dc476 100644 --- a/src/NHibernate.Test/Async/NHSpecificTest/NH3141/ProxyIdFixture.cs +++ b/src/NHibernate.Test/Async/NHSpecificTest/NH3141/ProxyIdFixture.cs @@ -21,6 +21,11 @@ public class ProxyIdFixtureAsync : BugTestCase { private int id; + protected override bool AppliesTo(Dialect.Dialect dialect) + { + return TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator; + } + protected override void OnSetUp() { using (var s = OpenSession()) diff --git a/src/NHibernate.Test/Async/NHSpecificTest/NH315/Fixture.cs b/src/NHibernate.Test/Async/NHSpecificTest/NH315/Fixture.cs index a4b7caf3376..67d731e834d 100644 --- a/src/NHibernate.Test/Async/NHSpecificTest/NH315/Fixture.cs +++ b/src/NHibernate.Test/Async/NHSpecificTest/NH315/Fixture.cs @@ -25,6 +25,11 @@ public override string BugNumber get { return "NH315"; } } + protected override bool AppliesTo(Dialect.Dialect dialect) + { + return TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator; + } + [Test] public async Task SaveClientAsync() { @@ -54,4 +59,4 @@ public async Task SaveClientAsync() } } } -} \ No newline at end of file +} diff --git a/src/NHibernate.Test/Async/NHSpecificTest/NH3414/FixtureByCode.cs b/src/NHibernate.Test/Async/NHSpecificTest/NH3414/FixtureByCode.cs index e507d77fd62..51eae05506e 100644 --- a/src/NHibernate.Test/Async/NHSpecificTest/NH3414/FixtureByCode.cs +++ b/src/NHibernate.Test/Async/NHSpecificTest/NH3414/FixtureByCode.cs @@ -23,7 +23,7 @@ public class ByCodeFixtureAsync : TestCaseMappingByCode protected override bool AppliesTo(Dialect.Dialect dialect) { // Test ordering by a scalar sub-select. - return Dialect.SupportsScalarSubSelects; + return TestDialect.SupportsAggregatingScalarSubSelectsInOrderBy; } protected override HbmMapping GetMappings() diff --git a/src/NHibernate.Test/Async/NHSpecificTest/NH386/Fixture.cs b/src/NHibernate.Test/Async/NHSpecificTest/NH386/Fixture.cs index 5c40c9f04c6..96f71b7d62d 100644 --- a/src/NHibernate.Test/Async/NHSpecificTest/NH386/Fixture.cs +++ b/src/NHibernate.Test/Async/NHSpecificTest/NH386/Fixture.cs @@ -32,4 +32,4 @@ public async Task QueryAsync() } } } -} \ No newline at end of file +} diff --git a/src/NHibernate.Test/Async/NHSpecificTest/NH440/Fixture.cs b/src/NHibernate.Test/Async/NHSpecificTest/NH440/Fixture.cs index 105576c0948..3bec8c77eec 100644 --- a/src/NHibernate.Test/Async/NHSpecificTest/NH440/Fixture.cs +++ b/src/NHibernate.Test/Async/NHSpecificTest/NH440/Fixture.cs @@ -8,7 +8,6 @@ //------------------------------------------------------------------------------ -using System; using System.Collections; using NUnit.Framework; @@ -32,6 +31,11 @@ protected override IList Mappings get { return new string[] {"NHSpecificTest.NH440.Fruit.hbm.xml", "NHSpecificTest.NH440.Apple.hbm.xml"}; } } + protected override bool AppliesTo(Dialect.Dialect dialect) + { + return TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator; + } + protected override void OnSetUp() { @@ -150,4 +154,4 @@ public async Task StoreWithLinksAndLookupWithQueryFromFruitAsync() } } } -} \ No newline at end of file +} diff --git a/src/NHibernate.Test/Async/NHSpecificTest/NH473/Fixture.cs b/src/NHibernate.Test/Async/NHSpecificTest/NH473/Fixture.cs index de8d562a02e..cb8c96d7c6e 100644 --- a/src/NHibernate.Test/Async/NHSpecificTest/NH473/Fixture.cs +++ b/src/NHibernate.Test/Async/NHSpecificTest/NH473/Fixture.cs @@ -8,9 +8,6 @@ //------------------------------------------------------------------------------ -using System; -using System.Collections.Generic; -using System.Text; using NUnit.Framework; namespace NHibernate.Test.NHSpecificTest.NH473 @@ -19,6 +16,11 @@ namespace NHibernate.Test.NHSpecificTest.NH473 [TestFixture] public class FixtureAsync:BugTestCase { + protected override bool AppliesTo(Dialect.Dialect dialect) + { + return TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator; + } + protected override void OnSetUp() { using(var session=this.OpenSession()) diff --git a/src/NHibernate.Test/Async/NHSpecificTest/NH479/Fixture.cs b/src/NHibernate.Test/Async/NHSpecificTest/NH479/Fixture.cs index 444737bc6b8..4888f4a7c7a 100644 --- a/src/NHibernate.Test/Async/NHSpecificTest/NH479/Fixture.cs +++ b/src/NHibernate.Test/Async/NHSpecificTest/NH479/Fixture.cs @@ -8,7 +8,6 @@ //------------------------------------------------------------------------------ -using System; using NUnit.Framework; namespace NHibernate.Test.NHSpecificTest.NH479 @@ -22,6 +21,11 @@ public override string BugNumber get { return "NH479"; } } + protected override bool AppliesTo(Dialect.Dialect dialect) + { + return TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator; + } + [Test] public async Task MergeTestAsync() { @@ -57,4 +61,4 @@ public async Task MergeTestAsync() } } } -} \ No newline at end of file +} diff --git a/src/NHibernate.Test/Async/NHSpecificTest/NH521/Fixture.cs b/src/NHibernate.Test/Async/NHSpecificTest/NH521/Fixture.cs index 37f17159a17..0c2e46b13d1 100644 --- a/src/NHibernate.Test/Async/NHSpecificTest/NH521/Fixture.cs +++ b/src/NHibernate.Test/Async/NHSpecificTest/NH521/Fixture.cs @@ -21,6 +21,11 @@ public override string BugNumber get { return "NH521"; } } + protected override bool AppliesTo(Dialect.Dialect dialect) + { + return TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator; + } + [Test] public async Task AttachUninitProxyCausesInitAsync() { @@ -68,4 +73,4 @@ public async Task AttachUninitProxyCausesInitAsync() } } } -} \ No newline at end of file +} diff --git a/src/NHibernate.Test/Async/NHSpecificTest/NH607/Fixture.cs b/src/NHibernate.Test/Async/NHSpecificTest/NH607/Fixture.cs index ea368b7749b..553ba575773 100644 --- a/src/NHibernate.Test/Async/NHSpecificTest/NH607/Fixture.cs +++ b/src/NHibernate.Test/Async/NHSpecificTest/NH607/Fixture.cs @@ -8,7 +8,6 @@ //------------------------------------------------------------------------------ -using System; using NUnit.Framework; namespace NHibernate.Test.NHSpecificTest.NH607 @@ -22,6 +21,11 @@ public override string BugNumber get { return "NH607"; } } + protected override bool AppliesTo(Dialect.Dialect dialect) + { + return TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator; + } + [Test] public async Task TestAsync() { @@ -54,4 +58,4 @@ public async Task TestAsync() } } } -} \ No newline at end of file +} diff --git a/src/NHibernate.Test/Async/NHSpecificTest/NH623/Fixture.cs b/src/NHibernate.Test/Async/NHSpecificTest/NH623/Fixture.cs index 1bf9b24000e..b570712dbdd 100644 --- a/src/NHibernate.Test/Async/NHSpecificTest/NH623/Fixture.cs +++ b/src/NHibernate.Test/Async/NHSpecificTest/NH623/Fixture.cs @@ -10,6 +10,7 @@ using System; using System.Collections; +using NHibernate.Dialect; using NUnit.Framework; namespace NHibernate.Test.NHSpecificTest.NH623 @@ -23,6 +24,11 @@ public override string BugNumber get { return "NH623"; } } + protected override bool AppliesTo(Dialect.Dialect dialect) + { + return !(dialect is HanaDialectBase); // The WHERE clause "isactive = '1'" doesn't work on HANA because idactive is a boolean + } + private ISession session; private ITransaction tran; @@ -82,4 +88,4 @@ public async Task WhereAttributesOnBagsAsync() Assert.AreEqual(1, d.Pages.Count); } } -} \ No newline at end of file +} diff --git a/src/NHibernate.Test/Async/NHSpecificTest/NH643/Fixture.cs b/src/NHibernate.Test/Async/NHSpecificTest/NH643/Fixture.cs index 89165be75f2..9edf70f29c1 100644 --- a/src/NHibernate.Test/Async/NHSpecificTest/NH643/Fixture.cs +++ b/src/NHibernate.Test/Async/NHSpecificTest/NH643/Fixture.cs @@ -8,7 +8,6 @@ //------------------------------------------------------------------------------ -using System; using NUnit.Framework; namespace NHibernate.Test.NHSpecificTest.NH643 @@ -23,6 +22,11 @@ public override string BugNumber get { return "NH643"; } } + protected override bool AppliesTo(Dialect.Dialect dialect) + { + return TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator; + } + private object parentId; [Test] @@ -84,4 +88,4 @@ public async Task CacheAndLazyCollectionsAsync() } } } -} \ No newline at end of file +} diff --git a/src/NHibernate.Test/Async/NHSpecificTest/NH687/Fixture.cs b/src/NHibernate.Test/Async/NHSpecificTest/NH687/Fixture.cs index 23395ae2d78..413e8b3759a 100644 --- a/src/NHibernate.Test/Async/NHSpecificTest/NH687/Fixture.cs +++ b/src/NHibernate.Test/Async/NHSpecificTest/NH687/Fixture.cs @@ -8,7 +8,6 @@ //------------------------------------------------------------------------------ -using System; using NUnit.Framework; namespace NHibernate.Test.NHSpecificTest.NH687 @@ -22,6 +21,11 @@ public override string BugNumber get { return "NH687"; } } + protected override bool AppliesTo(Dialect.Dialect dialect) + { + return TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator; + } + [Test] public async Task GetQueryTestAsync() { diff --git a/src/NHibernate.Test/Async/NHSpecificTest/NH704/Fixture.cs b/src/NHibernate.Test/Async/NHSpecificTest/NH704/Fixture.cs index 7b9a60e7115..a29d68852c0 100644 --- a/src/NHibernate.Test/Async/NHSpecificTest/NH704/Fixture.cs +++ b/src/NHibernate.Test/Async/NHSpecificTest/NH704/Fixture.cs @@ -8,7 +8,6 @@ //------------------------------------------------------------------------------ -using System; using NUnit.Framework; namespace NHibernate.Test.NHSpecificTest.NH704 @@ -22,6 +21,11 @@ public override string BugNumber get { return "NH704"; } } + protected override bool AppliesTo(Dialect.Dialect dialect) + { + return TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator; + } + [Test] public async Task ReAttachCatTestAsync() { @@ -46,4 +50,4 @@ public async Task ReAttachCatTestAsync() } } } -} \ No newline at end of file +} diff --git a/src/NHibernate.Test/Async/NHSpecificTest/NH826/Fixture.cs b/src/NHibernate.Test/Async/NHSpecificTest/NH826/Fixture.cs index 9670b8e1e80..9acffe78e89 100644 --- a/src/NHibernate.Test/Async/NHSpecificTest/NH826/Fixture.cs +++ b/src/NHibernate.Test/Async/NHSpecificTest/NH826/Fixture.cs @@ -17,6 +17,11 @@ namespace NHibernate.Test.NHSpecificTest.NH826 [TestFixture] public class FixtureAsync : BugTestCase { + protected override bool AppliesTo(Dialect.Dialect dialect) + { + return TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator; + } + [Test] public async Task BugAsync() { @@ -59,4 +64,4 @@ public async Task BugAsync() session.Close(); } } -} \ No newline at end of file +} diff --git a/src/NHibernate.Test/Async/NHSpecificTest/NH830/AutoFlushTestFixture.cs b/src/NHibernate.Test/Async/NHSpecificTest/NH830/AutoFlushTestFixture.cs index afa5931b2f2..f0d9984e77c 100644 --- a/src/NHibernate.Test/Async/NHSpecificTest/NH830/AutoFlushTestFixture.cs +++ b/src/NHibernate.Test/Async/NHSpecificTest/NH830/AutoFlushTestFixture.cs @@ -18,6 +18,11 @@ namespace NHibernate.Test.NHSpecificTest.NH830 [TestFixture] public class AutoFlushTestFixtureAsync : BugTestCase { + protected override bool AppliesTo(Dialect.Dialect dialect) + { + return TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator; + } + [Test] public async Task AutoFlushTestAsync() { @@ -50,4 +55,4 @@ public async Task AutoFlushTestAsync() sess.Close(); } } -} \ No newline at end of file +} diff --git a/src/NHibernate.Test/Async/NHSpecificTest/NH898/NH898Fixture.cs b/src/NHibernate.Test/Async/NHSpecificTest/NH898/NH898Fixture.cs index 0b385e8f0ea..e30e7c6bb37 100644 --- a/src/NHibernate.Test/Async/NHSpecificTest/NH898/NH898Fixture.cs +++ b/src/NHibernate.Test/Async/NHSpecificTest/NH898/NH898Fixture.cs @@ -10,7 +10,6 @@ using System; using System.Collections; - using NUnit.Framework; namespace NHibernate.Test.NHSpecificTest.NH898 @@ -33,6 +32,11 @@ protected override IList Mappings } } + protected override bool AppliesTo(Dialect.Dialect dialect) + { + return TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator; + } + [Test] public async Task BugAsync() { diff --git a/src/NHibernate.Test/Async/NHSpecificTest/Properties/CompositePropertyRefTest.cs b/src/NHibernate.Test/Async/NHSpecificTest/Properties/CompositePropertyRefTest.cs index 35d73040c17..31de09b83e7 100644 --- a/src/NHibernate.Test/Async/NHSpecificTest/Properties/CompositePropertyRefTest.cs +++ b/src/NHibernate.Test/Async/NHSpecificTest/Properties/CompositePropertyRefTest.cs @@ -21,6 +21,11 @@ public class CompositePropertyRefTestAsync : BugTestCase private long p_id; private long p2_id; + protected override bool AppliesTo(Dialect.Dialect dialect) + { + return TestDialect.SupportsFKOnCompositeKeyWithBoolean; + } + protected override void OnSetUp() { using (var s = OpenSession()) diff --git a/src/NHibernate.Test/Async/NHSpecificTest/Properties/DynamicEntityTest.cs b/src/NHibernate.Test/Async/NHSpecificTest/Properties/DynamicEntityTest.cs index 90fa8b3a468..21c46451346 100644 --- a/src/NHibernate.Test/Async/NHSpecificTest/Properties/DynamicEntityTest.cs +++ b/src/NHibernate.Test/Async/NHSpecificTest/Properties/DynamicEntityTest.cs @@ -18,6 +18,11 @@ namespace NHibernate.Test.NHSpecificTest.Properties [TestFixture] public class DynamicEntityTestAsync : BugTestCase { + protected override bool AppliesTo(Dialect.Dialect dialect) + { + return TestDialect.SupportsFKOnCompositeKeyWithBoolean; + } + protected override void OnSetUp() { using (var s = OpenSession()) diff --git a/src/NHibernate.Test/Async/Operations/MergeFixture.cs b/src/NHibernate.Test/Async/Operations/MergeFixture.cs index f8864afcde5..125950bd47d 100644 --- a/src/NHibernate.Test/Async/Operations/MergeFixture.cs +++ b/src/NHibernate.Test/Async/Operations/MergeFixture.cs @@ -399,6 +399,9 @@ public async Task MergeManagedAsync() [Test] public async Task MergeManyToManyWithCollectionDeferenceAsync() { + if (!TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator) + Assert.Ignore("Support of empty inserts is required"); + // setup base data... Competition competition; using (ISession s = OpenSession()) @@ -823,6 +826,9 @@ public async Task PersistThenMergeInSameTxnWithVersionAsync() [Test] public async Task RecursiveMergeTransientAsync() { + if (!TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator) + Assert.Ignore("Support of empty inserts is required"); + using (ISession s = OpenSession()) { using (ITransaction tx = s.BeginTransaction()) diff --git a/src/NHibernate.Test/Async/Stateless/StatelessSessionQueryFixture.cs b/src/NHibernate.Test/Async/Stateless/StatelessSessionQueryFixture.cs index 817c41bc38e..8a25d5c7ef4 100644 --- a/src/NHibernate.Test/Async/Stateless/StatelessSessionQueryFixture.cs +++ b/src/NHibernate.Test/Async/Stateless/StatelessSessionQueryFixture.cs @@ -35,6 +35,11 @@ protected override void Configure(Configuration configuration) cfg.SetProperty(Environment.MaxFetchDepth, 1.ToString()); } + protected override bool AppliesTo(Dialect.Dialect dialect) + { + return TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator; + } + private class TestData { internal readonly IList list = new ArrayList(); @@ -127,4 +132,4 @@ public async Task HqlAsync() await (testData.cleanDataAsync()); } } -} \ No newline at end of file +} diff --git a/src/NHibernate.Test/Async/SystemTransactions/SystemTransactionFixture.cs b/src/NHibernate.Test/Async/SystemTransactions/SystemTransactionFixture.cs index c9dc337df13..ff3ea86958f 100644 --- a/src/NHibernate.Test/Async/SystemTransactions/SystemTransactionFixture.cs +++ b/src/NHibernate.Test/Async/SystemTransactions/SystemTransactionFixture.cs @@ -190,8 +190,14 @@ public async Task CanUseSessionWithManyScopesAsync(bool explicitFlush) // ODBC with SQL-Server always causes scopes to go distributed, which causes their transaction completion to run // asynchronously. But ODBC enlistment also check the previous transaction in a way that do not guard against it // being concurrently disposed of. See https://github.com/nhibernate/nhibernate-core/pull/1505 for more details. - Assume.That(!(Sfi.ConnectionProvider.Driver is OdbcDriver), - "ODBC sometimes fails on second scope by checking the previous transaction status, which may yield an object disposed exception"); + if (Sfi.ConnectionProvider.Driver is OdbcDriver) + Assert.Ignore("ODBC sometimes fails on second scope by checking the previous transaction status, which may yield an object disposed exception"); + // SAP HANA .Net provider always causes system transactions to be distributed, causing them to complete + // on concurrent threads. This creates race conditions when chaining scopes, the subsequent scope usage + // finding the connection still enlisted in the previous transaction, its complete being still not finished + // on its own thread. + if (Sfi.ConnectionProvider.Driver is HanaDriverBase) + Assert.Ignore("SAP HANA scope handling causes concurrency issues preventing chaining scope usages."); using (var s = WithOptions().ConnectionReleaseMode(ConnectionReleaseMode.OnClose).OpenSession()) { diff --git a/src/NHibernate.Test/Criteria/Lambda/IntegrationFixture.cs b/src/NHibernate.Test/Criteria/Lambda/IntegrationFixture.cs index 9dac8b5ea81..6adbb11f0b1 100644 --- a/src/NHibernate.Test/Criteria/Lambda/IntegrationFixture.cs +++ b/src/NHibernate.Test/Criteria/Lambda/IntegrationFixture.cs @@ -252,6 +252,9 @@ public void IsType() [Test] public void OverrideEagerJoin() { + if (!TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator) + Assert.Ignore("Support of empty inserts is required"); + using (ISession s = OpenSession()) using (ITransaction t = s.BeginTransaction()) { @@ -443,4 +446,4 @@ public void StatelessSession() } } } -} \ No newline at end of file +} diff --git a/src/NHibernate.Test/DialectTest/FunctionTests/SubstringSupportFixture.cs b/src/NHibernate.Test/DialectTest/FunctionTests/SubstringSupportFixture.cs index a2361535c1f..8644493b502 100644 --- a/src/NHibernate.Test/DialectTest/FunctionTests/SubstringSupportFixture.cs +++ b/src/NHibernate.Test/DialectTest/FunctionTests/SubstringSupportFixture.cs @@ -34,18 +34,28 @@ public void DialectShouldUseCorrectSubstringImplementation(System.Type dialectTy var substringFunction = dialect.Functions["substring"]; - if (dialect is MsSql2000Dialect || dialect is MsSqlCeDialect || dialect is SybaseASE15Dialect) - Assert.That(substringFunction, Is.TypeOf()); - else if (dialect is DB2Dialect) - Assert.That(substringFunction, Is.TypeOf()); - else if (dialect is SybaseSQLAnywhere10Dialect) - Assert.That(substringFunction, Is.TypeOf()); - else if (dialect is Oracle8iDialect) - Assert.That(substringFunction, Is.TypeOf()); - else if (dialect is SQLiteDialect) - Assert.That(substringFunction, Is.TypeOf()); - else - Assert.That(substringFunction, Is.TypeOf()); + switch (dialect) + { + case MsSql2000Dialect _: + case MsSqlCeDialect _: + case SybaseASE15Dialect _: + Assert.That(substringFunction, Is.TypeOf()); + break; + case DB2Dialect _: + Assert.That(substringFunction, Is.TypeOf()); + break; + case SybaseSQLAnywhere10Dialect _: + Assert.That(substringFunction, Is.TypeOf()); + break; + case Oracle8iDialect _: + case SQLiteDialect _: + case HanaDialectBase _: + Assert.That(substringFunction, Is.TypeOf()); + break; + default: + Assert.That(substringFunction, Is.TypeOf()); + break; + } } } diff --git a/src/NHibernate.Test/Events/Collections/AbstractCollectionEventFixture.cs b/src/NHibernate.Test/Events/Collections/AbstractCollectionEventFixture.cs index 1d19a566322..3c6549f4c83 100644 --- a/src/NHibernate.Test/Events/Collections/AbstractCollectionEventFixture.cs +++ b/src/NHibernate.Test/Events/Collections/AbstractCollectionEventFixture.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using NHibernate.Collection; using NHibernate.Collection.Generic; -using NHibernate.Event; using NHibernate.Test.Events.Collections.Association.Bidirectional.ManyToMany; using NUnit.Framework; @@ -11,6 +10,11 @@ namespace NHibernate.Test.Events.Collections [TestFixture] public abstract class AbstractCollectionEventFixture : TestCase { + protected override bool AppliesTo(Dialect.Dialect dialect) + { + return TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator; + } + protected override string MappingsAssembly { get { return "NHibernate.Test"; } diff --git a/src/NHibernate.Test/Generatedkeys/Seqidentity/SequenceIdentityFixture.cs b/src/NHibernate.Test/Generatedkeys/Seqidentity/SequenceIdentityFixture.cs index 6bb032a5b19..88584e51366 100644 --- a/src/NHibernate.Test/Generatedkeys/Seqidentity/SequenceIdentityFixture.cs +++ b/src/NHibernate.Test/Generatedkeys/Seqidentity/SequenceIdentityFixture.cs @@ -18,7 +18,9 @@ protected override string MappingsAssembly protected override bool AppliesTo(Dialect.Dialect dialect) { - return dialect.SupportsSequences && !(dialect is Dialect.MsSql2012Dialect); + return dialect.SupportsSequences && + !(dialect is Dialect.MsSql2012Dialect) && + !(dialect is Dialect.HanaDialectBase); // SAP HANA does not support a syntax allowing to return the inserted id as an output parameter or a return value } [Test] @@ -38,4 +40,4 @@ public void SequenceIdentityGenerator() session.Close(); } } -} \ No newline at end of file +} diff --git a/src/NHibernate.Test/GenericTest/Overall/Fixture.cs b/src/NHibernate.Test/GenericTest/Overall/Fixture.cs index b4c6b31e5cb..95d1f068b4a 100644 --- a/src/NHibernate.Test/GenericTest/Overall/Fixture.cs +++ b/src/NHibernate.Test/GenericTest/Overall/Fixture.cs @@ -42,6 +42,9 @@ public void CRUD() [Test] public void CRUDAB() { + if (!TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator) + Assert.Ignore("Support of empty inserts is required"); + var entity = new A { Property = new B { Prop = 2 }, diff --git a/src/NHibernate.Test/Hql/HQLFunctions.cs b/src/NHibernate.Test/Hql/HQLFunctions.cs index 2d54fc6ebaf..35a447cbbfd 100644 --- a/src/NHibernate.Test/Hql/HQLFunctions.cs +++ b/src/NHibernate.Test/Hql/HQLFunctions.cs @@ -936,6 +936,13 @@ public void Cast() throw; } } + else if (Dialect is HanaDialectBase) + { + string msgToCheck = + "not a GROUP BY expression: 'ANIMAL0_.BODYWEIGHT' must be in group by clause"; + if (!ex.InnerException.Message.Contains(msgToCheck)) + throw; + } else { string msgToCheck = @@ -1133,7 +1140,7 @@ public void Str() [Test] public void Iif() { - AssumeFunctionSupported("Iif"); + AssumeFunctionSupported("iif"); using (ISession s = OpenSession()) { s.Save(new MaterialResource("Flash card 512MB", "A001/07", MaterialResource.MaterialState.Available)); diff --git a/src/NHibernate.Test/Insertordering/FamilyModel/Fixture.cs b/src/NHibernate.Test/Insertordering/FamilyModel/Fixture.cs index 845dc19d58e..8f85ad8ee20 100644 --- a/src/NHibernate.Test/Insertordering/FamilyModel/Fixture.cs +++ b/src/NHibernate.Test/Insertordering/FamilyModel/Fixture.cs @@ -19,6 +19,11 @@ protected override string MappingsAssembly get { return "NHibernate.Test"; } } + protected override bool AppliesTo(Dialect.Dialect dialect) + { + return TestDialect.SupportsBatchingDependentDML; + } + protected override void Configure(Configuration configuration) { configuration.DataBaseIntegration(x => @@ -95,4 +100,4 @@ public void CircularReferences() } } } -} \ No newline at end of file +} diff --git a/src/NHibernate.Test/Legacy/FooBarTest.cs b/src/NHibernate.Test/Legacy/FooBarTest.cs index 0a05c46e884..7be39e672f8 100644 --- a/src/NHibernate.Test/Legacy/FooBarTest.cs +++ b/src/NHibernate.Test/Legacy/FooBarTest.cs @@ -2478,7 +2478,7 @@ public void CollectionsInSelect() // probably the conversion ProxyArray.id (to_number ensuring a not null value) // Indeed, ProxyArray.id is Glarch.tha_key which is a string filled with a Guid. It does // not fail with most engine likely because there are no results thanks to other conditions. - if (!(Dialect is Oracle8iDialect) && !(Dialect is MsSqlCeDialect)) + if (!(Dialect is Oracle8iDialect) && !(Dialect is MsSqlCeDialect) && !(Dialect is HanaDialectBase)) { s.CreateQuery( "select count(*) from Bar as bar join bar.Component.Glarch.ProxyArray as g where cast(g.id as Int32) in indices(bar.Baz.FooArray)"). @@ -4091,6 +4091,9 @@ public void UpdateOrder() [Test] public void UpdateFromTransient() { + if (!TestDialect.SupportsBatchingDependentDML) + Assert.Ignore($"Dialect {Dialect} does not support batching of dependent DML (fee update on related fee)"); + ISession s = OpenSession(); Fee fee1 = new Fee(); s.Save(fee1); diff --git a/src/NHibernate.Test/Legacy/FumTest.cs b/src/NHibernate.Test/Legacy/FumTest.cs index ab43bed1595..d1373873159 100644 --- a/src/NHibernate.Test/Legacy/FumTest.cs +++ b/src/NHibernate.Test/Legacy/FumTest.cs @@ -716,4 +716,4 @@ private ISession SpoofSerialization(ISession session) return (ISession) formatter.Deserialize(stream); } } -} \ No newline at end of file +} diff --git a/src/NHibernate.Test/Legacy/MasterDetailTest.cs b/src/NHibernate.Test/Legacy/MasterDetailTest.cs index 6d3e7b4e067..5b6fb4eba27 100644 --- a/src/NHibernate.Test/Legacy/MasterDetailTest.cs +++ b/src/NHibernate.Test/Legacy/MasterDetailTest.cs @@ -41,6 +41,9 @@ protected override IList Mappings [Test] public void ParentChildren() { + if (!TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator) + Assert.Ignore("Support of empty inserts is required"); + ISession session = OpenSession(); M parent = new M(); @@ -841,6 +844,9 @@ public void MixNativeAssigned() [Test] public void CollectionReplaceOnUpdate() { + if (!TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator) + Assert.Ignore("Support of empty inserts is required"); + ISession s = OpenSession(); ITransaction t = s.BeginTransaction(); Category c = new Category(); @@ -886,6 +892,9 @@ public void CollectionReplaceOnUpdate() [Test] public void CollectionReplace2() { + if (!TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator) + Assert.Ignore("Support of empty inserts is required"); + ISession s = OpenSession(); ITransaction t = s.BeginTransaction(); Category c = new Category(); @@ -925,6 +934,9 @@ public void CollectionReplace2() [Test] public void CollectionReplace() { + if (!TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator) + Assert.Ignore("Support of empty inserts is required"); + ISession s = OpenSession(); ITransaction t = s.BeginTransaction(); Category c = new Category(); @@ -970,6 +982,9 @@ public void CollectionReplace() [Test] public void Categories() { + if (!TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator) + Assert.Ignore("Support of empty inserts is required"); + Category c = new Category(); c.Name = Category.RootCategory; Category c1 = new Category(); @@ -1011,6 +1026,9 @@ public void Categories() [Test] public void CollectionRefresh() { + if (!TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator) + Assert.Ignore("Support of empty inserts is required"); + ISession s = OpenSession(); Category c = new Category(); IList list = new List(); @@ -1054,6 +1072,9 @@ public void CollectionRefresh() [Test] public void CachedCollectionRefresh() { + if (!TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator) + Assert.Ignore("Support of empty inserts is required"); + ISession s = OpenSession(); Category c = new Category(); IList list = new List(); @@ -1239,6 +1260,9 @@ public void QueuedBagAdds() [Test] public void PolymorphicCriteria() { + if (!TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator) + Assert.Ignore("Support of empty inserts is required"); + ISession s = OpenSession(); ITransaction txn = s.BeginTransaction(); Category f = new Category(); diff --git a/src/NHibernate.Test/Legacy/MultiTableTest.cs b/src/NHibernate.Test/Legacy/MultiTableTest.cs index ee9841eb1c4..30ecf60edb7 100644 --- a/src/NHibernate.Test/Legacy/MultiTableTest.cs +++ b/src/NHibernate.Test/Legacy/MultiTableTest.cs @@ -149,7 +149,7 @@ public void Queries() ISession s = OpenSession(); long id = 1L; - if (Dialect is MsSql2000Dialect) + if (TestDialect.HasIdentityNativeGenerator) { id = (long) s.Save(new TrivialClass()); } @@ -185,7 +185,7 @@ public void Constraints() ITransaction t = s.BeginTransaction(); SubMulti sm = new SubMulti(); sm.Amount = 66.5f; - if (Dialect is MsSql2000Dialect) + if (TestDialect.HasIdentityNativeGenerator) { s.Save(sm); } @@ -216,7 +216,7 @@ public void MultiTable() simp.Name = "simp"; object mid; object sid; - if (Dialect is MsSql2000Dialect) + if (TestDialect.HasIdentityNativeGenerator) { mid = s.Save(multi); sid = s.Save(simp); @@ -231,7 +231,7 @@ public void MultiTable() SubMulti sm = new SubMulti(); sm.Amount = 66.5f; object smid; - if (Dialect is MsSql2000Dialect) + if (TestDialect.HasIdentityNativeGenerator) { smid = s.Save(sm); } @@ -465,7 +465,7 @@ public void MultiTableCollections() simp.Name = "simp"; object mid; object sid; - if (Dialect is MsSql2000Dialect) + if (TestDialect.HasIdentityNativeGenerator) { mid = s.Save(multi); sid = s.Save(simp); @@ -485,7 +485,7 @@ public void MultiTableCollections() ls.Set = new HashSet { multi, simp }; object id; - if (Dialect is MsSql2000Dialect) + if (TestDialect.HasIdentityNativeGenerator) { id = s.Save(ls); } @@ -542,7 +542,7 @@ public void MultiTableManyToOne() simp.Name = "simp"; object mid; - if (Dialect is MsSql2000Dialect) + if (TestDialect.HasIdentityNativeGenerator) { mid = s.Save(multi); } @@ -557,7 +557,7 @@ public void MultiTableManyToOne() ls.YetAnother = ls; ls.Name = "Less Simple"; object id; - if (Dialect is MsSql2000Dialect) + if (TestDialect.HasIdentityNativeGenerator) { id = s.Save(ls); } @@ -603,6 +603,9 @@ public void MultiTableNativeId() [Test] public void Collection() { + if (!TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator) + Assert.Ignore("Support of empty inserts is required"); + ISession s = OpenSession(); ITransaction t = s.BeginTransaction(); Multi multi1 = new Multi(); @@ -702,4 +705,4 @@ public void DynamicUpdate() } } } -} \ No newline at end of file +} diff --git a/src/NHibernate.Test/Legacy/ParentChildTest.cs b/src/NHibernate.Test/Legacy/ParentChildTest.cs index fbc6d5913be..2790357ad8a 100644 --- a/src/NHibernate.Test/Legacy/ParentChildTest.cs +++ b/src/NHibernate.Test/Legacy/ParentChildTest.cs @@ -44,6 +44,9 @@ protected override IList Mappings [Test] public void Replicate() { + if (!TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator) + Assert.Ignore("Support of empty inserts is required"); + ISession s = OpenSession(); Container baz = new Container(); Contained f = new Contained(); @@ -342,6 +345,9 @@ public void ClassWhere() [Test] public void CollectionQuery() { + if (!TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator) + Assert.Ignore("Support of empty inserts is required"); + ISession s = OpenSession(); ITransaction t = s.BeginTransaction(); @@ -499,6 +505,9 @@ public void ParentNullChild() [Test] public void ManyToMany() { + if (!TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator) + Assert.Ignore("Support of empty inserts is required"); + // if( dialect is Dialect.HSQLDialect) return; ISession s = OpenSession(); @@ -556,6 +565,9 @@ public void ManyToMany() [Test] public void Container() { + if (!TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator) + Assert.Ignore("Support of empty inserts is required"); + ISession s = OpenSession(); ITransaction t = s.BeginTransaction(); Container c = new Container(); @@ -688,6 +700,9 @@ public void Container() [Test] public void CascadeCompositeElements() { + if (!TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator) + Assert.Ignore("Support of empty inserts is required"); + Container c = new Container(); c.Cascades = new List(); @@ -749,6 +764,9 @@ public void CascadeCompositeElements() [Test] public void Bag() { + if (!TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator) + Assert.Ignore("Support of empty inserts is required"); + //if( dialect is Dialect.HSQLDialect ) return; ISession s = OpenSession(); diff --git a/src/NHibernate.Test/Linq/ByMethod/OrderByTests.cs b/src/NHibernate.Test/Linq/ByMethod/OrderByTests.cs index 7f19c1bdc73..0a4f0ade222 100644 --- a/src/NHibernate.Test/Linq/ByMethod/OrderByTests.cs +++ b/src/NHibernate.Test/Linq/ByMethod/OrderByTests.cs @@ -60,8 +60,8 @@ orderby c.CustomerId descending [Test] public void OrderByCalculatedAggregatedSubselectProperty() { - if (!Dialect.SupportsScalarSubSelects) - Assert.Ignore("Dialect does not support scalar sub-selects"); + if (!TestDialect.SupportsAggregatingScalarSubSelectsInOrderBy) + Assert.Ignore("Dialect does not support aggregating scalar sub-selects in order by"); //NH-2781 var result = db.Orders @@ -81,8 +81,8 @@ public void OrderByCalculatedAggregatedSubselectProperty() [Test] public void AggregateAscendingOrderByClause() { - if (!Dialect.SupportsScalarSubSelects) - Assert.Ignore("Dialect does not support scalar sub-selects"); + if (!TestDialect.SupportsAggregatingScalarSubSelectsInOrderBy) + Assert.Ignore("Dialect does not support aggregating scalar sub-selects in order by"); var query = from c in db.Customers orderby c.Orders.Count @@ -97,8 +97,8 @@ orderby c.Orders.Count [Test] public void AggregateDescendingOrderByClause() { - if (!Dialect.SupportsScalarSubSelects) - Assert.Ignore("Dialect does not support scalar sub-selects"); + if (!TestDialect.SupportsAggregatingScalarSubSelectsInOrderBy) + Assert.Ignore("Dialect does not support aggregating scalar sub-selects in order by"); var query = from c in db.Customers orderby c.Orders.Count descending @@ -179,6 +179,9 @@ public void OrderByWithSelfReferencedSubquery1() if (!Dialect.SupportsScalarSubSelects) Assert.Ignore("Dialect does not support scalar sub-selects"); + if (!TestDialect.SupportsOrderByAndLimitInSubQueries) + Assert.Ignore("Dialect does not support sub-selects with order by or limit/top"); + if (Dialect is Oracle8iDialect) Assert.Ignore("On Oracle this generates a correlated subquery two levels deep which isn't supported until Oracle 10g."); @@ -197,6 +200,9 @@ public void OrderByWithSelfReferencedSubquery2() if (!Dialect.SupportsScalarSubSelects) Assert.Ignore("Dialect does not support scalar sub-selects"); + if (!TestDialect.SupportsOrderByAndLimitInSubQueries) + Assert.Ignore("Dialect does not support sub-selects with order by or limit/top"); + if (Dialect is Oracle8iDialect) Assert.Ignore("On Oracle this generates a correlated subquery two levels deep which isn't supported until Oracle 10g."); @@ -225,4 +231,4 @@ public void OrderByWithSelectDistinctAndTake() db.Orders.Select(o => o.ShippedTo).Distinct().OrderBy(o => o).Take(1000).ToList(); } } -} \ No newline at end of file +} diff --git a/src/NHibernate.Test/Linq/PropertyMethodMappingTests.cs b/src/NHibernate.Test/Linq/PropertyMethodMappingTests.cs index b425f1ee0c8..5881e3abba4 100644 --- a/src/NHibernate.Test/Linq/PropertyMethodMappingTests.cs +++ b/src/NHibernate.Test/Linq/PropertyMethodMappingTests.cs @@ -15,7 +15,7 @@ protected override bool AppliesTo(Dialect.Dialect dialect) public void CanExecuteCountInSelectClause() { var results = db.Timesheets - .Select(t => t.Entries.Count).ToList(); + .Select(t => t.Entries.Count).OrderBy(s => s).ToList(); Assert.AreEqual(3, results.Count); Assert.AreEqual(0, results[0]); @@ -32,4 +32,4 @@ public void CanExecuteCountInWhereClause() Assert.AreEqual(2, results.Count); } } -} \ No newline at end of file +} diff --git a/src/NHibernate.Test/Linq/SelectionTests.cs b/src/NHibernate.Test/Linq/SelectionTests.cs index a8cb1692af8..3873558badf 100644 --- a/src/NHibernate.Test/Linq/SelectionTests.cs +++ b/src/NHibernate.Test/Linq/SelectionTests.cs @@ -286,7 +286,7 @@ public void CanSelectWithAggregateSubQuery() if (!Dialect.SupportsScalarSubSelects) Assert.Ignore(Dialect.GetType().Name + " does not support scalar sub-queries"); - var timesheets = (from timesheet in db.Timesheets + var timesheets = (from timesheet in db.Timesheets orderby timesheet.Id select new { timesheet.Id, diff --git a/src/NHibernate.Test/Linq/WhereSubqueryTests.cs b/src/NHibernate.Test/Linq/WhereSubqueryTests.cs index 15fcec0ef36..060d6bc1710 100644 --- a/src/NHibernate.Test/Linq/WhereSubqueryTests.cs +++ b/src/NHibernate.Test/Linq/WhereSubqueryTests.cs @@ -601,6 +601,9 @@ public void SubqueryWhereFailingTest() if (!Dialect.SupportsScalarSubSelects) Assert.Ignore(Dialect.GetType().Name + " does not support subquery in select clause"); + if (!TestDialect.SupportsOrderByAndLimitInSubQueries) + Assert.Ignore("Dialect does not support sub-selects with order by or limit/top"); + var list = (db.OrderLines .Select(ol => new { @@ -620,6 +623,9 @@ public void SubqueryWhereFailingTest2() if (!Dialect.SupportsScalarSubSelects) Assert.Ignore(Dialect.GetType().Name + " does not support subquery in select clause"); + if (!TestDialect.SupportsOrderByAndLimitInSubQueries) + Assert.Ignore("Dialect does not support sub-selects with order by or limit/top"); + var list = db.OrderLines .Select(ol => new { @@ -639,6 +645,9 @@ public void SubqueryWhereFailingTest3() if (!Dialect.SupportsScalarSubSelects) Assert.Ignore(Dialect.GetType().Name + " does not support subquery in select clause"); + if (!TestDialect.SupportsOrderByAndLimitInSubQueries) + Assert.Ignore("Dialect does not support sub-selects with order by or limit/top"); + var list = db.OrderLines .Select(ol => new { @@ -658,6 +667,9 @@ public void ProductsWithSubqueryReturningBoolFirstOrDefaultEq() if (!Dialect.SupportsScalarSubSelects) Assert.Ignore(Dialect.GetType().Name + " does not support scalar sub-queries"); + if (!TestDialect.SupportsOrderByAndLimitInSubQueries) + Assert.Ignore("Dialect does not support sub-selects with order by or limit/top"); + var result = (from p in db.Products where (from c in db.Categories where c.Name == "Confections" @@ -675,6 +687,9 @@ public void SubselectCanHaveBoolResult() if (!Dialect.SupportsScalarSubSelects) Assert.Ignore(Dialect.GetType().Name + " does not support scalar sub-queries"); + if (!TestDialect.SupportsOrderByAndLimitInSubQueries) + Assert.Ignore("Dialect does not support sub-selects with order by or limit/top"); + var result = (from c in db.Categories where c.Products.OrderBy(p => p.ProductId).Select(p => p.Discontinued).FirstOrDefault() == false select c).ToList(); @@ -689,6 +704,9 @@ public void ProductsWithSubqueryReturningProjectionBoolFirstOrDefaultEq() if (!Dialect.SupportsScalarSubSelects) Assert.Ignore(Dialect.GetType().Name + " does not support scalar sub-queries"); + if (!TestDialect.SupportsOrderByAndLimitInSubQueries) + Assert.Ignore("Dialect does not support sub-selects with order by or limit/top"); + //NH-3190 var result = (from p in db.Products where (from c in db.Categories @@ -707,6 +725,9 @@ public void ProductsWithSubqueryReturningStringFirstOrDefaultEq() if (!Dialect.SupportsScalarSubSelects) Assert.Ignore(Dialect.GetType().Name + " does not support scalar sub-queries"); + if (!TestDialect.SupportsOrderByAndLimitInSubQueries) + Assert.Ignore("Dialect does not support sub-selects with order by or limit/top"); + var result = (from p in db.Products where (from c in db.Categories where c.Name == "Confections" diff --git a/src/NHibernate.Test/NHSpecificTest/CollectionFixture.cs b/src/NHibernate.Test/NHSpecificTest/CollectionFixture.cs index ebe24a0164c..e400f72cd3a 100644 --- a/src/NHibernate.Test/NHSpecificTest/CollectionFixture.cs +++ b/src/NHibernate.Test/NHSpecificTest/CollectionFixture.cs @@ -1,4 +1,3 @@ -using System; using System.Collections; using NHibernate.DomainModel.NHSpecific; using NUnit.Framework; @@ -25,6 +24,11 @@ protected override void OnTearDown() } } + protected override bool AppliesTo(Dialect.Dialect dialect) + { + return TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator; + } + [Test] public void TestLoadParentFirst() { @@ -85,4 +89,4 @@ public void TestLoadChildFirst() } } } -} \ No newline at end of file +} diff --git a/src/NHibernate.Test/NHSpecificTest/Docs/Associations/BiM21/Fixture.cs b/src/NHibernate.Test/NHSpecificTest/Docs/Associations/BiM21/Fixture.cs index 6abbe6da8ec..713c96c5784 100644 --- a/src/NHibernate.Test/NHSpecificTest/Docs/Associations/BiM21/Fixture.cs +++ b/src/NHibernate.Test/NHSpecificTest/Docs/Associations/BiM21/Fixture.cs @@ -1,4 +1,3 @@ -using System; using System.Collections; using NUnit.Framework; @@ -17,6 +16,11 @@ protected override IList Mappings get { return new string[] {"NHSpecificTest.Docs.Associations.BiM21.Mappings.hbm.xml"}; } } + protected override bool AppliesTo(Dialect.Dialect dialect) + { + return TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator; + } + [Test] public void TestCorrectUse() { @@ -62,4 +66,4 @@ public void TestErrorUsage() } } } -} \ No newline at end of file +} diff --git a/src/NHibernate.Test/NHSpecificTest/Docs/ExampleParentChild/UpdateFixture.cs b/src/NHibernate.Test/NHSpecificTest/Docs/ExampleParentChild/UpdateFixture.cs index e9be1db91ad..5460d27ed96 100644 --- a/src/NHibernate.Test/NHSpecificTest/Docs/ExampleParentChild/UpdateFixture.cs +++ b/src/NHibernate.Test/NHSpecificTest/Docs/ExampleParentChild/UpdateFixture.cs @@ -1,4 +1,3 @@ -using System; using System.Collections; using NUnit.Framework; @@ -17,6 +16,11 @@ protected override IList Mappings get { return new string[] {"NHSpecificTest.Docs.ExampleParentChild.Mappings.hbm.xml"}; } } + protected override bool AppliesTo(Dialect.Dialect dialect) + { + return TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator; + } + [Test] public void Update() { @@ -53,4 +57,4 @@ public void Update() } } } -} \ No newline at end of file +} diff --git a/src/NHibernate.Test/NHSpecificTest/GH1565/LockEntityWithOuterJoinTest.cs b/src/NHibernate.Test/NHSpecificTest/GH1565/LockEntityWithOuterJoinTest.cs index 2815ff61c20..4e957f99ba6 100644 --- a/src/NHibernate.Test/NHSpecificTest/GH1565/LockEntityWithOuterJoinTest.cs +++ b/src/NHibernate.Test/NHSpecificTest/GH1565/LockEntityWithOuterJoinTest.cs @@ -44,6 +44,11 @@ protected override void OnTearDown() session.CreateSQLQuery("delete from MainEntity").ExecuteUpdate(); } } + + protected override bool AppliesTo(Dialect.Dialect dialect) + { + return TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator; + } } public class MainEntity diff --git a/src/NHibernate.Test/NHSpecificTest/LazyLoadBugTest.cs b/src/NHibernate.Test/NHSpecificTest/LazyLoadBugTest.cs index b16ba8f4140..f131bf5cf3f 100644 --- a/src/NHibernate.Test/NHSpecificTest/LazyLoadBugTest.cs +++ b/src/NHibernate.Test/NHSpecificTest/LazyLoadBugTest.cs @@ -1,4 +1,3 @@ -using System; using System.Collections; using NHibernate.DomainModel.NHSpecific; using NUnit.Framework; @@ -13,6 +12,11 @@ protected override IList Mappings get { return new string[] {"NHSpecific.LazyLoadBug.hbm.xml"}; } } + protected override bool AppliesTo(Dialect.Dialect dialect) + { + return TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator; + } + [Test] public void TestLazyLoad() { @@ -91,4 +95,4 @@ public void TestLazyLoadNoAdd() } } } -} \ No newline at end of file +} diff --git a/src/NHibernate.Test/NHSpecificTest/ListsWithHoles/Fixture.cs b/src/NHibernate.Test/NHSpecificTest/ListsWithHoles/Fixture.cs index 9c5a81b9046..1ca671df404 100644 --- a/src/NHibernate.Test/NHSpecificTest/ListsWithHoles/Fixture.cs +++ b/src/NHibernate.Test/NHSpecificTest/ListsWithHoles/Fixture.cs @@ -1,9 +1,3 @@ -using System; -using System.Collections.Generic; -using System.Text; -using log4net.Appender; -using log4net.Core; -using log4net.Repository.Hierarchy; using NUnit.Framework; namespace NHibernate.Test.NHSpecificTest.ListsWithHoles @@ -13,6 +7,10 @@ namespace NHibernate.Test.NHSpecificTest.ListsWithHoles [TestFixture] public class Fixture : TestCase { + protected override bool AppliesTo(Dialect.Dialect dialect) + { + return TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator; + } protected override IList Mappings { diff --git a/src/NHibernate.Test/NHSpecificTest/LoadingNullEntityInSet/Fixture.cs b/src/NHibernate.Test/NHSpecificTest/LoadingNullEntityInSet/Fixture.cs index edd65f33634..3acdfcb0b76 100644 --- a/src/NHibernate.Test/NHSpecificTest/LoadingNullEntityInSet/Fixture.cs +++ b/src/NHibernate.Test/NHSpecificTest/LoadingNullEntityInSet/Fixture.cs @@ -21,6 +21,11 @@ protected override string MappingsAssembly get { return "NHibernate.Test"; } } + protected override bool AppliesTo(Dialect.Dialect dialect) + { + return TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator; + } + protected override DebugSessionFactory BuildSessionFactory() { cfg.GetCollectionMapping(typeof (Employee).FullName + ".Primaries") diff --git a/src/NHibernate.Test/NHSpecificTest/Logs/LogsFixture.cs b/src/NHibernate.Test/NHSpecificTest/Logs/LogsFixture.cs index 525535fbbb0..144f6002f10 100644 --- a/src/NHibernate.Test/NHSpecificTest/Logs/LogsFixture.cs +++ b/src/NHibernate.Test/NHSpecificTest/Logs/LogsFixture.cs @@ -136,6 +136,11 @@ public void WillGetSessionIdFromInterlacedSessionsLogs() [Test] public void WillGetSessionIdFromSessionLogsConcurrent() { + if (!TestDialect.SupportsConcurrencyTests) + { + Assert.Ignore($"Dialect {Dialect} does not supports concurrency tests"); + } + GlobalContext.Properties["sessionId"] = new SessionIdCapturer(); // Do not use a ManualResetEventSlim, it does not support async and exhausts the task thread pool in the diff --git a/src/NHibernate.Test/NHSpecificTest/NH1274ExportExclude/NH1274ExportExcludeFixture.cs b/src/NHibernate.Test/NHSpecificTest/NH1274ExportExclude/NH1274ExportExcludeFixture.cs index 1af7989aa05..4433f923f47 100644 --- a/src/NHibernate.Test/NHSpecificTest/NH1274ExportExclude/NH1274ExportExcludeFixture.cs +++ b/src/NHibernate.Test/NHSpecificTest/NH1274ExportExclude/NH1274ExportExcludeFixture.cs @@ -58,8 +58,8 @@ public void SchemaExport_Export_CreatesExportScript() Assert.IsTrue(s.Contains("drop table Home_All")); } - Assert.IsTrue(s.Contains("create table Home_All")); - Assert.IsTrue(s.Contains("create table Home_Export")); + Assert.That(s, Does.Match("create ((column|row) )?table Home_All")); + Assert.That(s, Does.Match("create ((column|row) )?table Home_Export")); } [Test] @@ -71,8 +71,8 @@ public void SchemaExport_Update_CreatesUpdateScript() update.Execute(tw.WriteLine, false); string s = tw.ToString(); - Assert.IsTrue(s.Contains("create table Home_Update")); - Assert.IsTrue(s.Contains("create table Home_All")); + Assert.That(s, Does.Match("create ((column|row) )?table Home_Update")); + Assert.That(s, Does.Match("create ((column|row) )?table Home_All")); } [Test] diff --git a/src/NHibernate.Test/NHSpecificTest/NH1301/Fixture.cs b/src/NHibernate.Test/NHSpecificTest/NH1301/Fixture.cs index f4cc7773dfd..529b7909599 100644 --- a/src/NHibernate.Test/NHSpecificTest/NH1301/Fixture.cs +++ b/src/NHibernate.Test/NHSpecificTest/NH1301/Fixture.cs @@ -10,6 +10,11 @@ public override string BugNumber get { return "NH1301"; } } + protected override bool AppliesTo(Dialect.Dialect dialect) + { + return TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator; + } + [Test] public void Test() { diff --git a/src/NHibernate.Test/NHSpecificTest/NH1388/Fixture.cs b/src/NHibernate.Test/NHSpecificTest/NH1388/Fixture.cs index 2a7a94a7550..7a7afd596e4 100644 --- a/src/NHibernate.Test/NHSpecificTest/NH1388/Fixture.cs +++ b/src/NHibernate.Test/NHSpecificTest/NH1388/Fixture.cs @@ -37,6 +37,11 @@ public class Major [TestFixture] public class Fixture : BugTestCase { + protected override bool AppliesTo(Dialect.Dialect dialect) + { + return TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator; + } + [Test] public void BagTest() { @@ -129,4 +134,4 @@ protected override string CacheConcurrencyStrategy get { return null; } } } -} \ No newline at end of file +} diff --git a/src/NHibernate.Test/NHSpecificTest/NH1394/Fixture.cs b/src/NHibernate.Test/NHSpecificTest/NH1394/Fixture.cs index 90b7ee820b2..0bad20e6fc7 100644 --- a/src/NHibernate.Test/NHSpecificTest/NH1394/Fixture.cs +++ b/src/NHibernate.Test/NHSpecificTest/NH1394/Fixture.cs @@ -74,8 +74,8 @@ public void CanOrderByPropertyProjection() [Test] public void CanOrderBySubqueryProjection() { - if (!Dialect.SupportsScalarSubSelects) - Assert.Ignore(Dialect.GetType().Name + " does not support scalar sub-queries"); + if (!TestDialect.SupportsAggregatingScalarSubSelectsInOrderBy) + Assert.Ignore("Dialect does not support aggregating scalar sub-selects in order by"); using (ISession s = OpenSession()) { @@ -104,8 +104,8 @@ public void CanOrderBySubqueryProjection() [Test] public void CanOrderBySubqueryProjectionDesc() { - if (!Dialect.SupportsScalarSubSelects) - Assert.Ignore(Dialect.GetType().Name + " does not support scalar sub-queries"); + if (!TestDialect.SupportsAggregatingScalarSubSelectsInOrderBy) + Assert.Ignore("Dialect does not support aggregating scalar sub-selects in order by"); using (ISession s = OpenSession()) { @@ -166,4 +166,4 @@ public void CanOrderBySqlProjectionDesc() } } } -} \ No newline at end of file +} diff --git a/src/NHibernate.Test/NHSpecificTest/NH1443/Fixture.cs b/src/NHibernate.Test/NHSpecificTest/NH1443/Fixture.cs index 6efebb7ace0..7613aa9cfdd 100644 --- a/src/NHibernate.Test/NHSpecificTest/NH1443/Fixture.cs +++ b/src/NHibernate.Test/NHSpecificTest/NH1443/Fixture.cs @@ -21,7 +21,7 @@ private static void Bug(Configuration cfg) else Assert.That(script, Does.Match("drop table nhibernate.dbo.Aclass")); - Assert.That(script, Does.Match("create table nhibernate.dbo.Aclass")); + Assert.That(script, Does.Match("create ((column|row) )?table nhibernate.dbo.Aclass")); } diff --git a/src/NHibernate.Test/NHSpecificTest/NH1601/Fixture1.cs b/src/NHibernate.Test/NHSpecificTest/NH1601/Fixture1.cs index f801ed475f9..c7077c576d7 100644 --- a/src/NHibernate.Test/NHSpecificTest/NH1601/Fixture1.cs +++ b/src/NHibernate.Test/NHSpecificTest/NH1601/Fixture1.cs @@ -1,4 +1,3 @@ -using System.Collections.Generic; using NUnit.Framework; namespace NHibernate.Test.NHSpecificTest.NH1601 @@ -6,6 +5,11 @@ namespace NHibernate.Test.NHSpecificTest.NH1601 [TestFixture] public class Fixture1 : BugTestCase { + protected override bool AppliesTo(Dialect.Dialect dialect) + { + return TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator; + } + /// /// Loads the project do not call Count on the list assigned. /// diff --git a/src/NHibernate.Test/NHSpecificTest/NH1601/Fixture2.cs b/src/NHibernate.Test/NHSpecificTest/NH1601/Fixture2.cs index f629eff9eac..dd860d3d778 100644 --- a/src/NHibernate.Test/NHSpecificTest/NH1601/Fixture2.cs +++ b/src/NHibernate.Test/NHSpecificTest/NH1601/Fixture2.cs @@ -1,4 +1,3 @@ -using System.Collections.Generic; using NUnit.Framework; namespace NHibernate.Test.NHSpecificTest.NH1601 @@ -6,6 +5,11 @@ namespace NHibernate.Test.NHSpecificTest.NH1601 [TestFixture] public class Fixture2 : BugTestCase { + protected override bool AppliesTo(Dialect.Dialect dialect) + { + return TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator; + } + /// /// Loads the project and when Scenario2 and Scenario3 are set calls Count on the list assigned. /// diff --git a/src/NHibernate.Test/NHSpecificTest/NH1609/Fixture.cs b/src/NHibernate.Test/NHSpecificTest/NH1609/Fixture.cs index 5fb0474b9f6..6b8141f40db 100644 --- a/src/NHibernate.Test/NHSpecificTest/NH1609/Fixture.cs +++ b/src/NHibernate.Test/NHSpecificTest/NH1609/Fixture.cs @@ -71,4 +71,4 @@ private EntityB CreateEntityB(ISession session, EntityA a, EntityC c) return b; } } -} \ No newline at end of file +} diff --git a/src/NHibernate.Test/NHSpecificTest/NH1691/Fixture.cs b/src/NHibernate.Test/NHSpecificTest/NH1691/Fixture.cs index 68b364eb2be..00132cfed28 100644 --- a/src/NHibernate.Test/NHSpecificTest/NH1691/Fixture.cs +++ b/src/NHibernate.Test/NHSpecificTest/NH1691/Fixture.cs @@ -6,6 +6,11 @@ namespace NHibernate.Test.NHSpecificTest.NH1691 [TestFixture] public class Fixture : BugTestCase { + protected override bool AppliesTo(Dialect.Dialect dialect) + { + return TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator; + } + private static Component GetInitializedComponent() { var component = new Component(); @@ -112,4 +117,4 @@ public void NestedComponentCollection() } } } -} \ No newline at end of file +} diff --git a/src/NHibernate.Test/NHSpecificTest/NH1812/Fixture.cs b/src/NHibernate.Test/NHSpecificTest/NH1812/Fixture.cs index 2d71ab1fc44..0eca9db58c0 100644 --- a/src/NHibernate.Test/NHSpecificTest/NH1812/Fixture.cs +++ b/src/NHibernate.Test/NHSpecificTest/NH1812/Fixture.cs @@ -38,7 +38,7 @@ left outer join p.PeriodCollection p1 protected override bool AppliesTo(Dialect.Dialect dialect) { - return Dialect.SupportsScalarSubSelects; + return Dialect.SupportsScalarSubSelects && TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator; } protected override void OnTearDown() @@ -53,4 +53,4 @@ protected override void OnTearDown() } } } -} \ No newline at end of file +} diff --git a/src/NHibernate.Test/NHSpecificTest/NH1869/Fixture.cs b/src/NHibernate.Test/NHSpecificTest/NH1869/Fixture.cs index d69c8a630d6..db540190871 100644 --- a/src/NHibernate.Test/NHSpecificTest/NH1869/Fixture.cs +++ b/src/NHibernate.Test/NHSpecificTest/NH1869/Fixture.cs @@ -64,4 +64,4 @@ private IList GetResult(ISession session) return multi.List(); } } -} \ No newline at end of file +} diff --git a/src/NHibernate.Test/NHSpecificTest/NH1908ThreadSafety/Fixture.cs b/src/NHibernate.Test/NHSpecificTest/NH1908ThreadSafety/Fixture.cs index ee56f076a3f..6daf21a77a6 100644 --- a/src/NHibernate.Test/NHSpecificTest/NH1908ThreadSafety/Fixture.cs +++ b/src/NHibernate.Test/NHSpecificTest/NH1908ThreadSafety/Fixture.cs @@ -12,10 +12,11 @@ public class Fixture : BugTestCase { protected override bool AppliesTo(Dialect.Dialect dialect) { - return !(dialect is Oracle8iDialect); // Oracle sometimes causes: ORA-12520: TNS:listener could not find available handler for requested type of server // Following links bizarrely suggest it's an Oracle limitation under load: // http://www.orafaq.com/forum/t/60019/2/ & http://www.ispirer.com/wiki/sqlways/troubleshooting-guide/oracle/import/tns_listener + return !(dialect is Oracle8iDialect) && + TestDialect.SupportsConcurrencyTests; } [Test] diff --git a/src/NHibernate.Test/NHSpecificTest/NH1914/Fixture.cs b/src/NHibernate.Test/NHSpecificTest/NH1914/Fixture.cs index 9c87004392b..529347170bb 100644 --- a/src/NHibernate.Test/NHSpecificTest/NH1914/Fixture.cs +++ b/src/NHibernate.Test/NHSpecificTest/NH1914/Fixture.cs @@ -7,6 +7,10 @@ namespace NHibernate.Test.NHSpecificTest.NH1914 [TestFixture] public class Fixture : BugTestCase { + protected override bool AppliesTo(Dialect.Dialect dialect) + { + return TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator; + } [Test] public void CascadeInsertAssigned() diff --git a/src/NHibernate.Test/NHSpecificTest/NH2192/Fixture.cs b/src/NHibernate.Test/NHSpecificTest/NH2192/Fixture.cs index b0a895a0b63..9ec01b44380 100644 --- a/src/NHibernate.Test/NHSpecificTest/NH2192/Fixture.cs +++ b/src/NHibernate.Test/NHSpecificTest/NH2192/Fixture.cs @@ -9,6 +9,11 @@ namespace NHibernate.Test.NHSpecificTest.NH2192 [TestFixture] public class Fixture : BugTestCase { + protected override bool AppliesTo(Dialect.Dialect dialect) + { + return TestDialect.SupportsConcurrencyTests; + } + protected override void OnSetUp() { base.OnSetUp(); diff --git a/src/NHibernate.Test/NHSpecificTest/NH2328/Fixture.cs b/src/NHibernate.Test/NHSpecificTest/NH2328/Fixture.cs index a0dcb58b148..2ad2d25d5dc 100644 --- a/src/NHibernate.Test/NHSpecificTest/NH2328/Fixture.cs +++ b/src/NHibernate.Test/NHSpecificTest/NH2328/Fixture.cs @@ -1,5 +1,4 @@ using System.Linq; -using NHibernate.Linq; using NUnit.Framework; namespace NHibernate.Test.NHSpecificTest.NH2328 @@ -7,6 +6,11 @@ namespace NHibernate.Test.NHSpecificTest.NH2328 [TestFixture] public class Fixture : BugTestCase { + protected override bool AppliesTo(Dialect.Dialect dialect) + { + return TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator; + } + protected override void OnSetUp() { base.OnSetUp(); @@ -98,4 +102,4 @@ public void AnyIs_HqlWorksWithClassNameInTheLeft() } } } -} \ No newline at end of file +} diff --git a/src/NHibernate.Test/NHSpecificTest/NH2409/Fixture.cs b/src/NHibernate.Test/NHSpecificTest/NH2409/Fixture.cs index bb12d516a2c..af5110215ba 100644 --- a/src/NHibernate.Test/NHSpecificTest/NH2409/Fixture.cs +++ b/src/NHibernate.Test/NHSpecificTest/NH2409/Fixture.cs @@ -1,4 +1,3 @@ -using System; using System.Linq; using NHibernate.Criterion; using NHibernate.SqlCommand; @@ -9,6 +8,11 @@ namespace NHibernate.Test.NHSpecificTest.NH2409 [TestFixture] public class Fixture : BugTestCase { + protected override bool AppliesTo(Dialect.Dialect dialect) + { + return TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator; + } + [Test] public void Bug() { diff --git a/src/NHibernate.Test/NHSpecificTest/NH2703/Fixture.cs b/src/NHibernate.Test/NHSpecificTest/NH2703/Fixture.cs index 6cb1673da80..418d30fd051 100644 --- a/src/NHibernate.Test/NHSpecificTest/NH2703/Fixture.cs +++ b/src/NHibernate.Test/NHSpecificTest/NH2703/Fixture.cs @@ -7,6 +7,11 @@ public class Fixture : BugTestCase { Parent RootElement = null; + protected override bool AppliesTo(Dialect.Dialect dialect) + { + return TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator; + } + protected override void OnSetUp() { using (ISession session = Sfi.OpenSession()) diff --git a/src/NHibernate.Test/NHSpecificTest/NH2705/Test.cs b/src/NHibernate.Test/NHSpecificTest/NH2705/Test.cs index e70545a672b..bec7503160f 100644 --- a/src/NHibernate.Test/NHSpecificTest/NH2705/Test.cs +++ b/src/NHibernate.Test/NHSpecificTest/NH2705/Test.cs @@ -82,4 +82,4 @@ public void LinqQueryWithFetch_WhenDerivedClassesUseComponentAndEagerFetchManyTo } } } -} \ No newline at end of file +} diff --git a/src/NHibernate.Test/NHSpecificTest/NH2760/Fixture.cs b/src/NHibernate.Test/NHSpecificTest/NH2760/Fixture.cs index c11ad466463..30bf81f82c5 100644 --- a/src/NHibernate.Test/NHSpecificTest/NH2760/Fixture.cs +++ b/src/NHibernate.Test/NHSpecificTest/NH2760/Fixture.cs @@ -57,6 +57,9 @@ protected override void OnTearDown() [Test] public void ShouldBeAbleToSelectUserGroupAndOrderByUserCount() { + if (!TestDialect.SupportsAggregatingScalarSubSelectsInOrderBy) + Assert.Ignore("Dialect does not support aggregating scalar sub-selects in order by"); + using (ISession session = base.OpenSession()) using (ITransaction transaction = session.BeginTransaction()) { @@ -125,6 +128,9 @@ from ug in session.Query() [Test] public void ShouldBeAbleToSelectUserGroupAndOrderByUserCountWithHql() { + if (!TestDialect.SupportsAggregatingScalarSubSelectsInOrderBy) + Assert.Ignore("Dialect does not support aggregating scalar sub-selects in order by"); + using (ISession session = base.OpenSession()) using (ITransaction transaction = session.BeginTransaction()) { @@ -140,4 +146,4 @@ public void ShouldBeAbleToSelectUserGroupAndOrderByUserCountWithHql() } } } -} \ No newline at end of file +} diff --git a/src/NHibernate.Test/NHSpecificTest/NH280/Fixture.cs b/src/NHibernate.Test/NHSpecificTest/NH280/Fixture.cs index 459ffdf2f42..d5a5c45a9cf 100644 --- a/src/NHibernate.Test/NHSpecificTest/NH280/Fixture.cs +++ b/src/NHibernate.Test/NHSpecificTest/NH280/Fixture.cs @@ -26,16 +26,21 @@ public void ConstInSelect() s.Save(f); s.Flush(); - IList l = s.CreateQuery("select 'TextConst', 123, 123.5, .5 from Foo").List(); - IList result = l[0] as IList; - Assert.AreEqual(typeof(string), result[0].GetType()); - Assert.AreEqual(typeof(Int32), result[1].GetType()); - Assert.AreEqual(typeof(Double), result[2].GetType()); - Assert.AreEqual(typeof(Double), result[3].GetType()); - Assert.AreEqual("TextConst", result[0]); - Assert.AreEqual(123, result[1]); - Assert.AreEqual(123.5D, result[2]); - Assert.AreEqual(0.5D, result[3]); + IList l; + IList result; + if (TestDialect.SupportsSelectingDoubleLiteral) + { + l = s.CreateQuery("select 'TextConst', 123, 123.5, .5 from Foo").List(); + result = l[0] as IList; + Assert.AreEqual(typeof(string), result[0].GetType()); + Assert.AreEqual(typeof(Int32), result[1].GetType()); + Assert.AreEqual(typeof(Double), result[2].GetType()); + Assert.AreEqual(typeof(Double), result[3].GetType()); + Assert.AreEqual("TextConst", result[0]); + Assert.AreEqual(123, result[1]); + Assert.AreEqual(123.5D, result[2]); + Assert.AreEqual(0.5D, result[3]); + } l = s.CreateQuery("select 123, f from Foo f").List(); result = l[0] as IList; diff --git a/src/NHibernate.Test/NHSpecificTest/NH3141/ProxyIdFixture.cs b/src/NHibernate.Test/NHSpecificTest/NH3141/ProxyIdFixture.cs index d43a3aaf481..a1dfcdef4e3 100644 --- a/src/NHibernate.Test/NHSpecificTest/NH3141/ProxyIdFixture.cs +++ b/src/NHibernate.Test/NHSpecificTest/NH3141/ProxyIdFixture.cs @@ -9,6 +9,11 @@ public class ProxyIdFixture : BugTestCase { private int id; + protected override bool AppliesTo(Dialect.Dialect dialect) + { + return TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator; + } + protected override void OnSetUp() { using (var s = OpenSession()) diff --git a/src/NHibernate.Test/NHSpecificTest/NH315/Fixture.cs b/src/NHibernate.Test/NHSpecificTest/NH315/Fixture.cs index 5b5279d0c8a..2adcae544c5 100644 --- a/src/NHibernate.Test/NHSpecificTest/NH315/Fixture.cs +++ b/src/NHibernate.Test/NHSpecificTest/NH315/Fixture.cs @@ -14,6 +14,11 @@ public override string BugNumber get { return "NH315"; } } + protected override bool AppliesTo(Dialect.Dialect dialect) + { + return TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator; + } + [Test] public void SaveClient() { @@ -43,4 +48,4 @@ public void SaveClient() } } } -} \ No newline at end of file +} diff --git a/src/NHibernate.Test/NHSpecificTest/NH3414/FixtureByCode.cs b/src/NHibernate.Test/NHSpecificTest/NH3414/FixtureByCode.cs index c58d1768136..8fc7299d3b6 100644 --- a/src/NHibernate.Test/NHSpecificTest/NH3414/FixtureByCode.cs +++ b/src/NHibernate.Test/NHSpecificTest/NH3414/FixtureByCode.cs @@ -12,7 +12,7 @@ public class ByCodeFixture : TestCaseMappingByCode protected override bool AppliesTo(Dialect.Dialect dialect) { // Test ordering by a scalar sub-select. - return Dialect.SupportsScalarSubSelects; + return TestDialect.SupportsAggregatingScalarSubSelectsInOrderBy; } protected override HbmMapping GetMappings() diff --git a/src/NHibernate.Test/NHSpecificTest/NH3436/Fixture.cs b/src/NHibernate.Test/NHSpecificTest/NH3436/Fixture.cs index be1ac06dc84..88b3a0a67d3 100644 --- a/src/NHibernate.Test/NHSpecificTest/NH3436/Fixture.cs +++ b/src/NHibernate.Test/NHSpecificTest/NH3436/Fixture.cs @@ -54,6 +54,11 @@ protected override void OnTearDown() [Test] public void TestQueryWithContainsInParallel() { + if (!TestDialect.SupportsConcurrencyTests) + { + Assert.Ignore($"Dialect {Dialect} does not supports concurrency tests"); + } + var ids = new List { Guid.NewGuid(), diff --git a/src/NHibernate.Test/NHSpecificTest/NH386/Fixture.cs b/src/NHibernate.Test/NHSpecificTest/NH386/Fixture.cs index 174af83a6b0..10352cac845 100644 --- a/src/NHibernate.Test/NHSpecificTest/NH386/Fixture.cs +++ b/src/NHibernate.Test/NHSpecificTest/NH386/Fixture.cs @@ -21,4 +21,4 @@ public void Query() } } } -} \ No newline at end of file +} diff --git a/src/NHibernate.Test/NHSpecificTest/NH440/Fixture.cs b/src/NHibernate.Test/NHSpecificTest/NH440/Fixture.cs index 32080c5fa3d..c40c1d4b6f2 100644 --- a/src/NHibernate.Test/NHSpecificTest/NH440/Fixture.cs +++ b/src/NHibernate.Test/NHSpecificTest/NH440/Fixture.cs @@ -1,4 +1,3 @@ -using System; using System.Collections; using NUnit.Framework; @@ -21,6 +20,11 @@ protected override IList Mappings get { return new string[] {"NHSpecificTest.NH440.Fruit.hbm.xml", "NHSpecificTest.NH440.Apple.hbm.xml"}; } } + protected override bool AppliesTo(Dialect.Dialect dialect) + { + return TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator; + } + protected override void OnSetUp() { @@ -139,4 +143,4 @@ public void StoreWithLinksAndLookupWithQueryFromFruit() } } } -} \ No newline at end of file +} diff --git a/src/NHibernate.Test/NHSpecificTest/NH473/Fixture.cs b/src/NHibernate.Test/NHSpecificTest/NH473/Fixture.cs index cae122f1407..e80bef95b52 100644 --- a/src/NHibernate.Test/NHSpecificTest/NH473/Fixture.cs +++ b/src/NHibernate.Test/NHSpecificTest/NH473/Fixture.cs @@ -1,13 +1,15 @@ -using System; -using System.Collections.Generic; -using System.Text; -using NUnit.Framework; +using NUnit.Framework; namespace NHibernate.Test.NHSpecificTest.NH473 { [TestFixture] public class Fixture:BugTestCase { + protected override bool AppliesTo(Dialect.Dialect dialect) + { + return TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator; + } + protected override void OnSetUp() { using(var session=this.OpenSession()) diff --git a/src/NHibernate.Test/NHSpecificTest/NH479/Fixture.cs b/src/NHibernate.Test/NHSpecificTest/NH479/Fixture.cs index f28fcc5ed40..d88498d957e 100644 --- a/src/NHibernate.Test/NHSpecificTest/NH479/Fixture.cs +++ b/src/NHibernate.Test/NHSpecificTest/NH479/Fixture.cs @@ -1,4 +1,3 @@ -using System; using NUnit.Framework; namespace NHibernate.Test.NHSpecificTest.NH479 @@ -11,6 +10,11 @@ public override string BugNumber get { return "NH479"; } } + protected override bool AppliesTo(Dialect.Dialect dialect) + { + return TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator; + } + [Test] public void MergeTest() { @@ -46,4 +50,4 @@ public void MergeTest() } } } -} \ No newline at end of file +} diff --git a/src/NHibernate.Test/NHSpecificTest/NH521/Fixture.cs b/src/NHibernate.Test/NHSpecificTest/NH521/Fixture.cs index 793b3cd568f..6333bcf5a36 100644 --- a/src/NHibernate.Test/NHSpecificTest/NH521/Fixture.cs +++ b/src/NHibernate.Test/NHSpecificTest/NH521/Fixture.cs @@ -10,6 +10,11 @@ public override string BugNumber get { return "NH521"; } } + protected override bool AppliesTo(Dialect.Dialect dialect) + { + return TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator; + } + [Test] public void AttachUninitProxyCausesInit() { @@ -57,4 +62,4 @@ public void AttachUninitProxyCausesInit() } } } -} \ No newline at end of file +} diff --git a/src/NHibernate.Test/NHSpecificTest/NH607/Fixture.cs b/src/NHibernate.Test/NHSpecificTest/NH607/Fixture.cs index 1e5045c17d3..756e1da1252 100644 --- a/src/NHibernate.Test/NHSpecificTest/NH607/Fixture.cs +++ b/src/NHibernate.Test/NHSpecificTest/NH607/Fixture.cs @@ -1,4 +1,3 @@ -using System; using NUnit.Framework; namespace NHibernate.Test.NHSpecificTest.NH607 @@ -11,6 +10,11 @@ public override string BugNumber get { return "NH607"; } } + protected override bool AppliesTo(Dialect.Dialect dialect) + { + return TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator; + } + [Test] public void Test() { @@ -43,4 +47,4 @@ public void Test() } } } -} \ No newline at end of file +} diff --git a/src/NHibernate.Test/NHSpecificTest/NH623/Fixture.cs b/src/NHibernate.Test/NHSpecificTest/NH623/Fixture.cs index 5bb1c16ee9f..371adb5cf2f 100644 --- a/src/NHibernate.Test/NHSpecificTest/NH623/Fixture.cs +++ b/src/NHibernate.Test/NHSpecificTest/NH623/Fixture.cs @@ -1,5 +1,6 @@ using System; using System.Collections; +using NHibernate.Dialect; using NUnit.Framework; namespace NHibernate.Test.NHSpecificTest.NH623 @@ -12,6 +13,11 @@ public override string BugNumber get { return "NH623"; } } + protected override bool AppliesTo(Dialect.Dialect dialect) + { + return !(dialect is HanaDialectBase); // The WHERE clause "isactive = '1'" doesn't work on HANA because idactive is a boolean + } + private ISession session; private ITransaction tran; @@ -71,4 +77,4 @@ public void WhereAttributesOnBags() Assert.AreEqual(1, d.Pages.Count); } } -} \ No newline at end of file +} diff --git a/src/NHibernate.Test/NHSpecificTest/NH643/Fixture.cs b/src/NHibernate.Test/NHSpecificTest/NH643/Fixture.cs index 8967d4356c8..e2fe3b8dbfc 100644 --- a/src/NHibernate.Test/NHSpecificTest/NH643/Fixture.cs +++ b/src/NHibernate.Test/NHSpecificTest/NH643/Fixture.cs @@ -1,4 +1,3 @@ -using System; using NUnit.Framework; namespace NHibernate.Test.NHSpecificTest.NH643 @@ -11,6 +10,11 @@ public override string BugNumber get { return "NH643"; } } + protected override bool AppliesTo(Dialect.Dialect dialect) + { + return TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator; + } + private object parentId; [Test] @@ -72,4 +76,4 @@ private void CheckChildrenCount(int count) } } } -} \ No newline at end of file +} diff --git a/src/NHibernate.Test/NHSpecificTest/NH687/Fixture.cs b/src/NHibernate.Test/NHSpecificTest/NH687/Fixture.cs index 843640e7c7d..4fd1bca6d9b 100644 --- a/src/NHibernate.Test/NHSpecificTest/NH687/Fixture.cs +++ b/src/NHibernate.Test/NHSpecificTest/NH687/Fixture.cs @@ -1,4 +1,3 @@ -using System; using NUnit.Framework; namespace NHibernate.Test.NHSpecificTest.NH687 @@ -11,6 +10,11 @@ public override string BugNumber get { return "NH687"; } } + protected override bool AppliesTo(Dialect.Dialect dialect) + { + return TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator; + } + [Test] public void GetQueryTest() { diff --git a/src/NHibernate.Test/NHSpecificTest/NH704/Fixture.cs b/src/NHibernate.Test/NHSpecificTest/NH704/Fixture.cs index be2482e3fad..e539583d2e5 100644 --- a/src/NHibernate.Test/NHSpecificTest/NH704/Fixture.cs +++ b/src/NHibernate.Test/NHSpecificTest/NH704/Fixture.cs @@ -1,4 +1,3 @@ -using System; using NUnit.Framework; namespace NHibernate.Test.NHSpecificTest.NH704 @@ -11,6 +10,11 @@ public override string BugNumber get { return "NH704"; } } + protected override bool AppliesTo(Dialect.Dialect dialect) + { + return TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator; + } + [Test] public void ReAttachCatTest() { @@ -35,4 +39,4 @@ public void ReAttachCatTest() } } } -} \ No newline at end of file +} diff --git a/src/NHibernate.Test/NHSpecificTest/NH826/Fixture.cs b/src/NHibernate.Test/NHSpecificTest/NH826/Fixture.cs index 88103136994..1c5d0c6d210 100644 --- a/src/NHibernate.Test/NHSpecificTest/NH826/Fixture.cs +++ b/src/NHibernate.Test/NHSpecificTest/NH826/Fixture.cs @@ -6,6 +6,11 @@ namespace NHibernate.Test.NHSpecificTest.NH826 [TestFixture] public class Fixture : BugTestCase { + protected override bool AppliesTo(Dialect.Dialect dialect) + { + return TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator; + } + [Test] public void Bug() { @@ -48,4 +53,4 @@ public void Bug() session.Close(); } } -} \ No newline at end of file +} diff --git a/src/NHibernate.Test/NHSpecificTest/NH830/AutoFlushTestFixture.cs b/src/NHibernate.Test/NHSpecificTest/NH830/AutoFlushTestFixture.cs index 15ee45a0f22..52dafb0a139 100644 --- a/src/NHibernate.Test/NHSpecificTest/NH830/AutoFlushTestFixture.cs +++ b/src/NHibernate.Test/NHSpecificTest/NH830/AutoFlushTestFixture.cs @@ -7,6 +7,11 @@ namespace NHibernate.Test.NHSpecificTest.NH830 [TestFixture] public class AutoFlushTestFixture : BugTestCase { + protected override bool AppliesTo(Dialect.Dialect dialect) + { + return TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator; + } + [Test] public void AutoFlushTest() { @@ -39,4 +44,4 @@ public void AutoFlushTest() sess.Close(); } } -} \ No newline at end of file +} diff --git a/src/NHibernate.Test/NHSpecificTest/NH898/NH898Fixture.cs b/src/NHibernate.Test/NHSpecificTest/NH898/NH898Fixture.cs index f77717854bc..978de34368d 100644 --- a/src/NHibernate.Test/NHSpecificTest/NH898/NH898Fixture.cs +++ b/src/NHibernate.Test/NHSpecificTest/NH898/NH898Fixture.cs @@ -1,6 +1,5 @@ using System; using System.Collections; - using NUnit.Framework; namespace NHibernate.Test.NHSpecificTest.NH898 @@ -22,6 +21,11 @@ protected override IList Mappings } } + protected override bool AppliesTo(Dialect.Dialect dialect) + { + return TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator; + } + [Test] public void Bug() { diff --git a/src/NHibernate.Test/NHSpecificTest/Properties/CompositePropertyRefTest.cs b/src/NHibernate.Test/NHSpecificTest/Properties/CompositePropertyRefTest.cs index 77893017777..4bbcca81380 100644 --- a/src/NHibernate.Test/NHSpecificTest/Properties/CompositePropertyRefTest.cs +++ b/src/NHibernate.Test/NHSpecificTest/Properties/CompositePropertyRefTest.cs @@ -10,6 +10,11 @@ public class CompositePropertyRefTest : BugTestCase private long p_id; private long p2_id; + protected override bool AppliesTo(Dialect.Dialect dialect) + { + return TestDialect.SupportsFKOnCompositeKeyWithBoolean; + } + protected override void OnSetUp() { using (var s = OpenSession()) diff --git a/src/NHibernate.Test/NHSpecificTest/Properties/DynamicEntityTest.cs b/src/NHibernate.Test/NHSpecificTest/Properties/DynamicEntityTest.cs index 7c5a7ba4b16..f981231b461 100644 --- a/src/NHibernate.Test/NHSpecificTest/Properties/DynamicEntityTest.cs +++ b/src/NHibernate.Test/NHSpecificTest/Properties/DynamicEntityTest.cs @@ -7,6 +7,11 @@ namespace NHibernate.Test.NHSpecificTest.Properties [TestFixture] public class DynamicEntityTest : BugTestCase { + protected override bool AppliesTo(Dialect.Dialect dialect) + { + return TestDialect.SupportsFKOnCompositeKeyWithBoolean; + } + protected override void OnSetUp() { using (var s = OpenSession()) diff --git a/src/NHibernate.Test/Operations/MergeFixture.cs b/src/NHibernate.Test/Operations/MergeFixture.cs index 201d3ee7233..66c4367f82d 100644 --- a/src/NHibernate.Test/Operations/MergeFixture.cs +++ b/src/NHibernate.Test/Operations/MergeFixture.cs @@ -361,6 +361,9 @@ public void MergeManaged() [Test] public void MergeManyToManyWithCollectionDeference() { + if (!TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator) + Assert.Ignore("Support of empty inserts is required"); + // setup base data... Competition competition; using (ISession s = OpenSession()) @@ -785,6 +788,9 @@ public void PersistThenMergeInSameTxnWithVersion() [Test] public void RecursiveMergeTransient() { + if (!TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator) + Assert.Ignore("Support of empty inserts is required"); + using (ISession s = OpenSession()) { using (ITransaction tx = s.BeginTransaction()) diff --git a/src/NHibernate.Test/ReadOnly/TextHolder.cs b/src/NHibernate.Test/ReadOnly/TextHolder.cs index 8b17f5107c1..f0561a59d5d 100644 --- a/src/NHibernate.Test/ReadOnly/TextHolder.cs +++ b/src/NHibernate.Test/ReadOnly/TextHolder.cs @@ -10,7 +10,7 @@ public class TextHolder /// public static bool SupportedForDialect(Dialect.Dialect dialect) { - return !(dialect is FirebirdDialect || dialect is Oracle8iDialect || dialect is MsSqlCeDialect); + return !(dialect is FirebirdDialect || dialect is Oracle8iDialect || dialect is MsSqlCeDialect || dialect is HanaRowStoreDialect); } diff --git a/src/NHibernate.Test/Stateless/StatelessSessionQueryFixture.cs b/src/NHibernate.Test/Stateless/StatelessSessionQueryFixture.cs index 562d0e56328..c20e8c2bea6 100644 --- a/src/NHibernate.Test/Stateless/StatelessSessionQueryFixture.cs +++ b/src/NHibernate.Test/Stateless/StatelessSessionQueryFixture.cs @@ -23,6 +23,11 @@ protected override void Configure(Configuration configuration) cfg.SetProperty(Environment.MaxFetchDepth, 1.ToString()); } + protected override bool AppliesTo(Dialect.Dialect dialect) + { + return TestDialect.SupportsEmptyInsertsOrHasNonIdentityNativeGenerator; + } + private class TestData { internal readonly IList list = new ArrayList(); @@ -115,4 +120,4 @@ public void Hql() testData.cleanData(); } } -} \ No newline at end of file +} diff --git a/src/NHibernate.Test/SystemTransactions/SystemTransactionFixture.cs b/src/NHibernate.Test/SystemTransactions/SystemTransactionFixture.cs index 12c4cc12d1d..cf0fe078414 100644 --- a/src/NHibernate.Test/SystemTransactions/SystemTransactionFixture.cs +++ b/src/NHibernate.Test/SystemTransactions/SystemTransactionFixture.cs @@ -179,8 +179,14 @@ public void CanUseSessionWithManyScopes(bool explicitFlush) // ODBC with SQL-Server always causes scopes to go distributed, which causes their transaction completion to run // asynchronously. But ODBC enlistment also check the previous transaction in a way that do not guard against it // being concurrently disposed of. See https://github.com/nhibernate/nhibernate-core/pull/1505 for more details. - Assume.That(!(Sfi.ConnectionProvider.Driver is OdbcDriver), - "ODBC sometimes fails on second scope by checking the previous transaction status, which may yield an object disposed exception"); + if (Sfi.ConnectionProvider.Driver is OdbcDriver) + Assert.Ignore("ODBC sometimes fails on second scope by checking the previous transaction status, which may yield an object disposed exception"); + // SAP HANA .Net provider always causes system transactions to be distributed, causing them to complete + // on concurrent threads. This creates race conditions when chaining scopes, the subsequent scope usage + // finding the connection still enlisted in the previous transaction, its complete being still not finished + // on its own thread. + if (Sfi.ConnectionProvider.Driver is HanaDriverBase) + Assert.Ignore("SAP HANA scope handling causes concurrency issues preventing chaining scope usages."); using (var s = WithOptions().ConnectionReleaseMode(ConnectionReleaseMode.OnClose).OpenSession()) { diff --git a/src/NHibernate.Test/SystemTransactions/SystemTransactionFixtureBase.cs b/src/NHibernate.Test/SystemTransactions/SystemTransactionFixtureBase.cs index 6a13a609c2a..5e587563a64 100644 --- a/src/NHibernate.Test/SystemTransactions/SystemTransactionFixtureBase.cs +++ b/src/NHibernate.Test/SystemTransactions/SystemTransactionFixtureBase.cs @@ -39,8 +39,12 @@ protected void DisableConnectionAutoEnlist(Configuration configuration) } // Purge any previous enlist connectionString = Regex.Replace( - connectionString, $"[^;\"a-zA-Z]*{autoEnlistmentKeywordPattern}=[^;\"]*", string.Empty, - RegexOptions.IgnoreCase | RegexOptions.Multiline); + connectionString, $"[^;\"a-zA-Z]*{autoEnlistmentKeywordPattern}=[^;\"]*;?", string.Empty, + RegexOptions.IgnoreCase); + // Avoid redundant semi-colon + connectionString = Regex.Replace( + connectionString, $";[/s]*$", string.Empty, + RegexOptions.IgnoreCase); connectionString += $";{autoEnlistmentKeyword}=false;"; configuration.SetProperty(Cfg.Environment.ConnectionString, connectionString); } @@ -143,4 +147,4 @@ public override void AfterTransactionCompletion(ITransaction tx) } } } -} \ No newline at end of file +} diff --git a/src/NHibernate.Test/SystemTransactions/TransactionNotificationFixture.cs b/src/NHibernate.Test/SystemTransactions/TransactionNotificationFixture.cs index 8960ce31d1b..5a8da0fc3fa 100644 --- a/src/NHibernate.Test/SystemTransactions/TransactionNotificationFixture.cs +++ b/src/NHibernate.Test/SystemTransactions/TransactionNotificationFixture.cs @@ -182,7 +182,6 @@ public void ShouldNotifyAfterDistributedTransactionWithOwnConnection(bool doComm { using (var tx = new TransactionScope()) { - ownConnection1.EnlistTransaction(System.Transactions.Transaction.Current); using (s1 = Sfi.WithOptions().Connection(ownConnection1).Interceptor(interceptor).OpenSession()) { s1.CreateCriteria().List(); diff --git a/src/NHibernate.Test/TestDialect.cs b/src/NHibernate.Test/TestDialect.cs index 68efde5d7f3..b18a5c556d9 100644 --- a/src/NHibernate.Test/TestDialect.cs +++ b/src/NHibernate.Test/TestDialect.cs @@ -1,4 +1,5 @@ using System; +using NHibernate.Id; using NHibernate.SqlTypes; namespace NHibernate.Test @@ -26,6 +27,12 @@ public TestDialect(Dialect.Dialect dialect) _dialect = dialect; } + /// + /// Has a native generator strategy resolving to identity. + /// + public bool HasIdentityNativeGenerator + => _dialect.NativeIdentifierGeneratorClass == typeof(IdentityGenerator); + public virtual bool SupportsOperatorAll => true; public virtual bool SupportsOperatorSome => true; public virtual bool SupportsLocate => true; @@ -58,6 +65,16 @@ public TestDialect(Dialect.Dialect dialect) /// public virtual bool SupportsEmptyInserts => true; + /// + /// Either supports inserting in a table without any column specified in the insert, or has a native + /// generator strategy resolving to something else than identity. + /// + /// This property is useful for cases where empty inserts happens only when the entities + /// generator is native while the dialect uses identity for this generator. + public bool SupportsEmptyInsertsOrHasNonIdentityNativeGenerator + => SupportsEmptyInserts || !HasIdentityNativeGenerator; + + /// /// Supports condition not bound to any data, like "where @p1 = @p2". /// @@ -80,5 +97,36 @@ public bool SupportsSqlType(SqlType sqlType) /// Supports the modulo operator on decimal types /// public virtual bool SupportsModuloOnDecimal => true; + + /// + /// Supports aggregating sub-selects in order by clause + /// + public virtual bool SupportsAggregatingScalarSubSelectsInOrderBy => _dialect.SupportsScalarSubSelects; + + /// + /// Supports order by and limits/top in correlated sub-queries + /// + public virtual bool SupportsOrderByAndLimitInSubQueries => true; + + /// + /// Supports selecting a double literal. + /// + public virtual bool SupportsSelectingDoubleLiteral => true; + + /// + /// Supports foreign keys on composite keys including a boolean column. + /// + public virtual bool SupportsFKOnCompositeKeyWithBoolean => true; + + /// + /// Supports tests involving concurrency. + /// + public virtual bool SupportsConcurrencyTests => true; + + /// + /// Supports batching together inserts/updates/Delets among which some depends (auto foreign key) on others + /// in the batch. + /// + public virtual bool SupportsBatchingDependentDML => true; } } diff --git a/src/NHibernate.Test/TestDialects/HanaColumnStoreTestDialect.cs b/src/NHibernate.Test/TestDialects/HanaColumnStoreTestDialect.cs new file mode 100644 index 00000000000..e85ef979b24 --- /dev/null +++ b/src/NHibernate.Test/TestDialects/HanaColumnStoreTestDialect.cs @@ -0,0 +1,17 @@ +namespace NHibernate.Test.TestDialects +{ + public class HanaColumnStoreTestDialect : HanaTestDialectBase + { + public HanaColumnStoreTestDialect(Dialect.Dialect dialect) + : base(dialect) + { + } + + /// + /// + /// When the target table is a column store, HANA 2 SP3 with its .Net data provider fails to process DML of + /// a batch of rows when some of them depends on other rows of the batch. + /// + public override bool SupportsBatchingDependentDML => false; + } +} diff --git a/src/NHibernate.Test/TestDialects/HanaRowStoreTestDialect.cs b/src/NHibernate.Test/TestDialects/HanaRowStoreTestDialect.cs new file mode 100644 index 00000000000..2f129f262f9 --- /dev/null +++ b/src/NHibernate.Test/TestDialects/HanaRowStoreTestDialect.cs @@ -0,0 +1,12 @@ +namespace NHibernate.Test.TestDialects +{ + public class HanaRowStoreTestDialect : HanaTestDialectBase + { + public HanaRowStoreTestDialect(Dialect.Dialect dialect) + : base(dialect) + { + } + + public override bool SupportsSelectForUpdateOnOuterJoin => false; + } +} diff --git a/src/NHibernate.Test/TestDialects/HanaTestDialectBase.cs b/src/NHibernate.Test/TestDialects/HanaTestDialectBase.cs new file mode 100644 index 00000000000..c44c8099854 --- /dev/null +++ b/src/NHibernate.Test/TestDialects/HanaTestDialectBase.cs @@ -0,0 +1,49 @@ +namespace NHibernate.Test.TestDialects +{ + public abstract class HanaTestDialectBase : TestDialect + { + protected HanaTestDialectBase(Dialect.Dialect dialect) + : base(dialect) + { + } + + public override bool SupportsComplexExpressionInGroupBy => false; + + public override bool SupportsEmptyInserts => false; + + /// + /// + /// Looks as a HANA 2 SP3 bug: HANA complains about the main select columns not being part of a group-by + /// or not being in an aggregation function, while only the sub-select in order by is grouped. + /// + public override bool SupportsAggregatingScalarSubSelectsInOrderBy => false; + + /// + /// + /// HANA 2 SP3 yields in such case: correlated subquery cannot have TOP or ORDER BY + /// + public override bool SupportsOrderByAndLimitInSubQueries => false; + + /// + /// + /// HANA 2 SP3 with its .Net data provider yields 0 instead of the value. + /// + public override bool SupportsSelectingDoubleLiteral => false; + + /// + /// + /// HANA 2 SP3 fails creating the foreign key with the message + /// "expression is of wrong type: cannot convert 'boolean' to 'varchar'". + /// + public override bool SupportsFKOnCompositeKeyWithBoolean => false; + + /// + /// + /// HANA 2 SP3 with its .Net data provider regularly fails to open connections in tests involving + /// many parallel connection openings. It yields a message beginning with "Could not open connection to:" + /// followed by the connection string, with a System.Runtime.InteropServices.SEHException inner + /// exception (External component has thrown an exception). + /// + public override bool SupportsConcurrencyTests => false; + } +} diff --git a/src/NHibernate.Test/TransactionTest/TransactionFixtureBase.cs b/src/NHibernate.Test/TransactionTest/TransactionFixtureBase.cs index 16c21294c78..f2530e91da6 100644 --- a/src/NHibernate.Test/TransactionTest/TransactionFixtureBase.cs +++ b/src/NHibernate.Test/TransactionTest/TransactionFixtureBase.cs @@ -87,4 +87,4 @@ public override void PreFlush(ICollection entitites) } } } -} \ No newline at end of file +} diff --git a/src/NHibernate/AdoNet/GenericBatchingBatcher.cs b/src/NHibernate/AdoNet/GenericBatchingBatcher.cs index 26074117c4a..83840f55cba 100644 --- a/src/NHibernate/AdoNet/GenericBatchingBatcher.cs +++ b/src/NHibernate/AdoNet/GenericBatchingBatcher.cs @@ -17,6 +17,7 @@ namespace NHibernate.AdoNet /// - FirebirdSql.Data.FirebirdClient /// - Oracle.ManagedDataAccess /// - System.Data.SqlServerCe + /// - Sap.Data.Hana /// public partial class GenericBatchingBatcher : AbstractBatcher { diff --git a/src/NHibernate/AdoNet/HanaBatchingBatcher.cs b/src/NHibernate/AdoNet/HanaBatchingBatcher.cs new file mode 100644 index 00000000000..545dc504865 --- /dev/null +++ b/src/NHibernate/AdoNet/HanaBatchingBatcher.cs @@ -0,0 +1,176 @@ +using System; +using System.Collections.Generic; +using System.Data.Common; +using System.Text; +using NHibernate.AdoNet.Util; +using NHibernate.Exceptions; + +namespace NHibernate.AdoNet +{ + /// + /// DML batcher for HANA. + /// By Jonathan Bregler + /// + public partial class HanaBatchingBatcher : AbstractBatcher + { + private int _batchSize; + private int _countOfCommands; + private int _totalExpectedRowsAffected; + private DbCommand _currentBatch; + private readonly IList _currentBatchCommands = new List(); + private StringBuilder _currentBatchCommandsLog; + + public HanaBatchingBatcher(ConnectionManager connectionManager, IInterceptor interceptor) + : base(connectionManager, interceptor) + { + _batchSize = Factory.Settings.AdoBatchSize; + //we always create this, because we need to deal with a scenario in which + //the user change the logging configuration at runtime. Trying to put this + //behind an if(log.IsDebugEnabled) will cause a null reference exception + //at that point. + _currentBatchCommandsLog = new StringBuilder().AppendLine("Batch commands:"); + } + + public override void AddToBatch(IExpectation expectation) + { + // HanaCommands are cloneable + if (!(CurrentCommand is ICloneable cloneableCurrentCommand)) + throw new InvalidOperationException("Current command is not an ICloneable"); + + var batchUpdate = CurrentCommand; + Prepare(batchUpdate); + Driver.AdjustCommand(batchUpdate); + + _totalExpectedRowsAffected += expectation.ExpectedRowCount; + string lineWithParameters = null; + var sqlStatementLogger = Factory.Settings.SqlStatementLogger; + if (sqlStatementLogger.IsDebugEnabled || Log.IsDebugEnabled()) + { + lineWithParameters = sqlStatementLogger.GetCommandLineWithParameters(batchUpdate); + var formatStyle = sqlStatementLogger.DetermineActualStyle(FormatStyle.Basic); + lineWithParameters = formatStyle.Formatter.Format(lineWithParameters); + _currentBatchCommandsLog.Append("command ") + .Append(_countOfCommands) + .Append(":") + .AppendLine(lineWithParameters); + } + if (Log.IsDebugEnabled()) + { + Log.Debug("Adding to batch:{0}", lineWithParameters); + } + + if (_currentBatch == null) + { + // use first command as the batching command + _currentBatch = cloneableCurrentCommand.Clone() as DbCommand; + } + + _currentBatchCommands.Add(cloneableCurrentCommand.Clone() as DbCommand); + + _countOfCommands++; + + if (_countOfCommands >= _batchSize) + { + DoExecuteBatch(batchUpdate); + } + } + + protected override void DoExecuteBatch(DbCommand ps) + { + Log.Info("Executing batch"); + CheckReaders(); + + if (Factory.Settings.SqlStatementLogger.IsDebugEnabled) + { + Factory.Settings.SqlStatementLogger.LogBatchCommand(_currentBatchCommandsLog.ToString()); + _currentBatchCommandsLog = new StringBuilder().AppendLine("Batch commands:"); + } + + try + { + int rowCount = 0; + + if (_countOfCommands > 0) + { + _currentBatch.Parameters.Clear(); + + foreach (var command in _currentBatchCommands) + { + // Batching with HANA works by simply defining multiple times each command parameter. + // (Undocumented feature explained by a developer of the provider.) + foreach (DbParameter parameter in command.Parameters) + { + _currentBatch.Parameters.Add(parameter); + } + } + + _currentBatch.Prepare(); + + try + { + rowCount = _currentBatch.ExecuteNonQuery(); + } + catch (DbException e) + { + throw ADOExceptionHelper.Convert(Factory.SQLExceptionConverter, e, "could not execute batch command."); + } + } + + Expectations.VerifyOutcomeBatched(_totalExpectedRowsAffected, rowCount); + } + finally + { + // Cleaning up even if batched outcome is invalid + _totalExpectedRowsAffected = 0; + _countOfCommands = 0; + CloseBatchCommands(); + } + } + + protected override int CountOfStatementsInCurrentBatch + { + get { return _countOfCommands; } + } + + public override int BatchSize + { + get { return _batchSize; } + set { _batchSize = value; } + } + + public override void CloseCommands() + { + base.CloseCommands(); + + CloseBatchCommands(); + } + + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + + CloseBatchCommands(); + } + + private void CloseBatchCommands() + { + try + { + foreach (var currentBatchCommand in _currentBatchCommands) + { + currentBatchCommand.Dispose(); + } + _currentBatchCommands.Clear(); + + _currentBatch?.Dispose(); + _currentBatch = null; + } + catch (Exception e) + { + // Prevent exceptions when clearing the batch from hiding any original exception + // (We do not know here if this batch closing occurs after a failure or not.) + Log.Warn(e, "Exception clearing batch"); + } + } + } +} diff --git a/src/NHibernate/AdoNet/HanaBatchingBatcherFactory.cs b/src/NHibernate/AdoNet/HanaBatchingBatcherFactory.cs new file mode 100644 index 00000000000..613fc4bcd54 --- /dev/null +++ b/src/NHibernate/AdoNet/HanaBatchingBatcherFactory.cs @@ -0,0 +1,12 @@ +using NHibernate.Engine; + +namespace NHibernate.AdoNet +{ + public class HanaBatchingBatcherFactory : IBatcherFactory + { + public virtual IBatcher CreateBatcher(ConnectionManager connectionManager, IInterceptor interceptor) + { + return new HanaBatchingBatcher(connectionManager, interceptor); + } + } +} diff --git a/src/NHibernate/Async/AdoNet/HanaBatchingBatcher.cs b/src/NHibernate/Async/AdoNet/HanaBatchingBatcher.cs new file mode 100644 index 00000000000..af028fedf37 --- /dev/null +++ b/src/NHibernate/Async/AdoNet/HanaBatchingBatcher.cs @@ -0,0 +1,130 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by AsyncGenerator. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + + +using System; +using System.Collections.Generic; +using System.Data.Common; +using System.Text; +using NHibernate.AdoNet.Util; +using NHibernate.Exceptions; + +namespace NHibernate.AdoNet +{ + using System.Threading.Tasks; + using System.Threading; + public partial class HanaBatchingBatcher : AbstractBatcher + { + + public override Task AddToBatchAsync(IExpectation expectation, CancellationToken cancellationToken) + { + // HanaCommands are cloneable + if (!(CurrentCommand is ICloneable cloneableCurrentCommand)) + throw new InvalidOperationException("Current command is not an ICloneable"); + if (cancellationToken.IsCancellationRequested) + { + return Task.FromCanceled(cancellationToken); + } + return InternalAddToBatchAsync(); + async Task InternalAddToBatchAsync() + { + + var batchUpdate = CurrentCommand; + await (PrepareAsync(batchUpdate, cancellationToken)).ConfigureAwait(false); + Driver.AdjustCommand(batchUpdate); + + _totalExpectedRowsAffected += expectation.ExpectedRowCount; + string lineWithParameters = null; + var sqlStatementLogger = Factory.Settings.SqlStatementLogger; + if (sqlStatementLogger.IsDebugEnabled || Log.IsDebugEnabled()) + { + lineWithParameters = sqlStatementLogger.GetCommandLineWithParameters(batchUpdate); + var formatStyle = sqlStatementLogger.DetermineActualStyle(FormatStyle.Basic); + lineWithParameters = formatStyle.Formatter.Format(lineWithParameters); + _currentBatchCommandsLog.Append("command ") + .Append(_countOfCommands) + .Append(":") + .AppendLine(lineWithParameters); + } + if (Log.IsDebugEnabled()) + { + Log.Debug("Adding to batch:{0}", lineWithParameters); + } + + if (_currentBatch == null) + { + // use first command as the batching command + _currentBatch = cloneableCurrentCommand.Clone() as DbCommand; + } + + _currentBatchCommands.Add(cloneableCurrentCommand.Clone() as DbCommand); + + _countOfCommands++; + + if (_countOfCommands >= _batchSize) + { + await (DoExecuteBatchAsync(batchUpdate, cancellationToken)).ConfigureAwait(false); + } + } + } + + protected override async Task DoExecuteBatchAsync(DbCommand ps, CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + Log.Info("Executing batch"); + await (CheckReadersAsync(cancellationToken)).ConfigureAwait(false); + + if (Factory.Settings.SqlStatementLogger.IsDebugEnabled) + { + Factory.Settings.SqlStatementLogger.LogBatchCommand(_currentBatchCommandsLog.ToString()); + _currentBatchCommandsLog = new StringBuilder().AppendLine("Batch commands:"); + } + + try + { + int rowCount = 0; + + if (_countOfCommands > 0) + { + _currentBatch.Parameters.Clear(); + + foreach (var command in _currentBatchCommands) + { + // Batching with HANA works by simply defining multiple times each command parameter. + // (Undocumented feature explained by a developer of the provider.) + foreach (DbParameter parameter in command.Parameters) + { + _currentBatch.Parameters.Add(parameter); + } + } + + _currentBatch.Prepare(); + + try + { + rowCount = await (_currentBatch.ExecuteNonQueryAsync(cancellationToken)).ConfigureAwait(false); + } + catch (DbException e) + { + throw ADOExceptionHelper.Convert(Factory.SQLExceptionConverter, e, "could not execute batch command."); + } + } + + Expectations.VerifyOutcomeBatched(_totalExpectedRowsAffected, rowCount); + } + finally + { + // Cleaning up even if batched outcome is invalid + _totalExpectedRowsAffected = 0; + _countOfCommands = 0; + CloseBatchCommands(); + } + } + } +} diff --git a/src/NHibernate/Dialect/Dialect.cs b/src/NHibernate/Dialect/Dialect.cs index 7cf2a77d7e2..26abe6bc081 100644 --- a/src/NHibernate/Dialect/Dialect.cs +++ b/src/NHibernate/Dialect/Dialect.cs @@ -2473,13 +2473,21 @@ public virtual string LowercaseFunction public virtual char StatementTerminator => ';'; /// - /// The syntax used to add a column to a table. Note this is deprecated + /// The syntax used to add a column to a table. /// public virtual string AddColumnString { get { throw new NotSupportedException("No add column syntax supported by Dialect"); } } + /// + /// The syntax for the suffix used to add a column to a table. + /// + public virtual string AddColumnSuffixString + { + get { return String.Empty; } + } + public virtual string DropForeignKeyString { get { return " drop constraint "; } diff --git a/src/NHibernate/Dialect/Function/SQLFunctionTemplate.cs b/src/NHibernate/Dialect/Function/SQLFunctionTemplate.cs index 0c2c9156ea2..976a5f0e127 100644 --- a/src/NHibernate/Dialect/Function/SQLFunctionTemplate.cs +++ b/src/NHibernate/Dialect/Function/SQLFunctionTemplate.cs @@ -101,7 +101,7 @@ public bool HasParenthesesIfNoArguments /// args function arguments /// generated SQL function call /// - public SqlString Render(IList args, ISessionFactoryImplementor factory) + public virtual SqlString Render(IList args, ISessionFactoryImplementor factory) { SqlStringBuilder buf = new SqlStringBuilder(); foreach (TemplateChunk tc in chunks) diff --git a/src/NHibernate/Dialect/Function/SQLFunctionTemplateWithRequiredParameters.cs b/src/NHibernate/Dialect/Function/SQLFunctionTemplateWithRequiredParameters.cs new file mode 100644 index 00000000000..ab722134e65 --- /dev/null +++ b/src/NHibernate/Dialect/Function/SQLFunctionTemplateWithRequiredParameters.cs @@ -0,0 +1,40 @@ +using System.Collections; +using System.Globalization; +using System.Text; +using System.Text.RegularExpressions; +using System.Linq; +using NHibernate.Engine; +using NHibernate.SqlCommand; +using NHibernate.Type; +using System; + +namespace NHibernate.Dialect.Function +{ + /// + /// A template-based SQL function which substitutes required missing parameters with defaults. + /// + [Serializable] + public class SQLFunctionTemplateWithRequiredParameters : SQLFunctionTemplate + { + private readonly object[] _requiredArgs; + + public SQLFunctionTemplateWithRequiredParameters(IType type, string template, object[] requiredArgs) : base(type, template) + { + _requiredArgs = requiredArgs; + } + + public SQLFunctionTemplateWithRequiredParameters(IType type, string template, object[] requiredArgs, bool hasParenthesesIfNoArgs) : base(type, template, hasParenthesesIfNoArgs) + { + _requiredArgs = requiredArgs; + } + + public override SqlString Render(IList args, ISessionFactoryImplementor factory) + { + var combinedArgs = + args.Cast() + .Concat(_requiredArgs.Skip(args.Count)) + .ToArray(); + return base.Render(combinedArgs, factory); + } + } +} diff --git a/src/NHibernate/Dialect/HanaColumnStoreDialect.cs b/src/NHibernate/Dialect/HanaColumnStoreDialect.cs new file mode 100644 index 00000000000..e508022f9b4 --- /dev/null +++ b/src/NHibernate/Dialect/HanaColumnStoreDialect.cs @@ -0,0 +1,34 @@ +using Environment = NHibernate.Cfg.Environment; + +namespace NHibernate.Dialect +{ + /// + /// A SQL dialect for the SAP HANA column store + /// + /// + /// The HanaColumnStoreDialect defaults the following configuration properties: + /// + /// + /// Property + /// Default Value + /// + /// + /// connection.driver_class + /// + /// + /// + /// + public class HanaColumnStoreDialect : HanaDialectBase + { + public HanaColumnStoreDialect() + { + DefaultProperties[Environment.ConnectionDriver] = typeof(NHibernate.Driver.HanaColumnStoreDriver).FullName; + } + + /// + public override string CreateTableString => "create column table"; + + /// + public override string CreateTemporaryTableString => "create local temporary column table"; + } +} diff --git a/src/NHibernate/Dialect/HanaDialectBase.cs b/src/NHibernate/Dialect/HanaDialectBase.cs new file mode 100644 index 00000000000..66fdd36437d --- /dev/null +++ b/src/NHibernate/Dialect/HanaDialectBase.cs @@ -0,0 +1,941 @@ +using System; +using System.Collections; +using System.Data; +using System.Data.Common; +using NHibernate.Dialect.Function; +using NHibernate.Dialect.Schema; +using NHibernate.Engine; +using NHibernate.SqlCommand; +using NHibernate.SqlTypes; +using NHibernate.Type; + +namespace NHibernate.Dialect +{ + /// + /// A SQL dialect base class for SAP HANA + /// + public abstract class HanaDialectBase : Dialect + { + [Serializable] + private class TypeConvertingVarArgsSQLFunction : ISQLFunction + { + private readonly string _begin; + private readonly string _sep; + private readonly string _end; + private SqlType _type; + + public TypeConvertingVarArgsSQLFunction(string begin, string sep, string end) + { + _begin = begin; + _sep = sep; + _end = end; + } + + #region ISQLFunction Members + + public IType ReturnType(IType columnType, IMapping mapping) + { + _type = columnType.SqlTypes(mapping)[0]; + return columnType; + } + + public bool HasArguments => true; + + public bool HasParenthesesIfNoArguments => true; + + public SqlString Render(IList args, ISessionFactoryImplementor factory) + { + var buf = new SqlStringBuilder().Add(_begin); + for (var i = 0; i < args.Count; i++) + { + var arg = args[i]; + if (arg is SqlString str && str.EqualsCaseInsensitive("?")) + { + buf.Add("cast("); + buf.AddObject(arg); + buf.Add(" as "); + buf.Add(factory.Dialect.GetCastTypeName(_type)); + buf.Add(")"); + } + else + { + buf.AddObject(arg); + } + if (i < args.Count - 1) buf.Add(_sep); + } + return buf.Add(_end).ToSqlString(); + } + + #endregion + } + + protected HanaDialectBase() + { + //string type + RegisterColumnType(DbType.AnsiStringFixedLength, "VARCHAR(255)"); + RegisterColumnType(DbType.AnsiStringFixedLength, 5000, "VARCHAR($l)"); + RegisterColumnType(DbType.AnsiStringFixedLength, 2147483647, "CLOB"); + RegisterColumnType(DbType.AnsiString, "VARCHAR(255)"); + RegisterColumnType(DbType.AnsiString, 5000, "VARCHAR($l)"); + RegisterColumnType(DbType.AnsiString, 2147483647, "CLOB"); + RegisterColumnType(DbType.StringFixedLength, "NVARCHAR(255)"); + RegisterColumnType(DbType.StringFixedLength, 5000, "NVARCHAR($l)"); + RegisterColumnType(DbType.StringFixedLength, 2147483647, "NCLOB"); + RegisterColumnType(DbType.String, "NVARCHAR(255)"); + RegisterColumnType(DbType.String, 5000, "NVARCHAR($l)"); + RegisterColumnType(DbType.String, 2147483647, "NCLOB"); + + //binary type: + RegisterColumnType(DbType.Binary, "VARBINARY(5000)"); + RegisterColumnType(DbType.Binary, 5000, "VARBINARY($l)"); + RegisterColumnType(DbType.Binary, 2147483647, "BLOB"); + + //Numeric type: + RegisterColumnType(DbType.Boolean, "BOOLEAN"); + RegisterColumnType(DbType.Byte, "TINYINT"); + RegisterColumnType(DbType.Currency, "DECIMAL(19, 4)"); + RegisterColumnType(DbType.Decimal, "DECIMAL(19, 5)"); + RegisterColumnType(DbType.Decimal, 29, "DECIMAL($p, $s)"); + RegisterColumnType(DbType.Double, "DOUBLE"); + RegisterColumnType(DbType.Int16, "SMALLINT"); + RegisterColumnType(DbType.Int32, "INTEGER"); + RegisterColumnType(DbType.Int64, "BIGINT"); + RegisterColumnType(DbType.Single, "FLOAT"); + RegisterColumnType(DbType.SByte, "SMALLINT"); + + //Date and time type: + RegisterColumnType(DbType.Date, "DATE"); + RegisterColumnType(DbType.DateTime, "TIMESTAMP"); + RegisterColumnType(DbType.Time, "TIME"); + + //special: + RegisterColumnType(DbType.Guid, "VARCHAR(36)"); + + RegisterKeywords(); + + //functions: + RegisterFunctions(); + } + + #region private static readonly string[] DialectKeywords = { ... } + + private static readonly string[] DialectKeywords = + { + "add", + "aes_decrypt", + "all", + "alphanum", + "alter", + "and", + "any", + "array", + "as", + "asc", + "attach", + "backup", + "begin", + "between", + "bigint", + "binary", + "bit", + "bottom", + "break", + "by", + "call", + "capability", + "cascade", + "case", + "cast", + "char", + "char_convert", + "character", + "check", + "checkpoint", + "close", + "comment", + "commit", + "compressed", + "conflict", + "connect", + "constraint", + "contains", + "continue", + "convert", + "create", + "cross", + "cube", + "current", + "current_timestamp", + "current_user", + "cursor", + "date", + "datetimeoffset", + "dbspace", + "deallocate", + "dec", + "decimal", + "declare", + "default", + "delete", + "deleting", + "desc", + "detach", + "distinct", + "do", + "double", + "drop", + "dynamic", + "else", + "elseif", + "encrypted", + "end", + "endif", + "escape", + "except", + "exception", + "exec", + "execute", + "existing", + "exists", + "externlogin", + "fetch", + "first", + "float", + "for", + "force", + "foreign", + "forward", + "from", + "full", + "goto", + "grant", + "group", + "having", + "holdlock", + "identified", + "if", + "in", + "index", + "inner", + "inout", + "insensitive", + "insert", + "inserting", + "install", + "instead", + "integer", + "integrated", + "intersect", + "into", + "iq", + "is", + "isolation", + "join", + "json", + "kerberos", + "key", + "lateral", + "left", + "like", + "limit", + "lock", + "login", + "long", + "match", + "membership", + "merge", + "message", + "mode", + "modify", + "natural", + "nchar", + "new", + "no", + "noholdlock", + "not", + "notify", + "null", + "numeric", + "nvarchar", + "of", + "off", + "on", + "open", + "openstring", + "openxml", + "option", + "options", + "or", + "order", + "others", + "out", + "outer", + "over", + "passthrough", + "precision", + "prepare", + "primary", + "print", + "privileges", + "proc", + "procedure", + "publication", + "raiserror", + "readtext", + "real", + "reference", + "references", + "refresh", + "release", + "remote", + "remove", + "rename", + "reorganize", + "resource", + "restore", + "restrict", + "return", + "revoke", + "right", + "rollback", + "rollup", + "row", + "rowtype", + "save", + "savepoint", + "scroll", + "seconddate", + "select", + "sensitive", + "session", + "set", + "setuser", + "share", + "shorttext", + "smalldecimal", + "smallint", + "some", + "spatial", + "sqlcode", + "sqlstate", + "start", + "stop", + "subtrans", + "subtransaction", + "synchronize", + "table", + "temporary", + "text", + "then", + "time", + "timestamp", + "tinyint", + "to", + "top", + "treat", + "trigger", + "truncate", + "tsequal", + "unbounded", + "union", + "unique", + "uniqueidentifier", + "unknown", + "unnest", + "unsigned", + "update", + "updating", + "user", + "using", + "validate", + "values", + "varbinary", + "varbit", + "varchar", + "variable", + "varray", + "varying", + "view", + "wait", + "waitfor", + "when", + "where", + "while", + "window", + "with", + "within", + "work", + "writetext", + "xml" + }; + + #endregion + + protected virtual void RegisterKeywords() + { + RegisterKeywords(DialectKeywords); + } + + protected virtual void RegisterFunctions() + { + RegisterHANAFunctions(); + RegisterNHibernateFunctions(); + } + + protected virtual void RegisterNHibernateFunctions() + { + RegisterFunction("band", new BitwiseFunctionOperation("bitand")); + RegisterFunction("bor", new BitwiseFunctionOperation("bitor")); + RegisterFunction("bxor", new BitwiseFunctionOperation("bitxor")); + RegisterFunction("bnot", new BitwiseFunctionOperation("bitnot")); + RegisterFunction("bit_length", new SQLFunctionTemplate(NHibernateUtil.Int32, "length(to_binary(?1))*8")); + RegisterFunction("ceiling", new StandardSQLFunction("ceil")); + RegisterFunction("chr", new StandardSQLFunction("char", NHibernateUtil.AnsiChar)); + RegisterFunction("date", new SQLFunctionTemplate(NHibernateUtil.Date, "to_date(?1)")); + RegisterFunction("iif", new SQLFunctionTemplate(null, "case when ?1 then ?2 else ?3 end")); + RegisterFunction("sysdate", new NoArgSQLFunction("current_timestamp", NHibernateUtil.DateTime, false)); + RegisterFunction("truncate", new SQLFunctionTemplateWithRequiredParameters(null, "floor(?1 * power(10, ?2)) / power(10, ?2)", new object[] { null, "0" })); + } + + protected virtual void RegisterHANAFunctions() + { + RegisterFunction("abap_alphanum", new StandardSQLFunction("abap_alphanum", NHibernateUtil.String)); + RegisterFunction("abap_lower", new StandardSQLFunction("abap_lower", NHibernateUtil.String)); + RegisterFunction("abap_numc", new StandardSQLFunction("abap_numc", NHibernateUtil.String)); + RegisterFunction("abap_upper", new StandardSQLFunction("abap_upper", NHibernateUtil.String)); + RegisterFunction("abs", new StandardSQLFunction("abs")); + RegisterFunction("acos", new StandardSQLFunction("acos", NHibernateUtil.Double)); + RegisterFunction("add_days", new StandardSQLFunction("add_days", NHibernateUtil.DateTime)); + RegisterFunction("add_months", new StandardSQLFunction("add_months", NHibernateUtil.DateTime)); + RegisterFunction("add_months_last", new StandardSQLFunction("add_months_last", NHibernateUtil.DateTime)); + RegisterFunction("add_seconds", new StandardSQLFunction("add_seconds", NHibernateUtil.DateTime)); + RegisterFunction("add_workdays", new StandardSQLFunction("add_workdays", NHibernateUtil.DateTime)); + RegisterFunction("add_years", new StandardSQLFunction("add_years", NHibernateUtil.DateTime)); + RegisterFunction("ascii", new StandardSQLFunction("ascii", NHibernateUtil.Int32)); + RegisterFunction("asin", new StandardSQLFunction("asin", NHibernateUtil.Double)); + RegisterFunction("atan", new StandardSQLFunction("atan", NHibernateUtil.Double)); + RegisterFunction("atan2", new StandardSQLFunction("atan2", NHibernateUtil.Double)); + RegisterFunction("auto_corr", new StandardSQLFunction("auto_corr", NHibernateUtil.Object)); + RegisterFunction("bintohex", new StandardSQLFunction("bintohex", NHibernateUtil.String)); + RegisterFunction("bintonhex", new StandardSQLFunction("bintonhex", NHibernateUtil.String)); + RegisterFunction("bintostr", new StandardSQLFunction("bintostr", NHibernateUtil.String)); + RegisterFunction("bitand", new StandardSQLFunction("bitand")); + RegisterFunction("bitcount", new StandardSQLFunction("bitcount", NHibernateUtil.Int32)); + RegisterFunction("bitnot", new StandardSQLFunction("bitnot")); + RegisterFunction("bitor", new StandardSQLFunction("bitor")); + RegisterFunction("bitset", new StandardSQLFunction("bitset", NHibernateUtil.Binary)); + RegisterFunction("bitunset", new StandardSQLFunction("bitunset", NHibernateUtil.Binary)); + RegisterFunction("bitxor", new StandardSQLFunction("bitxor")); + RegisterFunction("cardinality", new StandardSQLFunction("cardinality", NHibernateUtil.Int32)); + RegisterFunction("cast", new CastFunction()); + RegisterFunction("ceil", new StandardSQLFunction("ceil")); + RegisterFunction("char", new StandardSQLFunction("char", NHibernateUtil.AnsiChar)); + RegisterFunction("coalesce", new TypeConvertingVarArgsSQLFunction("coalesce(", ",", ")")); + RegisterFunction("concat", new VarArgsSQLFunction("(", " || ", ")")); + RegisterFunction("concat_naz", new StandardSQLFunction("concat_naz", NHibernateUtil.String)); + RegisterFunction("convert_currency", new VarArgsSQLFunction("convert_currency(", ",", ")")); + RegisterFunction("convert_unit", new VarArgsSQLFunction("convert_unit(", ",", ")")); + RegisterFunction("cos", new StandardSQLFunction("cos", NHibernateUtil.Double)); + RegisterFunction("cosh", new StandardSQLFunction("cosh", NHibernateUtil.Double)); + RegisterFunction("cot", new StandardSQLFunction("cot", NHibernateUtil.Double)); + RegisterFunction("current_connection", new NoArgSQLFunction("current_connection", NHibernateUtil.Int32)); + RegisterFunction("current_date", new NoArgSQLFunction("current_date", NHibernateUtil.DateTime, false)); + RegisterFunction("current_identity_value", new NoArgSQLFunction("current_identity_value", NHibernateUtil.Int64)); + RegisterFunction("current_mvcc_snapshot_timestamp", new NoArgSQLFunction("current_mvcc_snapshot_timestamp", NHibernateUtil.Int32)); + RegisterFunction("current_object_schema", new NoArgSQLFunction("current_object_schema", NHibernateUtil.String)); + RegisterFunction("current_schema", new NoArgSQLFunction("current_schema", NHibernateUtil.String, false)); + RegisterFunction("current_time", new NoArgSQLFunction("current_time", NHibernateUtil.DateTime, false)); + RegisterFunction("current_timestamp", new NoArgSQLFunction("current_timestamp", NHibernateUtil.DateTime, false)); + RegisterFunction("current_transaction_isolation_level", new NoArgSQLFunction("current_transaction_isolation_level", NHibernateUtil.String, false)); + RegisterFunction("current_update_statement_sequence", new NoArgSQLFunction("current_update_statement_sequence", NHibernateUtil.Int64)); + RegisterFunction("current_update_transaction", new NoArgSQLFunction("current_update_transaction", NHibernateUtil.Int64)); + RegisterFunction("current_user", new NoArgSQLFunction("current_user", NHibernateUtil.String, false)); + RegisterFunction("current_utcdate", new NoArgSQLFunction("current_utcdate", NHibernateUtil.DateTime, false)); + RegisterFunction("current_utctime", new NoArgSQLFunction("current_utctime", NHibernateUtil.DateTime, false)); + RegisterFunction("current_utctimestamp", new NoArgSQLFunction("current_utctimestamp", NHibernateUtil.DateTime, false)); + RegisterFunction("dayname", new StandardSQLFunction("dayname", NHibernateUtil.String)); + RegisterFunction("dayofmonth", new StandardSQLFunction("dayofmonth", NHibernateUtil.Int32)); + RegisterFunction("dayofyear", new StandardSQLFunction("dayofyear", NHibernateUtil.Int32)); + RegisterFunction("days_between", new StandardSQLFunction("days_between", NHibernateUtil.Int32)); + RegisterFunction("encryption_root_keys_extract_keys", new StandardSQLFunction("encryption_root_keys_extract_keys", NHibernateUtil.StringClob)); + RegisterFunction("encryption_root_keys_has_backup_password", new StandardSQLFunction("encryption_root_keys_has_backup_password", NHibernateUtil.Int16)); + RegisterFunction("escape_double_quotes", new StandardSQLFunction("escape_double_quotes", NHibernateUtil.String)); + RegisterFunction("escape_single_quotes", new StandardSQLFunction("escape_single_quotes", NHibernateUtil.String)); + RegisterFunction("exp", new StandardSQLFunction("exp", NHibernateUtil.Double)); + RegisterFunction("extract", new AnsiExtractFunction()); + RegisterFunction("floor", new StandardSQLFunction("floor")); + RegisterFunction("greatest", new VarArgsSQLFunction("greatest(", ",", ")")); + RegisterFunction("grouping", new StandardSQLFunction("grouping", NHibernateUtil.Int32)); + RegisterFunction("grouping_id", new StandardSQLFunction("grouping_id", NHibernateUtil.Int32)); + RegisterFunction("hamming_distance", new StandardSQLFunction("hamming_distance", NHibernateUtil.Int32)); + RegisterFunction("hash_md5", new StandardSQLFunction("hash_md5", NHibernateUtil.Binary)); + RegisterFunction("hash_sha256", new StandardSQLFunction("hash_sha256", NHibernateUtil.Binary)); + RegisterFunction("hextobin", new StandardSQLFunction("hextobin", NHibernateUtil.Binary)); + RegisterFunction("hour", new StandardSQLFunction("hour", NHibernateUtil.Int32)); + RegisterFunction("ifnull", new StandardSQLFunction("ifnull")); + RegisterFunction("indexing_error_code", new StandardSQLFunction("indexing_error_code", NHibernateUtil.Int32)); + RegisterFunction("indexing_error_message", new StandardSQLFunction("indexing_error_message", NHibernateUtil.String)); + RegisterFunction("indexing_status", new StandardSQLFunction("indexing_status", NHibernateUtil.String)); + RegisterFunction("initcap", new StandardSQLFunction("initcap", NHibernateUtil.String)); + RegisterFunction("is_sql_injection_safe", new StandardSQLFunction("is_sql_injection_safe", NHibernateUtil.Int32)); + RegisterFunction("isoweek", new StandardSQLFunction("isoweek", NHibernateUtil.Int32)); + RegisterFunction("language", new StandardSQLFunction("language", NHibernateUtil.String)); + RegisterFunction("last_day", new StandardSQLFunction("last_day", NHibernateUtil.DateTime)); + RegisterFunction("lcase", new StandardSQLFunction("lcase", NHibernateUtil.String)); + RegisterFunction("least", new VarArgsSQLFunction("least(", ",", ")")); + RegisterFunction("left", new StandardSQLFunction("left", NHibernateUtil.String)); + RegisterFunction("length", new StandardSQLFunction("length", NHibernateUtil.Int32)); + RegisterFunction("ln", new StandardSQLFunction("ln", NHibernateUtil.Double)); + RegisterFunction("localtoutc", new StandardSQLFunction("localtoutc", NHibernateUtil.DateTime)); + RegisterFunction("locate", new SQLFunctionTemplateWithRequiredParameters(NHibernateUtil.Int32, "locate(?2, ?1, ?3)", new object[] { null, null, "0" })); + RegisterFunction("locate_regexpr", new StandardSQLFunction("locate_regexpr", NHibernateUtil.Int32)); + RegisterFunction("log", new StandardSQLFunction("log", NHibernateUtil.Double)); + RegisterFunction("lower", new StandardSQLFunction("lower", NHibernateUtil.String)); + RegisterFunction("lpad", new StandardSQLFunction("lpad", NHibernateUtil.String)); + RegisterFunction("ltrim", new StandardSQLFunction("ltrim", NHibernateUtil.String)); + RegisterFunction("map", new VarArgsSQLFunction("map(", ",", ")")); + RegisterFunction("mimetype", new StandardSQLFunction("mimetype", NHibernateUtil.String)); + RegisterFunction("minute", new StandardSQLFunction("minute", NHibernateUtil.Int32)); + RegisterFunction("mod", new StandardSQLFunction("mod", NHibernateUtil.Int32)); + RegisterFunction("month", new StandardSQLFunction("month", NHibernateUtil.Int32)); + RegisterFunction("monthname", new StandardSQLFunction("monthname", NHibernateUtil.String)); + RegisterFunction("months_between", new StandardSQLFunction("months_between", NHibernateUtil.Int32)); + RegisterFunction("nano100_between", new StandardSQLFunction("nano100_between", NHibernateUtil.Int64)); + RegisterFunction("nchar", new StandardSQLFunction("nchar", NHibernateUtil.Character)); + RegisterFunction("ndiv0", new StandardSQLFunction("ndiv0", NHibernateUtil.Double)); + RegisterFunction("next_day", new StandardSQLFunction("next_day", NHibernateUtil.DateTime)); + RegisterFunction("newuid", new NoArgSQLFunction("newuid", NHibernateUtil.String)); + RegisterFunction("now", new NoArgSQLFunction("now", NHibernateUtil.DateTime)); + RegisterFunction("nullif", new StandardSQLFunction("nullif")); + RegisterFunction("occurrences_regexpr", new StandardSQLFunction("occurrences_regexpr", NHibernateUtil.Int32)); + RegisterFunction("plaintext", new StandardSQLFunction("plaintext", NHibernateUtil.String)); + RegisterFunction("power", new StandardSQLFunction("power", NHibernateUtil.Double)); + RegisterFunction("quarter", new StandardSQLFunction("quarter", NHibernateUtil.String)); + RegisterFunction("rand", new NoArgSQLFunction("rand", NHibernateUtil.Double)); + RegisterFunction("rand_secure", new NoArgSQLFunction("rand_secure", NHibernateUtil.Double)); + RegisterFunction("replace", new StandardSQLFunction("replace", NHibernateUtil.String)); + RegisterFunction("replace_regexpr", new StandardSQLFunction("replace_regexpr", NHibernateUtil.String)); + RegisterFunction("result_cache_id", new NoArgSQLFunction("result_cache_id", NHibernateUtil.Int64)); + RegisterFunction("result_cache_refresh_time", new NoArgSQLFunction("result_cache_refresh_time", NHibernateUtil.DateTime)); + RegisterFunction("right", new StandardSQLFunction("right", NHibernateUtil.String)); + RegisterFunction("round", new StandardSQLFunction("round")); + RegisterFunction("rpad", new StandardSQLFunction("rpad", NHibernateUtil.String)); + RegisterFunction("rtrim", new StandardSQLFunction("rtrim", NHibernateUtil.String)); + RegisterFunction("score", new NoArgSQLFunction("score", NHibernateUtil.Double)); + RegisterFunction("second", new StandardSQLFunction("second", NHibernateUtil.Double)); + RegisterFunction("seconds_between", new StandardSQLFunction("seconds_between", NHibernateUtil.Int64)); + RegisterFunction("session_context", new StandardSQLFunction("session_context", NHibernateUtil.String)); + RegisterFunction("session_user", new NoArgSQLFunction("session_user", NHibernateUtil.String, false)); + RegisterFunction("sign", new StandardSQLFunction("sign", NHibernateUtil.Int32)); + RegisterFunction("sin", new StandardSQLFunction("sin", NHibernateUtil.Double)); + RegisterFunction("sinh", new StandardSQLFunction("sinh", NHibernateUtil.Double)); + RegisterFunction("soundex", new StandardSQLFunction("soundex", NHibernateUtil.String)); + RegisterFunction("sqrt", new StandardSQLFunction("sqrt", NHibernateUtil.Double)); + RegisterFunction("stddev_pop", new StandardSQLFunction("stddev_pop", NHibernateUtil.Double)); + RegisterFunction("stddev_samp", new StandardSQLFunction("stddev_samp", NHibernateUtil.Double)); + RegisterFunction("string_agg", new StandardSQLFunction("String_agg", NHibernateUtil.String)); + RegisterFunction("strtobin", new StandardSQLFunction("strtobin", NHibernateUtil.BinaryBlob)); + RegisterFunction("subarray", new StandardSQLFunction("subarray")); + RegisterFunction("substr_after", new StandardSQLFunction("substr_after", NHibernateUtil.String)); + RegisterFunction("substr_before", new StandardSQLFunction("substr_before", NHibernateUtil.String)); + RegisterFunction("substring_regexpr", new StandardSQLFunction("substring_regexpr", NHibernateUtil.String)); + RegisterFunction("substring", new StandardSQLFunction("substring", NHibernateUtil.String)); + RegisterFunction("sysuuid", new NoArgSQLFunction("sysuuid", NHibernateUtil.String, false)); + RegisterFunction("tan", new StandardSQLFunction("tan", NHibernateUtil.Double)); + RegisterFunction("tanh", new StandardSQLFunction("tanh", NHibernateUtil.Double)); + RegisterFunction("to_alphanum", new StandardSQLFunction("to_alphanum", NHibernateUtil.String)); + RegisterFunction("to_bigint", new StandardSQLFunction("to_bigint", NHibernateUtil.Int64)); + RegisterFunction("to_binary", new StandardSQLFunction("to_binary", NHibernateUtil.Binary)); + RegisterFunction("to_blob", new StandardSQLFunction("to_blob", NHibernateUtil.BinaryBlob)); + RegisterFunction("to_clob", new StandardSQLFunction("to_clob", NHibernateUtil.StringClob)); + RegisterFunction("to_date", new StandardSQLFunction("to_date", NHibernateUtil.Date)); + RegisterFunction("to_dats", new StandardSQLFunction("to_dats", NHibernateUtil.String)); + RegisterFunction("to_decimal", new StandardSQLFunction("to_decimal", NHibernateUtil.Decimal)); + RegisterFunction("to_double", new StandardSQLFunction("to_double", NHibernateUtil.Double)); + RegisterFunction("to_fixedchar", new StandardSQLFunction("to_fixedchar", NHibernateUtil.Character)); + RegisterFunction("to_int", new StandardSQLFunction("to_int", NHibernateUtil.Int32)); + RegisterFunction("to_integer", new StandardSQLFunction("to_integer", NHibernateUtil.Int32)); + RegisterFunction("to_nclob", new StandardSQLFunction("to_nclob", NHibernateUtil.StringClob)); + RegisterFunction("to_nvarchar", new StandardSQLFunction("to_nvarchar", NHibernateUtil.String)); + RegisterFunction("to_real", new StandardSQLFunction("to_real", NHibernateUtil.Double)); + RegisterFunction("to_seconddate", new StandardSQLFunction("to_seconddate", NHibernateUtil.DateTime)); + RegisterFunction("to_smalldecimal", new StandardSQLFunction("to_smalldecimal", NHibernateUtil.Decimal)); + RegisterFunction("to_smallint", new StandardSQLFunction("to_smallint", NHibernateUtil.Int16)); + RegisterFunction("to_time", new StandardSQLFunction("to_time", NHibernateUtil.Time)); + RegisterFunction("to_timestamp", new StandardSQLFunction("to_timestamp", NHibernateUtil.DateTime)); + RegisterFunction("to_tinyint", new StandardSQLFunction("to_tinyint", NHibernateUtil.Byte)); + RegisterFunction("to_varchar", new StandardSQLFunction("to_varchar", NHibernateUtil.AnsiString)); + RegisterFunction("trim", new AnsiTrimFunction()); + RegisterFunction("trim_array", new StandardSQLFunction("trim_array")); + RegisterFunction("ucase", new StandardSQLFunction("ucase", NHibernateUtil.String)); + RegisterFunction("uminus", new StandardSQLFunction("uminus")); + RegisterFunction("unicode", new StandardSQLFunction("unicode", NHibernateUtil.Int32)); + RegisterFunction("upper", new StandardSQLFunction("upper", NHibernateUtil.String)); + RegisterFunction("utctolocal", new StandardSQLFunction("utctolocal", NHibernateUtil.DateTime)); + RegisterFunction("var_pop", new StandardSQLFunction("var_pop", NHibernateUtil.Double)); + RegisterFunction("var_samp", new StandardSQLFunction("var_samp", NHibernateUtil.Double)); + RegisterFunction("week", new StandardSQLFunction("week", NHibernateUtil.Int32)); + RegisterFunction("weekday", new StandardSQLFunction("weekday", NHibernateUtil.Int32)); + RegisterFunction("width_bucket", new StandardSQLFunction("width_bucket", NHibernateUtil.Int32)); + RegisterFunction("workdays_between", new StandardSQLFunction("workdays_between", NHibernateUtil.Int32)); + RegisterFunction("xmlextract", new StandardSQLFunction("xmlextract", NHibernateUtil.String)); + RegisterFunction("xmlextractvalue", new StandardSQLFunction("xmlextractvalue", NHibernateUtil.String)); + RegisterFunction("xmltable", new StandardSQLFunction("xmltable")); + RegisterFunction("year", new StandardSQLFunction("year", NHibernateUtil.Int32)); + RegisterFunction("years_between", new StandardSQLFunction("years_between", NHibernateUtil.Int32)); + + } + + #region DDL support + + /// + public override bool DropConstraints => false; + + /// + public override bool QualifyIndexName => false; + + public override bool SupportsCommentOn => true; + + public override string GetTableComment(string comment) + { + return "comment '" + comment + "'"; + } + + public override string GetColumnComment(string comment) + { + return "comment '" + comment + "'"; + } + + /// + public override bool SupportsColumnCheck => false; + + public override IDataBaseSchema GetDataBaseSchema(DbConnection connection) + { + return new HanaDataBaseSchema(connection); + } + + #endregion + + #region Lock acquisition support + + /// + public override bool UsesColumnsWithForUpdateOf => true; + + /// + public override string GetForUpdateString(string aliases) + { + return ForUpdateString + " of " + aliases; + } + + /// + public override string ForUpdateNowaitString + { + get { return ForUpdateString + " nowait"; } + } + + /// + public override string GetForUpdateNowaitString(string aliases) + { + return GetForUpdateString(aliases) + " nowait"; + } + + #endregion + + #region Table support + + #region Temporary table support + + /// + public override bool SupportsTemporaryTables => true; + + /// + public override string GenerateTemporaryTableName(string baseTableName) + { + return "#HT_" + baseTableName; + } + + /// + public override bool? PerformTemporaryTableDDLInIsolation() + { + return false; + } + + #endregion + + #endregion + + #region Callable statement support + + /// + public override int RegisterResultSetOutParameter(DbCommand statement, int position) + { + // Result set (TABLE) OUT parameters don't need to be registered + return position; + } + + #endregion + + #region Current timestamp support + + /// + public override bool SupportsCurrentTimestampSelection => true; + + /// + public override long TimestampResolutionInTicks + // According to https://help.sap.com/viewer/4fe29514fd584807ac9f2a04f6754767/2.0.02/en-US/3f81ccc7e35d44cbbc595c7d552c202a.html, + // it is supposed to have a 7 digits fractional second precision, but tests show only a 6 digits one. This is maybe a + // limitation of the data provider. + => 10L; + + #endregion + + #region Constraint support + + /// + public override string CascadeConstraintsString + { + get { return " cascade"; } + } + + #endregion + + #region Native identifier generation + + #region IDENTITY support + + /// + public override bool SupportsIdentityColumns => true; + + /// + public override string GetIdentitySelectString(string identityColumn, string tableName, DbType type) + { + return IdentitySelectString + tableName; + } + + /// + public override string IdentitySelectString + { + get { return "select current_identity_value() from "; } + } + + /// + public override string IdentityColumnString + { + get { return "generated by default as identity"; } + } + + #endregion + + #region SEQUENCE support + + /// + public override bool SupportsSequences => true; + + /// + public override bool SupportsPooledSequences => true; + + /// + public override string GetSequenceNextValString(string sequenceName) + { + // See https://help.sap.com/viewer/4fe29514fd584807ac9f2a04f6754767/2.0.02/en-US/20d509277519101489029c064d468c5d.html, + // this seems to be the recommended way of querying a sequence. + // SYS.DUMMY is a system table having normally one row. If someone has fiddled with it, this will cause failures... + return "select " + GetSelectSequenceNextValString(sequenceName) + " from sys.dummy"; + } + + /// + public override string GetDropSequenceString(string sequenceName) + { + return "drop sequence " + sequenceName; + } + + /// + public override string GetSelectSequenceNextValString(string sequenceName) + { + return sequenceName + ".nextval"; + } + + /// + public override string GetCreateSequenceString(string sequenceName) + { + return "create sequence " + sequenceName; + } + + /// + protected override string GetCreateSequenceString(string sequenceName, int initialValue, int incrementSize) + { + if (incrementSize == 0) + { + throw new MappingException("Unable to create the sequence [" + sequenceName + "]: the increment size must not be 0"); + } + + var createSequenceString = GetCreateSequenceString(sequenceName) + " start with " + initialValue + " increment by " + incrementSize; + if (incrementSize > 0) + { + if (initialValue < 1) + { + // default minvalue for an ascending sequence is 1 + createSequenceString += " minvalue " + initialValue; + } + } + else if (incrementSize < 0) + { + if (initialValue > -1) + { + // default maxvalue for a descending sequence is -1 + createSequenceString += " maxvalue " + initialValue; + } + } + return createSequenceString; + } + + /// + public override string QuerySequencesString + { + get { return "select sequence_name from sys.sequences"; } + } + + #endregion + + #endregion + + #region Miscellaneous support + + /// + public override string ToBooleanValueString(bool value) + { + return value ? "true" : "false"; + } + + #endregion + + #region Limit/offset support + + /// + public override bool SupportsLimit => true; + + /// + public override SqlString GetLimitString(SqlString queryString, SqlString offset, SqlString limit) + { + if (offset == null && limit == null) + { + return queryString; + } + + var limitBuilder = new SqlStringBuilder(queryString); + limitBuilder.Add(" limit "); + + if (limit == null) + { + limitBuilder.Add(uint.MaxValue.ToString()); + } + else + { + limitBuilder.Add(limit); + } + + if (offset != null) + { + limitBuilder.Add(" offset "); + limitBuilder.Add(offset); + } + + return limitBuilder.ToSqlString(); + } + + #endregion + + #region Union subclass support + + /// + public override string GetSelectClauseNullString(SqlType sqlType) + { + switch (sqlType.DbType) + { + case DbType.AnsiString: + case DbType.AnsiStringFixedLength: + case DbType.Guid: + return "to_varchar(null)"; + case DbType.Binary: + return "to_binary(null)"; + case DbType.Boolean: + return "cast(null as boolean)"; + case DbType.Byte: + return "to_tinyint(null)"; + case DbType.Currency: + case DbType.Decimal: + return "to_decimal(null)"; + case DbType.Date: + return "to_date(null)"; + case DbType.DateTime: + return "to_timestamp(null)"; + case DbType.Double: + return "to_double(null)"; + case DbType.Int16: + case DbType.SByte: + return "to_smallint(null)"; + case DbType.Int32: + return "to_integer(null)"; + case DbType.Int64: + return "to_bigint(null)"; + case DbType.Single: + return "to_real(null)"; + case DbType.String: + case DbType.StringFixedLength: + return "to_nvarchar(null)"; + case DbType.Time: + return "to_time(null)"; + } + return "null"; + } + + /// + public override bool SupportsUnionAll => true; + + #endregion + + #region Informational metadata + + /// + public override bool SupportsEmptyInList => false; + + /// + public override bool SupportsRowValueConstructorSyntax => false; // HANA supports this, but setting it to true causes the tests NH2294 and NH2394 to fail (see issue #1676) + + /// + public override bool SupportsRowValueConstructorSyntaxInInList => true; + + /// + public override bool SupportsExpectedLobUsagePattern => false; + + /// + public override bool SupportsUnboundedLobLocatorMaterialization => false; + + /// + public override bool SupportsExistsInSelect => false; + + #endregion + + /// + public override string SelectGUIDString + // SYS.DUMMY is a system table having normally one row. If someone has fiddled with it, this will cause failures... + => "select sysuuid from sys.dummy"; + + /// + public override bool IsCurrentTimestampSelectStringCallable => false; + + /// + public override string CurrentTimestampSelectString + // SYS.DUMMY is a system table having normally one row. If someone has fiddled with it, this will cause failures... + => "select current_timestamp from sys.dummy"; + + /// + public override int MaxAliasLength => 128; + + /// + public override string AddColumnString => "add ("; + + /// + public override string AddColumnSuffixString => ")"; + } +} diff --git a/src/NHibernate/Dialect/HanaRowStoreDialect.cs b/src/NHibernate/Dialect/HanaRowStoreDialect.cs new file mode 100644 index 00000000000..e94be1928b5 --- /dev/null +++ b/src/NHibernate/Dialect/HanaRowStoreDialect.cs @@ -0,0 +1,40 @@ +using Environment = NHibernate.Cfg.Environment; + +namespace NHibernate.Dialect +{ + /// + /// A SQL dialect for the SAP HANA row store + /// + /// + /// The HanaRowStoreDialect defaults the following configuration properties: + /// + /// + /// Property + /// Default Value + /// + /// + /// connection.driver_class + /// + /// + /// + /// + public class HanaRowStoreDialect : HanaDialectBase + { + public HanaRowStoreDialect() + { + DefaultProperties[Environment.ConnectionDriver] = typeof(NHibernate.Driver.HanaRowStoreDriver).FullName; + } + + /// + public override string CreateTableString => "create row table"; + + /// + public override string CreateTemporaryTableString => "create local temporary row table"; + + /// + public override bool SupportsOuterJoinForUpdate => false; + + /// + public override bool SupportsDistributedTransactions => false; + } +} diff --git a/src/NHibernate/Dialect/Schema/HanaMetaData.cs b/src/NHibernate/Dialect/Schema/HanaMetaData.cs new file mode 100644 index 00000000000..c1125d5bb32 --- /dev/null +++ b/src/NHibernate/Dialect/Schema/HanaMetaData.cs @@ -0,0 +1,159 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Data.Common; + +namespace NHibernate.Dialect.Schema +{ + public class HanaDataBaseSchema : AbstractDataBaseSchema + { + public HanaDataBaseSchema(DbConnection connection) : base(connection) + { + } + + public override ITableMetadata GetTableMetadata(DataRow rs, bool extras) + { + return new HanaTableMetadata(rs, this, extras); + } + + public override ISet GetReservedWords() + { + var result = new HashSet(StringComparer.OrdinalIgnoreCase); + DataTable dtReservedWords = Connection.GetSchema(DbMetaDataCollectionNames.ReservedWords); + foreach (DataRow row in dtReservedWords.Rows) + { + result.Add(row["reserved_word"].ToString()); + } + + if (IncludeDataTypesInReservedWords) + { + DataTable dtTypes = Connection.GetSchema(DbMetaDataCollectionNames.DataTypes); + foreach (DataRow row in dtTypes.Rows) + { + result.Add(row["TypeName"].ToString()); + } + } + + return result; + } + + public override DataTable GetTables(string catalog, string schemaPattern, string tableNamePattern, string[] types) + { + var restrictions = new[] { schemaPattern, tableNamePattern, null }; + DataTable objTbl = Connection.GetSchema("Tables", restrictions); + return objTbl; + } + + public override DataTable GetIndexInfo(string catalog, string schemaPattern, string tableName) + { + var restrictions = new[] { schemaPattern, tableName, null }; + DataTable objTbl = Connection.GetSchema("Indexes", restrictions); + return objTbl; + } + + public override DataTable GetIndexColumns(string catalog, string schemaPattern, string tableName, string indexName) + { + var restrictions = new[] { schemaPattern, tableName, indexName, null }; + DataTable objTbl = Connection.GetSchema("IndexColumns", restrictions); + return objTbl; + } + + public override DataTable GetColumns( + string catalog, + string schemaPattern, + string tableNamePattern, + string columnNamePattern) + { + var restrictions = new[] { schemaPattern, tableNamePattern, null }; + DataTable objTbl = Connection.GetSchema("Columns", restrictions); + return objTbl; + } + + public override DataTable GetForeignKeys(string catalog, string schema, string table) + { + var restrictions = new[] { schema, table, null }; + DataTable objTbl = Connection.GetSchema("ForeignKeys", restrictions); + return objTbl; + } + + public override bool StoresUpperCaseIdentifiers => true; + } + + public class HanaTableMetadata : AbstractTableMetadata + { + public HanaTableMetadata(DataRow rs, IDataBaseSchema meta, bool extras) : base(rs, meta, extras) + { + } + + protected override void ParseTableInfo(DataRow rs) + { + Catalog = null; + Schema = Convert.ToString(rs["TABLE_SCHEMA"]); + if (string.IsNullOrEmpty(Schema)) Schema = null; + Name = Convert.ToString(rs["TABLE_NAME"]); + } + + protected override string GetConstraintName(DataRow rs) + { + return Convert.ToString(rs["CONSTRAINT_NAME"]); + } + + protected override string GetColumnName(DataRow rs) + { + return Convert.ToString(rs["COLUMN_NAME"]); + } + + protected override string GetIndexName(DataRow rs) + { + return Convert.ToString(rs["INDEX_NAME"]); + } + + protected override IColumnMetadata GetColumnMetadata(DataRow rs) + { + return new HanaColumnMetadata(rs); + } + + protected override IForeignKeyMetadata GetForeignKeyMetadata(DataRow rs) + { + return new HanaForeignKeyMetadata(rs); + } + + protected override IIndexMetadata GetIndexMetadata(DataRow rs) + { + return new HanaIndexMetadata(rs); + } + } + + public class HanaColumnMetadata : AbstractColumnMetaData + { + public HanaColumnMetadata(DataRow rs) + : base(rs) + { + Name = Convert.ToString(rs["COLUMN_NAME"]); + + SetColumnSize(rs["CHARACTER_MAXIMUM_LENGTH"]); + SetNumericalPrecision(rs["NUMERIC_PRECISION"]); + + Nullable = Convert.ToString(rs["IS_NULLABLE"]); + TypeName = Convert.ToString(rs["DATA_TYPE"]); + } + } + + public class HanaIndexMetadata : AbstractIndexMetadata + { + public HanaIndexMetadata(DataRow rs) + : base(rs) + { + Name = Convert.ToString(rs["INDEX_NAME"]); + } + } + + public class HanaForeignKeyMetadata : AbstractForeignKeyMetadata + { + public HanaForeignKeyMetadata(DataRow rs) + : base(rs) + { + Name = Convert.ToString(rs["CONSTRAINT_NAME"]); + } + } +} diff --git a/src/NHibernate/Driver/HanaColumnStoreDriver.cs b/src/NHibernate/Driver/HanaColumnStoreDriver.cs new file mode 100644 index 00000000000..75c339767e6 --- /dev/null +++ b/src/NHibernate/Driver/HanaColumnStoreDriver.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace NHibernate.Driver +{ + /// + /// Provides a database driver for the SAP HANA column store. + /// + /// + /// + /// In order to use this driver you must have the assembly Sap.Data.Hana.v4.5.dll available for + /// NHibernate to load, including its dependencies (libadonetHDB.dll and libSQLDBCHDB.dll + /// are required by the assembly Sap.Data.Hana.v4.5.dll as of the time of this writing). + /// + /// + /// Please check the product's website + /// for any updates and/or documentation regarding SAP HANA. + /// + /// + public class HanaColumnStoreDriver : HanaDriverBase + { + } +} diff --git a/src/NHibernate/Driver/HanaDriverBase.cs b/src/NHibernate/Driver/HanaDriverBase.cs new file mode 100644 index 00000000000..aa01f55fe1e --- /dev/null +++ b/src/NHibernate/Driver/HanaDriverBase.cs @@ -0,0 +1,55 @@ +using NHibernate.AdoNet; + +namespace NHibernate.Driver +{ + /// + /// Provides a database driver base class for SAP HANA. + /// + public abstract class HanaDriverBase : ReflectionBasedDriver, IEmbeddedBatcherFactoryProvider + { + /// + /// Initializes a new instance of the class. + /// + /// + /// Thrown when the Sap.Data.Hana.v4.5 assembly can not be loaded. + /// + protected HanaDriverBase() : base( + "Sap.Data.Hana", + "Sap.Data.Hana.v4.5", + "Sap.Data.Hana.HanaConnection", + "Sap.Data.Hana.HanaCommand") + { + } + + /// + /// + /// Named parameters are not supported by the SAP HANA .Net provider. + /// https://help.sap.com/viewer/0eec0d68141541d1b07893a39944924e/2.0.02/en-US/d197835a6d611014a07fd73ee6fed6eb.html + /// + public override bool UseNamedPrefixInSql => false; + + /// + public override bool UseNamedPrefixInParameter => false; + + /// + public override string NamedPrefix => string.Empty; + + public override IResultSetsCommand GetResultSetsCommand(Engine.ISessionImplementor session) + { + return new BasicResultSetsCommand(session); + } + + /// + /// It does support it indeed, provided any previous transaction has finished completing. But scopes + /// are always promoted to distributed with HanaConnection, which causes them to complete on concurrent + /// threads. This creates race conditions with following a scope disposal. As this null enlistment feature + /// is here for attemptinng de-enlisting a connection from a completed transaction not yet cleaned-up, and as + /// HanaConnection does not handle such a case, better disable it. + /// + public override bool SupportsNullEnlistment => false; + + public override bool RequiresTimeSpanForTime => true; + + System.Type IEmbeddedBatcherFactoryProvider.BatcherFactoryClass => typeof(HanaBatchingBatcherFactory); + } +} diff --git a/src/NHibernate/Driver/HanaRowStoreDriver.cs b/src/NHibernate/Driver/HanaRowStoreDriver.cs new file mode 100644 index 00000000000..8b09bea9a9d --- /dev/null +++ b/src/NHibernate/Driver/HanaRowStoreDriver.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace NHibernate.Driver +{ + /// + /// Provides a database driver for the SAP HANA row store. + /// + /// + /// + /// In order to use this driver you must have the assembly Sap.Data.Hana.v4.5.dll available for + /// NHibernate to load, including its dependencies (libadonetHDB.dll and libSQLDBCHDB.dll + /// are required by the assembly Sap.Data.Hana.v4.5.dll as of the time of this writing). + /// + /// + /// Please check the product's website + /// for any updates and/or documentation regarding SAP HANA. + /// + /// + public class HanaRowStoreDriver : HanaDriverBase + { + /// + public override bool SupportsSystemTransactions => false; + } +} diff --git a/src/NHibernate/Mapping/Table.cs b/src/NHibernate/Mapping/Table.cs index 6e84c3f6965..c61ac35cec0 100644 --- a/src/NHibernate/Mapping/Table.cs +++ b/src/NHibernate/Mapping/Table.cs @@ -686,6 +686,7 @@ public string[] SqlAlterStrings(Dialect.Dialect dialect, IMapping p, ITableMetad alter.Append(dialect.GetColumnComment(columnComment)); } + alter.Append(dialect.AddColumnSuffixString); results.Add(alter.ToString()); }