Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
张重言
rails
提交
3e5e1f94
R
rails
项目概览
张重言
/
rails
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
rails
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
未验证
提交
3e5e1f94
编写于
4月 05, 2019
作者:
R
Ryuta Kamizono
提交者:
GitHub
4月 05, 2019
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #35864 from kamipo/improve_left_joins
Stash `left_joins` into `joins` to deduplicate redundant LEFT JOIN
上级
cadc5de2
8f05035b
变更
6
隐藏空白更改
内联
并排
Showing
6 changed file
with
45 addition
and
32 deletion
+45
-32
activerecord/lib/active_record/relation/finder_methods.rb
activerecord/lib/active_record/relation/finder_methods.rb
+0
-6
activerecord/lib/active_record/relation/merger.rb
activerecord/lib/active_record/relation/merger.rb
+7
-16
activerecord/lib/active_record/relation/query_methods.rb
activerecord/lib/active_record/relation/query_methods.rb
+23
-8
activerecord/test/cases/associations/inner_join_association_test.rb
...rd/test/cases/associations/inner_join_association_test.rb
+4
-1
activerecord/test/cases/associations/left_outer_join_association_test.rb
...st/cases/associations/left_outer_join_association_test.rb
+10
-0
activerecord/test/cases/relation/delegation_test.rb
activerecord/test/cases/relation/delegation_test.rb
+1
-1
未找到文件。
activerecord/lib/active_record/relation/finder_methods.rb
浏览文件 @
3e5e1f94
...
...
@@ -370,12 +370,6 @@ def construct_relation_for_exists(conditions)
relation
end
def
construct_join_dependency
(
associations
)
ActiveRecord
::
Associations
::
JoinDependency
.
new
(
klass
,
table
,
associations
)
end
def
apply_join_dependency
(
eager_loading:
group_values
.
empty?
)
join_dependency
=
construct_join_dependency
(
eager_load_values
+
includes_values
)
relation
=
except
(
:includes
,
:eager_load
,
:preload
).
joins!
(
join_dependency
)
...
...
activerecord/lib/active_record/relation/merger.rb
浏览文件 @
3e5e1f94
...
...
@@ -117,16 +117,14 @@ def merge_joins
if
other
.
klass
==
relation
.
klass
relation
.
joins!
(
*
other
.
joins_values
)
else
joins_dependency
=
other
.
joins_values
.
map
do
|
join
|
associations
,
others
=
other
.
joins_values
.
partition
do
|
join
|
case
join
when
Hash
,
Symbol
,
Array
other
.
send
(
:construct_join_dependency
,
join
)
else
join
when
Hash
,
Symbol
,
Array
;
true
end
end
relation
.
joins!
(
*
joins_dependency
)
join_dependency
=
other
.
construct_join_dependency
(
associations
)
relation
.
joins!
(
join_dependency
,
*
others
)
end
end
...
...
@@ -136,16 +134,9 @@ def merge_outer_joins
if
other
.
klass
==
relation
.
klass
relation
.
left_outer_joins!
(
*
other
.
left_outer_joins_values
)
else
joins_dependency
=
other
.
left_outer_joins_values
.
map
do
|
join
|
case
join
when
Hash
,
Symbol
,
Array
other
.
send
(
:construct_join_dependency
,
join
)
else
join
end
end
relation
.
left_outer_joins!
(
*
joins_dependency
)
associations
=
other
.
left_outer_joins_values
join_dependency
=
other
.
construct_join_dependency
(
associations
)
relation
.
joins!
(
join_dependency
)
end
end
...
...
activerecord/lib/active_record/relation/query_methods.rb
浏览文件 @
3e5e1f94
...
...
@@ -992,6 +992,12 @@ def arel(aliases = nil) # :nodoc:
@arel
||=
build_arel
(
aliases
)
end
def
construct_join_dependency
(
associations
)
# :nodoc:
ActiveRecord
::
Associations
::
JoinDependency
.
new
(
klass
,
table
,
associations
)
end
protected
def
build_subquery
(
subquery_alias
,
select_value
)
# :nodoc:
subquery
=
except
(
:optimizer_hints
).
arel
.
as
(
subquery_alias
)
...
...
@@ -1021,8 +1027,11 @@ def assert_mutability!
def
build_arel
(
aliases
)
arel
=
Arel
::
SelectManager
.
new
(
table
)
aliases
=
build_joins
(
arel
,
joins_values
.
flatten
,
aliases
)
unless
joins_values
.
empty?
build_left_outer_joins
(
arel
,
left_outer_joins_values
.
flatten
,
aliases
)
unless
left_outer_joins_values
.
empty?
if
!
joins_values
.
empty?
build_joins
(
arel
,
joins_values
.
flatten
,
aliases
)
elsif
!
left_outer_joins_values
.
empty?
build_left_outer_joins
(
arel
,
left_outer_joins_values
.
flatten
,
aliases
)
end
arel
.
where
(
where_clause
.
ast
)
unless
where_clause
.
empty?
arel
.
having
(
having_clause
.
ast
)
unless
having_clause
.
empty?
...
...
@@ -1072,22 +1081,28 @@ def build_from
end
end
def
build_left_outer_joins
(
manager
,
outer_joins
,
aliase
s
)
buckets
=
outer_joins
.
group_by
do
|
joi
n
|
case
joi
n
def
valid_association_list
(
association
s
)
associations
.
each
do
|
associatio
n
|
case
associatio
n
when
Hash
,
Symbol
,
Array
:association_join
when
ActiveRecord
::
Associations
::
JoinDependency
:stashed_join
# valid
else
raise
ArgumentError
,
"only Hash, Symbol and Array are allowed"
end
end
end
def
build_left_outer_joins
(
manager
,
outer_joins
,
aliases
)
buckets
=
{
association_join:
valid_association_list
(
outer_joins
)
}
build_join_query
(
manager
,
buckets
,
Arel
::
Nodes
::
OuterJoin
,
aliases
)
end
def
build_joins
(
manager
,
joins
,
aliases
)
unless
left_outer_joins_values
.
empty?
left_joins
=
valid_association_list
(
left_outer_joins_values
.
flatten
)
joins
<<
construct_join_dependency
(
left_joins
)
end
buckets
=
joins
.
group_by
do
|
join
|
case
join
when
String
...
...
activerecord/test/cases/associations/inner_join_association_test.rb
浏览文件 @
3e5e1f94
...
...
@@ -29,7 +29,10 @@ def test_construct_finder_sql_does_not_table_name_collide_on_duplicate_associati
def
test_construct_finder_sql_does_not_table_name_collide_on_duplicate_associations_with_left_outer_joins
sql
=
Person
.
joins
(
agents: :agents
).
left_outer_joins
(
agents: :agents
).
to_sql
assert_match
(
/agents_people_4/i
,
sql
)
assert_match
(
/agents_people_2/i
,
sql
)
assert_match
(
/INNER JOIN/i
,
sql
)
assert_no_match
(
/agents_people_4/i
,
sql
)
assert_no_match
(
/LEFT OUTER JOIN/i
,
sql
)
end
def
test_construct_finder_sql_does_not_table_name_collide_with_string_joins
...
...
activerecord/test/cases/associations/left_outer_join_association_test.rb
浏览文件 @
3e5e1f94
...
...
@@ -46,6 +46,12 @@ def test_left_outer_joins_actually_does_a_left_outer_join
assert
queries
.
any?
{
|
sql
|
/LEFT OUTER JOIN/i
.
match?
(
sql
)
}
end
def
test_left_outer_joins_is_deduped_when_same_association_is_joined
queries
=
capture_sql
{
Author
.
joins
(
:posts
).
left_outer_joins
(
:posts
).
to_a
}
assert
queries
.
any?
{
|
sql
|
/INNER JOIN/i
.
match?
(
sql
)
}
assert
queries
.
none?
{
|
sql
|
/LEFT OUTER JOIN/i
.
match?
(
sql
)
}
end
def
test_construct_finder_sql_ignores_empty_left_outer_joins_hash
queries
=
capture_sql
{
Author
.
left_outer_joins
({}).
to_a
}
assert
queries
.
none?
{
|
sql
|
/LEFT OUTER JOIN/i
.
match?
(
sql
)
}
...
...
@@ -60,6 +66,10 @@ def test_left_outer_joins_forbids_to_use_string_as_argument
assert_raise
(
ArgumentError
)
{
Author
.
left_outer_joins
(
'LEFT OUTER JOIN "posts" ON "posts"."user_id" = "users"."id"'
).
to_a
}
end
def
test_left_outer_joins_with_string_join
assert_equal
16
,
Author
.
left_outer_joins
(
:posts
).
joins
(
"LEFT OUTER JOIN comments ON comments.post_id = posts.id"
).
count
end
def
test_join_conditions_added_to_join_clause
queries
=
capture_sql
{
Author
.
left_outer_joins
(
:essays
).
to_a
}
assert
queries
.
any?
{
|
sql
|
/writer_type.*?=.*?(Author|\?|\$1|\:a1)/i
.
match?
(
sql
)
}
...
...
activerecord/test/cases/relation/delegation_test.rb
浏览文件 @
3e5e1f94
...
...
@@ -51,7 +51,7 @@ class QueryingMethodsDelegationTest < ActiveRecord::TestCase
ActiveRecord
::
SpawnMethods
.
public_instance_methods
(
false
)
-
[
:spawn
,
:merge!
]
+
ActiveRecord
::
QueryMethods
.
public_instance_methods
(
false
).
reject
{
|
method
|
method
.
to_s
.
end_with?
(
"="
,
"!"
,
"value"
,
"values"
,
"clause"
)
}
-
[
:reverse_order
,
:arel
,
:extensions
]
+
[
}
-
[
:reverse_order
,
:arel
,
:extensions
,
:construct_join_dependency
]
+
[
:any?
,
:many?
,
:none?
,
:one?
,
:first_or_create
,
:first_or_create!
,
:first_or_initialize
,
:find_or_create_by
,
:find_or_create_by!
,
:find_or_initialize_by
,
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录