From: <aye...@us...> - 2008-10-15 13:59:33
|
Revision: 3858 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=3858&view=rev Author: ayenderahien Date: 2008-10-15 13:58:32 +0000 (Wed, 15 Oct 2008) Log Message: ----------- Fixing NH-1526 - Cannot use projection for Count in OrderBy Fixing NH-1029 - Misleading SQL Query on exception Modified Paths: -------------- trunk/nhibernate/src/NHibernate/AdoNet/AbstractBatcher.cs trunk/nhibernate/src/NHibernate/Criterion/CountProjection.cs trunk/nhibernate/src/NHibernate/Exceptions/ADOExceptionHelper.cs trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj Added Paths: ----------- trunk/nhibernate/src/NHibernate.Test/ProjectionFixtures/ trunk/nhibernate/src/NHibernate.Test/ProjectionFixtures/Fixture.cs trunk/nhibernate/src/NHibernate.Test/ProjectionFixtures/Key.cs trunk/nhibernate/src/NHibernate.Test/ProjectionFixtures/Mapping.hbm.xml trunk/nhibernate/src/NHibernate.Test/ProjectionFixtures/NodeType.cs trunk/nhibernate/src/NHibernate.Test/ProjectionFixtures/TreeNode.cs Modified: trunk/nhibernate/src/NHibernate/AdoNet/AbstractBatcher.cs =================================================================== --- trunk/nhibernate/src/NHibernate/AdoNet/AbstractBatcher.cs 2008-10-15 12:03:06 UTC (rev 3857) +++ trunk/nhibernate/src/NHibernate/AdoNet/AbstractBatcher.cs 2008-10-15 13:58:32 UTC (rev 3858) @@ -193,7 +193,15 @@ { CheckReaders(); Prepare(cmd); - return cmd.ExecuteNonQuery(); + try + { + return cmd.ExecuteNonQuery(); + } + catch (Exception e) + { + e.Data["actual-sql-query"] = cmd.CommandText; + throw; + } } public IDataReader ExecuteReader(IDbCommand cmd) @@ -201,9 +209,18 @@ CheckReaders(); Prepare(cmd); - IDataReader reader = cmd.ExecuteReader(); + IDataReader reader; + try + { + reader = cmd.ExecuteReader(); + } + catch (Exception e) + { + e.Data["actual-sql-query"] = cmd.CommandText; + throw; + } - if (!factory.ConnectionProvider.Driver.SupportsMultipleOpenReaders) + if (!factory.ConnectionProvider.Driver.SupportsMultipleOpenReaders) { reader = new NHybridDataReader(reader); } Modified: trunk/nhibernate/src/NHibernate/Criterion/CountProjection.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Criterion/CountProjection.cs 2008-10-15 12:03:06 UTC (rev 3857) +++ trunk/nhibernate/src/NHibernate/Criterion/CountProjection.cs 2008-10-15 13:58:32 UTC (rev 3858) @@ -2,6 +2,7 @@ using System.Collections.Generic; using NHibernate.SqlCommand; using NHibernate.Type; +using NHibernate.Util; namespace NHibernate.Criterion { @@ -34,7 +35,19 @@ { buf.Add("distinct "); } - buf.Add(criteriaQuery.GetColumn(criteria, propertyName)).Add(") as y").Add(position.ToString()).Add("_"); + string column; + if(projection!=null) + { + column = + StringHelper.RemoveAsAliasesFromSql(projection.ToSqlString(criteria, position, criteriaQuery, + enabledFilters)).ToString(); + } + else + { + column = criteriaQuery.GetColumn(criteria, propertyName); + } + + buf.Add(column).Add(") as y").Add(position.ToString()).Add("_"); return buf.ToSqlString(); } Modified: trunk/nhibernate/src/NHibernate/Exceptions/ADOExceptionHelper.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Exceptions/ADOExceptionHelper.cs 2008-10-15 12:03:06 UTC (rev 3857) +++ trunk/nhibernate/src/NHibernate/Exceptions/ADOExceptionHelper.cs 2008-10-15 13:58:32 UTC (rev 3858) @@ -8,15 +8,11 @@ namespace NHibernate.Exceptions { - public sealed class ADOExceptionHelper + public static class ADOExceptionHelper { public const string SQLNotAvailable = "SQL not available"; - private ADOExceptionHelper() - { - } - - /// <summary> + /// <summary> /// Converts the given SQLException into NHibernate's ADOException hierarchy, as well as performing /// appropriate logging. /// </summary> @@ -27,6 +23,7 @@ /// <returns> The converted <see cref="ADOException"/>.</returns> public static ADOException Convert(ISQLExceptionConverter converter, Exception sqlException, string message, SqlString sql) { + sql = TryGetActualSqlQuery(sqlException, sql); ADOExceptionReporter.LogExceptions(sqlException, ExtendMessage(message, sql, null, null)); return converter.Convert(sqlException, message, sql); } @@ -41,13 +38,16 @@ /// <returns> The converted <see cref="ADOException"/>.</returns> public static ADOException Convert(ISQLExceptionConverter converter, Exception sqlException, string message) { - return Convert(converter, sqlException, message, new SqlString(SQLNotAvailable)); + SqlString sql = new SqlString(SQLNotAvailable); + sql = TryGetActualSqlQuery(sqlException, sql); + return Convert(converter, sqlException, message, sql); } public static ADOException Convert(ISQLExceptionConverter converter, Exception sqle, string message, SqlString sql, object[] parameterValues, IDictionary<string, TypedValue> namedParameters) { - string extendMessage = ExtendMessage(message, sql, parameterValues, namedParameters); + sql = TryGetActualSqlQuery(sqle, sql); + string extendMessage = ExtendMessage(message, sql, parameterValues, namedParameters); ADOExceptionReporter.LogExceptions(sqle, extendMessage); return new ADOException(extendMessage, sqle, sql); } @@ -100,5 +100,13 @@ sb.Append(Environment.NewLine); return sb.ToString(); } + + public static SqlString TryGetActualSqlQuery(Exception sqle, SqlString sql) + { + string query = (string)sqle.Data["actual-sql-query"]; + if(query!=null) + sql = new SqlString(query); + return sql; + } } } \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2008-10-15 12:03:06 UTC (rev 3857) +++ trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2008-10-15 13:58:32 UTC (rev 3858) @@ -757,6 +757,10 @@ <Compile Include="Ondelete\ParentChildFixture.cs" /> <Compile Include="Ondelete\Person.cs" /> <Compile Include="Ondelete\Salesperson.cs" /> + <Compile Include="ProjectionFixtures\Key.cs" /> + <Compile Include="ProjectionFixtures\Fixture.cs" /> + <Compile Include="ProjectionFixtures\NodeType.cs" /> + <Compile Include="ProjectionFixtures\TreeNode.cs" /> <Compile Include="PropertyRef\A.cs" /> <Compile Include="PropertyRef\B.cs" /> <Compile Include="PropertyRef\KeyPropertyRefFixture.cs" /> @@ -1499,6 +1503,7 @@ <EmbeddedResource Include="Cascade\JobBatch.hbm.xml" /> <EmbeddedResource Include="Deletetransient\Person.hbm.xml" /> <Content Include="DynamicEntity\package.html" /> + <EmbeddedResource Include="ProjectionFixtures\Mapping.hbm.xml" /> <EmbeddedResource Include="NHSpecificTest\NH1033\Mappings.hbm.xml" /> <EmbeddedResource Include="EntityModeTest\Multi\Stock.hbm.xml" /> <EmbeddedResource Include="EntityModeTest\Multi\Valuation.hbm.xml" /> Property changes on: trunk/nhibernate/src/NHibernate.Test/ProjectionFixtures ___________________________________________________________________ Added: bugtraq:url + http://jira.nhibernate.org/browse/%BUGID% Added: bugtraq:logregex + NH-\d+ Added: trunk/nhibernate/src/NHibernate.Test/ProjectionFixtures/Fixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/ProjectionFixtures/Fixture.cs (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/ProjectionFixtures/Fixture.cs 2008-10-15 13:58:32 UTC (rev 3858) @@ -0,0 +1,123 @@ +using System; +using NHibernate; +using NHibernate.Criterion; +using NHibernate.Test.PropertyRef; +using NUnit.Framework; + +namespace NHibernate.Test.ProjectionFixtures +{ + [TestFixture] + public class Fixture : TestCase + { + protected override System.Collections.IList Mappings + { + get { return new string[] { "ProjectionFixtures.Mapping.hbm.xml" }; } + } + + protected override string MappingsAssembly + { + get { return "NHibernate.Test"; } + } + + protected override void OnSetUp() + { + using(var s = sessions.OpenSession()) + using(var tx = s.BeginTransaction()) + { + var root = new TreeNode + { + Key = new Key {Id = 1, Area = 2}, + Type = NodeType.Plain + }; + var child = new TreeNode + { + Key = new Key { Id = 11, Area = 2 }, + Type = NodeType.Blue + }; + var grandchild = new TreeNode + { + Key = new Key {Id = 111, Area = 2}, + Type = NodeType.Smart + }; + root.DirectChildren.Add(child); + child.Parent = root; + grandchild.Parent = child; + child.DirectChildren.Add(grandchild); + + s.Save(root); + s.Save(child); + s.Save(grandchild); + + tx.Commit(); + } + } + + protected override void OnTearDown() + { + using(var s = sessions.OpenSession()) + using (var tx = s.BeginTransaction()) + { + s.Delete("from TreeNode"); + + tx.Commit(); + } + } + + + [Test] + [ExpectedException(typeof(ADOException), ExpectedMessage = @"could not execute query +[ SELECT this_.Id as y0_, count(this_.Area) as y1_ FROM TreeNode this_ WHERE this_.Id = @p0 ] +Positional parameters: #0>2 +[SQL: SELECT this_.Id as y0_, count(this_.Area) as y1_ FROM TreeNode this_ WHERE this_.Id = @p0]")] + public void ErrorFromDBWillGiveTheActualSQLExecuted() + { + DetachedCriteria projection = DetachedCriteria.For<TreeNode>("child") + .Add(Restrictions.Eq("child.Key.Id", 2)) + .SetProjection( + Projections.ProjectionList() + .Add(Projections.Property("child.Key.Id")) + .Add(Projections.Count("child.Key.Area")) + ); + + using (var s = sessions.OpenSession()) + using (var tx = s.BeginTransaction()) + { + var criteria = projection.GetExecutableCriteria(s); + criteria.List(); + + tx.Commit(); + } + } + + [Test] + public void AggregatingHirearchyWithCount() + { + var root = new Key {Id = 1, Area = 2}; + + DetachedCriteria projection = DetachedCriteria.For<TreeNode>("child") + .Add(Restrictions.Eq("Parent.id", root)) + .Add(Restrictions.Gt("Key.Id", 0)) + .Add(Restrictions.Eq("Type", NodeType.Blue)) + .CreateAlias("DirectChildren", "grandchild") + .SetProjection( + Projections.ProjectionList() + .Add(Projections.GroupProperty("child.Key.Id")) + .Add(Projections.GroupProperty("child.Key.Area")) + .Add(Projections.Count(Projections.Property("grandchild.Key.Id"))) + ); + + using(var s = sessions.OpenSession()) + using(var tx = s.BeginTransaction()) + { + var criteria = projection.GetExecutableCriteria(s); + var list = criteria.List(); + Assert.AreEqual(1, list.Count); + var tuple = (object[]) list[0]; + Assert.AreEqual(11, tuple[0]); + Assert.AreEqual(2, tuple[1]); + Assert.AreEqual(1, tuple[2]); + tx.Commit(); + } + } + } +} \ No newline at end of file Added: trunk/nhibernate/src/NHibernate.Test/ProjectionFixtures/Key.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/ProjectionFixtures/Key.cs (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/ProjectionFixtures/Key.cs 2008-10-15 13:58:32 UTC (rev 3858) @@ -0,0 +1,31 @@ +namespace NHibernate.Test.ProjectionFixtures +{ + public class Key + { + public virtual int Id { get; set; } + public virtual int Area { get; set; } + + public virtual bool Equals(Key obj) + { + if (ReferenceEquals(null, obj)) return false; + if (ReferenceEquals(this, obj)) return true; + return obj.Id == Id && obj.Area == Area; + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) return false; + if (ReferenceEquals(this, obj)) return true; + if (obj.GetType() != typeof (Key)) return false; + return Equals((Key) obj); + } + + public override int GetHashCode() + { + unchecked + { + return (Id*397) ^ Area; + } + } + } +} \ No newline at end of file Added: trunk/nhibernate/src/NHibernate.Test/ProjectionFixtures/Mapping.hbm.xml =================================================================== --- trunk/nhibernate/src/NHibernate.Test/ProjectionFixtures/Mapping.hbm.xml (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/ProjectionFixtures/Mapping.hbm.xml 2008-10-15 13:58:32 UTC (rev 3858) @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="utf-8" ?> +<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" + assembly="NHibernate.Test" + namespace="NHibernate.Test.ProjectionFixtures"> + + <class name="TreeNode"> + <composite-id name="Key"> + <key-property name="Id" /> + <key-property name="Area" /> + </composite-id> + <many-to-one name="Parent"> + <column name="Parent"/> + <column name="ParentArea"/> + </many-to-one> + <set name="DirectChildren"> + <key> + <column name="Parent"/> + <column name="ParentArea"/> + </key> + <one-to-many class="TreeNode"/> + </set> + <property name="Type"/> + </class> + +</hibernate-mapping> \ No newline at end of file Added: trunk/nhibernate/src/NHibernate.Test/ProjectionFixtures/NodeType.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/ProjectionFixtures/NodeType.cs (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/ProjectionFixtures/NodeType.cs 2008-10-15 13:58:32 UTC (rev 3858) @@ -0,0 +1,9 @@ +namespace NHibernate.Test.ProjectionFixtures +{ + public enum NodeType + { + Smart, + Plain, + Blue + } +} \ No newline at end of file Added: trunk/nhibernate/src/NHibernate.Test/ProjectionFixtures/TreeNode.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/ProjectionFixtures/TreeNode.cs (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/ProjectionFixtures/TreeNode.cs 2008-10-15 13:58:32 UTC (rev 3858) @@ -0,0 +1,18 @@ +using Iesi.Collections.Generic; +using NHibernate.Test.ProjectionFixtures; + +namespace NHibernate.Test.ProjectionFixtures +{ + public class TreeNode + { + public virtual Key Key { get; set; } + public virtual TreeNode Parent { get; set; } + public virtual NodeType Type { get; set; } + public virtual ISet<TreeNode> DirectChildren { get; set; } + + public TreeNode() + { + DirectChildren = new HashedSet<TreeNode>(); + } + } +} \ No newline at end of file This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |