From: <fab...@us...> - 2011-05-02 14:09:06
|
Revision: 5793 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5793&view=rev Author: fabiomaulo Date: 2011-05-02 14:08:59 +0000 (Mon, 02 May 2011) Log Message: ----------- Fix NH-2673, NH-1090, NH-1344 Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Cache/QueryKey.cs trunk/nhibernate/src/NHibernate/Cache/StandardQueryCache.cs trunk/nhibernate/src/NHibernate/Cfg/Loquacious/CacheConfiguration.cs trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Loader/QueryLoader.cs trunk/nhibernate/src/NHibernate/Hql/Classic/QueryTranslator.cs trunk/nhibernate/src/NHibernate/Impl/CriteriaImpl.cs trunk/nhibernate/src/NHibernate/Impl/MultiCriteriaImpl.cs trunk/nhibernate/src/NHibernate/Impl/MultiQueryImpl.cs trunk/nhibernate/src/NHibernate/Loader/Criteria/CriteriaLoader.cs trunk/nhibernate/src/NHibernate/Loader/Custom/CustomLoader.cs trunk/nhibernate/src/NHibernate/Loader/Loader.cs trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj Added Paths: ----------- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2673/ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2673/Blog.cs trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2673/CachingWithTrasformerTests.cs Modified: trunk/nhibernate/src/NHibernate/Cache/QueryKey.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Cache/QueryKey.cs 2011-04-29 22:51:08 UTC (rev 5792) +++ trunk/nhibernate/src/NHibernate/Cache/QueryKey.cs 2011-05-02 14:08:59 UTC (rev 5793) @@ -61,6 +61,11 @@ hashCode = ComputeHashCode(); } + public bool HasResultTrasformer + { + get { return customTransformer != null; } + } + public QueryKey SetFirstRows(int[] firstRows) { multiQueriesFirstRows = firstRows; Modified: trunk/nhibernate/src/NHibernate/Cache/StandardQueryCache.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Cache/StandardQueryCache.cs 2011-04-29 22:51:08 UTC (rev 5792) +++ trunk/nhibernate/src/NHibernate/Cache/StandardQueryCache.cs 2011-05-02 14:08:59 UTC (rev 5793) @@ -77,7 +77,7 @@ IList cacheable = new List<object>(result.Count + 1) {ts}; for (int i = 0; i < result.Count; i++) { - if (returnTypes.Length == 1) + if (returnTypes.Length == 1 && !key.HasResultTrasformer) { cacheable.Add(returnTypes[0].Disassemble(result[i], session, null)); } Modified: trunk/nhibernate/src/NHibernate/Cfg/Loquacious/CacheConfiguration.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Cfg/Loquacious/CacheConfiguration.cs 2011-04-29 22:51:08 UTC (rev 5792) +++ trunk/nhibernate/src/NHibernate/Cfg/Loquacious/CacheConfiguration.cs 2011-05-02 14:08:59 UTC (rev 5793) @@ -35,15 +35,21 @@ public void Provider<TProvider>() where TProvider : ICacheProvider { - cfg.SetProperty(Environment.CacheProvider, typeof (TProvider).AssemblyQualifiedName); + UseSecondLevelCache = true; + cfg.SetProperty(Environment.CacheProvider, typeof(TProvider).AssemblyQualifiedName); } public void QueryCache<TFactory>() where TFactory : IQueryCache { + UseSecondLevelCache = true; UseQueryCache = true; cfg.SetProperty(Environment.QueryCacheFactory, typeof(TFactory).AssemblyQualifiedName); } + private bool UseSecondLevelCache + { + set { cfg.SetProperty(Environment.UseSecondLevelCache, value.ToString().ToLowerInvariant()); } + } #endregion } @@ -66,6 +72,7 @@ public ICacheConfiguration Through<TProvider>() where TProvider : ICacheProvider { + fc.Configuration.SetProperty(Environment.UseSecondLevelCache, "true"); fc.Configuration.SetProperty(Environment.CacheProvider, typeof(TProvider).AssemblyQualifiedName); return this; } @@ -106,6 +113,8 @@ public ICacheConfiguration Through<TFactory>() where TFactory : IQueryCache { + cc.Configuration.SetProperty(Environment.UseSecondLevelCache, "true"); + cc.Configuration.SetProperty(Environment.UseQueryCache, "true"); cc.Configuration.SetProperty(Environment.QueryCacheFactory, typeof(TFactory).AssemblyQualifiedName); return cc; } Modified: trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Loader/QueryLoader.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Loader/QueryLoader.cs 2011-04-29 22:51:08 UTC (rev 5792) +++ trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Loader/QueryLoader.cs 2011-05-02 14:08:59 UTC (rev 5793) @@ -300,7 +300,7 @@ return List(session, queryParameters, _queryTranslator.QuerySpaces, _queryReturnTypes); } - protected override IList GetResultList(IList results, IResultTransformer resultTransformer) + public override IList GetResultList(IList results, IResultTransformer resultTransformer) { // meant to handle dynamic instantiation queries... HolderInstantiator holderInstantiator = HolderInstantiator.GetHolderInstantiator(_selectNewTransformer, Modified: trunk/nhibernate/src/NHibernate/Hql/Classic/QueryTranslator.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Hql/Classic/QueryTranslator.cs 2011-04-29 22:51:08 UTC (rev 5792) +++ trunk/nhibernate/src/NHibernate/Hql/Classic/QueryTranslator.cs 2011-05-02 14:08:59 UTC (rev 5793) @@ -1512,7 +1512,7 @@ } } - protected override IList GetResultList(IList results, IResultTransformer resultTransformer) + public override IList GetResultList(IList results, IResultTransformer resultTransformer) { HolderInstantiator holderInstantiator = HolderInstantiator.CreateClassicHolderInstantiator(holderConstructor, resultTransformer); Modified: trunk/nhibernate/src/NHibernate/Impl/CriteriaImpl.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Impl/CriteriaImpl.cs 2011-04-29 22:51:08 UTC (rev 5792) +++ trunk/nhibernate/src/NHibernate/Impl/CriteriaImpl.cs 2011-05-02 14:08:59 UTC (rev 5793) @@ -26,7 +26,7 @@ private int timeout = RowSelection.NoValue; private int fetchSize = RowSelection.NoValue; private ISessionImplementor session; - private IResultTransformer resultTransformer = CriteriaSpecification.RootEntity; + private IResultTransformer resultTransformer; private bool cacheable; private string cacheRegion; private CacheMode? cacheMode; Modified: trunk/nhibernate/src/NHibernate/Impl/MultiCriteriaImpl.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Impl/MultiCriteriaImpl.cs 2011-04-29 22:51:08 UTC (rev 5792) +++ trunk/nhibernate/src/NHibernate/Impl/MultiCriteriaImpl.cs 2011-05-02 14:08:59 UTC (rev 5793) @@ -14,6 +14,7 @@ using NHibernate.SqlCommand; using NHibernate.Transform; using NHibernate.Type; +using NHibernate.Util; namespace NHibernate.Impl { @@ -91,7 +92,6 @@ } } - private IList ListUsingQueryCache() { IQueryCache queryCache = session.Factory.GetQueryCache(cacheRegion); @@ -141,21 +141,28 @@ protected virtual IList GetResultList(IList results) { - if (resultTransformer != null) + for (int i = 0; i < loaders.Count; i++) { - for (int i = 0; i < results.Count; i++) + CriteriaLoader loader = loaders[i]; + results[i] = loader.GetResultList((IList)results[i], parameters[i].ResultTransformer); + IList tmpResults; + if (resultCollectionGenericType[i] == typeof (object)) { - results[i] = resultTransformer.TransformList((IList)results[i]); + tmpResults = new ArrayList(); } + else + { + tmpResults = (IList) Activator.CreateInstance(typeof (List<>).MakeGenericType(resultCollectionGenericType[i])); + } + ArrayHelper.AddAll(tmpResults, (IList)results[i]); + + results[i] = tmpResults; } - else + if (resultTransformer != null) { for (int i = 0; i < results.Count; i++) { - CriteriaImpl critImp = criteriaQueries[i] as CriteriaImpl; - if (critImp == null || critImp.ResultTransformer == null) - continue; - results[i] = critImp.ResultTransformer.TransformList((IList)results[i]); + results[i] = resultTransformer.TransformList((IList)results[i]); } } return results; @@ -205,15 +212,7 @@ hydratedObjects[i] = entitySpan == 0 ? null : new ArrayList(entitySpan); EntityKey[] keys = new EntityKey[entitySpan]; QueryParameters queryParameters = parameters[i]; - IList tmpResults; - if (resultCollectionGenericType[i] == typeof(object)) - { - tmpResults = new ArrayList(); - } - else - { - tmpResults = (IList)Activator.CreateInstance(typeof(List<>).MakeGenericType(resultCollectionGenericType[i])); - } + IList tmpResults = new ArrayList(); RowSelection selection = parameters[i].RowSelection; createSubselects[i] = loader.IsSubselectLoadingEnabled; @@ -238,6 +237,7 @@ } tmpResults.Add(o); } + results.Add(tmpResults); reader.NextResult(); } Modified: trunk/nhibernate/src/NHibernate/Impl/MultiQueryImpl.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Impl/MultiQueryImpl.cs 2011-04-29 22:51:08 UTC (rev 5792) +++ trunk/nhibernate/src/NHibernate/Impl/MultiQueryImpl.cs 2011-05-02 14:08:59 UTC (rev 5793) @@ -453,7 +453,8 @@ for (int i = 0; i < len; ++i) { // First use the transformer of each query transformig each row and then the list - results[i] = GetTransformedResults((IList)results[i], GetQueryHolderInstantiator(i)); + // DONE: The behavior when the query has a 'new' istead a trasformer is delegated to the Loader + results[i] = translators[i].Loader.GetResultList((IList)results[i], Parameters[i].ResultTransformer); // then use the MultiQueryTransformer (if it has some sense...) using, as source, the transformed result. results[i] = GetTransformedResults((IList)results[i], multiqueryHolderInstatiator); } @@ -475,15 +476,6 @@ return holderInstantiator.ResultTransformer.TransformList(source); } - private HolderInstantiator GetQueryHolderInstantiator(int queryPosition) - { - // TODO : we need a test to check the behavior when the query has a 'new' istead a trasformer - // we should take the HolderInstantiator directly from QueryTranslator... taking care with Parameters. - return Parameters[queryPosition].ResultTransformer != null ? - new HolderInstantiator(Parameters[queryPosition].ResultTransformer, translators[queryPosition].ReturnAliases) - : HolderInstantiator.NoopInstantiator; - } - private HolderInstantiator GetMultiQueryHolderInstatiator() { return HasMultiQueryResultTrasformer() ? new HolderInstantiator(resultTransformer, null) : HolderInstantiator.NoopInstantiator; Modified: trunk/nhibernate/src/NHibernate/Loader/Criteria/CriteriaLoader.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Loader/Criteria/CriteriaLoader.cs 2011-04-29 22:51:08 UTC (rev 5792) +++ trunk/nhibernate/src/NHibernate/Loader/Criteria/CriteriaLoader.cs 2011-05-02 14:08:59 UTC (rev 5793) @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Data; using Iesi.Collections.Generic; +using NHibernate.Criterion; using NHibernate.Engine; using NHibernate.Impl; using NHibernate.Persister.Entity; @@ -78,7 +79,6 @@ ISessionImplementor session) { object[] result; - string[] aliases; if (translator.HasProjection) { @@ -101,14 +101,17 @@ } position += numColumns; } - aliases = translator.ProjectedAliases; } else { result = row; - aliases = userAliases; } - return translator.RootCriteria.ResultTransformer.TransformTuple(result, aliases); + + if (resultTransformer == null && result.Length == 1) + { + return result[0]; + } + return result; } protected override SqlString ApplyLocks(SqlString sqlSelectString, IDictionary<string, LockMode> lockModes, @@ -161,9 +164,20 @@ return lockModesArray; } - protected override IList GetResultList(IList results, IResultTransformer resultTransformer) + public override IList GetResultList(IList results, IResultTransformer resultTransformer) { - return translator.RootCriteria.ResultTransformer.TransformList(results); + var transformer = resultTransformer ?? CriteriaSpecification.RootEntity; + for (int i = 0; i < results.Count; i++) + { + var row = results[i] as object[]; + if(row == null) + { + row = new object[] { results[i] }; + } + object result = transformer.TransformTuple(row, translator.HasProjection ? translator.ProjectedAliases : userAliases); + results[i] = result; + } + return transformer.TransformList(results); } } } \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate/Loader/Custom/CustomLoader.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Loader/Custom/CustomLoader.cs 2011-04-29 22:51:08 UTC (rev 5792) +++ trunk/nhibernate/src/NHibernate/Loader/Custom/CustomLoader.cs 2011-05-02 14:08:59 UTC (rev 5793) @@ -280,7 +280,7 @@ return rowProcessor.BuildResultRow(row, rs, resultTransformer != null, session); } - protected override IList GetResultList(IList results, IResultTransformer resultTransformer) + public override IList GetResultList(IList results, IResultTransformer resultTransformer) { // meant to handle dynamic instantiation queries...(Copy from QueryLoader) HolderInstantiator holderInstantiator = Modified: trunk/nhibernate/src/NHibernate/Loader/Loader.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Loader/Loader.cs 2011-04-29 22:51:08 UTC (rev 5792) +++ trunk/nhibernate/src/NHibernate/Loader/Loader.cs 2011-05-02 14:08:59 UTC (rev 5793) @@ -628,7 +628,7 @@ collectionPersister); } - protected virtual IList GetResultList(IList results, IResultTransformer resultTransformer) + public virtual IList GetResultList(IList results, IResultTransformer resultTransformer) { return results; } Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2673/Blog.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2673/Blog.cs (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2673/Blog.cs 2011-05-02 14:08:59 UTC (rev 5793) @@ -0,0 +1,34 @@ +using Iesi.Collections.Generic; + +namespace NHibernate.Test.NHSpecificTest.NH2673 +{ + public class Blog + { + public Blog() + { + Posts = new HashedSet<Post>(); + Comments = new HashedSet<Comment>(); + } + + public virtual int Id { get; set; } + public virtual string Author { get; set; } + public virtual string Name { get; set; } + public virtual ISet<Post> Posts { get; set; } + public virtual ISet<Comment> Comments { get; set; } + } + + public class Post + { + public virtual int Id { get; protected set; } + public virtual string Title { get; set; } + public virtual string Body { get; set; } + } + + + public class Comment + { + public virtual int Id { get; protected set; } + public virtual string Title { get; set; } + public virtual string Body { get; set; } + } +} \ No newline at end of file Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2673/CachingWithTrasformerTests.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2673/CachingWithTrasformerTests.cs (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2673/CachingWithTrasformerTests.cs 2011-05-02 14:08:59 UTC (rev 5793) @@ -0,0 +1,157 @@ +using System; +using System.Collections; +using NHibernate.Cache; +using NHibernate.Cfg; +using NHibernate.Cfg.MappingSchema; +using NHibernate.Mapping.ByCode; +using NHibernate.Transform; +using NUnit.Framework; +using SharpTestsEx; + +namespace NHibernate.Test.NHSpecificTest.NH2673 +{ + public class CachingWithTrasformerTests: TestCaseMappingByCode + { + protected override HbmMapping GetMappings() + { + var mapper = new ConventionModelMapper(); + mapper.BeforeMapClass += (inspector, type, map) => map.Id(x => x.Generator(Generators.HighLow)); + mapper.BeforeMapClass += (inspector, type, map) => map.Cache(x => x.Usage(CacheUsage.ReadWrite)); + mapper.BeforeMapSet += (inspector, property, map) => + { + map.Cascade(Mapping.ByCode.Cascade.All); + map.Cache(x => x.Usage(CacheUsage.ReadWrite)); + }; + var mapping = mapper.CompileMappingFor(new[] { typeof(Blog), typeof(Post), typeof(Comment) }); + return mapping; + } + + protected override void Configure(Cfg.Configuration configuration) + { + configuration.Cache(x => + { + x.Provider<HashtableCacheProvider>(); + x.UseQueryCache = true; + }); + } + + private class Scenario: IDisposable + { + private readonly ISessionFactory factory; + + public Scenario(ISessionFactory factory) + { + this.factory = factory; + using (var session= factory.OpenSession()) + using (var tx = session.BeginTransaction()) + { + var blog = new Blog { Author = "Gabriel", Name = "Keep on running" }; + blog.Posts.Add(new Post { Title = "First post", Body = "Some text" }); + blog.Posts.Add(new Post { Title = "Second post", Body = "Some other text" }); + blog.Posts.Add(new Post { Title = "Third post", Body = "Third post text" }); + + + blog.Comments.Add(new Comment { Title = "First comment", Body = "Some text" }); + blog.Comments.Add(new Comment { Title = "Second comment", Body = "Some other text" }); + session.Save(blog); + tx.Commit(); + } + } + + public void Dispose() + { + using (var session = factory.OpenSession()) + using (var tx = session.BeginTransaction()) + { + session.CreateQuery("delete from Comment").ExecuteUpdate(); + session.CreateQuery("delete from Post").ExecuteUpdate(); + session.CreateQuery("delete from Blog").ExecuteUpdate(); + tx.Commit(); + } + } + } + + [Test] + public void WhenQueryThenNotThrows() + { + using (new Scenario(Sfi)) + { + using (var session = OpenSession()) + using (var tx = session.BeginTransaction()) + { + var query = session.CreateQuery("from Blog b where b.Author = : author") + .SetString("author", "Gabriel") + .SetCacheable(true) + .SetResultTransformer(new DistinctRootEntityResultTransformer()); + query.Executing(q=> q.List<Blog>()).NotThrows(); + tx.Commit(); + } + } + } + + [Test] + public void WhenCriteriaThenNotThrows() + { + using (new Scenario(Sfi)) + { + using (var session = OpenSession()) + using (var tx = session.BeginTransaction()) + { + var query = session.QueryOver<Blog>().Where(x => x.Author == "Gabriel") + .TransformUsing(new DistinctRootEntityResultTransformer()) + .Cacheable(); + query.Executing(q => q.List<Blog>()).NotThrows(); + tx.Commit(); + } + } + } + + private class BlogAuthorDto + { + public string BlogName { get; set; } + public string AuthorName { get; set; } + } + + private class BlogAuthorTrasformer : IResultTransformer + { + public object TransformTuple(object[] tuple, string[] aliases) + { + return new BlogAuthorDto { BlogName = tuple[0].ToString(), AuthorName = tuple[1].ToString() }; + } + + public IList TransformList(IList collection) + { + return collection; + } + } + + [Test] + public void WhenCriteriaProjectionThenNotThrows() + { + // during the fix of NH-2673 was faund another bug related to cacheability of criteria with projection + trasformer + // then found reported as NH-1090 + var transformer = new BlogAuthorTrasformer(); + using (new Scenario(Sfi)) + { + using (var session = OpenSession()) + using (var tx = session.BeginTransaction()) + { + var query = session.QueryOver<Blog>().Select(x=> x.Author, x=> x.Name).Where(x => x.Author == "Gabriel") + .TransformUsing(transformer) + .Cacheable(); + query.List<BlogAuthorDto>(); + tx.Commit(); + } + using (var session = OpenSession()) + using (var tx = session.BeginTransaction()) + { + var query = session.QueryOver<Blog>().Select(x => x.Author, x => x.Name).Where(x => x.Author == "Gabriel") + .TransformUsing(transformer) + .Cacheable(); + query.Executing(q => q.List<BlogAuthorDto>()).NotThrows(); + tx.Commit(); + } + } + } + } +} \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2011-04-29 22:51:08 UTC (rev 5792) +++ trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2011-05-02 14:08:59 UTC (rev 5793) @@ -810,6 +810,8 @@ <Compile Include="NHSpecificTest\NH2632\Fixture.cs" /> <Compile Include="NHSpecificTest\NH2660And2661\DomainClass.cs" /> <Compile Include="NHSpecificTest\NH2660And2661\Test.cs" /> + <Compile Include="NHSpecificTest\NH2673\Blog.cs" /> + <Compile Include="NHSpecificTest\NH2673\CachingWithTrasformerTests.cs" /> <Compile Include="NHSpecificTest\Properties\CompositePropertyRefTest.cs" /> <Compile Include="NHSpecificTest\Properties\DynamicEntityTest.cs" /> <Compile Include="NHSpecificTest\Properties\Model.cs" /> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |