From: <ste...@us...> - 2009-09-28 17:04:24
|
Revision: 4731 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=4731&view=rev Author: steverstrong Date: 2009-09-28 17:04:14 +0000 (Mon, 28 Sep 2009) Log Message: ----------- Changes to Linq execution to tie in with HQLQueryPlan caching Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Engine/Query/HQLQueryPlan.cs trunk/nhibernate/src/NHibernate/Engine/Query/QueryPlanCache.cs trunk/nhibernate/src/NHibernate/IQueryExpression.cs trunk/nhibernate/src/NHibernate/Impl/AbstractSessionImpl.cs trunk/nhibernate/src/NHibernate/Impl/QueryImpl.cs trunk/nhibernate/src/NHibernate/Linq/CommandData.cs trunk/nhibernate/src/NHibernate/Linq/NhQueryable.cs trunk/nhibernate/src/NHibernate/NHibernate.csproj trunk/nhibernate/src/NHibernate.Test/Linq/LinqTestCase.cs trunk/nhibernate/src/NHibernate.Test/Linq/ReadonlyTestCase.cs Removed Paths: ------------- trunk/nhibernate/src/NHibernate/Hql/Ast/HqlExpression.cs trunk/nhibernate/src/NHibernate/Linq/NhQueryExecutor.cs Modified: trunk/nhibernate/src/NHibernate/Engine/Query/HQLQueryPlan.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Engine/Query/HQLQueryPlan.cs 2009-09-27 10:06:52 UTC (rev 4730) +++ trunk/nhibernate/src/NHibernate/Engine/Query/HQLQueryPlan.cs 2009-09-28 17:04:14 UTC (rev 4731) @@ -28,8 +28,9 @@ private readonly HashedSet<string> enabledFilterNames; private readonly bool shallow; + private IQueryExpression sourceQueryExpression; - public HQLQueryPlan(string hql, bool shallow, + public HQLQueryPlan(string hql, bool shallow, IDictionary<string, IFilter> enabledFilters, ISessionFactoryImplementor factory) : this(hql, (string) null, shallow, enabledFilters, factory) { @@ -110,6 +111,7 @@ protected internal HQLQueryPlan(string expressionStr, IQueryExpression queryExpression, string collectionRole, bool shallow, IDictionary<string, IFilter> enabledFilters, ISessionFactoryImplementor factory) { + sourceQueryExpression = queryExpression; sourceQuery = expressionStr; this.shallow = shallow; @@ -192,7 +194,12 @@ } } - private static ParameterMetadata BuildParameterMetadata(IParameterTranslations parameterTranslations, string hql) + public IQueryExpression QueryExpression + { + get { return sourceQueryExpression; } + } + + private static ParameterMetadata BuildParameterMetadata(IParameterTranslations parameterTranslations, string hql) { long start = DateTime.Now.Ticks; ParamLocationRecognizer recognizer = ParamLocationRecognizer.ParseLocations(hql); Modified: trunk/nhibernate/src/NHibernate/Engine/Query/QueryPlanCache.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Engine/Query/QueryPlanCache.cs 2009-09-27 10:06:52 UTC (rev 4730) +++ trunk/nhibernate/src/NHibernate/Engine/Query/QueryPlanCache.cs 2009-09-28 17:04:14 UTC (rev 4731) @@ -86,6 +86,7 @@ log.Debug("unable to locate HQL query plan in cache; generating (" + expressionStr + ")"); } plan = new HQLQueryPlan(expressionStr, queryExpression, shallow, enabledFilters, factory); + planCache.Put(key, plan); } else { @@ -95,8 +96,6 @@ } } - planCache.Put(key, plan); - return plan; } Deleted: trunk/nhibernate/src/NHibernate/Hql/Ast/HqlExpression.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Hql/Ast/HqlExpression.cs 2009-09-27 10:06:52 UTC (rev 4730) +++ trunk/nhibernate/src/NHibernate/Hql/Ast/HqlExpression.cs 2009-09-28 17:04:14 UTC (rev 4731) @@ -1,36 +0,0 @@ -using System.Collections.Generic; -using System.Reflection; -using NHibernate.Hql.Ast.ANTLR; -using NHibernate.Hql.Ast.ANTLR.Tree; - -namespace NHibernate.Hql.Ast -{ - public class HqlExpression : IQueryExpression - { - private readonly IASTNode _node; - private readonly System.Type _type; - private readonly string _key; - - public HqlExpression(HqlQuery node, System.Type type) - { - _node = node.AstNode; - _type = type; - _key = _node.ToStringTree(); - } - - public IASTNode Translate(ISessionFactory sessionFactory) - { - return _node; - } - - public string Key - { - get { return _key; } - } - - public System.Type Type - { - get { return _type; } - } - } -} Modified: trunk/nhibernate/src/NHibernate/IQueryExpression.cs =================================================================== --- trunk/nhibernate/src/NHibernate/IQueryExpression.cs 2009-09-27 10:06:52 UTC (rev 4730) +++ trunk/nhibernate/src/NHibernate/IQueryExpression.cs 2009-09-28 17:04:14 UTC (rev 4731) @@ -1,4 +1,6 @@ +using NHibernate.Engine; using NHibernate.Hql.Ast.ANTLR.Tree; +using NHibernate.Impl; namespace NHibernate { @@ -7,5 +9,6 @@ IASTNode Translate(ISessionFactory sessionFactory); string Key { get; } System.Type Type { get; } + void SetQueryParametersPriorToExecute(QueryImpl impl); } } \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate/Impl/AbstractSessionImpl.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Impl/AbstractSessionImpl.cs 2009-09-27 10:06:52 UTC (rev 4730) +++ trunk/nhibernate/src/NHibernate/Impl/AbstractSessionImpl.cs 2009-09-28 17:04:14 UTC (rev 4731) @@ -252,8 +252,9 @@ using (new SessionIdLoggingContext(SessionId)) { CheckAndUpdateSessionStatus(); - QueryImpl query = new QueryImpl(queryExpression, this, - GetHQLQueryPlan(queryExpression, false).ParameterMetadata); + HQLQueryPlan queryPlan = GetHQLQueryPlan(queryExpression, false); + QueryImpl query = new QueryImpl(queryPlan.QueryExpression, this, + queryPlan.ParameterMetadata); query.SetComment("[expression]"); return query; } Modified: trunk/nhibernate/src/NHibernate/Impl/QueryImpl.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Impl/QueryImpl.cs 2009-09-27 10:06:52 UTC (rev 4730) +++ trunk/nhibernate/src/NHibernate/Impl/QueryImpl.cs 2009-09-28 17:04:14 UTC (rev 4731) @@ -74,6 +74,7 @@ } else { + _queryExpression.SetQueryParametersPriorToExecute(this); return Session.List(_queryExpression, GetQueryParameters(namedParams)); } } Modified: trunk/nhibernate/src/NHibernate/Linq/CommandData.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Linq/CommandData.cs 2009-09-27 10:06:52 UTC (rev 4730) +++ trunk/nhibernate/src/NHibernate/Linq/CommandData.cs 2009-09-28 17:04:14 UTC (rev 4731) @@ -8,8 +8,10 @@ { public class CommandData { + private readonly NamedParameter[] _namedParameters; private readonly List<LambdaExpression> _itemTransformers; private readonly List<LambdaExpression> _listTransformers; + private readonly List<Action<IQuery>> _additionalCriteria; public CommandData(HqlQuery statement, NamedParameter[] namedParameters, List<LambdaExpression> itemTransformers, List<LambdaExpression> listTransformers, List<Action<IQuery>> additionalCriteria) { @@ -17,47 +19,29 @@ _listTransformers = listTransformers; Statement = statement; - NamedParameters = namedParameters; - AdditionalCriteria = additionalCriteria; + _namedParameters = namedParameters; + _additionalCriteria = additionalCriteria; } public HqlQuery Statement { get; private set; } - public NamedParameter[] NamedParameters { get; private set; } - public List<Action<IQuery>> AdditionalCriteria { get; set; } - - public System.Type QueryResultType { get; set; } - - public IQuery CreateQuery(ISession session, System.Type type) + public void SetParameters(IQuery query) { - var query = session.CreateQuery(new HqlExpression(Statement, type)); - - SetParameters(query); - - SetResultTransformer(query); - - AddAdditionalCriteria(query); - - return query; - } - - private void SetParameters(IQuery query) - { - foreach (var parameter in NamedParameters) + foreach (var parameter in _namedParameters) { query.SetParameter(parameter.Name, parameter.Value); } } - private void AddAdditionalCriteria(IQuery query) + public void AddAdditionalCriteria(IQuery query) { - foreach (var criteria in AdditionalCriteria) + foreach (var criteria in _additionalCriteria) { criteria(query); } } - private void SetResultTransformer(IQuery query) + public void SetResultTransformer(IQuery query) { var itemTransformer = MergeLambdas(_itemTransformers); var listTransformer = MergeLambdas(_listTransformers); Deleted: trunk/nhibernate/src/NHibernate/Linq/NhQueryExecutor.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Linq/NhQueryExecutor.cs 2009-09-27 10:06:52 UTC (rev 4730) +++ trunk/nhibernate/src/NHibernate/Linq/NhQueryExecutor.cs 2009-09-28 17:04:14 UTC (rev 4731) @@ -1,39 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using Remotion.Data.Linq; - -namespace NHibernate.Linq -{ - public class NhQueryExecutor : IQueryExecutor - { - private readonly ISession _session; - - public NhQueryExecutor(ISession session) - { - _session = session; - } - - // Executes a query with a scalar result, i.e. a query that ends with a result operator such as Count, Sum, or Average. - public T ExecuteScalar<T>(QueryModel queryModel) - { - return ExecuteCollection<T>(queryModel).Single(); - } - - // Executes a query with a single result object, i.e. a query that ends with a result operator such as First, Last, Single, Min, or Max. - public T ExecuteSingle<T>(QueryModel queryModel, bool returnDefaultWhenEmpty) - { - return returnDefaultWhenEmpty ? ExecuteCollection<T>(queryModel).SingleOrDefault() : ExecuteCollection<T>(queryModel).Single(); - } - - // Executes a query with a collection result. - public IEnumerable<T> ExecuteCollection<T>(QueryModel queryModel) - { - var commandData = QueryModelVisitor.GenerateHqlQuery(queryModel); - - var query = commandData.CreateQuery(_session, typeof(T)); - - // TODO - check which call on Query makes most sense... - return (IEnumerable<T>) query.List(); - } - } -} \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate/Linq/NhQueryable.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Linq/NhQueryable.cs 2009-09-27 10:06:52 UTC (rev 4730) +++ trunk/nhibernate/src/NHibernate/Linq/NhQueryable.cs 2009-09-28 17:04:14 UTC (rev 4731) @@ -1,6 +1,10 @@ +using System; using System.Linq; using System.Linq.Expressions; +using NHibernate.Hql.Ast.ANTLR.Tree; +using NHibernate.Impl; using Remotion.Data.Linq; +using Remotion.Data.Linq.Parsing.Structure; namespace NHibernate.Linq { @@ -9,14 +13,9 @@ /// </summary> public class NhQueryable<T> : QueryableBase<T> { - private static IQueryExecutor CreateExecutor(ISession session) - { - return new NhQueryExecutor(session); - } - // This constructor is called by our users, create a new IQueryExecutor. public NhQueryable(ISession session) - : base(CreateExecutor(session)) + : base(new NhQueryProvider(session)) { } @@ -26,4 +25,95 @@ { } } + + public class NhQueryProvider : IQueryProvider + { + private readonly ISession _session; + + public NhQueryProvider(ISession session) + { + _session = session; + } + + public object Execute(Expression expression) + { + var nhLinqExpression = new NhLinqExpression(expression); + + var query = _session.CreateQuery(nhLinqExpression).List(); + + if (nhLinqExpression.ReturnType == NhLinqExpressionReturnType.Sequence) + { + return query.AsQueryable(); + } + + return query[0]; + } + + public TResult Execute<TResult>(Expression expression) + { + return (TResult) Execute(expression); + } + + public IQueryable CreateQuery(Expression expression) + { + throw new NotImplementedException(); + } + + public IQueryable<T> CreateQuery<T>(Expression expression) + { + return new NhQueryable<T>(this, expression); + } + } + + public enum NhLinqExpressionReturnType + { + Sequence, + Scalar + } + + public class NhLinqExpression : IQueryExpression + { + private readonly Expression _expression; + private CommandData _commandData; + + public NhLinqExpression(Expression expression) + { + _expression = expression; + + Key = expression.ToString(); + + Type = expression.Type; + + // Note - re-linq handles return types via the GetOutputDataInfo method, and allows for SingleOrDefault here for the ChoiceResultOperator... + ReturnType = NhLinqExpressionReturnType.Scalar; + + if (typeof(IQueryable).IsAssignableFrom(Type)) + { + Type = Type.GetGenericArguments()[0]; + ReturnType = NhLinqExpressionReturnType.Sequence; + } + } + + public IASTNode Translate(ISessionFactory sessionFactory) + { + var queryModel = new QueryParser(new ExpressionTreeParser(MethodCallExpressionNodeTypeRegistry.CreateDefault())).GetParsedQuery(_expression); + + _commandData = QueryModelVisitor.GenerateHqlQuery(queryModel); + + return _commandData.Statement.AstNode; + } + + public string Key { get; private set; } + + public NhLinqExpressionReturnType ReturnType { get; private set; } + + public System.Type Type { get; private set; } + + public void SetQueryParametersPriorToExecute(QueryImpl impl) + { + _commandData.SetParameters(impl); + _commandData.SetResultTransformer(impl); + _commandData.AddAdditionalCriteria(impl); + } + } } \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate/NHibernate.csproj =================================================================== --- trunk/nhibernate/src/NHibernate/NHibernate.csproj 2009-09-27 10:06:52 UTC (rev 4730) +++ trunk/nhibernate/src/NHibernate/NHibernate.csproj 2009-09-28 17:04:14 UTC (rev 4731) @@ -557,7 +557,6 @@ <Compile Include="Hql\Ast\ANTLR\Tree\ASTErrorNode.cs" /> <Compile Include="Hql\Ast\ANTLR\Tree\InsertStatement.cs" /> <Compile Include="Hql\Ast\ANTLR\Tree\UpdateStatement.cs" /> - <Compile Include="Hql\Ast\HqlExpression.cs" /> <Compile Include="Hql\Ast\HqlTreeBuilder.cs" /> <Compile Include="Hql\Ast\HqlTreeNode.cs" /> <Compile Include="IQueryExpression.cs" /> @@ -581,7 +580,6 @@ <Compile Include="Linq\NhExpressionTreeVisitor.cs" /> <Compile Include="Linq\NhNewExpression.cs" /> <Compile Include="Linq\NhQueryable.cs" /> - <Compile Include="Linq\NhQueryExecutor.cs" /> <Compile Include="Linq\NhThrowingExpressionTreeVisitor.cs" /> <Compile Include="Linq\Nominator.cs" /> <Compile Include="Linq\NonAggregatingGroupBy.cs" /> Modified: trunk/nhibernate/src/NHibernate.Test/Linq/LinqTestCase.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/Linq/LinqTestCase.cs 2009-09-27 10:06:52 UTC (rev 4730) +++ trunk/nhibernate/src/NHibernate.Test/Linq/LinqTestCase.cs 2009-09-28 17:04:14 UTC (rev 4731) @@ -13,6 +13,16 @@ private Northwind _northwind; private ISession _session; + protected override bool PerformDbDataSetup + { + get { return true; } + } + + protected override bool PerformDbDataTeardown + { + get { return true; } + } + protected override string MappingsAssembly { get { return "NHibernate.Test"; } Modified: trunk/nhibernate/src/NHibernate.Test/Linq/ReadonlyTestCase.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/Linq/ReadonlyTestCase.cs 2009-09-27 10:06:52 UTC (rev 4730) +++ trunk/nhibernate/src/NHibernate.Test/Linq/ReadonlyTestCase.cs 2009-09-28 17:04:14 UTC (rev 4731) @@ -63,6 +63,9 @@ get { return "NHibernate.DomainModel"; } } + protected abstract bool PerformDbDataSetup { get; } + protected abstract bool PerformDbDataTeardown { get; } + static ReadonlyTestCase() { // Configure log4net here since configuration through an attribute doesn't always work. @@ -84,7 +87,12 @@ } BuildSessionFactory(); - CreateSchema(); + + if (PerformDbDataSetup) + { + CreateSchema(); + } + if (!AppliesTo(_sessions)) { DropSchema(); @@ -92,7 +100,10 @@ Assert.Ignore(GetType() + " does not apply with the current session-factory configuration"); } - OnFixtureSetup(); + if (PerformDbDataSetup) + { + OnFixtureSetup(); + } } catch (Exception e) { @@ -114,8 +125,12 @@ public void TestFixtureTearDown() { OnFixtureTeardown(); - - DropSchema(); + + if (PerformDbDataTeardown) + { + DropSchema(); + } + Cleanup(); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |