|
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.
|