Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
张重言
rails
提交
f3e379f0
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,发现更多精彩内容 >>
提交
f3e379f0
编写于
1月 15, 2014
作者:
A
Aaron Patterson
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
use a params hash so we know what bind parameters are used
上级
7fff71b3
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
65 addition
and
25 deletion
+65
-25
activerecord/lib/active_record/relation/query_methods.rb
activerecord/lib/active_record/relation/query_methods.rb
+1
-1
activerecord/lib/active_record/statement_cache.rb
activerecord/lib/active_record/statement_cache.rb
+48
-9
activerecord/test/cases/statement_cache_test.rb
activerecord/test/cases/statement_cache_test.rb
+16
-15
未找到文件。
activerecord/lib/active_record/relation/query_methods.rb
浏览文件 @
f3e379f0
...
...
@@ -948,7 +948,7 @@ def build_where(opts, other = [])
def
create_binds
(
opts
,
idx
)
bindable
,
non_binds
=
opts
.
partition
do
|
column
,
value
|
case
value
when
String
,
Integer
when
String
,
Integer
,
ActiveRecord
::
StatementCache
::
Substitute
@klass
.
columns_hash
.
include?
column
.
to_s
else
false
...
...
activerecord/lib/active_record/statement_cache.rb
浏览文件 @
f3e379f0
...
...
@@ -14,25 +14,64 @@ module ActiveRecord
# The relation returned by the block is cached, and for each +execute+ call the cached relation gets duped.
# Database is queried when +to_a+ is called on the relation.
class
StatementCache
Substitute
=
Struct
.
new
:name
class
Params
def
[]
(
name
);
Substitute
.
new
name
;
end
end
class
BindMap
def
initialize
(
bind_values
)
@value_map
=
{}
@bind_values
=
bind_values
bind_values
.
each_with_index
do
|
(
column
,
value
),
i
|
if
Substitute
===
value
@value_map
[
value
.
name
]
=
i
end
end
end
def
bind
(
values
)
bvs
=
@bind_values
.
map
{
|
pair
|
pair
.
dup
}
values
.
each
{
|
k
,
v
|
bvs
[
@value_map
[
k
]][
1
]
=
v
}
bvs
end
end
def
initialize
(
block
=
Proc
.
new
)
@mutex
=
Mutex
.
new
@relation
=
nil
@sql
=
nil
@binds
=
nil
@block
=
block
@params
=
Params
.
new
end
def
execute
(
*
vals
)
rel
=
relation
vals
@mutex
.
synchronize
do
rel
.
set_binds
vals
rel
.
to_a
end
def
execute
(
params
)
rel
=
relation
@params
arel
=
rel
.
arel
klass
=
rel
.
klass
bv
=
binds
rel
klass
.
find_by_sql
sql
(
klass
,
arel
,
bv
),
bv
.
bind
(
params
)
end
alias
:call
:execute
private
def
relation
(
values
)
@relation
||
@mutex
.
synchronize
{
@block
.
call
(
*
values
)
def
binds
(
rel
)
@binds
||
@mutex
.
synchronize
{
@binds
||=
BindMap
.
new
rel
.
bind_values
}
end
def
sql
(
klass
,
arel
,
bv
)
@sql
||
@mutex
.
synchronize
{
@sql
||=
klass
.
connection
.
to_sql
arel
,
bv
}
end
def
relation
(
values
)
@relation
||
@mutex
.
synchronize
{
@relation
||=
@block
.
call
(
values
)
}
end
end
end
activerecord/test/cases/statement_cache_test.rb
浏览文件 @
f3e379f0
...
...
@@ -7,6 +7,7 @@
module
ActiveRecord
class
StatementCacheTest
<
ActiveRecord
::
TestCase
def
setup
skip
if
current_adapter?
(
:Mysql2Adapter
)
@connection
=
ActiveRecord
::
Base
.
connection
end
...
...
@@ -15,13 +16,13 @@ def test_statement_cache
Book
.
create
(
name:
"my book"
)
Book
.
create
(
name:
"my other book"
)
cache
=
StatementCache
.
new
do
|
name
|
Book
.
where
(
:name
=>
name
)
cache
=
StatementCache
.
new
do
|
params
|
Book
.
where
(
:name
=>
params
[
:name
]
)
end
b
=
cache
.
execute
"my book"
b
=
cache
.
execute
name:
"my book"
assert_equal
"my book"
,
b
[
0
].
name
b
=
cache
.
execute
"my other book"
b
=
cache
.
execute
name:
"my other book"
assert_equal
"my other book"
,
b
[
0
].
name
end
...
...
@@ -30,13 +31,13 @@ def test_statement_cache_id
b1
=
Book
.
create
(
name:
"my book"
)
b2
=
Book
.
create
(
name:
"my other book"
)
cache
=
StatementCache
.
new
do
|
id
|
Book
.
where
(
id:
id
)
cache
=
StatementCache
.
new
do
|
params
|
Book
.
where
(
id:
params
[
:id
]
)
end
b
=
cache
.
execute
b1
.
id
b
=
cache
.
execute
id:
b1
.
id
assert_equal
b1
.
name
,
b
[
0
].
name
b
=
cache
.
execute
b2
.
id
b
=
cache
.
execute
id:
b2
.
id
assert_equal
b2
.
name
,
b
[
0
].
name
end
...
...
@@ -53,18 +54,18 @@ def test_find_or_create_by
#End
def
test_statement_cache_with_simple_statement
cache
=
ActiveRecord
::
StatementCache
.
new
do
cache
=
ActiveRecord
::
StatementCache
.
new
do
|
params
|
Book
.
where
(
name:
"my book"
).
where
(
"author_id > 3"
)
end
Book
.
create
(
name:
"my book"
,
author_id:
4
)
books
=
cache
.
execute
books
=
cache
.
execute
({})
assert_equal
"my book"
,
books
[
0
].
name
end
def
test_statement_cache_with_complex_statement
cache
=
ActiveRecord
::
StatementCache
.
new
do
cache
=
ActiveRecord
::
StatementCache
.
new
do
|
params
|
Liquid
.
joins
(
:molecules
=>
:electrons
).
where
(
'molecules.name'
=>
'dioxane'
,
'electrons.name'
=>
'lepton'
)
end
...
...
@@ -72,12 +73,12 @@ def test_statement_cache_with_complex_statement
molecule
=
salty
.
molecules
.
create
(
name:
'dioxane'
)
molecule
.
electrons
.
create
(
name:
'lepton'
)
liquids
=
cache
.
execute
liquids
=
cache
.
execute
({})
assert_equal
"salty"
,
liquids
[
0
].
name
end
def
test_statement_cache_values_differ
cache
=
ActiveRecord
::
StatementCache
.
new
do
cache
=
ActiveRecord
::
StatementCache
.
new
do
|
params
|
Book
.
where
(
name:
"my book"
)
end
...
...
@@ -85,13 +86,13 @@ def test_statement_cache_values_differ
Book
.
create
(
name:
"my book"
)
end
first_books
=
cache
.
execute
first_books
=
cache
.
execute
({})
3
.
times
do
Book
.
create
(
name:
"my book"
)
end
additional_books
=
cache
.
execute
additional_books
=
cache
.
execute
({})
assert
first_books
!=
additional_books
end
end
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录