Browse files

Implemented proper, join-aware paging in SQL Server

  • Loading branch information...
1 parent 5bcbf2e commit 54581ae53bc077787d28a0f784eb7192c9e23c01 @markrendle committed Nov 6, 2012
View
212 Simple.Data.Ado.Test/ProviderHelperTest.cs
@@ -1,118 +1,118 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using NUnit.Framework;
-using System.Data;
-using Simple.Data.Ado.Schema;
-using System.ComponentModel.Composition;
-
-namespace Simple.Data.Ado.Test
-{
- [TestFixture]
- public class ProviderHelperTest
- {
- [Test]
- public void ShouldNotRequestExportableTypeFromServiceProvider()
- {
- var helper = new ProviderHelper();
- var connectionProvider = new StubConnectionAndServiceProvider();
- var actual = helper.GetCustomProvider<ITestInterface>(connectionProvider);
- Assert.IsNull(connectionProvider.RequestedServiceType);
- }
-
- [Test]
- public void ShouldRequestNonExportedTypeFromServiceProvider()
- {
- var helper = new ProviderHelper();
- var connectionProvider = new StubConnectionAndServiceProvider();
- var actual = helper.GetCustomProvider<IQueryPager>(connectionProvider);
- Assert.AreEqual(typeof(IQueryPager), connectionProvider.RequestedServiceType);
- }
-
- [Test]
- public void ShouldReturnNonExportedTypeFromServiceProvider()
- {
- var helper = new ProviderHelper();
- var connectionProvider = new StubConnectionAndServiceProvider();
- var actual = helper.GetCustomProvider<IQueryPager>(connectionProvider);
- Assert.IsInstanceOf(typeof(IQueryPager), actual);
- }
-
- [Test]
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using NUnit.Framework;
+using System.Data;
+using Simple.Data.Ado.Schema;
+using System.ComponentModel.Composition;
+
+namespace Simple.Data.Ado.Test
+{
+ [TestFixture]
+ public class ProviderHelperTest
+ {
+ [Test]
+ public void ShouldNotRequestExportableTypeFromServiceProvider()
+ {
+ var helper = new ProviderHelper();
+ var connectionProvider = new StubConnectionAndServiceProvider();
+ var actual = helper.GetCustomProvider<ITestInterface>(connectionProvider);
+ Assert.IsNull(connectionProvider.RequestedServiceType);
+ }
+
+ [Test]
+ public void ShouldRequestNonExportedTypeFromServiceProvider()
+ {
+ var helper = new ProviderHelper();
+ var connectionProvider = new StubConnectionAndServiceProvider();
+ var actual = helper.GetCustomProvider<IQueryPager>(connectionProvider);
+ Assert.AreEqual(typeof(IQueryPager), connectionProvider.RequestedServiceType);
+ }
+
+ [Test]
+ public void ShouldReturnNonExportedTypeFromServiceProvider()
+ {
+ var helper = new ProviderHelper();
+ var connectionProvider = new StubConnectionAndServiceProvider();
+ var actual = helper.GetCustomProvider<IQueryPager>(connectionProvider);
+ Assert.IsInstanceOf(typeof(IQueryPager), actual);
+ }
+
+ [Test]
public void ShouldFindProviderUsingAssemblyAttribute()
{
IConnectionProvider provider;
Assert.True(ProviderHelper.TryLoadAssemblyUsingAttribute("Test", null, out provider));
Assert.IsNotNull(provider);
Assert.IsInstanceOf<StubConnectionProvider>(provider);
- }
-
- public class StubConnectionAndServiceProvider : IConnectionProvider, IServiceProvider
- {
- public void SetConnectionString(string connectionString)
- {
- throw new NotImplementedException();
- }
-
- public IDbConnection CreateConnection()
- {
- throw new NotImplementedException();
- }
-
- public ISchemaProvider GetSchemaProvider()
- {
- throw new NotImplementedException();
- }
-
- public string ConnectionString
- {
- get { throw new NotImplementedException(); }
- }
-
- public bool SupportsCompoundStatements
- {
- get { throw new NotImplementedException(); }
- }
-
- public string GetIdentityFunction()
- {
- throw new NotImplementedException();
- }
-
- public bool SupportsStoredProcedures
- {
- get { throw new NotImplementedException(); }
- }
-
- public IProcedureExecutor GetProcedureExecutor(AdoAdapter adapter, ObjectName procedureName)
- {
- throw new NotImplementedException();
- }
-
- public Type RequestedServiceType { get; private set; }
- public Object GetService(Type serviceType)
- {
- this.RequestedServiceType = serviceType;
- return new StubQueryPager();
- }
- }
-
- public class StubQueryPager : IQueryPager
+ }
+
+ public class StubConnectionAndServiceProvider : IConnectionProvider, IServiceProvider
+ {
+ public void SetConnectionString(string connectionString)
+ {
+ throw new NotImplementedException();
+ }
+
+ public IDbConnection CreateConnection()
+ {
+ throw new NotImplementedException();
+ }
+
+ public ISchemaProvider GetSchemaProvider()
+ {
+ throw new NotImplementedException();
+ }
+
+ public string ConnectionString
+ {
+ get { throw new NotImplementedException(); }
+ }
+
+ public bool SupportsCompoundStatements
+ {
+ get { throw new NotImplementedException(); }
+ }
+
+ public string GetIdentityFunction()
+ {
+ throw new NotImplementedException();
+ }
+
+ public bool SupportsStoredProcedures
+ {
+ get { throw new NotImplementedException(); }
+ }
+
+ public IProcedureExecutor GetProcedureExecutor(AdoAdapter adapter, ObjectName procedureName)
+ {
+ throw new NotImplementedException();
+ }
+
+ public Type RequestedServiceType { get; private set; }
+ public Object GetService(Type serviceType)
+ {
+ this.RequestedServiceType = serviceType;
+ return new StubQueryPager();
+ }
+ }
+
+ public class StubQueryPager : IQueryPager
{
public IEnumerable<string> ApplyLimit(string sql, int take)
{
throw new NotImplementedException();
}
- public IEnumerable<string> ApplyPaging(string sql, int skip, int take)
- {
- throw new NotImplementedException();
- }
- }
-
- public interface ITestInterface { }
- [Export(typeof(ITestInterface))]
- public class TestClass : ITestInterface { }
- }
-}
+ public IEnumerable<string> ApplyPaging(string sql, string[] keys, int skip, int take)
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+ public interface ITestInterface { }
+ [Export(typeof(ITestInterface))]
+ public class TestClass : ITestInterface { }
+ }
+}
View
14 Simple.Data.Ado/AdoAdapterQueryRunner.cs
@@ -151,7 +151,7 @@ public AdoAdapterQueryRunner(AdoAdapter adapter, AdoAdapterTransaction transacti
}
else
{
- ApplyPaging(commandBuilders, mainCommandBuilder, skipClause, takeClause, query.Clauses.OfType<WithClause>().Any(), queryPager);
+ ApplyPaging(query, commandBuilders, mainCommandBuilder, skipClause, takeClause, query.Clauses.OfType<WithClause>().Any(), queryPager);
}
}
return commandBuilders.ToArray();
@@ -168,7 +168,7 @@ public AdoAdapterQueryRunner(AdoAdapter adapter, AdoAdapterTransaction transacti
commandBuilders.Add(commandBuilder);
}
- private void ApplyPaging(List<ICommandBuilder> commandBuilders, ICommandBuilder mainCommandBuilder, SkipClause skipClause, TakeClause takeClause, bool hasWithClause, IQueryPager queryPager)
+ private void ApplyPaging(SimpleQuery query, List<ICommandBuilder> commandBuilders, ICommandBuilder mainCommandBuilder, SkipClause skipClause, TakeClause takeClause, bool hasWithClause, IQueryPager queryPager)
{
const int maxInt = 2147483646;
@@ -179,9 +179,17 @@ private void ApplyPaging(List<ICommandBuilder> commandBuilders, ICommandBuilder
}
else
{
+ var table = _adapter.GetSchema().FindTable(query.TableName);
+ if (table.PrimaryKey == null || table.PrimaryKey.Length == 0)
+ {
+ throw new AdoAdapterException("Cannot apply paging to a table with no primary key.");
+ }
+ var keys = table.PrimaryKey.AsEnumerable()
+ .Select(k => string.Format("{0}.{1}", table.QualifiedName, _adapter.GetSchema().QuoteObjectName(k)))
+ .ToArray();
int skip = skipClause == null ? 0 : skipClause.Count;
int take = takeClause == null ? maxInt : takeClause.Count;
- commandTexts = queryPager.ApplyPaging(mainCommandBuilder.Text, skip, take);
+ commandTexts = queryPager.ApplyPaging(mainCommandBuilder.Text, keys, skip, take);
}
commandBuilders.AddRange(
View
2 Simple.Data.Ado/IQueryPager.cs
@@ -5,6 +5,6 @@ namespace Simple.Data.Ado
public interface IQueryPager
{
IEnumerable<string> ApplyLimit(string sql, int take);
- IEnumerable<string> ApplyPaging(string sql, int skip, int take);
+ IEnumerable<string> ApplyPaging(string sql, string[] keys, int skip, int take);
}
}
View
28 Simple.Data.Ado/Joiner.cs
@@ -121,12 +121,12 @@ private string MakeJoinText(Table rightTable, string alias, ForeignKey foreignKe
builder.AppendFormat(" JOIN {0}", rightTable.QualifiedName);
if (!string.IsNullOrWhiteSpace(alias)) builder.Append(" " + _schema.QuoteObjectName(alias));
builder.Append(" ON (");
- builder.Append(FormatJoinExpression(foreignKey, 0, alias));
+ builder.Append(FormatJoinExpression(foreignKey, 0, rightTable, alias));
for (int i = 1; i < foreignKey.Columns.Length; i++)
{
builder.Append(" AND ");
- builder.Append(FormatJoinExpression(foreignKey, i, alias));
+ builder.Append(FormatJoinExpression(foreignKey, i, rightTable, alias));
}
builder.Append(")");
return builder.ToString();
@@ -167,13 +167,25 @@ private SimpleExpression CreateJoinExpression(ObjectReference table, ForeignKey
return masterObjectReference == detailObjectReference;
}
- private string FormatJoinExpression(ForeignKey foreignKey, int columnIndex, string alias)
+ private string FormatJoinExpression(ForeignKey foreignKey, int columnIndex, Table rightTable, string alias)
{
- var leftTable = string.IsNullOrWhiteSpace(alias)
- ? _schema.QuoteObjectName(foreignKey.MasterTable)
- : _schema.QuoteObjectName(alias);
- return string.Format("{0}.{1} = {2}.{3}", leftTable, _schema.QuoteObjectName(foreignKey.UniqueColumns[columnIndex]),
- _schema.QuoteObjectName(foreignKey.DetailTable), _schema.QuoteObjectName(foreignKey.Columns[columnIndex]));
+ if (rightTable.ActualName == foreignKey.MasterTable.Name &&
+ rightTable.Schema == foreignKey.MasterTable.Schema)
+ {
+ var rightTableName = string.IsNullOrWhiteSpace(alias)
+ ? _schema.QuoteObjectName(foreignKey.MasterTable)
+ : _schema.QuoteObjectName(alias);
+ return string.Format("{0}.{1} = {2}.{3}",
+ rightTableName, _schema.QuoteObjectName(foreignKey.UniqueColumns[columnIndex]),
+ _schema.QuoteObjectName(foreignKey.DetailTable), _schema.QuoteObjectName(foreignKey.Columns[columnIndex])
+ );
+ }
+
+ var leftTableName = string.IsNullOrWhiteSpace(alias)
+ ? _schema.QuoteObjectName(foreignKey.DetailTable)
+ : _schema.QuoteObjectName(alias);
+ return string.Format("{0}.{1} = {2}.{3}", _schema.QuoteObjectName(foreignKey.MasterTable), _schema.QuoteObjectName(foreignKey.UniqueColumns[columnIndex]),
+ leftTableName, _schema.QuoteObjectName(foreignKey.Columns[columnIndex]));
}
private string JoinKeyword
View
2 Simple.Data.SqlCe40/SqlCe40QueryPager.cs
@@ -19,7 +19,7 @@ public IEnumerable<string> ApplyLimit(string sql, int take)
yield return SelectMatch.Replace(sql, match => match.Value + " TOP(" + take + ") ");
}
- public IEnumerable<string> ApplyPaging(string sql, int skip, int take)
+ public IEnumerable<string> ApplyPaging(string sql, string[] keys, int skip, int take)
{
if (sql.IndexOf("order by", StringComparison.InvariantCultureIgnoreCase) < 0)
{
View
4 Simple.Data.SqlCe40Test/SqlCe40QueryPagerTest.cs
@@ -29,7 +29,7 @@ public void ShouldApplyPagingUsingOrderBy()
var expected = new[]{
"select a,b,c from d where a = 1 order by c offset 5 rows fetch next 10 rows only"};
- var pagedSql = new SqlCe40QueryPager().ApplyPaging(sql, 5, 10);
+ var pagedSql = new SqlCe40QueryPager().ApplyPaging(sql, new string[0], 5, 10);
var modified = pagedSql.Select(x=> Normalize.Replace(x, " ").ToLowerInvariant());
Assert.IsTrue(expected.SequenceEqual(modified));
@@ -42,7 +42,7 @@ public void ShouldApplyPagingUsingOrderByFirstColumnIfNotAlreadyOrdered()
var expected = new[]{
"select a,b,c from d where a = 1 order by a offset 10 rows fetch next 20 rows only"};
- var pagedSql = new SqlCe40QueryPager().ApplyPaging(sql, 10, 20);
+ var pagedSql = new SqlCe40QueryPager().ApplyPaging(sql, new string[0], 10, 20);
var modified = pagedSql.Select(x => Normalize.Replace(x, " ").ToLowerInvariant());
Assert.IsTrue(expected.SequenceEqual(modified));
View
32 Simple.Data.SqlServer/SqlQueryPager.cs
@@ -19,36 +19,47 @@ public IEnumerable<string> ApplyLimit(string sql, int take)
yield return SelectMatch.Replace(sql, match => match.Value + " TOP " + take + " ");
}
- public IEnumerable<string> ApplyPaging(string sql, int skip, int take)
+ public IEnumerable<string> ApplyPaging(string sql, string[] keys, int skip, int take)
{
var builder = new StringBuilder("WITH __Data AS (SELECT ");
var match = ColumnExtract.Match(sql);
var columns = match.Groups[1].Value.Trim();
var fromEtc = match.Groups[2].Value.Trim();
- builder.Append(columns);
+ builder.Append(string.Join(",", keys));
- var orderBy = ExtractOrderBy(columns, ref fromEtc);
+ var orderBy = ExtractOrderBy(columns, keys, ref fromEtc);
builder.AppendFormat(", ROW_NUMBER() OVER({0}) AS [_#_]", orderBy);
builder.AppendLine();
builder.Append(fromEtc);
builder.AppendLine(")");
- builder.AppendFormat("SELECT {0} FROM __Data WHERE [_#_] BETWEEN {1} AND {2}", DequalifyColumns(columns),
- skip + 1, skip + take);
+ builder.AppendFormat("SELECT {0} FROM __Data ", columns);
+ builder.AppendFormat("JOIN {0} ON ",
+ keys[0].Substring(0, keys[0].LastIndexOf(".", StringComparison.OrdinalIgnoreCase)));
+ builder.AppendFormat(string.Join(" ", keys.Select(MakeDataJoin)));
+ var rest = Regex.Replace(fromEtc, @"^from (\[.*?\]\.\[.*?\])", @"");
+ builder.Append(rest);
+
+ builder.AppendFormat(" AND [_#_] BETWEEN {0} AND {1}", skip + 1, skip + take);
yield return builder.ToString();
}
+ private static string MakeDataJoin(string key)
+ {
+ return key + " = __Data" + key.Substring(key.LastIndexOf(".", StringComparison.OrdinalIgnoreCase));
+ }
+
private static string DequalifyColumns(string original)
{
var q = from part in original.Split(',')
select part.Substring(Math.Max(part.LastIndexOf('.') + 1, part.LastIndexOf('[')));
return string.Join(",", q);
}
- private static string ExtractOrderBy(string columns, ref string fromEtc)
+ private static string ExtractOrderBy(string columns, string[] keys, ref string fromEtc)
{
string orderBy;
int index = fromEtc.IndexOf("ORDER BY", StringComparison.InvariantCultureIgnoreCase);
@@ -59,14 +70,7 @@ private static string ExtractOrderBy(string columns, ref string fromEtc)
}
else
{
- orderBy = "ORDER BY " + columns.Split(',').First().Trim();
-
- var aliasIndex = orderBy.IndexOf(" AS [", StringComparison.InvariantCultureIgnoreCase);
-
- if (aliasIndex > -1)
- {
- orderBy = orderBy.Substring(0, aliasIndex);
- }
+ orderBy = "ORDER BY " + string.Join(", ", keys);
}
return orderBy;
}
View
24 Simple.Data.SqlServer/SqlSchemaProvider.cs
@@ -109,7 +109,12 @@ public IEnumerable<Parameter> GetParameters(Procedure storedProcedure)
public Key GetPrimaryKey(Table table)
{
if (table == null) throw new ArgumentNullException("table");
- return new Key(GetPrimaryKeys(table.ActualName).AsEnumerable()
+ var primaryKeys = GetPrimaryKeys(table.ActualName);
+ if (primaryKeys == null)
+ {
+ return new Key(Enumerable.Empty<string>());
+ }
+ return new Key(primaryKeys.AsEnumerable()
.Where(
row =>
row["TABLE_SCHEMA"].ToString() == table.Schema && row["TABLE_NAME"].ToString() == table.ActualName)
@@ -176,8 +181,21 @@ private DataTable GetForeignKeys()
private DataTable GetPrimaryKeys(string tableName)
{
var primaryKeys = GetPrimaryKeys();
- var dataTable = primaryKeys.AsEnumerable().Where(row => row["TABLE_NAME"].ToString().Equals(tableName, StringComparison.InvariantCultureIgnoreCase)).CopyToDataTable();
- return dataTable;
+ try
+ {
+ var dataTable =
+ primaryKeys.AsEnumerable()
+ .Where(
+ row =>
+ row["TABLE_NAME"].ToString()
+ .Equals(tableName, StringComparison.InvariantCultureIgnoreCase))
+ .CopyToDataTable();
+ return dataTable;
+ }
+ catch (InvalidOperationException)
+ {
+ return null;
+ }
}
private EnumerableRowCollection<DataRow> GetForeignKeys(string tableName)
View
15 Simple.Data.SqlTest/QueryTest.cs
@@ -414,6 +414,21 @@ public void WithClauseShouldCastToStaticTypeWithEmptyCollection()
}
[Test]
+ public void WithClauseContainingAliasShouldReturnResults()
+ {
+ var db = DatabaseHelper.Open();
+ var actual = db.Customers
+ .With(db.Customers.Orders.As("Orders_1"))
+ .With(db.Customers.Orders.As("Orders_2"))
+ .FirstOrDefault();
+ Assert.IsNotNull(actual);
+ Assert.AreEqual(1, actual.Orders_1.Single().OrderId);
+ Assert.AreEqual(1, actual.Orders_2.Single().OrderId);
+ Assert.AreEqual(new DateTime(2010, 10, 10), actual.Orders_1.Single().OrderDate);
+ Assert.AreEqual(new DateTime(2010, 10, 10), actual.Orders_2.Single().OrderDate);
+ }
+
+ [Test]
public void SelfJoinShouldNotThrowException()
{
var db = DatabaseHelper.Open();
View
3 Simple.Data.SqlTest/Resources/DatabaseReset.txt
@@ -160,7 +160,8 @@ BEGIN
CREATE TABLE [dbo].[PagingTest] ([Id] int not null, [Dummy] int)
- CREATE CLUSTERED INDEX [ci_azure_fixup_dbo_PagingTest] ON [dbo].[PagingTest] ( [Id] ASC )
+ ALTER TABLE [dbo].[PagingTest]
+ ADD CONSTRAINT [PK_PagingTest] PRIMARY KEY CLUSTERED ([Id] ASC) ;
CREATE TABLE [dbo].[Blobs](
[Id] [int] NOT NULL,
View
52 Simple.Data.SqlTest/SqlQueryPagerTest.cs
@@ -28,57 +28,43 @@ public void ShouldApplyLimitUsingTop()
[Test]
public void ShouldApplyPagingUsingOrderBy()
{
- var sql = "select a,b,c from d where a = 1 order by c";
+ var sql = "select [dbo].[d].[a],[dbo].[d].[b],[dbo].[d].[c] from [dbo].[d] where [dbo].[d].[a] = 1 order by [dbo].[d].[c]";
var expected = new[]{
- "with __data as (select a,b,c, row_number() over(order by c) as [_#_] from d where a = 1)"
- + " select a,b,c from __data where [_#_] between 6 and 15"};
+ "with __data as (select [dbo].[d].[a], row_number() over(order by [dbo].[d].[c]) as [_#_] from [dbo].[d] where [dbo].[d].[a] = 1)"
+ + " select [dbo].[d].[a],[dbo].[d].[b],[dbo].[d].[c] from __data join [dbo].[d] on [dbo].[d].[a] = __data.[a] where [dbo].[d].[a] = 1 and [_#_] between 6 and 15"};
- var pagedSql = new SqlQueryPager().ApplyPaging(sql, 5, 10);
- var modified = pagedSql.Select(x => Normalize.Replace(x, " ").ToLowerInvariant());
+ var pagedSql = new SqlQueryPager().ApplyPaging(sql, new[] {"[dbo].[d].[a]"}, 5, 10);
+ var modified = pagedSql.Select(x => Normalize.Replace(x, " ").ToLowerInvariant()).ToArray();
- Assert.IsTrue(expected.SequenceEqual(modified));
+ Assert.AreEqual(expected[0], modified[0]);
}
[Test]
- public void ShouldApplyPagingUsingOrderByFirstColumnIfNotAlreadyOrdered()
+ public void ShouldApplyPagingUsingOrderByKeysIfNotAlreadyOrdered()
{
- var sql = "select a,b,c from d where a = 1";
+ var sql = "select [dbo].[d].[a],[dbo].[d].[b],[dbo].[d].[c] from [dbo].[d] where [dbo].[d].[a] = 1";
var expected = new[]{
- "with __data as (select a,b,c, row_number() over(order by a) as [_#_] from d where a = 1)"
- + " select a,b,c from __data where [_#_] between 11 and 30"};
+ "with __data as (select [dbo].[d].[a], row_number() over(order by [dbo].[d].[a]) as [_#_] from [dbo].[d] where [dbo].[d].[a] = 1)"
+ + " select [dbo].[d].[a],[dbo].[d].[b],[dbo].[d].[c] from __data join [dbo].[d] on [dbo].[d].[a] = __data.[a] where [dbo].[d].[a] = 1 and [_#_] between 11 and 30"};
- var pagedSql = new SqlQueryPager().ApplyPaging(sql, 10, 20);
- var modified = pagedSql.Select(x => Normalize.Replace(x, " ").ToLowerInvariant());
+ var pagedSql = new SqlQueryPager().ApplyPaging(sql, new[] {"[dbo].[d].[a]"}, 10, 20);
+ var modified = pagedSql.Select(x => Normalize.Replace(x, " ").ToLowerInvariant()).ToArray();
- Assert.IsTrue(expected.SequenceEqual(modified));
+ Assert.AreEqual(expected[0], modified[0]);
}
[Test]
public void ShouldCopeWithAliasedColumns()
{
- var sql = "select [a],[b] as [foo],[c] from [d] where [a] = 1";
+ var sql = "select [dbo].[d].[a],[dbo].[d].[b] as [foo],[dbo].[d].[c] from [dbo].[d] where [dbo].[d].[a] = 1";
var expected =new[]{
- "with __data as (select [a],[b] as [foo],[c], row_number() over(order by [a]) as [_#_] from [d] where [a] = 1)"
- + " select [a],[foo],[c] from __data where [_#_] between 21 and 25"};
-
- var pagedSql = new SqlQueryPager().ApplyPaging(sql, 20, 5);
- var modified = pagedSql.Select(x => Normalize.Replace(x, " ").ToLowerInvariant());
-
- Assert.IsTrue(expected.SequenceEqual(modified));
- }
-
- [Test]
- public void ShouldCopeWithAliasedDefaultSortColumn()
- {
- var sql = "select [a] as [foo],[b],[c] from [d] where [a] = 1";
- var expected = new[]{
- "with __data as (select [a] as [foo],[b],[c], row_number() over(order by [a]) as [_#_] from [d] where [a] = 1)"
- + " select [foo],[b],[c] from __data where [_#_] between 31 and 40"};
+ "with __data as (select [dbo].[d].[a], row_number() over(order by [dbo].[d].[a]) as [_#_] from [dbo].[d] where [dbo].[d].[a] = 1)"
+ + " select [dbo].[d].[a],[dbo].[d].[b] as [foo],[dbo].[d].[c] from __data join [dbo].[d] on [dbo].[d].[a] = __data.[a] where [dbo].[d].[a] = 1 and [_#_] between 21 and 25"};
- var pagedSql = new SqlQueryPager().ApplyPaging(sql, 30, 10);
- var modified = pagedSql.Select(x => Normalize.Replace(x, " ").ToLowerInvariant());
+ var pagedSql = new SqlQueryPager().ApplyPaging(sql, new[]{"[dbo].[d].[a]"}, 20, 5);
+ var modified = pagedSql.Select(x => Normalize.Replace(x, " ").ToLowerInvariant()).ToArray();
- Assert.IsTrue(expected.SequenceEqual(modified));
+ Assert.AreEqual(expected[0], modified[0]);
}
}
}

0 comments on commit 54581ae

Please sign in to comment.