From 9f7c2325735e9a5743ffd357b6e96a97bdfc40a4 Mon Sep 17 00:00:00 2001 From: Sebastien Ros Date: Wed, 26 Sep 2012 16:08:44 -0700 Subject: [PATCH] #18809: Fixing duplicate results in Hql queries Work Item: 18809 --HG-- branch : 1.x --- .../Orchard.Tags/Projections/TagsFilter.cs | 29 +++++++++++++++++-- .../Projections/TagsFilterForms.cs | 13 +++++++-- .../ContentManagement/DefaultContentQuery.cs | 8 +++-- .../ContentManagement/DefaultHqlQuery.cs | 15 ++++++++-- 4 files changed, 56 insertions(+), 9 deletions(-) diff --git a/src/Orchard.Web/Modules/Orchard.Tags/Projections/TagsFilter.cs b/src/Orchard.Web/Modules/Orchard.Tags/Projections/TagsFilter.cs index 0dcbbca40..812e28892 100644 --- a/src/Orchard.Web/Modules/Orchard.Tags/Projections/TagsFilter.cs +++ b/src/Orchard.Web/Modules/Orchard.Tags/Projections/TagsFilter.cs @@ -34,8 +34,33 @@ namespace Orchard.Tags.Projections { string tags = Convert.ToString(context.State.TagIds); if (!String.IsNullOrEmpty(tags)) { var ids = tags.Split(new[] { ',' }).Select(Int32.Parse).ToArray(); - var query = (IHqlQuery)context.Query; - context.Query = query.Where(x => x.ContentPartRecord().Property("Tags", "tags"), x => x.In("TagRecord.Id", ids)); + + if (ids.Length == 0) { + return; + } + + int op = Convert.ToInt32(context.State.Operator); + + switch (op) { + case 0: + // is one of + Action s = alias => alias.ContentPartRecord().Property("Tags", "tags").Property("TagRecord", "tagRecord"); + Action f = x => x.InG("Id", ids); + context.Query.Where(s, f); + break; + case 1: + // is all of + foreach (var id in ids) { + int tagId = id; + Action selector = alias => alias.ContentPartRecord().Property("Tags", "tags" + tagId); + Action filter = x => x.Eq("TagRecord.Id", tagId); + context.Query.Where(selector, filter); + } + break; + case 2: + // is not one of can't be done without sub queries + break; + } } } diff --git a/src/Orchard.Web/Modules/Orchard.Tags/Projections/TagsFilterForms.cs b/src/Orchard.Web/Modules/Orchard.Tags/Projections/TagsFilterForms.cs index 532f560f5..a3220cf17 100644 --- a/src/Orchard.Web/Modules/Orchard.Tags/Projections/TagsFilterForms.cs +++ b/src/Orchard.Web/Modules/Orchard.Tags/Projections/TagsFilterForms.cs @@ -35,8 +35,17 @@ namespace Orchard.Tags.Projections { Description: T("Select some tags."), Size: 10, Multiple: true - ) - ); + ), + _Exclusion: Shape.FieldSet( + _OperatorOneOf: Shape.Radio( + Id: "operator-is-one-of", Name: "Operator", + Title: T("Is one of"), Value: "0", Checked: true + ), + _OperatorIsAllOf: Shape.Radio( + Id: "operator-is-all-of", Name: "Operator", + Title: T("Is all of"), Value: "1" + ) + )); foreach (var tag in _tagService.GetTags()) { f._Tags.Add(new SelectListItem { Value = tag.Id.ToString(), Text = tag.TagName }); diff --git a/src/Orchard/ContentManagement/DefaultContentQuery.cs b/src/Orchard/ContentManagement/DefaultContentQuery.cs index feb533453..60511c856 100644 --- a/src/Orchard/ContentManagement/DefaultContentQuery.cs +++ b/src/Orchard/ContentManagement/DefaultContentQuery.cs @@ -10,17 +10,20 @@ using Orchard.ContentManagement.Records; using Orchard.Data; using NHibernate.Transform; using NHibernate.SqlCommand; +using Orchard.Environment.Configuration; using Orchard.Utility.Extensions; namespace Orchard.ContentManagement { public class DefaultContentQuery : IContentQuery { private readonly ISessionLocator _sessionLocator; + private readonly ShellSettings _shellSettings; private ISession _session; private ICriteria _itemVersionCriteria; private VersionOptions _versionOptions; - public DefaultContentQuery(IContentManager contentManager, ISessionLocator sessionLocator) { + public DefaultContentQuery(IContentManager contentManager, ISessionLocator sessionLocator, ShellSettings shellSettings) { _sessionLocator = sessionLocator; + _shellSettings = shellSettings; ContentManager = contentManager; } @@ -51,7 +54,7 @@ namespace Orchard.ContentManagement { ICriteria BindItemVersionCriteria() { if (_itemVersionCriteria == null) { _itemVersionCriteria = BindSession().CreateCriteria(); - _itemVersionCriteria.SetCacheable(true); + _itemVersionCriteria.SetCacheable(true).SetCacheRegion(_shellSettings.Name); } return _itemVersionCriteria; } @@ -142,6 +145,7 @@ namespace Orchard.ContentManagement { if (count != 0) { criteria = criteria.SetMaxResults(count); } + return criteria .List() .Select(x => ContentManager.Get(x.Id, VersionOptions.VersionRecord(x.Id))) diff --git a/src/Orchard/ContentManagement/DefaultHqlQuery.cs b/src/Orchard/ContentManagement/DefaultHqlQuery.cs index 4228fe015..bf20968e7 100644 --- a/src/Orchard/ContentManagement/DefaultHqlQuery.cs +++ b/src/Orchard/ContentManagement/DefaultHqlQuery.cs @@ -5,6 +5,7 @@ using System.Globalization; using System.Linq; using System.Text; using NHibernate; +using NHibernate.Transform; using Orchard.ContentManagement.Records; using Orchard.Utility.Extensions; @@ -158,12 +159,15 @@ namespace Orchard.ContentManagement { public IEnumerable Slice(int skip, int count) { ApplyHqlVersionOptionsRestrictions(_versionOptions); var hql = ToHql(false); - var query = _session.CreateQuery(hql); + var query = _session + .CreateQuery(hql) + .SetCacheable(true) + .SetResultTransformer(new DistinctRootEntityResultTransformer()); if (skip != 0) { query.SetFirstResult(skip); } - if (count != 0) { + if (count != 0 && count != Int32.MaxValue) { query.SetMaxResults(count); } @@ -174,7 +178,12 @@ namespace Orchard.ContentManagement { public int Count() { ApplyHqlVersionOptionsRestrictions(_versionOptions); - return Convert.ToInt32(_session.CreateQuery(ToHql(true)).UniqueResult()); + return Convert.ToInt32( + _session.CreateQuery(ToHql(true)) + .SetCacheable(true) + .SetResultTransformer(new DistinctRootEntityResultTransformer()) + .UniqueResult() + ); } public string ToHql(bool count) {