Skip to content

Commit a9f4d38

Browse files
h-lamemetaskills
authored andcommitted
Changing add_limit! in ActiveRecord::Base for SQLServer so that it passes through any scoped :order parameters.
We need these so that our limit and offset code can properly reverse and re-order the inner query and thus correctly paginate the results. Signed-off-by: Murray Steele <muz@h-lame.com>
1 parent 9265961 commit a9f4d38

File tree

2 files changed

+45
-0
lines changed

2 files changed

+45
-0
lines changed

lib/core_ext/active_record.rb

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ def self.included(klass)
99
class << klass
1010
alias_method_chain :reset_column_information, :sqlserver_cache_support
1111
alias_method_chain :add_order!, :sqlserver_unique_checking
12+
alias_method_chain :add_limit!, :sqlserver_order_checking
1213
end
1314
end
1415

@@ -45,6 +46,23 @@ def reset_column_information_with_sqlserver_cache_support
4546

4647
private
4748

49+
def add_limit_with_sqlserver_order_checking!(sql, options, scope = :auto)
50+
if connection.respond_to?(:sqlserver?)
51+
scope = scope(:find) if :auto == scope
52+
if scope
53+
options = options.dup
54+
scoped_order = scope[:order]
55+
order = options[:order]
56+
if order && scoped_order
57+
options[:order] = add_order_with_sqlserver_unique_checking!('', order, scope).gsub(/^ ORDER BY /,'')
58+
elsif scoped_order
59+
options[:order] = scoped_order
60+
end
61+
end
62+
end
63+
add_limit_without_sqlserver_order_checking!(sql, options, scope)
64+
end
65+
4866
def add_order_with_sqlserver_unique_checking!(sql, order, scope = :auto)
4967
if connection.respond_to?(:sqlserver?)
5068
order_sql = ''

test/cases/adapter_test_sqlserver.rb

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,28 @@ def setup
159159
end
160160

161161
end
162+
163+
context "for add_limit! within a scoped method call" do
164+
setup do
165+
@connection.stubs(:select_value).with(regexp_matches(/TotalRows/)).returns '100000000'
166+
end
167+
168+
should 'not add any ordering if the scope doesn\'t have an order' do
169+
assert_equal 'SELECT * FROM (SELECT TOP 10 * FROM (SELECT TOP 40 * FROM [developers]) AS tmp1) AS tmp2', add_limit!('SELECT * FROM [developers]', {:offset => 30, :limit => 10}, {})
170+
end
171+
172+
should 'still add the default ordering if the scope doesn\'t have an order but the raw order option is there' do
173+
assert_equal 'SELECT * FROM (SELECT TOP 10 * FROM (SELECT TOP 40 * FROM [developers]) AS tmp1 ORDER BY [name] DESC) AS tmp2 ORDER BY [name]', add_limit!('SELECT * FROM [developers]', {:offset => 30, :limit => 10, :order => 'name'}, {})
174+
end
175+
176+
should 'add scoped order options to the offset and limit sql' do
177+
assert_equal 'SELECT * FROM (SELECT TOP 10 * FROM (SELECT TOP 40 * FROM [developers]) AS tmp1 ORDER BY [id] DESC) AS tmp2 ORDER BY [id]', add_limit!('SELECT * FROM [developers]', {:offset => 30, :limit => 10}, {:order => 'id'})
178+
end
179+
180+
should 'combine scoped order with raw order options in the offset and limit sql' do
181+
assert_equal 'SELECT * FROM (SELECT TOP 10 * FROM (SELECT TOP 40 * FROM [developers]) AS tmp1 ORDER BY [name] DESC, [id] DESC) AS tmp2 ORDER BY [name], [id]', add_limit!('SELECT * FROM [developers]', {:offset => 30, :limit => 10, :order => 'name'}, {:order => 'id'})
182+
end
183+
end
162184

163185
context 'dealing with various orders SQL snippets' do
164186

@@ -659,6 +681,11 @@ def add_order!(order,sql='')
659681
sql
660682
end
661683

684+
def add_limit!(sql, options, scope = :auto)
685+
ActiveRecord::Base.send :add_limit!, sql, options, scope
686+
sql
687+
end
688+
662689
def order_to_min_set(order)
663690
@connection.send :order_to_min_set, order
664691
end

0 commit comments

Comments
 (0)