From a094efac2d8394a4e89d3b96a56864b26f159e95 Mon Sep 17 00:00:00 2001 From: Sebastien Ros Date: Thu, 23 May 2013 11:15:15 -0700 Subject: [PATCH] #19703, 19209: Fixing Hql queries with duplicated roots Work Items: 19703, 19209 --HG-- branch : 1.x --- .../ContentManagement/HqlExpressionTests.cs | 25 ++++++++++ .../DefaultContentManager.cs | 13 +++-- .../ContentManagement/DefaultHqlQuery.cs | 48 ++++++++++++++----- .../ContentManagement/IContentManager.cs | 1 + 4 files changed, 70 insertions(+), 17 deletions(-) diff --git a/src/Orchard.Tests/ContentManagement/HqlExpressionTests.cs b/src/Orchard.Tests/ContentManagement/HqlExpressionTests.cs index 2341f2e2c..92b9c0b76 100644 --- a/src/Orchard.Tests/ContentManagement/HqlExpressionTests.cs +++ b/src/Orchard.Tests/ContentManagement/HqlExpressionTests.cs @@ -953,6 +953,31 @@ namespace Orchard.Tests.ContentManagement { Assert.That(firstResults.Distinct().Count(), Is.GreaterThan(1)); } + [Test] + public void ShouldSortByProperty() { + var dt = new DateTime(1980, 1, 1); + + _manager.Create("lambda", init => { + init.Record.IntegerStuff = 1; + }); + + _manager.Create("lambda", init => { + init.Record.IntegerStuff = 2; + }); + + _manager.Create("lambda", init => { + init.Record.IntegerStuff = 3; + }); + _session.Flush(); + + var results =_manager.HqlQuery().Join(alias => alias.ContentPartRecord()).OrderBy(x => x.ContentPartRecord(), order => order.Asc("IntegerStuff")).List(); + Assert.That(results.Count(), Is.EqualTo(3)); + + Assert.That(results.Skip(0).First().As().Record.IntegerStuff, Is.EqualTo(1)); + Assert.That(results.Skip(1).First().As().Record.IntegerStuff, Is.EqualTo(2)); + Assert.That(results.Skip(2).First().As().Record.IntegerStuff, Is.EqualTo(3)); + } + [Test] public void ShouldQueryUsingOperatorNot() { var dt = new DateTime(1980, 1, 1); diff --git a/src/Orchard/ContentManagement/DefaultContentManager.cs b/src/Orchard/ContentManagement/DefaultContentManager.cs index df256cc19..e1fa2d006 100644 --- a/src/Orchard/ContentManagement/DefaultContentManager.cs +++ b/src/Orchard/ContentManagement/DefaultContentManager.cs @@ -289,9 +289,10 @@ namespace Orchard.ContentManagement { return itemsById.TryGetValue(id, out values) ? values : Enumerable.Empty(); }).AsPart().ToArray(); } - - public IEnumerable GetManyByVersionId(IEnumerable versionRecordIds, QueryHints hints) where T : class, IContent { - var contentItemVersionRecords = GetManyImplementation(hints, (contentItemCriteria, contentItemVersionCriteria) => + + + public IEnumerable GetManyByVersionId(IEnumerable versionRecordIds, QueryHints hints) { + var contentItemVersionRecords = GetManyImplementation(hints, (contentItemCriteria, contentItemVersionCriteria) => contentItemVersionCriteria.Add(Restrictions.In("Id", versionRecordIds.ToArray()))); var itemsById = contentItemVersionRecords @@ -302,7 +303,11 @@ namespace Orchard.ContentManagement { return versionRecordIds.SelectMany(id => { IGrouping values; return itemsById.TryGetValue(id, out values) ? values : Enumerable.Empty(); - }).AsPart().ToArray(); + }).ToArray(); + } + + public IEnumerable GetManyByVersionId(IEnumerable versionRecordIds, QueryHints hints) where T : class, IContent { + return GetManyByVersionId(versionRecordIds, hints).AsPart(); } private IEnumerable GetManyImplementation(QueryHints hints, Action predicate) { diff --git a/src/Orchard/ContentManagement/DefaultHqlQuery.cs b/src/Orchard/ContentManagement/DefaultHqlQuery.cs index 8d0b7768d..d9dd6338b 100644 --- a/src/Orchard/ContentManagement/DefaultHqlQuery.cs +++ b/src/Orchard/ContentManagement/DefaultHqlQuery.cs @@ -159,10 +159,11 @@ namespace Orchard.ContentManagement { public IEnumerable Slice(int skip, int count) { ApplyHqlVersionOptionsRestrictions(_versionOptions); var hql = ToHql(false); + var query = _session .CreateQuery(hql) .SetCacheable(true) - .SetResultTransformer(new DistinctRootEntityResultTransformer()); + ; if (skip != 0) { query.SetFirstResult(skip); @@ -171,29 +172,49 @@ namespace Orchard.ContentManagement { query.SetMaxResults(count); } - return query.List() - .Select(x => ContentManager.Get(x.Id, VersionOptions.VersionRecord(x.Id))) - .ToReadOnlyCollection(); + var ids = query + .SetResultTransformer(Transformers.AliasToEntityMap) + .List() + .Select(x => (int)x["Id"]); + + return ContentManager.GetManyByVersionId(ids, QueryHints.Empty); } public int Count() { ApplyHqlVersionOptionsRestrictions(_versionOptions); - return Convert.ToInt32( - _session.CreateQuery(ToHql(true)) - .SetCacheable(true) - .SetResultTransformer(new DistinctRootEntityResultTransformer()) - .UniqueResult() - ); + var hql = ToHql(true); + hql = "select count(Id) from Orchard.ContentManagement.Records.ContentItemVersionRecord where Id in ( " + hql + " )"; + return Convert.ToInt32(_session.CreateQuery(hql) + .SetCacheable(true) + .UniqueResult()) + ; } public string ToHql(bool count) { var sb = new StringBuilder(); if (count) { - sb.Append("select count(civ) ").AppendLine(); + sb.Append("select distinct civ.Id as Id").AppendLine(); } else { - sb.Append("select civ ").AppendLine(); + sb.Append("select distinct civ.Id as Id"); + + // add sort properties in the select + foreach (var sort in _sortings) { + var sortFactory = new DefaultHqlSortFactory(); + sort.Item2(sortFactory); + + if (!sortFactory.Randomize) { + sb.Append(", "); + sb.Append(sort.Item1.Name).Append(".").Append(sortFactory.PropertyName); + } + else { + // select distinct can't be used with newid() + sb.Replace("select distinct", "select "); + } + } + + sb.AppendLine(); } sb.Append("from ").Append(_from.TableName).Append(" as ").Append(_from.Name).AppendLine(); @@ -232,7 +253,8 @@ namespace Orchard.ContentManagement { sort.Item2(sortFactory); if (sortFactory.Randomize) { - sb.Append(" newid()"); + //sb.Append(" newid()"); + sb.Append("newid()"); } else { sb.Append(sort.Item1.Name).Append(".").Append(sortFactory.PropertyName); diff --git a/src/Orchard/ContentManagement/IContentManager.cs b/src/Orchard/ContentManagement/IContentManager.cs index 3c36b0e5b..37d610b11 100644 --- a/src/Orchard/ContentManagement/IContentManager.cs +++ b/src/Orchard/ContentManagement/IContentManager.cs @@ -63,6 +63,7 @@ namespace Orchard.ContentManagement { IEnumerable GetMany(IEnumerable ids, VersionOptions options, QueryHints hints) where T : class, IContent; IEnumerable GetManyByVersionId(IEnumerable versionRecordIds, QueryHints hints) where T : class, IContent; + IEnumerable GetManyByVersionId(IEnumerable versionRecordIds, QueryHints hints); void Publish(IContent content); void Unpublish(IContent content);