Added adapter independent limit clause as a two-element array with the first being the limit, the second being the offset #795 [Sam Stephenson]
git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@944 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
This commit is contained in:
parent
9fe45f31eb
commit
ee8d110068
@ -1,5 +1,12 @@
|
||||
*SVN*
|
||||
|
||||
* Added adapter independent limit clause as a two-element array with the first being the limit, the second being the offset #795 [Sam Stephenson]. Example:
|
||||
|
||||
Developer.find_all nil, 'id ASC', 5 # return the first five developers
|
||||
Developer.find_all nil, 'id ASC', [3, 8] # return three developers, starting from #8 and forward
|
||||
|
||||
This doesn't yet work with the DB2 or MS SQL adapters. Patches to make that happen are encouraged.
|
||||
|
||||
* Added alias_method :to_param, :id to Base, such that Active Record objects to be used as URL parameters in Action Pack automatically #812 [Nicholas Seckar/Sam Stephenson]
|
||||
|
||||
* Improved the performance of the OCI8 adapter for Oracle #723 [pilx/gjenkins]
|
||||
|
@ -346,16 +346,18 @@ def find_on_conditions(ids, conditions)
|
||||
# table in the database. The +conditions+ can be used to narrow the selection of objects (WHERE-part),
|
||||
# such as by "color = 'red'", and arrangement of the selection can be done through +orderings+ (ORDER BY-part),
|
||||
# such as by "last_name, first_name DESC". A maximum of returned objects and their offset can be specified in
|
||||
# +limit+ (LIMIT...OFFSET-part). Examples:
|
||||
# +limit+ with either just a single integer as the limit or as an array with the first element as the limit,
|
||||
# the second as the offset. Examples:
|
||||
# Project.find_all "category = 'accounts'", "last_accessed DESC", 15
|
||||
# Project.find_all ["category = ?", category_name], "created ASC", ["? OFFSET ?", 15, 20]
|
||||
# Project.find_all ["category = ?", category_name], "created ASC", [15, 20]
|
||||
def find_all(conditions = nil, orderings = nil, limit = nil, joins = nil)
|
||||
sql = "SELECT * FROM #{table_name} "
|
||||
sql << "#{joins} " if joins
|
||||
add_conditions!(sql, conditions)
|
||||
sql << "ORDER BY #{orderings} " unless orderings.nil?
|
||||
|
||||
connection.add_limit!(sql, sanitize_sql(limit)) unless limit.nil?
|
||||
limit = sanitize_sql(limit) if limit.is_a? Array and limit.first.is_a? String
|
||||
connection.add_limit!(sql, limit) if limit
|
||||
|
||||
find_by_sql(sql)
|
||||
end
|
||||
|
@ -353,10 +353,22 @@ def adapter_name()
|
||||
def structure_dump() end
|
||||
|
||||
def add_limit!(sql, limit)
|
||||
if limit.is_a? Array
|
||||
limit, offset = *limit
|
||||
add_limit_with_offset!(sql, limit.to_i, offset.to_i)
|
||||
else
|
||||
add_limit_without_offset!(sql, limit)
|
||||
end
|
||||
end
|
||||
|
||||
def add_limit_with_offset!(sql, limit, offset)
|
||||
sql << " LIMIT #{limit} OFFSET #{offset}"
|
||||
end
|
||||
|
||||
def add_limit_without_offset!(sql, limit)
|
||||
sql << " LIMIT #{limit}"
|
||||
end
|
||||
|
||||
|
||||
def initialize_schema_information
|
||||
begin
|
||||
execute "CREATE TABLE schema_info (version #{native_database_types[:integer][:name]}#{native_database_types[:integer][:limit]})"
|
||||
|
@ -89,7 +89,11 @@ def quote_string(s)
|
||||
s.gsub(/'/, "''") # ' (for ruby-mode)
|
||||
end
|
||||
|
||||
def add_limit!(sql, limit)
|
||||
def add_limit_with_offset!(sql, limit, offset)
|
||||
raise ArgumentError, 'add_limit_with_offset! not implemented'
|
||||
end
|
||||
|
||||
def add_limit_without_offset!(sql, limit)
|
||||
sql << " FETCH FIRST #{limit} ROWS ONLY"
|
||||
end
|
||||
|
||||
|
@ -172,7 +172,11 @@ def structure_dump
|
||||
structure += select_one("SHOW CREATE TABLE #{table.to_a.first.last}")["Create Table"] + ";\n\n"
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def add_limit_with_offset!(sql, limit, offset)
|
||||
sql << " LIMIT #{offset}, #{limit}"
|
||||
end
|
||||
|
||||
def recreate_database(name)
|
||||
drop_database(name)
|
||||
create_database(name)
|
||||
|
@ -182,10 +182,6 @@ def execute(sql, name = nil)
|
||||
alias :update :execute
|
||||
alias :delete :execute
|
||||
|
||||
def add_limit!(sql, limit)
|
||||
sql << "LIMIT=" << limit.to_s
|
||||
end
|
||||
|
||||
def begin_db_transaction()
|
||||
@connection.autocommit = false
|
||||
end
|
||||
|
@ -253,19 +253,12 @@ def quote_column_name(name)
|
||||
"[#{name}]"
|
||||
end
|
||||
|
||||
def add_limit!(sql, limit)
|
||||
if sql =~ /LIMIT/i
|
||||
limit = sql.slice!(/LIMIT.*/).gsub(/LIMIT.(.*)$/, '\1')
|
||||
end
|
||||
if !limit.nil?
|
||||
limit_amount = limit.to_s.include?("OFFSET") ? get_offset_amount(limit) : Array.new([limit])
|
||||
order_by = sql.include?("ORDER BY") ? get_order_by(sql.sub(/.*ORDER\sBY./, "")) : nil
|
||||
if limit_amount.size == 2
|
||||
sql.gsub!(/SELECT/i, "SELECT * FROM ( SELECT TOP #{limit_amount[0]} * FROM ( SELECT TOP #{limit_amount[1]}")<<" ) AS tmp1 ORDER BY #{order_by[1]} ) AS tmp2 ORDER BY #{order_by[0]}"
|
||||
else
|
||||
sql.gsub!(/SELECT/i, "SELECT TOP #{limit_amount[0]}")
|
||||
end
|
||||
end
|
||||
def add_limit_with_offset!(sql, limit, offset)
|
||||
raise ArgumentError, 'add_limit_with_offset! not implemented'
|
||||
end
|
||||
|
||||
def add_limit_without_offset!(sql, limit)
|
||||
raise ArgumentError, 'add_limit_without_offset! not implemented'
|
||||
end
|
||||
|
||||
def recreate_database(name)
|
||||
|
@ -4,7 +4,7 @@
|
||||
require 'fixtures/entrant'
|
||||
|
||||
class FinderTest < Test::Unit::TestCase
|
||||
fixtures :companies, :topics, :entrants
|
||||
fixtures :companies, :topics, :entrants, :developers
|
||||
|
||||
def test_find
|
||||
assert_equal(@topics["first"]["title"], Topic.find(1).title)
|
||||
@ -244,6 +244,33 @@ def test_find_with_bad_sql
|
||||
assert_raises(ActiveRecord::StatementInvalid) { Topic.find_by_sql "select 1 from badtable" }
|
||||
end
|
||||
|
||||
def test_find_all_with_limit
|
||||
first_five_developers = Developer.find_all nil, 'id ASC', 5
|
||||
assert_equal 5, first_five_developers.length
|
||||
assert_equal 'David', first_five_developers.first.name
|
||||
assert_equal 'fixture_5', first_five_developers.last.name
|
||||
|
||||
no_developers = Developer.find_all nil, 'id ASC', 0
|
||||
assert_equal 0, no_developers.length
|
||||
|
||||
assert_equal first_five_developers, Developer.find_all(nil, 'id ASC', [5])
|
||||
assert_equal no_developers, Developer.find_all(nil, 'id ASC', [0])
|
||||
end
|
||||
|
||||
def test_find_all_with_limit_and_offset
|
||||
first_three_developers = Developer.find_all nil, 'id ASC', [3, 0]
|
||||
second_three_developers = Developer.find_all nil, 'id ASC', [3, 3]
|
||||
last_two_developers = Developer.find_all nil, 'id ASC', [3, 8]
|
||||
|
||||
assert_equal 3, first_three_developers.length
|
||||
assert_equal 3, second_three_developers.length
|
||||
assert_equal 2, last_two_developers.length
|
||||
|
||||
assert_equal 'David', first_three_developers.first.name
|
||||
assert_equal 'fixture_4', second_three_developers.first.name
|
||||
assert_equal 'fixture_9', last_two_developers.first.name
|
||||
end
|
||||
|
||||
protected
|
||||
def bind(statement, *vars)
|
||||
if vars.first.is_a?(Hash)
|
||||
|
Loading…
Reference in New Issue
Block a user