diff --git a/src/NHibernate.Test/NHSpecificTest/NH1990/Fixture.cs b/src/NHibernate.Test/NHSpecificTest/NH1990/Fixture.cs new file mode 100644 index 00000000000..c06e5d061b5 --- /dev/null +++ b/src/NHibernate.Test/NHSpecificTest/NH1990/Fixture.cs @@ -0,0 +1,134 @@ +using System.Collections.Generic; +using System.Text; +using NHibernate.Criterion; +using NUnit.Framework; + +namespace NHibernate.Test.NHSpecificTest.NH1990 +{ + [TestFixture] + public class Fixture : BugTestCase + { + protected override void OnSetUp() + { + using (ISession s = OpenSession()) + { + using (ITransaction tx = s.BeginTransaction()) + { + for (int i = 0; i < 10; i++) + { + var feed = new NewsFeed + { + Url = string.Format("Feed{0}Uri", i), + Title = string.Format("Feed{0}", i), + Status = (i % 2 == 0 ? 1 : 2) + }; + s.Save(feed); + + for (int j = 0; j < 8; j++) + { + var item = new NewsItem + {Title = string.Format("Feed{0}Item{1}", i, j), Status = (j % 2 == 0 ? 1 : 2), Feed = feed}; + s.Save(item); + } + } + tx.Commit(); + } + } + } + + protected override void OnTearDown() + { + using (ISession s = OpenSession()) + { + using (ITransaction tx = s.BeginTransaction()) + { + s.Delete(string.Format("from {0}", typeof (NewsItem).Name)); + s.Delete(string.Format("from {0}", typeof (NewsFeed).Name)); + tx.Commit(); + } + } + } + + [Test] + public void FetchingBySubqueryFilterParameters() + { + using (ISession s = OpenSession()) + { + using (ITransaction tx = s.BeginTransaction()) + { + IFilter filter = s.EnableFilter("StatusFilter"); + filter.SetParameter("Status", 1); + + ICriteria criteria = s.CreateCriteria(typeof (NewsFeed), "NewsFeed"); + IList feeds = criteria.List(); + + Assert.That(feeds.Count, Is.EqualTo(5)); + foreach (NewsFeed feed in feeds) + { + Assert.That(feed.Items.Count, Is.EqualTo(4)); + } + + tx.Commit(); + } + } + } + + [Test] + public void FetchingBySubqueryFilterParametersAndPositionalParameters() + { + using (ISession s = OpenSession()) + { + using (ITransaction tx = s.BeginTransaction()) + { + IFilter filter = s.EnableFilter("StatusFilter"); + filter.SetParameter("Status", 1); + + ICriteria criteria = s.CreateCriteria(typeof (NewsFeed), "NewsFeed"); + criteria.Add(Restrictions.In("Url", new[] {"Feed2Uri", "Feed4Uri", "Feed8Uri"})); + + IList feeds = criteria.List(); + + Assert.That(feeds.Count, Is.EqualTo(3)); + foreach (NewsFeed feed in feeds) + { + Assert.That(feed.Items.Count, Is.EqualTo(4)); + } + + tx.Commit(); + } + } + } + + [Test] + public void FetchingBySubqueryFilterParametersAndPositionalParametersAndNamedParameters() + { + using (ISession s = OpenSession()) + { + using (ITransaction tx = s.BeginTransaction()) + { + IFilter filter = s.EnableFilter("StatusFilter"); + filter.SetParameter("Status", 1); + + var hql = new StringBuilder(); + hql.AppendLine("from NewsFeed"); + hql.AppendLine("where (Url = ? or Url = ?) and Title in (:TitleList)) "); + + IQuery query = s.CreateQuery(hql.ToString()); + query.SetString(0, "Feed4Uri"); + query.SetString(1, "Feed8Uri"); + query.SetParameterList("TitleList", new[] {"Feed2", "Feed4", "Feed8"}); + + IList feeds = query.List(); + + Assert.That(feeds.Count, Is.EqualTo(2)); + foreach (NewsFeed feed in feeds) + { + Assert.That(feed.Items.Count, Is.EqualTo(4)); + } + + tx.Commit(); + } + } + } + } +} diff --git a/src/NHibernate.Test/NHSpecificTest/NH1990/Mappings.hbm.xml b/src/NHibernate.Test/NHSpecificTest/NH1990/Mappings.hbm.xml new file mode 100644 index 00000000000..c9e513899f4 --- /dev/null +++ b/src/NHibernate.Test/NHSpecificTest/NH1990/Mappings.hbm.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/NHibernate.Test/NHSpecificTest/NH1990/Model.cs b/src/NHibernate.Test/NHSpecificTest/NH1990/Model.cs new file mode 100644 index 00000000000..4acb199d390 --- /dev/null +++ b/src/NHibernate.Test/NHSpecificTest/NH1990/Model.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; + +namespace NHibernate.Test.NHSpecificTest.NH1990 +{ + public class NewsFeed + { + public NewsFeed() + { + Items = new List(); + } + + public virtual Guid Id { get; set; } + public virtual string Title { get; set; } + public virtual string Url { get; set; } + public virtual int Status { get; set; } + public virtual IList Items { get; set; } + } + + public class NewsItem + { + public virtual Guid Id { get; set; } + public virtual string Title { get; set; } + public virtual int Status { get; set; } + public virtual NewsFeed Feed { get; set; } + } +} diff --git a/src/NHibernate.Test/NHibernate.Test.csproj b/src/NHibernate.Test/NHibernate.Test.csproj index 5bf1fe87475..451f9259566 100644 --- a/src/NHibernate.Test/NHibernate.Test.csproj +++ b/src/NHibernate.Test/NHibernate.Test.csproj @@ -617,6 +617,8 @@ + + @@ -1439,6 +1441,7 @@ + @@ -2032,6 +2035,7 @@ + diff --git a/src/NHibernate.Test/UtilityTest/BasicFormatterFixture.cs b/src/NHibernate.Test/UtilityTest/BasicFormatterFixture.cs new file mode 100644 index 00000000000..888a4e60338 --- /dev/null +++ b/src/NHibernate.Test/UtilityTest/BasicFormatterFixture.cs @@ -0,0 +1,23 @@ +using NHibernate.AdoNet.Util; +using NUnit.Framework; + +namespace NHibernate.Test.UtilityTest +{ + [TestFixture] + public class BasicFormatterFixture + { + [Test] + public void StringWithNestedDelimiters() + { + string formattedSql = null; + IFormatter formatter = new BasicFormatter(); + string sql = @"INSERT INTO Table (Name, id) VALUES (@p0, @p1); @p0 = 'a'(b', @p1 = 1"; + Assert.DoesNotThrow(() => formattedSql = formatter.Format(sql)); + Assert.That(formattedSql, Text.Contains("'a'(b'")); + + sql = @"UPDATE Table SET Column = @p0;@p0 = '(')'"; + Assert.DoesNotThrow(() => formattedSql = formatter.Format(sql)); + Assert.That(formattedSql, Text.Contains("'(')'")); + } + } +} diff --git a/src/NHibernate/AdoNet/Util/BasicFormatter.cs b/src/NHibernate/AdoNet/Util/BasicFormatter.cs index 124b41775ef..a4e716feaf1 100644 --- a/src/NHibernate/AdoNet/Util/BasicFormatter.cs +++ b/src/NHibernate/AdoNet/Util/BasicFormatter.cs @@ -79,6 +79,7 @@ private class FormatProcess private bool afterInsert; private bool afterOn; private bool beginLine = true; + private bool endCommandFound; private int indent = 1; private int inFunction; @@ -186,6 +187,7 @@ private void StartingNewQuery() { Out(); indent = 1; + endCommandFound = true; Newline(); } @@ -285,6 +287,7 @@ private void UpdateOrInsertOrDelete() { afterInsert = true; } + endCommandFound = false; } private void Select() @@ -296,6 +299,7 @@ private void Select() afterByOrFromOrSelects.Insert(afterByOrFromOrSelects.Count, afterByOrSetOrFromOrSelect); parensSinceSelect = 0; afterByOrSetOrFromOrSelect = true; + endCommandFound = false; } private void Out() @@ -353,6 +357,11 @@ private void Values() private void CloseParen() { + if (endCommandFound) + { + Out(); + return; + } parensSinceSelect--; if (parensSinceSelect < 0) { @@ -384,6 +393,11 @@ private void CloseParen() private void OpenParen() { + if(endCommandFound) + { + Out(); + return; + } if (IsFunctionName(lastToken) || inFunction > 0) { inFunction++; diff --git a/src/NHibernate/Loader/Collection/SubselectOneToManyLoader.cs b/src/NHibernate/Loader/Collection/SubselectOneToManyLoader.cs index b955a637b0a..f563e88b734 100644 --- a/src/NHibernate/Loader/Collection/SubselectOneToManyLoader.cs +++ b/src/NHibernate/Loader/Collection/SubselectOneToManyLoader.cs @@ -3,6 +3,7 @@ using NHibernate.Persister.Collection; using NHibernate.SqlCommand; using NHibernate.Type; +using NHibernate.Util; namespace NHibernate.Loader.Collection { @@ -31,8 +32,8 @@ public class SubselectOneToManyLoader : OneToManyLoader namedParameters = queryParameters.NamedParameters; // NH Different behavior: to deal with positionslParameter+NamedParameter+ParameterOfFilters - types = queryParameters.PositionalParameterTypes; - values = queryParameters.PositionalParameterValues; + types = new List(new JoinedEnumerable(queryParameters.FilteredParameterTypes, queryParameters.PositionalParameterTypes)).ToArray(); + values = new List(new JoinedEnumerable(queryParameters.FilteredParameterValues, queryParameters.PositionalParameterValues)).ToArray(); this.namedParameterLocMap = namedParameterLocMap; }