From: <te...@us...> - 2008-12-12 14:57:23
|
Revision: 3946 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=3946&view=rev Author: tehlike Date: 2008-12-12 14:57:17 +0000 (Fri, 12 Dec 2008) Log Message: ----------- Another proposal for MsSql2005 Paging issue, by Dana Naideth Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Dialect/MsSql2005Dialect.cs trunk/nhibernate/src/NHibernate.Test/DialectTest/MsSql2005DialectFixture.cs Modified: trunk/nhibernate/src/NHibernate/Dialect/MsSql2005Dialect.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Dialect/MsSql2005Dialect.cs 2008-12-12 14:40:38 UTC (rev 3945) +++ trunk/nhibernate/src/NHibernate/Dialect/MsSql2005Dialect.cs 2008-12-12 14:57:17 UTC (rev 3946) @@ -29,12 +29,13 @@ /// The <c>LIMIT</c> SQL will look like /// <code> /// - /// SELECT TOP last (columns) FROM ( - /// SELECT ROW_NUMBER() OVER(ORDER BY __hibernate_sort_expr_1__ {sort direction 1} [, __hibernate_sort_expr_2__ {sort direction 2}, ...]) as row, (query.columns) FROM ( - /// {original select query part}, {sort field 1} as __hibernate_sort_expr_1__ [, {sort field 2} as __hibernate_sort_expr_2__, ...] - /// {remainder of original query minus the order by clause} - /// ) query - /// ) page WHERE page.row > offset + /// SELECT + /// TOP last (columns) + /// FROM + /// (SELECT (columns), ROW_NUMBER() OVER(ORDER BY {original order by, with un-aliased column names) as __hibernate_sort_row + /// {original from}) as query + /// WHERE query.__hibernate_sort_row > offset + /// ORDER BY query.__hibernate_sort_row /// /// </code> /// @@ -76,58 +77,26 @@ { from = querySqlString.Substring(fromIndex).Trim(); // Use dummy sort to avoid errors - sortExpressions = new[] { new SqlString("CURRENT_TIMESTAMP"), }; + sortExpressions = new[] {new SqlString("CURRENT_TIMESTAMP"),}; } SqlStringBuilder result = - new SqlStringBuilder().Add("SELECT TOP ").Add(last.ToString()).Add(" ").Add(StringHelper.Join(", ", columnsOrAliases)) - .Add(" FROM (SELECT ROW_NUMBER() OVER(ORDER BY "); + new SqlStringBuilder() + .Add("SELECT TOP ") + .Add(last.ToString()) + .Add(" ") + .Add(StringHelper.Join(", ", columnsOrAliases)) + .Add(" FROM (") + .Add(select) + .Add(", ROW_NUMBER() OVER(ORDER BY "); - AppendSortExpressions(columnsOrAliases, sortExpressions, result); + AppendSortExpressions(aliasToColumn, sortExpressions, result); - result.Add(") as row, "); - - for (int i = 0; i < columnsOrAliases.Count; i++) - { - result.Add("query.").Add(columnsOrAliases[i]); - bool notLastColumn = i != columnsOrAliases.Count - 1; - if (notLastColumn) - { - result.Add(", "); - } - } - for (int i = 0; i < sortExpressions.Length; i++) - { - SqlString sortExpression = RemoveSortOrderDirection(sortExpressions[i]); - if (!columnsOrAliases.Contains(sortExpression)) - { - result.Add(", query.__hibernate_sort_expr_").Add(i.ToString()).Add("__"); - } - } - - result.Add(" FROM (").Add(select); - - for (int i = 0; i < sortExpressions.Length; i++) - { - SqlString sortExpression = RemoveSortOrderDirection(sortExpressions[i]); - - if (columnsOrAliases.Contains(sortExpression)) - { - continue; - } - - if (aliasToColumn.ContainsKey(sortExpression)) - { - sortExpression = aliasToColumn[sortExpression]; - } - - result.Add(", ").Add(sortExpression).Add(" as __hibernate_sort_expr_").Add(i.ToString()).Add("__"); - } - - result.Add(" ").Add(from).Add(") query ) page WHERE page.row > ").Add(offset.ToString()).Add(" ORDER BY "); - - AppendSortExpressions(columnsOrAliases, sortExpressions, result); - + result.Add(") as __hibernate_sort_row ") + .Add(from) + .Add(") as query WHERE query.__hibernate_sort_row > ") + .Add(offset.ToString()).Add(" ORDER BY query.__hibernate_sort_row"); + return result.ToSqlString(); } @@ -141,7 +110,7 @@ return trimmedExpression.Trim(); } - private static void AppendSortExpressions(ICollection<SqlString> columnsOrAliases, SqlString[] sortExpressions, + private static void AppendSortExpressions(Dictionary<SqlString, SqlString> aliasToColumn, SqlString[] sortExpressions, SqlStringBuilder result) { for (int i = 0; i < sortExpressions.Length; i++) @@ -152,13 +121,13 @@ } SqlString sortExpression = RemoveSortOrderDirection(sortExpressions[i]); - if (columnsOrAliases.Contains(sortExpression)) + if (aliasToColumn.ContainsKey(sortExpression)) { - result.Add(sortExpression); + result.Add(aliasToColumn[sortExpression]); } else { - result.Add("__hibernate_sort_expr_").Add(i.ToString()).Add("__"); + result.Add(sortExpression); } if (sortExpressions[i].Trim().EndsWithCaseInsensitive("desc")) { @@ -240,7 +209,7 @@ } columnsOrAliases.Add(new SqlString(alias)); - aliasToColumn[new SqlString(alias)] = new SqlString(token); + aliasToColumn[SqlString.Parse(alias)] = SqlString.Parse(token); } } @@ -443,3 +412,4 @@ } } } + Modified: trunk/nhibernate/src/NHibernate.Test/DialectTest/MsSql2005DialectFixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/DialectTest/MsSql2005DialectFixture.cs 2008-12-12 14:40:38 UTC (rev 3945) +++ trunk/nhibernate/src/NHibernate.Test/DialectTest/MsSql2005DialectFixture.cs 2008-12-12 14:57:17 UTC (rev 3946) @@ -16,55 +16,65 @@ MsSql2005Dialect d = new MsSql2005Dialect(); SqlString str = d.GetLimitString(new SqlString("select distinct c.Contact_Id as Contact1_19_0_, c._Rating as Rating2_19_0_ from dbo.Contact c where COALESCE(c.Rating, 0) > 0 order by c.Rating desc , c.Last_Name , c.First_Name"), 0, 10); + System.Console.WriteLine(str); Assert.AreEqual( - "SELECT TOP 10 Contact1_19_0_, Rating2_19_0_ FROM (SELECT ROW_NUMBER() OVER(ORDER BY __hibernate_sort_expr_0__ DESC, __hibernate_sort_expr_1__, __hibernate_sort_expr_2__) as row, query.Contact1_19_0_, query.Rating2_19_0_, query.__hibernate_sort_expr_0__, query.__hibernate_sort_expr_1__, query.__hibernate_sort_expr_2__ FROM (select distinct c.Contact_Id as Contact1_19_0_, c._Rating as Rating2_19_0_, c.Rating as __hibernate_sort_expr_0__, c.Last_Name as __hibernate_sort_expr_1__, c.First_Name as __hibernate_sort_expr_2__ from dbo.Contact c where COALESCE(c.Rating, 0) > 0) query ) page WHERE page.row > 0 ORDER BY __hibernate_sort_expr_0__ DESC, __hibernate_sort_expr_1__, __hibernate_sort_expr_2__", + "SELECT TOP 10 Contact1_19_0_, Rating2_19_0_ FROM (select distinct c.Contact_Id as Contact1_19_0_, c._Rating as Rating2_19_0_, ROW_NUMBER() OVER(ORDER BY c.Rating DESC, c.Last_Name, c.First_Name) as __hibernate_sort_row from dbo.Contact c where COALESCE(c.Rating, 0) > 0) as query WHERE query.__hibernate_sort_row > 0 ORDER BY query.__hibernate_sort_row", str.ToString()); str = d.GetLimitString(new SqlString("SELECT fish.id FROM fish"), 0, 10); + System.Console.WriteLine(str); Assert.AreEqual( - "SELECT TOP 10 id FROM (SELECT ROW_NUMBER() OVER(ORDER BY __hibernate_sort_expr_0__) as row, query.id, query.__hibernate_sort_expr_0__ FROM (SELECT fish.id, CURRENT_TIMESTAMP as __hibernate_sort_expr_0__ FROM fish) query ) page WHERE page.row > 0 ORDER BY __hibernate_sort_expr_0__", + "SELECT TOP 10 id FROM (SELECT fish.id, ROW_NUMBER() OVER(ORDER BY CURRENT_TIMESTAMP) as __hibernate_sort_row FROM fish) as query WHERE query.__hibernate_sort_row > 0 ORDER BY query.__hibernate_sort_row", str.ToString()); str = d.GetLimitString(new SqlString("SELECT DISTINCT fish_.id FROM fish fish_"), 0, 10); + System.Console.WriteLine(str); Assert.AreEqual( - "SELECT TOP 10 id FROM (SELECT ROW_NUMBER() OVER(ORDER BY __hibernate_sort_expr_0__) as row, query.id, query.__hibernate_sort_expr_0__ FROM (SELECT DISTINCT fish_.id, CURRENT_TIMESTAMP as __hibernate_sort_expr_0__ FROM fish fish_) query ) page WHERE page.row > 0 ORDER BY __hibernate_sort_expr_0__", + "SELECT TOP 10 id FROM (SELECT DISTINCT fish_.id, ROW_NUMBER() OVER(ORDER BY CURRENT_TIMESTAMP) as __hibernate_sort_row FROM fish fish_) as query WHERE query.__hibernate_sort_row > 0 ORDER BY query.__hibernate_sort_row", str.ToString()); str = d.GetLimitString(new SqlString("SELECT DISTINCT fish_.id as ixx9_ FROM fish fish_"), 0, 10); + System.Console.WriteLine(str); Assert.AreEqual( - "SELECT TOP 10 ixx9_ FROM (SELECT ROW_NUMBER() OVER(ORDER BY __hibernate_sort_expr_0__) as row, query.ixx9_, query.__hibernate_sort_expr_0__ FROM (SELECT DISTINCT fish_.id as ixx9_, CURRENT_TIMESTAMP as __hibernate_sort_expr_0__ FROM fish fish_) query ) page WHERE page.row > 0 ORDER BY __hibernate_sort_expr_0__", + "SELECT TOP 10 ixx9_ FROM (SELECT DISTINCT fish_.id as ixx9_, ROW_NUMBER() OVER(ORDER BY CURRENT_TIMESTAMP) as __hibernate_sort_row FROM fish fish_) as query WHERE query.__hibernate_sort_row > 0 ORDER BY query.__hibernate_sort_row", str.ToString()); str = d.GetLimitString(new SqlString("SELECT * FROM fish ORDER BY name"), 5, 15); + System.Console.WriteLine(str); Assert.AreEqual( - "SELECT TOP 15 * FROM (SELECT ROW_NUMBER() OVER(ORDER BY __hibernate_sort_expr_0__) as row, query.*, query.__hibernate_sort_expr_0__ FROM (SELECT *, name as __hibernate_sort_expr_0__ FROM fish) query ) page WHERE page.row > 5 ORDER BY __hibernate_sort_expr_0__", + "SELECT TOP 15 * FROM (SELECT *, ROW_NUMBER() OVER(ORDER BY name) as __hibernate_sort_row FROM fish) as query WHERE query.__hibernate_sort_row > 5 ORDER BY query.__hibernate_sort_row", str.ToString()); str = d.GetLimitString(new SqlString("SELECT fish.id, fish.name FROM fish ORDER BY name DESC"), 7, 28); + System.Console.WriteLine(str); Assert.AreEqual( - "SELECT TOP 28 id, name FROM (SELECT ROW_NUMBER() OVER(ORDER BY name DESC) as row, query.id, query.name FROM (SELECT fish.id, fish.name FROM fish) query ) page WHERE page.row > 7 ORDER BY name DESC", + "SELECT TOP 28 id, name FROM (SELECT fish.id, fish.name, ROW_NUMBER() OVER(ORDER BY fish.name DESC) as __hibernate_sort_row FROM fish) as query WHERE query.__hibernate_sort_row > 7 ORDER BY query.__hibernate_sort_row", str.ToString()); str = d.GetLimitString( new SqlString("SELECT * FROM fish LEFT JOIN (SELECT * FROM meat ORDER BY weight) AS t ORDER BY name DESC"), 10, 20); + System.Console.WriteLine(str); Assert.AreEqual( - "SELECT TOP 20 * FROM (SELECT ROW_NUMBER() OVER(ORDER BY __hibernate_sort_expr_0__ DESC) as row, query.*, query.__hibernate_sort_expr_0__ FROM (SELECT *, name as __hibernate_sort_expr_0__ FROM fish LEFT JOIN (SELECT * FROM meat ORDER BY weight) AS t) query ) page WHERE page.row > 10 ORDER BY __hibernate_sort_expr_0__ DESC", + "SELECT TOP 20 * FROM (SELECT *, ROW_NUMBER() OVER(ORDER BY name DESC) as __hibernate_sort_row FROM fish LEFT JOIN (SELECT * FROM meat ORDER BY weight) AS t) as query WHERE query.__hibernate_sort_row > 10 ORDER BY query.__hibernate_sort_row", str.ToString()); str = d.GetLimitString(new SqlString("SELECT *, (SELECT COUNT(1) FROM fowl WHERE fish_id = fish.id) AS some_count FROM fish"), 0, 10); + System.Console.WriteLine(str); Assert.AreEqual( - "SELECT TOP 10 *, some_count FROM (SELECT ROW_NUMBER() OVER(ORDER BY __hibernate_sort_expr_0__) as row, query.*, query.some_count, query.__hibernate_sort_expr_0__ FROM (SELECT *, (SELECT COUNT(1) FROM fowl WHERE fish_id = fish.id) AS some_count, CURRENT_TIMESTAMP as __hibernate_sort_expr_0__ FROM fish) query ) page WHERE page.row > 0 ORDER BY __hibernate_sort_expr_0__", + "SELECT TOP 10 *, some_count FROM (SELECT *, (SELECT COUNT(1) FROM fowl WHERE fish_id = fish.id) AS some_count, ROW_NUMBER() OVER(ORDER BY CURRENT_TIMESTAMP) as __hibernate_sort_row FROM fish) as query WHERE query.__hibernate_sort_row > 0 ORDER BY query.__hibernate_sort_row", str.ToString()); str = d.GetLimitString(new SqlString("SELECT * FROM fish WHERE scales = ", Parameter.Placeholder), 0, 10); + System.Console.WriteLine(str); Assert.AreEqual( - "SELECT TOP 10 * FROM (SELECT ROW_NUMBER() OVER(ORDER BY __hibernate_sort_expr_0__) as row, query.*, query.__hibernate_sort_expr_0__ FROM (SELECT *, CURRENT_TIMESTAMP as __hibernate_sort_expr_0__ FROM fish WHERE scales = ?) query ) page WHERE page.row > 0 ORDER BY __hibernate_sort_expr_0__", + "SELECT TOP 10 * FROM (SELECT *, ROW_NUMBER() OVER(ORDER BY CURRENT_TIMESTAMP) as __hibernate_sort_row FROM fish WHERE scales = ?) as query WHERE query.__hibernate_sort_row > 0 ORDER BY query.__hibernate_sort_row", str.ToString()); str = d.GetLimitString(new SqlString("SELECT f.Type, COUNT(DISTINCT f.Name) AS Name FROM Fish f GROUP BY f.Type ORDER BY COUNT(DISTINCT f.Name)"), 0, 10); + System.Console.WriteLine(str); Assert.AreEqual( - "SELECT TOP 10 Type, Name FROM (SELECT ROW_NUMBER() OVER(ORDER BY __hibernate_sort_expr_0__) as row, query.Type, query.Name, query.__hibernate_sort_expr_0__ FROM (SELECT f.Type, COUNT(DISTINCT f.Name) AS Name, COUNT(DISTINCT f.Name) as __hibernate_sort_expr_0__ FROM Fish f GROUP BY f.Type) query ) page WHERE page.row > 0 ORDER BY __hibernate_sort_expr_0__", + "SELECT TOP 10 Type, Name FROM (SELECT f.Type, COUNT(DISTINCT f.Name) AS Name, ROW_NUMBER() OVER(ORDER BY COUNT(DISTINCT f.Name)) as __hibernate_sort_row FROM Fish f GROUP BY f.Type) as query WHERE query.__hibernate_sort_row > 0 ORDER BY query.__hibernate_sort_row", str.ToString()); } @@ -74,13 +84,15 @@ MsSql2005Dialect d = new MsSql2005Dialect(); SqlString result = d.GetLimitString(new SqlString("select concat(a.Description,', ', a.Description) as desc from Animal a"), 0, 10); - Assert.AreEqual("SELECT TOP 10 desc FROM (SELECT ROW_NUMBER() OVER(ORDER BY __hibernate_sort_expr_0__) as row, query.desc, query.__hibernate_sort_expr_0__ FROM (select concat(a.Description,', ', a.Description) as desc, CURRENT_TIMESTAMP as __hibernate_sort_expr_0__ from Animal a) query ) page WHERE page.row > 0 ORDER BY __hibernate_sort_expr_0__", result.ToString()); + System.Console.WriteLine(result); + Assert.AreEqual("SELECT TOP 10 desc FROM (select concat(a.Description,', ', a.Description) as desc, ROW_NUMBER() OVER(ORDER BY CURRENT_TIMESTAMP) as __hibernate_sort_row from Animal a) as query WHERE query.__hibernate_sort_row > 0 ORDER BY query.__hibernate_sort_row", result.ToString()); // The test use the function "cast" because cast need the keyWork "as" too SqlString str = d.GetLimitString(new SqlString("SELECT fish.id, cast('astring, with,comma' as string) as bar FROM fish"), 0, 10); + System.Console.WriteLine(str); Assert.AreEqual( - "SELECT TOP 10 id, bar FROM (SELECT ROW_NUMBER() OVER(ORDER BY __hibernate_sort_expr_0__) as row, query.id, query.bar, query.__hibernate_sort_expr_0__ FROM (SELECT fish.id, cast('astring, with,comma' as string) as bar, CURRENT_TIMESTAMP as __hibernate_sort_expr_0__ FROM fish) query ) page WHERE page.row > 0 ORDER BY __hibernate_sort_expr_0__", + "SELECT TOP 10 id, bar FROM (SELECT fish.id, cast('astring, with,comma' as string) as bar, ROW_NUMBER() OVER(ORDER BY CURRENT_TIMESTAMP) as __hibernate_sort_row FROM fish) as query WHERE query.__hibernate_sort_row > 0 ORDER BY query.__hibernate_sort_row", str.ToString()); } [Test] This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |