Skip to content

Commit c5a99e0

Browse files
committed
Allow PredicateBuilder to recognize schema namespaced table names. [Fix rails#48172]
1 parent 6adaeb8 commit c5a99e0

File tree

2 files changed

+33
-13
lines changed

2 files changed

+33
-13
lines changed

activerecord/lib/active_record/relation/predicate_builder.rb

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@ def self.references(attributes)
2929
attributes.each_with_object([]) do |(key, value), result|
3030
if value.is_a?(Hash)
3131
result << Arel.sql(key)
32-
elsif key.include?(".")
33-
result << Arel.sql(key.split(".").first)
32+
elsif (idx = key.rindex("."))
33+
result << Arel.sql(key[0, idx])
3434
end
3535
end
3636
end
@@ -149,19 +149,25 @@ def grouping_queries(queries)
149149
end
150150

151151
def convert_dot_notation_to_hash(attributes)
152-
dot_notation = attributes.select do |k, v|
153-
k.include?(".") && !v.is_a?(Hash)
154-
end
155-
156-
dot_notation.each_key do |key|
157-
table_name, column_name = key.split(".")
158-
value = attributes.delete(key)
159-
attributes[table_name] ||= {}
152+
attributes.each_with_object({}) do |(key, value), converted|
153+
if value.is_a?(Hash)
154+
if (existing = converted[key])
155+
existing.merge!(value)
156+
else
157+
converted[key] = value.dup
158+
end
159+
elsif (idx = key.rindex("."))
160+
table_name, column_name = key[0, idx], key[idx + 1, key.length]
160161

161-
attributes[table_name] = attributes[table_name].merge(column_name => value)
162+
if (existing = converted[table_name])
163+
existing[column_name] = value
164+
else
165+
converted[table_name] = { column_name => value }
166+
end
167+
else
168+
converted[key] = value
169+
end
162170
end
163-
164-
attributes
165171
end
166172

167173
def handler_for(object)

activerecord/test/cases/relation/predicate_builder_test.rb

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,20 @@ def test_registering_new_handlers_for_association
2323
assert_match %r{#{Regexp.escape(topic_title)} ~ 'rails'}i, Reply.joins(:topic).where(topics: { title: /rails/ }).to_sql
2424
end
2525

26+
def test_references_with_schema
27+
assert_equal %w{schema.table}, ActiveRecord::PredicateBuilder.references(%w{schema.table.column})
28+
end
29+
30+
def test_build_from_hash_with_schema
31+
assert_match %r{schema.+table.+column}i, Topic.predicate_builder.build_from_hash("schema.table.column" => "value").first.to_sql
32+
end
33+
34+
def test_does_not_mutate
35+
defaults = { topics: { title: "rails" }, "topics.approved" => true }
36+
Topic.where(defaults).to_sql
37+
assert_equal({ topics: { title: "rails" }, "topics.approved" => true }, defaults)
38+
end
39+
2640
private
2741
def topic_title
2842
Topic.connection.quote_table_name("topics.title")

0 commit comments

Comments
 (0)