|
From: <fab...@us...> - 2009-04-22 22:12:52
|
Revision: 4200
http://nhibernate.svn.sourceforge.net/nhibernate/?rev=4200&view=rev
Author: fabiomaulo
Date: 2009-04-22 22:12:41 +0000 (Wed, 22 Apr 2009)
Log Message:
-----------
Fix NH-1754 and adjust of test to check exactly what we need (some RDBMS may store values in different way; for example 1.3f return 1.29999995... in MsSQL)
Modified Paths:
--------------
trunk/nhibernate/src/NHibernate/Dialect/Function/CastFunction.cs
trunk/nhibernate/src/NHibernate.Test/HQL/HQLFunctions.cs
Modified: trunk/nhibernate/src/NHibernate/Dialect/Function/CastFunction.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Dialect/Function/CastFunction.cs 2009-04-22 19:45:48 UTC (rev 4199)
+++ trunk/nhibernate/src/NHibernate/Dialect/Function/CastFunction.cs 2009-04-22 22:12:41 UTC (rev 4200)
@@ -1,5 +1,7 @@
using System;
using System.Collections;
+using System.Data;
+using System.Xml;
using NHibernate.Engine;
using NHibernate.SqlCommand;
using NHibernate.SqlTypes;
@@ -13,15 +15,25 @@
[Serializable]
public class CastFunction : ISQLFunction, IFunctionGrammar
{
+ private LazyType returnType;
#region ISQLFunction Members
public IType ReturnType(IType columnType, IMapping mapping)
{
//note there is a weird implementation in the client side
- //TODO: cast that use only costant are not supported in SELECT. Ex: cast(5 as string)
- return columnType;
+ //TODO: cast that use only costant are not supported in SELECT. Ex: cast(5 as string)
+ return SetLazyType(columnType);
}
+ private LazyType SetLazyType(IType columnType)
+ {
+ if(returnType == null)
+ {
+ returnType = new LazyType();
+ }
+ returnType.RealType = columnType;
+ return returnType;
+ }
public bool HasArguments
{
get { return true; }
@@ -41,12 +53,13 @@
string typeName = args[1].ToString();
string sqlType;
IType hqlType = TypeFactory.HeuristicType(typeName);
+ SetLazyType(hqlType);
if (hqlType != null)
{
SqlType[] sqlTypeCodes = hqlType.SqlTypes(factory);
if (sqlTypeCodes.Length != 1)
{
- throw new QueryException("invalid Hibernate type for cast()");
+ throw new QueryException("invalid NHibernate type for cast(), was:" + typeName);
}
sqlType = factory.Dialect.GetCastTypeName(sqlTypeCodes[0]);
if (sqlType == null)
@@ -92,5 +105,217 @@
}
#endregion
+
+ /// <summary>
+ /// Delegate the values to a real type
+ /// </summary>
+ /// <remarks>
+ /// The real return type of Cast is know only after the Cast is parsed.
+ /// This class was created in NH to remove the responsibility of the parser about know the
+ /// real return type.
+ /// </remarks>
+ [Serializable]
+ private class LazyType: IType
+ {
+ public IType RealType { get; set; }
+
+ #region Implementation of ICacheAssembler
+
+ public object Disassemble(object value, ISessionImplementor session, object owner)
+ {
+ return RealType.Disassemble(value, session, owner);
+ }
+
+ public object Assemble(object cached, ISessionImplementor session, object owner)
+ {
+ return RealType.Assemble(cached, session, owner);
+ }
+
+ public void BeforeAssemble(object cached, ISessionImplementor session)
+ {
+ RealType.BeforeAssemble(cached, session);
+ }
+
+ #endregion
+
+ #region Implementation of IType
+
+ public string Name
+ {
+ get { return RealType.Name; }
+ }
+
+ public System.Type ReturnedClass
+ {
+ get { return RealType.ReturnedClass; }
+ }
+
+ public bool IsMutable
+ {
+ get { return RealType.IsMutable; }
+ }
+
+ public bool IsAssociationType
+ {
+ get { return RealType.IsAssociationType; }
+ }
+
+ public bool IsXMLElement
+ {
+ get { return RealType.IsXMLElement; }
+ }
+
+ public bool IsCollectionType
+ {
+ get { return RealType.IsCollectionType; }
+ }
+
+ public bool IsComponentType
+ {
+ get { return RealType.IsComponentType; }
+ }
+
+ public bool IsEntityType
+ {
+ get { return RealType.IsEntityType; }
+ }
+
+ public bool IsAnyType
+ {
+ get { return RealType.IsAnyType; }
+ }
+
+ public SqlType[] SqlTypes(IMapping mapping)
+ {
+ return RealType.SqlTypes(mapping);
+ }
+
+ public int GetColumnSpan(IMapping mapping)
+ {
+ return RealType.GetColumnSpan(mapping);
+ }
+
+ public bool IsDirty(object old, object current, ISessionImplementor session)
+ {
+ return RealType.IsDirty(old, current, session);
+ }
+
+ public bool IsDirty(object old, object current, bool[] checkable, ISessionImplementor session)
+ {
+ return RealType.IsDirty(old, current, checkable, session);
+ }
+
+ public bool IsModified(object oldHydratedState, object currentState, bool[] checkable, ISessionImplementor session)
+ {
+ return RealType.IsModified(oldHydratedState, currentState, checkable, session);
+ }
+
+ public object NullSafeGet(IDataReader rs, string[] names, ISessionImplementor session, object owner)
+ {
+ return RealType.NullSafeGet(rs, names, session, owner);
+ }
+
+ public object NullSafeGet(IDataReader rs, string name, ISessionImplementor session, object owner)
+ {
+ return RealType.NullSafeGet(rs, name, session, owner);
+ }
+
+ public void NullSafeSet(IDbCommand st, object value, int index, bool[] settable, ISessionImplementor session)
+ {
+ RealType.NullSafeSet(st, value, index, settable, session);
+ }
+
+ public void NullSafeSet(IDbCommand st, object value, int index, ISessionImplementor session)
+ {
+ RealType.NullSafeSet(st, value, index, session);
+ }
+
+ public string ToLoggableString(object value, ISessionFactoryImplementor factory)
+ {
+ return RealType.ToLoggableString(value, factory);
+ }
+
+ public object DeepCopy(object val, EntityMode entityMode, ISessionFactoryImplementor factory)
+ {
+ return RealType.DeepCopy(val, entityMode, factory);
+ }
+
+ public object Hydrate(IDataReader rs, string[] names, ISessionImplementor session, object owner)
+ {
+ return RealType.Hydrate(rs, names, session, owner);
+ }
+
+ public object ResolveIdentifier(object value, ISessionImplementor session, object owner)
+ {
+ return RealType.ResolveIdentifier(value, session, owner);
+ }
+
+ public object SemiResolve(object value, ISessionImplementor session, object owner)
+ {
+ return RealType.SemiResolve(value, session, owner);
+ }
+
+ public object Replace(object original, object target, ISessionImplementor session, object owner, IDictionary copiedAlready)
+ {
+ return RealType.Replace(original, target, session, owner, copiedAlready);
+ }
+
+ public object Replace(object original, object target, ISessionImplementor session, object owner, IDictionary copyCache, ForeignKeyDirection foreignKeyDirection)
+ {
+ return RealType.Replace(original, target, session, owner, copyCache, foreignKeyDirection);
+ }
+
+ public bool IsSame(object x, object y, EntityMode entityMode)
+ {
+ return RealType.IsSame(x, y, entityMode);
+ }
+
+ public bool IsEqual(object x, object y, EntityMode entityMode)
+ {
+ return RealType.IsEqual(x, y, entityMode);
+ }
+
+ public bool IsEqual(object x, object y, EntityMode entityMode, ISessionFactoryImplementor factory)
+ {
+ return RealType.IsEqual(x, y, entityMode, factory);
+ }
+
+ public int GetHashCode(object x, EntityMode entityMode)
+ {
+ return RealType.GetHashCode(x, entityMode);
+ }
+
+ public int GetHashCode(object x, EntityMode entityMode, ISessionFactoryImplementor factory)
+ {
+ return RealType.GetHashCode(x, entityMode, factory);
+ }
+
+ public int Compare(object x, object y, EntityMode? entityMode)
+ {
+ return RealType.Compare(x, y, entityMode);
+ }
+
+ public IType GetSemiResolvedType(ISessionFactoryImplementor factory)
+ {
+ return RealType.GetSemiResolvedType(factory);
+ }
+
+ public void SetToXMLNode(XmlNode node, object value, ISessionFactoryImplementor factory)
+ {
+ RealType.SetToXMLNode(node, value, factory);
+ }
+
+ public object FromXMLNode(XmlNode xml, IMapping factory)
+ {
+ return RealType.FromXMLNode(xml, factory);
+ }
+
+ public bool[] ToColumnNullness(object value, IMapping mapping)
+ {
+ return RealType.ToColumnNullness(value, mapping);
+ }
+
+ #endregion
+ }
}
}
Modified: trunk/nhibernate/src/NHibernate.Test/HQL/HQLFunctions.cs
===================================================================
--- trunk/nhibernate/src/NHibernate.Test/HQL/HQLFunctions.cs 2009-04-22 19:45:48 UTC (rev 4199)
+++ trunk/nhibernate/src/NHibernate.Test/HQL/HQLFunctions.cs 2009-04-22 22:12:41 UTC (rev 4200)
@@ -3,6 +3,7 @@
using NHibernate.Dialect;
using NHibernate.Dialect.Function;
using NUnit.Framework;
+using NUnit.Framework.SyntaxHelpers;
namespace NHibernate.Test.Hql
{
@@ -413,13 +414,13 @@
if(!IsOracleDialect())
{
hql1 = "select nullif(h.NickName, '1e1') from Human h";
- hql2 = "from Human h where nullif(h.NickName, '1e1') not is null";
+ hql2 = "from Human h where not(nullif(h.NickName, '1e1') is null)";
}
else
{
// Oracle need same specific types
hql1 = "select nullif(str(h.NickName), '1e1') from Human h";
- hql2 = "from Human h where nullif(str(h.NickName), '1e1') not is null";
+ hql2 = "from Human h where not (nullif(str(h.NickName), '1e1') is null)";
}
// test only the parser and render
using (ISession s = OpenSession())
@@ -576,18 +577,18 @@
string hql;
IList l;
Animal result;
-
+ double expectedBodyWeight = 1.3;
// Rendered in SELECT using a property
hql = "select cast(a.BodyWeight as Double) from Animal a";
l = s.CreateQuery(hql).List();
Assert.AreEqual(1, l.Count);
- Assert.AreEqual(1.3f, l[0]);
+ Assert.That(l[0], Is.TypeOf(typeof (double)));
// Rendered in SELECT using a property in an operation with costant
hql = "select cast(7+123-5*a.BodyWeight as Double) from Animal a";
l = s.CreateQuery(hql).List();
Assert.AreEqual(1, l.Count);
- Assert.AreEqual(7f + 123f - 5f * 1.3f, l[0]);
+ Assert.AreEqual(7 + 123 - 5 * 1.3d, l[0]);
// Rendered in SELECT using a property and nested functions
if (!(Dialect is Oracle8iDialect))
@@ -595,7 +596,7 @@
hql = "select cast(cast(a.BodyWeight as string) as Double) from Animal a";
l = s.CreateQuery(hql).List();
Assert.AreEqual(1, l.Count);
- Assert.AreEqual(1.3F, l[0]);
+ Assert.That(l[0], Is.TypeOf(typeof(double)));
}
// TODO: Rendered in SELECT using string costant assigned with critic chars (separators)
@@ -632,13 +633,13 @@
hql = "select cast(a.BodyWeight as Double) from Animal a group by cast(a.BodyWeight as Double)";
l = s.CreateQuery(hql).List();
Assert.AreEqual(1, l.Count);
- Assert.AreEqual(1.3f, l[0]);
+ Assert.That(l[0], Is.TypeOf(typeof(double)));
// Rendered in GROUP BY using a property in an operation with costant
hql = "select cast(7+123-5*a.BodyWeight as Double) from Animal a group by cast(7+123-5*a.BodyWeight as Double)";
l = s.CreateQuery(hql).List();
Assert.AreEqual(1, l.Count);
- Assert.AreEqual(7f + 123f - 5f * 1.3f, l[0]);
+ Assert.AreEqual(7 + 123 - 5 * 1.3d, l[0]);
// Rendered in GROUP BY using a property and nested functions
if (!(Dialect is Oracle8iDialect))
@@ -647,14 +648,14 @@
"select cast(cast(a.BodyWeight as string) as Double) from Animal a group by cast(cast(a.BodyWeight as string) as Double)";
l = s.CreateQuery(hql).List();
Assert.AreEqual(1, l.Count);
- Assert.AreEqual(1.3F, l[0]);
+ Assert.That(l[0], Is.TypeOf(typeof(double)));
}
// Rendered in HAVING using a property
hql = "select cast(a.BodyWeight as Double) from Animal a group by cast(a.BodyWeight as Double) having cast(a.BodyWeight as Double)>0";
l = s.CreateQuery(hql).List();
Assert.AreEqual(1, l.Count);
- Assert.AreEqual(1.3f, l[0]);
+ Assert.That(l[0], Is.TypeOf(typeof(double)));
// Rendered in HAVING using a property in an operation with costants
hql = "select cast(7+123.3-1*a.BodyWeight as int) from Animal a group by cast(7+123.3-1*a.BodyWeight as int) having cast(7+123.3-1*a.BodyWeight as int)>0";
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|