From: <fab...@us...> - 2010-08-02 11:35:15
|
Revision: 5091 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5091&view=rev Author: fabiomaulo Date: 2010-08-02 11:35:07 +0000 (Mon, 02 Aug 2010) Log Message: ----------- Apply NH-2190 (thanks to Mihai Codrean) Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Criterion/DetachedCriteria.cs trunk/nhibernate/src/NHibernate/Dialect/Sybase11Dialect.cs trunk/nhibernate/src/NHibernate/Engine/JoinSequence.cs trunk/nhibernate/src/NHibernate/ICriteria.cs trunk/nhibernate/src/NHibernate/Impl/CriteriaImpl.cs trunk/nhibernate/src/NHibernate/Loader/AbstractEntityJoinWalker.cs trunk/nhibernate/src/NHibernate/Loader/Collection/BasicCollectionJoinWalker.cs trunk/nhibernate/src/NHibernate/Loader/Collection/OneToManyJoinWalker.cs trunk/nhibernate/src/NHibernate/Loader/Criteria/CriteriaJoinWalker.cs trunk/nhibernate/src/NHibernate/Loader/Criteria/CriteriaQueryTranslator.cs trunk/nhibernate/src/NHibernate/Loader/JoinWalker.cs trunk/nhibernate/src/NHibernate/Loader/OuterJoinableAssociation.cs trunk/nhibernate/src/NHibernate/SqlCommand/ANSIJoinFragment.cs trunk/nhibernate/src/NHibernate/SqlCommand/InformixJoinFragment.cs trunk/nhibernate/src/NHibernate/SqlCommand/JoinFragment.cs trunk/nhibernate/src/NHibernate/SqlCommand/OracleJoinFragment.cs trunk/nhibernate/src/NHibernate/SqlCommand/QueryJoinFragment.cs trunk/nhibernate/src/NHibernate/Util/StringHelper.cs trunk/nhibernate/src/NHibernate.Test/Criteria/CriteriaQueryTest.cs Modified: trunk/nhibernate/src/NHibernate/Criterion/DetachedCriteria.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Criterion/DetachedCriteria.cs 2010-08-01 19:49:12 UTC (rev 5090) +++ trunk/nhibernate/src/NHibernate/Criterion/DetachedCriteria.cs 2010-08-02 11:35:07 UTC (rev 5091) @@ -129,6 +129,12 @@ return this; } + public DetachedCriteria CreateAlias(string associationPath, string alias, JoinType joinType, ICriterion withClause) + { + criteria.CreateAlias(associationPath, alias, joinType, withClause); + return this; + } + public DetachedCriteria CreateCriteria(string associationPath, string alias) { return new DetachedCriteria(impl, criteria.CreateCriteria(associationPath, alias)); Modified: trunk/nhibernate/src/NHibernate/Dialect/Sybase11Dialect.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Dialect/Sybase11Dialect.cs 2010-08-01 19:49:12 UTC (rev 5090) +++ trunk/nhibernate/src/NHibernate/Dialect/Sybase11Dialect.cs 2010-08-02 11:35:07 UTC (rev 5091) @@ -69,7 +69,7 @@ } public override void AddJoin(string tableName, string alias, string[] fkColumns, string[] pkColumns, JoinType joinType, - string on) + SqlString on) { AddJoin(tableName, alias, fkColumns, pkColumns, joinType); AddCondition(on); Modified: trunk/nhibernate/src/NHibernate/Engine/JoinSequence.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Engine/JoinSequence.cs 2010-08-01 19:49:12 UTC (rev 5090) +++ trunk/nhibernate/src/NHibernate/Engine/JoinSequence.cs 2010-08-02 11:35:07 UTC (rev 5091) @@ -203,7 +203,7 @@ join.LHSColumns, JoinHelper.GetRHSColumnNames(join.AssociationType, factory), join.JoinType, - condition + new SqlString(condition) ); if (includeExtraJoins) { Modified: trunk/nhibernate/src/NHibernate/ICriteria.cs =================================================================== --- trunk/nhibernate/src/NHibernate/ICriteria.cs 2010-08-01 19:49:12 UTC (rev 5090) +++ trunk/nhibernate/src/NHibernate/ICriteria.cs 2010-08-02 11:35:07 UTC (rev 5091) @@ -130,6 +130,17 @@ ICriteria CreateAlias(string associationPath, string alias, JoinType joinType); /// <summary> + /// Join an association using the specified join-type, assigning an alias to the joined + /// association + /// </summary> + /// <param name="associationPath"></param> + /// <param name="alias"></param> + /// <param name="joinType">The type of join to use.</param> + /// <param name="withClause"The criteria to be added to the join condition (ON clause)</param> + /// <returns>this (for method chaining)</returns> + ICriteria CreateAlias(string associationPath, string alias, JoinType joinType, ICriterion withClause); + + /// <summary> /// Create a new <see cref="ICriteria" />, "rooted" at the associated entity /// </summary> /// <param name="associationPath"></param> @@ -165,6 +176,17 @@ ICriteria CreateCriteria(string associationPath, string alias, JoinType joinType); /// <summary> + /// Create a new <see cref="ICriteria" />, "rooted" at the associated entity, + /// assigning the given alias and using the specified join type. + /// </summary> + /// <param name="associationPath">A dot-separated property path</param> + /// <param name="alias">The alias to assign to the joined association (for later reference).</param> + /// <param name="joinType">The type of join to use.</param> + /// <param name="withClause"The criteria to be added to the join condition (ON clause)</param> + /// <returns>The created "sub criteria"</returns> + ICriteria CreateCriteria(string associationPath, string alias, JoinType joinType, ICriterion withClause); + + /// <summary> /// Set a strategy for handling the query results. This determines the /// "shape" of the query result set. /// <seealso cref="CriteriaSpecification.RootEntity"/> Modified: trunk/nhibernate/src/NHibernate/Impl/CriteriaImpl.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Impl/CriteriaImpl.cs 2010-08-01 19:49:12 UTC (rev 5090) +++ trunk/nhibernate/src/NHibernate/Impl/CriteriaImpl.cs 2010-08-02 11:35:07 UTC (rev 5091) @@ -345,6 +345,12 @@ return this; } + public ICriteria CreateAlias(string associationPath, string alias, JoinType joinType, ICriterion withClause) + { + new Subcriteria(this, this, associationPath, alias, joinType, withClause); + return this; + } + public ICriteria Add(ICriteria criteriaInst, ICriterion expression) { criteria.Add(new CriterionEntry(expression, criteriaInst)); @@ -371,6 +377,11 @@ return new Subcriteria(this, this, associationPath, alias, joinType); } + public ICriteria CreateCriteria(string associationPath, string alias, JoinType joinType, ICriterion withClause) + { + return new Subcriteria(this, this, associationPath, alias, joinType, withClause); + } + public IFutureValue<T> FutureValue<T>() { if (!session.Factory.ConnectionProvider.Driver.SupportsMultipleQueries) @@ -607,14 +618,16 @@ private readonly string path; private LockMode lockMode; private readonly JoinType joinType; + private ICriterion withClause; - internal Subcriteria(CriteriaImpl root, ICriteria parent, string path, string alias, JoinType joinType) + internal Subcriteria(CriteriaImpl root, ICriteria parent, string path, string alias, JoinType joinType, ICriterion withClause) { this.root = root; this.parent = parent; this.alias = alias; this.path = path; this.joinType = joinType; + this.withClause = withClause; root.subcriteriaList.Add(this); @@ -625,9 +638,17 @@ } } + internal Subcriteria(CriteriaImpl root, ICriteria parent, string path, string alias, JoinType joinType) + : this(root, parent, path, alias, joinType, null) {} + internal Subcriteria(CriteriaImpl root, ICriteria parent, string path, JoinType joinType) - : this(root, parent, path, null, joinType) {} + : this(root, parent, path, null, joinType) { } + public ICriterion WithClause + { + get { return withClause; } + } + public string Path { get { return path; } @@ -688,6 +709,12 @@ return this; } + public ICriteria CreateAlias(string associationPath, string alias, JoinType joinType, ICriterion withClause) + { + new Subcriteria(root, this, associationPath, alias, joinType, withClause); + return this; + } + public ICriteria CreateCriteria(string associationPath) { return CreateCriteria(associationPath, JoinType.InnerJoin); @@ -708,6 +735,11 @@ return new Subcriteria(root, this, associationPath, alias, joinType); } + public ICriteria CreateCriteria(string associationPath, string alias, JoinType joinType, ICriterion withClause) + { + return new Subcriteria(root, this, associationPath, alias, joinType, withClause); + } + public ICriteria SetCacheable(bool cacheable) { root.SetCacheable(cacheable); Modified: trunk/nhibernate/src/NHibernate/Loader/AbstractEntityJoinWalker.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Loader/AbstractEntityJoinWalker.cs 2010-08-01 19:49:12 UTC (rev 5090) +++ trunk/nhibernate/src/NHibernate/Loader/AbstractEntityJoinWalker.cs 2010-08-02 11:35:07 UTC (rev 5091) @@ -4,6 +4,7 @@ using NHibernate.SqlCommand; using NHibernate.Type; using NHibernate.Util; +using NHibernate.Loader.Criteria; namespace NHibernate.Loader { @@ -33,19 +34,27 @@ WalkEntityTree(persister, Alias); IList<OuterJoinableAssociation> allAssociations = new List<OuterJoinableAssociation>(associations); allAssociations.Add( - new OuterJoinableAssociation(persister.EntityType, null, null, alias, JoinType.LeftOuterJoin, Factory, + new OuterJoinableAssociation(persister.EntityType, null, null, alias, JoinType.LeftOuterJoin, null, Factory, new CollectionHelper.EmptyMapClass<string, IFilter>())); InitPersisters(allAssociations, lockMode); InitStatementString(whereString, orderByString, lockMode); } - protected void InitProjection(SqlString projectionString, SqlString whereString, - SqlString orderByString, string groupByString, SqlString havingString, LockMode lockMode) + protected void InitProjection(CriteriaQueryTranslator translator, + IDictionary<string, IFilter> enabledFilters, LockMode lockMode) { + // the order of the calls here is important, as the join clauses can contain parameter bindings + SqlString projectionString = translator.GetSelect(enabledFilters); WalkEntityTree(persister, Alias); + SqlString whereString = translator.GetWhereCondition(enabledFilters); + SqlString orderByString = translator.GetOrderBy(); + SqlString groupByString = translator.GetGroupBy(); + SqlString havingString = translator.GetHavingCondition(enabledFilters); + Persisters = new ILoadable[0]; - InitStatementString(projectionString, whereString, orderByString, groupByString, havingString, lockMode); + InitStatementString(projectionString, whereString, orderByString, groupByString.ToString(), + havingString, lockMode); } private void InitStatementString(SqlString condition, SqlString orderBy, LockMode lockMode) Modified: trunk/nhibernate/src/NHibernate/Loader/Collection/BasicCollectionJoinWalker.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Loader/Collection/BasicCollectionJoinWalker.cs 2010-08-01 19:49:12 UTC (rev 5090) +++ trunk/nhibernate/src/NHibernate/Loader/Collection/BasicCollectionJoinWalker.cs 2010-08-02 11:35:07 UTC (rev 5091) @@ -29,7 +29,7 @@ // NH Different behavior : passing enabledFilters instead empty-filter allAssociations.Add( - new OuterJoinableAssociation(collectionPersister.CollectionType, null, null, alias, JoinType.LeftOuterJoin, Factory, + new OuterJoinableAssociation(collectionPersister.CollectionType, null, null, alias, JoinType.LeftOuterJoin, null, Factory, enabledFilters)); InitPersisters(allAssociations, LockMode.None); Modified: trunk/nhibernate/src/NHibernate/Loader/Collection/OneToManyJoinWalker.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Loader/Collection/OneToManyJoinWalker.cs 2010-08-01 19:49:12 UTC (rev 5090) +++ trunk/nhibernate/src/NHibernate/Loader/Collection/OneToManyJoinWalker.cs 2010-08-02 11:35:07 UTC (rev 5091) @@ -35,7 +35,7 @@ IList<OuterJoinableAssociation> allAssociations = new List<OuterJoinableAssociation>(associations); allAssociations.Add( - new OuterJoinableAssociation(oneToManyPersister.CollectionType, null, null, alias, JoinType.LeftOuterJoin, Factory, + new OuterJoinableAssociation(oneToManyPersister.CollectionType, null, null, alias, JoinType.LeftOuterJoin, null, Factory, new CollectionHelper.EmptyMapClass<string, IFilter>())); InitPersisters(allAssociations, LockMode.None); Modified: trunk/nhibernate/src/NHibernate/Loader/Criteria/CriteriaJoinWalker.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Loader/Criteria/CriteriaJoinWalker.cs 2010-08-01 19:49:12 UTC (rev 5090) +++ trunk/nhibernate/src/NHibernate/Loader/Criteria/CriteriaJoinWalker.cs 2010-08-02 11:35:07 UTC (rev 5091) @@ -42,9 +42,7 @@ { resultTypes = translator.ProjectedTypes; - InitProjection(translator.GetSelect(enabledFilters), translator.GetWhereCondition(enabledFilters), - translator.GetOrderBy(), translator.GetGroupBy().ToString(), - translator.GetHavingCondition(enabledFilters), LockMode.None); + InitProjection(translator, enabledFilters, LockMode.None); } else { @@ -175,5 +173,10 @@ return CriteriaQueryTranslator.RootSqlAlias; // NH: really not used (we are using a different ctor to support SubQueryCriteria) } + + protected override SqlString GetWithClause(string path) + { + return translator.GetWithClause(path, EnabledFilters); + } } } \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate/Loader/Criteria/CriteriaQueryTranslator.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Loader/Criteria/CriteriaQueryTranslator.cs 2010-08-01 19:49:12 UTC (rev 5090) +++ trunk/nhibernate/src/NHibernate/Loader/Criteria/CriteriaQueryTranslator.cs 2010-08-02 11:35:07 UTC (rev 5091) @@ -39,6 +39,7 @@ private readonly IDictionary<string, ICriteria> aliasCriteriaMap = new Dictionary<string, ICriteria>(); private readonly IDictionary<string, ICriteria> associationPathCriteriaMap = new LinkedHashMap<string, ICriteria>(); private readonly IDictionary<string, JoinType> associationPathJoinTypesMap = new LinkedHashMap<string, JoinType>(); + private readonly IDictionary<string, ICriterion> withClauseMap = new Dictionary<string, ICriterion>(); private readonly ISessionFactoryImplementor sessionFactory; private int indexForAlias = 0; @@ -300,6 +301,18 @@ { throw new QueryException("duplicate association path: " + wholeAssociationPath, ae); } + + try + { + if (crit.WithClause != null) + { + withClauseMap.Add(wholeAssociationPath, crit.WithClause); + } + } + catch (ArgumentException ae) + { + throw new QueryException("duplicate association path: " + wholeAssociationPath, ae); + } } } @@ -685,6 +698,16 @@ return propertyName; } + public SqlString GetWithClause(string path, IDictionary<string, IFilter> enabledFilters) + { + if (withClauseMap.ContainsKey(path)) + { + ICriterion crit = (ICriterion)withClauseMap[path]; + return crit == null ? null : crit.ToSqlString(GetCriteria(path), this, enabledFilters); + } + return null; + } + #region NH specific public int GetIndexForAlias() Modified: trunk/nhibernate/src/NHibernate/Loader/JoinWalker.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Loader/JoinWalker.cs 2010-08-01 19:49:12 UTC (rev 5090) +++ trunk/nhibernate/src/NHibernate/Loader/JoinWalker.cs 2010-08-02 11:35:07 UTC (rev 5091) @@ -130,6 +130,11 @@ } } + protected virtual SqlString GetWithClause(string path) + { + return SqlString.Empty; + } + /// <summary> /// Add on association (one-to-one, many-to-one, or a collection) to a list /// of associations to be fetched by outerjoin @@ -142,7 +147,7 @@ string subalias = GenerateTableAlias(associations.Count + 1, path, joinable); OuterJoinableAssociation assoc = - new OuterJoinableAssociation(type, alias, aliasedLhsColumns, subalias, joinType, Factory, enabledFilters); + new OuterJoinableAssociation(type, alias, aliasedLhsColumns, subalias, joinType, GetWithClause(path), Factory, enabledFilters); assoc.ValidateJoin(path); associations.Add(assoc); Modified: trunk/nhibernate/src/NHibernate/Loader/OuterJoinableAssociation.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Loader/OuterJoinableAssociation.cs 2010-08-01 19:49:12 UTC (rev 5090) +++ trunk/nhibernate/src/NHibernate/Loader/OuterJoinableAssociation.cs 2010-08-02 11:35:07 UTC (rev 5091) @@ -5,6 +5,7 @@ using NHibernate.Persister.Entity; using NHibernate.SqlCommand; using NHibernate.Type; +using NHibernate.Util; namespace NHibernate.Loader { @@ -17,11 +18,11 @@ private readonly string rhsAlias; private readonly string[] rhsColumns; private readonly JoinType joinType; - private readonly string on; + private readonly SqlString on; private readonly IDictionary<string, IFilter> enabledFilters; public OuterJoinableAssociation(IAssociationType joinableType, String lhsAlias, String[] lhsColumns, String rhsAlias, - JoinType joinType, ISessionFactoryImplementor factory, + JoinType joinType, SqlString withClause, ISessionFactoryImplementor factory, IDictionary<string, IFilter> enabledFilters) { this.joinableType = joinableType; @@ -31,7 +32,9 @@ this.joinType = joinType; joinable = joinableType.GetAssociatedJoinable(factory); rhsColumns = JoinHelper.GetRHSColumnNames(joinableType, factory); - on = joinableType.GetOnCondition(rhsAlias, factory, enabledFilters); + on = new SqlString(joinableType.GetOnCondition(rhsAlias, factory, enabledFilters)); + if (StringHelper.IsNotEmpty(withClause)) + on = on.Append(" and ( ").Append(withClause).Append(" )"); this.enabledFilters = enabledFilters; // needed later for many-to-many/filter application } @@ -146,9 +149,10 @@ public void AddManyToManyJoin(JoinFragment outerjoin, IQueryableCollection collection) { string manyToManyFilter = collection.GetManyToManyFilterFragment(rhsAlias, enabledFilters); - string condition = string.Empty.Equals(manyToManyFilter) + SqlString condition = string.Empty.Equals(manyToManyFilter) ? on - : string.Empty.Equals(on) ? manyToManyFilter : on + " and " + manyToManyFilter; + : StringHelper.IsEmpty(on) ? new SqlString(manyToManyFilter) : + on.Append(" and ").Append(manyToManyFilter); outerjoin.AddJoin(joinable.TableName, rhsAlias, lhsColumns, rhsColumns, joinType, condition); outerjoin.AddJoins(joinable.FromJoinFragment(rhsAlias, false, true), Modified: trunk/nhibernate/src/NHibernate/SqlCommand/ANSIJoinFragment.cs =================================================================== --- trunk/nhibernate/src/NHibernate/SqlCommand/ANSIJoinFragment.cs 2010-08-01 19:49:12 UTC (rev 5090) +++ trunk/nhibernate/src/NHibernate/SqlCommand/ANSIJoinFragment.cs 2010-08-02 11:35:07 UTC (rev 5091) @@ -17,7 +17,7 @@ } public override void AddJoin(string tableName, string alias, string[] fkColumns, string[] pkColumns, JoinType joinType, - string on) + SqlString on) { string joinString; switch (joinType) Modified: trunk/nhibernate/src/NHibernate/SqlCommand/InformixJoinFragment.cs =================================================================== --- trunk/nhibernate/src/NHibernate/SqlCommand/InformixJoinFragment.cs 2010-08-01 19:49:12 UTC (rev 5090) +++ trunk/nhibernate/src/NHibernate/SqlCommand/InformixJoinFragment.cs 2010-08-02 11:35:07 UTC (rev 5091) @@ -40,7 +40,7 @@ } public override void AddJoin(string tableName, string alias, string[] fkColumns, string[] pkColumns, JoinType joinType, - string on) + SqlString on) { //arbitrary on clause ignored!! AddJoin(tableName, alias, fkColumns, pkColumns, joinType); Modified: trunk/nhibernate/src/NHibernate/SqlCommand/JoinFragment.cs =================================================================== --- trunk/nhibernate/src/NHibernate/SqlCommand/JoinFragment.cs 2010-08-01 19:49:12 UTC (rev 5090) +++ trunk/nhibernate/src/NHibernate/SqlCommand/JoinFragment.cs 2010-08-02 11:35:07 UTC (rev 5091) @@ -20,7 +20,7 @@ public abstract void AddJoin(string tableName, string alias, string[] fkColumns, string[] pkColumns, JoinType joinType); public abstract void AddJoin(string tableName, string alias, string[] fkColumns, string[] pkColumns, JoinType joinType, - string on); + SqlString on); public abstract void AddCrossJoin(string tableName, string alias); Modified: trunk/nhibernate/src/NHibernate/SqlCommand/OracleJoinFragment.cs =================================================================== --- trunk/nhibernate/src/NHibernate/SqlCommand/OracleJoinFragment.cs 2010-08-01 19:49:12 UTC (rev 5090) +++ trunk/nhibernate/src/NHibernate/SqlCommand/OracleJoinFragment.cs 2010-08-02 11:35:07 UTC (rev 5091) @@ -36,7 +36,7 @@ } public override void AddJoin(string tableName, string alias, string[] fkColumns, string[] pkColumns, JoinType joinType, - string on) + SqlString on) { //arbitrary on clause ignored!! AddJoin(tableName, alias, fkColumns, pkColumns, joinType); @@ -62,9 +62,9 @@ /// was a normal join condition, but is natural /// for a filter. /// </summary> - private void AddLeftOuterJoinCondition(string on) + private void AddLeftOuterJoinCondition(SqlString on) { - StringBuilder buf = new StringBuilder(on); + StringBuilder buf = new StringBuilder(on.ToString()); for (int i = 0; i < buf.Length; i++) { char character = buf[i]; @@ -76,7 +76,7 @@ i += 3; } } - AddCondition(buf.ToString()); + AddCondition(SqlString.Parse(buf.ToString())); } private static readonly ISet Operators = new HashedSet(); Modified: trunk/nhibernate/src/NHibernate/SqlCommand/QueryJoinFragment.cs =================================================================== --- trunk/nhibernate/src/NHibernate/SqlCommand/QueryJoinFragment.cs 2010-08-01 19:49:12 UTC (rev 5090) +++ trunk/nhibernate/src/NHibernate/SqlCommand/QueryJoinFragment.cs 2010-08-02 11:35:07 UTC (rev 5091) @@ -25,7 +25,7 @@ } private void AddJoin(string tableName, string alias, string concreteAlias, string[] fkColumns, string[] pkColumns, - JoinType joinType, string on) + JoinType joinType, SqlString on) { if (!useThetaStyleInnerJoins || joinType != JoinType.InnerJoin) { @@ -42,7 +42,7 @@ } public override void AddJoin(string tableName, string alias, string[] fkColumns, string[] pkColumns, JoinType joinType, - string on) + SqlString on) { AddJoin(tableName, alias, alias, fkColumns, pkColumns, joinType, on); } Modified: trunk/nhibernate/src/NHibernate/Util/StringHelper.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Util/StringHelper.cs 2010-08-01 19:49:12 UTC (rev 5090) +++ trunk/nhibernate/src/NHibernate/Util/StringHelper.cs 2010-08-02 11:35:07 UTC (rev 5091) @@ -496,9 +496,14 @@ public static bool IsNotEmpty(SqlString str) { - return str != null && str.Count > 0; + return !IsEmpty(str); } + public static bool IsEmpty(SqlString str) + { + return str == null || str.Count == 0; + } + /// <summary> /// /// </summary> Modified: trunk/nhibernate/src/NHibernate.Test/Criteria/CriteriaQueryTest.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/Criteria/CriteriaQueryTest.cs 2010-08-01 19:49:12 UTC (rev 5090) +++ trunk/nhibernate/src/NHibernate.Test/Criteria/CriteriaQueryTest.cs 2010-08-02 11:35:07 UTC (rev 5091) @@ -1849,5 +1849,111 @@ criteria.List(); } } + + + [Test] + public void AliasJoinCriterion() + { + using (ISession session = this.OpenSession()) + { + using (ITransaction t = session.BeginTransaction()) + { + Course courseA = new Course(); + courseA.CourseCode = "HIB-A"; + courseA.Description = "Hibernate Training A"; + session.Persist(courseA); + + Course courseB = new Course(); + courseB.CourseCode = "HIB-B"; + courseB.Description = "Hibernate Training B"; + session.Persist(courseB); + + Student gavin = new Student(); + gavin.Name = "Gavin King"; + gavin.StudentNumber = 232; + gavin.PreferredCourse = courseA; + session.Persist(gavin); + + Student leonardo = new Student(); + leonardo.Name = "Leonardo Quijano"; + leonardo.StudentNumber = 233; + leonardo.PreferredCourse = courseB; + session.Persist(leonardo); + + Student johnDoe = new Student(); + johnDoe.Name = "John Doe"; + johnDoe.StudentNumber = 235; + johnDoe.PreferredCourse = null; + session.Persist(johnDoe); + + // test == on one value exists + IList<string> result = session.CreateCriteria<Student>() + .CreateAlias("PreferredCourse", "pc", JoinType.LeftOuterJoin, + Restrictions.Eq("pc.CourseCode", "HIB-A")) + .SetProjection(Property.ForName("pc.CourseCode")) + .AddOrder(Order.Asc("pc.CourseCode")) + .List<string>(); + + // can't be sure of NULL comparison ordering aside from they should + // either come first or last + if (result[0] == null) + { + Assert.IsNull(result[1]); + Assert.AreEqual("HIB-A", result[2]); + } + else + { + Assert.IsNull(result[2]); + Assert.IsNull(result[1]); + Assert.AreEqual("HIB-A", result[0]); + } + + // test == on non existent value + result = session.CreateCriteria<Student>() + .CreateAlias("PreferredCourse", "pc", JoinType.LeftOuterJoin, + Restrictions.Eq("pc.CourseCode", "HIB-R")) + .SetProjection(Property.ForName("pc.CourseCode")) + .AddOrder(Order.Asc("pc.CourseCode")) + .List<string>(); + + Assert.AreEqual(3, result.Count); + Assert.IsNull(result[2]); + Assert.IsNull(result[1]); + Assert.IsNull(result[0]); + + // test != on one existing value + result = session.CreateCriteria<Student>() + .CreateAlias("PreferredCourse", "pc", JoinType.LeftOuterJoin, + Restrictions.Not(Restrictions.Eq("pc.CourseCode", "HIB-A"))) + .SetProjection(Property.ForName("pc.CourseCode")) + .AddOrder(Order.Asc("pc.CourseCode")) + .List<string>(); + + Assert.AreEqual(3, result.Count); + + // can't be sure of NULL comparison ordering aside from they should + // either come first or last + if (result[0] == null) + { + Assert.IsNull(result[1]); + Assert.AreEqual("HIB-B", result[2]); + } + else + { + Assert.AreEqual("HIB-B", result[0]); + Assert.IsNull(result[1]); + Assert.IsNull(result[2]); + } + + session.Delete(gavin); + session.Delete(leonardo); + session.Delete(johnDoe); + session.Delete(courseA); + session.Delete(courseB); + + t.Commit(); + } + } + } } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |