未验证 提交 d326b029 编写于 作者: R Ryuta Kamizono 提交者: GitHub

Merge pull request #39051 from kamipo/more_concise_or_ast

More concise Arel `Or` ast and make `Or` visitor non recursive
...@@ -39,10 +39,16 @@ def or(other) ...@@ -39,10 +39,16 @@ def or(other)
if left.empty? || right.empty? if left.empty? || right.empty?
common common
else else
or_clause = WhereClause.new( left = left.ast
[left.ast.or(right.ast)], left = left.expr if left.is_a?(Arel::Nodes::Grouping)
)
common + or_clause right = right.ast
right = right.expr if right.is_a?(Arel::Nodes::Grouping)
or_clause = Arel::Nodes::Or.new(left, right)
common.predicates << Arel::Nodes::Grouping.new(or_clause)
common
end end
end end
......
...@@ -546,9 +546,18 @@ def visit_Arel_Nodes_And(o, collector) ...@@ -546,9 +546,18 @@ def visit_Arel_Nodes_And(o, collector)
end end
def visit_Arel_Nodes_Or(o, collector) def visit_Arel_Nodes_Or(o, collector)
collector = visit o.left, collector stack = [o.right, o.left]
collector << " OR "
visit o.right, collector while o = stack.pop
if o.is_a?(Arel::Nodes::Or)
stack.push o.right, o.left
else
visit o, collector
collector << " OR " unless stack.empty?
end
end
collector
end end
def visit_Arel_Nodes_Assignment(o, collector) def visit_Arel_Nodes_Assignment(o, collector)
......
...@@ -4,11 +4,11 @@ ...@@ -4,11 +4,11 @@
require "models/author" require "models/author"
require "models/categorization" require "models/categorization"
require "models/post" require "models/post"
require "models/citation"
module ActiveRecord module ActiveRecord
class OrTest < ActiveRecord::TestCase class OrTest < ActiveRecord::TestCase
fixtures :posts fixtures :posts, :authors, :author_addresses
fixtures :authors, :author_addresses
def test_or_with_relation def test_or_with_relation
expected = Post.where("id = 1 or id = 2").to_a expected = Post.where("id = 1 or id = 2").to_a
...@@ -151,4 +151,20 @@ def test_structurally_incompatible_values ...@@ -151,4 +151,20 @@ def test_structurally_incompatible_values
end end
end end
end end
# The maximum expression tree depth is 1000 by default for SQLite3.
# https://www.sqlite.org/limits.html#max_expr_depth
unless current_adapter?(:SQLite3Adapter)
class TooManyOrTest < ActiveRecord::TestCase
fixtures :citations
def test_too_many_or
citations = 6000.times.map do |i|
Citation.where(id: i, book2_id: i * i)
end
assert_equal 6000, citations.inject(&:or).count
end
end
end
end end
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册