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

Merge pull request #35847 from kamipo/optimizer_hints_with_count_subquery

Optimizer hints should be applied on Top level query as much as possible
......@@ -23,8 +23,7 @@ def collection_cache_key(collection = all, timestamp_column = :updated_at) # :no
query = collection.select("#{column} AS collection_cache_key_timestamp")
subquery_alias = "subquery_for_cache_key"
subquery_column = "#{subquery_alias}.collection_cache_key_timestamp"
subquery = query.arel.as(subquery_alias)
arel = Arel::SelectManager.new(subquery).project(select_values % subquery_column)
arel = query.send(:build_subquery, subquery_alias, select_values % subquery_column)
else
query = collection.unscope(:order)
query.select_values = [select_values % column]
......
......@@ -416,16 +416,17 @@ def select_for_count
def build_count_subquery(relation, column_name, distinct)
if column_name == :all
column_alias = Arel.star
relation.select_values = [ Arel.sql(FinderMethods::ONE_AS_ONE) ] unless distinct
else
column_alias = Arel.sql("count_column")
relation.select_values = [ aggregate_column(column_name).as(column_alias) ]
end
subquery = relation.arel.as(Arel.sql("subquery_for_count"))
select_value = operation_over_aggregate_column(column_alias || Arel.star, "count", false)
subquery_alias = Arel.sql("subquery_for_count")
select_value = operation_over_aggregate_column(column_alias, "count", false)
Arel::SelectManager.new(subquery).project(select_value)
relation.build_subquery(subquery_alias, select_value)
end
end
end
......@@ -992,6 +992,15 @@ def arel(aliases = nil) # :nodoc:
@arel ||= build_arel(aliases)
end
protected
def build_subquery(subquery_alias, select_value) # :nodoc:
subquery = except(:optimizer_hints).arel.as(subquery_alias)
Arel::SelectManager.new(subquery).project(select_value).tap do |arel|
arel.optimizer_hints(*optimizer_hints_values) unless optimizer_hints_values.empty?
end
end
private
# Returns a relation value with a given name
def get_value(name)
......
......@@ -15,6 +15,14 @@ def test_optimizer_hints
end
end
def test_optimizer_hints_with_count_subquery
assert_sql(%r{\ASELECT /\*\+ NO_RANGE_OPTIMIZATION\(posts index_posts_on_author_id\) \*/}) do
posts = Post.optimizer_hints("NO_RANGE_OPTIMIZATION(posts index_posts_on_author_id)")
posts = posts.select(:id).where(author_id: [0, 1]).limit(5)
assert_equal 5, posts.count
end
end
def test_optimizer_hints_is_sanitized
assert_sql(%r{\ASELECT /\*\+ NO_RANGE_OPTIMIZATION\(posts index_posts_on_author_id\) \*/}) do
posts = Post.optimizer_hints("/*+ NO_RANGE_OPTIMIZATION(posts index_posts_on_author_id) */")
......
......@@ -19,6 +19,14 @@ def test_optimizer_hints
end
end
def test_optimizer_hints_with_count_subquery
assert_sql(%r{\ASELECT /\*\+ SeqScan\(posts\) \*/}) do
posts = Post.optimizer_hints("SeqScan(posts)")
posts = posts.select(:id).where(author_id: [0, 1]).limit(5)
assert_equal 5, posts.count
end
end
def test_optimizer_hints_is_sanitized
assert_sql(%r{\ASELECT /\*\+ SeqScan\(posts\) \*/}) do
posts = Post.optimizer_hints("/*+ SeqScan(posts) */")
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册