|
From: <ric...@us...> - 2011-05-25 21:16:08
|
Revision: 5871
http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5871&view=rev
Author: ricbrown
Date: 2011-05-25 21:16:01 +0000 (Wed, 25 May 2011)
Log Message:
-----------
NH-2733 (NH-2683): Using an expression in QueryOver gives: Lambda Parameter not in scope
Modified Paths:
--------------
trunk/nhibernate/src/NHibernate/Impl/ExpressionProcessor.cs
trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/ExpressionProcessorFixture.cs
trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj
Added Paths:
-----------
trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2733/
trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2733/Fixture.cs
trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2733/Mappings.hbm.xml
trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2733/Model.cs
Modified: trunk/nhibernate/src/NHibernate/Impl/ExpressionProcessor.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Impl/ExpressionProcessor.cs 2011-05-25 12:47:06 UTC (rev 5870)
+++ trunk/nhibernate/src/NHibernate/Impl/ExpressionProcessor.cs 2011-05-25 21:16:01 UTC (rev 5871)
@@ -334,10 +334,14 @@
if (memberExpression.Expression.NodeType == ExpressionType.MemberAccess)
{
+ if (IsMemberExpression(memberExpression.Expression))
+ return true;
+
// if the member has a null value, it was an alias
- if (EvaluatesToNull(memberExpression.Expression))
- return true;
+ return EvaluatesToNull(memberExpression.Expression);
}
+
+ return IsMemberExpression(memberExpression.Expression);
}
if (expression is UnaryExpression)
@@ -358,9 +362,16 @@
if (_customProjectionProcessors.ContainsKey(signature))
return true;
+ if (methodCallExpression.Method.Name == "First")
+ {
+ if (IsMemberExpression(methodCallExpression.Arguments[0]))
+ return true;
+
+ return EvaluatesToNull(methodCallExpression.Arguments[0]);
+ }
+
if (methodCallExpression.Method.Name == "GetType"
- || methodCallExpression.Method.Name == "get_Item"
- || methodCallExpression.Method.Name == "First")
+ || methodCallExpression.Method.Name == "get_Item")
{
if (IsMemberExpression(methodCallExpression.Object))
return true;
Modified: trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/ExpressionProcessorFixture.cs
===================================================================
--- trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/ExpressionProcessorFixture.cs 2011-05-25 12:47:06 UTC (rev 5870)
+++ trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/ExpressionProcessorFixture.cs 2011-05-25 21:16:01 UTC (rev 5871)
@@ -1,5 +1,6 @@
using System;
+using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
@@ -19,35 +20,165 @@
public void TestFindMemberExpressionReference()
{
Expression<Func<Person, string>> e = (Person p) => p.Name;
- string property = ExpressionProcessor.FindMemberExpression(e.Body);
+ string property = ExpressionProcessor.FindMemberProjection(e.Body).ToString();
Assert.AreEqual("Name", property);
}
[Test]
+ public void TestFindMemberExpressionReferenceAlias()
+ {
+ Person personAlias = null;
+ Expression<Func<string>> e = () => personAlias.Name;
+ string property = ExpressionProcessor.FindMemberProjection(e.Body).ToString();
+ Assert.AreEqual("personAlias.Name", property);
+ }
+
+ [Test]
+ public void TestFindMemberExpressionComponent()
+ {
+ Expression<Func<Person, string>> e = (Person p) => p.Father.Name;
+ string property = ExpressionProcessor.FindMemberProjection(e.Body).ToString();
+ Assert.AreEqual("Father.Name", property);
+ }
+
+ [Test]
+ public void TestFindMemberExpressionComponentAlias()
+ {
+ Person personAlias = null;
+ Expression<Func<string>> e = () => personAlias.Father.Name;
+ string property = ExpressionProcessor.FindMemberProjection(e.Body).ToString();
+ Assert.AreEqual("personAlias.Father.Name", property);
+ }
+
+ [Test]
public void TestFindMemberExpressionValue()
{
Expression<Func<Person, object>> e = (Person p) => p.Age;
- string property = ExpressionProcessor.FindMemberExpression(e.Body);
+ string property = ExpressionProcessor.FindMemberProjection(e.Body).ToString();
Assert.AreEqual("Age", property);
}
[Test]
+ public void TestFindMemberExpressionValueAlias()
+ {
+ Person personAlias = null;
+ Expression<Func<object>> e = () => personAlias.Age;
+ string property = ExpressionProcessor.FindMemberProjection(e.Body).ToString();
+ Assert.AreEqual("personAlias.Age", property);
+ }
+
+ [Test]
public void TestFindMemberExpressionSubCollectionIndex()
{
Expression<Func<Person, object>> e = (Person p) => p.PersonList[0].Children;
- string property = ExpressionProcessor.FindMemberExpression(e.Body);
+ string property = ExpressionProcessor.FindMemberProjection(e.Body).ToString();
Assert.AreEqual("PersonList.Children", property);
}
[Test]
+ public void TestFindMemberExpressionSubCollectionIndexAlias()
+ {
+ Person personAlias = null;
+ Expression<Func<object>> e = () => personAlias.PersonList[0].Children;
+ string property = ExpressionProcessor.FindMemberProjection(e.Body).ToString();
+ Assert.AreEqual("personAlias.PersonList.Children", property);
+ }
+
+ [Test]
+ public void TestFindMemberExpressionSubCollectionFirst()
+ {
+ Expression<Func<Person, object>> e = (Person p) => p.PersonList.First().Children;
+ string property = ExpressionProcessor.FindMemberProjection(e.Body).ToString();
+ Assert.AreEqual("PersonList.Children", property);
+ }
+
+ [Test]
+ public void TestFindMemberExpressionSubCollectionFirstAlias()
+ {
+ Person personAlias = null;
+ Expression<Func<object>> e = () => personAlias.PersonList.First().Children;
+ string property = ExpressionProcessor.FindMemberProjection(e.Body).ToString();
+ Assert.AreEqual("personAlias.PersonList.Children", property);
+ }
+
+ [Test]
public void TestFindMemberExpressionSubCollectionExtensionMethod()
{
Expression<Func<Person, object>> e = (Person p) => p.PersonList.First().Children;
- string property = ExpressionProcessor.FindMemberExpression(e.Body);
+ string property = ExpressionProcessor.FindMemberProjection(e.Body).ToString();
Assert.AreEqual("PersonList.Children", property);
}
[Test]
+ public void TestFindMemberExpressionSubCollectionExtensionMethodAlias()
+ {
+ Person personAlias = null;
+ Expression<Func<object>> e = () => personAlias.PersonList.First().Children;
+ string property = ExpressionProcessor.FindMemberProjection(e.Body).ToString();
+ Assert.AreEqual("personAlias.PersonList.Children", property);
+ }
+
+ [Test]
+ public void TestFindMemberExpressionClass()
+ {
+ Expression<Func<Person, object>> e = (Person p) => p.GetType();
+ string property = ExpressionProcessor.FindMemberProjection(e.Body).ToString();
+ Assert.AreEqual("class", property);
+ }
+
+ [Test]
+ public void TestFindMemberExpressionClassAlias()
+ {
+ Person personAlias = null;
+ Expression<Func<object>> e = () => personAlias.GetType();
+ string property = ExpressionProcessor.FindMemberProjection(e.Body).ToString();
+ Assert.AreEqual("personAlias.class", property);
+ }
+
+ [Test]
+ public void TestFindMemberExpressionNullableValue()
+ {
+ Expression<Func<Person, object>> e = (Person p) => p.NullableGender.Value;
+ string property = ExpressionProcessor.FindMemberProjection(e.Body).ToString();
+ Assert.AreEqual("NullableGender", property);
+ }
+
+ [Test]
+ public void TestFindMemberExpressionNullableValueAlias()
+ {
+ Person personAlias = null;
+ Expression<Func<object>> e = () => personAlias.NullableGender.Value;
+ string property = ExpressionProcessor.FindMemberProjection(e.Body).ToString();
+ Assert.AreEqual("personAlias.NullableGender", property);
+ }
+
+ [Test]
+ public void TestFindMemberExpressionConstants()
+ {
+ var children = new List<Child> { new Child { Nickname = "test nickname" } };
+ Person person =
+ new Person()
+ {
+ Name = "test name",
+ NullableAge = 4,
+ Children = children,
+ };
+
+ Assert.That(Projection(() => person.Name), Is.EqualTo("test name"));
+ Assert.That(Projection(() => "test name"), Is.EqualTo("test name"));
+ Assert.That(Projection(() => person.NullableAge.Value), Is.EqualTo(4));
+ Assert.That(Projection(() => person.GetType()), Is.EqualTo(typeof(Person)));
+ Assert.That(Projection(() => person.Children.First().Nickname), Is.EqualTo("test nickname"));
+ Assert.That(Projection(() => children[0].Nickname), Is.EqualTo("test nickname"));
+ }
+
+ private T Projection<T>(Expression<Func<T>> e)
+ {
+ var constantProjection = ExpressionProcessor.FindMemberProjection(e.Body);
+ return (T)typeof(ConstantProjection).GetField("value", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(constantProjection);
+ }
+
+ [Test]
public void TestEvaluatePropertyExpression()
{
string testName = "testName";
Property changes on: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2733
___________________________________________________________________
Added: bugtraq:url
+ http://jira.nhibernate.org/browse/%BUGID%
Added: bugtraq:logregex
+ NH-\d+
Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2733/Fixture.cs
===================================================================
--- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2733/Fixture.cs (rev 0)
+++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2733/Fixture.cs 2011-05-25 21:16:01 UTC (rev 5871)
@@ -0,0 +1,81 @@
+using System;
+using System.Linq.Expressions;
+using NUnit.Framework;
+
+namespace NHibernate.Test.NHSpecificTest.NH2733
+{
+ public interface ISpecification
+ {
+ Expression Expression { get; }
+ }
+
+ public interface ISpecification<T> : ISpecification
+ {
+ Expression<Func<T, bool>> Predicate { get; }
+ }
+
+ public class Specification<T>
+ {
+ public Expression<Func<T, bool>> Predicate { get; protected set; }
+
+ public Expression Expression
+ {
+ get
+ {
+ return Predicate;
+ }
+ }
+
+ public Specification(Expression<Func<T, bool>> predicate)
+ {
+ Predicate = predicate;
+ }
+ }
+
+ [TestFixture]
+ public class Fixture : BugTestCase
+ {
+ Item Item = null;
+
+ protected override void OnSetUp()
+ {
+ using (ISession session = Sfi.OpenSession())
+ {
+ var item = new Item();
+ session.Persist(item);
+ session.Flush();
+ }
+ }
+
+ protected override void OnTearDown()
+ {
+ using (ISession session = Sfi.OpenSession())
+ {
+ session.CreateQuery("delete from Item").ExecuteUpdate();
+ session.Flush();
+ }
+ base.OnTearDown();
+ }
+
+ public static Expression<Func<Item, bool>> GetExpression(DateTime startTime)
+ {
+ return item => item.Details.StartTime == startTime;
+ }
+
+ [Test]
+ public void CanUseExpressionForWhere()
+ {
+ using (ISession session = Sfi.OpenSession())
+ {
+ IQueryOver<Item, Item> query = session.QueryOver(() => Item);
+
+ var start = DateTime.UtcNow;
+
+ query
+ .Where(GetExpression(start));
+
+ query.List();
+ }
+ }
+ }
+}
Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2733/Mappings.hbm.xml
===================================================================
--- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2733/Mappings.hbm.xml (rev 0)
+++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2733/Mappings.hbm.xml 2011-05-25 21:16:01 UTC (rev 5871)
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
+ namespace="NHibernate.Test.NHSpecificTest.NH2733"
+ assembly="NHibernate.Test">
+
+ <class name="Item" table="`Item_Table`">
+ <id name="Id">
+ <generator class="native"/>
+ </id>
+ <component name="Details">
+ <property name="StartTime" />
+ </component>
+ </class>
+</hibernate-mapping>
Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2733/Model.cs
===================================================================
--- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2733/Model.cs (rev 0)
+++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2733/Model.cs 2011-05-25 21:16:01 UTC (rev 5871)
@@ -0,0 +1,22 @@
+using System;
+using System.Collections.Generic;
+
+namespace NHibernate.Test.NHSpecificTest.NH2733
+{
+ public class Item
+ {
+ public virtual int Id { get; set; }
+
+ public class ItemDetails
+ {
+ public virtual DateTime? StartTime { get; set; }
+ }
+
+ public virtual ItemDetails Details { get; set; }
+
+ public Item()
+ {
+ Details = new ItemDetails();
+ }
+ }
+}
\ No newline at end of file
Modified: trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj
===================================================================
--- trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2011-05-25 12:47:06 UTC (rev 5870)
+++ trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2011-05-25 21:16:01 UTC (rev 5871)
@@ -854,6 +854,8 @@
<Compile Include="NHSpecificTest\NH2705\SubItemBase.cs" />
<Compile Include="NHSpecificTest\NH2705\SubItemDetails.cs" />
<Compile Include="NHSpecificTest\NH2705\Test.cs" />
+ <Compile Include="NHSpecificTest\NH2733\Fixture.cs" />
+ <Compile Include="NHSpecificTest\NH2733\Model.cs" />
<Compile Include="NHSpecificTest\Properties\CompositePropertyRefTest.cs" />
<Compile Include="NHSpecificTest\Properties\DynamicEntityTest.cs" />
<Compile Include="NHSpecificTest\Properties\Model.cs" />
@@ -2696,6 +2698,7 @@
<EmbeddedResource Include="NHSpecificTest\NH1291AnonExample\Mappings.hbm.xml" />
</ItemGroup>
<ItemGroup>
+ <EmbeddedResource Include="NHSpecificTest\NH2733\Mappings.hbm.xml" />
<EmbeddedResource Include="NHSpecificTest\NH2317\Mappings.hbm.xml" />
<EmbeddedResource Include="NHSpecificTest\NH2366\Mappings.hbm.xml" />
<EmbeddedResource Include="NHSpecificTest\NH2404\Mappings.hbm.xml" />
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <pa...@us...> - 2011-05-28 06:39:20
|
Revision: 5874
http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5874&view=rev
Author: patearl
Date: 2011-05-28 06:39:13 +0000 (Sat, 28 May 2011)
Log Message:
-----------
Linq: Support Trim function.
Modified Paths:
--------------
trunk/nhibernate/src/NHibernate/Linq/Functions/DefaultLinqToHqlGeneratorsRegistry.cs
trunk/nhibernate/src/NHibernate/Linq/Functions/StringGenerator.cs
trunk/nhibernate/src/NHibernate.Test/Linq/FunctionTests.cs
trunk/nhibernate/src/NHibernate.Test/TestDialect.cs
Added Paths:
-----------
trunk/nhibernate/src/NHibernate.Test/TestDialects/MsSql2008TestDialect.cs
Modified: trunk/nhibernate/src/NHibernate/Linq/Functions/DefaultLinqToHqlGeneratorsRegistry.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Linq/Functions/DefaultLinqToHqlGeneratorsRegistry.cs 2011-05-28 05:34:42 UTC (rev 5873)
+++ trunk/nhibernate/src/NHibernate/Linq/Functions/DefaultLinqToHqlGeneratorsRegistry.cs 2011-05-28 06:39:13 UTC (rev 5874)
@@ -30,6 +30,7 @@
this.Merge(new IndexOfGenerator());
this.Merge(new ReplaceGenerator());
this.Merge(new LengthGenerator());
+ this.Merge(new TrimGenerator());
this.Merge(new AnyHqlGenerator());
this.Merge(new AllHqlGenerator());
Modified: trunk/nhibernate/src/NHibernate/Linq/Functions/StringGenerator.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Linq/Functions/StringGenerator.cs 2011-05-28 05:34:42 UTC (rev 5873)
+++ trunk/nhibernate/src/NHibernate/Linq/Functions/StringGenerator.cs 2011-05-28 06:39:13 UTC (rev 5874)
@@ -195,6 +195,46 @@
}
}
+ public class TrimGenerator : BaseHqlGeneratorForMethod
+ {
+ public TrimGenerator()
+ {
+ SupportedMethods = new[]
+ {
+ ReflectionHelper.GetMethodDefinition<string>(s => s.Trim()),
+ ReflectionHelper.GetMethodDefinition<string>(s => s.Trim('a')),
+ ReflectionHelper.GetMethodDefinition<string>(s => s.TrimStart('a')),
+ ReflectionHelper.GetMethodDefinition<string>(s => s.TrimEnd('a'))
+ };
+ }
+
+ public override HqlTreeNode BuildHql(MethodInfo method, Expression targetObject, ReadOnlyCollection<Expression> arguments, HqlTreeBuilder treeBuilder, IHqlExpressionVisitor visitor)
+ {
+ string trimWhere;
+ if (method.Name == "TrimStart")
+ trimWhere = "leading";
+ else if (method.Name == "TrimEnd")
+ trimWhere = "trailing";
+ else
+ trimWhere = "both";
+
+ string trimChars = "";
+ if (method.GetParameters().Length > 0)
+ foreach (char c in (char[])((ConstantExpression)arguments[0]).Value)
+ trimChars += c;
+
+
+ if (trimChars == "")
+ {
+ return treeBuilder.MethodCall("trim", treeBuilder.Ident(trimWhere), treeBuilder.Ident("from"), visitor.Visit(targetObject).AsExpression());
+ }
+ else
+ {
+ return treeBuilder.MethodCall("trim", treeBuilder.Ident(trimWhere), treeBuilder.Constant(trimChars), treeBuilder.Ident("from"), visitor.Visit(targetObject).AsExpression());
+ }
+ }
+ }
+
public class ToStringRuntimeMethodHqlGenerator : IRuntimeMethodHqlGenerator
{
private readonly ToStringHqlGeneratorForMethod generator = new ToStringHqlGeneratorForMethod();
Modified: trunk/nhibernate/src/NHibernate.Test/Linq/FunctionTests.cs
===================================================================
--- trunk/nhibernate/src/NHibernate.Test/Linq/FunctionTests.cs 2011-05-28 05:34:42 UTC (rev 5873)
+++ trunk/nhibernate/src/NHibernate.Test/Linq/FunctionTests.cs 2011-05-28 06:39:13 UTC (rev 5874)
@@ -118,5 +118,29 @@
{
Assert.AreEqual(2, session.Query<AnotherEntity>().Where(e => (e.Input ?? "hello") == "hello").Count());
}
+
+ [Test]
+ public void Trim()
+ {
+ try
+ {
+ session.Save(new AnotherEntity { Id = 100, Input = " hi " });
+ session.Save(new AnotherEntity { Id = 101, Input = "hi" });
+ session.Save(new AnotherEntity { Id = 102, Input = "heh" });
+
+ Assert.AreEqual(2, session.Query<AnotherEntity>().Where(e => e.Input.Trim() == "hi").Count());
+ Assert.AreEqual(TestDialect.IgnoresTrailingWhitespace ? 2 : 1, session.Query<AnotherEntity>().Where(e => e.Input.TrimStart() == "hi ").Count());
+ Assert.AreEqual(1, session.Query<AnotherEntity>().Where(e => e.Input.TrimEnd() == " hi").Count());
+
+ // Emulated trim does not support multiple trim characters, but for many databases it should work fine anyways.
+ Assert.AreEqual(1, session.Query<AnotherEntity>().Where(e => e.Input.Trim('h') == "e").Count());
+ Assert.AreEqual(1, session.Query<AnotherEntity>().Where(e => e.Input.TrimStart('h') == "eh").Count());
+ Assert.AreEqual(1, session.Query<AnotherEntity>().Where(e => e.Input.TrimEnd('h') == "he").Count());
+ }
+ finally
+ {
+ session.Delete("from AnotherEntity where Id >= 100");
+ }
+ }
}
}
\ No newline at end of file
Modified: trunk/nhibernate/src/NHibernate.Test/TestDialect.cs
===================================================================
--- trunk/nhibernate/src/NHibernate.Test/TestDialect.cs 2011-05-28 05:34:42 UTC (rev 5873)
+++ trunk/nhibernate/src/NHibernate.Test/TestDialect.cs 2011-05-28 06:39:13 UTC (rev 5874)
@@ -53,6 +53,8 @@
public virtual bool SupportsHavingWithoutGroupBy { get { return true; } }
+ public virtual bool IgnoresTrailingWhitespace { get { return false; } }
+
public bool SupportsSqlType(SqlType sqlType)
{
try
Copied: trunk/nhibernate/src/NHibernate.Test/TestDialects/MsSql2008TestDialect.cs (from rev 5872, trunk/nhibernate/src/NHibernate.Test/TestDialects/SQLiteTestDialect.cs)
===================================================================
--- trunk/nhibernate/src/NHibernate.Test/TestDialects/MsSql2008TestDialect.cs (rev 0)
+++ trunk/nhibernate/src/NHibernate.Test/TestDialects/MsSql2008TestDialect.cs 2011-05-28 06:39:13 UTC (rev 5874)
@@ -0,0 +1,20 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace NHibernate.Test.TestDialects
+{
+ public class MsSql2008TestDialect : TestDialect
+ {
+ public MsSql2008TestDialect(Dialect.Dialect dialect)
+ : base(dialect)
+ {
+ }
+
+ public override bool IgnoresTrailingWhitespace
+ {
+ get { return true; }
+ }
+ }
+}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ric...@us...> - 2011-05-28 11:13:57
|
Revision: 5877
http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5877&view=rev
Author: ricbrown
Date: 2011-05-28 11:13:51 +0000 (Sat, 28 May 2011)
Log Message:
-----------
NH-2683: Added QueryOver functions to OrderBy
Modified Paths:
--------------
trunk/nhibernate/src/NHibernate/Criterion/Lambda/QueryOverOrderBuilder.cs
trunk/nhibernate/src/NHibernate/Impl/ExpressionProcessor.cs
trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/IntegrationFixture.cs
trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/QueryOverFixture.cs
Modified: trunk/nhibernate/src/NHibernate/Criterion/Lambda/QueryOverOrderBuilder.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Criterion/Lambda/QueryOverOrderBuilder.cs 2011-05-28 07:12:07 UTC (rev 5876)
+++ trunk/nhibernate/src/NHibernate/Criterion/Lambda/QueryOverOrderBuilder.cs 2011-05-28 11:13:51 UTC (rev 5877)
@@ -70,7 +70,10 @@
if (projection != null)
root.UnderlyingCriteria.AddOrder(orderDelegate(projection));
else
- root.UnderlyingCriteria.AddOrder(ExpressionProcessor.ProcessOrder(path, orderStringDelegate, isAlias));
+ if (isAlias)
+ root.UnderlyingCriteria.AddOrder(ExpressionProcessor.ProcessOrder(path, orderStringDelegate));
+ else
+ root.UnderlyingCriteria.AddOrder(ExpressionProcessor.ProcessOrder(path, orderDelegate));
}
public TReturn Asc
Modified: trunk/nhibernate/src/NHibernate/Impl/ExpressionProcessor.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Impl/ExpressionProcessor.cs 2011-05-28 07:12:07 UTC (rev 5876)
+++ trunk/nhibernate/src/NHibernate/Impl/ExpressionProcessor.cs 2011-05-28 11:13:51 UTC (rev 5877)
@@ -650,17 +650,29 @@
/// </summary>
/// <param name="expression">The lambda expression to convert</param>
/// <param name="orderDelegate">The appropriate order delegate (order direction)</param>
- /// <param name="isAlias">Indicates if the path is an aliased projection</param>
/// <returns>NHibernate Order</returns>
public static Order ProcessOrder( LambdaExpression expression,
- Func<string, Order> orderDelegate,
- bool isAlias)
+ Func<string, Order> orderDelegate)
{
- string property = isAlias ? FindPropertyExpression(expression.Body) : FindMemberExpression(expression.Body);
+ string property = FindPropertyExpression(expression.Body);
Order order = orderDelegate(property);
return order;
}
+ /// <summary>
+ /// Convert a lambda expression to NHibernate Order
+ /// </summary>
+ /// <param name="expression">The lambda expression to convert</param>
+ /// <param name="orderDelegate">The appropriate order delegate (order direction)</param>
+ /// <returns>NHibernate Order</returns>
+ public static Order ProcessOrder( LambdaExpression expression,
+ Func<IProjection, Order> orderDelegate)
+ {
+ IProjection projection = FindMemberProjection(expression.Body);
+ Order order = orderDelegate(projection);
+ return order;
+ }
+
private static AbstractCriterion ProcessSubqueryExpression(LambdaSubqueryType subqueryType,
BinaryExpression be)
{
Modified: trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/IntegrationFixture.cs
===================================================================
--- trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/IntegrationFixture.cs 2011-05-28 07:12:07 UTC (rev 5876)
+++ trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/IntegrationFixture.cs 2011-05-28 11:13:51 UTC (rev 5877)
@@ -640,6 +640,34 @@
}
[Test]
+ public void FunctionsOrder()
+ {
+ using (ISession s = OpenSession())
+ using (ITransaction t = s.BeginTransaction())
+ {
+ s.Save(new Person() { Name = "p2", BirthDate = new DateTime(2008, 07, 06) });
+ s.Save(new Person() { Name = "p1", BirthDate = new DateTime(2009, 08, 07) });
+ s.Save(new Person() { Name = "p3", BirthDate = new DateTime(2007, 06, 05) });
+
+ t.Commit();
+ }
+
+ using (ISession s = OpenSession())
+ using (ITransaction t = s.BeginTransaction())
+ {
+ var persons =
+ s.QueryOver<Person>()
+ .OrderBy(p => p.BirthDate.YearPart()).Desc
+ .List();
+
+ persons.Count.Should().Be(3);
+ persons[0].Name.Should().Be("p1");
+ persons[1].Name.Should().Be("p2");
+ persons[2].Name.Should().Be("p3");
+ }
+ }
+
+ [Test]
public void MultiCriteria()
{
SetupPagingData();
Modified: trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/QueryOverFixture.cs
===================================================================
--- trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/QueryOverFixture.cs 2011-05-28 07:12:07 UTC (rev 5876)
+++ trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/QueryOverFixture.cs 2011-05-28 11:13:51 UTC (rev 5877)
@@ -608,10 +608,10 @@
{
ICriteria expected =
CreateTestCriteria(typeof(Person), "personAlias")
- .AddOrder(Order.Asc("Name"))
- .AddOrder(Order.Desc("Age"))
- .AddOrder(Order.Desc("personAlias.Name"))
- .AddOrder(Order.Asc("personAlias.Age"))
+ .AddOrder(Order.Asc(Projections.Property("Name")))
+ .AddOrder(Order.Desc(Projections.Property("Age")))
+ .AddOrder(Order.Desc(Projections.Property("personAlias.Name")))
+ .AddOrder(Order.Asc(Projections.Property("personAlias.Age")))
.AddOrder(Order.Asc("summary"))
.AddOrder(Order.Desc("Count"));
@@ -630,11 +630,26 @@
}
[Test]
+ public void OrderByFunction()
+ {
+ ICriteria expected =
+ CreateTestCriteria(typeof(Person), "personAlias")
+ .AddOrder(Order.Desc(Projections.SqlFunction("year", NHibernateUtil.Int32, Projections.Property("personAlias.BirthDate"))));
+
+ Person personAlias = null;
+ IQueryOver<Person> actual =
+ CreateTestQueryOver<Person>(() => personAlias)
+ .OrderBy(() => personAlias.BirthDate.YearPart()).Desc;
+
+ AssertCriteriaAreEqual(expected, actual);
+ }
+
+ [Test]
public void AllowSingleCallSyntax()
{
ICriteria expected = CreateTestCriteria(typeof(Person));
expected.Add(Restrictions.IsNotEmpty("Children"));
- expected.AddOrder(Order.Asc("Name"));
+ expected.AddOrder(Order.Asc(Projections.Property("Name")));
expected.SetFetchMode("PersonList", FetchMode.Eager);
expected.SetLockMode(LockMode.UpgradeNoWait);
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ric...@us...> - 2011-05-29 18:06:28
|
Revision: 5879
http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5879&view=rev
Author: ricbrown
Date: 2011-05-29 18:06:21 +0000 (Sun, 29 May 2011)
Log Message:
-----------
NH-2683: Added QueryOver functions to projections and SQL functions
Modified Paths:
--------------
trunk/nhibernate/src/NHibernate/Criterion/Lambda/LambdaRestrictionBuilder.cs
trunk/nhibernate/src/NHibernate/Criterion/Lambda/QueryOverRestrictionBuilder.cs
trunk/nhibernate/src/NHibernate/Criterion/Projections.cs
trunk/nhibernate/src/NHibernate/Criterion/QueryOver.cs
trunk/nhibernate/src/NHibernate/Criterion/Restrictions.cs
trunk/nhibernate/src/NHibernate/Criterion/RestrictionsExtensions.cs
trunk/nhibernate/src/NHibernate/Impl/ExpressionProcessor.cs
trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/IntegrationFixture.cs
trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/ProjectionsFixture.cs
trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/QueryOverFixture.cs
trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/RestrictionsFixture.cs
Modified: trunk/nhibernate/src/NHibernate/Criterion/Lambda/LambdaRestrictionBuilder.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Criterion/Lambda/LambdaRestrictionBuilder.cs 2011-05-29 02:36:57 UTC (rev 5878)
+++ trunk/nhibernate/src/NHibernate/Criterion/Lambda/LambdaRestrictionBuilder.cs 2011-05-29 18:06:21 UTC (rev 5879)
@@ -14,13 +14,13 @@
{
public class LambdaBetweenBuilder
{
- private string propertyName;
+ private IProjection projection;
private object lo;
private bool isNot;
- public LambdaBetweenBuilder(string propertyName, object lo, bool isNot)
+ public LambdaBetweenBuilder(IProjection projection, object lo, bool isNot)
{
- this.propertyName = propertyName;
+ this.projection = projection;
this.lo = lo;
this.isNot = isNot;
}
@@ -28,13 +28,13 @@
public AbstractCriterion And(object hi)
{
if (isNot)
- return Restrictions.Not(Restrictions.Between(propertyName, lo, hi));
+ return Restrictions.Not(Restrictions.Between(projection, lo, hi));
- return Restrictions.Between(propertyName, lo, hi);
+ return Restrictions.Between(projection, lo, hi);
}
}
- private string propertyName;
+ private IProjection projection;
private bool isNot;
private AbstractCriterion Process(AbstractCriterion criterion)
@@ -48,9 +48,9 @@
/// <summary>
/// Constructed with property name
/// </summary>
- public LambdaRestrictionBuilder(string propertyName)
+ public LambdaRestrictionBuilder(IProjection projection)
{
- this.propertyName = propertyName;
+ this.projection = projection;
}
/// <summary>
@@ -58,7 +58,7 @@
/// </summary>
public LambdaBetweenBuilder IsBetween(object lo)
{
- return new LambdaBetweenBuilder(propertyName, lo, isNot);
+ return new LambdaBetweenBuilder(projection, lo, isNot);
}
public LambdaRestrictionBuilder Not
@@ -75,7 +75,7 @@
/// </summary>
public AbstractCriterion IsIn(ICollection values)
{
- return Process(Restrictions.In(propertyName, values));
+ return Process(Restrictions.In(projection, values));
}
/// <summary>
@@ -83,7 +83,7 @@
/// </summary>
public AbstractCriterion IsIn(object[] values)
{
- return Process(Restrictions.In(propertyName, values));
+ return Process(Restrictions.In(projection, values));
}
/// <summary>
@@ -91,7 +91,7 @@
/// </summary>
public AbstractCriterion IsInG<T>(ICollection<T> values)
{
- return Process(Restrictions.InG(propertyName, values));
+ return Process(Restrictions.InG(projection, values));
}
/// <summary>
@@ -99,7 +99,7 @@
/// </summary>
public AbstractCriterion IsInsensitiveLike(object value)
{
- return Process(Restrictions.InsensitiveLike(propertyName, value));
+ return Process(Restrictions.InsensitiveLike(projection, value));
}
/// <summary>
@@ -107,7 +107,7 @@
/// </summary>
public AbstractCriterion IsInsensitiveLike(string value, MatchMode matchMode)
{
- return Process(Restrictions.InsensitiveLike(propertyName, value, matchMode));
+ return Process(Restrictions.InsensitiveLike(projection, value, matchMode));
}
/// <summary>
@@ -115,7 +115,7 @@
/// </summary>
public AbstractCriterion IsEmpty
{
- get { return Process(Restrictions.IsEmpty(propertyName)); }
+ get { return Process(Restrictions.IsEmpty(ExpressionProcessor.FindProperty(projection))); }
}
/// <summary>
@@ -123,7 +123,7 @@
/// </summary>
public AbstractCriterion IsNotEmpty
{
- get { return Process(Restrictions.IsNotEmpty(propertyName)); }
+ get { return Process(Restrictions.IsNotEmpty(ExpressionProcessor.FindProperty(projection))); }
}
/// <summary>
@@ -131,7 +131,7 @@
/// </summary>
public AbstractCriterion IsNull
{
- get { return Process(Restrictions.IsNull(propertyName)); }
+ get { return Process(Restrictions.IsNull(projection)); }
}
/// <summary>
@@ -139,7 +139,7 @@
/// </summary>
public AbstractCriterion IsNotNull
{
- get { return Process(Restrictions.IsNotNull(propertyName)); }
+ get { return Process(Restrictions.IsNotNull(projection)); }
}
/// <summary>
@@ -147,7 +147,7 @@
/// </summary>
public AbstractCriterion IsLike(object value)
{
- return Process(Restrictions.Like(propertyName, value));
+ return Process(Restrictions.Like(projection, value));
}
/// <summary>
@@ -155,7 +155,7 @@
/// </summary>
public AbstractCriterion IsLike(string value, MatchMode matchMode)
{
- return Process(Restrictions.Like(propertyName, value, matchMode));
+ return Process(Restrictions.Like(projection, value, matchMode));
}
/// <summary>
@@ -163,7 +163,7 @@
/// </summary>
public AbstractCriterion IsLike(string value, MatchMode matchMode, char? escapeChar)
{
- return Process(Restrictions.Like(propertyName, value, matchMode, escapeChar));
+ return Process(Restrictions.Like(ExpressionProcessor.FindProperty(projection), value, matchMode, escapeChar));
}
}
Modified: trunk/nhibernate/src/NHibernate/Criterion/Lambda/QueryOverRestrictionBuilder.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Criterion/Lambda/QueryOverRestrictionBuilder.cs 2011-05-29 02:36:57 UTC (rev 5878)
+++ trunk/nhibernate/src/NHibernate/Criterion/Lambda/QueryOverRestrictionBuilder.cs 2011-05-29 18:06:21 UTC (rev 5879)
@@ -13,8 +13,8 @@
public class QueryOverRestrictionBuilder<TRoot,TSubType> : QueryOverRestrictionBuilderBase<QueryOver<TRoot,TSubType>, TRoot, TSubType>
{
- public QueryOverRestrictionBuilder(QueryOver<TRoot,TSubType> root, string propertyName)
- : base(root, propertyName) { }
+ public QueryOverRestrictionBuilder(QueryOver<TRoot,TSubType> root, IProjection projection)
+ : base(root, projection) { }
public QueryOverRestrictionBuilder<TRoot,TSubType> Not
{
@@ -30,8 +30,8 @@
public class IQueryOverRestrictionBuilder<TRoot,TSubType> : QueryOverRestrictionBuilderBase<IQueryOver<TRoot,TSubType>, TRoot, TSubType>
{
- public IQueryOverRestrictionBuilder(IQueryOver<TRoot,TSubType> root, string propertyName)
- : base(root, propertyName) { }
+ public IQueryOverRestrictionBuilder(IQueryOver<TRoot,TSubType> root, IProjection projection)
+ : base(root, projection) { }
public IQueryOverRestrictionBuilder<TRoot,TSubType> Not
{
@@ -50,14 +50,14 @@
public class LambdaBetweenBuilder
{
private TReturn root;
- private string propertyName;
+ private IProjection projection;
private bool isNot;
private object lo;
- public LambdaBetweenBuilder(TReturn root, string propertyName, bool isNot, object lo)
+ public LambdaBetweenBuilder(TReturn root, IProjection projection, bool isNot, object lo)
{
this.root = root;
- this.propertyName = propertyName;
+ this.projection = projection;
this.isNot = isNot;
this.lo = lo;
}
@@ -72,21 +72,21 @@
public TReturn And(object hi)
{
- return Add(Restrictions.Between(propertyName, lo, hi));
+ return Add(Restrictions.Between(projection, lo, hi));
}
}
private TReturn root;
- private string propertyName;
+ private IProjection projection;
protected bool isNot;
/// <summary>
/// Constructed with property name
/// </summary>
- public QueryOverRestrictionBuilderBase(TReturn root, string propertyName)
+ public QueryOverRestrictionBuilderBase(TReturn root, IProjection projection)
{
this.root = root;
- this.propertyName = propertyName;
+ this.projection = projection;
}
private TReturn Add(ICriterion criterion)
@@ -102,7 +102,7 @@
/// </summary>
public LambdaBetweenBuilder IsBetween(object lo)
{
- return new LambdaBetweenBuilder(root, propertyName, isNot, lo);
+ return new LambdaBetweenBuilder(root, projection, isNot, lo);
}
/// <summary>
@@ -110,7 +110,7 @@
/// </summary>
public TReturn IsIn(ICollection values)
{
- return Add(Restrictions.In(propertyName, values));
+ return Add(Restrictions.In(projection, values));
}
/// <summary>
@@ -118,7 +118,7 @@
/// </summary>
public TReturn IsIn(object[] values)
{
- return Add(Restrictions.In(propertyName, values));
+ return Add(Restrictions.In(projection, values));
}
/// <summary>
@@ -126,7 +126,7 @@
/// </summary>
public TReturn IsInG<T>(ICollection<T> values)
{
- return Add(Restrictions.InG(propertyName, values));
+ return Add(Restrictions.InG(projection, values));
}
/// <summary>
@@ -134,7 +134,7 @@
/// </summary>
public TReturn IsInsensitiveLike(object value)
{
- return Add(Restrictions.InsensitiveLike(propertyName, value));
+ return Add(Restrictions.InsensitiveLike(projection, value));
}
/// <summary>
@@ -142,7 +142,7 @@
/// </summary>
public TReturn IsInsensitiveLike(string value, MatchMode matchMode)
{
- return Add(Restrictions.InsensitiveLike(propertyName, value, matchMode));
+ return Add(Restrictions.InsensitiveLike(projection, value, matchMode));
}
/// <summary>
@@ -150,7 +150,7 @@
/// </summary>
public TReturn IsEmpty
{
- get { return Add(Restrictions.IsEmpty(propertyName)); }
+ get { return Add(Restrictions.IsEmpty(ExpressionProcessor.FindProperty(projection))); }
}
/// <summary>
@@ -158,7 +158,7 @@
/// </summary>
public TReturn IsNotEmpty
{
- get { return Add(Restrictions.IsNotEmpty(propertyName)); }
+ get { return Add(Restrictions.IsNotEmpty(ExpressionProcessor.FindProperty(projection))); }
}
/// <summary>
@@ -166,7 +166,7 @@
/// </summary>
public TReturn IsNull
{
- get { return Add(Restrictions.IsNull(propertyName)); }
+ get { return Add(Restrictions.IsNull(projection)); }
}
/// <summary>
@@ -174,7 +174,7 @@
/// </summary>
public TReturn IsNotNull
{
- get { return Add(Restrictions.IsNotNull(propertyName)); }
+ get { return Add(Restrictions.IsNotNull(projection)); }
}
/// <summary>
@@ -182,7 +182,7 @@
/// </summary>
public TReturn IsLike(object value)
{
- return Add(Restrictions.Like(propertyName, value));
+ return Add(Restrictions.Like(projection, value));
}
/// <summary>
@@ -190,7 +190,7 @@
/// </summary>
public TReturn IsLike(string value, MatchMode matchMode)
{
- return Add(Restrictions.Like(propertyName, value, matchMode));
+ return Add(Restrictions.Like(projection, value, matchMode));
}
/// <summary>
@@ -198,7 +198,7 @@
/// </summary>
public TReturn IsLike(string value, MatchMode matchMode, char? escapeChar)
{
- return Add(Restrictions.Like(propertyName, value, matchMode, escapeChar));
+ return Add(Restrictions.Like(ExpressionProcessor.FindProperty(projection), value, matchMode, escapeChar));
}
}
Modified: trunk/nhibernate/src/NHibernate/Criterion/Projections.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Criterion/Projections.cs 2011-05-29 02:36:57 UTC (rev 5878)
+++ trunk/nhibernate/src/NHibernate/Criterion/Projections.cs 2011-05-29 18:06:21 UTC (rev 5879)
@@ -324,7 +324,7 @@
/// </summary>
public static AggregateProjection Avg<T>(Expression<Func<T, object>> expression)
{
- return Projections.Avg(ExpressionProcessor.FindMemberExpression(expression.Body));
+ return Projections.Avg(ExpressionProcessor.FindMemberProjection(expression.Body));
}
/// <summary>
@@ -332,7 +332,7 @@
/// </summary>
public static AggregateProjection Avg(Expression<Func<object>> expression)
{
- return Projections.Avg(ExpressionProcessor.FindMemberExpression(expression.Body));
+ return Projections.Avg(ExpressionProcessor.FindMemberProjection(expression.Body));
}
/// <summary>
@@ -340,7 +340,7 @@
/// </summary>
public static CountProjection Count<T>(Expression<Func<T, object>> expression)
{
- return Projections.Count(ExpressionProcessor.FindMemberExpression(expression.Body));
+ return Projections.Count(ExpressionProcessor.FindMemberProjection(expression.Body));
}
/// <summary>
@@ -348,7 +348,7 @@
/// </summary>
public static CountProjection Count(Expression<Func<object>> expression)
{
- return Projections.Count(ExpressionProcessor.FindMemberExpression(expression.Body));
+ return Projections.Count(ExpressionProcessor.FindMemberProjection(expression.Body));
}
/// <summary>
@@ -388,7 +388,7 @@
/// </summary>
public static AggregateProjection Max<T>(Expression<Func<T, object>> expression)
{
- return Projections.Max(ExpressionProcessor.FindMemberExpression(expression.Body));
+ return Projections.Max(ExpressionProcessor.FindMemberProjection(expression.Body));
}
/// <summary>
@@ -396,7 +396,7 @@
/// </summary>
public static AggregateProjection Max(Expression<Func<object>> expression)
{
- return Projections.Max(ExpressionProcessor.FindMemberExpression(expression.Body));
+ return Projections.Max(ExpressionProcessor.FindMemberProjection(expression.Body));
}
/// <summary>
@@ -404,7 +404,7 @@
/// </summary>
public static AggregateProjection Min<T>(Expression<Func<T, object>> expression)
{
- return Projections.Min(ExpressionProcessor.FindMemberExpression(expression.Body));
+ return Projections.Min(ExpressionProcessor.FindMemberProjection(expression.Body));
}
/// <summary>
@@ -412,7 +412,7 @@
/// </summary>
public static AggregateProjection Min(Expression<Func<object>> expression)
{
- return Projections.Min(ExpressionProcessor.FindMemberExpression(expression.Body));
+ return Projections.Min(ExpressionProcessor.FindMemberProjection(expression.Body));
}
/// <summary>
@@ -441,7 +441,7 @@
/// </summary>
public static AggregateProjection Sum<T>(Expression<Func<T, object>> expression)
{
- return Projections.Sum(ExpressionProcessor.FindMemberExpression(expression.Body));
+ return Projections.Sum(ExpressionProcessor.FindMemberProjection(expression.Body));
}
/// <summary>
@@ -449,7 +449,7 @@
/// </summary>
public static AggregateProjection Sum(Expression<Func<object>> expression)
{
- return Projections.Sum(ExpressionProcessor.FindMemberExpression(expression.Body));
+ return Projections.Sum(ExpressionProcessor.FindMemberProjection(expression.Body));
}
/// <summary>
Modified: trunk/nhibernate/src/NHibernate/Criterion/QueryOver.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Criterion/QueryOver.cs 2011-05-29 02:36:57 UTC (rev 5878)
+++ trunk/nhibernate/src/NHibernate/Criterion/QueryOver.cs 2011-05-29 18:06:21 UTC (rev 5879)
@@ -344,12 +344,12 @@
public QueryOverRestrictionBuilder<TRoot,TSubType> AndRestrictionOn(Expression<Func<TSubType, object>> expression)
{
- return new QueryOverRestrictionBuilder<TRoot,TSubType>(this, ExpressionProcessor.FindMemberExpression(expression.Body));
+ return new QueryOverRestrictionBuilder<TRoot,TSubType>(this, ExpressionProcessor.FindMemberProjection(expression.Body));
}
public QueryOverRestrictionBuilder<TRoot,TSubType> AndRestrictionOn(Expression<Func<object>> expression)
{
- return new QueryOverRestrictionBuilder<TRoot,TSubType>(this, ExpressionProcessor.FindMemberExpression(expression.Body));
+ return new QueryOverRestrictionBuilder<TRoot,TSubType>(this, ExpressionProcessor.FindMemberProjection(expression.Body));
}
public QueryOver<TRoot,TSubType> Where(Expression<Func<TSubType, bool>> expression)
@@ -379,12 +379,12 @@
public QueryOverRestrictionBuilder<TRoot,TSubType> WhereRestrictionOn(Expression<Func<TSubType, object>> expression)
{
- return new QueryOverRestrictionBuilder<TRoot,TSubType>(this, ExpressionProcessor.FindMemberExpression(expression.Body));
+ return new QueryOverRestrictionBuilder<TRoot,TSubType>(this, ExpressionProcessor.FindMemberProjection(expression.Body));
}
public QueryOverRestrictionBuilder<TRoot,TSubType> WhereRestrictionOn(Expression<Func<object>> expression)
{
- return new QueryOverRestrictionBuilder<TRoot,TSubType>(this, ExpressionProcessor.FindMemberExpression(expression.Body));
+ return new QueryOverRestrictionBuilder<TRoot,TSubType>(this, ExpressionProcessor.FindMemberProjection(expression.Body));
}
public QueryOver<TRoot,TSubType> Select(params Expression<Func<TRoot, object>>[] projections)
@@ -791,10 +791,10 @@
{ return AndNot(expression); }
IQueryOverRestrictionBuilder<TRoot,TSubType> IQueryOver<TRoot,TSubType>.AndRestrictionOn(Expression<Func<TSubType, object>> expression)
- { return new IQueryOverRestrictionBuilder<TRoot,TSubType>(this, ExpressionProcessor.FindMemberExpression(expression.Body)); }
+ { return new IQueryOverRestrictionBuilder<TRoot,TSubType>(this, ExpressionProcessor.FindMemberProjection(expression.Body)); }
IQueryOverRestrictionBuilder<TRoot,TSubType> IQueryOver<TRoot,TSubType>.AndRestrictionOn(Expression<Func<object>> expression)
- { return new IQueryOverRestrictionBuilder<TRoot,TSubType>(this, ExpressionProcessor.FindMemberExpression(expression.Body)); }
+ { return new IQueryOverRestrictionBuilder<TRoot,TSubType>(this, ExpressionProcessor.FindMemberProjection(expression.Body)); }
IQueryOver<TRoot,TSubType> IQueryOver<TRoot,TSubType>.Where(Expression<Func<TSubType, bool>> expression)
{ return Where(expression); }
@@ -812,10 +812,10 @@
{ return WhereNot(expression); }
IQueryOverRestrictionBuilder<TRoot,TSubType> IQueryOver<TRoot,TSubType>.WhereRestrictionOn(Expression<Func<TSubType, object>> expression)
- { return new IQueryOverRestrictionBuilder<TRoot,TSubType>(this, ExpressionProcessor.FindMemberExpression(expression.Body)); }
+ { return new IQueryOverRestrictionBuilder<TRoot,TSubType>(this, ExpressionProcessor.FindMemberProjection(expression.Body)); }
IQueryOverRestrictionBuilder<TRoot,TSubType> IQueryOver<TRoot,TSubType>.WhereRestrictionOn(Expression<Func<object>> expression)
- { return new IQueryOverRestrictionBuilder<TRoot,TSubType>(this, ExpressionProcessor.FindMemberExpression(expression.Body)); }
+ { return new IQueryOverRestrictionBuilder<TRoot,TSubType>(this, ExpressionProcessor.FindMemberProjection(expression.Body)); }
IQueryOver<TRoot,TSubType> IQueryOver<TRoot,TSubType>.Select(params Expression<Func<TRoot, object>>[] projections)
{ return Select(projections); }
Modified: trunk/nhibernate/src/NHibernate/Criterion/Restrictions.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Criterion/Restrictions.cs 2011-05-29 02:36:57 UTC (rev 5878)
+++ trunk/nhibernate/src/NHibernate/Criterion/Restrictions.cs 2011-05-29 18:06:21 UTC (rev 5879)
@@ -790,8 +790,8 @@
/// <returns>returns LambdaRestrictionBuilder</returns>
public static LambdaRestrictionBuilder On<T>(Expression<Func<T, object>> expression)
{
- string property = ExpressionProcessor.FindMemberExpression(expression.Body);
- return new LambdaRestrictionBuilder(property);
+ IProjection projection = ExpressionProcessor.FindMemberProjection(expression.Body);
+ return new LambdaRestrictionBuilder(projection);
}
/// <summary>
@@ -801,8 +801,8 @@
/// <returns>returns LambdaRestrictionBuilder</returns>
public static LambdaRestrictionBuilder On(Expression<Func<object>> expression)
{
- string property = ExpressionProcessor.FindMemberExpression(expression.Body);
- return new LambdaRestrictionBuilder(property);
+ IProjection projection = ExpressionProcessor.FindMemberProjection(expression.Body);
+ return new LambdaRestrictionBuilder(projection);
}
}
Modified: trunk/nhibernate/src/NHibernate/Criterion/RestrictionsExtensions.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Criterion/RestrictionsExtensions.cs 2011-05-29 02:36:57 UTC (rev 5878)
+++ trunk/nhibernate/src/NHibernate/Criterion/RestrictionsExtensions.cs 2011-05-29 18:06:21 UTC (rev 5879)
@@ -89,17 +89,17 @@
public static ICriterion ProcessIsLike(MethodCallExpression methodCallExpression)
{
- string property = ExpressionProcessor.FindMemberExpression(methodCallExpression.Arguments[0]);
+ IProjection projection = ExpressionProcessor.FindMemberProjection(methodCallExpression.Arguments[0]);
object value = ExpressionProcessor.FindValue(methodCallExpression.Arguments[1]);
- return Restrictions.Like(property, value);
+ return Restrictions.Like(projection, value);
}
public static ICriterion ProcessIsLikeMatchMode(MethodCallExpression methodCallExpression)
{
- string property = ExpressionProcessor.FindMemberExpression(methodCallExpression.Arguments[0]);
+ IProjection projection = ExpressionProcessor.FindMemberProjection(methodCallExpression.Arguments[0]);
string value = (string)ExpressionProcessor.FindValue(methodCallExpression.Arguments[1]);
MatchMode matchMode = (MatchMode)ExpressionProcessor.FindValue(methodCallExpression.Arguments[2]);
- return Restrictions.Like(property, value, matchMode);
+ return Restrictions.Like(projection, value, matchMode);
}
public static ICriterion ProcessIsLikeMatchModeEscapeChar(MethodCallExpression methodCallExpression)
@@ -113,40 +113,40 @@
public static ICriterion ProcessIsInsensitiveLike(MethodCallExpression methodCallExpression)
{
- string property = ExpressionProcessor.FindMemberExpression(methodCallExpression.Arguments[0]);
+ IProjection projection = ExpressionProcessor.FindMemberProjection(methodCallExpression.Arguments[0]);
object value = ExpressionProcessor.FindValue(methodCallExpression.Arguments[1]);
- return Restrictions.InsensitiveLike(property, value);
+ return Restrictions.InsensitiveLike(projection, value);
}
public static ICriterion ProcessIsInsensitiveLikeMatchMode(MethodCallExpression methodCallExpression)
{
- string property = ExpressionProcessor.FindMemberExpression(methodCallExpression.Arguments[0]);
+ IProjection projection = ExpressionProcessor.FindMemberProjection(methodCallExpression.Arguments[0]);
string value = (string)ExpressionProcessor.FindValue(methodCallExpression.Arguments[1]);
MatchMode matchMode = (MatchMode)ExpressionProcessor.FindValue(methodCallExpression.Arguments[2]);
- return Restrictions.InsensitiveLike(property, value, matchMode);
+ return Restrictions.InsensitiveLike(projection, value, matchMode);
}
public static ICriterion ProcessIsInArray(MethodCallExpression methodCallExpression)
{
- string property = ExpressionProcessor.FindMemberExpression(methodCallExpression.Arguments[0]);
+ IProjection projection = ExpressionProcessor.FindMemberProjection(methodCallExpression.Arguments[0]);
object[] values = (object[])ExpressionProcessor.FindValue(methodCallExpression.Arguments[1]);
- return Restrictions.In(property, values);
+ return Restrictions.In(projection, values);
}
public static ICriterion ProcessIsInCollection(MethodCallExpression methodCallExpression)
{
- string property = ExpressionProcessor.FindMemberExpression(methodCallExpression.Arguments[0]);
+ IProjection projection = ExpressionProcessor.FindMemberProjection(methodCallExpression.Arguments[0]);
ICollection values = (ICollection)ExpressionProcessor.FindValue(methodCallExpression.Arguments[1]);
- return Restrictions.In(property, values);
+ return Restrictions.In(projection, values);
}
public static ICriterion ProcessIsBetween(MethodCallExpression methodCallExpression)
{
MethodCallExpression betweenFunction = (MethodCallExpression)methodCallExpression.Object;
- string property = ExpressionProcessor.FindMemberExpression(betweenFunction.Arguments[0]);
+ IProjection projection = ExpressionProcessor.FindMemberProjection(betweenFunction.Arguments[0]);
object lo = ExpressionProcessor.FindValue(betweenFunction.Arguments[1]);
object hi = ExpressionProcessor.FindValue(methodCallExpression.Arguments[0]);
- return Restrictions.Between(property, lo, hi);
+ return Restrictions.Between(projection, lo, hi);
}
}
}
Modified: trunk/nhibernate/src/NHibernate/Impl/ExpressionProcessor.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Impl/ExpressionProcessor.cs 2011-05-29 02:36:57 UTC (rev 5878)
+++ trunk/nhibernate/src/NHibernate/Impl/ExpressionProcessor.cs 2011-05-29 18:06:21 UTC (rev 5879)
@@ -741,6 +741,18 @@
_customProjectionProcessors.Add(signature, functionProcessor);
}
+ /// <summary>
+ /// Retreive the property name from a supplied PropertyProjection
+ /// Note: throws is the supplied IProjection is not a PropertyProjection
+ /// </summary>
+ public static string FindProperty(IProjection projection)
+ {
+ if (!(projection is PropertyProjection))
+ throw new Exception("Cannot determine property for " + projection.ToString());
+
+ return ((PropertyProjection)projection).PropertyName;
+ }
+
}
}
Modified: trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/IntegrationFixture.cs
===================================================================
--- trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/IntegrationFixture.cs 2011-05-29 02:36:57 UTC (rev 5878)
+++ trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/IntegrationFixture.cs 2011-05-29 18:06:21 UTC (rev 5879)
@@ -593,6 +593,19 @@
using (ISession s = OpenSession())
{
+ var persons =
+ s.QueryOver<Person>()
+ .Where(p => p.BirthDate.YearPart().IsIn(new [] { 2008, 2009 }))
+ .OrderBy(p => p.Name).Asc
+ .List();
+
+ persons.Count.Should().Be(2);
+ persons[0].Name.Should().Be("p1");
+ persons[1].Name.Should().Be("p2");
+ }
+
+ using (ISession s = OpenSession())
+ {
var yearOfBirth =
s.QueryOver<Person>()
.Where(p => p.Name == "p2")
@@ -605,6 +618,17 @@
using (ISession s = OpenSession())
{
+ var avgYear =
+ s.QueryOver<Person>()
+ .SelectList(list => list.SelectAvg(p => p.BirthDate.YearPart()))
+ .SingleOrDefault<object>();
+
+ avgYear.GetType().Should().Be(typeof(double));
+ string.Format("{0:0}", avgYear).Should().Be("2008");
+ }
+
+ using (ISession s = OpenSession())
+ {
var sqrtOfAge =
s.QueryOver<Person>()
.Where(p => p.Name == "p1")
Modified: trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/ProjectionsFixture.cs
===================================================================
--- trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/ProjectionsFixture.cs 2011-05-29 02:36:57 UTC (rev 5878)
+++ trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/ProjectionsFixture.cs 2011-05-29 18:06:21 UTC (rev 5879)
@@ -39,24 +39,24 @@
ICriteria expected =
CreateTestCriteria(typeof(Person), "personAlias")
.SetProjection(Projections.ProjectionList()
- .Add(Projections.Alias(Projections.Avg("Age"), "personAgeProjectionAlias"))
- .Add(Projections.Avg("Age"), "personAgeProjectionAlias")
- .Add(Projections.Avg("personAlias.Age"), "Age")
- .Add(Projections.Count("Age"))
- .Add(Projections.Count("personAlias.Age"))
+ .Add(Projections.Alias(Projections.Avg(Projections.Property("Age")), "personAgeProjectionAlias"))
+ .Add(Projections.Avg(Projections.Property("Age")), "personAgeProjectionAlias")
+ .Add(Projections.Avg(Projections.Property("personAlias.Age")), "Age")
+ .Add(Projections.Count(Projections.Property("Age")))
+ .Add(Projections.Count(Projections.Property("personAlias.Age")))
.Add(Projections.CountDistinct("Age"))
.Add(Projections.CountDistinct("personAlias.Age"))
.Add(Projections.GroupProperty("Age"))
.Add(Projections.GroupProperty("personAlias.Age"))
- .Add(Projections.Max("Age"))
- .Add(Projections.Max("personAlias.Age"))
- .Add(Projections.Min("Age"))
- .Add(Projections.Min("personAlias.Age"))
+ .Add(Projections.Max(Projections.Property("Age")))
+ .Add(Projections.Max(Projections.Property("personAlias.Age")))
+ .Add(Projections.Min(Projections.Property("Age")))
+ .Add(Projections.Min(Projections.Property("personAlias.Age")))
.Add(Projections.Property("Age"))
.Add(Projections.Property("personAlias.Age"))
.Add(Projections.SubQuery(DetachedCriteriaAge))
- .Add(Projections.Sum("Age"))
- .Add(Projections.Sum("personAlias.Age")));
+ .Add(Projections.Sum(Projections.Property("Age")))
+ .Add(Projections.Sum(Projections.Property("personAlias.Age"))));
Person personAlias = null;
Person personAgeProjectionAlias = null;
@@ -91,24 +91,24 @@
ICriteria expected =
CreateTestCriteria(typeof(Person), "personAlias")
.SetProjection(Projections.ProjectionList()
- .Add(Projections.Alias(Projections.Avg("Age"), "personAgeProjectionAlias"))
+ .Add(Projections.Alias(Projections.Avg(Projections.Property("Age")), "personAgeProjectionAlias"))
.Add(Projections.Avg("Age"))
- .Add(Projections.Avg("personAlias.Age"), "Age")
- .Add(Projections.Count("Age"))
- .Add(Projections.Count("personAlias.Age"))
+ .Add(Projections.Avg(Projections.Property("personAli...
[truncated message content] |
|
From: <fab...@us...> - 2011-05-30 13:58:33
|
Revision: 5881
http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5881&view=rev
Author: fabiomaulo
Date: 2011-05-30 13:58:24 +0000 (Mon, 30 May 2011)
Log Message:
-----------
- Fix NH-2736
- refactoring of sql-parameters managements for HQL-LINQ
Modified Paths:
--------------
trunk/nhibernate/src/NHibernate/Engine/JoinSequence.cs
trunk/nhibernate/src/NHibernate/Engine/QueryParameters.cs
trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Exec/BasicExecutor.cs
trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Exec/MultiTableDeleteExecutor.cs
trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Exec/MultiTableUpdateExecutor.cs
trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/HqlSqlWalker.cs
trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Loader/QueryLoader.cs
trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/SqlGenerator.cs
trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Tree/BinaryLogicOperatorNode.cs
trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Tree/FromElement.cs
trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Tree/SqlFragment.cs
trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Util/JoinProcessor.cs
trunk/nhibernate/src/NHibernate/NHibernate.csproj
trunk/nhibernate/src/NHibernate/Param/AbstractExplicitParameterSpecification.cs
trunk/nhibernate/src/NHibernate/Param/AggregatedIndexCollectionSelectorParameterSpecifications.cs
trunk/nhibernate/src/NHibernate/Param/CollectionFilterKeyParameterSpecification.cs
trunk/nhibernate/src/NHibernate/Param/DynamicFilterParameterSpecification.cs
trunk/nhibernate/src/NHibernate/Param/IExplicitParameterSpecification.cs
trunk/nhibernate/src/NHibernate/Param/IParameterSpecification.cs
trunk/nhibernate/src/NHibernate/Param/NamedParameterSpecification.cs
trunk/nhibernate/src/NHibernate/Param/PositionalParameterSpecification.cs
trunk/nhibernate/src/NHibernate/Param/VersionTypeSeedParameterSpecification.cs
trunk/nhibernate/src/NHibernate/SqlCommand/Parameter.cs
trunk/nhibernate/src/NHibernate/SqlCommand/SqlString.cs
trunk/nhibernate/src/NHibernate.Test/Linq/FunctionTests.cs
trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj
trunk/nhibernate/src/NHibernate.Test/SqlCommandTest/SqlStringFixture.cs
Added Paths:
-----------
trunk/nhibernate/src/NHibernate/Param/ParametersBackTrackExtensions.cs
trunk/nhibernate/src/NHibernate/Param/QuerySkipParameterSpecification.cs
trunk/nhibernate/src/NHibernate/Param/QueryTakeParameterSpecification.cs
trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2736/
trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2736/Domain.cs
trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2736/Fixture.cs
trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2736/Mappings.hbm.xml
Modified: trunk/nhibernate/src/NHibernate/Engine/JoinSequence.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Engine/JoinSequence.cs 2011-05-29 18:36:56 UTC (rev 5880)
+++ trunk/nhibernate/src/NHibernate/Engine/JoinSequence.cs 2011-05-30 13:58:24 UTC (rev 5881)
@@ -139,7 +139,7 @@
public JoinFragment ToJoinFragment(
IDictionary<string, IFilter> enabledFilters,
bool includeExtraJoins,
- string withClauseFragment,
+ SqlString withClauseFragment,
string withClauseJoinAlias)
{
QueryJoinFragment joinFragment = new QueryJoinFragment(factory.Dialect, useThetaStyle);
@@ -164,7 +164,7 @@
{
Join join = joins[i];
string on = join.AssociationType.GetOnCondition(join.Alias, factory, enabledFilters);
- string condition;
+ SqlString condition = new SqlString();
if (last != null &&
IsManyToManyRoot(last) &&
((IQueryableCollection)last).ElementType == join.AssociationType)
@@ -174,36 +174,38 @@
// defined specifically on the many-to-many
string manyToManyFilter = ((IQueryableCollection)last)
.GetManyToManyFilterFragment(join.Alias, enabledFilters);
- condition = "".Equals(manyToManyFilter)
+ condition = new SqlString("".Equals(manyToManyFilter)
? on
: "".Equals(on)
? manyToManyFilter
- : on + " and " + manyToManyFilter;
+ : on + " and " + manyToManyFilter);
}
else
{
// NH Different behavior : NH1179 and NH1293
// Apply filters in Many-To-One association
var enabledForManyToOne = FilterHelper.GetEnabledForManyToOne(enabledFilters);
- condition = string.IsNullOrEmpty(on) && enabledForManyToOne.Count > 0
+ condition = new SqlString(string.IsNullOrEmpty(on) && enabledForManyToOne.Count > 0
? join.Joinable.FilterFragment(join.Alias, enabledForManyToOne)
- : on;
+ : on);
}
if (withClauseFragment != null)
{
if (join.Alias.Equals(withClauseJoinAlias))
{
- condition += " and " + withClauseFragment;
+ condition = condition.Append(" and ").Append(withClauseFragment);
}
}
+
+ // NH: the variable "condition" have to be a SqlString because it may contains Parameter instances with BackTrack
joinFragment.AddJoin(
join.Joinable.TableName,
join.Alias,
join.LHSColumns,
JoinHelper.GetRHSColumnNames(join.AssociationType, factory),
join.JoinType,
- new SqlString(condition)
+ condition
);
if (includeExtraJoins)
{
Modified: trunk/nhibernate/src/NHibernate/Engine/QueryParameters.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Engine/QueryParameters.cs 2011-05-29 18:36:56 UTC (rev 5880)
+++ trunk/nhibernate/src/NHibernate/Engine/QueryParameters.cs 2011-05-30 13:58:24 UTC (rev 5881)
@@ -324,7 +324,7 @@
{
if (part is Parameter)
{
- result.AddParameter();
+ result.Add(((Parameter)part).Clone());
// (?) can be a position parameter or a named parameter (already substituted by (?),
// but only the positional parameters are available at this point. Adding them in the
@@ -487,7 +487,7 @@
int span = typedval.Type.GetColumnSpan(factory);
string name = namedParameter.Key;
- int[] locs = GetEffectiveNamedParameterLocations(sqlParameters, name) ?? getNamedParameterLocations(name);
+ int[] locs = getNamedParameterLocations(name);
for (int i = 0; i < locs.Length; i++)
{
int location = locs[i];
@@ -567,23 +567,6 @@
return ConvertITypesToSqlTypes(paramTypeList, factory, totalSpan);
}
- private int[] GetEffectiveNamedParameterLocations(IList<Parameter> sqlParameters, object backTrackId)
- {
- var locations = new List<int>(5);
- for (int i = 0; i < sqlParameters.Count; i++)
- {
- if (backTrackId.Equals(sqlParameters[i].BackTrack))
- {
- locations.Add(i);
- }
- }
- if(locations.Count == 0)
- {
- return null;
- }
- return locations.ToArray();
- }
-
public int BindParameters(IDbCommand command, int start, ISessionImplementor session)
{
int location = start;
@@ -651,6 +634,12 @@
return span;
}
+ internal SqlString ProcessedSql
+ {
+ get { return processedSQL; }
+ set { processedSQL = value; }
+ }
+
public SqlString FilteredSQL
{
get { return processedSQL; }
@@ -659,16 +648,19 @@
public IList<IType> FilteredParameterTypes
{
get { return filteredParameterTypes; }
+ internal set { filteredParameterTypes = value; }
}
public IList<object> FilteredParameterValues
{
get { return filteredParameterValues; }
+ internal set { filteredParameterValues = value; }
}
public IList<int> FilteredParameterLocations
{
get { return filteredParameterLocations; }
+ internal set { filteredParameterLocations = value; }
}
public bool NaturalKeyLookup { get; set; }
Modified: trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Exec/BasicExecutor.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Exec/BasicExecutor.cs 2011-05-29 18:36:56 UTC (rev 5880)
+++ trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Exec/BasicExecutor.cs 2011-05-30 13:58:24 UTC (rev 5881)
@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
+using System.Linq;
using Antlr.Runtime;
using Antlr.Runtime.Tree;
@@ -9,9 +10,9 @@
using NHibernate.Exceptions;
using NHibernate.Hql.Ast.ANTLR.Tree;
using NHibernate.Param;
-using NHibernate.Persister.Entity;
using NHibernate.SqlCommand;
using NHibernate.SqlTypes;
+using IQueryable = NHibernate.Persister.Entity.IQueryable;
namespace NHibernate.Hql.Ast.ANTLR.Exec
{
@@ -59,24 +60,16 @@
try
{
CheckParametersExpectedType(parameters); // NH Different behavior (NH-1898)
- var parameterTypes = new List<SqlType>(Parameters.Count);
+
+ var sqlQueryParametersList = sql.GetParameters().ToList();
+ SqlType[] parameterTypes = Parameters.GetQueryParameterTypes(sqlQueryParametersList, session.Factory);
+
+ st = session.Batcher.PrepareCommand(CommandType.Text, sql, parameterTypes);
foreach (var parameterSpecification in Parameters)
{
- if (parameterSpecification.ExpectedType == null)
- {
- throw new QuerySyntaxException("Can't determine SqlType of parameter " + parameterSpecification.RenderDisplayInfo()+"\n Possible cause: wrong case-sensitive property-name.");
- }
- parameterTypes.AddRange(parameterSpecification.ExpectedType.SqlTypes(Factory));
+ parameterSpecification.Bind(st, sqlQueryParametersList, parameters, session);
}
- st = session.Batcher.PrepareCommand(CommandType.Text, sql, parameterTypes.ToArray());
- IEnumerator<IParameterSpecification> paramSpecifications = Parameters.GetEnumerator();
- // NH Different behavior: The inital value is 0 (initialized to 1 in JAVA)
- int pos = 0;
- while (paramSpecifications.MoveNext())
- {
- var paramSpec = paramSpecifications.Current;
- pos += paramSpec.Bind(st, parameters, session, pos);
- }
+
if (selection != null)
{
if (selection.Timeout != RowSelection.NoValue)
Modified: trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Exec/MultiTableDeleteExecutor.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Exec/MultiTableDeleteExecutor.cs 2011-05-29 18:36:56 UTC (rev 5880)
+++ trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Exec/MultiTableDeleteExecutor.cs 2011-05-30 13:58:24 UTC (rev 5881)
@@ -1,16 +1,15 @@
using System;
-using System.Collections.Generic;
using System.Data;
using System.Data.Common;
-
+using System.Linq;
using NHibernate.Engine;
using NHibernate.Exceptions;
using NHibernate.Hql.Ast.ANTLR.Tree;
using NHibernate.Param;
-using NHibernate.Persister.Entity;
using NHibernate.SqlCommand;
using NHibernate.SqlTypes;
using NHibernate.Util;
+using IQueryable = NHibernate.Persister.Entity.IQueryable;
namespace NHibernate.Hql.Ast.ANTLR.Exec
{
@@ -83,19 +82,15 @@
try
{
var paramsSpec = Walker.Parameters;
- var parameterTypes = new List<SqlType>(paramsSpec.Count);
+ var sqlQueryParametersList = idInsertSelect.GetParameters().ToList();
+ SqlType[] parameterTypes = paramsSpec.GetQueryParameterTypes(sqlQueryParametersList, session.Factory);
+
+ ps = session.Batcher.PrepareCommand(CommandType.Text, idInsertSelect, parameterTypes);
foreach (var parameterSpecification in paramsSpec)
{
- parameterTypes.AddRange(parameterSpecification.ExpectedType.SqlTypes(Factory));
+ parameterSpecification.Bind(ps, sqlQueryParametersList, parameters, session);
}
- ps = session.Batcher.PrepareCommand(CommandType.Text, idInsertSelect, parameterTypes.ToArray());
- // NH Different behavior: The inital value is 0 (initialized to 1 in JAVA)
- int pos = 0;
- foreach (var specification in paramsSpec)
- {
- pos += specification.Bind(ps, parameters, session, pos);
- }
resultCount = session.Batcher.ExecuteNonQuery(ps);
}
finally
Modified: trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Exec/MultiTableUpdateExecutor.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Exec/MultiTableUpdateExecutor.cs 2011-05-29 18:36:56 UTC (rev 5880)
+++ trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Exec/MultiTableUpdateExecutor.cs 2011-05-30 13:58:24 UTC (rev 5881)
@@ -2,7 +2,7 @@
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
-
+using System.Linq;
using NHibernate.Engine;
using NHibernate.Exceptions;
using NHibernate.Hql.Ast.ANTLR.Tree;
@@ -11,6 +11,7 @@
using NHibernate.SqlCommand;
using NHibernate.SqlTypes;
using NHibernate.Util;
+using IQueryable = NHibernate.Persister.Entity.IQueryable;
namespace NHibernate.Hql.Ast.ANTLR.Exec
{
@@ -109,9 +110,15 @@
List<IParameterSpecification> whereParams = (new List<IParameterSpecification>(allParams)).GetRange(
parameterStart, allParams.Count - parameterStart);
- ps = session.Batcher.PrepareCommand(CommandType.Text, idInsertSelect, GetParametersTypes(whereParams));
+ var sqlQueryParametersList = idInsertSelect.GetParameters().ToList();
+ SqlType[] parameterTypes = whereParams.GetQueryParameterTypes(sqlQueryParametersList, session.Factory);
- BindParameters(whereParams, ps, parameters, session);
+ ps = session.Batcher.PrepareCommand(CommandType.Text, idInsertSelect, parameterTypes);
+ foreach (var parameterSpecification in whereParams)
+ {
+ parameterSpecification.Bind(ps, sqlQueryParametersList, parameters, session);
+ }
+
resultCount = session.Batcher.ExecuteNonQuery(ps);
}
finally
@@ -139,8 +146,16 @@
{
try
{
- ps = session.Batcher.PrepareCommand(CommandType.Text, updates[i], GetParametersTypes(hqlParameters[i]));
- BindParameters(hqlParameters[i], ps, parameters, session);
+ var sqlQueryParametersList = updates[i].GetParameters().ToList();
+ var paramsSpec = hqlParameters[i];
+ SqlType[] parameterTypes = paramsSpec.GetQueryParameterTypes(sqlQueryParametersList, session.Factory);
+
+ ps = session.Batcher.PrepareCommand(CommandType.Text, updates[i], parameterTypes);
+ foreach (var parameterSpecification in paramsSpec)
+ {
+ parameterSpecification.Bind(ps, sqlQueryParametersList, parameters, session);
+ }
+
session.Batcher.ExecuteNonQuery(ps);
}
finally
@@ -165,34 +180,6 @@
}
}
- private SqlType[] GetParametersTypes(IEnumerable<IParameterSpecification> specifications)
- {
- if (specifications == null)
- {
- return new SqlType[0];
- }
- var result = new List<SqlType>();
- foreach (var specification in specifications)
- {
- result.AddRange(specification.ExpectedType.SqlTypes(Factory));
- }
- return result.ToArray();
- }
-
- private static void BindParameters(IEnumerable<IParameterSpecification> specifications, IDbCommand command,
- QueryParameters parameters, ISessionImplementor session)
- {
- if (specifications == null)
- {
- return;
- }
- int position = 0; // ADO params are 0-based
- foreach (var specification in specifications)
- {
- position += specification.Bind(command, parameters, session, position);
- }
- }
-
protected override IQueryable[] AffectedQueryables
{
get { return new[] {persister}; }
Modified: trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/HqlSqlWalker.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/HqlSqlWalker.cs 2011-05-29 18:36:56 UTC (rev 5880)
+++ trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/HqlSqlWalker.cs 2011-05-30 13:58:24 UTC (rev 5881)
@@ -907,6 +907,7 @@
{
if (_namedParameters.Count > 0)
{
+ // NH TODO: remove this limitation
throw new SemanticException("cannot define positional parameter after any named parameters have been defined");
}
ParameterNode parameter = (ParameterNode)adaptor.Create(PARAM, "?");
@@ -1081,7 +1082,8 @@
sql.whereExpr();
- fromElement.SetWithClauseFragment(visitor.GetJoinAlias(), "(" + sql.GetSQL() + ")");
+ var withClauseFragment = new SqlString("(", sql.GetSQL(), ")");
+ fromElement.SetWithClauseFragment(visitor.GetJoinAlias(), withClauseFragment);
}
catch (SemanticException)
{
Modified: trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Loader/QueryLoader.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Loader/QueryLoader.cs 2011-05-29 18:36:56 UTC (rev 5880)
+++ trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Loader/QueryLoader.cs 2011-05-30 13:58:24 UTC (rev 5881)
@@ -1,21 +1,24 @@
using System;
+using System.Linq;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
-
using NHibernate.Engine;
using NHibernate.Event;
using NHibernate.Hql.Ast.ANTLR.Tree;
+using NHibernate.Hql.Classic;
using NHibernate.Impl;
using NHibernate.Loader;
using NHibernate.Param;
using NHibernate.Persister.Collection;
using NHibernate.Persister.Entity;
using NHibernate.SqlCommand;
+using NHibernate.SqlTypes;
using NHibernate.Transform;
using NHibernate.Type;
using NHibernate.Util;
+using IQueryable = NHibernate.Persister.Entity.IQueryable;
namespace NHibernate.Hql.Ast.ANTLR.Loader
{
@@ -23,7 +26,6 @@
public class QueryLoader : BasicLoader
{
private readonly QueryTranslatorImpl _queryTranslator;
- private SelectClause _selectClause;
private bool _hasScalars;
private string[][] _scalarColumnNames;
@@ -49,7 +51,6 @@
: base(factory)
{
_queryTranslator = queryTranslator;
- _selectClause = selectClause;
Initialize(selectClause);
PostInstantiate();
@@ -434,5 +435,241 @@
}
return result;
}
+
+ /// <summary>
+ /// Obtain an <c>IDbCommand</c> with all parameters pre-bound. Bind positional parameters,
+ /// named parameters, and limit parameters.
+ /// </summary>
+ /// <remarks>
+ /// Creates an IDbCommand object and populates it with the values necessary to execute it against the
+ /// database to Load an Entity.
+ /// </remarks>
+ /// <param name="queryParameters">The <see cref="QueryParameters"/> to use for the IDbCommand.</param>
+ /// <param name="scroll">TODO: find out where this is used...</param>
+ /// <param name="session">The SessionImpl this Command is being prepared in.</param>
+ /// <returns>A CommandWrapper wrapping an IDbCommand that is ready to be executed.</returns>
+ protected internal override IDbCommand PrepareQueryCommand(QueryParameters queryParameters, bool scroll, ISessionImplementor session)
+ {
+ // NH: In this QueryLoader we can know better all parameters used so we can simplify the IDbCommand construction
+ // NH: would be very useful if we can do the same with Criteria. This method works just for HQL and LINQ.
+
+ // A distinct-copy of parameter specifications collected during query construction
+ var parameterSpecs = new HashSet<IParameterSpecification>(_queryTranslator.CollectedParameterSpecifications);
+ SqlString sqlString = SqlString.Copy();
+
+ // dynamic-filter parameters: during the HQL->SQL parsing, filters can be added as SQL_TOKEN/string and the SqlGenerator will not find it
+ sqlString = ExpandDynamicFilterParameters(sqlString, parameterSpecs, session);
+ AdjustQueryParametersForSubSelectFetching(sqlString, parameterSpecs, session, queryParameters); // NOTE: see TODO below
+
+ sqlString = AddLimitsParametersIfNeeded(sqlString, parameterSpecs, queryParameters, session);
+ // TODO: for sub-select fetching we have to try to assign the QueryParameter.ProcessedSQL here (with limits) but only after use IParameterSpecification for any kind of queries
+
+ // The PreprocessSQL method can modify the SqlString but should never add parameters (or we have to override it)
+ sqlString = PreprocessSQL(sqlString, queryParameters, session.Factory.Dialect);
+
+ // After the last modification to the SqlString we can collect all parameters types.
+ ResetEffectiveExpectedType(parameterSpecs, queryParameters); // <= TODO: remove this method when we can infer the type during the parse
+ var sqlQueryParametersList = sqlString.GetParameters().ToList();
+ SqlType[] parameterTypes = parameterSpecs.GetQueryParameterTypes(sqlQueryParametersList, session.Factory);
+
+ parameterSpecs.SetQueryParameterLocations(sqlQueryParametersList, session.Factory);
+
+ IDbCommand command = session.Batcher.PrepareQueryCommand(CommandType.Text, sqlString, parameterTypes);
+
+ try
+ {
+ RowSelection selection = queryParameters.RowSelection;
+ if (selection != null && selection.Timeout != RowSelection.NoValue)
+ {
+ command.CommandTimeout = selection.Timeout;
+ }
+
+ BindParametersValues(command, sqlQueryParametersList, parameterSpecs, queryParameters, session);
+
+ session.Batcher.ExpandQueryParameters(command, sqlString);
+ }
+ catch (HibernateException)
+ {
+ session.Batcher.CloseCommand(command, null);
+ throw;
+ }
+ catch (Exception sqle)
+ {
+ session.Batcher.CloseCommand(command, null);
+ ADOExceptionReporter.LogExceptions(sqle);
+ throw;
+ }
+ return command;
+ }
+
+ private void AdjustQueryParametersForSubSelectFetching(SqlString sqlString, IEnumerable<IParameterSpecification> parameterSpecs, ISessionImplementor session, QueryParameters queryParameters)
+ {
+ // TODO: Remove this when all parameters are managed using IParameterSpecification (QueryParameters does not need to have decomposed values for filters)
+
+ var dynamicFilterParameterSpecifications = parameterSpecs.OfType<DynamicFilterParameterSpecification>().ToList();
+ var filteredParameterValues = new List<object>();
+ var filteredParameterTypes = new List<IType>();
+ var filteredParameterLocations = new List<int>();
+
+ if (dynamicFilterParameterSpecifications.Count != 0)
+ {
+ var sqlQueryParametersList = sqlString.GetParameters().ToList();
+ foreach (DynamicFilterParameterSpecification specification in dynamicFilterParameterSpecifications)
+ {
+ string backTrackId = specification.GetIdsForBackTrack(session.Factory).First();
+ object value = session.GetFilterParameterValue(specification.FilterParameterFullName);
+ var elementType = specification.ExpectedType;
+ foreach (int position in sqlQueryParametersList.GetEffectiveParameterLocations(backTrackId))
+ {
+ filteredParameterValues.Add(value);
+ filteredParameterTypes.Add(elementType);
+ filteredParameterLocations.Add(position);
+ }
+ }
+ }
+
+ queryParameters.ProcessedSql = sqlString;
+ queryParameters.FilteredParameterLocations = filteredParameterLocations;
+ queryParameters.FilteredParameterTypes = filteredParameterTypes;
+ queryParameters.FilteredParameterValues = filteredParameterValues;
+ }
+
+ private SqlString ExpandDynamicFilterParameters(SqlString sqlString, ICollection<IParameterSpecification> parameterSpecs, ISessionImplementor session)
+ {
+ var enabledFilters = session.EnabledFilters;
+ if (enabledFilters.Count == 0 || sqlString.ToString().IndexOf(ParserHelper.HqlVariablePrefix) < 0)
+ {
+ return sqlString;
+ }
+
+ Dialect.Dialect dialect = session.Factory.Dialect;
+ string symbols = ParserHelper.HqlSeparators + dialect.OpenQuote + dialect.CloseQuote;
+
+ var originSql = sqlString.Compact();
+ var result = new SqlStringBuilder();
+ foreach (var sqlPart in originSql.Parts)
+ {
+ var parameter = sqlPart as Parameter;
+ if (parameter != null)
+ {
+ result.Add(parameter);
+ continue;
+ }
+
+ var sqlFragment = sqlPart.ToString();
+ var tokens = new StringTokenizer(sqlFragment, symbols, true);
+
+ foreach (string token in tokens)
+ {
+ if (token.StartsWith(ParserHelper.HqlVariablePrefix))
+ {
+ string filterParameterName = token.Substring(1);
+ string[] parts = StringHelper.ParseFilterParameterName(filterParameterName);
+ string filterName = parts[0];
+ string parameterName = parts[1];
+ var filter = (FilterImpl)enabledFilters[filterName];
+
+ object value = filter.GetParameter(parameterName);
+ IType type = filter.FilterDefinition.GetParameterType(parameterName);
+ int parameterColumnSpan = type.GetColumnSpan(session.Factory);
+ var collectionValue = value as ICollection;
+ int? collectionSpan = null;
+
+ // Add query chunk
+ string typeBindFragment = string.Join(", ", Enumerable.Repeat("?", parameterColumnSpan).ToArray());
+ string bindFragment;
+ if (collectionValue != null && !type.ReturnedClass.IsArray)
+ {
+ collectionSpan = collectionValue.Count;
+ bindFragment = string.Join(", ", Enumerable.Repeat(typeBindFragment, collectionValue.Count).ToArray());
+ }
+ else
+ {
+ bindFragment = typeBindFragment;
+ }
+
+ // dynamic-filter parameter tracking
+ var filterParameterFragment = SqlString.Parse(bindFragment);
+ var dynamicFilterParameterSpecification = new DynamicFilterParameterSpecification(filterName, parameterName, type, collectionSpan);
+ var parameters = filterParameterFragment.GetParameters().ToArray();
+ var sqlParameterPos = 0;
+ var paramTrackers = dynamicFilterParameterSpecification.GetIdsForBackTrack(session.Factory);
+ foreach (var paramTracker in paramTrackers)
+ {
+ parameters[sqlParameterPos++].BackTrack = paramTracker;
+ }
+
+ parameterSpecs.Add(dynamicFilterParameterSpecification);
+ result.Add(filterParameterFragment);
+ }
+ else
+ {
+ result.Add(token);
+ }
+ }
+ }
+ return result.ToSqlString().Compact();
+ }
+
+ private SqlString AddLimitsParametersIfNeeded(SqlString sqlString, ICollection<IParameterSpecification> parameterSpecs, QueryParameters queryParameters, ISessionImplementor session)
+ {
+ var sessionFactory = session.Factory;
+ Dialect.Dialect dialect = sessionFactory.Dialect;
+
+ RowSelection selection = queryParameters.RowSelection;
+ bool useLimit = UseLimit(selection, dialect);
+ if (useLimit)
+ {
+ bool hasFirstRow = GetFirstRow(selection) > 0;
+ bool useOffset = hasFirstRow && dialect.SupportsLimitOffset;
+ int max = GetMaxOrLimit(dialect, selection);
+ int? skip = useOffset ? (int?) dialect.GetOffsetValue(GetFirstRow(selection)) : null;
+ int? take = max != int.MaxValue ? (int?) max : null;
+
+ Parameter skipSqlParameter = null;
+ Parameter takeSqlParameter = null;
+ if (skip.HasValue)
+ {
+ var skipParameter = new QuerySkipParameterSpecification();
+ skipSqlParameter = Parameter.Placeholder;
+ skipSqlParameter.BackTrack = skipParameter.GetIdsForBackTrack(sessionFactory).First();
+ parameterSpecs.Add(skipParameter);
+ }
+ if (take.HasValue)
+ {
+ var takeParameter = new QueryTakeParameterSpecification();
+ takeSqlParameter = Parameter.Placeholder;
+ takeSqlParameter.BackTrack = takeParameter.GetIdsForBackTrack(sessionFactory).First();
+ parameterSpecs.Add(takeParameter);
+ }
+ // The dialect can move the given parameters where he need, what it can't do is generates new parameters loosing the BackTrack.
+ return dialect.GetLimitString(sqlString, skip, take, skipSqlParameter, takeSqlParameter);
+ }
+ return sqlString;
+ }
+
+ private void ResetEffectiveExpectedType(IEnumerable<IParameterSpecification> parameterSpecs, QueryParameters queryParameters)
+ {
+ foreach (var parameterSpecification in parameterSpecs.OfType<IExplicitParameterSpecification>())
+ {
+ parameterSpecification.SetEffectiveType(queryParameters);
+ }
+ }
+
+ /// <summary>
+ /// Bind all parameters values.
+ /// </summary>
+ /// <param name="command">The command where bind each value.</param>
+ /// <param name="sqlQueryParametersList">The list of Sql query parameter in the exact sequence they are present in the query.</param>
+ /// <param name="parameterSpecs">All parameter-specifications collected during query construction.</param>
+ /// <param name="queryParameters">The encapsulation of the parameter values to be bound.</param>
+ /// <param name="session">The session from where execute the query.</param>
+ private void BindParametersValues(IDbCommand command, IList<Parameter> sqlQueryParametersList, IEnumerable<IParameterSpecification> parameterSpecs, QueryParameters queryParameters, ISessionImplementor session)
+ {
+ foreach (var parameterSpecification in parameterSpecs)
+ {
+ parameterSpecification.Bind(command, sqlQueryParametersList, queryParameters, session);
+ }
+ }
}
}
\ No newline at end of file
Modified: trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/SqlGenerator.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/SqlGenerator.cs 2011-05-29 18:36:56 UTC (rev 5880)
+++ trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/SqlGenerator.cs 2011-05-30 13:58:24 UTC (rev 5881)
@@ -1,6 +1,7 @@
using System;
using System.Collections;
using System.Collections.Generic;
+using System.Linq;
using Antlr.Runtime;
using Antlr.Runtime.Tree;
using NHibernate.Dialect.Function;
@@ -92,11 +93,6 @@
writer.Clause(s);
}
- private void ParameterOut()
- {
- writer.Parameter();
- }
-
/// <summary>
/// Add a aspace if the previous token was not a space or a parenthesis.
/// </summary>
@@ -129,11 +125,12 @@
private void Out(IASTNode n)
{
- var parameterNode= n as ParameterNode;
+ var parameterNode = n as ParameterNode;
if (parameterNode != null)
{
var parameter = Parameter.Placeholder;
- parameter.BackTrack = parameterNode.HqlParameterSpecification.IdForBackTrack;
+ // supposed to be simplevalue
+ parameter.BackTrack = parameterNode.HqlParameterSpecification.GetIdsForBackTrack(sessionFactory).Single();
writer.PushParameter(parameter);
}
else if (n is SqlNode)
@@ -151,13 +148,11 @@
}
els...
[truncated message content] |
|
From: <fab...@us...> - 2011-05-30 16:12:03
|
Revision: 5884
http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5884&view=rev
Author: fabiomaulo
Date: 2011-05-30 16:11:57 +0000 (Mon, 30 May 2011)
Log Message:
-----------
Fix NH-2738
Modified Paths:
--------------
trunk/nhibernate/src/NHibernate/Type/TypeFactory.cs
trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj
Added Paths:
-----------
trunk/nhibernate/src/NHibernate.Test/MappingByCode/IntegrationTests/NH2738/
trunk/nhibernate/src/NHibernate.Test/MappingByCode/IntegrationTests/NH2738/Fixture.cs
Modified: trunk/nhibernate/src/NHibernate/Type/TypeFactory.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Type/TypeFactory.cs 2011-05-30 15:31:30 UTC (rev 5883)
+++ trunk/nhibernate/src/NHibernate/Type/TypeFactory.cs 2011-05-30 16:11:57 UTC (rev 5884)
@@ -517,11 +517,25 @@
}
else if (typeClass.IsEnum)
{
- type = (IType) Activator.CreateInstance(typeof (EnumType<>).MakeGenericType(typeClass));
+ try
+ {
+ type = (IType)Activator.CreateInstance(typeof(EnumType<>).MakeGenericType(typeClass));
+ }
+ catch (Exception e)
+ {
+ throw new MappingException("Can't instantiate enum "+ typeClass.FullName +"; The enum can't be empty", e);
+ }
}
else if (IsNullableEnum(typeClass))
{
- type = (IType)Activator.CreateInstance(typeof(EnumType<>).MakeGenericType(typeClass.GetGenericArguments()[0]));
+ try
+ {
+ type = (IType)Activator.CreateInstance(typeof(EnumType<>).MakeGenericType(typeClass.GetGenericArguments()[0]));
+ }
+ catch (Exception e)
+ {
+ throw new MappingException("Can't instantiate enum " + typeClass.FullName + "; The enum can't be empty", e);
+ }
}
else if (typeClass.IsSerializable)
{
Added: trunk/nhibernate/src/NHibernate.Test/MappingByCode/IntegrationTests/NH2738/Fixture.cs
===================================================================
--- trunk/nhibernate/src/NHibernate.Test/MappingByCode/IntegrationTests/NH2738/Fixture.cs (rev 0)
+++ trunk/nhibernate/src/NHibernate.Test/MappingByCode/IntegrationTests/NH2738/Fixture.cs 2011-05-30 16:11:57 UTC (rev 5884)
@@ -0,0 +1,35 @@
+using NHibernate.Mapping.ByCode;
+using NUnit.Framework;
+using SharpTestsEx;
+
+namespace NHibernate.Test.MappingByCode.IntegrationTests.NH2738
+{
+ public enum MyEmptyEnum
+ {
+
+ }
+
+ public class MyClass
+ {
+ public virtual int Id { get; set; }
+ public MyEmptyEnum MyEmptyEnum { get; set; }
+ }
+ public class Fixture
+ {
+ [Test]
+ public void WhenMapEmptyEnumThenThrowsExplicitException()
+ {
+ var mapper = new ModelMapper();
+ mapper.Class<MyClass>(rc =>
+ {
+ rc.Id(x => x.Id);
+ rc.Property(x => x.MyEmptyEnum);
+ });
+ var mappings = mapper.CompileMappingForAllExplicitAddedEntities();
+ var conf = TestConfigurationHelper.GetDefaultConfiguration();
+ conf.AddMapping(mappings);
+
+ conf.Executing(c => c.BuildSessionFactory()).Throws<MappingException>().And.ValueOf.Message.Should().Contain("MyEmptyEnum");
+ }
+ }
+}
\ No newline at end of file
Modified: trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj
===================================================================
--- trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2011-05-30 15:31:30 UTC (rev 5883)
+++ trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2011-05-30 16:11:57 UTC (rev 5884)
@@ -557,6 +557,7 @@
<Compile Include="MappingByCode\IntegrationTests\NH2728\IAnimal.cs" />
<Compile Include="MappingByCode\IntegrationTests\NH2728\SampleTest.cs" />
<Compile Include="MappingByCode\IntegrationTests\NH2728\Toy.cs" />
+ <Compile Include="MappingByCode\IntegrationTests\NH2738\Fixture.cs" />
<Compile Include="MappingByCode\MappersTests\AnyMapperTest.cs" />
<Compile Include="MappingByCode\MappersTests\IdMapperTest.cs" />
<Compile Include="MappingByCode\MappersTests\ManyToOneMapperTest.cs" />
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <fab...@us...> - 2011-05-30 16:50:36
|
Revision: 5887
http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5887&view=rev
Author: fabiomaulo
Date: 2011-05-30 16:50:30 +0000 (Mon, 30 May 2011)
Log Message:
-----------
Fix NH-2328, NH-2741 (thanks to Andrei Alecu, patch applied with modifications)
Modified Paths:
--------------
trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Tree/BinaryLogicOperatorNode.cs
trunk/nhibernate/src/NHibernate/Type/MetaType.cs
trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2328/Fixture.cs
Modified: trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Tree/BinaryLogicOperatorNode.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Tree/BinaryLogicOperatorNode.cs 2011-05-30 16:33:17 UTC (rev 5886)
+++ trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Tree/BinaryLogicOperatorNode.cs 2011-05-30 16:50:30 UTC (rev 5887)
@@ -6,6 +6,7 @@
using NHibernate.Param;
using NHibernate.SqlCommand;
using NHibernate.Type;
+using NHibernate.Util;
namespace NHibernate.Hql.Ast.ANTLR.Tree
{
@@ -50,7 +51,7 @@
{
throw new SemanticException( "right-hand operand of a binary operator was null" );
}
-
+ ProcessMetaTypeDiscriminatorIfNecessary(lhs, rhs);
IType lhsType = ExtractDataType( lhs );
IType rhsType = ExtractDataType( rhs );
@@ -265,5 +266,40 @@
return type;
}
+
+ private void ProcessMetaTypeDiscriminatorIfNecessary(IASTNode lhs, IASTNode rhs)
+ {
+ // this method inserts the discriminator value for the rhs node so that .class queries on <any> mappings work with the class name
+ var lhsNode = lhs as SqlNode;
+ var rhsNode = rhs as SqlNode;
+ if (lhsNode == null || rhsNode == null)
+ {
+ return;
+ }
+ if (rhsNode.Text == null)
+ {
+ var lhsNodeMetaType = lhsNode.DataType as MetaType;
+ if (lhsNodeMetaType != null)
+ {
+ string className = SessionFactoryHelper.GetImportedClassName(rhsNode.OriginalText);
+
+ object discriminatorValue = lhsNodeMetaType.GetMetaValue(TypeNameParser.Parse(className).Type);
+ rhsNode.Text = discriminatorValue.ToString();
+ return;
+ }
+ }
+ if (lhsNode.Text == null)
+ {
+ var rhsNodeMetaType = rhsNode.DataType as MetaType;
+ if (rhsNodeMetaType != null)
+ {
+ string className = SessionFactoryHelper.GetImportedClassName(lhsNode.OriginalText);
+
+ object discriminatorValue = rhsNodeMetaType.GetMetaValue(TypeNameParser.Parse(className).Type);
+ lhsNode.Text = discriminatorValue.ToString();
+ return;
+ }
+ }
+ }
}
}
Modified: trunk/nhibernate/src/NHibernate/Type/MetaType.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Type/MetaType.cs 2011-05-30 16:33:17 UTC (rev 5886)
+++ trunk/nhibernate/src/NHibernate/Type/MetaType.cs 2011-05-30 16:50:30 UTC (rev 5887)
@@ -117,5 +117,9 @@
return (string)value; //value is the entity name
}
+ internal object GetMetaValue(string className)
+ {
+ return keys[className];
+ }
}
}
\ No newline at end of file
Modified: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2328/Fixture.cs
===================================================================
--- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2328/Fixture.cs 2011-05-30 16:33:17 UTC (rev 5886)
+++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2328/Fixture.cs 2011-05-30 16:50:30 UTC (rev 5887)
@@ -56,7 +56,6 @@
}
[Test]
- [Ignore("VisitTypeBinaryExpression generates HQL tree with string constant, but DB has a number")]
public void AnyIs_Linq()
{
using (ISession s = OpenSession())
@@ -72,18 +71,31 @@
}
[Test]
- [Description("Is this right? - the HQL translation should turn the class-string to an int, not the user?")]
- public void AnyIs_HqlRequiresNumberIn()
+ public void AnyIs_HqlWorksWithClassNameInTheRight()
{
using (ISession s = OpenSession())
{
var boxes =
- s.CreateQuery("from ToyBox t where t.Shape.class = 2")
+ s.CreateQuery("from ToyBox t where t.Shape.class = Square")
.List<ToyBox>();
Assert.That(boxes.Count, Is.EqualTo(1));
Assert.That(boxes[0].Name, Is.EqualTo("Box2"));
}
}
+
+ [Test]
+ public void AnyIs_HqlWorksWithClassNameInTheLeft()
+ {
+ using (ISession s = OpenSession())
+ {
+ var boxes =
+ s.CreateQuery("from ToyBox t where Square = t.Shape.class")
+ .List<ToyBox>();
+
+ Assert.That(boxes.Count, Is.EqualTo(1));
+ Assert.That(boxes[0].Name, Is.EqualTo("Box2"));
+ }
+ }
}
}
\ No newline at end of file
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <fab...@us...> - 2011-05-30 17:31:45
|
Revision: 5888
http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5888&view=rev
Author: fabiomaulo
Date: 2011-05-30 17:31:39 +0000 (Mon, 30 May 2011)
Log Message:
-----------
Fixed NH-2318 for HQL and LINQ
Modified Paths:
--------------
trunk/nhibernate/src/NHibernate/Dialect/Function/AnsiTrimEmulationFunction.cs
trunk/nhibernate/src/NHibernate/Param/PositionalParameterSpecification.cs
trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2318/Fixture.cs
Modified: trunk/nhibernate/src/NHibernate/Dialect/Function/AnsiTrimEmulationFunction.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Dialect/Function/AnsiTrimEmulationFunction.cs 2011-05-30 16:50:30 UTC (rev 5887)
+++ trunk/nhibernate/src/NHibernate/Dialect/Function/AnsiTrimEmulationFunction.cs 2011-05-30 17:31:39 UTC (rev 5888)
@@ -111,7 +111,7 @@
// are present and "do the right thing"
bool leading = true; // should leading trim-characters be trimmed?
bool trailing = true; // should trailing trim-characters be trimmed?
- string trimCharacter = null; // the trim-character
+ object trimCharacter = null; // the trim-character
object trimSource = null; // the trim-source
// potentialTrimCharacterArgIndex = 1 assumes that a
@@ -147,7 +147,7 @@
}
else
{
- trimCharacter = potentialTrimCharacter.ToString();
+ trimCharacter = potentialTrimCharacter;
if (StringHelper.EqualsCaseInsensitive("from", args[potentialTrimCharacterArgIndex + 1].ToString()))
{
trimSource = args[potentialTrimCharacterArgIndex + 2];
@@ -158,9 +158,7 @@
}
}
- IList argsToUse = new List<object>();
- argsToUse.Add(trimSource);
- argsToUse.Add(trimCharacter);
+ IList argsToUse = new List<object> {trimSource, trimCharacter};
if (trimCharacter.Equals("' '"))
{
Modified: trunk/nhibernate/src/NHibernate/Param/PositionalParameterSpecification.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Param/PositionalParameterSpecification.cs 2011-05-30 16:50:30 UTC (rev 5887)
+++ trunk/nhibernate/src/NHibernate/Param/PositionalParameterSpecification.cs 2011-05-30 17:31:39 UTC (rev 5888)
@@ -56,8 +56,11 @@
object value = queryParameters.PositionalParameterValues[hqlPosition];
string backTrackId = GetIdsForBackTrack(session.Factory).First(); // just the first because IType suppose the oders in certain sequence
- int position = sqlQueryParametersList.GetEffectiveParameterLocations(backTrackId).Single(); // an HQL positional parameter can't appear more than once
- type.NullSafeSet(command, value, position, session);
+ // an HQL positional parameter can appear more than once because a custom HQL-Function can duplicate it
+ foreach (int position in sqlQueryParametersList.GetEffectiveParameterLocations(backTrackId))
+ {
+ type.NullSafeSet(command, value, position, session);
+ }
}
public override void SetEffectiveType(QueryParameters queryParameters)
Modified: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2318/Fixture.cs
===================================================================
--- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2318/Fixture.cs 2011-05-30 16:50:30 UTC (rev 5887)
+++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2318/Fixture.cs 2011-05-30 17:31:39 UTC (rev 5888)
@@ -70,7 +70,6 @@
}
[Test]
- [Ignore]
public void LinqTrimFunctionsWithParameters()
{
AddObjects();
@@ -94,7 +93,6 @@
}
[Test]
- [Ignore]
public void HqlTrimFunctionsWithParameters()
{
AddObjects();
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <fab...@us...> - 2011-05-30 18:24:36
|
Revision: 5889
http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5889&view=rev
Author: fabiomaulo
Date: 2011-05-30 18:24:30 +0000 (Mon, 30 May 2011)
Log Message:
-----------
Fix NH-2703 thanks to Roy Jacobs
Modified Paths:
--------------
trunk/nhibernate/src/NHibernate/Loader/JoinWalker.cs
trunk/nhibernate/src/NHibernate/Loader/OuterJoinableAssociation.cs
trunk/nhibernate/src/NHibernate/NHibernate.csproj
trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj
Added Paths:
-----------
trunk/nhibernate/src/NHibernate/Loader/TopologicalSorter.cs
trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2703/
trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2703/Fixture.cs
trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2703/Mappings.hbm.xml
trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2703/Model.cs
Modified: trunk/nhibernate/src/NHibernate/Loader/JoinWalker.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Loader/JoinWalker.cs 2011-05-30 17:31:39 UTC (rev 5888)
+++ trunk/nhibernate/src/NHibernate/Loader/JoinWalker.cs 2011-05-30 18:24:30 UTC (rev 5889)
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Text.RegularExpressions;
using Iesi.Collections.Generic;
using NHibernate.Collection;
using NHibernate.Engine;
@@ -18,6 +19,7 @@
private readonly ISet<AssociationKey> visitedAssociationKeys = new HashedSet<AssociationKey>();
private readonly IDictionary<string, IFilter> enabledFilters;
private readonly IDictionary<string, IFilter> enabledFiltersForManyToOne;
+ private readonly Regex aliasRegex = new Regex(@"([\w]+)\.", RegexOptions.IgnoreCase | RegexOptions.Compiled);
private string[] suffixes;
private string[] collectionSuffixes;
@@ -110,6 +112,14 @@
get { return false; }
}
+ public class DependentAlias
+ {
+ public string Alias { get; set; }
+ public string[] DependsOn { get; set; }
+ }
+
+ readonly List<DependentAlias> _dependentAliases = new List<DependentAlias>();
+
protected JoinWalker(ISessionFactoryImplementor factory, IDictionary<string, IFilter> enabledFilters)
{
this.factory = factory;
@@ -149,7 +159,7 @@
OuterJoinableAssociation assoc =
new OuterJoinableAssociation(type, alias, aliasedLhsColumns, subalias, joinType, GetWithClause(path), Factory, enabledFilters);
assoc.ValidateJoin(path);
- associations.Add(assoc);
+ AddAssociation(subalias, assoc);
int nextDepth = currentDepth + 1;
@@ -167,7 +177,65 @@
}
}
+ private static int[] GetTopologicalSortOrder(List<DependentAlias> fields)
+ {
+ TopologicalSorter g = new TopologicalSorter(fields.Count);
+ Dictionary<string, int> _indexes = new Dictionary<string, int>();
+
+ // add vertices
+ for (int i = 0; i < fields.Count; i++)
+ {
+ _indexes[fields[i].Alias.ToLower()] = g.AddVertex(i);
+ }
+
+ // add edges
+ for (int i = 0; i < fields.Count; i++)
+ {
+ if (fields[i].DependsOn != null)
+ {
+ for (int j = 0; j < fields[i].DependsOn.Length; j++)
+ {
+ var dependentField = fields[i].DependsOn[j].ToLower();
+ if (_indexes.ContainsKey(dependentField))
+ {
+ g.AddEdge(i, _indexes[dependentField]);
+ }
+ }
+ }
+ }
+
+ return g.Sort();
+ }
+
/// <summary>
+ /// Adds an association and extracts the aliases the association's 'with clause' is dependent on
+ /// </summary>
+ private void AddAssociation(string subalias, OuterJoinableAssociation association)
+ {
+ subalias = subalias.ToLower();
+
+ var dependencies = new List<string>();
+ var on = association.On.ToString();
+ if (!String.IsNullOrEmpty(on))
+ {
+ foreach (Match match in aliasRegex.Matches(on))
+ {
+ string alias = match.Groups[1].Value;
+ if (alias == subalias) continue;
+ dependencies.Add(alias.ToLower());
+ }
+ }
+
+ _dependentAliases.Add(new DependentAlias
+ {
+ Alias = subalias,
+ DependsOn = dependencies.ToArray()
+ });
+
+ associations.Add(association);
+ }
+
+ /// <summary>
/// For an entity class, return a list of associations to be fetched by outerjoin
/// </summary>
protected void WalkEntityTree(IOuterJoinLoadable persister, string alias)
@@ -559,10 +627,18 @@
/// </summary>
protected JoinFragment MergeOuterJoins(IList<OuterJoinableAssociation> associations)
{
+ IList<OuterJoinableAssociation> sortedAssociations = new List<OuterJoinableAssociation>();
+
+ var indices = GetTopologicalSortOrder(_dependentAliases);
+ for (int index = indices.Length - 1; index >= 0; index--)
+ {
+ sortedAssociations.Add(associations[indices[index]]);
+ }
+
JoinFragment outerjoin = Dialect.CreateOuterJoinFragment();
OuterJoinableAssociation last = null;
- foreach (OuterJoinableAssociation oj in associations)
+ foreach (OuterJoinableAssociation oj in sortedAssociations)
{
if (last != null && last.IsManyToManyWith(oj))
{
Modified: trunk/nhibernate/src/NHibernate/Loader/OuterJoinableAssociation.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Loader/OuterJoinableAssociation.cs 2011-05-30 17:31:39 UTC (rev 5888)
+++ trunk/nhibernate/src/NHibernate/Loader/OuterJoinableAssociation.cs 2011-05-30 18:24:30 UTC (rev 5889)
@@ -48,6 +48,11 @@
get { return rhsAlias; }
}
+ public SqlString On
+ {
+ get { return on; }
+ }
+
private bool IsOneToOne
{
get
Added: trunk/nhibernate/src/NHibernate/Loader/TopologicalSorter.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Loader/TopologicalSorter.cs (rev 0)
+++ trunk/nhibernate/src/NHibernate/Loader/TopologicalSorter.cs 2011-05-30 18:24:30 UTC (rev 5889)
@@ -0,0 +1,122 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+// Algorithm from: http://tawani.blogspot.com/2009/02/topological-sorting-and-cyclic.html
+namespace NHibernate.Loader
+{
+ class TopologicalSorter
+ {
+ #region - Private Members -
+
+ private readonly int[] _vertices; // list of vertices
+ private readonly int[,] _matrix; // adjacency matrix
+ private int _numVerts; // current number of vertices
+ private readonly int[] _sortedArray;
+
+ #endregion
+
+ #region - CTors -
+
+ public TopologicalSorter(int size)
+ {
+ _vertices = new int[size];
+ _matrix = new int[size, size];
+ _numVerts = 0;
+ for (int i = 0; i < size; i++)
+ for (int j = 0; j < size; j++)
+ _matrix[i, j] = 0;
+ _sortedArray = new int[size]; // sorted vert labels
+ }
+
+ #endregion
+
+ #region - Public Methods -
+
+ public int AddVertex(int vertex)
+ {
+ _vertices[_numVerts++] = vertex;
+ return _numVerts - 1;
+ }
+
+ public void AddEdge(int start, int end)
+ {
+ _matrix[start, end] = 1;
+ }
+
+ public int[] Sort() // toplogical sort
+ {
+ while (_numVerts > 0) // while vertices remain,
+ {
+ // get a vertex with no successors, or -1
+ int currentVertex = noSuccessors();
+ if (currentVertex == -1) // must be a cycle
+ throw new Exception("Graph has cycles");
+
+ // insert vertex label in sorted array (start at end)
+ _sortedArray[_numVerts - 1] = _vertices[currentVertex];
+
+ deleteVertex(currentVertex); // delete vertex
+ }
+
+ // vertices all gone; return sortedArray
+ return _sortedArray;
+ }
+
+ #endregion
+
+ #region - Private Helper Methods -
+
+ // returns vert with no successors (or -1 if no such verts)
+ private int noSuccessors()
+ {
+ for (int row = 0; row < _numVerts; row++)
+ {
+ bool isEdge = false; // edge from row to column in adjMat
+ for (int col = 0; col < _numVerts; col++)
+ {
+ if (_matrix[row, col] > 0) // if edge to another,
+ {
+ isEdge = true;
+ break; // this vertex has a successor try another
+ }
+ }
+ if (!isEdge) // if no edges, has no successors
+ return row;
+ }
+ return -1; // no
+ }
+
+ private void deleteVertex(int delVert)
+ {
+ // if not last vertex, delete from vertexList
+ if (delVert != _numVerts - 1)
+ {
+ for (int j = delVert; j < _numVerts - 1; j++)
+ _vertices[j] = _vertices[j + 1];
+
+ for (int row = delVert; row < _numVerts - 1; row++)
+ moveRowUp(row, _numVerts);
+
+ for (int col = delVert; col < _numVerts - 1; col++)
+ moveColLeft(col, _numVerts - 1);
+ }
+ _numVerts--; // one less vertex
+ }
+
+ private void moveRowUp(int row, int length)
+ {
+ for (int col = 0; col < length; col++)
+ _matrix[row, col] = _matrix[row + 1, col];
+ }
+
+ private void moveColLeft(int col, int length)
+ {
+ for (int row = 0; row < length; row++)
+ _matrix[row, col] = _matrix[row, col + 1];
+ }
+
+ #endregion
+ }
+}
Modified: trunk/nhibernate/src/NHibernate/NHibernate.csproj
===================================================================
--- trunk/nhibernate/src/NHibernate/NHibernate.csproj 2011-05-30 17:31:39 UTC (rev 5888)
+++ trunk/nhibernate/src/NHibernate/NHibernate.csproj 2011-05-30 18:24:30 UTC (rev 5889)
@@ -281,6 +281,7 @@
<Compile Include="Linq\Visitors\ResultOperatorProcessors\ProcessAggregateFromSeed.cs" />
<Compile Include="Linq\Visitors\SelectAndOrderByJoinDetector.cs" />
<Compile Include="Linq\Visitors\WhereJoinDetector.cs" />
+ <Compile Include="Loader\TopologicalSorter.cs" />
<Compile Include="Loader\Loader.cs" />
<Compile Include="Loader\OuterJoinLoader.cs" />
<Compile Include="LockMode.cs" />
Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2703/Fixture.cs
===================================================================
--- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2703/Fixture.cs (rev 0)
+++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2703/Fixture.cs 2011-05-30 18:24:30 UTC (rev 5889)
@@ -0,0 +1,76 @@
+using NUnit.Framework;
+
+namespace NHibernate.Test.NHSpecificTest.NH2703
+{
+ [TestFixture]
+ public class Fixture : BugTestCase
+ {
+ Parent RootElement = null;
+
+ protected override void OnSetUp()
+ {
+ using (ISession session = Sfi.OpenSession())
+ {
+ var parent = new Parent();
+ parent.A.Add(new A() { PropA = "Child" });
+ parent.B.Add(new B() { PropB = "Child" });
+ parent.C.Add(new C() { PropC = "Child" });
+ session.Persist(parent);
+ session.Flush();
+ }
+ }
+
+ protected override void OnTearDown()
+ {
+ using (ISession session = Sfi.OpenSession())
+ {
+ session.CreateQuery("delete from A").ExecuteUpdate();
+ session.CreateQuery("delete from B").ExecuteUpdate();
+ session.CreateQuery("delete from C").ExecuteUpdate();
+ session.CreateQuery("delete from Parent").ExecuteUpdate();
+ session.Flush();
+ }
+ base.OnTearDown();
+ }
+
+ [Test]
+ public void CanOuterJoinMultipleTablesWithSimpleWithClause()
+ {
+ using (ISession session = Sfi.OpenSession())
+ {
+ IQueryOver<Parent, Parent> query = session.QueryOver(() => RootElement);
+
+ A A_Alias = null;
+ B B_Alias = null;
+ C C_Alias = null;
+ query.Left.JoinQueryOver(parent => parent.C, () => C_Alias, c => c.PropC == A_Alias.PropA);
+ query.Left.JoinQueryOver(parent => parent.A, () => A_Alias);
+ query.Left.JoinQueryOver(parent => parent.B, () => B_Alias, b => b.PropB == C_Alias.PropC);
+ // Expected join order: a --> c --> b
+
+ // This query should not throw
+ query.List();
+ }
+ }
+
+ [Test]
+ public void CanOuterJoinMultipleTablesWithComplexWithClause()
+ {
+ using (ISession session = Sfi.OpenSession())
+ {
+ IQueryOver<Parent, Parent> query = session.QueryOver(() => RootElement);
+
+ A A_Alias = null;
+ B B_Alias = null;
+ C C_Alias = null;
+ query.Left.JoinQueryOver(parent => parent.C, () => C_Alias, c => c.PropC == A_Alias.PropA && c.PropC == B_Alias.PropB);
+ query.Left.JoinQueryOver(parent => parent.A, () => A_Alias);
+ query.Left.JoinQueryOver(parent => parent.B, () => B_Alias, b => b.PropB == A_Alias.PropA);
+ // Expected join order: a --> b --> c
+
+ // This query should not throw
+ query.List();
+ }
+ }
+ }
+}
Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2703/Mappings.hbm.xml
===================================================================
--- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2703/Mappings.hbm.xml (rev 0)
+++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2703/Mappings.hbm.xml 2011-05-30 18:24:30 UTC (rev 5889)
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
+ namespace="NHibernate.Test.NHSpecificTest.NH2703"
+ assembly="NHibernate.Test">
+
+ <class name="Parent" table="`Parent_Table`">
+ <id name="Id">
+ <generator class="native"/>
+ </id>
+ <list name="A" cascade="all">
+ <key column="parent_id" />
+ <index column="a_index" />
+ <one-to-many class="A" />
+ </list>
+ <list name="B" cascade="all">
+ <key column="parent_id" />
+ <index column="b_index" />
+ <one-to-many class="B" />
+ </list>
+ <list name="C" cascade="all">
+ <key column="parent_id" />
+ <index column="c_index" />
+ <one-to-many class="C" />
+ </list>
+ </class>
+
+ <class name="A" table="`A_Table`">
+ <id name="Id">
+ <generator class="native"/>
+ </id>
+ <property name="PropA" type="String(15)"/>
+ </class>
+
+ <class name="B" table="`B_Table`">
+ <id name="Id">
+ <generator class="native"/>
+ </id>
+ <property name="PropB" type="String(15)"/>
+ </class>
+
+ <class name="C" table="`C_Table`">
+ <id name="Id">
+ <generator class="native"/>
+ </id>
+ <property name="PropC" type="String(15)"/>
+ </class>
+</hibernate-mapping>
Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2703/Model.cs
===================================================================
--- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2703/Model.cs (rev 0)
+++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2703/Model.cs 2011-05-30 18:24:30 UTC (rev 5889)
@@ -0,0 +1,75 @@
+using System.Collections.Generic;
+
+namespace NHibernate.Test.NHSpecificTest.NH2703
+{
+ public class Parent
+ {
+ private IList<A> a = new List<A>();
+ private IList<B> b = new List<B>();
+ private IList<C> c = new List<C>();
+ private int id;
+
+ public virtual IList<A> A
+ {
+ get { return a; }
+ set { a = value; }
+ }
+
+ public virtual IList<B> B
+ {
+ get { return b; }
+ set { b = value; }
+ }
+
+ public virtual IList<C> C
+ {
+ get { return c; }
+ set { c = value; }
+ }
+
+ public virtual int Id
+ {
+ get { return id; }
+ set { id = value; }
+ }
+ }
+
+ public class A
+ {
+ private int id;
+
+ public virtual int Id
+ {
+ get { return id; }
+ set { id = value; }
+ }
+
+ public virtual string PropA { get; set; }
+ }
+
+ public class B
+ {
+ private int id;
+
+ public virtual int Id
+ {
+ get { return id; }
+ set { id = value; }
+ }
+
+ public virtual string PropB { get; set; }
+ }
+
+ public class C
+ {
+ private int id;
+
+ public virtual int Id
+ {
+ get { return id; }
+ set { id = value; }
+ }
+
+ public virtual string PropC { get; set; }
+ }
+}
Modified: trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj
===================================================================
--- trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2011-05-30 17:31:39 UTC (rev 5888)
+++ trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2011-05-30 18:24:30 UTC (rev 5889)
@@ -854,6 +854,8 @@
<Compile Include="NHSpecificTest\NH2697\ArticleGroupItem.cs" />
<Compile Include="NHSpecificTest\NH2697\ArticleItem.cs" />
<Compile Include="NHSpecificTest\NH2697\SampleTest.cs" />
+ <Compile Include="NHSpecificTest\NH2703\Fixture.cs" />
+ <Compile Include="NHSpecificTest\NH2703\Model.cs" />
<Compile Include="NHSpecificTest\NH2705\ItemBase.cs" />
<Compile Include="NHSpecificTest\NH2705\SubItemBase.cs" />
<Compile Include="NHSpecificTest\NH2705\SubItemDetails.cs" />
@@ -2707,6 +2709,7 @@
<EmbeddedResource Include="NHSpecificTest\NH1291AnonExample\Mappings.hbm.xml" />
</ItemGroup>
<ItemGroup>
+ <EmbeddedResource Include="NHSpecificTest\NH2703\Mappings.hbm.xml" />
<EmbeddedResource Include="NHSpecificTest\NH2736\Mappings.hbm.xml" />
<EmbeddedResource Include="NHSpecificTest\NH2721\Mappings.hbm.xml" />
<EmbeddedResource Include="NHSpecificTest\NH2733\Mappings.hbm.xml" />
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <fab...@us...> - 2011-05-30 19:32:29
|
Revision: 5892
http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5892&view=rev
Author: fabiomaulo
Date: 2011-05-30 19:32:23 +0000 (Mon, 30 May 2011)
Log Message:
-----------
Fix NH-2070 as possible
Modified Paths:
--------------
trunk/nhibernate/src/NHibernate/Engine/CascadingAction.cs
trunk/nhibernate/src/NHibernate/Engine/ForeignKeys.cs
trunk/nhibernate/src/NHibernate/Impl/SessionImpl.cs
Modified: trunk/nhibernate/src/NHibernate/Engine/CascadingAction.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Engine/CascadingAction.cs 2011-05-30 19:14:52 UTC (rev 5891)
+++ trunk/nhibernate/src/NHibernate/Engine/CascadingAction.cs 2011-05-30 19:32:23 UTC (rev 5892)
@@ -377,7 +377,7 @@
string propertyName = persister.PropertyNames[propertyIndex];
throw new TransientObjectException(
string.Format(
- "object references an unsaved transient instance - save the transient instance before flushing: {0}.{1} -> {2}",
+ "object references an unsaved transient instance - save the transient instance before flushing or set cascade action for the property to something that would make it autosave: {0}.{1} -> {2}",
parentEntiytName, propertyName, childEntityName));
}
}
Modified: trunk/nhibernate/src/NHibernate/Engine/ForeignKeys.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Engine/ForeignKeys.cs 2011-05-30 19:14:52 UTC (rev 5891)
+++ trunk/nhibernate/src/NHibernate/Engine/ForeignKeys.cs 2011-05-30 19:32:23 UTC (rev 5892)
@@ -262,7 +262,8 @@
entityName = entityName ?? session.GuessEntityName(entity);
string entityString = entity.ToString();
throw new TransientObjectException(
- string.Format("object references an unsaved transient instance - save the transient instance before flushing. Type: {0}, Entity: {1}", entityName, entityString));
+ string.Format("object references an unsaved transient instance - save the transient instance before flushing or set cascade action for the property to something that would make it autosave. Type: {0}, Entity: {1}", entityName, entityString));
+
}
id = session.GetEntityPersister(entityName, entity).GetIdentifier(entity, session.EntityMode);
}
Modified: trunk/nhibernate/src/NHibernate/Impl/SessionImpl.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Impl/SessionImpl.cs 2011-05-30 19:14:52 UTC (rev 5891)
+++ trunk/nhibernate/src/NHibernate/Impl/SessionImpl.cs 2011-05-30 19:32:23 UTC (rev 5892)
@@ -1318,7 +1318,7 @@
if (entry == null)
{
throw new TransientObjectException(
- "object references an unsaved transient instance - save the transient instance before flushing: "
+ "object references an unsaved transient instance - save the transient instance before flushing or set cascade action for the property to something that would make it autosave: "
+ obj.GetType().FullName);
}
return entry.Persister.EntityName;
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <fab...@us...> - 2011-05-30 22:28:10
|
Revision: 5893
http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5893&view=rev
Author: fabiomaulo
Date: 2011-05-30 22:28:04 +0000 (Mon, 30 May 2011)
Log Message:
-----------
Support Unique and NotNullable for IKeyMapper
Modified Paths:
--------------
trunk/nhibernate/src/NHibernate/Mapping/ByCode/IKeyMapper.cs
trunk/nhibernate/src/NHibernate/Mapping/ByCode/Impl/CustomizersImpl/CollectionKeyCustomizer.cs
trunk/nhibernate/src/NHibernate/Mapping/ByCode/Impl/CustomizersImpl/JoinKeyCustomizer.cs
trunk/nhibernate/src/NHibernate/Mapping/ByCode/Impl/CustomizersImpl/JoinedSubclassKeyCustomizer.cs
trunk/nhibernate/src/NHibernate/Mapping/ByCode/Impl/KeyMapper.cs
Added Paths:
-----------
trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH941/
trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH941/Fixture.cs
Modified: trunk/nhibernate/src/NHibernate/Mapping/ByCode/IKeyMapper.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Mapping/ByCode/IKeyMapper.cs 2011-05-30 19:32:23 UTC (rev 5892)
+++ trunk/nhibernate/src/NHibernate/Mapping/ByCode/IKeyMapper.cs 2011-05-30 22:28:04 UTC (rev 5893)
@@ -15,6 +15,8 @@
void OnDelete(OnDeleteAction deleteAction);
void PropertyRef(MemberInfo property);
void Update(bool consideredInUpdateQuery);
+ void NotNullable(bool notnull);
+ void Unique(bool unique);
/// <summary>
/// Set the Foreing-Key name
@@ -33,5 +35,7 @@
void PropertyRef<TProperty>(Expression<Func<TEntity, TProperty>> propertyGetter);
void Update(bool consideredInUpdateQuery);
void ForeignKey(string foreingKeyName);
+ void NotNullable(bool notnull);
+ void Unique(bool unique);
}
}
\ No newline at end of file
Modified: trunk/nhibernate/src/NHibernate/Mapping/ByCode/Impl/CustomizersImpl/CollectionKeyCustomizer.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Mapping/ByCode/Impl/CustomizersImpl/CollectionKeyCustomizer.cs 2011-05-30 19:32:23 UTC (rev 5892)
+++ trunk/nhibernate/src/NHibernate/Mapping/ByCode/Impl/CustomizersImpl/CollectionKeyCustomizer.cs 2011-05-30 22:28:04 UTC (rev 5893)
@@ -55,6 +55,16 @@
CustomizersHolder.AddCustomizer(propertyPath, (ICollectionPropertiesMapper m) => m.Key(x => x.ForeignKey(foreingKeyName)));
}
+ public void NotNullable(bool notnull)
+ {
+ CustomizersHolder.AddCustomizer(propertyPath, (ICollectionPropertiesMapper m) => m.Key(x => x.NotNullable(notnull)));
+ }
+
+ public void Unique(bool unique)
+ {
+ // Do nothing (a collection with the key as unique... no thanks!)
+ }
+
#endregion
}
}
\ No newline at end of file
Modified: trunk/nhibernate/src/NHibernate/Mapping/ByCode/Impl/CustomizersImpl/JoinKeyCustomizer.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Mapping/ByCode/Impl/CustomizersImpl/JoinKeyCustomizer.cs 2011-05-30 19:32:23 UTC (rev 5892)
+++ trunk/nhibernate/src/NHibernate/Mapping/ByCode/Impl/CustomizersImpl/JoinKeyCustomizer.cs 2011-05-30 22:28:04 UTC (rev 5893)
@@ -52,6 +52,16 @@
CustomizersHolder.AddCustomizer(typeof(TEntity), (IJoinAttributesMapper m) => m.Key(x => x.ForeignKey(foreingKeyName)));
}
+ public void NotNullable(bool notnull)
+ {
+ CustomizersHolder.AddCustomizer(typeof(TEntity), (IJoinAttributesMapper m) => m.Key(x => x.NotNullable(notnull)));
+ }
+
+ public void Unique(bool unique)
+ {
+ CustomizersHolder.AddCustomizer(typeof(TEntity), (IJoinAttributesMapper m) => m.Key(x => x.Unique(unique)));
+ }
+
#endregion
}
}
\ No newline at end of file
Modified: trunk/nhibernate/src/NHibernate/Mapping/ByCode/Impl/CustomizersImpl/JoinedSubclassKeyCustomizer.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Mapping/ByCode/Impl/CustomizersImpl/JoinedSubclassKeyCustomizer.cs 2011-05-30 19:32:23 UTC (rev 5892)
+++ trunk/nhibernate/src/NHibernate/Mapping/ByCode/Impl/CustomizersImpl/JoinedSubclassKeyCustomizer.cs 2011-05-30 22:28:04 UTC (rev 5893)
@@ -52,6 +52,16 @@
CustomizersHolder.AddCustomizer(typeof (TEntity), (IJoinedSubclassAttributesMapper m) => m.Key(x => x.ForeignKey(foreingKeyName)));
}
+ public void NotNullable(bool notnull)
+ {
+ CustomizersHolder.AddCustomizer(typeof(TEntity), (IJoinedSubclassAttributesMapper m) => m.Key(x => x.NotNullable(notnull)));
+ }
+
+ public void Unique(bool unique)
+ {
+ CustomizersHolder.AddCustomizer(typeof(TEntity), (IJoinedSubclassAttributesMapper m) => m.Key(x => x.Unique(unique)));
+ }
+
#endregion
}
}
\ No newline at end of file
Modified: trunk/nhibernate/src/NHibernate/Mapping/ByCode/Impl/KeyMapper.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Mapping/ByCode/Impl/KeyMapper.cs 2011-05-30 19:32:23 UTC (rev 5892)
+++ trunk/nhibernate/src/NHibernate/Mapping/ByCode/Impl/KeyMapper.cs 2011-05-30 22:28:04 UTC (rev 5893)
@@ -50,8 +50,8 @@
else
{
mapping.column1 = !DefaultColumnName(ownerEntityType).Equals(hbm.name) ? hbm.name : null;
- mapping.notnull = hbm.notnull;
- mapping.unique = hbm.unique;
+ NotNullable(hbm.notnull);
+ Unique(hbm.unique);
}
}
@@ -109,6 +109,16 @@
mapping.updateSpecified = true;
}
+ public void NotNullable(bool notnull)
+ {
+ mapping.notnull = mapping.notnullSpecified = notnull;
+ }
+
+ public void Unique(bool unique)
+ {
+ mapping.unique = mapping.uniqueSpecified = unique;
+ }
+
public void ForeignKey(string foreingKeyName)
{
if (foreingKeyName == null)
Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH941/Fixture.cs
===================================================================
--- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH941/Fixture.cs (rev 0)
+++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH941/Fixture.cs 2011-05-30 22:28:04 UTC (rev 5893)
@@ -0,0 +1,62 @@
+using System.Collections.Generic;
+using NHibernate.Cfg.MappingSchema;
+using NHibernate.Mapping.ByCode;
+using NUnit.Framework;
+
+namespace NHibernate.Test.NHSpecificTest.NH941
+{
+ public class MyClass
+ {
+ public virtual int Id { get; set; }
+ public virtual ICollection<Related> Relateds { get; set; }
+ }
+
+ public class Related
+ {
+ public virtual int Id { get; set; }
+ }
+
+ public class Fixture : TestCaseMappingByCode
+ {
+ protected override HbmMapping GetMappings()
+ {
+ var mapper = new ModelMapper();
+ mapper.Class<MyClass>(rc =>
+ {
+ rc.Id(x => x.Id, map => map.Generator(Generators.HighLow));
+ rc.Bag(x => x.Relateds, map =>
+ {
+ map.Key(km => km.Column(cm => cm.NotNullable(true)));
+ map.Cascade(Mapping.ByCode.Cascade.All);
+ }, rel => rel.OneToMany());
+ });
+ mapper.Class<Related>(rc => rc.Id(x => x.Id, map => map.Generator(Generators.HighLow)));
+ HbmMapping mappings = mapper.CompileMappingForAllExplicitAddedEntities();
+ return mappings;
+ }
+
+ [Test]
+ public void WhenSaveOneThenShouldSaveMany()
+ {
+ using (ISession session = OpenSession())
+ {
+ using (ITransaction tx = session.BeginTransaction())
+ {
+ var one = new MyClass();
+ one.Relateds = new List<Related> {new Related(), new Related()};
+ session.Persist(one);
+ tx.Commit();
+ }
+ }
+ using (ISession session = OpenSession())
+ {
+ using (ITransaction tx = session.BeginTransaction())
+ {
+ session.CreateQuery("delete from Related").ExecuteUpdate();
+ session.CreateQuery("delete from MyClass").ExecuteUpdate();
+ tx.Commit();
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <fab...@us...> - 2011-05-30 22:38:08
|
Revision: 5894
http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5894&view=rev
Author: fabiomaulo
Date: 2011-05-30 22:38:01 +0000 (Mon, 30 May 2011)
Log Message:
-----------
Porting to start fix NH-941
Modified Paths:
--------------
trunk/nhibernate/src/NHibernate/Engine/Cascade.cs
trunk/nhibernate/src/NHibernate/Engine/IPersistenceContext.cs
trunk/nhibernate/src/NHibernate/Engine/StatefulPersistenceContext.cs
trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH941/Fixture.cs
trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj
Modified: trunk/nhibernate/src/NHibernate/Engine/Cascade.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Engine/Cascade.cs 2011-05-30 22:28:04 UTC (rev 5893)
+++ trunk/nhibernate/src/NHibernate/Engine/Cascade.cs 2011-05-30 22:38:01 UTC (rev 5894)
@@ -123,7 +123,7 @@
if (style.DoCascade(action))
{
- CascadeProperty(persister.GetPropertyValue(parent, i, entityMode), types[i], style, anything, false);
+ CascadeProperty(parent, persister.GetPropertyValue(parent, i, entityMode), types[i], style, anything, false);
}
else if (action.RequiresNoCascadeChecking)
{
@@ -136,7 +136,7 @@
}
/// <summary> Cascade an action to the child or children</summary>
- private void CascadeProperty(object child, IType type, CascadeStyle style, object anything, bool isCascadeDeleteEnabled)
+ private void CascadeProperty(object parent, object child, IType type, CascadeStyle style, object anything, bool isCascadeDeleteEnabled)
{
if (child != null)
{
@@ -145,12 +145,12 @@
IAssociationType associationType = (IAssociationType)type;
if (CascadeAssociationNow(associationType))
{
- CascadeAssociation(child, type, style, anything, isCascadeDeleteEnabled);
+ CascadeAssociation(parent, child, type, style, anything, isCascadeDeleteEnabled);
}
}
else if (type.IsComponentType)
{
- CascadeComponent(child, (IAbstractComponentType)type, anything);
+ CascadeComponent(parent, child, (IAbstractComponentType)type, anything);
}
}
}
@@ -160,7 +160,7 @@
return associationType.ForeignKeyDirection.CascadeNow(point) && (eventSource.EntityMode != EntityMode.Xml || associationType.IsEmbeddedInXML);
}
- private void CascadeComponent(object child, IAbstractComponentType componentType, object anything)
+ private void CascadeComponent(object parent, object child, IAbstractComponentType componentType, object anything)
{
object[] children = componentType.GetPropertyValues(child, eventSource);
IType[] types = componentType.Subtypes;
@@ -169,25 +169,25 @@
CascadeStyle componentPropertyStyle = componentType.GetCascadeStyle(i);
if (componentPropertyStyle.DoCascade(action))
{
- CascadeProperty(children[i], types[i], componentPropertyStyle, anything, false);
+ CascadeProperty(parent, children[i], types[i], componentPropertyStyle, anything, false);
}
}
}
- private void CascadeAssociation(object child, IType type, CascadeStyle style, object anything, bool isCascadeDeleteEnabled)
+ private void CascadeAssociation(object parent, object child, IType type, CascadeStyle style, object anything, bool isCascadeDeleteEnabled)
{
if (type.IsEntityType || type.IsAnyType)
{
- CascadeToOne(child, type, style, anything, isCascadeDeleteEnabled);
+ CascadeToOne(parent, child, type, style, anything, isCascadeDeleteEnabled);
}
else if (type.IsCollectionType)
{
- CascadeCollection(child, style, anything, (CollectionType)type);
+ CascadeCollection(parent, child, style, anything, (CollectionType)type);
}
}
/// <summary> Cascade an action to a collection</summary>
- private void CascadeCollection(object child, CascadeStyle style, object anything, CollectionType type)
+ private void CascadeCollection(object parent, object child, CascadeStyle style, object anything, CollectionType type)
{
ICollectionPersister persister = eventSource.Factory.GetCollectionPersister(type.Role);
IType elemType = persister.ElementType;
@@ -198,24 +198,32 @@
//cascade to current collection elements
if (elemType.IsEntityType || elemType.IsAnyType || elemType.IsComponentType)
- CascadeCollectionElements(child, type, style, elemType, anything, persister.CascadeDeleteEnabled);
+ CascadeCollectionElements(parent, child, type, style, elemType, anything, persister.CascadeDeleteEnabled);
point = oldCascadeTo;
}
/// <summary> Cascade an action to a to-one association or any type</summary>
- private void CascadeToOne(object child, IType type, CascadeStyle style, object anything, bool isCascadeDeleteEnabled)
+ private void CascadeToOne(object parent, object child, IType type, CascadeStyle style, object anything, bool isCascadeDeleteEnabled)
{
string entityName = type.IsEntityType ? ((EntityType)type).GetAssociatedEntityName() : null;
if (style.ReallyDoCascade(action))
{
//not really necessary, but good for consistency...
- action.Cascade(eventSource, child, entityName, anything, isCascadeDeleteEnabled);
+ eventSource.PersistenceContext.AddChildParent(child, parent);
+ try
+ {
+ action.Cascade(eventSource, child, entityName, anything, isCascadeDeleteEnabled);
+ }
+ finally
+ {
+ eventSource.PersistenceContext.RemoveChildParent(child);
+ }
}
}
/// <summary> Cascade to the collection elements</summary>
- private void CascadeCollectionElements(object child, CollectionType collectionType, CascadeStyle style, IType elemType, object anything, bool isCascadeDeleteEnabled)
+ private void CascadeCollectionElements(object parent, object child, CollectionType collectionType, CascadeStyle style, IType elemType, object anything, bool isCascadeDeleteEnabled)
{
// we can't cascade to non-embedded elements
bool embeddedElements = eventSource.EntityMode != EntityMode.Xml
@@ -229,7 +237,7 @@
log.Info("cascade " + action + " for collection: " + collectionType.Role);
foreach (object o in action.GetCascadableChildrenIterator(eventSource, collectionType, child))
- CascadeProperty(o, elemType, style, anything, isCascadeDeleteEnabled);
+ CascadeProperty(parent, o, elemType, style, anything, isCascadeDeleteEnabled);
log.Info("done cascade " + action + " for collection: " + collectionType.Role);
}
Modified: trunk/nhibernate/src/NHibernate/Engine/IPersistenceContext.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Engine/IPersistenceContext.cs 2011-05-30 22:28:04 UTC (rev 5893)
+++ trunk/nhibernate/src/NHibernate/Engine/IPersistenceContext.cs 2011-05-30 22:38:01 UTC (rev 5894)
@@ -396,5 +396,18 @@
/// <summary>Is in a two-phase load? </summary>
bool IsLoadFinished { get; }
+
+ /// <summary>
+ /// Add child/parent relation to cache for cascading operations
+ /// </summary>
+ /// <param name="child">The child.</param>
+ /// <param name="parent">The parent.</param>
+ void AddChildParent(object child, object parent);
+
+ /// <summary>
+ /// Remove child/parent relation from cache
+ /// </summary>
+ /// <param name="child">The child.</param>
+ void RemoveChildParent(object child);
}
}
Modified: trunk/nhibernate/src/NHibernate/Engine/StatefulPersistenceContext.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Engine/StatefulPersistenceContext.cs 2011-05-30 22:28:04 UTC (rev 5893)
+++ trunk/nhibernate/src/NHibernate/Engine/StatefulPersistenceContext.cs 2011-05-30 22:38:01 UTC (rev 5894)
@@ -81,6 +81,11 @@
private Dictionary<CollectionKey, IPersistentCollection> unownedCollections;
private bool hasNonReadOnlyEntities;
+
+ // Parent entities cache by their child for cascading
+ // May be empty or not contains all relation
+ [NonSerialized]
+ private IDictionary parentsByChild;
[NonSerialized]
private int cascading;
@@ -116,6 +121,7 @@
collectionEntries = IdentityMap.InstantiateSequenced(InitCollectionSize);
collectionsByKey = new Dictionary<CollectionKey, IPersistentCollection>(InitCollectionSize);
arrayHolders = IdentityMap.Instantiate(InitCollectionSize);
+ parentsByChild = IdentityMap.Instantiate(InitCollectionSize);
nullifiableEntityKeys = new HashedSet<EntityKey>();
InitTransientState();
}
@@ -279,6 +285,7 @@
{
loadContexts.Cleanup();
}
+ parentsByChild.Clear();
}
/// <summary>False if we know for certain that all the entities are read-only</summary>
@@ -458,6 +465,7 @@
nullifiableEntityKeys.Remove(key);
BatchFetchQueue.RemoveBatchLoadableEntityKey(key);
BatchFetchQueue.RemoveSubselect(key);
+ parentsByChild.Clear();
return entity;
}
@@ -1084,21 +1092,165 @@
/// Search the persistence context for an owner for the child object,
/// given a collection role
/// </summary>
- public object GetOwnerId(string entity, string property, object childObject, IDictionary mergeMap)
+ public object GetOwnerId(string entityName, string propertyName, object childEntity, IDictionary mergeMap)
{
- throw new NotImplementedException();
- // TODO persistent context (BackrefPropertyAccessor)
+ string collectionRole = entityName + '.' + propertyName;
+ IEntityPersister persister = session.Factory.GetEntityPersister(entityName);
+ ICollectionPersister collectionPersister = session.Factory.GetCollectionPersister(collectionRole);
+
+ object parent = parentsByChild[childEntity];
+ if (parent != null)
+ {
+ var entityEntry = (EntityEntry) entityEntries[parent];
+ //there maybe more than one parent, filter by type
+ if (persister.IsSubclassEntityName(entityEntry.EntityName) && IsFoundInParent(propertyName, childEntity, persister, collectionPersister, parent))
+ {
+ return GetEntry(parent).Id;
+ }
+ parentsByChild.Remove(childEntity); // remove wrong entry
+ }
+
+ // iterate all the entities currently associated with the persistence context.
+ foreach (DictionaryEntry entry in entityEntries)
+ {
+ var entityEntry = (EntityEntry) entry.Value;
+ // does this entity entry pertain to the entity persister in which we are interested (owner)?
+ if (persister.IsSubclassEntityName(entityEntry.EntityName))
+ {
+ object entityEntryInstance = entry.Key;
+
+ //check if the managed object is the parent
+ bool found = IsFoundInParent(propertyName, childEntity, persister, collectionPersister, entityEntryInstance);
+
+ if (!found && mergeMap != null)
+ {
+ //check if the detached object being merged is the parent
+ object unmergedInstance = mergeMap[entityEntryInstance];
+ object unmergedChild = mergeMap[childEntity];
+ if (unmergedInstance != null && unmergedChild != null)
+ {
+ found = IsFoundInParent(propertyName, unmergedChild, persister, collectionPersister, unmergedInstance);
+ }
+ }
+
+ if (found)
+ {
+ return entityEntry.Id;
+ }
+ }
+ }
+
+ // if we get here, it is possible that we have a proxy 'in the way' of the merge map resolution...
+ // NOTE: decided to put this here rather than in the above loop as I was nervous about the performance
+ // of the loop-in-loop especially considering this is far more likely the 'edge case'
+ if (mergeMap != null)
+ {
+ foreach (DictionaryEntry mergeMapEntry in mergeMap)
+ {
+ var proxy = mergeMapEntry.Key as INHibernateProxy;
+ if (proxy != null)
+ {
+ if (persister.IsSubclassEntityName(proxy.HibernateLazyInitializer.EntityName))
+ {
+ bool found = IsFoundInParent(propertyName, childEntity, persister, collectionPersister, mergeMap[proxy]);
+ if (!found)
+ {
+ found = IsFoundInParent(propertyName, mergeMap[childEntity], persister, collectionPersister, mergeMap[proxy]);
+ }
+ if (found)
+ {
+ return proxy.HibernateLazyInitializer.Identifier;
+ }
+ }
+ }
+ }
+ }
+
+ return null;
}
+ private bool IsFoundInParent(string property, object childEntity, IEntityPersister persister, ICollectionPersister collectionPersister, object potentialParent)
+ {
+ object collection = persister.GetPropertyValue(potentialParent, property, session.EntityMode);
+ return collection != null && NHibernateUtil.IsInitialized(collection) && collectionPersister.CollectionType.Contains(collection, childEntity, session);
+ }
+
/// <summary>
/// Search the persistence context for an index of the child object, given a collection role
/// </summary>
- public object GetIndexInOwner(string entity, string property, object childObject, IDictionary mergeMap)
+ public object GetIndexInOwner(string entity, string property, object childEntity, IDictionary mergeMap)
{
- throw new NotImplementedException();
- // TODO persistent context (IndexPropertyAccessor)
+ IEntityPersister persister = session.Factory.GetEntityPersister(entity);
+ ICollectionPersister cp = session.Factory.GetCollectionPersister(entity + '.' + property);
+
+ // try cache lookup first
+ object parent = parentsByChild[childEntity];
+ if (parent != null)
+ {
+ var entityEntry = (EntityEntry) entityEntries[parent];
+ //there maybe more than one parent, filter by type
+ if (persister.IsSubclassEntityName(entityEntry.EntityName))
+ {
+ Object index = GetIndexInParent(property, childEntity, persister, cp, parent);
+
+ if (index == null && mergeMap != null)
+ {
+ Object unmergedInstance = mergeMap[parent];
+ Object unmergedChild = mergeMap[childEntity];
+ if (unmergedInstance != null && unmergedChild != null)
+ {
+ index = GetIndexInParent(property, unmergedChild, persister, cp, unmergedInstance);
+ }
+ }
+ if (index != null)
+ {
+ return index;
+ }
+ }
+ else
+ {
+ parentsByChild.Remove(childEntity); // remove wrong entry
+ }
+ }
+
+ //Not found in cache, proceed
+ foreach (DictionaryEntry me in entityEntries)
+ {
+ var ee = (EntityEntry) me.Value;
+ if (persister.IsSubclassEntityName(ee.EntityName))
+ {
+ object instance = me.Key;
+ object index = GetIndexInParent(property, childEntity, persister, cp, instance);
+
+ if (index == null && mergeMap != null)
+ {
+ object unmergedInstance = mergeMap[instance];
+ object unmergedChild = mergeMap[childEntity];
+ if (unmergedInstance != null && unmergedChild != null)
+ {
+ index = GetIndexInParent(property, unmergedChild, persister, cp, unmergedInstance);
+ }
+ }
+
+ if (index != null)
+ {
+ return index;
+ }
+ }
+ }
+ return null;
}
+ private object GetIndexInParent(string property, object childEntity, IEntityPersister persister, ICollectionPersister collectionPersister, object potentialParent)
+ {
+ object collection = persister.GetPropertyValue(potentialParent, property, session.EntityMode);
+ if (collection != null && NHibernateUtil.IsInitialized(collection))
+ {
+ return collectionPersister.CollectionType.IndexOf(collection, childEntity);
+ }
+ return null;
+ }
+
/// <summary>
/// Record the fact that the association belonging to the keyed entity is null.
/// </summary>
@@ -1196,9 +1348,10 @@
object entity = tempObject;
object tempObject2 = entityEntries[entity];
entityEntries.Remove(entity);
- EntityEntry oldEntry = (EntityEntry) tempObject2;
+ var oldEntry = (EntityEntry) tempObject2;
+ parentsByChild.Clear();
- EntityKey newKey = new EntityKey(generatedId, oldEntry.Persister, Session.EntityMode);
+ var newKey = new EntityKey(generatedId, oldEntry.Persister, Session.EntityMode);
AddEntity(newKey, entity);
AddEntry(entity, oldEntry.Status, oldEntry.LoadedState, oldEntry.RowId, generatedId, oldEntry.Version,
oldEntry.LockMode, oldEntry.ExistsInDatabase, oldEntry.Persister, oldEntry.IsBeingReplicated,
@@ -1213,6 +1366,16 @@
}
}
+ public void AddChildParent(object child, object parent)
+ {
+ parentsByChild[child] = parent;
+ }
+
+ public void RemoveChildParent(object child)
+ {
+ parentsByChild.Remove(child);
+ }
+
#endregion
public override string ToString()
@@ -1240,6 +1403,7 @@
// collections to this session, as well as the EntityEntry and
// CollectionEntry instances; these associations are transient
// because serialization is used for different things.
+ parentsByChild = IdentityMap.Instantiate(InitCollectionSize);
// TODO NH: "reconnect" EntityKey with session.factory and create a test for serialization of StatefulPersistenceContext
foreach (DictionaryEntry collectionEntry in collectionEntries)
Modified: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH941/Fixture.cs
===================================================================
--- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH941/Fixture.cs 2011-05-30 22:28:04 UTC (rev 5893)
+++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH941/Fixture.cs 2011-05-30 22:38:01 UTC (rev 5894)
@@ -16,6 +16,7 @@
public virtual int Id { get; set; }
}
+ [Ignore("Not fixed yet")]
public class Fixture : TestCaseMappingByCode
{
protected override HbmMapping GetMappings()
Modified: trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj
===================================================================
--- trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2011-05-30 22:28:04 UTC (rev 5893)
+++ trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2011-05-30 22:38:01 UTC (rev 5894)
@@ -867,6 +867,7 @@
<Compile Include="NHSpecificTest\NH2733\Model.cs" />
<Compile Include="NHSpecificTest\NH2736\Domain.cs" />
<Compile Include="NHSpecificTest\NH2736\Fixture.cs" />
+ <Compile Include="NHSpecificTest\NH941\Fixture.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.
|
|
From: <fab...@us...> - 2011-05-31 12:12:32
|
Revision: 5896
http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5896&view=rev
Author: fabiomaulo
Date: 2011-05-31 12:12:20 +0000 (Tue, 31 May 2011)
Log Message:
-----------
Fix NH-941 NH-1050
Modified Paths:
--------------
trunk/nhibernate/src/NHibernate/Cfg/XmlHbmBinding/CollectionBinder.cs
trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH941/Fixture.cs
Modified: trunk/nhibernate/src/NHibernate/Cfg/XmlHbmBinding/CollectionBinder.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Cfg/XmlHbmBinding/CollectionBinder.cs 2011-05-31 03:41:20 UTC (rev 5895)
+++ trunk/nhibernate/src/NHibernate/Cfg/XmlHbmBinding/CollectionBinder.cs 2011-05-31 12:12:20 UTC (rev 5896)
@@ -760,6 +760,21 @@
}
BindCache(collectionMapping.Cache, model);
+
+ if (model.IsOneToMany && !model.IsInverse && !model.Key.IsNullable)
+ {
+ // for non-inverse one-to-many, with a not-null fk, add a backref!
+ string entityName = ((OneToMany)model.Element).ReferencedEntityName;
+ PersistentClass referenced = mappings.GetClass(entityName);
+ Backref prop = new Backref();
+ prop.Name = '_' + model.OwnerEntityName + "." + collectionMapping.Name + "Backref";
+ prop.IsUpdateable = false;
+ prop.IsSelectable = false;
+ prop.CollectionRole = model.Role;
+ prop.EntityName = model.Owner.EntityName;
+ prop.Value = model.Key;
+ referenced.AddProperty(prop);
+ }
}
private void BindManyToMany(HbmManyToMany manyToManyMapping, Mapping.Collection model)
Modified: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH941/Fixture.cs
===================================================================
--- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH941/Fixture.cs 2011-05-31 03:41:20 UTC (rev 5895)
+++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH941/Fixture.cs 2011-05-31 12:12:20 UTC (rev 5896)
@@ -16,7 +16,6 @@
public virtual int Id { get; set; }
}
- [Ignore("Not fixed yet")]
public class Fixture : TestCaseMappingByCode
{
protected override HbmMapping GetMappings()
@@ -27,7 +26,7 @@
rc.Id(x => x.Id, map => map.Generator(Generators.HighLow));
rc.Bag(x => x.Relateds, map =>
{
- map.Key(km => km.Column(cm => cm.NotNullable(true)));
+ map.Key(km => km.NotNullable(true));
map.Cascade(Mapping.ByCode.Cascade.All);
}, rel => rel.OneToMany());
});
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <fab...@us...> - 2011-05-31 15:06:28
|
Revision: 5897
http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5897&view=rev
Author: fabiomaulo
Date: 2011-05-31 15:06:16 +0000 (Tue, 31 May 2011)
Log Message:
-----------
- Fix NH-2753
- added <key> column mapping by code
Modified Paths:
--------------
trunk/nhibernate/src/NHibernate/Cfg/XmlHbmBinding/CollectionBinder.cs
trunk/nhibernate/src/NHibernate/Engine/StatefulPersistenceContext.cs
trunk/nhibernate/src/NHibernate/Mapping/ByCode/IListIndexMapper.cs
trunk/nhibernate/src/NHibernate/Mapping/ByCode/Impl/ListIndexMapper.cs
trunk/nhibernate/src/NHibernate/Properties/IndexPropertyAccessor.cs
trunk/nhibernate/src/NHibernate/Type/ListType.cs
trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH941/Fixture.cs
trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj
Added Paths:
-----------
trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH941/Domain.cs
trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH941/FixtureUsingList.cs
Modified: trunk/nhibernate/src/NHibernate/Cfg/XmlHbmBinding/CollectionBinder.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Cfg/XmlHbmBinding/CollectionBinder.cs 2011-05-31 12:12:20 UTC (rev 5896)
+++ trunk/nhibernate/src/NHibernate/Cfg/XmlHbmBinding/CollectionBinder.cs 2011-05-31 15:06:16 UTC (rev 5897)
@@ -517,6 +517,20 @@
{
model.BaseIndex = Convert.ToInt32(listMapping.ListIndex.@base);
}
+
+ if (model.IsOneToMany && !model.Key.IsNullable && !model.IsInverse)
+ {
+ string entityName = ((OneToMany)model.Element).ReferencedEntityName;
+ PersistentClass referenced = mappings.GetClass(entityName);
+ var ib = new IndexBackref();
+ ib.Name = '_' + model.OwnerEntityName + "." + listMapping.Name + "IndexBackref";
+ ib.IsUpdateable = false;
+ ib.IsSelectable = false;
+ ib.CollectionRole = model.Role;
+ ib.EntityName = model.Owner.EntityName;
+ ib.Value = model.Index;
+ referenced.AddProperty(ib);
+ }
}
private void BindArraySecondPass(HbmArray arrayMapping, List model,
@@ -664,6 +678,21 @@
BindIndexManyToAny(indexManyToAnyMapping, any, model.IsOneToMany);
model.Index = any;
}
+
+ bool indexIsFormula = model.Index.ColumnIterator.Any(x=> x.IsFormula);
+ if (model.IsOneToMany && !model.Key.IsNullable && !model.IsInverse && !indexIsFormula)
+ {
+ string entityName = ((OneToMany)model.Element).ReferencedEntityName;
+ PersistentClass referenced = mappings.GetClass(entityName);
+ var ib = new IndexBackref();
+ ib.Name = '_' + model.OwnerEntityName + "." + mapMapping.Name + "IndexBackref";
+ ib.IsUpdateable = false;
+ ib.IsSelectable = false;
+ ib.CollectionRole = model.Role;
+ ib.EntityName = model.Owner.EntityName;
+ ib.Value = model.Index;
+ referenced.AddProperty(ib);
+ }
}
private void BindIndexManyToAny(HbmIndexManyToAny indexManyToAnyMapping, Any any, bool isNullable)
Modified: trunk/nhibernate/src/NHibernate/Engine/StatefulPersistenceContext.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Engine/StatefulPersistenceContext.cs 2011-05-31 12:12:20 UTC (rev 5896)
+++ trunk/nhibernate/src/NHibernate/Engine/StatefulPersistenceContext.cs 2011-05-31 15:06:16 UTC (rev 5897)
@@ -1191,12 +1191,12 @@
//there maybe more than one parent, filter by type
if (persister.IsSubclassEntityName(entityEntry.EntityName))
{
- Object index = GetIndexInParent(property, childEntity, persister, cp, parent);
+ object index = GetIndexInParent(property, childEntity, persister, cp, parent);
if (index == null && mergeMap != null)
{
- Object unmergedInstance = mergeMap[parent];
- Object unmergedChild = mergeMap[childEntity];
+ object unmergedInstance = mergeMap[parent];
+ object unmergedChild = mergeMap[childEntity];
if (unmergedInstance != null && unmergedChild != null)
{
index = GetIndexInParent(property, unmergedChild, persister, cp, unmergedInstance);
Modified: trunk/nhibernate/src/NHibernate/Mapping/ByCode/IListIndexMapper.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Mapping/ByCode/IListIndexMapper.cs 2011-05-31 12:12:20 UTC (rev 5896)
+++ trunk/nhibernate/src/NHibernate/Mapping/ByCode/IListIndexMapper.cs 2011-05-31 15:06:16 UTC (rev 5897)
@@ -1,3 +1,5 @@
+using System;
+
namespace NHibernate.Mapping.ByCode
{
public interface IListIndexMapper
@@ -4,5 +6,6 @@
{
void Column(string columnName);
void Base(int baseIndex);
+ void Column(Action<IColumnMapper> columnMapper);
}
}
\ No newline at end of file
Modified: trunk/nhibernate/src/NHibernate/Mapping/ByCode/Impl/ListIndexMapper.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Mapping/ByCode/Impl/ListIndexMapper.cs 2011-05-31 12:12:20 UTC (rev 5896)
+++ trunk/nhibernate/src/NHibernate/Mapping/ByCode/Impl/ListIndexMapper.cs 2011-05-31 15:06:16 UTC (rev 5897)
@@ -1,10 +1,12 @@
using System;
+using System.Linq;
using NHibernate.Cfg.MappingSchema;
namespace NHibernate.Mapping.ByCode.Impl
{
public class ListIndexMapper : IListIndexMapper
{
+ private const string DefaultIndexColumnName = "ListIdx";
private readonly HbmListIndex mapping;
private readonly System.Type ownerEntityType;
@@ -18,9 +20,42 @@
public void Column(string columnName)
{
- mapping.column1 = columnName;
+ Column(x => x.Name(columnName));
}
+ public void Column(Action<IColumnMapper> columnMapper)
+ {
+ HbmColumn hbm = mapping.Columns.SingleOrDefault();
+ hbm = hbm
+ ??
+ new HbmColumn
+ {
+ name = mapping.column1
+ };
+ columnMapper(new ColumnMapper(hbm, DefaultIndexColumnName));
+ if (ColumnTagIsRequired(hbm))
+ {
+ mapping.column = hbm;
+ ResetColumnPlainValues();
+ }
+ else
+ {
+ mapping.column1 = !DefaultIndexColumnName.Equals(hbm.name) ? hbm.name : null;
+ }
+ }
+
+ private void ResetColumnPlainValues()
+ {
+ mapping.column1 = null;
+ }
+
+ private bool ColumnTagIsRequired(HbmColumn hbm)
+ {
+ return hbm.length != null || hbm.precision != null || hbm.scale != null || hbm.notnull || hbm.unique
+ || hbm.uniquekey != null || hbm.sqltype != null || hbm.index != null || hbm.@default != null
+ || hbm.check != null;
+ }
+
public void Base(int baseIndex)
{
if (baseIndex <= 0)
Modified: trunk/nhibernate/src/NHibernate/Properties/IndexPropertyAccessor.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Properties/IndexPropertyAccessor.cs 2011-05-31 12:12:20 UTC (rev 5896)
+++ trunk/nhibernate/src/NHibernate/Properties/IndexPropertyAccessor.cs 2011-05-31 15:06:16 UTC (rev 5897)
@@ -25,12 +25,12 @@
public IGetter GetGetter(System.Type theClass, string propertyName)
{
- throw new NotImplementedException();
+ return new IndexGetter(this);
}
public ISetter GetSetter(System.Type theClass, string propertyName)
{
- throw new NotImplementedException();
+ return new IndexSetter();
}
public bool CanAccessThroughReflectionOptimizer
Modified: trunk/nhibernate/src/NHibernate/Type/ListType.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Type/ListType.cs 2011-05-31 12:12:20 UTC (rev 5896)
+++ trunk/nhibernate/src/NHibernate/Type/ListType.cs 2011-05-31 15:06:16 UTC (rev 5897)
@@ -79,8 +79,7 @@
int i = list.IndexOf(element);
if (i < 0)
return null;
- else
- return list[i];
+ return i;
}
}
}
\ No newline at end of file
Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH941/Domain.cs
===================================================================
--- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH941/Domain.cs (rev 0)
+++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH941/Domain.cs 2011-05-31 15:06:16 UTC (rev 5897)
@@ -0,0 +1,15 @@
+using System.Collections.Generic;
+
+namespace NHibernate.Test.NHSpecificTest.NH941
+{
+ public class MyClass
+ {
+ public virtual int Id { get; set; }
+ public virtual IList<Related> Relateds { get; set; }
+ }
+
+ public class Related
+ {
+ public virtual int Id { get; set; }
+ }
+}
\ No newline at end of file
Modified: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH941/Fixture.cs
===================================================================
--- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH941/Fixture.cs 2011-05-31 12:12:20 UTC (rev 5896)
+++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH941/Fixture.cs 2011-05-31 15:06:16 UTC (rev 5897)
@@ -5,17 +5,6 @@
namespace NHibernate.Test.NHSpecificTest.NH941
{
- public class MyClass
- {
- public virtual int Id { get; set; }
- public virtual ICollection<Related> Relateds { get; set; }
- }
-
- public class Related
- {
- public virtual int Id { get; set; }
- }
-
public class Fixture : TestCaseMappingByCode
{
protected override HbmMapping GetMappings()
Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH941/FixtureUsingList.cs
===================================================================
--- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH941/FixtureUsingList.cs (rev 0)
+++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH941/FixtureUsingList.cs 2011-05-31 15:06:16 UTC (rev 5897)
@@ -0,0 +1,52 @@
+using System.Collections.Generic;
+using NHibernate.Cfg.MappingSchema;
+using NHibernate.Mapping.ByCode;
+using NUnit.Framework;
+
+namespace NHibernate.Test.NHSpecificTest.NH941
+{
+ public class FixtureUsingList : TestCaseMappingByCode
+ {
+ protected override HbmMapping GetMappings()
+ {
+ var mapper = new ModelMapper();
+ mapper.Class<MyClass>(rc =>
+ {
+ rc.Id(x => x.Id, map => map.Generator(Generators.HighLow));
+ rc.List(x => x.Relateds, map =>
+ {
+ map.Key(km => km.NotNullable(true));
+ map.Cascade(Mapping.ByCode.Cascade.All);
+ map.Index(idxm=> idxm.Column(colmap=> colmap.NotNullable(true)));
+ }, rel => rel.OneToMany());
+ });
+ mapper.Class<Related>(rc => rc.Id(x => x.Id, map => map.Generator(Generators.HighLow)));
+ HbmMapping mappings = mapper.CompileMappingForAllExplicitAddedEntities();
+ return mappings;
+ }
+
+ [Test]
+ public void WhenSaveOneThenShouldSaveMany()
+ {
+ using (ISession session = OpenSession())
+ {
+ using (ITransaction tx = session.BeginTransaction())
+ {
+ var one = new MyClass();
+ one.Relateds = new List<Related> {new Related(), new Related()};
+ session.Persist(one);
+ tx.Commit();
+ }
+ }
+ using (ISession session = OpenSession())
+ {
+ using (ITransaction tx = session.BeginTransaction())
+ {
+ session.CreateQuery("delete from Related").ExecuteUpdate();
+ session.CreateQuery("delete from MyClass").ExecuteUpdate();
+ 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-05-31 12:12:20 UTC (rev 5896)
+++ trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2011-05-31 15:06:16 UTC (rev 5897)
@@ -867,7 +867,9 @@
<Compile Include="NHSpecificTest\NH2733\Model.cs" />
<Compile Include="NHSpecificTest\NH2736\Domain.cs" />
<Compile Include="NHSpecificTest\NH2736\Fixture.cs" />
+ <Compile Include="NHSpecificTest\NH941\Domain.cs" />
<Compile Include="NHSpecificTest\NH941\Fixture.cs" />
+ <Compile Include="NHSpecificTest\NH941\FixtureUsingList.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.
|
|
From: <fab...@us...> - 2011-05-31 17:46:21
|
Revision: 5900
http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5900&view=rev
Author: fabiomaulo
Date: 2011-05-31 17:46:14 +0000 (Tue, 31 May 2011)
Log Message:
-----------
Starting usage of IParameterSpecification for Criteria
Modified Paths:
--------------
trunk/nhibernate/src/NHibernate/Criterion/BetweenExpression.cs
trunk/nhibernate/src/NHibernate/Criterion/ConstantProjection.cs
trunk/nhibernate/src/NHibernate/Criterion/ICriteriaQuery.cs
trunk/nhibernate/src/NHibernate/Criterion/IdentifierEqExpression.cs
trunk/nhibernate/src/NHibernate/Criterion/InExpression.cs
trunk/nhibernate/src/NHibernate/Criterion/InsensitiveLikeExpression.cs
trunk/nhibernate/src/NHibernate/Criterion/LikeExpression.cs
trunk/nhibernate/src/NHibernate/Criterion/SimpleExpression.cs
trunk/nhibernate/src/NHibernate/Loader/Criteria/CriteriaQueryTranslator.cs
trunk/nhibernate/src/NHibernate/SqlCommand/SqlStringBuilder.cs
trunk/nhibernate/src/NHibernate.Test/Criteria/AddNumberProjection.cs
Modified: trunk/nhibernate/src/NHibernate/Criterion/BetweenExpression.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Criterion/BetweenExpression.cs 2011-05-31 17:08:07 UTC (rev 5899)
+++ trunk/nhibernate/src/NHibernate/Criterion/BetweenExpression.cs 2011-05-31 17:46:14 UTC (rev 5900)
@@ -58,9 +58,9 @@
sqlBuilder
.Add(columnNames[0])
.Add(" between ")
- .AddParameter()
+ .Add(criteriaQuery.NewQueryParameter())
.Add(" and ")
- .AddParameter();
+ .Add(criteriaQuery.NewQueryParameter());
}
else
{
@@ -76,7 +76,7 @@
sqlBuilder.Add(columnNames[i])
.Add(" >= ")
- .AddParameter();
+ .Add(criteriaQuery.NewQueryParameter());
}
for (int i = 0; i < columnNames.Length; i++)
@@ -84,7 +84,7 @@
sqlBuilder.Add(" AND ")
.Add(columnNames[i])
.Add(" <= ")
- .AddParameter();
+ .Add(criteriaQuery.NewQueryParameter());
}
}
Modified: trunk/nhibernate/src/NHibernate/Criterion/ConstantProjection.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Criterion/ConstantProjection.cs 2011-05-31 17:08:07 UTC (rev 5899)
+++ trunk/nhibernate/src/NHibernate/Criterion/ConstantProjection.cs 2011-05-31 17:46:14 UTC (rev 5900)
@@ -43,7 +43,7 @@
public override SqlString ToSqlString(ICriteria criteria, int position, ICriteriaQuery criteriaQuery, IDictionary<string, IFilter> enabledFilters)
{
return new SqlStringBuilder()
- .AddParameter()
+ .Add(criteriaQuery.NewQueryParameter())
.Add(" as ")
.Add(GetColumnAliases(position)[0])
.ToSqlString();
Modified: trunk/nhibernate/src/NHibernate/Criterion/ICriteriaQuery.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Criterion/ICriteriaQuery.cs 2011-05-31 17:08:07 UTC (rev 5899)
+++ trunk/nhibernate/src/NHibernate/Criterion/ICriteriaQuery.cs 2011-05-31 17:46:14 UTC (rev 5900)
@@ -1,4 +1,7 @@
+using System.Collections.Generic;
using NHibernate.Engine;
+using NHibernate.Param;
+using NHibernate.SqlCommand;
using NHibernate.Type;
namespace NHibernate.Criterion
@@ -67,6 +70,12 @@
int GetIndexForAlias();
/// <summary>
+ /// Create a new query parameter to use in a <see cref="ICriterion"/>
+ /// </summary>
+ /// <returns>A new instance of a query parameter to be added to a <see cref="SqlString"/>.</returns>
+ Parameter NewQueryParameter();
+
+ /// <summary>
/// Creates a dummy parameter index for the supplied paged value.
/// Returns null if the Dialect does not support limit parameters
/// </summary>
Modified: trunk/nhibernate/src/NHibernate/Criterion/IdentifierEqExpression.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Criterion/IdentifierEqExpression.cs 2011-05-31 17:08:07 UTC (rev 5899)
+++ trunk/nhibernate/src/NHibernate/Criterion/IdentifierEqExpression.cs 2011-05-31 17:46:14 UTC (rev 5900)
@@ -62,7 +62,7 @@
{
if (_projection == null)
{
- result.AddParameter();
+ result.Add(criteriaQuery.NewQueryParameter());
}
else
{
Modified: trunk/nhibernate/src/NHibernate/Criterion/InExpression.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Criterion/InExpression.cs 2011-05-31 17:08:07 UTC (rev 5899)
+++ trunk/nhibernate/src/NHibernate/Criterion/InExpression.cs 2011-05-31 17:46:14 UTC (rev 5900)
@@ -88,7 +88,7 @@
{
result.Add(StringHelper.CommaSpace);
}
- result.AddParameter();
+ result.Add(criteriaQuery.NewQueryParameter());
}
result.Add(")");
Modified: trunk/nhibernate/src/NHibernate/Criterion/InsensitiveLikeExpression.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Criterion/InsensitiveLikeExpression.cs 2011-05-31 17:08:07 UTC (rev 5899)
+++ trunk/nhibernate/src/NHibernate/Criterion/InsensitiveLikeExpression.cs 2011-05-31 17:46:14 UTC (rev 5900)
@@ -84,7 +84,7 @@
.Add(" like ");
}
- sqlBuilder.AddParameter();
+ sqlBuilder.Add(criteriaQuery.NewQueryParameter());
return sqlBuilder.ToSqlString();
}
Modified: trunk/nhibernate/src/NHibernate/Criterion/LikeExpression.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Criterion/LikeExpression.cs 2011-05-31 17:08:07 UTC (rev 5899)
+++ trunk/nhibernate/src/NHibernate/Criterion/LikeExpression.cs 2011-05-31 17:46:14 UTC (rev 5900)
@@ -79,11 +79,11 @@
lhs.Add(" like ")
.Add(dialect.LowercaseFunction)
.Add(StringHelper.OpenParen)
- .AddParameter()
+ .Add(criteriaQuery.NewQueryParameter())
.Add(StringHelper.ClosedParen);
}
else
- lhs.Add(" like ").AddParameter();
+ lhs.Add(" like ").Add(criteriaQuery.NewQueryParameter());
if (escapeChar.HasValue)
lhs.Add(" escape '" + escapeChar + "'");
Modified: trunk/nhibernate/src/NHibernate/Criterion/SimpleExpression.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Criterion/SimpleExpression.cs 2011-05-31 17:08:07 UTC (rev 5899)
+++ trunk/nhibernate/src/NHibernate/Criterion/SimpleExpression.cs 2011-05-31 17:46:14 UTC (rev 5900)
@@ -101,7 +101,7 @@
.Add(columnNames[0])
.Add(StringHelper.ClosedParen)
.Add(Op)
- .AddParameter()
+ .Add(criteriaQuery.NewQueryParameter())
.ToSqlString();
}
else
@@ -117,7 +117,7 @@
sqlBuilder.Add(columnNames[i])
.Add(Op)
- .AddParameter();
+ .Add(criteriaQuery.NewQueryParameter());
}
return sqlBuilder.ToSqlString();
}
Modified: trunk/nhibernate/src/NHibernate/Loader/Criteria/CriteriaQueryTranslator.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Loader/Criteria/CriteriaQueryTranslator.cs 2011-05-31 17:08:07 UTC (rev 5899)
+++ trunk/nhibernate/src/NHibernate/Loader/Criteria/CriteriaQueryTranslator.cs 2011-05-31 17:46:14 UTC (rev 5900)
@@ -772,6 +772,11 @@
return indexForAlias++;
}
+ public Parameter NewQueryParameter()
+ {
+ return Parameter.Placeholder;
+ }
+
public int? CreatePagingParameter(int value)
{
if (!Factory.Dialect.SupportsVariableLimit)
Modified: trunk/nhibernate/src/NHibernate/SqlCommand/SqlStringBuilder.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/SqlCommand/SqlStringBuilder.cs 2011-05-31 17:08:07 UTC (rev 5899)
+++ trunk/nhibernate/src/NHibernate/SqlCommand/SqlStringBuilder.cs 2011-05-31 17:46:14 UTC (rev 5900)
@@ -110,11 +110,6 @@
return Add(Parameter.Placeholder);
}
- public SqlStringBuilder AddParameter(int position)
- {
- return Add(Parameter.WithIndex(position));
- }
-
/// <summary>
/// Attempts to discover what type of object this is and calls the appropriate
/// method.
Modified: trunk/nhibernate/src/NHibernate.Test/Criteria/AddNumberProjection.cs
===================================================================
--- trunk/nhibernate/src/NHibernate.Test/Criteria/AddNumberProjection.cs 2011-05-31 17:08:07 UTC (rev 5899)
+++ trunk/nhibernate/src/NHibernate.Test/Criteria/AddNumberProjection.cs 2011-05-31 17:46:14 UTC (rev 5900)
@@ -31,7 +31,7 @@
.Add("(")
.Add(projection[0])
.Add(" + ")
- .AddParameter()
+ .Add(criteriaQuery.NewQueryParameter())
.Add(") as ")
.Add(GetColumnAliases(0)[0])
.ToSqlString();
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <fab...@us...> - 2011-05-31 19:56:35
|
Revision: 5901
http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5901&view=rev
Author: fabiomaulo
Date: 2011-05-31 19:56:28 +0000 (Tue, 31 May 2011)
Log Message:
-----------
usage of IParameterSpecification for Criteria (step 2)
Modified Paths:
--------------
trunk/nhibernate/src/NHibernate/Criterion/BetweenExpression.cs
trunk/nhibernate/src/NHibernate/Criterion/ConstantProjection.cs
trunk/nhibernate/src/NHibernate/Criterion/ICriteriaQuery.cs
trunk/nhibernate/src/NHibernate/Criterion/IdentifierEqExpression.cs
trunk/nhibernate/src/NHibernate/Criterion/InExpression.cs
trunk/nhibernate/src/NHibernate/Criterion/InsensitiveLikeExpression.cs
trunk/nhibernate/src/NHibernate/Criterion/LikeExpression.cs
trunk/nhibernate/src/NHibernate/Criterion/SimpleExpression.cs
trunk/nhibernate/src/NHibernate/Loader/Criteria/CriteriaQueryTranslator.cs
trunk/nhibernate/src/NHibernate/NHibernate.csproj
trunk/nhibernate/src/NHibernate.Test/Criteria/AddNumberProjection.cs
Added Paths:
-----------
trunk/nhibernate/src/NHibernate/Param/CriteriaNamedParameterSpecification.cs
Modified: trunk/nhibernate/src/NHibernate/Criterion/BetweenExpression.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Criterion/BetweenExpression.cs 2011-05-31 17:46:14 UTC (rev 5900)
+++ trunk/nhibernate/src/NHibernate/Criterion/BetweenExpression.cs 2011-05-31 19:56:28 UTC (rev 5901)
@@ -1,7 +1,9 @@
using System;
using System.Collections.Generic;
+using System.Linq;
using NHibernate.Engine;
using NHibernate.SqlCommand;
+using NHibernate.Type;
namespace NHibernate.Criterion
{
@@ -49,7 +51,9 @@
//TODO: add a default capacity
SqlStringBuilder sqlBuilder = new SqlStringBuilder();
- //IType propertyType = criteriaQuery.GetTypeUsingProjection( criteria, _propertyName );
+ IType[] parametersTypes = GetTypedValues(criteria, criteriaQuery).Select(x=> x.Type).ToArray();
+ IType lowType = parametersTypes[0];
+ IType highType = parametersTypes[1];
SqlString[] columnNames =
CriterionUtil.GetColumnNames(_propertyName, _projection, criteriaQuery, criteria, enabledFilters);
@@ -58,14 +62,15 @@
sqlBuilder
.Add(columnNames[0])
.Add(" between ")
- .Add(criteriaQuery.NewQueryParameter())
+ .Add(criteriaQuery.NewQueryParameter(lowType).Single())
.Add(" and ")
- .Add(criteriaQuery.NewQueryParameter());
+ .Add(criteriaQuery.NewQueryParameter(highType).Single());
}
else
{
bool andNeeded = false;
+ var lowParameters = criteriaQuery.NewQueryParameter(lowType).ToArray();
for (int i = 0; i < columnNames.Length; i++)
{
if (andNeeded)
@@ -76,15 +81,16 @@
sqlBuilder.Add(columnNames[i])
.Add(" >= ")
- .Add(criteriaQuery.NewQueryParameter());
+ .Add(lowParameters[i]);
}
+ var highParameters = criteriaQuery.NewQueryParameter(highType).ToArray();
for (int i = 0; i < columnNames.Length; i++)
{
sqlBuilder.Add(" AND ")
.Add(columnNames[i])
.Add(" <= ")
- .Add(criteriaQuery.NewQueryParameter());
+ .Add(highParameters[i]);
}
}
Modified: trunk/nhibernate/src/NHibernate/Criterion/ConstantProjection.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Criterion/ConstantProjection.cs 2011-05-31 17:46:14 UTC (rev 5900)
+++ trunk/nhibernate/src/NHibernate/Criterion/ConstantProjection.cs 2011-05-31 19:56:28 UTC (rev 5901)
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Linq;
using NHibernate.Engine;
using NHibernate.SqlCommand;
using NHibernate.Type;
@@ -43,7 +44,7 @@
public override SqlString ToSqlString(ICriteria criteria, int position, ICriteriaQuery criteriaQuery, IDictionary<string, IFilter> enabledFilters)
{
return new SqlStringBuilder()
- .Add(criteriaQuery.NewQueryParameter())
+ .Add(criteriaQuery.NewQueryParameter(type).Single())
.Add(" as ")
.Add(GetColumnAliases(position)[0])
.ToSqlString();
Modified: trunk/nhibernate/src/NHibernate/Criterion/ICriteriaQuery.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Criterion/ICriteriaQuery.cs 2011-05-31 17:46:14 UTC (rev 5900)
+++ trunk/nhibernate/src/NHibernate/Criterion/ICriteriaQuery.cs 2011-05-31 19:56:28 UTC (rev 5901)
@@ -1,6 +1,5 @@
using System.Collections.Generic;
using NHibernate.Engine;
-using NHibernate.Param;
using NHibernate.SqlCommand;
using NHibernate.Type;
@@ -72,8 +71,9 @@
/// <summary>
/// Create a new query parameter to use in a <see cref="ICriterion"/>
/// </summary>
+ /// <param name="parameterType">The expected type of the parameter.</param>
/// <returns>A new instance of a query parameter to be added to a <see cref="SqlString"/>.</returns>
- Parameter NewQueryParameter();
+ IEnumerable<Parameter> NewQueryParameter(IType parameterType);
/// <summary>
/// Creates a dummy parameter index for the supplied paged value.
Modified: trunk/nhibernate/src/NHibernate/Criterion/IdentifierEqExpression.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Criterion/IdentifierEqExpression.cs 2011-05-31 17:46:14 UTC (rev 5900)
+++ trunk/nhibernate/src/NHibernate/Criterion/IdentifierEqExpression.cs 2011-05-31 19:56:28 UTC (rev 5901)
@@ -1,7 +1,9 @@
using System;
using System.Collections.Generic;
+using System.Linq;
using NHibernate.Engine;
using NHibernate.SqlCommand;
+using NHibernate.Type;
using NHibernate.Util;
namespace NHibernate.Criterion
@@ -32,6 +34,8 @@
{
//Implementation changed from H3.2 to use SqlString
string[] columns = criteriaQuery.GetIdentifierColumns(criteria);
+ Parameter[] parameters = GetTypedValues(criteria, criteriaQuery).Select(x => x.Type).SelectMany(t => criteriaQuery.NewQueryParameter(t)).ToArray();
+
SqlStringBuilder result = new SqlStringBuilder(4 * columns.Length + 2);
if (columns.Length > 1)
{
@@ -48,7 +52,7 @@
result.Add(columns[i])
.Add(" = ");
- AddValueOrProjection(criteria, criteriaQuery, enabledFilters, result);
+ AddValueOrProjection(parameters, i, criteria, criteriaQuery, enabledFilters, result);
}
if (columns.Length > 1)
@@ -58,15 +62,15 @@
return result.ToSqlString();
}
- private void AddValueOrProjection(ICriteria criteria, ICriteriaQuery criteriaQuery, IDictionary<string, IFilter> enabledFilters, SqlStringBuilder result)
+ private void AddValueOrProjection(Parameter[] parameters, int paramIndex, ICriteria criteria, ICriteriaQuery criteriaQuery, IDictionary<string, IFilter> enabledFilters, SqlStringBuilder result)
{
if (_projection == null)
{
- result.Add(criteriaQuery.NewQueryParameter());
+ result.Add(parameters[paramIndex]);
}
else
{
- SqlString sql = _projection.ToSqlString(criteria, GetHashCode(),criteriaQuery, enabledFilters);
+ SqlString sql = _projection.ToSqlString(criteria, GetHashCode(), criteriaQuery, enabledFilters);
result.Add(StringHelper.RemoveAsAliasesFromSql(sql));
}
}
Modified: trunk/nhibernate/src/NHibernate/Criterion/InExpression.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Criterion/InExpression.cs 2011-05-31 17:46:14 UTC (rev 5900)
+++ trunk/nhibernate/src/NHibernate/Criterion/InExpression.cs 2011-05-31 19:56:28 UTC (rev 5901)
@@ -1,6 +1,7 @@
using System;
using System.Collections;
using System.Collections.Generic;
+using System.Linq;
using NHibernate.Engine;
using NHibernate.SqlCommand;
using NHibernate.Type;
@@ -68,6 +69,7 @@
// Generate SqlString of the form:
// columnName1 in (values) and columnName2 in (values) and ...
+ Parameter[] parameters = GetTypedValues(criteria, criteriaQuery).Select(x => x.Type).SelectMany(t => criteriaQuery.NewQueryParameter(t)).ToArray();
for (int columnIndex = 0; columnIndex < columnNames.Length; columnIndex++)
{
@@ -88,7 +90,7 @@
{
result.Add(StringHelper.CommaSpace);
}
- result.Add(criteriaQuery.NewQueryParameter());
+ result.Add(parameters[i]);
}
result.Add(")");
Modified: trunk/nhibernate/src/NHibernate/Criterion/InsensitiveLikeExpression.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Criterion/InsensitiveLikeExpression.cs 2011-05-31 17:46:14 UTC (rev 5900)
+++ trunk/nhibernate/src/NHibernate/Criterion/InsensitiveLikeExpression.cs 2011-05-31 19:56:28 UTC (rev 5901)
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Linq;
using NHibernate.Dialect;
using NHibernate.Engine;
using NHibernate.SqlCommand;
@@ -84,7 +85,7 @@
.Add(" like ");
}
- sqlBuilder.Add(criteriaQuery.NewQueryParameter());
+ sqlBuilder.Add(criteriaQuery.NewQueryParameter(NHibernateUtil.String).Single());
return sqlBuilder.ToSqlString();
}
Modified: trunk/nhibernate/src/NHibernate/Criterion/LikeExpression.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Criterion/LikeExpression.cs 2011-05-31 17:46:14 UTC (rev 5900)
+++ trunk/nhibernate/src/NHibernate/Criterion/LikeExpression.cs 2011-05-31 19:56:28 UTC (rev 5901)
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Linq;
using NHibernate.Engine;
using NHibernate.SqlCommand;
using NHibernate.Util;
@@ -79,11 +80,11 @@
lhs.Add(" like ")
.Add(dialect.LowercaseFunction)
.Add(StringHelper.OpenParen)
- .Add(criteriaQuery.NewQueryParameter())
+ .Add(criteriaQuery.NewQueryParameter(NHibernateUtil.String).Single())
.Add(StringHelper.ClosedParen);
}
else
- lhs.Add(" like ").Add(criteriaQuery.NewQueryParameter());
+ lhs.Add(" like ").Add(criteriaQuery.NewQueryParameter(NHibernateUtil.String).Single());
if (escapeChar.HasValue)
lhs.Add(" escape '" + escapeChar + "'");
Modified: trunk/nhibernate/src/NHibernate/Criterion/SimpleExpression.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Criterion/SimpleExpression.cs 2011-05-31 17:46:14 UTC (rev 5900)
+++ trunk/nhibernate/src/NHibernate/Criterion/SimpleExpression.cs 2011-05-31 19:56:28 UTC (rev 5901)
@@ -1,7 +1,9 @@
using System;
using System.Collections.Generic;
+using System.Linq;
using NHibernate.Engine;
using NHibernate.SqlCommand;
+using NHibernate.Type;
using NHibernate.Util;
namespace NHibernate.Criterion
@@ -86,6 +88,8 @@
this,
value);
+ Parameter[] parameters = GetTypedValues(criteria, criteriaQuery).Select(x => x.Type).SelectMany(t => criteriaQuery.NewQueryParameter(t)).ToArray();
+
if (ignoreCase)
{
if (columnNames.Length != 1)
@@ -101,7 +105,7 @@
.Add(columnNames[0])
.Add(StringHelper.ClosedParen)
.Add(Op)
- .Add(criteriaQuery.NewQueryParameter())
+ .Add(parameters.FirstOrDefault())
.ToSqlString();
}
else
@@ -117,7 +121,7 @@
sqlBuilder.Add(columnNames[i])
.Add(Op)
- .Add(criteriaQuery.NewQueryParameter());
+ .Add(parameters[i]);
}
return sqlBuilder.ToSqlString();
}
Modified: trunk/nhibernate/src/NHibernate/Loader/Criteria/CriteriaQueryTranslator.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Loader/Criteria/CriteriaQueryTranslator.cs 2011-05-31 17:46:14 UTC (rev 5900)
+++ trunk/nhibernate/src/NHibernate/Loader/Criteria/CriteriaQueryTranslator.cs 2011-05-31 19:56:28 UTC (rev 5901)
@@ -8,6 +8,7 @@
using NHibernate.Engine;
using NHibernate.Hql.Util;
using NHibernate.Impl;
+using NHibernate.Param;
using NHibernate.Persister.Collection;
using NHibernate_Persister_Entity = NHibernate.Persister.Entity;
using NHibernate.SqlCommand;
@@ -19,10 +20,10 @@
public class CriteriaQueryTranslator : ICriteriaQuery
{
public static readonly string RootSqlAlias = CriteriaSpecification.RootAlias + '_';
-
private static readonly IInternalLogger logger = LoggerProvider.LoggerFor(typeof(CriteriaQueryTranslator));
private const int AliasCount = 0;
+ private readonly string queryTranslatorId = Guid.NewGuid().ToString("N");
private readonly ICriteriaQuery outerQueryTranslator;
private readonly CriteriaImpl rootCriteria;
@@ -44,6 +45,7 @@
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 IList<IParameterSpecification> collectedParameterSpecifications = new List<IParameterSpecification>();
private readonly ISessionFactoryImplementor sessionFactory;
private SessionFactoryHelper helper;
@@ -772,9 +774,18 @@
return indexForAlias++;
}
- public Parameter NewQueryParameter()
+ public IEnumerable<Parameter> NewQueryParameter(IType parameterType)
{
- return Parameter.Placeholder;
+ // the queryTranslatorId is to avoid possible conflicts using sub-queries
+ string parameterName = string.Format("cr_{0}_p{1}", queryTranslatorId, collectedParameterSpecifications.Count);
+ var specification = new CriteriaNamedParameterSpecification(parameterName, parameterType);
+ collectedParameterSpecifications.Add(specification);
+ return specification.GetIdsForBackTrack(Factory).Select(x =>
+ {
+ Parameter p = Parameter.Placeholder;
+ p.BackTrack = x;
+ return p;
+ });
}
public int? CreatePagingParameter(int value)
Modified: trunk/nhibernate/src/NHibernate/NHibernate.csproj
===================================================================
--- trunk/nhibernate/src/NHibernate/NHibernate.csproj 2011-05-31 17:46:14 UTC (rev 5900)
+++ trunk/nhibernate/src/NHibernate/NHibernate.csproj 2011-05-31 19:56:28 UTC (rev 5901)
@@ -496,6 +496,7 @@
<Compile Include="NonUniqueResultException.cs" />
<Compile Include="ObjectDeletedException.cs" />
<Compile Include="ObjectNotFoundException.cs" />
+ <Compile Include="Param\CriteriaNamedParameterSpecification.cs" />
<Compile Include="Param\ParametersBackTrackExtensions.cs" />
<Compile Include="Param\QuerySkipParameterSpecification.cs" />
<Compile Include="Param\QueryTakeParameterSpecification.cs" />
Added: trunk/nhibernate/src/NHibernate/Param/CriteriaNamedParameterSpecification.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Param/CriteriaNamedParameterSpecification.cs (rev 0)
+++ trunk/nhibernate/src/NHibernate/Param/CriteriaNamedParameterSpecification.cs 2011-05-31 19:56:28 UTC (rev 5901)
@@ -0,0 +1,85 @@
+using System;
+using System.Collections.Generic;
+using System.Data;
+using System.Linq;
+using NHibernate.Engine;
+using NHibernate.SqlCommand;
+using NHibernate.Type;
+
+namespace NHibernate.Param
+{
+ public class CriteriaNamedParameterSpecification : IParameterSpecification
+ {
+ private const string CriteriaNamedParameterIdTemplate = "<criteria-nh{0}_span{1}>";
+ private readonly string name;
+
+ public CriteriaNamedParameterSpecification(string name, IType expectedType)
+ {
+ this.name = name;
+ ExpectedType = expectedType;
+ }
+
+ #region IParameterSpecification Members
+
+ public void Bind(IDbCommand command, IList<Parameter> sqlQueryParametersList, QueryParameters queryParameters, ISessionImplementor session)
+ {
+ TypedValue typedValue = queryParameters.NamedParameters[name];
+ string backTrackId = GetIdsForBackTrack(session.Factory).First();
+ foreach (int position in sqlQueryParametersList.GetEffectiveParameterLocations(backTrackId))
+ {
+ ExpectedType.NullSafeSet(command, typedValue.Value, position, session);
+ }
+ }
+
+ public IType ExpectedType { get; set; }
+
+ public string RenderDisplayInfo()
+ {
+ const string format = "criteria: parameter-name={0}, expectedType={1}";
+ return ExpectedType != null ? string.Format(format, name, ExpectedType) : string.Format(format, name, "Unknow");
+ }
+
+ public IEnumerable<string> GetIdsForBackTrack(IMapping sessionFactory)
+ {
+ int paremeterSpan = GetParemeterSpan(sessionFactory);
+ for (int i = 0; i < paremeterSpan; i++)
+ {
+ yield return string.Format(CriteriaNamedParameterIdTemplate, name, i);
+ }
+ }
+
+ #endregion
+
+ protected int GetParemeterSpan(IMapping sessionFactory)
+ {
+ if (sessionFactory == null)
+ {
+ throw new ArgumentNullException("sessionFactory");
+ }
+ return ExpectedType.GetColumnSpan(sessionFactory);
+ }
+
+ public override bool Equals(object obj)
+ {
+ return base.Equals(obj as CriteriaNamedParameterSpecification);
+ }
+
+ public bool Equals(CriteriaNamedParameterSpecification other)
+ {
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+ return Equals(other.name, name);
+ }
+
+ public override int GetHashCode()
+ {
+ return name.GetHashCode() ^ 211;
+ }
+ }
+}
\ No newline at end of file
Modified: trunk/nhibernate/src/NHibernate.Test/Criteria/AddNumberProjection.cs
===================================================================
--- trunk/nhibernate/src/NHibernate.Test/Criteria/AddNumberProjection.cs 2011-05-31 17:46:14 UTC (rev 5900)
+++ trunk/nhibernate/src/NHibernate.Test/Criteria/AddNumberProjection.cs 2011-05-31 19:56:28 UTC (rev 5901)
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Linq;
using NHibernate.Engine;
using NHibernate.Criterion;
using NHibernate.SqlCommand;
@@ -31,7 +32,7 @@
.Add("(")
.Add(projection[0])
.Add(" + ")
- .Add(criteriaQuery.NewQueryParameter())
+ .Add(criteriaQuery.NewQueryParameter(NHibernateUtil.Int32).Single())
.Add(") as ")
.Add(GetColumnAliases(0)[0])
.ToSqlString();
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ric...@us...> - 2011-06-04 14:14:45
|
Revision: 5905
http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5905&view=rev
Author: ricbrown
Date: 2011-06-04 14:14:38 +0000 (Sat, 04 Jun 2011)
Log Message:
-----------
NH-2683: Added QueryOver functions to property comparisons
Modified Paths:
--------------
trunk/nhibernate/src/NHibernate/Impl/ExpressionProcessor.cs
trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/IntegrationFixture.cs
trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/QueryOverFixture.cs
trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/RestrictionsFixture.cs
Modified: trunk/nhibernate/src/NHibernate/Impl/ExpressionProcessor.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Impl/ExpressionProcessor.cs 2011-06-04 05:53:30 UTC (rev 5904)
+++ trunk/nhibernate/src/NHibernate/Impl/ExpressionProcessor.cs 2011-06-04 14:14:38 UTC (rev 5905)
@@ -32,7 +32,7 @@
{
private readonly static IDictionary<ExpressionType, Func<IProjection, object, ICriterion>> _simpleExpressionCreators = null;
- private readonly static IDictionary<ExpressionType, Func<string, string, ICriterion>> _propertyExpressionCreators = null;
+ private readonly static IDictionary<ExpressionType, Func<IProjection, IProjection, ICriterion>> _propertyExpressionCreators = null;
private readonly static IDictionary<LambdaSubqueryType, IDictionary<ExpressionType, Func<string, DetachedCriteria, AbstractCriterion>>> _subqueryExpressionCreatorTypes = null;
private readonly static IDictionary<string, Func<MethodCallExpression, ICriterion>> _customMethodCallProcessors = null;
private readonly static IDictionary<string, Func<MethodCallExpression, IProjection>> _customProjectionProcessors = null;
@@ -47,7 +47,7 @@
_simpleExpressionCreators[ExpressionType.LessThan] = Lt;
_simpleExpressionCreators[ExpressionType.LessThanOrEqual] = Le;
- _propertyExpressionCreators = new Dictionary<ExpressionType, Func<string, string, ICriterion>>();
+ _propertyExpressionCreators = new Dictionary<ExpressionType, Func<IProjection, IProjection, ICriterion>>();
_propertyExpressionCreators[ExpressionType.Equal] = Restrictions.EqProperty;
_propertyExpressionCreators[ExpressionType.NotEqual] = Restrictions.NotEqProperty;
_propertyExpressionCreators[ExpressionType.GreaterThan] = Restrictions.GtProperty;
@@ -465,13 +465,13 @@
private static ICriterion ProcessMemberExpression(Expression left, Expression right, ExpressionType nodeType)
{
- string leftProperty = FindMemberExpression(left);
- string rightProperty = FindMemberExpression(right);
+ IProjection leftProperty = FindMemberProjection(left);
+ IProjection rightProperty = FindMemberProjection(right);
if (!_propertyExpressionCreators.ContainsKey(nodeType))
throw new Exception("Unhandled property expression type: " + nodeType);
- Func<string, string, ICriterion> propertyExpressionCreator = _propertyExpressionCreators[nodeType];
+ Func<IProjection, IProjection, ICriterion> propertyExpressionCreator = _propertyExpressionCreators[nodeType];
ICriterion criterion = propertyExpressionCreator(leftProperty, rightProperty);
return criterion;
}
Modified: trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/IntegrationFixture.cs
===================================================================
--- trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/IntegrationFixture.cs 2011-06-04 05:53:30 UTC (rev 5904)
+++ trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/IntegrationFixture.cs 2011-06-04 14:14:38 UTC (rev 5905)
@@ -664,6 +664,31 @@
}
[Test]
+ public void FunctionsProperty()
+ {
+ using (ISession s = OpenSession())
+ using (ITransaction t = s.BeginTransaction())
+ {
+ s.Save(new Person() { Name = "p1", BirthDate = new DateTime(2009, 08, 07) });
+ s.Save(new Person() { Name = "p2", BirthDate = new DateTime(2008, 07, 07) });
+ s.Save(new Person() { Name = "p3", BirthDate = new DateTime(2007, 06, 07) });
+
+ t.Commit();
+ }
+
+ using (ISession s = OpenSession())
+ {
+ var persons =
+ s.QueryOver<Person>()
+ .Where(p => p.BirthDate.MonthPart() == p.BirthDate.DayPart())
+ .List();
+
+ persons.Count.Should().Be(1);
+ persons[0].Name.Should().Be("p2");
+ }
+ }
+
+ [Test]
public void FunctionsOrder()
{
using (ISession s = OpenSession())
Modified: trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/QueryOverFixture.cs
===================================================================
--- trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/QueryOverFixture.cs 2011-06-04 05:53:30 UTC (rev 5904)
+++ trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/QueryOverFixture.cs 2011-06-04 14:14:38 UTC (rev 5905)
@@ -61,12 +61,12 @@
.Add(Restrictions.Ge(Projections.Property("Name"), "test name"))
.Add(Restrictions.Lt(Projections.Property("Name"), "test name"))
.Add(Restrictions.Le(Projections.Property("Name"), "test name"))
- .Add(Restrictions.EqProperty("Name", "Name"))
- .Add(Restrictions.Not(Restrictions.EqProperty("Name", "Name")))
- .Add(Restrictions.GtProperty("Name", "Name"))
- .Add(Restrictions.GeProperty("Name", "Name"))
- .Add(Restrictions.LtProperty("Name", "Name"))
- .Add(Restrictions.LeProperty("Name", "Name"));
+ .Add(Restrictions.EqProperty(Projections.Property("Name"), Projections.Property("Name")))
+ .Add(Restrictions.Not(Restrictions.EqProperty(Projections.Property("Name"), Projections.Property("Name"))))
+ .Add(Restrictions.GtProperty(Projections.Property("Name"), Projections.Property("Name")))
+ .Add(Restrictions.GeProperty(Projections.Property("Name"), Projections.Property("Name")))
+ .Add(Restrictions.LtProperty(Projections.Property("Name"), Projections.Property("Name")))
+ .Add(Restrictions.LeProperty(Projections.Property("Name"), Projections.Property("Name")));
IQueryOver<Person> actual =
CreateTestQueryOver<Person>()
@@ -91,12 +91,12 @@
{
ICriteria expected =
CreateTestCriteria(typeof(Person))
- .Add(Restrictions.EqProperty("Age", "Height"))
- .Add(Restrictions.NotEqProperty("Age", "Height"))
- .Add(Restrictions.GtProperty("Age", "Height"))
- .Add(Restrictions.GeProperty("Age", "Height"))
- .Add(Restrictions.LtProperty("Age", "Height"))
- .Add(Restrictions.LeProperty("Age", "Height"));
+ .Add(Restrictions.EqProperty(Projections.Property("Age"), Projections.Property("Height")))
+ .Add(Restrictions.NotEqProperty(Projections.Property("Age"), Projections.Property("Height")))
+ .Add(Restrictions.GtProperty(Projections.Property("Age"), Projections.Property("Height")))
+ .Add(Restrictions.GeProperty(Projections.Property("Age"), Projections.Property("Height")))
+ .Add(Restrictions.LtProperty(Projections.Property("Age"), Projections.Property("Height")))
+ .Add(Restrictions.LeProperty(Projections.Property("Age"), Projections.Property("Height")));
IQueryOver<Person> actual =
CreateTestQueryOver<Person>()
Modified: trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/RestrictionsFixture.cs
===================================================================
--- trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/RestrictionsFixture.cs 2011-06-04 05:53:30 UTC (rev 5904)
+++ trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/RestrictionsFixture.cs 2011-06-04 14:14:38 UTC (rev 5905)
@@ -305,6 +305,22 @@
AssertCriteriaAreEqual(expected, actual);
}
+ [Test]
+ public void FunctionExtensionsProperty()
+ {
+ ICriteria expected =
+ CreateTestCriteria(typeof(Person))
+ .Add(Restrictions.EqProperty(
+ Projections.SqlFunction("month", NHibernateUtil.Int32, Projections.Property("BirthDate")),
+ Projections.SqlFunction("day", NHibernateUtil.Int32, Projections.Property("BirthDate"))));
+
+ IQueryOver<Person> actual =
+ CreateTestQueryOver<Person>()
+ .Where(p => p.BirthDate.MonthPart() == p.BirthDate.DayPart());
+
+ AssertCriteriaAreEqual(expected, actual);
+ }
+
}
}
\ No newline at end of file
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ric...@us...> - 2011-06-04 19:19:19
|
Revision: 5908
http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5908&view=rev
Author: ricbrown
Date: 2011-06-04 19:19:12 +0000 (Sat, 04 Jun 2011)
Log Message:
-----------
NH-2662: Casting a joined alias in QueryOver loses alias context and looks for property on QueryOver root
Modified Paths:
--------------
trunk/nhibernate/src/NHibernate/Impl/ExpressionProcessor.cs
trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/ExpressionProcessorFixture.cs
trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/Model.cs
trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj
Added Paths:
-----------
trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2662/
trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2662/Domain.cs
trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2662/Fixture.cs
trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2662/Mappings.hbm.xml
Modified: trunk/nhibernate/src/NHibernate/Impl/ExpressionProcessor.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Impl/ExpressionProcessor.cs 2011-06-04 15:54:40 UTC (rev 5907)
+++ trunk/nhibernate/src/NHibernate/Impl/ExpressionProcessor.cs 2011-06-04 19:19:12 UTC (rev 5908)
@@ -212,6 +212,10 @@
return FindMemberExpression(memberExpression.Expression) + "." + memberExpression.Member.Name;
}
+ else if (memberExpression.Expression.NodeType == ExpressionType.Convert)
+ {
+ return (FindMemberExpression(memberExpression.Expression) + "." + memberExpression.Member.Name).TrimStart('.');
+ }
else
{
return memberExpression.Member.Name;
@@ -244,6 +248,9 @@
throw new Exception("Unrecognised method call in expression " + expression.ToString());
}
+ if (expression is ParameterExpression)
+ return "";
+
throw new Exception("Could not determine member from " + expression.ToString());
}
@@ -322,26 +329,11 @@
if (memberExpression.Expression == null)
return false; // it's a member of a static class
- if (memberExpression.Expression.NodeType == ExpressionType.Parameter)
+ if (IsMemberExpression(memberExpression.Expression))
return true;
- if (IsNullableOfT(memberExpression.Member.DeclaringType))
- {
- // it's a Nullable<T>, so ignore any .Value
- if (memberExpression.Member.Name == "Value")
- return IsMemberExpression(memberExpression.Expression);
- }
-
- if (memberExpression.Expression.NodeType == ExpressionType.MemberAccess)
- {
- if (IsMemberExpression(memberExpression.Expression))
- return true;
-
- // if the member has a null value, it was an alias
- return EvaluatesToNull(memberExpression.Expression);
- }
-
- return IsMemberExpression(memberExpression.Expression);
+ // if the member has a null value, it was an alias
+ return EvaluatesToNull(memberExpression.Expression);
}
if (expression is UnaryExpression)
Modified: trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/ExpressionProcessorFixture.cs
===================================================================
--- trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/ExpressionProcessorFixture.cs 2011-06-04 15:54:40 UTC (rev 5907)
+++ trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/ExpressionProcessorFixture.cs 2011-06-04 19:19:12 UTC (rev 5908)
@@ -25,6 +25,14 @@
}
[Test]
+ public void TestFindMemberExpressionReferenceCast()
+ {
+ Expression<Func<Person, string>> e = (Person p) => ((CustomPerson)p).MiddleName;
+ string property = ExpressionProcessor.FindMemberProjection(e.Body).ToString();
+ Assert.AreEqual("MiddleName", property);
+ }
+
+ [Test]
public void TestFindMemberExpressionReferenceAlias()
{
Person personAlias = null;
@@ -34,6 +42,15 @@
}
[Test]
+ public void TestFindMemberExpressionReferenceCastAlias()
+ {
+ Person personAlias = null;
+ Expression<Func<string>> e = () => ((CustomPerson)personAlias).MiddleName;
+ string property = ExpressionProcessor.FindMemberProjection(e.Body).ToString();
+ Assert.AreEqual("personAlias.MiddleName", property);
+ }
+
+ [Test]
public void TestFindMemberExpressionComponent()
{
Expression<Func<Person, string>> e = (Person p) => p.Father.Name;
@@ -157,17 +174,19 @@
{
var children = new List<Child> { new Child { Nickname = "test nickname" } };
Person person =
- new Person()
+ new CustomPerson()
{
Name = "test name",
+ MiddleName = "test middle name",
NullableAge = 4,
Children = children,
};
Assert.That(Projection(() => person.Name), Is.EqualTo("test name"));
+ Assert.That(Projection(() => ((CustomPerson)person).MiddleName), Is.EqualTo("test middle name"));
Assert.That(Projection(() => "test name"), Is.EqualTo("test name"));
Assert.That(Projection(() => person.NullableAge.Value), Is.EqualTo(4));
- Assert.That(Projection(() => person.GetType()), Is.EqualTo(typeof(Person)));
+ Assert.That(Projection(() => person.GetType()), Is.EqualTo(typeof(CustomPerson)));
Assert.That(Projection(() => person.Children.First().Nickname), Is.EqualTo("test nickname"));
Assert.That(Projection(() => children[0].Nickname), Is.EqualTo("test nickname"));
}
Modified: trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/Model.cs
===================================================================
--- trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/Model.cs 2011-06-04 15:54:40 UTC (rev 5907)
+++ trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/Model.cs 2011-06-04 19:19:12 UTC (rev 5908)
@@ -50,7 +50,10 @@
}
- public class CustomPerson : Person { }
+ public class CustomPerson : Person
+ {
+ public virtual string MiddleName { get; set; }
+ }
public class Child
{
Property changes on: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2662
___________________________________________________________________
Added: bugtraq:url
+ http://jira.nhibernate.org/browse/%BUGID%
Added: bugtraq:number
+ true
Added: bugtraq:logregex
+ NH-\d+
Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2662/Domain.cs
===================================================================
--- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2662/Domain.cs (rev 0)
+++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2662/Domain.cs 2011-06-04 19:19:12 UTC (rev 5908)
@@ -0,0 +1,43 @@
+using System;
+using System.Collections.Generic;
+
+namespace NHibernate.Test.NHSpecificTest.NH2662
+{
+ public class Customer
+ {
+ public virtual Guid Id
+ {
+ get;
+ protected set;
+ }
+ public virtual Order Order
+ {
+ get;
+ set;
+ }
+ }
+
+ public class Order
+ {
+ public virtual Guid Id
+ {
+ get;
+ protected set;
+ }
+
+ public virtual DateTime OrderDate
+ {
+ get;
+ set;
+ }
+ }
+
+ public class PizzaOrder: Order
+ {
+ public virtual string PizzaName
+ {
+ get;
+ set;
+ }
+ }
+}
\ No newline at end of file
Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2662/Fixture.cs
===================================================================
--- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2662/Fixture.cs (rev 0)
+++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2662/Fixture.cs 2011-06-04 19:19:12 UTC (rev 5908)
@@ -0,0 +1,67 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using NHibernate.Linq;
+using NUnit.Framework;
+using SharpTestsEx;
+
+namespace NHibernate.Test.NHSpecificTest.NH2662
+{
+ public class Fixture : BugTestCase
+ {
+ [Test]
+ public void WhenCastAliasInQueryOverThenDoNotThrow()
+ {
+ using (var session = OpenSession())
+ using (var tx = session.BeginTransaction())
+ {
+ var customer = new Customer
+ {
+ Order = new PizzaOrder { OrderDate = DateTime.Now, PizzaName = "Margarita" }
+ };
+
+ var customer2 = new Customer
+ {
+ Order = new Order { OrderDate = DateTime.Now.AddDays(1) }
+ };
+
+ session.Save(customer);
+ session.Save(customer2);
+ session.Flush();
+
+ Executing.This(
+ () =>
+ {
+ var temp = session.Query<Customer>().Select(
+ c => new {c.Id, c.Order.OrderDate, ((PizzaOrder)c.Order).PizzaName })
+ .ToArray();
+
+ foreach (var item in temp) { Trace.WriteLine(item.PizzaName);}
+ })
+ .Should().NotThrow();
+
+ Executing.This(
+ () =>
+ {
+ Order orderAlias = null;
+
+ var results =
+ session.QueryOver<Customer>()
+ .Left.JoinAlias(o => o.Order, () => orderAlias)
+ .OrderBy(() => orderAlias.OrderDate).Asc
+ .SelectList(list =>
+ list
+ .Select(o => o.Id)
+ .Select(() => orderAlias.OrderDate)
+ .Select(() => ((PizzaOrder) orderAlias).PizzaName))
+ .List<object[]>();
+
+ Assert.That(results.Count, Is.EqualTo(2));
+ Assert.That(results[0][2], Is.EqualTo("Margarita"));
+
+ }).Should().NotThrow();
+ }
+ }
+ }
+}
\ No newline at end of file
Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2662/Mappings.hbm.xml
===================================================================
--- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2662/Mappings.hbm.xml (rev 0)
+++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2662/Mappings.hbm.xml 2011-06-04 19:19:12 UTC (rev 5908)
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
+ assembly="NHibernate.Test"
+ namespace="NHibernate.Test.NHSpecificTest.NH2662">
+
+ <class name="Customer">
+ <id name="Id">
+ <generator class="guid" />
+ </id>
+
+ <many-to-one name="Order" class="Order" column="OrderId" cascade="save-update" />
+
+ </class>
+
+ <class name="Order" table="Orders">
+ <id name="Id">
+ <generator class="guid" />
+ </id>
+
+ <property name="OrderDate" />
+
+ <joined-subclass name="PizzaOrder" table="Pizzas">
+ <key column="OrderId" />
+ <property name="PizzaName" />
+ </joined-subclass>
+
+ </class>
+
+</hibernate-mapping>
Modified: trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj
===================================================================
--- trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2011-06-04 15:54:40 UTC (rev 5907)
+++ trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2011-06-04 19:19:12 UTC (rev 5908)
@@ -847,6 +847,8 @@
<Compile Include="NHSpecificTest\NH2632\Fixture.cs" />
<Compile Include="NHSpecificTest\NH2660And2661\DomainClass.cs" />
<Compile Include="NHSpecificTest\NH2660And2661\Test.cs" />
+ <Compile Include="NHSpecificTest\NH2662\Domain.cs" />
+ <Compile Include="NHSpecificTest\NH2662\Fixture.cs" />
<Compile Include="NHSpecificTest\NH2673\Blog.cs" />
<Compile Include="NHSpecificTest\NH2673\CachingWithTrasformerTests.cs" />
<Compile Include="NHSpecificTest\NH2691\Domain.cs" />
@@ -2712,6 +2714,7 @@
<EmbeddedResource Include="NHSpecificTest\NH1291AnonExample\Mappings.hbm.xml" />
</ItemGroup>
<ItemGroup>
+ <EmbeddedResource Include="NHSpecificTest\NH2662\Mappings.hbm.xml" />
<EmbeddedResource Include="NHSpecificTest\NH2703\Mappings.hbm.xml" />
<EmbeddedResource Include="NHSpecificTest\NH2736\Mappings.hbm.xml" />
<EmbeddedResource Include="NHSpecificTest\NH2721\Mappings.hbm.xml" />
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <fab...@us...> - 2011-06-05 20:34:19
|
Revision: 5909
http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5909&view=rev
Author: fabiomaulo
Date: 2011-06-05 20:34:11 +0000 (Sun, 05 Jun 2011)
Log Message:
-----------
Tackable parameters for Criteria (broken some use case with Multi-Criteria)
Modified Paths:
--------------
trunk/nhibernate/src/NHibernate/Criterion/BetweenExpression.cs
trunk/nhibernate/src/NHibernate/Criterion/ConstantProjection.cs
trunk/nhibernate/src/NHibernate/Criterion/ICriteriaQuery.cs
trunk/nhibernate/src/NHibernate/Criterion/IdentifierEqExpression.cs
trunk/nhibernate/src/NHibernate/Criterion/InExpression.cs
trunk/nhibernate/src/NHibernate/Criterion/InsensitiveLikeExpression.cs
trunk/nhibernate/src/NHibernate/Criterion/LikeExpression.cs
trunk/nhibernate/src/NHibernate/Criterion/SQLCriterion.cs
trunk/nhibernate/src/NHibernate/Criterion/SimpleExpression.cs
trunk/nhibernate/src/NHibernate/Criterion/SimpleSubqueryExpression.cs
trunk/nhibernate/src/NHibernate/Criterion/SubqueryExpression.cs
trunk/nhibernate/src/NHibernate/Engine/QueryParameters.cs
trunk/nhibernate/src/NHibernate/Impl/MultiCriteriaImpl.cs
trunk/nhibernate/src/NHibernate/Linq/NhLinqExpression.cs
trunk/nhibernate/src/NHibernate/Linq/ParameterAggregator.cs
trunk/nhibernate/src/NHibernate/Linq/Visitors/ExpressionKeyVisitor.cs
trunk/nhibernate/src/NHibernate/Linq/Visitors/ExpressionParameterVisitor.cs
trunk/nhibernate/src/NHibernate/Linq/Visitors/HqlGeneratorExpressionTreeVisitor.cs
trunk/nhibernate/src/NHibernate/Linq/Visitors/ResultOperatorProcessors/ProcessCacheable.cs
trunk/nhibernate/src/NHibernate/Linq/Visitors/ResultOperatorProcessors/ProcessSkip.cs
trunk/nhibernate/src/NHibernate/Linq/Visitors/ResultOperatorProcessors/ProcessTake.cs
trunk/nhibernate/src/NHibernate/Linq/Visitors/VisitorParameters.cs
trunk/nhibernate/src/NHibernate/Loader/Criteria/CriteriaLoader.cs
trunk/nhibernate/src/NHibernate/Loader/Criteria/CriteriaQueryTranslator.cs
trunk/nhibernate/src/NHibernate/NHibernate.csproj
trunk/nhibernate/src/NHibernate/Param/CriteriaNamedParameterSpecification.cs
trunk/nhibernate/src/NHibernate.Test/Criteria/AddNumberProjection.cs
trunk/nhibernate/src/NHibernate.Test/Pagination/CustomDialectFixture.cs
trunk/nhibernate/src/NHibernate.Test/Pagination/CustomMsSqlDriver.cs
trunk/nhibernate/src/NHibernate.Test/ProjectionFixtures/Fixture.cs
Added Paths:
-----------
trunk/nhibernate/src/NHibernate/Param/NamedParameter.cs
Removed Paths:
-------------
trunk/nhibernate/src/NHibernate/Linq/NamedParameter.cs
Modified: trunk/nhibernate/src/NHibernate/Criterion/BetweenExpression.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Criterion/BetweenExpression.cs 2011-06-04 19:19:12 UTC (rev 5908)
+++ trunk/nhibernate/src/NHibernate/Criterion/BetweenExpression.cs 2011-06-05 20:34:11 UTC (rev 5909)
@@ -51,9 +51,9 @@
//TODO: add a default capacity
SqlStringBuilder sqlBuilder = new SqlStringBuilder();
- IType[] parametersTypes = GetTypedValues(criteria, criteriaQuery).Select(x=> x.Type).ToArray();
- IType lowType = parametersTypes[0];
- IType highType = parametersTypes[1];
+ var parametersTypes = GetTypedValues(criteria, criteriaQuery).ToArray();
+ var lowType = parametersTypes[0];
+ var highType = parametersTypes[1];
SqlString[] columnNames =
CriterionUtil.GetColumnNames(_propertyName, _projection, criteriaQuery, criteria, enabledFilters);
Modified: trunk/nhibernate/src/NHibernate/Criterion/ConstantProjection.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Criterion/ConstantProjection.cs 2011-06-04 19:19:12 UTC (rev 5908)
+++ trunk/nhibernate/src/NHibernate/Criterion/ConstantProjection.cs 2011-06-05 20:34:11 UTC (rev 5909)
@@ -14,8 +14,8 @@
public class ConstantProjection : SimpleProjection
{
private readonly object value;
- private readonly IType type;
-
+ private readonly TypedValue typedValue;
+
public ConstantProjection(object value) : this(value, NHibernateUtil.GuessType(value.GetType()))
{
}
@@ -23,7 +23,7 @@
public ConstantProjection(object value, IType type)
{
this.value = value;
- this.type = type;
+ typedValue = new TypedValue(type, this.value, EntityMode.Poco);
}
public override bool IsAggregate
@@ -44,7 +44,7 @@
public override SqlString ToSqlString(ICriteria criteria, int position, ICriteriaQuery criteriaQuery, IDictionary<string, IFilter> enabledFilters)
{
return new SqlStringBuilder()
- .Add(criteriaQuery.NewQueryParameter(type).Single())
+ .Add(criteriaQuery.NewQueryParameter(typedValue).Single())
.Add(" as ")
.Add(GetColumnAliases(position)[0])
.ToSqlString();
@@ -52,12 +52,12 @@
public override IType[] GetTypes(ICriteria criteria, ICriteriaQuery criteriaQuery)
{
- return new IType[] { type };
+ return new IType[] { typedValue.Type };
}
public override TypedValue[] GetTypedValues(ICriteria criteria, ICriteriaQuery criteriaQuery)
{
- return new TypedValue[] { new TypedValue(type, value, EntityMode.Poco) };
+ return new TypedValue[] { typedValue };
}
}
}
Modified: trunk/nhibernate/src/NHibernate/Criterion/ICriteriaQuery.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Criterion/ICriteriaQuery.cs 2011-06-04 19:19:12 UTC (rev 5908)
+++ trunk/nhibernate/src/NHibernate/Criterion/ICriteriaQuery.cs 2011-06-05 20:34:11 UTC (rev 5909)
@@ -1,5 +1,6 @@
using System.Collections.Generic;
using NHibernate.Engine;
+using NHibernate.Param;
using NHibernate.SqlCommand;
using NHibernate.Type;
@@ -71,14 +72,12 @@
/// <summary>
/// Create a new query parameter to use in a <see cref="ICriterion"/>
/// </summary>
- /// <param name="parameterType">The expected type of the parameter.</param>
+ /// <param name="parameter">The value and the <see cref="IType"/> of the parameter.</param>
/// <returns>A new instance of a query parameter to be added to a <see cref="SqlString"/>.</returns>
- IEnumerable<Parameter> NewQueryParameter(IType parameterType);
-
- /// <summary>
- /// Creates a dummy parameter index for the supplied paged value.
- /// Returns null if the Dialect does not support limit parameters
- /// </summary>
- int? CreatePagingParameter(int value);
+ IEnumerable<Parameter> NewQueryParameter(TypedValue parameter);
+ ICollection<IParameterSpecification> CollectedParameterSpecifications { get; }
+ ICollection<NamedParameter> CollectedParameters { get; }
+ Parameter CreateSkipParameter(int value);
+ Parameter CreateTakeParameter(int value);
}
}
\ No newline at end of file
Modified: trunk/nhibernate/src/NHibernate/Criterion/IdentifierEqExpression.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Criterion/IdentifierEqExpression.cs 2011-06-04 19:19:12 UTC (rev 5908)
+++ trunk/nhibernate/src/NHibernate/Criterion/IdentifierEqExpression.cs 2011-06-05 20:34:11 UTC (rev 5909)
@@ -34,7 +34,7 @@
{
//Implementation changed from H3.2 to use SqlString
string[] columns = criteriaQuery.GetIdentifierColumns(criteria);
- Parameter[] parameters = GetTypedValues(criteria, criteriaQuery).Select(x => x.Type).SelectMany(t => criteriaQuery.NewQueryParameter(t)).ToArray();
+ Parameter[] parameters = GetTypedValues(criteria, criteriaQuery).SelectMany(t => criteriaQuery.NewQueryParameter(t)).ToArray();
SqlStringBuilder result = new SqlStringBuilder(4 * columns.Length + 2);
if (columns.Length > 1)
Modified: trunk/nhibernate/src/NHibernate/Criterion/InExpression.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Criterion/InExpression.cs 2011-06-04 19:19:12 UTC (rev 5908)
+++ trunk/nhibernate/src/NHibernate/Criterion/InExpression.cs 2011-06-05 20:34:11 UTC (rev 5909)
@@ -69,7 +69,7 @@
// Generate SqlString of the form:
// columnName1 in (values) and columnName2 in (values) and ...
- Parameter[] parameters = GetTypedValues(criteria, criteriaQuery).Select(x => x.Type).SelectMany(t => criteriaQuery.NewQueryParameter(t)).ToArray();
+ Parameter[] parameters = GetTypedValues(criteria, criteriaQuery).SelectMany(t => criteriaQuery.NewQueryParameter(t)).ToArray();
for (int columnIndex = 0; columnIndex < columnNames.Length; columnIndex++)
{
Modified: trunk/nhibernate/src/NHibernate/Criterion/InsensitiveLikeExpression.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Criterion/InsensitiveLikeExpression.cs 2011-06-04 19:19:12 UTC (rev 5908)
+++ trunk/nhibernate/src/NHibernate/Criterion/InsensitiveLikeExpression.cs 2011-06-05 20:34:11 UTC (rev 5909)
@@ -85,7 +85,7 @@
.Add(" like ");
}
- sqlBuilder.Add(criteriaQuery.NewQueryParameter(NHibernateUtil.String).Single());
+ sqlBuilder.Add(criteriaQuery.NewQueryParameter(GetParameterTypedValue(criteria, criteriaQuery)).Single());
return sqlBuilder.ToSqlString();
}
@@ -93,18 +93,26 @@
public override TypedValue[] GetTypedValues(ICriteria criteria, ICriteriaQuery criteriaQuery)
{
List<TypedValue> typedValues = new List<TypedValue>();
-
+
if (projection != null)
{
typedValues.AddRange(projection.GetTypedValues(criteria, criteriaQuery));
- typedValues.AddRange(CriterionUtil.GetTypedValues(criteriaQuery, criteria, projection, null, value.ToString().ToLower()));
}
- else
- typedValues.Add(criteriaQuery.GetTypedValue(criteria, propertyName, value.ToString().ToLower()));
+ typedValues.Add(GetParameterTypedValue(criteria, criteriaQuery));
return typedValues.ToArray();
}
+ public TypedValue GetParameterTypedValue(ICriteria criteria, ICriteriaQuery criteriaQuery)
+ {
+ var matchValue = value.ToString().ToLower();
+ if (projection != null)
+ {
+ return CriterionUtil.GetTypedValues(criteriaQuery, criteria, projection, null, matchValue).Single();
+ }
+ return criteriaQuery.GetTypedValue(criteria, propertyName, matchValue);
+ }
+
public override IProjection[] GetProjections()
{
if (projection != null)
Modified: trunk/nhibernate/src/NHibernate/Criterion/LikeExpression.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Criterion/LikeExpression.cs 2011-06-04 19:19:12 UTC (rev 5908)
+++ trunk/nhibernate/src/NHibernate/Criterion/LikeExpression.cs 2011-06-05 20:34:11 UTC (rev 5909)
@@ -22,11 +22,14 @@
private char? escapeChar;
private readonly bool ignoreCase;
private readonly IProjection projection;
+ private readonly TypedValue typedValue;
public LikeExpression(string propertyName, string value, char? escapeChar, bool ignoreCase)
{
this.projection = Projections.Property(propertyName);
this.value = value;
+ typedValue = new TypedValue(NHibernateUtil.String, this.value, EntityMode.Poco);
+
this.escapeChar = escapeChar;
this.ignoreCase = ignoreCase;
}
@@ -35,6 +38,7 @@
{
this.projection = projection;
this.value = matchMode.ToMatchString(value);
+ typedValue = new TypedValue(NHibernateUtil.String, this.value, EntityMode.Poco);
}
@@ -80,11 +84,11 @@
lhs.Add(" like ")
.Add(dialect.LowercaseFunction)
.Add(StringHelper.OpenParen)
- .Add(criteriaQuery.NewQueryParameter(NHibernateUtil.String).Single())
+ .Add(criteriaQuery.NewQueryParameter(typedValue).Single())
.Add(StringHelper.ClosedParen);
}
else
- lhs.Add(" like ").Add(criteriaQuery.NewQueryParameter(NHibernateUtil.String).Single());
+ lhs.Add(" like ").Add(criteriaQuery.NewQueryParameter(typedValue).Single());
if (escapeChar.HasValue)
lhs.Add(" escape '" + escapeChar + "'");
@@ -94,7 +98,7 @@
public override TypedValue[] GetTypedValues(ICriteria criteria, ICriteriaQuery criteriaQuery)
{
- return new TypedValue[] { new TypedValue(NHibernateUtil.String, value, EntityMode.Poco) };
+ return new TypedValue[] { typedValue };
}
public override IProjection[] GetProjections()
Modified: trunk/nhibernate/src/NHibernate/Criterion/SQLCriterion.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Criterion/SQLCriterion.cs 2011-06-04 19:19:12 UTC (rev 5908)
+++ trunk/nhibernate/src/NHibernate/Criterion/SQLCriterion.cs 2011-06-05 20:34:11 UTC (rev 5909)
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Linq;
using NHibernate.Engine;
using NHibernate.SqlCommand;
using NHibernate.Type;
@@ -32,6 +33,16 @@
public override SqlString ToSqlString(ICriteria criteria, ICriteriaQuery criteriaQuery, IDictionary<string, IFilter> enabledFilters)
{
+ var parameters = _sql.GetParameters().ToList();
+ var paramPos = 0;
+ for (int i = 0; i < _typedValues.Length; i++)
+ {
+ var controlledParameters = criteriaQuery.NewQueryParameter(_typedValues[i]);
+ foreach (Parameter parameter in controlledParameters)
+ {
+ parameters[paramPos++].BackTrack = parameter.BackTrack;
+ }
+ }
return _sql.Replace("{alias}", criteriaQuery.GetSQLAlias(criteria));
}
Modified: trunk/nhibernate/src/NHibernate/Criterion/SimpleExpression.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Criterion/SimpleExpression.cs 2011-06-04 19:19:12 UTC (rev 5908)
+++ trunk/nhibernate/src/NHibernate/Criterion/SimpleExpression.cs 2011-06-05 20:34:11 UTC (rev 5909)
@@ -88,7 +88,7 @@
this,
value);
- Parameter[] parameters = GetTypedValues(criteria, criteriaQuery).Select(x => x.Type).SelectMany(t => criteriaQuery.NewQueryParameter(t)).ToArray();
+ Parameter[] parameters = criteriaQuery.NewQueryParameter(GetParameterTypedValue(criteria, criteriaQuery)).ToArray();
if (ignoreCase)
{
@@ -105,7 +105,7 @@
.Add(columnNames[0])
.Add(StringHelper.ClosedParen)
.Add(Op)
- .Add(parameters.FirstOrDefault())
+ .Add(parameters.Single())
.ToSqlString();
}
else
@@ -129,20 +129,27 @@
public override TypedValue[] GetTypedValues(ICriteria criteria, ICriteriaQuery criteriaQuery)
{
- List<TypedValue> typedValues = new List<TypedValue>();
- object icvalue = ignoreCase ? value.ToString().ToLower() : value;
+ var typedValues = new List<TypedValue>();
if (_projection != null)
{
typedValues.AddRange(_projection.GetTypedValues(criteria, criteriaQuery));
- typedValues.AddRange(CriterionUtil.GetTypedValues(criteriaQuery, criteria, _projection, null, icvalue));
}
- else
- typedValues.Add(criteriaQuery.GetTypedValue(criteria, propertyName, icvalue));
+ typedValues.Add(GetParameterTypedValue(criteria, criteriaQuery));
return typedValues.ToArray();
}
+ public TypedValue GetParameterTypedValue(ICriteria criteria, ICriteriaQuery criteriaQuery)
+ {
+ object icvalue = ignoreCase ? value.ToString().ToLower() : value;
+ if (_projection != null)
+ {
+ return CriterionUtil.GetTypedValues(criteriaQuery, criteria, _projection, null, icvalue).Single();
+ }
+ return criteriaQuery.GetTypedValue(criteria, propertyName, icvalue);
+ }
+
public override IProjection[] GetProjections()
{
if (_projection != null)
Modified: trunk/nhibernate/src/NHibernate/Criterion/SimpleSubqueryExpression.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Criterion/SimpleSubqueryExpression.cs 2011-06-04 19:19:12 UTC (rev 5908)
+++ trunk/nhibernate/src/NHibernate/Criterion/SimpleSubqueryExpression.cs 2011-06-05 20:34:11 UTC (rev 5909)
@@ -1,4 +1,6 @@
using System;
+using System.Collections.Generic;
+using System.Linq;
using NHibernate.Engine;
using NHibernate.SqlCommand;
@@ -23,13 +25,18 @@
TypedValue[] superTv = base.GetTypedValues(criteria, criteriaQuery);
TypedValue[] result = new TypedValue[superTv.Length + 1];
superTv.CopyTo(result, 1);
- result[0] = new TypedValue(GetTypes()[0], value, EntityMode.Poco);
+ result[0] = FirstTypedValue();
return result;
}
+ private TypedValue FirstTypedValue()
+ {
+ return new TypedValue(GetTypes()[0], value, EntityMode.Poco);
+ }
+
protected override SqlString ToLeftSqlString(ICriteria criteria, ICriteriaQuery criteriaQuery)
{
- return SqlString.Parameter;
+ return new SqlString(criteriaQuery.NewQueryParameter(FirstTypedValue()).First());
}
}
}
Modified: trunk/nhibernate/src/NHibernate/Criterion/SubqueryExpression.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Criterion/SubqueryExpression.cs 2011-06-04 19:19:12 UTC (rev 5908)
+++ trunk/nhibernate/src/NHibernate/Criterion/SubqueryExpression.cs 2011-06-05 20:34:11 UTC (rev 5909)
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Linq;
using NHibernate.Engine;
using NHibernate.Impl;
using NHibernate.Loader.Criteria;
@@ -54,27 +55,30 @@
IOuterJoinLoadable persister = (IOuterJoinLoadable)factory.GetEntityPersister(criteriaImpl.EntityOrClassName);
- //buffer needs to be before CriteriaJoinWalker for sake of parameter order
- SqlStringBuilder buf = new SqlStringBuilder().Add(ToLeftSqlString(criteria, criteriaQuery));
-
//patch to generate joins on subqueries
//stolen from CriteriaLoader
CriteriaJoinWalker walker =
new CriteriaJoinWalker(persister, innerQuery, factory, criteriaImpl, criteriaImpl.EntityOrClassName, enabledFilters);
+ parameters = innerQuery.GetQueryParameters(); // parameters can be inferred only after initialize the walker
+
SqlString sql = walker.SqlString;
if (criteriaImpl.FirstResult != 0 || criteriaImpl.MaxResults != RowSelection.NoValue)
{
- int? offset = Loader.Loader.GetOffsetUsingDialect(parameters.RowSelection, factory.Dialect);
- int? limit = Loader.Loader.GetLimitUsingDialect(parameters.RowSelection, factory.Dialect);
- int? offsetParameterIndex = offset.HasValue ? criteriaQuery.CreatePagingParameter(offset.Value) : null;
- int? limitParameterIndex = limit.HasValue ? criteriaQuery.CreatePagingParameter(limit.Value) : null;
- Parameter offsetParameter = offsetParameterIndex.HasValue ? Parameter.WithIndex(offsetParameterIndex.Value) : null;
- Parameter limitParameter = limitParameterIndex.HasValue ? Parameter.WithIndex(limitParameterIndex.Value) : null;
- sql = factory.Dialect.GetLimitString(sql, offset, limit, offsetParameter, limitParameter);
+ int? offset = Loader.Loader.GetOffsetUsingDialect(parameters.RowSelection, factory.Dialect);
+ int? limit = Loader.Loader.GetLimitUsingDialect(parameters.RowSelection, factory.Dialect);
+ Parameter offsetParameter = offset.HasValue ? innerQuery.CreateSkipParameter(offset.Value) : null;
+ Parameter limitParameter = limit.HasValue ? innerQuery.CreateTakeParameter(limit.Value) : null;
+ sql = factory.Dialect.GetLimitString(sql, offset, limit, offsetParameter, limitParameter);
}
+ // during CriteriaImpl.Clone we are doing a shallow copy of each criterion.
+ // this is not a problem for common criterion but not for SubqueryExpression because here we are holding the state of inner CriteriaTraslator (ICriteriaQuery).
+ // After execution (ToSqlString) we have to clean the internal state because the next execution may be performed in a different tree reusing the same istance of SubqueryExpression.
+ innerQuery = null;
+
+ SqlStringBuilder buf = new SqlStringBuilder().Add(ToLeftSqlString(criteria, criteriaQuery));
if (op != null)
{
buf.Add(" ").Add(op).Add(" ");
@@ -105,15 +109,7 @@
public override TypedValue[] GetTypedValues(ICriteria criteria, ICriteriaQuery criteriaQuery)
{
- InitializeInnerQueryAndParameters(criteriaQuery);
- IType[] paramTypes = parameters.PositionalParameterTypes;
- Object[] values = parameters.PositionalParameterValues;
- TypedValue[] tv = new TypedValue[paramTypes.Length];
- for (int i = 0; i < paramTypes.Length; i++)
- {
- tv[i] = new TypedValue(paramTypes[i], values[i], EntityMode.Poco);
- }
- return tv;
+ return parameters.NamedParameters.Values.ToArray();
}
public override IProjection[] GetProjections()
@@ -126,24 +122,15 @@
if (innerQuery == null)
{
ISessionFactoryImplementor factory = criteriaQuery.Factory;
-
- innerQuery =
- new CriteriaQueryTranslator(
- factory,
- criteriaImpl, //implicit polymorphism not supported (would need a union)
- criteriaImpl.EntityOrClassName,
- criteriaQuery.GenerateSQLAlias(),
- criteriaQuery);
-
- if (innerQuery.HasProjection)
- {
- parameters = innerQuery.GetQueryParameters();
- types = innerQuery.ProjectedTypes;
- }
- else
- {
- types = null;
- }
+
+ innerQuery = new CriteriaQueryTranslator(
+ factory,
+ criteriaImpl, //implicit polymorphism not supported (would need a union)
+ criteriaImpl.EntityOrClassName,
+ criteriaQuery.GenerateSQLAlias(),
+ criteriaQuery);
+
+ types = innerQuery.HasProjection ? innerQuery.ProjectedTypes : null;
}
}
Modified: trunk/nhibernate/src/NHibernate/Engine/QueryParameters.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Engine/QueryParameters.cs 2011-06-04 19:19:12 UTC (rev 5908)
+++ trunk/nhibernate/src/NHibernate/Engine/QueryParameters.cs 2011-06-05 20:34:11 UTC (rev 5909)
@@ -78,6 +78,12 @@
_tempPagingParameterIndexes = tempPagingParameterIndexes;
}
+ public QueryParameters(IType[] positionalParameterTypes, object[] positionalParameterValues, IDictionary<string, TypedValue> namedParameters, IDictionary<string, LockMode> lockModes, RowSelection rowSelection, bool isReadOnlyInitialized, bool readOnly, bool cacheable, string cacheRegion, string comment, bool isLookupByNaturalKey, IResultTransformer transformer)
+ : this(positionalParameterTypes, positionalParameterValues, namedParameters, lockModes, rowSelection, isReadOnlyInitialized, readOnly, cacheable, cacheRegion, comment, null, transformer)
+ {
+ NaturalKeyLookup = isLookupByNaturalKey;
+ }
+
public QueryParameters(IType[] positionalParameterTypes, object[] positionalParameterValues, IDictionary<string, TypedValue> namedParameters, IDictionary<string, LockMode> lockModes, RowSelection rowSelection, bool isReadOnlyInitialized, bool readOnly, bool cacheable, string cacheRegion, string comment, object[] collectionKeys, IResultTransformer transformer)
{
_positionalParameterTypes = positionalParameterTypes;
Modified: trunk/nhibernate/src/NHibernate/Impl/MultiCriteriaImpl.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Impl/MultiCriteriaImpl.cs 2011-06-04 19:19:12 UTC (rev 5908)
+++ trunk/nhibernate/src/NHibernate/Impl/MultiCriteriaImpl.cs 2011-06-05 20:34:11 UTC (rev 5909)
@@ -436,10 +436,14 @@
combinedQueryParameters.NamedParameters = new Dictionary<string, TypedValue>();
ArrayList positionalParameterTypes = new ArrayList();
ArrayList positionalParameterValues = new ArrayList();
+ int index = 0;
foreach (QueryParameters queryParameters in parameters)
{
- // There aren't any named params in criteria queries
- //CopyNamedParametersDictionary(combinedQueryParameters.NamedParameters, queryParameters.NamedParameters);
+ foreach (KeyValuePair<string, TypedValue> dictionaryEntry in queryParameters.NamedParameters)
+ {
+ combinedQueryParameters.NamedParameters.Add(dictionaryEntry.Key + index, dictionaryEntry.Value);
+ }
+ index += 1;
positionalParameterTypes.AddRange(queryParameters.PositionalParameterTypes);
positionalParameterValues.AddRange(queryParameters.PositionalParameterValues);
}
Deleted: trunk/nhibernate/src/NHibernate/Linq/NamedParameter.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Linq/NamedParameter.cs 2011-06-04 19:19:12 UTC (rev 5908)
+++ trunk/nhibernate/src/NHibernate/Linq/NamedParameter.cs 2011-06-05 20:34:11 UTC (rev 5909)
@@ -1,19 +0,0 @@
-using System;
-using NHibernate.Type;
-
-namespace NHibernate.Linq
-{
- public class NamedParameter
- {
- public NamedParameter(string name, object value, IType type)
- {
- Name = name;
- Value = value;
- Type = type;
- }
-
- public string Name { get; private set; }
- public object Value { get; internal set; }
- public IType Type { get; internal set; }
- }
-}
\ No newline at end of file
Modified: trunk/nhibernate/src/NHibernate/Linq/NhLinqExpression.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Linq/NhLinqExpression.cs 2011-06-04 19:19:12 UTC (rev 5908)
+++ trunk/nhibernate/src/NHibernate/Linq/NhLinqExpression.cs 2011-06-05 20:34:11 UTC (rev 5909)
@@ -5,6 +5,7 @@
using NHibernate.Engine.Query;
using NHibernate.Hql.Ast.ANTLR.Tree;
using NHibernate.Linq.Visitors;
+using NHibernate.Param;
using NHibernate.Type;
using Remotion.Linq.Parsing.ExpressionTreeVisitors;
Modified: trunk/nhibernate/src/NHibernate/Linq/ParameterAggregator.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Linq/ParameterAggregator.cs 2011-06-04 19:19:12 UTC (rev 5908)
+++ trunk/nhibernate/src/NHibernate/Linq/ParameterAggregator.cs 2011-06-05 20:34:11 UTC (rev 5909)
@@ -1,4 +1,5 @@
using System.Collections.Generic;
+using NHibernate.Param;
using NHibernate.Type;
namespace NHibernate.Linq
Modified: trunk/nhibernate/src/NHibernate/Linq/Visitors/ExpressionKeyVisitor.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Linq/Visitors/ExpressionKeyVisitor.cs 2011-06-04 19:19:12 UTC (rev 5908)
+++ trunk/nhibernate/src/NHibernate/Linq/Visitors/ExpressionKeyVisitor.cs 2011-06-05 20:34:11 UTC (rev 5909)
@@ -4,6 +4,7 @@
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
+using NHibernate.Param;
namespace NHibernate.Linq.Visitors
{
Modified: trunk/nhibernate/src/NHibernate/Linq/Visitors/ExpressionParameterVisitor.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Linq/Visitors/ExpressionParameterVisitor.cs 2011-06-04 19:19:12 UTC (rev 5908)
+++ trunk/nhibernate/src/NHibernate/Linq/Visitors/ExpressionParameterVisitor.cs 2011-06-05 20:34:11 UTC (rev 5909)
@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
+using NHibernate.Param;
using NHibernate.Type;
namespace NHibernate.Linq.Visitors
Modified: trunk/nhibernate/src/NHibernate/Linq/Visitors/HqlGeneratorExpressionTreeVisitor.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Linq/Visitors/HqlGeneratorExpressionTreeVisitor.cs 2011-06-04 19:19:12 UTC (rev 5908)
+++ trunk/nhibernate/src/NHibernate/Linq/Visitors/HqlGeneratorExpressionTreeVisitor.cs 2011-06-05 20:34:11 UTC (rev 5909)
@@ -4,6 +4,7 @@
using NHibernate.Hql.Ast;
using NHibernate.Linq.Expressions;
using NHibernate.Linq.Functions;
+using NHibernate.Param;
using Remotion.Linq.Clauses.Expressions;
namespace NHibernate.Linq.Visitors
Modified: trunk/nhibernate/src/NHibernate/Linq/Visitors/ResultOperatorProcessors/ProcessCacheable.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Linq/Visitors/ResultOperatorProcessors/ProcessCacheable.cs 2011-06-04 19:19:12 UTC (rev 5908)
+++ trunk/nhibernate/src/NHibernate/Linq/Visitors/ResultOperatorProcessors/ProcessCacheable.cs 2011-06-05 20:34:11 UTC (rev 5909)
@@ -1,4 +1,6 @@
-namespace NHibernate.Linq.Visitors.ResultOperatorProcessors
+using NHibernate.Param;
+
+namespace NHibernate.Linq.Visitors.ResultOperatorProcessors
{
public class ProcessCacheable : IResultOperatorProcessor<CacheableResultOperator>
{
Modified: trunk/nhibernate/src/NHibernate/Linq/Visitors/ResultOperatorProcessors/ProcessSkip.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Linq/Visitors/ResultOperatorProcessors/ProcessSkip.cs 2011-06-04 19:19:12 UTC (rev 5908)
+++ trunk/nhibernate/src/NHibernate/Linq/Visitors/ResultOperatorProcessors/ProcessSkip.cs 2011-06-05 20:34:11 UTC (rev 5909)
@@ -1,5 +1,6 @@
using System.Linq.Expressions;
using NHibernate.Engine.Query;
+using NHibernate.Param;
using Remotion.Linq.Clauses.ResultOperators;
namespace NHibernate.Linq.Visitors.ResultOperatorProcessors
Modified: trunk/nhibernate/src/NHibernate/Linq/Visitors/ResultOperatorProcessors/ProcessTake.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Linq/Visitors/ResultOperatorProcessors/ProcessTake.cs 2011-06-04 19:19:12 UTC (rev 5908)
+++ trunk/nhibernate/src/NHibernate/Linq/Visitors/ResultOperatorProcessors/ProcessTake.cs 2011-06-05 20:34:11 UTC (rev 5909)
@@ -1,5 +1,6 @@
using System.Linq.Expressions;
using NHibernate.Engine.Query;
+using NHibernate.Param;
using Remotion.Linq.Clauses.ResultOperators;
namespace NHibernate.Linq.Visitors.ResultOperatorProcessors
Modified: trunk/nhibernate/src/NHibernate/Linq/Visitors/VisitorParameters.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Linq/Visitors/VisitorParameters.cs 2011-06-04 19:19:12 UTC (rev 5908)
+++ trunk/nhibernate/src/NHibernate/Linq/Visitors/VisitorParameters.cs 2011-06-05 20:34:11 UTC (rev 5909)
@@ -2,6 +2,7 @@
using System.Linq.Expressions;
using NHibernate.Engine;
using NHibernate.Engine.Query;
+using NHibernate.Param;
namespace NHibernate.Linq.Visitors
{
Modified: trunk/nhibernate/src/NHibernate/Loader/Criteria/CriteriaLoader.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Loader/Criteria/CriteriaLoader.cs 2011-06-04 19:19:12 UTC (rev 59...
[truncated message content] |
|
From: <fab...@us...> - 2011-06-05 21:24:36
|
Revision: 5910
http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5910&view=rev
Author: fabiomaulo
Date: 2011-06-05 21:24:29 +0000 (Sun, 05 Jun 2011)
Log Message:
-----------
Refactoring: IResultSetsCommand using Loader instances instead static methods
Modified Paths:
--------------
trunk/nhibernate/src/NHibernate/Driver/BasicResultSetsCommand.cs
trunk/nhibernate/src/NHibernate/Driver/IResultSetsCommand.cs
trunk/nhibernate/src/NHibernate/Impl/MultiCriteriaImpl.cs
trunk/nhibernate/src/NHibernate/Impl/MultiQueryImpl.cs
trunk/nhibernate/src/NHibernate/Loader/Loader.cs
Modified: trunk/nhibernate/src/NHibernate/Driver/BasicResultSetsCommand.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Driver/BasicResultSetsCommand.cs 2011-06-05 20:34:11 UTC (rev 5909)
+++ trunk/nhibernate/src/NHibernate/Driver/BasicResultSetsCommand.cs 2011-06-05 21:24:29 UTC (rev 5910)
@@ -47,7 +47,7 @@
get { return sqlString; }
}
- public virtual IDataReader GetReader(QueryParameters[] queryParameters, int? commandTimeout)
+ public virtual IDataReader GetReader(Loader.Loader[] queryLoaders, QueryParameters[] queryParameters, int? commandTimeout)
{
SqlType[] sqlTypes = types.ToArray();
var command= batcher.PrepareQueryCommand(CommandType.Text, sqlString, sqlTypes);
@@ -57,45 +57,45 @@
}
log.Info(command.CommandText);
- BindParameters(command, queryParameters);
+ BindParameters(command, queryLoaders, queryParameters);
return new BatcherDataReaderWrapper(batcher, command);
}
- protected virtual void BindParameters(IDbCommand command, QueryParameters[] queryParameters)
+ protected virtual void BindParameters(IDbCommand command, Loader.Loader[] queryLoaders, QueryParameters[] queryParameters)
{
int colIndex = 0;
for (int queryIndex = 0; queryIndex < resultSetsCount; queryIndex++)
{
- int limitParameterSpan = BindLimitParametersFirstIfNeccesary(command, queryParameters[queryIndex], colIndex);
- colIndex = BindQueryParameters(command, queryParameters[queryIndex], colIndex + limitParameterSpan);
- colIndex += BindLimitParametersLastIfNeccesary(command, queryParameters[queryIndex], colIndex);
+ int limitParameterSpan = BindLimitParametersFirstIfNeccesary(command, queryLoaders[queryIndex], queryParameters[queryIndex], colIndex);
+ colIndex = BindQueryParameters(command, queryLoaders[queryIndex], queryParameters[queryIndex], colIndex + limitParameterSpan);
+ colIndex += BindLimitParametersLastIfNeccesary(command, queryLoaders[queryIndex], queryParameters[queryIndex], colIndex);
}
}
- protected virtual int BindLimitParametersLastIfNeccesary(IDbCommand command, QueryParameters parameter, int colIndex)
+ protected virtual int BindLimitParametersLastIfNeccesary(IDbCommand command, Loader.Loader queryLoader, QueryParameters parameter, int colIndex)
{
RowSelection selection = parameter.RowSelection;
- if (Loader.Loader.UseLimit(selection, dialect) && !dialect.BindLimitParametersFirst)
+ if (queryLoader.UseLimit(selection, dialect) && !dialect.BindLimitParametersFirst)
{
- return Loader.Loader.BindLimitParameters(command, colIndex, selection, session);
+ return queryLoader.BindLimitParameters(command, colIndex, selection, session);
}
return 0;
}
- protected virtual int BindQueryParameters(IDbCommand command, QueryParameters parameter, int colIndex)
+ protected virtual int BindQueryParameters(IDbCommand command, Loader.Loader queryLoader, QueryParameters parameter, int colIndex)
{
colIndex += parameter.BindParameters(command, colIndex, session);
return colIndex;
}
- protected virtual int BindLimitParametersFirstIfNeccesary(IDbCommand command, QueryParameters parameter, int colIndex)
+ protected virtual int BindLimitParametersFirstIfNeccesary(IDbCommand command, Loader.Loader queryLoader, QueryParameters parameter, int colIndex)
{
int limitParameterSpan = 0;
RowSelection selection = parameter.RowSelection;
- if (Loader.Loader.UseLimit(selection, dialect) && dialect.BindLimitParametersFirst)
+ if (queryLoader.UseLimit(selection, dialect) && dialect.BindLimitParametersFirst)
{
- limitParameterSpan += Loader.Loader.BindLimitParameters(command, colIndex, selection, session);
+ limitParameterSpan += queryLoader.BindLimitParameters(command, colIndex, selection, session);
}
return limitParameterSpan;
}
Modified: trunk/nhibernate/src/NHibernate/Driver/IResultSetsCommand.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Driver/IResultSetsCommand.cs 2011-06-05 20:34:11 UTC (rev 5909)
+++ trunk/nhibernate/src/NHibernate/Driver/IResultSetsCommand.cs 2011-06-05 21:24:29 UTC (rev 5910)
@@ -10,6 +10,6 @@
int ParametersCount { get; }
bool HasQueries { get; }
SqlString Sql { get; }
- IDataReader GetReader(QueryParameters[] queryParameters, int? commandTimeout);
+ IDataReader GetReader(Loader.Loader[] queryLoaders, QueryParameters[] queryParameters, int? commandTimeout);
}
}
\ No newline at end of file
Modified: trunk/nhibernate/src/NHibernate/Impl/MultiCriteriaImpl.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Impl/MultiCriteriaImpl.cs 2011-06-05 20:34:11 UTC (rev 5909)
+++ trunk/nhibernate/src/NHibernate/Impl/MultiCriteriaImpl.cs 2011-06-05 21:24:29 UTC (rev 5910)
@@ -200,7 +200,7 @@
try
{
- using (var reader = resultSetsCommand.GetReader(parameters.ToArray(), null))
+ using (var reader = resultSetsCommand.GetReader(loaders.ToArray(), parameters.ToArray(), null))
{
ArrayList[] hydratedObjects = new ArrayList[loaders.Count];
List<EntityKey[]>[] subselectResultKeys = new List<EntityKey[]>[loaders.Count];
@@ -218,7 +218,7 @@
createSubselects[i] = loader.IsSubselectLoadingEnabled;
subselectResultKeys[i] = createSubselects[i] ? new List<EntityKey[]>() : null;
int maxRows = Loader.Loader.HasMaxRows(selection) ? selection.MaxRows : int.MaxValue;
- if (!dialect.SupportsLimitOffset || !Loader.Loader.UseLimit(selection, dialect))
+ if (!dialect.SupportsLimitOffset || !loader.UseLimit(selection, dialect))
{
Loader.Loader.Advance(reader, selection);
}
Modified: trunk/nhibernate/src/NHibernate/Impl/MultiQueryImpl.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Impl/MultiQueryImpl.cs 2011-06-05 20:34:11 UTC (rev 5909)
+++ trunk/nhibernate/src/NHibernate/Impl/MultiQueryImpl.cs 2011-06-05 21:24:29 UTC (rev 5910)
@@ -504,7 +504,7 @@
try
{
- using (var reader = resultSetsCommand.GetReader(Parameters.ToArray(), commandTimeout != RowSelection.NoValue ? commandTimeout : (int?)null))
+ using (var reader = resultSetsCommand.GetReader(translators.Select(t=> t.Loader).ToArray(), Parameters.ToArray(), commandTimeout != RowSelection.NoValue ? commandTimeout : (int?)null))
{
if (log.IsDebugEnabled)
{
@@ -527,7 +527,7 @@
hydratedObjects[i] = entitySpan > 0 ? new ArrayList() : null;
RowSelection selection = parameter.RowSelection;
int maxRows = Loader.Loader.HasMaxRows(selection) ? selection.MaxRows : int.MaxValue;
- if (!dialect.SupportsLimitOffset || !Loader.Loader.UseLimit(selection, dialect))
+ if (!dialect.SupportsLimitOffset || !translator.Loader.UseLimit(selection, dialect))
{
Loader.Loader.Advance(reader, selection);
}
Modified: trunk/nhibernate/src/NHibernate/Loader/Loader.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Loader/Loader.cs 2011-06-05 20:34:11 UTC (rev 5909)
+++ trunk/nhibernate/src/NHibernate/Loader/Loader.cs 2011-06-05 21:24:29 UTC (rev 5910)
@@ -1093,7 +1093,7 @@
/// <param name="selection"></param>
/// <param name="dialect"></param>
/// <returns></returns>
- internal static bool UseLimit(RowSelection selection, Dialect.Dialect dialect)
+ internal bool UseLimit(RowSelection selection, Dialect.Dialect dialect)
{
return dialect.SupportsLimit && (HasMaxRows(selection) || HasOffset(selection));
}
@@ -1263,7 +1263,7 @@
/// Bind parameters needed by the dialect-specific LIMIT clause
/// </summary>
/// <returns>The number of parameters bound</returns>
- internal static int BindLimitParameters(IDbCommand st, int index, RowSelection selection, ISessionImplementor session)
+ internal int BindLimitParameters(IDbCommand st, int index, RowSelection selection, ISessionImplementor session)
{
Dialect.Dialect dialect = session.Factory.Dialect;
if (!dialect.SupportsVariableLimit)
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <fab...@us...> - 2011-06-12 22:04:51
|
Revision: 5915
http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5915&view=rev
Author: fabiomaulo
Date: 2011-06-12 22:04:44 +0000 (Sun, 12 Jun 2011)
Log Message:
-----------
- "re-fix" multi-criteria with pagination
- re implemented MultiCriteriaImpl/MultiQueryImpl to fix parameters related problems
Modified Paths:
--------------
trunk/nhibernate/src/NHibernate/Driver/BasicResultSetsCommand.cs
trunk/nhibernate/src/NHibernate/Driver/IResultSetsCommand.cs
trunk/nhibernate/src/NHibernate/Engine/Query/ParameterParser.cs
trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Loader/QueryLoader.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/Custom/Sql/SQLCustomQuery.cs
trunk/nhibernate/src/NHibernate/Loader/Custom/Sql/SQLQueryParser.cs
trunk/nhibernate/src/NHibernate/Loader/Loader.cs
trunk/nhibernate/src/NHibernate/NHibernate.csproj
trunk/nhibernate/src/NHibernate/Param/AbstractExplicitParameterSpecification.cs
trunk/nhibernate/src/NHibernate/Param/AggregatedIndexCollectionSelectorParameterSpecifications.cs
trunk/nhibernate/src/NHibernate/Param/CollectionFilterKeyParameterSpecification.cs
trunk/nhibernate/src/NHibernate/Param/CriteriaNamedParameterSpecification.cs
trunk/nhibernate/src/NHibernate/Param/DynamicFilterParameterSpecification.cs
trunk/nhibernate/src/NHibernate/Param/IParameterSpecification.cs
trunk/nhibernate/src/NHibernate/Param/NamedParameterSpecification.cs
trunk/nhibernate/src/NHibernate/Param/PositionalParameterSpecification.cs
trunk/nhibernate/src/NHibernate/Param/QuerySkipParameterSpecification.cs
trunk/nhibernate/src/NHibernate/Param/QueryTakeParameterSpecification.cs
trunk/nhibernate/src/NHibernate/Param/VersionTypeSeedParameterSpecification.cs
trunk/nhibernate/src/NHibernate.Test/Pagination/CustomDialectFixture.cs
Added Paths:
-----------
trunk/nhibernate/src/NHibernate/SqlCommand/SqlCommandImpl.cs
Modified: trunk/nhibernate/src/NHibernate/Driver/BasicResultSetsCommand.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Driver/BasicResultSetsCommand.cs 2011-06-07 01:47:49 UTC (rev 5914)
+++ trunk/nhibernate/src/NHibernate/Driver/BasicResultSetsCommand.cs 2011-06-12 22:04:44 UTC (rev 5915)
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Data;
+using System.Linq;
using NHibernate.Engine;
using NHibernate.SqlCommand;
using NHibernate.SqlTypes;
@@ -14,9 +15,8 @@
private readonly ISessionImplementor session;
private readonly Dialect.Dialect dialect;
private readonly IBatcher batcher;
- private int resultSetsCount = 0;
- private readonly List<SqlType> types = new List<SqlType>();
private SqlString sqlString = new SqlString();
+ private readonly List<ISqlCommand> commands= new List<ISqlCommand>();
public BasicResultSetsCommand(ISessionImplementor session)
{
@@ -25,21 +25,15 @@
batcher = session.Batcher;
}
- public virtual void Append(SqlCommandInfo commandInfo)
+ public void Append(ISqlCommand command)
{
- resultSetsCount++;
- sqlString = sqlString.Append(commandInfo.Text).Append(";").Append(Environment.NewLine);
- types.AddRange(commandInfo.ParameterTypes);
+ commands.Add(command);
+ sqlString = sqlString.Append(command.Query).Append(";").Append(Environment.NewLine);
}
- public int ParametersCount
- {
- get { return types.Count; }
- }
-
public bool HasQueries
{
- get { return resultSetsCount > 0; }
+ get { return commands.Count > 0; }
}
public SqlString Sql
@@ -47,17 +41,22 @@
get { return sqlString; }
}
- public virtual IDataReader GetReader(Loader.Loader[] queryLoaders, QueryParameters[] queryParameters, int? commandTimeout)
+ public IDataReader GetReader(int? commandTimeout)
{
- SqlType[] sqlTypes = types.ToArray();
- var command= batcher.PrepareQueryCommand(CommandType.Text, sqlString, sqlTypes);
- if(commandTimeout.HasValue)
+ SqlType[] sqlTypes = commands.SelectMany(c => c.ParameterTypes).ToArray();
+ var command = batcher.PrepareQueryCommand(CommandType.Text, sqlString, sqlTypes);
+ if (commandTimeout.HasValue)
{
- command.CommandTimeout = commandTimeout.Value;
+ command.CommandTimeout = commandTimeout.Value;
}
log.Info(command.CommandText);
-
- BindParameters(command, queryLoaders, queryParameters);
+ var wholeQueryParametersList = sqlString.GetParameters().ToList();
+ var singleQueryParameterOffset = 0;
+ foreach (var sqlLoaderCommand in commands)
+ {
+ sqlLoaderCommand.Bind(command, wholeQueryParametersList, singleQueryParameterOffset, session);
+ singleQueryParameterOffset += sqlLoaderCommand.ParameterTypes.Length;
+ }
return new BatcherDataReaderWrapper(batcher, command);
}
@@ -65,7 +64,7 @@
{
int colIndex = 0;
- for (int queryIndex = 0; queryIndex < resultSetsCount; queryIndex++)
+ for (int queryIndex = 0; queryIndex < commands.Count; queryIndex++)
{
int limitParameterSpan = BindLimitParametersFirstIfNeccesary(command, queryLoaders[queryIndex], queryParameters[queryIndex], colIndex);
colIndex = BindQueryParameters(command, queryLoaders[queryIndex], queryParameters[queryIndex], colIndex + limitParameterSpan);
Modified: trunk/nhibernate/src/NHibernate/Driver/IResultSetsCommand.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Driver/IResultSetsCommand.cs 2011-06-07 01:47:49 UTC (rev 5914)
+++ trunk/nhibernate/src/NHibernate/Driver/IResultSetsCommand.cs 2011-06-12 22:04:44 UTC (rev 5915)
@@ -1,15 +1,13 @@
using System.Data;
-using NHibernate.Engine;
using NHibernate.SqlCommand;
namespace NHibernate.Driver
{
public interface IResultSetsCommand
{
- void Append(SqlCommandInfo commandInfo);
- int ParametersCount { get; }
+ void Append(ISqlCommand command);
bool HasQueries { get; }
SqlString Sql { get; }
- IDataReader GetReader(Loader.Loader[] queryLoaders, QueryParameters[] queryParameters, int? commandTimeout);
+ IDataReader GetReader(int? commandTimeout);
}
}
\ No newline at end of file
Modified: trunk/nhibernate/src/NHibernate/Engine/Query/ParameterParser.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Engine/Query/ParameterParser.cs 2011-06-07 01:47:49 UTC (rev 5914)
+++ trunk/nhibernate/src/NHibernate/Engine/Query/ParameterParser.cs 2011-06-12 22:04:44 UTC (rev 5915)
@@ -43,6 +43,7 @@
/// <exception cref="QueryException" />
public static void Parse(string sqlString, IRecognizer recognizer)
{
+ // TODO: WTF? "CALL"... it may work for ORACLE but what about others RDBMS ? (by FM)
bool hasMainOutputParameter = sqlString.IndexOf("call") > 0 &&
sqlString.IndexOf("?") > 0 &&
sqlString.IndexOf("=") > 0 &&
Modified: trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Loader/QueryLoader.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Loader/QueryLoader.cs 2011-06-07 01:47:49 UTC (rev 5914)
+++ trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Loader/QueryLoader.cs 2011-06-12 22:04:44 UTC (rev 5915)
@@ -436,6 +436,29 @@
return result;
}
+ public override ISqlCommand CreateSqlCommandInfo(QueryParameters queryParameters, ISessionImplementor session)
+ {
+ // NOTE: repeated code PrepareQueryCommand
+ // A distinct-copy of parameter specifications collected during query construction
+ var parameterSpecs = new HashSet<IParameterSpecification>(_queryTranslator.CollectedParameterSpecifications);
+ SqlString sqlString = SqlString.Copy();
+
+ // dynamic-filter parameters: during the HQL->SQL parsing, filters can be added as SQL_TOKEN/string and the SqlGenerator will not find it
+ sqlString = ExpandDynamicFilterParameters(sqlString, parameterSpecs, session);
+ AdjustQueryParametersForSubSelectFetching(sqlString, parameterSpecs, session, queryParameters); // NOTE: see TODO below
+
+ sqlString = AddLimitsParametersIfNeeded(sqlString, parameterSpecs, queryParameters, session);
+ // TODO: for sub-select fetching we have to try to assign the QueryParameter.ProcessedSQL here (with limits) but only after use IParameterSpecification for any kind of queries
+
+ // The PreprocessSQL method can modify the SqlString but should never add parameters (or we have to override it)
+ sqlString = PreprocessSQL(sqlString, queryParameters, session.Factory.Dialect);
+
+ // After the last modification to the SqlString we can collect all parameters types.
+ ResetEffectiveExpectedType(parameterSpecs, queryParameters); // <= TODO: remove this method when we can infer the type during the parse
+
+ return new SqlCommand.SqlCommandImpl(sqlString, parameterSpecs, queryParameters, session.Factory);
+ }
+
/// <summary>
/// Obtain an <c>IDbCommand</c> with all parameters pre-bound. Bind positional parameters,
/// named parameters, and limit parameters.
Modified: trunk/nhibernate/src/NHibernate/Impl/MultiCriteriaImpl.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Impl/MultiCriteriaImpl.cs 2011-06-07 01:47:49 UTC (rev 5914)
+++ trunk/nhibernate/src/NHibernate/Impl/MultiCriteriaImpl.cs 2011-06-12 22:04:44 UTC (rev 5915)
@@ -183,8 +183,8 @@
translators.Add(translator);
QueryParameters queryParameters = translator.GetQueryParameters();
parameters.Add(queryParameters);
- SqlCommandInfo commandInfo = loader.GetQueryStringAndTypes(session, queryParameters, resultSetsCommand.ParametersCount);
- resultSetsCommand.Append(commandInfo);
+ ISqlCommand singleCommand = loader.CreateSqlCommandInfo(queryParameters, session);
+ resultSetsCommand.Append(singleCommand);
}
}
@@ -200,7 +200,7 @@
try
{
- using (var reader = resultSetsCommand.GetReader(loaders.ToArray(), parameters.ToArray(), null))
+ using (var reader = resultSetsCommand.GetReader(null))
{
ArrayList[] hydratedObjects = new ArrayList[loaders.Count];
List<EntityKey[]>[] subselectResultKeys = new List<EntityKey[]>[loaders.Count];
Modified: trunk/nhibernate/src/NHibernate/Impl/MultiQueryImpl.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Impl/MultiQueryImpl.cs 2011-06-07 01:47:49 UTC (rev 5914)
+++ trunk/nhibernate/src/NHibernate/Impl/MultiQueryImpl.cs 2011-06-12 22:04:44 UTC (rev 5915)
@@ -504,7 +504,7 @@
try
{
- using (var reader = resultSetsCommand.GetReader(translators.Select(t=> t.Loader).ToArray(), Parameters.ToArray(), commandTimeout != RowSelection.NoValue ? commandTimeout : (int?)null))
+ using (var reader = resultSetsCommand.GetReader(commandTimeout != RowSelection.NoValue ? commandTimeout : (int?)null))
{
if (log.IsDebugEnabled)
{
@@ -640,9 +640,8 @@
{
translators.Add(translator);
parameters.Add(queryParameters);
- queryParameters = GetFilteredQueryParameters(queryParameters, translator);
- SqlCommandInfo commandInfo = translator.Loader.GetQueryStringAndTypes(session, queryParameters, resultSetsCommand.ParametersCount);
- resultSetsCommand.Append(commandInfo);
+ ISqlCommand singleCommand = translator.Loader.CreateSqlCommandInfo(queryParameters, session);
+ resultSetsCommand.Append(singleCommand);
}
}
}
@@ -866,7 +865,7 @@
var sqlQueryImpl = (SqlQueryImpl) sqlQuery;
NativeSQLQuerySpecification sqlQuerySpec = sqlQueryImpl.GenerateQuerySpecification(sqlQueryImpl.NamedParams);
var sqlCustomQuery = new SQLCustomQuery(sqlQuerySpec.SqlQueryReturns, sqlQuerySpec.QueryString, sqlQuerySpec.QuerySpaces, sessionFactory);
- loader = new CustomLoader(sqlCustomQuery, sessionFactory);
+ loader = new CustomLoader(sqlCustomQuery, sqlCustomQuery.CollectedParametersSpecifications, sessionFactory);
}
public IType[] ReturnTypes
Modified: trunk/nhibernate/src/NHibernate/Loader/Criteria/CriteriaLoader.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Loader/Criteria/CriteriaLoader.cs 2011-06-07 01:47:49 UTC (rev 5914)
+++ trunk/nhibernate/src/NHibernate/Loader/Criteria/CriteriaLoader.cs 2011-06-12 22:04:44 UTC (rev 5915)
@@ -185,6 +185,26 @@
return customResultTransformer.TransformList(results);
}
+ public override ISqlCommand CreateSqlCommandInfo(QueryParameters queryParameters, ISessionImplementor session)
+ {
+ // NOTE: repeated code PrepareQueryCommand
+ // A distinct-copy of parameter specifications collected during query construction
+ var parameterSpecs = new HashSet<IParameterSpecification>(translator.CollectedParameterSpecifications);
+ SqlString sqlString = SqlString.Copy();
+
+ // dynamic-filter parameters: during the HQL->SQL parsing, filters can be added as SQL_TOKEN/string and the SqlGenerator will not find it
+ sqlString = ExpandDynamicFilterParameters(sqlString, parameterSpecs, session);
+ AdjustQueryParametersForSubSelectFetching(sqlString, parameterSpecs, session, queryParameters); // NOTE: see TODO below
+
+ sqlString = AddLimitsParametersIfNeeded(sqlString, parameterSpecs, queryParameters, session);
+ // TODO: for sub-select fetching we have to try to assign the QueryParameter.ProcessedSQL here (with limits) but only after use IParameterSpecification for any kind of queries
+
+ // The PreprocessSQL method can modify the SqlString but should never add parameters (or we have to override it)
+ sqlString = PreprocessSQL(sqlString, queryParameters, session.Factory.Dialect);
+
+ return new SqlCommand.SqlCommandImpl(sqlString, parameterSpecs, queryParameters, session.Factory);
+ }
+
/// <summary>
/// Obtain an <c>IDbCommand</c> with all parameters pre-bound. Bind positional parameters,
/// named parameters, and limit parameters.
@@ -199,9 +219,7 @@
/// <returns>A CommandWrapper wrapping an IDbCommand that is ready to be executed.</returns>
protected internal override IDbCommand PrepareQueryCommand(QueryParameters queryParameters, bool scroll, ISessionImplementor session)
{
- // NH: In this Loader we can know better all parameters used so we can simplify the IDbCommand construction
- // NH: would be very useful if we can do the same with Criteria. This method works just for HQL and LINQ.
-
+ // NOTE: repeated code CreateSqlCommandInfo (here we are reusing some other variables)
// A distinct-copy of parameter specifications collected during query construction
var parameterSpecs = new HashSet<IParameterSpecification>(translator.CollectedParameterSpecifications);
SqlString sqlString = SqlString.Copy();
Modified: trunk/nhibernate/src/NHibernate/Loader/Custom/CustomLoader.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Loader/Custom/CustomLoader.cs 2011-06-07 01:47:49 UTC (rev 5914)
+++ trunk/nhibernate/src/NHibernate/Loader/Custom/CustomLoader.cs 2011-06-12 22:04:44 UTC (rev 5915)
@@ -1,3 +1,5 @@
+using System;
+using System.Linq;
using System.Collections;
using System.Collections.Generic;
using System.Data;
@@ -4,12 +6,14 @@
using Iesi.Collections.Generic;
using NHibernate.Engine;
using NHibernate.Hql;
+using NHibernate.Param;
using NHibernate.Persister.Collection;
using NHibernate.Persister.Entity;
using NHibernate.SqlCommand;
using NHibernate.Transform;
using NHibernate.Type;
using NHibernate.Util;
+using IQueryable = NHibernate.Persister.Entity.IQueryable;
namespace NHibernate.Loader.Custom
{
@@ -23,6 +27,7 @@
private readonly SqlString sql;
private readonly ISet<string> querySpaces = new HashedSet<string>();
private readonly IDictionary<string, object> namedParameterBindPoints;
+ private List<IParameterSpecification> parametersSpecifications;
private readonly IQueryable[] entityPersisters;
private readonly int[] entityOwners;
@@ -38,6 +43,12 @@
private IType[] resultTypes;
private string[] transformerAliases;
+ public CustomLoader(ICustomQuery customQuery, IEnumerable<IParameterSpecification> parametersSpecifications, ISessionFactoryImplementor factory)
+ : this(customQuery, factory)
+ {
+ this.parametersSpecifications = parametersSpecifications.ToList();
+ }
+
public CustomLoader(ICustomQuery customQuery, ISessionFactoryImplementor factory) : base(factory)
{
sql = customQuery.SQL;
@@ -337,6 +348,92 @@
transformerAliases = aliases.ToArray();
}
+ public override ISqlCommand CreateSqlCommandInfo(QueryParameters queryParameters, ISessionImplementor session)
+ {
+ if(parametersSpecifications == null)
+ {
+ throw new InvalidOperationException("The custom SQL loader was not initialized with Parameters Specifications.");
+ }
+ // A distinct-copy of parameter specifications collected during query construction
+ var parameterSpecs = new HashSet<IParameterSpecification>(parametersSpecifications);
+ SqlString sqlString = SqlString.Copy();
+
+ // dynamic-filter parameters: during the HQL->SQL parsing, filters can be added as SQL_TOKEN/string and the SqlGenerator will not find it
+ //sqlString = ExpandDynamicFilterParameters(sqlString, parameterSpecs, session);
+ //AdjustQueryParametersForSubSelectFetching(sqlString, parameterSpecs, session, queryParameters); // NOTE: see TODO below
+
+ sqlString = AddLimitsParametersIfNeeded(sqlString, parameterSpecs, queryParameters, session);
+ // TODO: for sub-select fetching we have to try to assign the QueryParameter.ProcessedSQL here (with limits) but only after use IParameterSpecification for any kind of queries
+
+ // The PreprocessSQL method can modify the SqlString but should never add parameters (or we have to override it)
+ sqlString = PreprocessSQL(sqlString, queryParameters, session.Factory.Dialect);
+
+ // After the last modification to the SqlString we can collect all parameters types.
+ ResetEffectiveExpectedType(parameterSpecs, queryParameters); // <= TODO: remove this method when we can infer the type during the parse
+
+ return new SqlCommand.SqlCommandImpl(sqlString, parameterSpecs, queryParameters, session.Factory);
+ }
+
+ private SqlString AddLimitsParametersIfNeeded(SqlString sqlString, ICollection<IParameterSpecification> parameterSpecs, QueryParameters queryParameters, ISessionImplementor session)
+ {
+ var sessionFactory = session.Factory;
+ Dialect.Dialect dialect = sessionFactory.Dialect;
+
+ RowSelection selection = queryParameters.RowSelection;
+ bool useLimit = UseLimit(selection, dialect);
+ if (useLimit)
+ {
+ bool hasFirstRow = GetFirstRow(selection) > 0;
+ bool useOffset = hasFirstRow && dialect.SupportsLimitOffset;
+ int max = GetMaxOrLimit(dialect, selection);
+ int? skip = useOffset ? (int?)dialect.GetOffsetValue(GetFirstRow(selection)) : null;
+ int? take = max != int.MaxValue ? (int?)max : null;
+
+ Parameter skipSqlParameter = null;
+ Parameter takeSqlParameter = null;
+ if (skip.HasValue)
+ {
+ var skipParameter = new QuerySkipParameterSpecification();
+ skipSqlParameter = Parameter.Placeholder;
+ skipSqlParameter.BackTrack = skipParameter.GetIdsForBackTrack(sessionFactory).First();
+ parameterSpecs.Add(skipParameter);
+ }
+ if (take.HasValue)
+ {
+ var takeParameter = new QueryTakeParameterSpecification();
+ takeSqlParameter = Parameter.Placeholder;
+ takeSqlParameter.BackTrack = takeParameter.GetIdsForBackTrack(sessionFactory).First();
+ parameterSpecs.Add(takeParameter);
+ }
+ // The dialect can move the given parameters where he need, what it can't do is generates new parameters loosing the BackTrack.
+ return dialect.GetLimitString(sqlString, skip, take, skipSqlParameter, takeSqlParameter);
+ }
+ return sqlString;
+ }
+
+ private void ResetEffectiveExpectedType(IEnumerable<IParameterSpecification> parameterSpecs, QueryParameters queryParameters)
+ {
+ foreach (var parameterSpecification in parameterSpecs.OfType<IExplicitParameterSpecification>())
+ {
+ parameterSpecification.SetEffectiveType(queryParameters);
+ }
+ }
+
+ public IType[] ResultTypes
+ {
+ get { return resultTypes; }
+ }
+
+ public string[] ReturnAliases
+ {
+ get { return transformerAliases; }
+ }
+
+ public IEnumerable<string> NamedParameters
+ {
+ get { return namedParameterBindPoints.Keys; }
+ }
+
public class ResultRowProcessor
{
private readonly bool hasScalars;
@@ -402,21 +499,6 @@
}
}
- public IType[] ResultTypes
- {
- get { return resultTypes; }
- }
-
- public string[] ReturnAliases
- {
- get { return transformerAliases; }
- }
-
- public IEnumerable<string> NamedParameters
- {
- get { return namedParameterBindPoints.Keys; }
- }
-
public interface IResultColumnProcessor
{
object Extract(object[] data, IDataReader resultSet, ISessionImplementor session);
Modified: trunk/nhibernate/src/NHibernate/Loader/Custom/Sql/SQLCustomQuery.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Loader/Custom/Sql/SQLCustomQuery.cs 2011-06-07 01:47:49 UTC (rev 5914)
+++ trunk/nhibernate/src/NHibernate/Loader/Custom/Sql/SQLCustomQuery.cs 2011-06-12 22:04:44 UTC (rev 5915)
@@ -1,8 +1,10 @@
using System.Collections.Generic;
+using System.Linq;
using Iesi.Collections.Generic;
using NHibernate.Engine;
using NHibernate.Engine.Query.Sql;
+using NHibernate.Param;
using NHibernate.Persister.Collection;
using NHibernate.Persister.Entity;
using NHibernate.SqlCommand;
@@ -20,6 +22,7 @@
private readonly Dictionary<string, object> namedParameterBindPoints = new Dictionary<string, object>();
private readonly ISet<string> querySpaces = new HashedSet<string>();
private readonly SqlString sql;
+ private List<IParameterSpecification> parametersSpecifications;
public SQLCustomQuery(INativeSQLQueryReturn[] queryReturns, string sqlQuery, ICollection<string> additionalQuerySpaces,
ISessionFactoryImplementor factory)
@@ -28,10 +31,11 @@
SQLQueryReturnProcessor processor = new SQLQueryReturnProcessor(queryReturns, factory);
SQLQueryReturnProcessor.ResultAliasContext aliasContext = processor.Process();
- SQLQueryParser parser = new SQLQueryParser(sqlQuery, new ParserContext(aliasContext));
+ SQLQueryParser parser = new SQLQueryParser(factory, sqlQuery, new ParserContext(aliasContext));
sql = parser.Process();
ArrayHelper.AddAll(namedParameterBindPoints, parser.NamedParameters);
ArrayHelper.AddAll(customQueryReturns, processor.GenerateCustomReturns(parser.QueryHasAliases));
+ parametersSpecifications = parser.CollectedParametersSpecifications.ToList();
if (additionalQuerySpaces != null)
{
@@ -39,6 +43,11 @@
}
}
+ public IEnumerable<IParameterSpecification> CollectedParametersSpecifications
+ {
+ get { return parametersSpecifications; }
+ }
+
#region ICustomQuery Members
public SqlString SQL
Modified: trunk/nhibernate/src/NHibernate/Loader/Custom/Sql/SQLQueryParser.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Loader/Custom/Sql/SQLQueryParser.cs 2011-06-07 01:47:49 UTC (rev 5914)
+++ trunk/nhibernate/src/NHibernate/Loader/Custom/Sql/SQLQueryParser.cs 2011-06-12 22:04:44 UTC (rev 5915)
@@ -1,7 +1,10 @@
using System.Collections;
using System.Collections.Generic;
+using System.Linq;
using System.Text;
+using NHibernate.Engine;
using NHibernate.Engine.Query;
+using NHibernate.Param;
using NHibernate.Persister.Collection;
using NHibernate.Persister.Entity;
using NHibernate.SqlCommand;
@@ -21,15 +24,18 @@
IDictionary<string, string[]> GetPropertyResultsMapByAlias(string alias);
}
+ private readonly ISessionFactoryImplementor factory;
private readonly string originalQueryString;
private readonly IParserContext context;
private readonly Dictionary<string, object> namedParameters = new Dictionary<string, object>();
private long aliasesFound;
+ private IEnumerable<IParameterSpecification> parametersSpecifications;
- public SQLQueryParser(string sqlQuery, IParserContext context)
+ public SQLQueryParser(ISessionFactoryImplementor factory, string sqlQuery, IParserContext context)
{
+ this.factory = factory;
originalQueryString = sqlQuery;
this.context = context;
}
@@ -49,6 +55,11 @@
return SubstituteParams(SubstituteBrackets());
}
+ public IEnumerable<IParameterSpecification> CollectedParametersSpecifications
+ {
+ get { return parametersSpecifications; }
+ }
+
// TODO: should "record" how many properties we have reffered to - and if we
// don't get'em'all we throw an exception! Way better than trial and error ;)
private string SubstituteBrackets()
@@ -239,9 +250,9 @@
/// <returns> The SQL query with parameter substitution complete. </returns>
private SqlString SubstituteParams(string sqlString)
{
- ParameterSubstitutionRecognizer recognizer = new ParameterSubstitutionRecognizer();
+ var recognizer = new ParameterSubstitutionRecognizer(factory);
ParameterParser.Parse(sqlString, recognizer);
-
+ parametersSpecifications = recognizer.ParametersSpecifications.ToList();
namedParameters.Clear();
foreach (KeyValuePair<string, object> de in recognizer.namedParameterBindPoints)
{
@@ -253,24 +264,49 @@
public class ParameterSubstitutionRecognizer : ParameterParser.IRecognizer
{
+ private readonly ISessionFactoryImplementor factory;
internal SqlStringBuilder result = new SqlStringBuilder();
internal Dictionary<string, object> namedParameterBindPoints = new Dictionary<string, object>();
internal int parameterCount = 0;
+ private readonly List<IParameterSpecification> parametersSpecifications = new List<IParameterSpecification>();
+ private int positionalParameterCount;
+ public ParameterSubstitutionRecognizer(ISessionFactoryImplementor factory)
+ {
+ this.factory = factory;
+ }
+
+ public IEnumerable<IParameterSpecification> ParametersSpecifications
+ {
+ get { return parametersSpecifications; }
+ }
+
public void OutParameter(int position)
{
- result.Add(Parameter.Placeholder);
+ var paramSpec = new PositionalParameterSpecification(1, position, positionalParameterCount++);
+ var parameter = Parameter.Placeholder;
+ parameter.BackTrack = paramSpec.GetIdsForBackTrack(factory).First();
+ parametersSpecifications.Add(paramSpec);
+ result.Add(parameter);
}
public void OrdinalParameter(int position)
{
- result.Add(Parameter.Placeholder);
+ var paramSpec = new PositionalParameterSpecification(1, position, positionalParameterCount++);
+ var parameter = Parameter.Placeholder;
+ parameter.BackTrack = paramSpec.GetIdsForBackTrack(factory).First();
+ parametersSpecifications.Add(paramSpec);
+ result.Add(parameter);
}
public void NamedParameter(string name, int position)
{
AddNamedParameter(name);
- result.Add(Parameter.Placeholder);
+ var paramSpec = new NamedParameterSpecification(1, position, name);
+ var parameter = Parameter.Placeholder;
+ parameter.BackTrack = paramSpec.GetIdsForBackTrack(factory).First();
+ parametersSpecifications.Add(paramSpec);
+ result.Add(parameter);
}
public void JpaPositionalParameter(string name, int position)
Modified: trunk/nhibernate/src/NHibernate/Loader/Loader.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Loader/Loader.cs 2011-06-07 01:47:49 UTC (rev 5914)
+++ trunk/nhibernate/src/NHibernate/Loader/Loader.cs 2011-06-12 22:04:44 UTC (rev 5915)
@@ -1785,6 +1785,11 @@
return new SqlCommandInfo(sqlString, sqlTypes);
}
+ public virtual ISqlCommand CreateSqlCommandInfo(QueryParameters queryParameters, ISessionImplementor session)
+ {
+ throw new NotSupportedException("This loader does not support extraction of single command.");
+ }
+
#endregion
}
}
Modified: trunk/nhibernate/src/NHibernate/NHibernate.csproj
===================================================================
--- trunk/nhibernate/src/NHibernate/NHibernate.csproj 2011-06-07 01:47:49 UTC (rev 5914)
+++ trunk/nhibernate/src/NHibernate/NHibernate.csproj 2011-06-12 22:04:44 UTC (rev 5915)
@@ -569,6 +569,7 @@
<Compile Include="SqlCommand\SqlBaseBuilder.cs" />
<Compile Include="SqlCommand\SqlDeleteBuilder.cs" />
<Compile Include="SqlCommand\SqlInsertBuilder.cs" />
+ <Compile Include="SqlCommand\SqlCommandImpl.cs" />
<Compile Include="SqlCommand\SqlSelectBuilder.cs" />
<Compile Include="SqlCommand\SqlSimpleSelectBuilder.cs" />
<Compile Include="SqlCommand\SqlString.cs" />
Modified: trunk/nhibernate/src/NHibernate/Param/AbstractExplicitParameterSpecification.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Param/AbstractExplicitParameterSpecification.cs 2011-06-07 01:47:49 UTC (rev 5914)
+++ trunk/nhibernate/src/NHibernate/Param/AbstractExplicitParameterSpecification.cs 2011-06-12 22:04:44 UTC (rev 5915)
@@ -40,6 +40,7 @@
public abstract string RenderDisplayInfo();
public abstract IEnumerable<string> GetIdsForBackTrack(IMapping sessionFactory);
public abstract void Bind(IDbCommand command, IList<Parameter> sqlQueryParametersList, QueryParameters queryParameters, ISessionImplementor session);
+ public abstract void Bind(IDbCommand command, IList<Parameter> multiSqlQueryParametersList, int singleSqlParametersOffset, IList<Parameter> sqlQueryParametersList, QueryParameters queryParameters, ISessionImplementor session);
public abstract void SetEffectiveType(QueryParameters queryParameters);
#endregion
Modified: trunk/nhibernate/src/NHibernate/Param/AggregatedIndexCollectionSelectorParameterSpecifications.cs
===================================================================
--- trunk/nhibernate/src/NH...
[truncated message content] |
|
From: <fab...@us...> - 2011-06-13 12:31:36
|
Revision: 5917
http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5917&view=rev
Author: fabiomaulo
Date: 2011-06-13 12:31:25 +0000 (Mon, 13 Jun 2011)
Log Message:
-----------
Refactoring:
- method renaming
- first DRY in QueryLoader
Modified Paths:
--------------
trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Loader/QueryLoader.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/Param/ParametersBackTrackExtensions.cs
trunk/nhibernate/src/NHibernate/SqlCommand/SqlCommandImpl.cs
Modified: trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Loader/QueryLoader.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Loader/QueryLoader.cs 2011-06-12 22:10:16 UTC (rev 5916)
+++ trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Loader/QueryLoader.cs 2011-06-13 12:31:25 UTC (rev 5917)
@@ -436,9 +436,8 @@
return result;
}
- public override ISqlCommand CreateSqlCommandInfo(QueryParameters queryParameters, ISessionImplementor session)
+ public override ISqlCommand CreateSqlCommand(QueryParameters queryParameters, ISessionImplementor session)
{
- // NOTE: repeated code PrepareQueryCommand
// A distinct-copy of parameter specifications collected during query construction
var parameterSpecs = new HashSet<IParameterSpecification>(_queryTranslator.CollectedParameterSpecifications);
SqlString sqlString = SqlString.Copy();
@@ -456,7 +455,7 @@
// After the last modification to the SqlString we can collect all parameters types.
ResetEffectiveExpectedType(parameterSpecs, queryParameters); // <= TODO: remove this method when we can infer the type during the parse
- return new SqlCommand.SqlCommandImpl(sqlString, parameterSpecs, queryParameters, session.Factory);
+ return new SqlCommandImpl(sqlString, parameterSpecs, queryParameters, session.Factory);
}
/// <summary>
@@ -473,31 +472,14 @@
/// <returns>A CommandWrapper wrapping an IDbCommand that is ready to be executed.</returns>
protected internal override IDbCommand PrepareQueryCommand(QueryParameters queryParameters, bool scroll, ISessionImplementor session)
{
- // NH: In this QueryLoader we can know better all parameters used so we can simplify the IDbCommand construction
- // NH: would be very useful if we can do the same with Criteria. This method works just for HQL and LINQ.
-
- // A distinct-copy of parameter specifications collected during query construction
- var parameterSpecs = new HashSet<IParameterSpecification>(_queryTranslator.CollectedParameterSpecifications);
- SqlString sqlString = SqlString.Copy();
-
- // dynamic-filter parameters: during the HQL->SQL parsing, filters can be added as SQL_TOKEN/string and the SqlGenerator will not find it
- sqlString = ExpandDynamicFilterParameters(sqlString, parameterSpecs, session);
- AdjustQueryParametersForSubSelectFetching(sqlString, parameterSpecs, session, queryParameters); // NOTE: see TODO below
-
- sqlString = AddLimitsParametersIfNeeded(sqlString, parameterSpecs, queryParameters, session);
- // TODO: for sub-select fetching we have to try to assign the QueryParameter.ProcessedSQL here (with limits) but only after use IParameterSpecification for any kind of queries
-
- // The PreprocessSQL method can modify the SqlString but should never add parameters (or we have to override it)
- sqlString = PreprocessSQL(sqlString, queryParameters, session.Factory.Dialect);
-
- // After the last modification to the SqlString we can collect all parameters types.
- ResetEffectiveExpectedType(parameterSpecs, queryParameters); // <= TODO: remove this method when we can infer the type during the parse
- var sqlQueryParametersList = sqlString.GetParameters().ToList();
- SqlType[] parameterTypes = parameterSpecs.GetQueryParameterTypes(sqlQueryParametersList, session.Factory);
+ var sqlCommand = (SqlCommandImpl)CreateSqlCommand(queryParameters, session);
+ var parameterSpecs = sqlCommand.Specifications;
+ var sqlString = sqlCommand.Query;
+ var sqlQueryParametersList = sqlCommand.SqlQueryParametersList;
parameterSpecs.SetQueryParameterLocations(sqlQueryParametersList, session.Factory);
- IDbCommand command = session.Batcher.PrepareQueryCommand(CommandType.Text, sqlString, parameterTypes);
+ IDbCommand command = session.Batcher.PrepareQueryCommand(CommandType.Text, sqlString, sqlCommand.ParameterTypes);
try
{
@@ -507,7 +489,7 @@
command.CommandTimeout = selection.Timeout;
}
- BindParametersValues(command, sqlQueryParametersList, parameterSpecs, queryParameters, session);
+ sqlCommand.Bind(command, sqlQueryParametersList, 0, session);
session.Batcher.ExpandQueryParameters(command, sqlString);
}
@@ -678,21 +660,5 @@
parameterSpecification.SetEffectiveType(queryParameters);
}
}
-
- /// <summary>
- /// Bind all parameters values.
- /// </summary>
- /// <param name="command">The command where bind each value.</param>
- /// <param name="sqlQueryParametersList">The list of Sql query parameter in the exact sequence they are present in the query.</param>
- /// <param name="parameterSpecs">All parameter-specifications collected during query construction.</param>
- /// <param name="queryParameters">The encapsulation of the parameter values to be bound.</param>
- /// <param name="session">The session from where execute the query.</param>
- private void BindParametersValues(IDbCommand command, IList<Parameter> sqlQueryParametersList, IEnumerable<IParameterSpecification> parameterSpecs, QueryParameters queryParameters, ISessionImplementor session)
- {
- foreach (var parameterSpecification in parameterSpecs)
- {
- parameterSpecification.Bind(command, sqlQueryParametersList, queryParameters, session);
- }
- }
}
}
\ No newline at end of file
Modified: trunk/nhibernate/src/NHibernate/Impl/MultiCriteriaImpl.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Impl/MultiCriteriaImpl.cs 2011-06-12 22:10:16 UTC (rev 5916)
+++ trunk/nhibernate/src/NHibernate/Impl/MultiCriteriaImpl.cs 2011-06-13 12:31:25 UTC (rev 5917)
@@ -183,7 +183,7 @@
translators.Add(translator);
QueryParameters queryParameters = translator.GetQueryParameters();
parameters.Add(queryParameters);
- ISqlCommand singleCommand = loader.CreateSqlCommandInfo(queryParameters, session);
+ ISqlCommand singleCommand = loader.CreateSqlCommand(queryParameters, session);
resultSetsCommand.Append(singleCommand);
}
}
Modified: trunk/nhibernate/src/NHibernate/Impl/MultiQueryImpl.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Impl/MultiQueryImpl.cs 2011-06-12 22:10:16 UTC (rev 5916)
+++ trunk/nhibernate/src/NHibernate/Impl/MultiQueryImpl.cs 2011-06-13 12:31:25 UTC (rev 5917)
@@ -640,7 +640,7 @@
{
translators.Add(translator);
parameters.Add(queryParameters);
- ISqlCommand singleCommand = translator.Loader.CreateSqlCommandInfo(queryParameters, session);
+ ISqlCommand singleCommand = translator.Loader.CreateSqlCommand(queryParameters, session);
resultSetsCommand.Append(singleCommand);
}
}
Modified: trunk/nhibernate/src/NHibernate/Loader/Criteria/CriteriaLoader.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Loader/Criteria/CriteriaLoader.cs 2011-06-12 22:10:16 UTC (rev 5916)
+++ trunk/nhibernate/src/NHibernate/Loader/Criteria/CriteriaLoader.cs 2011-06-13 12:31:25 UTC (rev 5917)
@@ -185,7 +185,7 @@
return customResultTransformer.TransformList(results);
}
- public override ISqlCommand CreateSqlCommandInfo(QueryParameters queryParameters, ISessionImplementor session)
+ public override ISqlCommand CreateSqlCommand(QueryParameters queryParameters, ISessionImplementor session)
{
// NOTE: repeated code PrepareQueryCommand
// A distinct-copy of parameter specifications collected during query construction
Modified: trunk/nhibernate/src/NHibernate/Loader/Custom/CustomLoader.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Loader/Custom/CustomLoader.cs 2011-06-12 22:10:16 UTC (rev 5916)
+++ trunk/nhibernate/src/NHibernate/Loader/Custom/CustomLoader.cs 2011-06-13 12:31:25 UTC (rev 5917)
@@ -348,7 +348,7 @@
transformerAliases = aliases.ToArray();
}
- public override ISqlCommand CreateSqlCommandInfo(QueryParameters queryParameters, ISessionImplementor session)
+ public override ISqlCommand CreateSqlCommand(QueryParameters queryParameters, ISessionImplementor session)
{
if(parametersSpecifications == null)
{
Modified: trunk/nhibernate/src/NHibernate/Loader/Loader.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Loader/Loader.cs 2011-06-12 22:10:16 UTC (rev 5916)
+++ trunk/nhibernate/src/NHibernate/Loader/Loader.cs 2011-06-13 12:31:25 UTC (rev 5917)
@@ -1785,7 +1785,7 @@
return new SqlCommandInfo(sqlString, sqlTypes);
}
- public virtual ISqlCommand CreateSqlCommandInfo(QueryParameters queryParameters, ISessionImplementor session)
+ public virtual ISqlCommand CreateSqlCommand(QueryParameters queryParameters, ISessionImplementor session)
{
throw new NotSupportedException("This loader does not support extraction of single command.");
}
Modified: trunk/nhibernate/src/NHibernate/Param/ParametersBackTrackExtensions.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Param/ParametersBackTrackExtensions.cs 2011-06-12 22:10:16 UTC (rev 5916)
+++ trunk/nhibernate/src/NHibernate/Param/ParametersBackTrackExtensions.cs 2011-06-13 12:31:25 UTC (rev 5917)
@@ -20,7 +20,7 @@
}
}
- public static SqlType[] GetQueryParameterTypes(this ICollection<IParameterSpecification> parameterSpecs, List<Parameter> sqlQueryParametersList, ISessionFactoryImplementor factory)
+ public static SqlType[] GetQueryParameterTypes(this IEnumerable<IParameterSpecification> parameterSpecs, List<Parameter> sqlQueryParametersList, ISessionFactoryImplementor factory)
{
// due to IType.NullSafeSet(System.Data.IDbCommand , object, int, ISessionImplementor) the SqlType[] is supposed to be in a certain sequence.
// here we can check and evetually Assert (see AssertionFailure) the supposition because each individual Parameter has its BackTrackId.
@@ -44,7 +44,7 @@
/// <param name="parameterSpecs"></param>
/// <param name="sqlQueryParametersList"></param>
/// <param name="factory"></param>
- public static void SetQueryParameterLocations(this ICollection<IParameterSpecification> parameterSpecs, List<Parameter> sqlQueryParametersList, ISessionFactoryImplementor factory)
+ public static void SetQueryParameterLocations(this IEnumerable<IParameterSpecification> parameterSpecs, List<Parameter> sqlQueryParametersList, ISessionFactoryImplementor factory)
{
// due to IType.NullSafeSet(System.Data.IDbCommand , object, int, ISessionImplementor) the SqlType[] is supposed to be in a certain sequence.
// this mean that found the first location of a parameter for the IType span, the others are in secuence
Modified: trunk/nhibernate/src/NHibernate/SqlCommand/SqlCommandImpl.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/SqlCommand/SqlCommandImpl.cs 2011-06-12 22:10:16 UTC (rev 5916)
+++ trunk/nhibernate/src/NHibernate/SqlCommand/SqlCommandImpl.cs 2011-06-13 12:31:25 UTC (rev 5917)
@@ -40,7 +40,7 @@
this.factory = factory;
}
- private List<Parameter> SqlQueryParametersList
+ public List<Parameter> SqlQueryParametersList
{
get { return sqlQueryParametersList ?? (sqlQueryParametersList = query.GetParameters().ToList()); }
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <fab...@us...> - 2011-06-13 12:51:53
|
Revision: 5919
http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5919&view=rev
Author: fabiomaulo
Date: 2011-06-13 12:51:47 +0000 (Mon, 13 Jun 2011)
Log Message:
-----------
Refactoring: Extracted extensions method
Modified Paths:
--------------
trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Loader/QueryLoader.cs
trunk/nhibernate/src/NHibernate/Loader/Custom/CustomLoader.cs
trunk/nhibernate/src/NHibernate/Param/ParametersBackTrackExtensions.cs
Modified: trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Loader/QueryLoader.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Loader/QueryLoader.cs 2011-06-13 12:48:08 UTC (rev 5918)
+++ trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Loader/QueryLoader.cs 2011-06-13 12:51:47 UTC (rev 5919)
@@ -453,7 +453,7 @@
sqlString = PreprocessSQL(sqlString, queryParameters, session.Factory.Dialect);
// After the last modification to the SqlString we can collect all parameters types.
- ResetEffectiveExpectedType(parameterSpecs, queryParameters); // <= TODO: remove this method when we can infer the type during the parse
+ parameterSpecs.ResetEffectiveExpectedType(queryParameters);
return new SqlCommandImpl(sqlString, parameterSpecs, queryParameters, session.Factory);
}
@@ -652,13 +652,5 @@
}
return sqlString;
}
-
- private void ResetEffectiveExpectedType(IEnumerable<IParameterSpecification> parameterSpecs, QueryParameters queryParameters)
- {
- foreach (var parameterSpecification in parameterSpecs.OfType<IExplicitParameterSpecification>())
- {
- parameterSpecification.SetEffectiveType(queryParameters);
- }
- }
}
}
\ No newline at end of file
Modified: trunk/nhibernate/src/NHibernate/Loader/Custom/CustomLoader.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Loader/Custom/CustomLoader.cs 2011-06-13 12:48:08 UTC (rev 5918)
+++ trunk/nhibernate/src/NHibernate/Loader/Custom/CustomLoader.cs 2011-06-13 12:51:47 UTC (rev 5919)
@@ -369,7 +369,7 @@
sqlString = PreprocessSQL(sqlString, queryParameters, session.Factory.Dialect);
// After the last modification to the SqlString we can collect all parameters types.
- ResetEffectiveExpectedType(parameterSpecs, queryParameters); // <= TODO: remove this method when we can infer the type during the parse
+ parameterSpecs.ResetEffectiveExpectedType(queryParameters);
return new SqlCommand.SqlCommandImpl(sqlString, parameterSpecs, queryParameters, session.Factory);
}
@@ -411,14 +411,6 @@
return sqlString;
}
- private void ResetEffectiveExpectedType(IEnumerable<IParameterSpecification> parameterSpecs, QueryParameters queryParameters)
- {
- foreach (var parameterSpecification in parameterSpecs.OfType<IExplicitParameterSpecification>())
- {
- parameterSpecification.SetEffectiveType(queryParameters);
- }
- }
-
public IType[] ResultTypes
{
get { return resultTypes; }
Modified: trunk/nhibernate/src/NHibernate/Param/ParametersBackTrackExtensions.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Param/ParametersBackTrackExtensions.cs 2011-06-13 12:48:08 UTC (rev 5918)
+++ trunk/nhibernate/src/NHibernate/Param/ParametersBackTrackExtensions.cs 2011-06-13 12:51:47 UTC (rev 5919)
@@ -38,6 +38,15 @@
return typesSequence.SelectMany(t => t.SqlTypes(factory)).ToArray();
}
+ public static void ResetEffectiveExpectedType(this IEnumerable<IParameterSpecification> parameterSpecs, QueryParameters queryParameters)
+ {
+ // TODO: remove this method when we can infer the type during the parse
+ foreach (var parameterSpecification in parameterSpecs.OfType<IExplicitParameterSpecification>())
+ {
+ parameterSpecification.SetEffectiveType(queryParameters);
+ }
+ }
+
/// <summary>
/// Influence the final name of the parameter.
/// </summary>
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <fab...@us...> - 2011-06-13 13:04:30
|
Revision: 5920
http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5920&view=rev
Author: fabiomaulo
Date: 2011-06-13 13:04:23 +0000 (Mon, 13 Jun 2011)
Log Message:
-----------
Refactoring:
- DRY
- removed dead-code
Modified Paths:
--------------
trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Loader/QueryLoader.cs
trunk/nhibernate/src/NHibernate/Loader/Criteria/CriteriaLoader.cs
trunk/nhibernate/src/NHibernate/Loader/Custom/CustomLoader.cs
trunk/nhibernate/src/NHibernate/Loader/Loader.cs
Modified: trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Loader/QueryLoader.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Loader/QueryLoader.cs 2011-06-13 12:51:47 UTC (rev 5919)
+++ trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Loader/QueryLoader.cs 2011-06-13 13:04:23 UTC (rev 5920)
@@ -1,5 +1,4 @@
using System;
-using System.Linq;
using System.Collections;
using System.Collections.Generic;
using System.Data;
@@ -7,14 +6,12 @@
using NHibernate.Engine;
using NHibernate.Event;
using NHibernate.Hql.Ast.ANTLR.Tree;
-using NHibernate.Hql.Classic;
using NHibernate.Impl;
using NHibernate.Loader;
using NHibernate.Param;
using NHibernate.Persister.Collection;
using NHibernate.Persister.Entity;
using NHibernate.SqlCommand;
-using NHibernate.SqlTypes;
using NHibernate.Transform;
using NHibernate.Type;
using NHibernate.Util;
@@ -506,151 +503,5 @@
}
return command;
}
-
- private void AdjustQueryParametersForSubSelectFetching(SqlString sqlString, IEnumerable<IParameterSpecification> parameterSpecs, ISessionImplementor session, QueryParameters queryParameters)
- {
- // TODO: Remove this when all parameters are managed using IParameterSpecification (QueryParameters does not need to have decomposed values for filters)
-
- var dynamicFilterParameterSpecifications = parameterSpecs.OfType<DynamicFilterParameterSpecification>().ToList();
- var filteredParameterValues = new List<object>();
- var filteredParameterTypes = new List<IType>();
- var filteredParameterLocations = new List<int>();
-
- if (dynamicFilterParameterSpecifications.Count != 0)
- {
- var sqlQueryParametersList = sqlString.GetParameters().ToList();
- foreach (DynamicFilterParameterSpecification specification in dynamicFilterParameterSpecifications)
- {
- string backTrackId = specification.GetIdsForBackTrack(session.Factory).First();
- object value = session.GetFilterParameterValue(specification.FilterParameterFullName);
- var elementType = specification.ExpectedType;
- foreach (int position in sqlQueryParametersList.GetEffectiveParameterLocations(backTrackId))
- {
- filteredParameterValues.Add(value);
- filteredParameterTypes.Add(elementType);
- filteredParameterLocations.Add(position);
- }
- }
- }
-
- queryParameters.ProcessedSql = sqlString;
- queryParameters.FilteredParameterLocations = filteredParameterLocations;
- queryParameters.FilteredParameterTypes = filteredParameterTypes;
- queryParameters.FilteredParameterValues = filteredParameterValues;
- }
-
- private SqlString ExpandDynamicFilterParameters(SqlString sqlString, ICollection<IParameterSpecification> parameterSpecs, ISessionImplementor session)
- {
- var enabledFilters = session.EnabledFilters;
- if (enabledFilters.Count == 0 || sqlString.ToString().IndexOf(ParserHelper.HqlVariablePrefix) < 0)
- {
- return sqlString;
- }
-
- Dialect.Dialect dialect = session.Factory.Dialect;
- string symbols = ParserHelper.HqlSeparators + dialect.OpenQuote + dialect.CloseQuote;
-
- var originSql = sqlString.Compact();
- var result = new SqlStringBuilder();
- foreach (var sqlPart in originSql.Parts)
- {
- var parameter = sqlPart as Parameter;
- if (parameter != null)
- {
- result.Add(parameter);
- continue;
- }
-
- var sqlFragment = sqlPart.ToString();
- var tokens = new StringTokenizer(sqlFragment, symbols, true);
-
- foreach (string token in tokens)
- {
- if (token.StartsWith(ParserHelper.HqlVariablePrefix))
- {
- string filterParameterName = token.Substring(1);
- string[] parts = StringHelper.ParseFilterParameterName(filterParameterName);
- string filterName = parts[0];
- string parameterName = parts[1];
- var filter = (FilterImpl)enabledFilters[filterName];
-
- object value = filter.GetParameter(parameterName);
- IType type = filter.FilterDefinition.GetParameterType(parameterName);
- int parameterColumnSpan = type.GetColumnSpan(session.Factory);
- var collectionValue = value as ICollection;
- int? collectionSpan = null;
-
- // Add query chunk
- string typeBindFragment = string.Join(", ", Enumerable.Repeat("?", parameterColumnSpan).ToArray());
- string bindFragment;
- if (collectionValue != null && !type.ReturnedClass.IsArray)
- {
- collectionSpan = collectionValue.Count;
- bindFragment = string.Join(", ", Enumerable.Repeat(typeBindFragment, collectionValue.Count).ToArray());
- }
- else
- {
- bindFragment = typeBindFragment;
- }
-
- // dynamic-filter parameter tracking
- var filterParameterFragment = SqlString.Parse(bindFragment);
- var dynamicFilterParameterSpecification = new DynamicFilterParameterSpecification(filterName, parameterName, type, collectionSpan);
- var parameters = filterParameterFragment.GetParameters().ToArray();
- var sqlParameterPos = 0;
- var paramTrackers = dynamicFilterParameterSpecification.GetIdsForBackTrack(session.Factory);
- foreach (var paramTracker in paramTrackers)
- {
- parameters[sqlParameterPos++].BackTrack = paramTracker;
- }
-
- parameterSpecs.Add(dynamicFilterParameterSpecification);
- result.Add(filterParameterFragment);
- }
- else
- {
- result.Add(token);
- }
- }
- }
- return result.ToSqlString().Compact();
- }
-
- private SqlString AddLimitsParametersIfNeeded(SqlString sqlString, ICollection<IParameterSpecification> parameterSpecs, QueryParameters queryParameters, ISessionImplementor session)
- {
- var sessionFactory = session.Factory;
- Dialect.Dialect dialect = sessionFactory.Dialect;
-
- RowSelection selection = queryParameters.RowSelection;
- bool useLimit = UseLimit(selection, dialect);
- if (useLimit)
- {
- bool hasFirstRow = GetFirstRow(selection) > 0;
- bool useOffset = hasFirstRow && dialect.SupportsLimitOffset;
- int max = GetMaxOrLimit(dialect, selection);
- int? skip = useOffset ? (int?) dialect.GetOffsetValue(GetFirstRow(selection)) : null;
- int? take = max != int.MaxValue ? (int?) max : null;
-
- Parameter skipSqlParameter = null;
- Parameter takeSqlParameter = null;
- if (skip.HasValue)
- {
- var skipParameter = new QuerySkipParameterSpecification();
- skipSqlParameter = Parameter.Placeholder;
- skipSqlParameter.BackTrack = skipParameter.GetIdsForBackTrack(sessionFactory).First();
- parameterSpecs.Add(skipParameter);
- }
- if (take.HasValue)
- {
- var takeParameter = new QueryTakeParameterSpecification();
- takeSqlParameter = Parameter.Placeholder;
- takeSqlParameter.BackTrack = takeParameter.GetIdsForBackTrack(sessionFactory).First();
- parameterSpecs.Add(takeParameter);
- }
- // The dialect can move the given parameters where he need, what it can't do is generates new parameters loosing the BackTrack.
- return dialect.GetLimitString(sqlString, skip, take, skipSqlParameter, takeSqlParameter);
- }
- return sqlString;
- }
}
}
\ No newline at end of file
Modified: trunk/nhibernate/src/NHibernate/Loader/Criteria/CriteriaLoader.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Loader/Criteria/CriteriaLoader.cs 2011-06-13 12:51:47 UTC (rev 5919)
+++ trunk/nhibernate/src/NHibernate/Loader/Criteria/CriteriaLoader.cs 2011-06-13 13:04:23 UTC (rev 5920)
@@ -2,15 +2,12 @@
using System.Collections;
using System.Collections.Generic;
using System.Data;
-using System.Linq;
using Iesi.Collections.Generic;
using NHibernate.Engine;
-using NHibernate.Hql.Classic;
using NHibernate.Impl;
using NHibernate.Param;
using NHibernate.Persister.Entity;
using NHibernate.SqlCommand;
-using NHibernate.SqlTypes;
using NHibernate.Transform;
using NHibernate.Type;
using NHibernate.Util;
@@ -256,151 +253,5 @@
{
return new int[0];
}
-
- private void AdjustQueryParametersForSubSelectFetching(SqlString sqlString, IEnumerable<IParameterSpecification> parameterSpecs, ISessionImplementor session, QueryParameters queryParameters)
- {
- // TODO: Remove this when all parameters are managed using IParameterSpecification (QueryParameters does not need to have decomposed values for filters)
-
- var dynamicFilterParameterSpecifications = parameterSpecs.OfType<DynamicFilterParameterSpecification>().ToList();
- var filteredParameterValues = new List<object>();
- var filteredParameterTypes = new List<IType>();
- var filteredParameterLocations = new List<int>();
-
- if (dynamicFilterParameterSpecifications.Count != 0)
- {
- var sqlQueryParametersList = sqlString.GetParameters().ToList();
- foreach (DynamicFilterParameterSpecification specification in dynamicFilterParameterSpecifications)
- {
- string backTrackId = specification.GetIdsForBackTrack(session.Factory).First();
- object value = session.GetFilterParameterValue(specification.FilterParameterFullName);
- var elementType = specification.ExpectedType;
- foreach (int position in sqlQueryParametersList.GetEffectiveParameterLocations(backTrackId))
- {
- filteredParameterValues.Add(value);
- filteredParameterTypes.Add(elementType);
- filteredParameterLocations.Add(position);
- }
- }
- }
-
- queryParameters.ProcessedSql = sqlString;
- queryParameters.FilteredParameterLocations = filteredParameterLocations;
- queryParameters.FilteredParameterTypes = filteredParameterTypes;
- queryParameters.FilteredParameterValues = filteredParameterValues;
- }
-
- private SqlString ExpandDynamicFilterParameters(SqlString sqlString, ICollection<IParameterSpecification> parameterSpecs, ISessionImplementor session)
- {
- var enabledFilters = session.EnabledFilters;
- if (enabledFilters.Count == 0 || sqlString.ToString().IndexOf(ParserHelper.HqlVariablePrefix) < 0)
- {
- return sqlString;
- }
-
- Dialect.Dialect dialect = session.Factory.Dialect;
- string symbols = ParserHelper.HqlSeparators + dialect.OpenQuote + dialect.CloseQuote;
-
- var originSql = sqlString.Compact();
- var result = new SqlStringBuilder();
- foreach (var sqlPart in originSql.Parts)
- {
- var parameter = sqlPart as Parameter;
- if (parameter != null)
- {
- result.Add(parameter);
- continue;
- }
-
- var sqlFragment = sqlPart.ToString();
- var tokens = new StringTokenizer(sqlFragment, symbols, true);
-
- foreach (string token in tokens)
- {
- if (token.StartsWith(ParserHelper.HqlVariablePrefix))
- {
- string filterParameterName = token.Substring(1);
- string[] parts = StringHelper.ParseFilterParameterName(filterParameterName);
- string filterName = parts[0];
- string parameterName = parts[1];
- var filter = (FilterImpl)enabledFilters[filterName];
-
- object value = filter.GetParameter(parameterName);
- IType type = filter.FilterDefinition.GetParameterType(parameterName);
- int parameterColumnSpan = type.GetColumnSpan(session.Factory);
- var collectionValue = value as ICollection;
- int? collectionSpan = null;
-
- // Add query chunk
- string typeBindFragment = string.Join(", ", Enumerable.Repeat("?", parameterColumnSpan).ToArray());
- string bindFragment;
- if (collectionValue != null && !type.ReturnedClass.IsArray)
- {
- collectionSpan = collectionValue.Count;
- bindFragment = string.Join(", ", Enumerable.Repeat(typeBindFragment, collectionValue.Count).ToArray());
- }
- else
- {
- bindFragment = typeBindFragment;
- }
-
- // dynamic-filter parameter tracking
- var filterParameterFragment = SqlString.Parse(bindFragment);
- var dynamicFilterParameterSpecification = new DynamicFilterParameterSpecification(filterName, parameterName, type, collectionSpan);
- var parameters = filterParameterFragment.GetParameters().ToArray();
- var sqlParameterPos = 0;
- var paramTrackers = dynamicFilterParameterSpecification.GetIdsForBackTrack(session.Factory);
- foreach (var paramTracker in paramTrackers)
- {
- parameters[sqlParameterPos++].BackTrack = paramTracker;
- }
-
- parameterSpecs.Add(dynamicFilterParameterSpecification);
- result.Add(filterParameterFragment);
- }
- else
- {
- result.Add(token);
- }
- }
- }
- return result.ToSqlString().Compact();
- }
-
- private SqlString AddLimitsParametersIfNeeded(SqlString sqlString, ICollection<IParameterSpecification> parameterSpecs, QueryParameters queryParameters, ISessionImplementor session)
- {
- var sessionFactory = session.Factory;
- Dialect.Dialect dialect = sessionFactory.Dialect;
-
- RowSelection selection = queryParameters.RowSelection;
- bool useLimit = UseLimit(selection, dialect);
- if (useLimit)
- {
- bool hasFirstRow = GetFirstRow(selection) > 0;
- bool useOffset = hasFirstRow && dialect.SupportsLimitOffset;
- int max = GetMaxOrLimit(dialect, selection);
- int? skip = useOffset ? (int?)dialect.GetOffsetValue(GetFirstRow(selection)) : null;
- int? take = max != int.MaxValue ? (int?)max : null;
-
- Parameter skipSqlParameter = null;
- Parameter takeSqlParameter = null;
- if (skip.HasValue)
- {
- var skipParameter = new QuerySkipParameterSpecification();
- skipSqlParameter = Parameter.Placeholder;
- skipSqlParameter.BackTrack = skipParameter.GetIdsForBackTrack(sessionFactory).First();
- parameterSpecs.Add(skipParameter);
- }
- if (take.HasValue)
- {
- var takeParameter = new QueryTakeParameterSpecification();
- takeSqlParameter = Parameter.Placeholder;
- takeSqlParameter.BackTrack = takeParameter.GetIdsForBackTrack(sessionFactory).First();
- parameterSpecs.Add(takeParameter);
- }
- // The dialect can move the given parameters where he need, what it can't do is generates new parameters loosing the BackTrack.
- return dialect.GetLimitString(sqlString, skip, take, skipSqlParameter, takeSqlParameter);
- }
- return sqlString;
- }
}
}
\ No newline at end of file
Modified: trunk/nhibernate/src/NHibernate/Loader/Custom/CustomLoader.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Loader/Custom/CustomLoader.cs 2011-06-13 12:51:47 UTC (rev 5919)
+++ trunk/nhibernate/src/NHibernate/Loader/Custom/CustomLoader.cs 2011-06-13 13:04:23 UTC (rev 5920)
@@ -374,43 +374,6 @@
return new SqlCommand.SqlCommandImpl(sqlString, parameterSpecs, queryParameters, session.Factory);
}
- private SqlString AddLimitsParametersIfNeeded(SqlString sqlString, ICollection<IParameterSpecification> parameterSpecs, QueryParameters queryParameters, ISessionImplementor session)
- {
- var sessionFactory = session.Factory;
- Dialect.Dialect dialect = sessionFactory.Dialect;
-
- RowSelection selection = queryParameters.RowSelection;
- bool useLimit = UseLimit(selection, dialect);
- if (useLimit)
- {
- bool hasFirstRow = GetFirstRow(selection) > 0;
- bool useOffset = hasFirstRow && dialect.SupportsLimitOffset;
- int max = GetMaxOrLimit(dialect, selection);
- int? skip = useOffset ? (int?)dialect.GetOffsetValue(GetFirstRow(selection)) : null;
- int? take = max != int.MaxValue ? (int?)max : null;
-
- Parameter skipSqlParameter = null;
- Parameter takeSqlParameter = null;
- if (skip.HasValue)
- {
- var skipParameter = new QuerySkipParameterSpecification();
- skipSqlParameter = Parameter.Placeholder;
- skipSqlParameter.BackTrack = skipParameter.GetIdsForBackTrack(sessionFactory).First();
- parameterSpecs.Add(skipParameter);
- }
- if (take.HasValue)
- {
- var takeParameter = new QueryTakeParameterSpecification();
- takeSqlParameter = Parameter.Placeholder;
- takeSqlParameter.BackTrack = takeParameter.GetIdsForBackTrack(sessionFactory).First();
- parameterSpecs.Add(takeParameter);
- }
- // The dialect can move the given parameters where he need, what it can't do is generates new parameters loosing the BackTrack.
- return dialect.GetLimitString(sqlString, skip, take, skipSqlParameter, takeSqlParameter);
- }
- return sqlString;
- }
-
public IType[] ResultTypes
{
get { return resultTypes; }
Modified: trunk/nhibernate/src/NHibernate/Loader/Loader.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Loader/Loader.cs 2011-06-13 12:51:47 UTC (rev 5919)
+++ trunk/nhibernate/src/NHibernate/Loader/Loader.cs 2011-06-13 13:04:23 UTC (rev 5920)
@@ -3,6 +3,7 @@
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
+using System.Linq;
using System.Runtime.CompilerServices;
using Iesi.Collections;
using Iesi.Collections.Generic;
@@ -13,8 +14,10 @@
using NHibernate.Engine;
using NHibernate.Event;
using NHibernate.Exceptions;
+using NHibernate.Hql.Classic;
using NHibernate.Hql.Util;
using NHibernate.Impl;
+using NHibernate.Param;
using NHibernate.Persister.Collection;
using NHibernate.Persister.Entity;
using NHibernate.Proxy;
@@ -1753,43 +1756,157 @@
#region NHibernate specific
- public virtual SqlCommandInfo GetQueryStringAndTypes(ISessionImplementor session, QueryParameters parameters, int startParameterIndex)
+ public virtual ISqlCommand CreateSqlCommand(QueryParameters queryParameters, ISessionImplementor session)
{
- SqlString sqlString = ProcessFilters(parameters, session);
- Dialect.Dialect dialect = session.Factory.Dialect;
+ throw new NotSupportedException("This loader does not support extraction of single command.");
+ }
- RowSelection selection = parameters.RowSelection;
- bool useLimit = UseLimit(selection, dialect);
- bool hasFirstRow = GetFirstRow(selection) > 0;
- bool useOffset = hasFirstRow && useLimit && dialect.SupportsLimitOffset;
- int limitParameterCount = GetFirstLimitParameterCount(dialect, useLimit, hasFirstRow, useOffset);
+ protected void AdjustQueryParametersForSubSelectFetching(SqlString sqlString, IEnumerable<IParameterSpecification> parameterSpecs, ISessionImplementor session, QueryParameters queryParameters)
+ {
+ // TODO: Remove this when all parameters are managed using IParameterSpecification (QueryParameters does not need to have decomposed values for filters)
- SqlType[] sqlTypes = parameters.PrepareParameterTypes(sqlString, Factory, GetNamedParameterLocs, startParameterIndex + limitParameterCount, useLimit, useOffset);
+ var dynamicFilterParameterSpecifications = parameterSpecs.OfType<DynamicFilterParameterSpecification>().ToList();
+ var filteredParameterValues = new List<object>();
+ var filteredParameterTypes = new List<IType>();
+ var filteredParameterLocations = new List<int>();
- if (useLimit)
+ if (dynamicFilterParameterSpecifications.Count != 0)
{
- int? offset = GetOffsetUsingDialect(selection, dialect);
- int? limit = GetLimitUsingDialect(selection, dialect);
- Parameter offsetParameter = parameters.OffsetParameterIndex.HasValue ? Parameter.WithIndex(parameters.OffsetParameterIndex.Value) : null;
- Parameter limitParameter = parameters.LimitParameterIndex.HasValue ? Parameter.WithIndex(parameters.LimitParameterIndex.Value) : null;
- sqlString =
- dialect.GetLimitString(
- sqlString.Trim(),
- useOffset ? offset : null,
- limit,
- useOffset ? offsetParameter : null,
- limitParameter);
- }
+ var sqlQueryParametersList = sqlString.GetParameters().ToList();
+ foreach (DynamicFilterParameterSpecification specification in dynamicFilterParameterSpecifications)
+ {
+ string backTrackId = specification.GetIdsForBackTrack(session.Factory).First();
+ object value = session.GetFilterParameterValue(specification.FilterParameterFullName);
+ var elementType = specification.ExpectedType;
+ foreach (int position in sqlQueryParametersList.GetEffectiveParameterLocations(backTrackId))
+ {
+ filteredParameterValues.Add(value);
+ filteredParameterTypes.Add(elementType);
+ filteredParameterLocations.Add(position);
+ }
+ }
+ }
- sqlString = PreprocessSQL(sqlString, parameters, dialect);
- return new SqlCommandInfo(sqlString, sqlTypes);
+ queryParameters.ProcessedSql = sqlString;
+ queryParameters.FilteredParameterLocations = filteredParameterLocations;
+ queryParameters.FilteredParameterTypes = filteredParameterTypes;
+ queryParameters.FilteredParameterValues = filteredParameterValues;
}
- public virtual ISqlCommand CreateSqlCommand(QueryParameters queryParameters, ISessionImplementor session)
+ protected SqlString ExpandDynamicFilterParameters(SqlString sqlString, ICollection<IParameterSpecification> parameterSpecs, ISessionImplementor session)
{
- throw new NotSupportedException("This loader does not support extraction of single command.");
+ var enabledFilters = session.EnabledFilters;
+ if (enabledFilters.Count == 0 || sqlString.ToString().IndexOf(ParserHelper.HqlVariablePrefix) < 0)
+ {
+ return sqlString;
+ }
+
+ Dialect.Dialect dialect = session.Factory.Dialect;
+ string symbols = ParserHelper.HqlSeparators + dialect.OpenQuote + dialect.CloseQuote;
+
+ var originSql = sqlString.Compact();
+ var result = new SqlStringBuilder();
+ foreach (var sqlPart in originSql.Parts)
+ {
+ var parameter = sqlPart as Parameter;
+ if (parameter != null)
+ {
+ result.Add(parameter);
+ continue;
+ }
+
+ var sqlFragment = sqlPart.ToString();
+ var tokens = new StringTokenizer(sqlFragment, symbols, true);
+
+ foreach (string token in tokens)
+ {
+ if (token.StartsWith(ParserHelper.HqlVariablePrefix))
+ {
+ string filterParameterName = token.Substring(1);
+ string[] parts = StringHelper.ParseFilterParameterName(filterParameterName);
+ string filterName = parts[0];
+ string parameterName = parts[1];
+ var filter = (FilterImpl)enabledFilters[filterName];
+
+ object value = filter.GetParameter(parameterName);
+ IType type = filter.FilterDefinition.GetParameterType(parameterName);
+ int parameterColumnSpan = type.GetColumnSpan(session.Factory);
+ var collectionValue = value as ICollection;
+ int? collectionSpan = null;
+
+ // Add query chunk
+ string typeBindFragment = string.Join(", ", Enumerable.Repeat("?", parameterColumnSpan).ToArray());
+ string bindFragment;
+ if (collectionValue != null && !type.ReturnedClass.IsArray)
+ {
+ collectionSpan = collectionValue.Count;
+ bindFragment = string.Join(", ", Enumerable.Repeat(typeBindFragment, collectionValue.Count).ToArray());
+ }
+ else
+ {
+ bindFragment = typeBindFragment;
+ }
+
+ // dynamic-filter parameter tracking
+ var filterParameterFragment = SqlString.Parse(bindFragment);
+ var dynamicFilterParameterSpecification = new DynamicFilterParameterSpecification(filterName, parameterName, type, collectionSpan);
+ var parameters = filterParameterFragment.GetParameters().ToArray();
+ var sqlParameterPos = 0;
+ var paramTrackers = dynamicFilterParameterSpecification.GetIdsForBackTrack(session.Factory);
+ foreach (var paramTracker in paramTrackers)
+ {
+ parameters[sqlParameterPos++].BackTrack = paramTracker;
+ }
+
+ parameterSpecs.Add(dynamicFilterParameterSpecification);
+ result.Add(filterParameterFragment);
+ }
+ else
+ {
+ result.Add(token);
+ }
+ }
+ }
+ return result.ToSqlString().Compact();
}
+ protected SqlString AddLimitsParametersIfNeeded(SqlString sqlString, ICollection<IParameterSpecification> parameterSpecs, QueryParameters queryParameters, ISessionImplementor session)
+ {
+ var sessionFactory = session.Factory;
+ Dialect.Dialect dialect = sessionFactory.Dialect;
+
+ RowSelection selection = queryParameters.RowSelection;
+ bool useLimit = UseLimit(selection, dialect);
+ if (useLimit)
+ {
+ bool hasFirstRow = GetFirstRow(selection) > 0;
+ bool useOffset = hasFirstRow && dialect.SupportsLimitOffset;
+ int max = GetMaxOrLimit(dialect, selection);
+ int? skip = useOffset ? (int?)dialect.GetOffsetValue(GetFirstRow(selection)) : null;
+ int? take = max != int.MaxValue ? (int?)max : null;
+
+ Parameter skipSqlParameter = null;
+ Parameter takeSqlParameter = null;
+ if (skip.HasValue)
+ {
+ var skipParameter = new QuerySkipParameterSpecification();
+ skipSqlParameter = Parameter.Placeholder;
+ skipSqlParameter.BackTrack = EnumerableExtensions.First(skipParameter.GetIdsForBackTrack(sessionFactory));
+ parameterSpecs.Add(skipParameter);
+ }
+ if (take.HasValue)
+ {
+ var takeParameter = new QueryTakeParameterSpecification();
+ takeSqlParameter = Parameter.Placeholder;
+ takeSqlParameter.BackTrack = EnumerableExtensions.First(takeParameter.GetIdsForBackTrack(sessionFactory));
+ parameterSpecs.Add(takeParameter);
+ }
+ // The dialect can move the given parameters where he need, what it can't do is generates new parameters loosing the BackTrack.
+ return dialect.GetLimitString(sqlString, skip, take, skipSqlParameter, takeSqlParameter);
+ }
+ return sqlString;
+ }
+
#endregion
}
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <fab...@us...> - 2011-06-13 15:32:49
|
Revision: 5923
http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5923&view=rev
Author: fabiomaulo
Date: 2011-06-13 15:32:42 +0000 (Mon, 13 Jun 2011)
Log Message:
-----------
First step to remove SqlString.Parameter
Modified Paths:
--------------
trunk/nhibernate/src/NHibernate/SqlCommand/SqlString.cs
trunk/nhibernate/src/NHibernate.Test/SqlCommandTest/SqlStringFixture.cs
Modified: trunk/nhibernate/src/NHibernate/SqlCommand/SqlString.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/SqlCommand/SqlString.cs 2011-06-13 15:18:20 UTC (rev 5922)
+++ trunk/nhibernate/src/NHibernate/SqlCommand/SqlString.cs 2011-06-13 15:32:42 UTC (rev 5923)
@@ -690,19 +690,24 @@
{
foreach (object part in sqlParts)
{
- string partString = part as string;
- SqlString partSqlString = part as SqlString;
+ var partString = part as string;
if (partString != null)
{
visitor.String(partString);
+ continue;
}
- else if (partSqlString != null && !SqlString.Parameter.Equals(partSqlString))
+
+ var partSqlString = part as SqlString;
+ if (partSqlString != null)
{
visitor.String(partSqlString);
+ continue;
}
- else
+
+ var partParameter = part as Parameter;
+ if(partParameter != null)
{
- visitor.Parameter((Parameter)part);
+ visitor.Parameter(partParameter);
}
}
}
Modified: trunk/nhibernate/src/NHibernate.Test/SqlCommandTest/SqlStringFixture.cs
===================================================================
--- trunk/nhibernate/src/NHibernate.Test/SqlCommandTest/SqlStringFixture.cs 2011-06-13 15:18:20 UTC (rev 5922)
+++ trunk/nhibernate/src/NHibernate.Test/SqlCommandTest/SqlStringFixture.cs 2011-06-13 15:32:42 UTC (rev 5923)
@@ -2,6 +2,7 @@
using System.Collections.Generic;
using NHibernate.SqlCommand;
using NUnit.Framework;
+using SharpTestsEx;
namespace NHibernate.Test.SqlCommandTest
{
@@ -374,10 +375,10 @@
Parameter[] parameters1 = new Parameter[1];
Parameter[] parameters2 = new Parameter[1];
- SqlString parameterString1 = SqlString.Parameter;
+ SqlString parameterString1 = new SqlString(Parameter.Placeholder);
parameterString1.Parts.CopyTo(parameters1, 0);
- SqlString parameterString2 = SqlString.Parameter;
+ SqlString parameterString2 = new SqlString(Parameter.Placeholder);
parameterString2.Parts.CopyTo(parameters2, 0);
Assert.AreEqual(parameterString1, parameterString2);
@@ -385,6 +386,9 @@
parameters1[0].ParameterPosition = 231;
Assert.IsNull(parameters2[0].ParameterPosition);
+
+ // more simple version of the test
+ Parameter.Placeholder.Should().Not.Be.SameInstanceAs(Parameter.Placeholder);
}
}
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|