Add add_limit_offset! to adapters.

This commit is contained in:
Emilio Tagua 2010-03-25 12:27:34 -03:00
parent ed21f0c502
commit e3a2fae05d
3 changed files with 56 additions and 0 deletions

View File

@ -181,6 +181,29 @@ module ActiveRecord
# done if the transaction block raises an exception or returns false.
def rollback_db_transaction() end
# Appends +LIMIT+ and +OFFSET+ options to an SQL statement, or some SQL
# fragment that has the same semantics as LIMIT and OFFSET.
#
# +options+ must be a Hash which contains a +:limit+ option
# and an +:offset+ option.
#
# This method *modifies* the +sql+ parameter.
#
# ===== Examples
# add_limit_offset!('SELECT * FROM suppliers', {:limit => 10, :offset => 50})
# generates
# SELECT * FROM suppliers LIMIT 10 OFFSET 50
def add_limit_offset!(sql, options)
if limit = options[:limit]
sql << " LIMIT #{sanitize_limit(limit)}"
end
if offset = options[:offset]
sql << " OFFSET #{offset.to_i}"
end
sql
end
def default_sequence_name(table, column)
nil
end

View File

@ -375,6 +375,18 @@ module ActiveRecord
execute("RELEASE SAVEPOINT #{current_savepoint_name}")
end
def add_limit_offset!(sql, options) #:nodoc:
limit, offset = options[:limit], options[:offset]
if limit && offset
sql << " LIMIT #{offset.to_i}, #{sanitize_limit(limit)}"
elsif limit
sql << " LIMIT #{sanitize_limit(limit)}"
elsif offset
sql << " OFFSET #{offset.to_i}"
end
sql
end
# SCHEMA STATEMENTS ========================================
def structure_dump #:nodoc:

View File

@ -142,4 +142,25 @@ class AdapterTest < ActiveRecord::TestCase
end
end
end
def test_add_limit_offset_should_sanitize_sql_injection_for_limit_without_comas
sql_inject = "1 select * from schema"
assert_equal " LIMIT 1", @connection.add_limit_offset!("", :limit => sql_inject)
if current_adapter?(:MysqlAdapter)
assert_equal " LIMIT 7, 1", @connection.add_limit_offset!("", :limit => sql_inject, :offset => 7)
else
assert_equal " LIMIT 1 OFFSET 7", @connection.add_limit_offset!("", :limit => sql_inject, :offset => 7)
end
end
def test_add_limit_offset_should_sanitize_sql_injection_for_limit_with_comas
sql_inject = "1, 7 procedure help()"
if current_adapter?(:MysqlAdapter)
assert_equal " LIMIT 1,7", @connection.add_limit_offset!("", :limit => sql_inject)
assert_equal " LIMIT 7, 1", @connection.add_limit_offset!("", :limit => '1 ; DROP TABLE USERS', :offset => 7)
else
assert_equal " LIMIT 1,7", @connection.add_limit_offset!("", :limit => sql_inject)
assert_equal " LIMIT 1,7 OFFSET 7", @connection.add_limit_offset!("", :limit => sql_inject, :offset => 7)
end
end
end