|
From: <pa...@us...> - 2010-11-28 20:14:08
|
Revision: 5280
http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5280&view=rev
Author: patearl
Date: 2010-11-28 20:14:01 +0000 (Sun, 28 Nov 2010)
Log Message:
-----------
Linq: Let HQL figure out the type of non-null parameters.
Modified Paths:
--------------
trunk/nhibernate/src/NHibernate/Linq/NhQueryProvider.cs
trunk/nhibernate/src/NHibernate/Linq/Visitors/ExpressionParameterVisitor.cs
trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj
Added Paths:
-----------
trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2394/
trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2394/A.cs
trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2394/EnumStringUserType.cs
trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2394/Fixture.cs
trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2394/Mappings.hbm.xml
trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2394/PhoneNumber.cs
trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2394/PhoneNumberUserType.cs
Modified: trunk/nhibernate/src/NHibernate/Linq/NhQueryProvider.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Linq/NhQueryProvider.cs 2010-11-28 19:18:45 UTC (rev 5279)
+++ trunk/nhibernate/src/NHibernate/Linq/NhQueryProvider.cs 2010-11-28 20:14:01 UTC (rev 5280)
@@ -137,9 +137,13 @@
{
query.SetParameterList(parameterName, (ICollection) param.First);
}
+ else if (param.Second != null)
+ {
+ query.SetParameter(parameterName, param.First, param.Second);
+ }
else
{
- query.SetParameter(parameterName, param.First);
+ query.SetParameter(parameterName, param.First);
}
}
}
Modified: trunk/nhibernate/src/NHibernate/Linq/Visitors/ExpressionParameterVisitor.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Linq/Visitors/ExpressionParameterVisitor.cs 2010-11-28 19:18:45 UTC (rev 5279)
+++ trunk/nhibernate/src/NHibernate/Linq/Visitors/ExpressionParameterVisitor.cs 2010-11-28 20:14:01 UTC (rev 5280)
@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
+using NHibernate.Type;
namespace NHibernate.Linq.Visitors
{
@@ -25,7 +26,20 @@
{
if (!typeof(IQueryable).IsAssignableFrom(expression.Type) && !IsNullObject(expression))
{
- _parameters.Add(expression, new NamedParameter("p" + (_parameters.Count + 1), expression.Value, NHibernateUtil.GuessType(expression.Type)));
+ // We use null for the type to indicate that the caller should let HQL figure it out.
+ IType type = null;
+
+ // We have a bit more information about the null parameter value.
+ // Figure out a type so that HQL doesn't break on the null. (Related to NH-2430)
+ if (expression.Value == null)
+ type = NHibernateUtil.GuessType(expression.Type);
+
+ // There is more information available in the Linq expression than to HQL directly.
+ // In some cases it might be advantageous to use the extra info. Assuming this
+ // comes up, it would be nice to combine the HQL parameter type determination code
+ // and the Expression information.
+
+ _parameters.Add(expression, new NamedParameter("p" + (_parameters.Count + 1), expression.Value, type));
}
return base.VisitConstantExpression(expression);
Property changes on: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2394
___________________________________________________________________
Added: bugtraq:url
+ http://jira.nhibernate.org/browse/%BUGID%
Added: bugtraq:logregex
+ NH-\d+
Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2394/A.cs
===================================================================
--- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2394/A.cs (rev 0)
+++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2394/A.cs 2010-11-28 20:14:01 UTC (rev 5280)
@@ -0,0 +1,30 @@
+using System;
+using System.Collections;
+
+namespace NHibernate.Test.NHSpecificTest.NH2394
+{
+ public interface IA
+ {
+ int? Id { get; set; }
+ TypeOfA Type { get; set; }
+ TypeOfA? NullableType { get; set; }
+ PhoneNumber Phone { get; set; }
+ bool IsNice { get; set; }
+ }
+
+ public class A : IA
+ {
+ public int? Id { get; set; }
+ public TypeOfA Type { get; set; }
+ public TypeOfA? NullableType { get; set; }
+ public PhoneNumber Phone { get; set; }
+ public bool IsNice { get; set; }
+ }
+
+ public enum TypeOfA
+ {
+ Awesome,
+ Boring,
+ Cool
+ }
+}
Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2394/EnumStringUserType.cs
===================================================================
--- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2394/EnumStringUserType.cs (rev 0)
+++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2394/EnumStringUserType.cs 2010-11-28 20:14:01 UTC (rev 5280)
@@ -0,0 +1,15 @@
+using System;
+using System.Collections.Generic;
+using System.Data;
+using System.Linq;
+using System.Text;
+using NHibernate.SqlTypes;
+using NHibernate.Type;
+using NHibernate.UserTypes;
+
+namespace NHibernate.Test.NHSpecificTest.NH2394
+{
+ public class EnumStringUserType : EnumStringType<TypeOfA>
+ {
+ }
+}
\ No newline at end of file
Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2394/Fixture.cs
===================================================================
--- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2394/Fixture.cs (rev 0)
+++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2394/Fixture.cs 2010-11-28 20:14:01 UTC (rev 5280)
@@ -0,0 +1,89 @@
+using System;
+using System.Collections.Generic;
+using NHibernate.Criterion;
+using NUnit.Framework;
+using NHibernate.Linq;
+using System.Linq;
+using NHibernate.Linq.Functions;
+
+namespace NHibernate.Test.NHSpecificTest.NH2394
+{
+ [TestFixture]
+ public class Fixture : BugTestCase
+ {
+ protected override void OnTearDown()
+ {
+ using (ISession s = sessions.OpenSession())
+ {
+ s.Delete("from A");
+ s.Flush();
+ }
+ }
+
+ [Test]
+ public void LinqUserTypeEquality()
+ {
+ ISession s = OpenSession();
+ try
+ {
+ s.Save(new A { Type = TypeOfA.Awesome, Phone = new PhoneNumber(1, "555-1111") });
+ s.Save(new A { Type = TypeOfA.Boring, NullableType = TypeOfA.Awesome, Phone = new PhoneNumber(1, "555-2222") });
+ s.Save(new A { Type = TypeOfA.Cool, Phone = new PhoneNumber(1, "555-3333") });
+ s.Flush();
+ }
+ finally
+ {
+ s.Close();
+ }
+
+ s = OpenSession();
+ try
+ {
+ A item;
+
+ Assert.AreEqual(3, s.CreateQuery("from A a where a.IsNice = ?").SetParameter(0, false).List().Count);
+ Assert.AreEqual(3, s.Query<A>().Count(a => a.IsNice == false));
+
+ item = s.CreateQuery("from A a where a.Type = ?").SetParameter(0, TypeOfA.Awesome).UniqueResult<A>();
+ Assert.AreEqual(TypeOfA.Awesome, item.Type);
+ Assert.AreEqual("555-1111", item.Phone.Number);
+
+ item = s.Query<A>().Where(a => a.Type == TypeOfA.Awesome).Single();
+ Assert.AreEqual(TypeOfA.Awesome, item.Type);
+ Assert.AreEqual("555-1111", item.Phone.Number);
+
+ item = s.Query<A>().Where(a => TypeOfA.Awesome == a.Type).Single();
+ Assert.AreEqual(TypeOfA.Awesome, item.Type);
+ Assert.AreEqual("555-1111", item.Phone.Number);
+
+ IA interfaceItem = s.Query<IA>().Where(a => a.Type == TypeOfA.Awesome).Single();
+ Assert.AreEqual(TypeOfA.Awesome, interfaceItem.Type);
+ Assert.AreEqual("555-1111", interfaceItem.Phone.Number);
+
+ item = s.CreateQuery("from A a where a.NullableType = ?").SetParameter(0, TypeOfA.Awesome).UniqueResult<A>();
+ Assert.AreEqual(TypeOfA.Boring, item.Type);
+ Assert.AreEqual("555-2222", item.Phone.Number);
+ Assert.AreEqual(TypeOfA.Awesome, item.NullableType);
+
+ item = s.Query<A>().Where(a => a.NullableType == TypeOfA.Awesome).Single();
+ Assert.AreEqual(TypeOfA.Boring, item.Type);
+ Assert.AreEqual("555-2222", item.Phone.Number);
+ Assert.AreEqual(TypeOfA.Awesome, item.NullableType);
+
+ Assert.AreEqual(2, s.Query<A>().Count(a => a.NullableType == null));
+
+ item = s.CreateQuery("from A a where a.Phone = ?").SetParameter(0, new PhoneNumber(1, "555-2222")).UniqueResult<A>();
+ Assert.AreEqual(TypeOfA.Boring, item.Type);
+ Assert.AreEqual("555-2222", item.Phone.Number);
+
+ item = s.Query<A>().Where(a => a.Phone == new PhoneNumber(1, "555-2222")).Single();
+ Assert.AreEqual(TypeOfA.Boring, item.Type);
+ Assert.AreEqual("555-2222", item.Phone.Number);
+ }
+ finally
+ {
+ s.Close();
+ }
+ }
+ }
+}
Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2394/Mappings.hbm.xml
===================================================================
--- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2394/Mappings.hbm.xml (rev 0)
+++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2394/Mappings.hbm.xml 2010-11-28 20:14:01 UTC (rev 5280)
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="NHibernate.Test" namespace="NHibernate.Test.NHSpecificTest.NH2394">
+ <class name="A" table="a" lazy="false" optimistic-lock="dirty" dynamic-update="true">
+ <id name="Id" column="id" unsaved-value="null">
+ <generator class="native" />
+ </id>
+ <property name="Phone" type="NHibernate.Test.NHSpecificTest.NH2394.PhoneNumberUserType, NHibernate.Test">
+ <column name="PhoneCountryCode"/>
+ <column name="PhoneNumber"/>
+ </property>
+ <property name="Type" type="NHibernate.Test.NHSpecificTest.NH2394.EnumStringUserType, NHibernate.Test"/>
+ <property name="NullableType" type="NHibernate.Test.NHSpecificTest.NH2394.EnumStringUserType, NHibernate.Test"/>
+ <property name="IsNice" type="TrueFalse"/>
+ </class>
+</hibernate-mapping>
Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2394/PhoneNumber.cs
===================================================================
--- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2394/PhoneNumber.cs (rev 0)
+++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2394/PhoneNumber.cs 2010-11-28 20:14:01 UTC (rev 5280)
@@ -0,0 +1,39 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace NHibernate.Test.NHSpecificTest.NH2394
+{
+ public class PhoneNumber
+ {
+ public PhoneNumber(int countryCode, string number)
+ {
+ CountryCode = countryCode;
+ Number = number;
+ }
+
+ public int CountryCode { get; private set; }
+ public string Number { get; private set; }
+
+ public override bool Equals(object obj)
+ {
+ if (obj == null)
+ return false;
+
+ if (obj.GetType() != GetType())
+ return false;
+
+ PhoneNumber that = (PhoneNumber) obj;
+
+ return
+ CountryCode == that.CountryCode &&
+ Number == that.Number;
+ }
+
+ public override int GetHashCode()
+ {
+ return CountryCode.GetHashCode() ^ (Number ?? "").GetHashCode();
+ }
+ }
+}
Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2394/PhoneNumberUserType.cs
===================================================================
--- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2394/PhoneNumberUserType.cs (rev 0)
+++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2394/PhoneNumberUserType.cs 2010-11-28 20:14:01 UTC (rev 5280)
@@ -0,0 +1,106 @@
+using System;
+using System.Collections.Generic;
+using System.Data;
+using System.Linq;
+using System.Text;
+using NHibernate.Engine;
+using NHibernate.Type;
+using NHibernate.UserTypes;
+
+namespace NHibernate.Test.NHSpecificTest.NH2394
+{
+ class PhoneNumberUserType : ICompositeUserType
+ {
+ public string[] PropertyNames
+ {
+ get { return new[] { "CountryCode", "Number" }; }
+ }
+
+ public IType[] PropertyTypes
+ {
+ get { return new[] { NHibernateUtil.Int32, NHibernateUtil.String }; }
+ }
+
+ public object GetPropertyValue(object component, int property)
+ {
+ PhoneNumber phone = (PhoneNumber)component;
+
+ switch (property)
+ {
+ case 0: return phone.CountryCode;
+ case 1: return phone.Number;
+ default: throw new NotImplementedException();
+ }
+ }
+
+ public void SetPropertyValue(object component, int property, object value)
+ {
+ throw new NotImplementedException();
+ }
+
+ public System.Type ReturnedClass
+ {
+ get { return typeof(PhoneNumber); }
+ }
+
+ bool ICompositeUserType.Equals(object x, object y)
+ {
+ if (ReferenceEquals(x, null) && ReferenceEquals(y, null))
+ return true;
+
+ if (ReferenceEquals(x, null) || ReferenceEquals(y, null))
+ return false;
+
+ return x.Equals(y);
+ }
+
+ public int GetHashCode(object x)
+ {
+ return x.GetHashCode();
+ }
+
+ public object NullSafeGet(IDataReader dr, string[] names, ISessionImplementor session, object owner)
+ {
+ if (dr.IsDBNull(dr.GetOrdinal(names[0])))
+ return null;
+
+ return new PhoneNumber(
+ (int)NHibernateUtil.Int32.NullSafeGet(dr, names[0], session, owner),
+ (string)NHibernateUtil.String.NullSafeGet(dr, names[1], session, owner));
+ }
+
+ public void NullSafeSet(IDbCommand cmd, object value, int index, bool[] settable, ISessionImplementor session)
+ {
+ object countryCode = value == null ? null : (int?)((PhoneNumber)value).CountryCode;
+ object number = value == null ? null : ((PhoneNumber)value).Number;
+
+ if (settable[0]) NHibernateUtil.Int32.NullSafeSet(cmd, countryCode, index++, session);
+ if (settable[1]) NHibernateUtil.String.NullSafeSet(cmd, number, index, session);
+ }
+
+ public object DeepCopy(object value)
+ {
+ return value;
+ }
+
+ public bool IsMutable
+ {
+ get { return false; }
+ }
+
+ public object Disassemble(object value, ISessionImplementor session)
+ {
+ return value;
+ }
+
+ public object Assemble(object cached, ISessionImplementor session, object owner)
+ {
+ return cached;
+ }
+
+ public object Replace(object original, object target, ISessionImplementor session, object owner)
+ {
+ return original;
+ }
+ }
+}
Modified: trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj
===================================================================
--- trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2010-11-28 19:18:45 UTC (rev 5279)
+++ trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2010-11-28 20:14:01 UTC (rev 5280)
@@ -543,6 +543,11 @@
<Compile Include="NHSpecificTest\NH2392\Fixture.cs" />
<Compile Include="NHSpecificTest\NH2392\PhoneNumber.cs" />
<Compile Include="NHSpecificTest\NH2392\PhoneNumberUserType.cs" />
+ <Compile Include="NHSpecificTest\NH2394\A.cs" />
+ <Compile Include="NHSpecificTest\NH2394\EnumStringUserType.cs" />
+ <Compile Include="NHSpecificTest\NH2394\Fixture.cs" />
+ <Compile Include="NHSpecificTest\NH2394\PhoneNumber.cs" />
+ <Compile Include="NHSpecificTest\NH2394\PhoneNumberUserType.cs" />
<Compile Include="NHSpecificTest\NH2409\Contest.cs" />
<Compile Include="NHSpecificTest\NH2409\Fixture.cs" />
<Compile Include="NHSpecificTest\NH2409\Message.cs" />
@@ -2329,6 +2334,7 @@
<EmbeddedResource Include="NHSpecificTest\NH1291AnonExample\Mappings.hbm.xml" />
</ItemGroup>
<ItemGroup>
+ <EmbeddedResource Include="NHSpecificTest\NH2394\Mappings.hbm.xml" />
<EmbeddedResource Include="DynamicEntity\Interceptor\Customer.hbm.xml" />
<EmbeddedResource Include="Any\Person.hbm.xml" />
<EmbeddedResource Include="Any\Properties.hbm.xml" />
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|