From efa37e1d7a1ac034a5b284ab994c7b8dd7a472bc Mon Sep 17 00:00:00 2001 From: Bertrand Le Roy Date: Thu, 6 Feb 2014 17:43:58 -0800 Subject: [PATCH] Added join types and join condition expressions on HQL API --- .../ContentManagement/DefaultHqlQuery.cs | 48 ++++++++++++------- src/Orchard/ContentManagement/IHqlQuery.cs | 9 +++- 2 files changed, 39 insertions(+), 18 deletions(-) diff --git a/src/Orchard/ContentManagement/DefaultHqlQuery.cs b/src/Orchard/ContentManagement/DefaultHqlQuery.cs index 5ffffb40e..59583999e 100644 --- a/src/Orchard/ContentManagement/DefaultHqlQuery.cs +++ b/src/Orchard/ContentManagement/DefaultHqlQuery.cs @@ -52,17 +52,17 @@ namespace Orchard.ContentManagement { return tuple == null ? null : tuple.Item2; } - internal IAlias BindCriteriaByPath(IAlias alias, string path) { - return BindCriteriaByAlias(alias, path, PathToAlias(path)); + internal IAlias BindCriteriaByPath(IAlias alias, string path, string type = null, Action withPredicate = null) { + return BindCriteriaByAlias(alias, path, PathToAlias(path), type, withPredicate); } - internal IAlias BindCriteriaByAlias(IAlias alias, string path, string aliasName) { + internal IAlias BindCriteriaByAlias(IAlias alias, string path, string aliasName, string type = null, Action withPredicate = null) { // is this Join already existing (based on aliasName) Join join = BindNamedAlias(aliasName); if (join == null) { - join = new Join(path, aliasName); + join = new Join(path, aliasName, type, withPredicate); _joins.Add(new Tuple(alias, join)); } @@ -88,19 +88,19 @@ namespace Orchard.ContentManagement { return _from; } - internal IAlias BindPartCriteria() where TRecord : ContentPartRecord { - return BindPartCriteria(typeof(TRecord)); + internal IAlias BindPartCriteria(string type = null, Action withPredicate = null) where TRecord : ContentPartRecord { + return BindPartCriteria(typeof(TRecord), type, withPredicate); } - internal IAlias BindPartCriteria(Type contentPartRecordType) { + internal IAlias BindPartCriteria(Type contentPartRecordType, string type = null, Action withPredicate = null) { if (!contentPartRecordType.IsSubclassOf(typeof(ContentPartRecord))) { throw new ArgumentException("The type must inherit from ContentPartRecord", "contentPartRecordType"); } if (contentPartRecordType.IsSubclassOf(typeof(ContentPartVersionRecord))) { - return BindCriteriaByPath(BindItemVersionCriteria(), contentPartRecordType.Name); + return BindCriteriaByPath(BindItemVersionCriteria(), contentPartRecordType.Name, type, withPredicate); } - return BindCriteriaByPath(BindItemCriteria(), contentPartRecordType.Name); + return BindCriteriaByPath(BindItemCriteria(), contentPartRecordType.Name, type, withPredicate); } internal void Where(IAlias alias, Action predicate) { @@ -246,7 +246,16 @@ namespace Orchard.ContentManagement { sb.Append("from ").Append(_from.TableName).Append(" as ").Append(_from.Name).AppendLine(); foreach (var join in _joins) { - sb.Append(join.Item2.Type).Append(" ").Append(join.Item1.Name + "." + join.Item2.TableName).Append(" as ").Append(join.Item2.Name).AppendLine(); + sb.Append(join.Item2.Type + " " + + join.Item1.Name + "." + join.Item2.TableName + + " as " + join.Item2.Name); + if (join.Item2.WithPredicate != null) { + var predicate = join.Item2.WithPredicate; + var expressionFactory = new DefaultHqlExpressionFactory(); + predicate(expressionFactory); + sb.Append(" with " + expressionFactory.Criterion.ToHql(join.Item2)); + } + sb.AppendLine(); } // generating where clause @@ -378,6 +387,7 @@ namespace Orchard.ContentManagement { public interface IJoin : IAlias { string TableName { get; set; } string Type { get; set; } + Action WithPredicate { get; set; } } public class Sort { @@ -396,20 +406,26 @@ namespace Orchard.ContentManagement { public class Join : Alias, IJoin { public Join(string tableName, string alias) - : this(tableName, alias, "join") {} + : this(tableName, alias, "join", null) {} public Join(string tableName, string alias, string type) + : this(tableName, alias, type, null) { + } + + public Join(string tableName, string alias, string type, Action withPredicate) : base(alias) { if (String.IsNullOrEmpty(tableName)) { throw new ArgumentException("Table Name can't be empty"); } TableName = tableName; - Type = type; + Type = type ?? "join"; + WithPredicate = withPredicate; } public string TableName { get; set; } public string Type { get; set; } + public Action WithPredicate { get; set; } } public class DefaultHqlSortFactory : IHqlSortFactory @@ -442,17 +458,17 @@ namespace Orchard.ContentManagement { Current = _query.BindItemCriteria(); } - public IAliasFactory ContentPartRecord() where TRecord : ContentPartRecord { - Current = _query.BindPartCriteria(); + public IAliasFactory ContentPartRecord(string type = null, Action withPredicate = null) where TRecord : ContentPartRecord { + Current = _query.BindPartCriteria(type, withPredicate); return this; } - public IAliasFactory ContentPartRecord(Type contentPartRecord) { + public IAliasFactory ContentPartRecord(Type contentPartRecord, string type = null, Action withPredicate = null) { if(!contentPartRecord.IsSubclassOf(typeof(ContentPartRecord))) { throw new ArgumentException("Type must inherit from ContentPartRecord", "contentPartRecord"); } - Current = _query.BindPartCriteria(contentPartRecord); + Current = _query.BindPartCriteria(contentPartRecord, type, withPredicate); return this; } diff --git a/src/Orchard/ContentManagement/IHqlQuery.cs b/src/Orchard/ContentManagement/IHqlQuery.cs index 553ad363a..829f5fc8d 100644 --- a/src/Orchard/ContentManagement/IHqlQuery.cs +++ b/src/Orchard/ContentManagement/IHqlQuery.cs @@ -133,13 +133,18 @@ namespace Orchard.ContentManagement { public interface IAliasFactory { /// /// Creates a join on a content part record or returns it if it already exists. + /// The type of join, e.g. "left outer join" + /// An expression for an additional constraint on the join /// - IAliasFactory ContentPartRecord() where TRecord : ContentPartRecord; + IAliasFactory ContentPartRecord(string type = null, Action withPredicate = null) where TRecord : ContentPartRecord; /// /// Creates a join on a content part record or returns it if it already exists. + /// The type of the part to join + /// The type of join, e.g. "left outer join" + /// An expression for an additional constraint on the join /// - IAliasFactory ContentPartRecord(Type contentPartRecord); + IAliasFactory ContentPartRecord(Type contentPartRecord, string type = null, Action withPredicate = null); /// /// Creates a join based on a property, or returns it if it already exists.