mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Allow the connection adapters to determine the order of bind params
In 5.0 we use bind parameters for limit and offset, while in 4.2 we used the values directly. The code as it was written assumed that limit and offset worked as `LIMIT ? OFFSET ?`. Both Oracle and SQL Server have a different syntax, where the offset is stated before the limit. We delegate this behavior to the connection adapter so that these adapters are able to determine how the bind parameters are flattened based on what order their specification has the various clauses appear. Fixes #24775
This commit is contained in:
parent
c763c00b5e
commit
96f3f3d826
3 changed files with 46 additions and 4 deletions
|
@ -454,6 +454,24 @@ module ActiveRecord
|
|||
visitor.accept(node, collector).value
|
||||
end
|
||||
|
||||
def combine_bind_parameters(
|
||||
from_clause: [],
|
||||
join_clause: [],
|
||||
where_clause: [],
|
||||
having_clause: [],
|
||||
limit: nil,
|
||||
offset: nil
|
||||
) # :nodoc:
|
||||
result = from_clause + join_clause + where_clause + having_clause
|
||||
if limit
|
||||
result << limit
|
||||
end
|
||||
if offset
|
||||
result << offset
|
||||
end
|
||||
result
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def initialize_type_map(m) # :nodoc:
|
||||
|
|
|
@ -99,22 +99,28 @@ module ActiveRecord
|
|||
end
|
||||
|
||||
def bound_attributes
|
||||
result = from_clause.binds + arel.bind_values + where_clause.binds + having_clause.binds
|
||||
if limit_value && !string_containing_comma?(limit_value)
|
||||
result << Attribute.with_cast_value(
|
||||
limit_bind = Attribute.with_cast_value(
|
||||
"LIMIT".freeze,
|
||||
connection.sanitize_limit(limit_value),
|
||||
Type::Value.new,
|
||||
)
|
||||
end
|
||||
if offset_value
|
||||
result << Attribute.with_cast_value(
|
||||
offset_bind = Attribute.with_cast_value(
|
||||
"OFFSET".freeze,
|
||||
offset_value.to_i,
|
||||
Type::Value.new,
|
||||
)
|
||||
end
|
||||
result
|
||||
connection.combine_bind_parameters(
|
||||
from_clause: from_clause.binds,
|
||||
join_clause: arel.bind_values,
|
||||
where_clause: where_clause.binds,
|
||||
having_clause: having_clause.binds,
|
||||
limit: limit_bind,
|
||||
offset: offset_bind,
|
||||
)
|
||||
end
|
||||
|
||||
FROZEN_EMPTY_HASH = {}.freeze
|
||||
|
|
|
@ -1989,4 +1989,22 @@ class RelationTest < ActiveRecord::TestCase
|
|||
def test_relation_join_method
|
||||
assert_equal 'Thank you for the welcome,Thank you again for the welcome', Post.first.comments.join(",")
|
||||
end
|
||||
|
||||
def test_connection_adapters_can_reorder_binds
|
||||
posts = Post.limit(1).offset(2)
|
||||
|
||||
stubbed_connection = Post.connection.dup
|
||||
def stubbed_connection.combine_bind_parameters(**kwargs)
|
||||
offset = kwargs[:offset]
|
||||
kwargs[:offset] = kwargs[:limit]
|
||||
kwargs[:limit] = offset
|
||||
super(**kwargs)
|
||||
end
|
||||
|
||||
posts.define_singleton_method(:connection) do
|
||||
stubbed_connection
|
||||
end
|
||||
|
||||
assert_equal 2, posts.to_a.length
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue