1
0
Fork 0
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:
Sean Griffin 2016-05-06 11:55:21 -05:00
parent c763c00b5e
commit 96f3f3d826
3 changed files with 46 additions and 4 deletions

View file

@ -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:

View file

@ -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

View file

@ -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