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