Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
张重言
rails
提交
bd2f5c06
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 搜索 >>
提交
bd2f5c06
编写于
11月 19, 2011
作者:
A
Aaron Patterson
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
pushing caching and visitors down to the connection
上级
4cdd44e3
变更
13
隐藏空白更改
内联
并排
Showing
13 changed file
with
181 addition
and
213 deletion
+181
-213
activerecord/lib/active_record/base.rb
activerecord/lib/active_record/base.rb
+9
-9
activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb
...ve_record/connection_adapters/abstract/connection_pool.rb
+31
-77
activerecord/lib/active_record/connection_adapters/abstract_adapter.rb
...lib/active_record/connection_adapters/abstract_adapter.rb
+3
-0
activerecord/lib/active_record/connection_adapters/schema_cache.rb
...ord/lib/active_record/connection_adapters/schema_cache.rb
+72
-0
activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb
...d/lib/active_record/connection_adapters/sqlite_adapter.rb
+1
-4
activerecord/lib/active_record/relation/predicate_builder.rb
activerecord/lib/active_record/relation/predicate_builder.rb
+1
-1
activerecord/lib/active_record/session_store.rb
activerecord/lib/active_record/session_store.rb
+2
-2
activerecord/test/active_record/connection_adapters/fake_adapter.rb
...rd/test/active_record/connection_adapters/fake_adapter.rb
+6
-1
activerecord/test/cases/adapter_test.rb
activerecord/test/cases/adapter_test.rb
+0
-10
activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb
...ecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb
+1
-0
activerecord/test/cases/connection_adapters/schema_cache_test.rb
...ecord/test/cases/connection_adapters/schema_cache_test.rb
+55
-0
activerecord/test/cases/connection_pool_test.rb
activerecord/test/cases/connection_pool_test.rb
+0
-37
activerecord/test/cases/pooled_connections_test.rb
activerecord/test/cases/pooled_connections_test.rb
+0
-72
未找到文件。
activerecord/lib/active_record/base.rb
浏览文件 @
bd2f5c06
...
...
@@ -710,21 +710,21 @@ def table_exists?
# Returns an array of column objects for the table associated with this class.
def
columns
if
defined?
(
@primary_key
)
connection
_pool
.
primary_keys
[
table_name
]
||=
primary_key
connection
.
schema_cache
.
primary_keys
[
table_name
]
||=
primary_key
end
connection
_pool
.
columns
[
table_name
]
connection
.
schema_cache
.
columns
[
table_name
]
end
# Returns a hash of column objects for the table associated with this class.
def
columns_hash
connection
_pool
.
columns_hash
[
table_name
]
connection
.
schema_cache
.
columns_hash
[
table_name
]
end
# Returns a hash where the keys are column names and the values are
# default values when instantiating the AR object for this table.
def
column_defaults
connection
_pool
.
column_defaults
[
table_name
]
connection
.
schema_cache
.
column_defaults
[
table_name
]
end
# Returns an array of column names as strings.
...
...
@@ -781,14 +781,14 @@ def column_methods_hash #:nodoc:
def
reset_column_information
connection
.
clear_cache!
undefine_attribute_methods
connection
_pool
.
clear_table_cache!
(
table_name
)
if
table_exists?
connection
.
schema_cache
.
clear_table_cache!
(
table_name
)
if
table_exists?
@column_names
=
@content_columns
=
@dynamic_methods_hash
=
@inheritance_column
=
nil
@arel_engine
=
@relation
=
nil
end
def
clear_cache!
# :nodoc:
connection
_pool
.
clear_cache
!
connection
.
schema_cache
.
clear
!
end
def
attribute_method?
(
attribute
)
...
...
@@ -1356,9 +1356,9 @@ def sanitize_sql_for_conditions(condition, table_name = self.table_name)
return
nil
if
condition
.
blank?
case
condition
when
Array
;
sanitize_sql_array
(
condition
)
when
Hash
;
sanitize_sql_hash_for_conditions
(
condition
,
table_name
)
else
condition
when
Array
;
sanitize_sql_array
(
condition
)
when
Hash
;
sanitize_sql_hash_for_conditions
(
condition
,
table_name
)
else
condition
end
end
alias_method
:sanitize_sql
,
:sanitize_sql_for_conditions
...
...
activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb
浏览文件 @
bd2f5c06
...
...
@@ -2,6 +2,7 @@
require
'monitor'
require
'set'
require
'active_support/core_ext/module/synchronization'
require
'active_support/core_ext/module/deprecation'
module
ActiveRecord
# Raised when a connection could not be obtained within the connection
...
...
@@ -59,8 +60,6 @@ module ConnectionAdapters
class
ConnectionPool
attr_accessor
:automatic_reconnect
attr_reader
:spec
,
:connections
attr_reader
:columns
,
:columns_hash
,
:primary_keys
,
:tables
attr_reader
:column_defaults
# Creates a new ConnectionPool object. +spec+ is a ConnectionSpecification
# object which describes database connection information (e.g. adapter,
...
...
@@ -85,72 +84,7 @@ def initialize(spec)
@connections
=
[]
@checked_out
=
[]
@automatic_reconnect
=
true
@tables
=
{}
@visitor
=
nil
@columns
=
Hash
.
new
do
|
h
,
table_name
|
h
[
table_name
]
=
with_connection
do
|
conn
|
# Fetch a list of columns
conn
.
columns
(
table_name
,
"
#{
table_name
}
Columns"
).
tap
do
|
columns
|
# set primary key information
columns
.
each
do
|
column
|
column
.
primary
=
column
.
name
==
primary_keys
[
table_name
]
end
end
end
end
@columns_hash
=
Hash
.
new
do
|
h
,
table_name
|
h
[
table_name
]
=
Hash
[
columns
[
table_name
].
map
{
|
col
|
[
col
.
name
,
col
]
}]
end
@column_defaults
=
Hash
.
new
do
|
h
,
table_name
|
h
[
table_name
]
=
Hash
[
columns
[
table_name
].
map
{
|
col
|
[
col
.
name
,
col
.
default
]
}]
end
@primary_keys
=
Hash
.
new
do
|
h
,
table_name
|
h
[
table_name
]
=
with_connection
do
|
conn
|
table_exists?
(
table_name
)
?
conn
.
primary_key
(
table_name
)
:
'id'
end
end
end
# A cached lookup for table existence.
def
table_exists?
(
name
)
return
@tables
[
name
]
if
@tables
.
key?
name
with_connection
do
|
conn
|
conn
.
tables
.
each
{
|
table
|
@tables
[
table
]
=
true
}
@tables
[
name
]
=
conn
.
table_exists?
(
name
)
if
!
@tables
.
key?
(
name
)
end
@tables
[
name
]
end
# Clears out internal caches:
#
# * columns
# * columns_hash
# * tables
def
clear_cache!
@columns
.
clear
@columns_hash
.
clear
@column_defaults
.
clear
@tables
.
clear
end
# Clear out internal caches for table with +table_name+.
def
clear_table_cache!
(
table_name
)
@columns
.
delete
table_name
@columns_hash
.
delete
table_name
@column_defaults
.
delete
table_name
@primary_keys
.
delete
table_name
end
# Retrieve the connection associated with the current thread, or call
...
...
@@ -227,6 +161,35 @@ def verify_active_connections! #:nodoc:
end
end
def
columns
with_connection
do
|
c
|
c
.
schema_cache
.
columns
end
end
deprecate
:columns
def
columns_hash
with_connection
do
|
c
|
c
.
schema_cache
.
columns_hash
end
end
deprecate
:columns_hash
def
primary_keys
raise
with_connection
do
|
c
|
c
.
schema_cache
.
primary_keys
end
end
deprecate
:primary_keys
def
clear_cache!
with_connection
do
|
c
|
c
.
schema_cache
.
clear!
end
end
deprecate
:clear_cache!
# Return any checked-out connections back to the pool by threads that
# are no longer alive.
def
clear_stale_cached_connections!
...
...
@@ -301,16 +264,7 @@ def checkin(conn)
private
def
new_connection
connection
=
ActiveRecord
::
Base
.
send
(
spec
.
adapter_method
,
spec
.
config
)
# TODO: This is a bit icky, and in the long term we may want to change the method
# signature for connections. Also, if we switch to have one visitor per
# connection (and therefore per thread), we can get rid of the thread-local
# variable in Arel::Visitors::ToSql.
@visitor
||=
connection
.
class
.
visitor_for
(
self
)
connection
.
visitor
=
@visitor
connection
ActiveRecord
::
Base
.
send
(
spec
.
adapter_method
,
spec
.
config
)
end
def
current_connection_id
#:nodoc:
...
...
activerecord/lib/active_record/connection_adapters/abstract_adapter.rb
浏览文件 @
bd2f5c06
...
...
@@ -3,6 +3,7 @@
require
'bigdecimal/util'
require
'active_support/core_ext/benchmark'
require
'active_support/deprecation'
require
'active_record/connection_adapters/schema_cache'
module
ActiveRecord
module
ConnectionAdapters
# :nodoc:
...
...
@@ -51,6 +52,7 @@ class AbstractAdapter
define_callbacks
:checkout
,
:checkin
attr_accessor
:visitor
attr_reader
:schema_cache
def
initialize
(
connection
,
logger
=
nil
)
#:nodoc:
@active
=
nil
...
...
@@ -60,6 +62,7 @@ def initialize(connection, logger = nil) #:nodoc:
@open_transactions
=
0
@instrumenter
=
ActiveSupport
::
Notifications
.
instrumenter
@visitor
=
nil
@schema_cache
=
SchemaCache
.
new
self
end
# Returns a visitor instance for this adaptor, which conforms to the Arel::ToSql interface
...
...
activerecord/lib/active_record/connection_adapters/schema_cache.rb
0 → 100644
浏览文件 @
bd2f5c06
module
ActiveRecord
module
ConnectionAdapters
class
SchemaCache
attr_reader
:columns
,
:columns_hash
,
:primary_keys
,
:tables
attr_reader
:column_defaults
attr_reader
:connection
def
initialize
(
conn
)
@connection
=
conn
@tables
=
{}
@columns
=
Hash
.
new
do
|
h
,
table_name
|
h
[
table_name
]
=
# Fetch a list of columns
conn
.
columns
(
table_name
,
"
#{
table_name
}
Columns"
).
tap
do
|
cs
|
# set primary key information
cs
.
each
do
|
column
|
column
.
primary
=
column
.
name
==
primary_keys
[
table_name
]
end
end
end
@columns_hash
=
Hash
.
new
do
|
h
,
table_name
|
h
[
table_name
]
=
Hash
[
columns
[
table_name
].
map
{
|
col
|
[
col
.
name
,
col
]
}]
end
@column_defaults
=
Hash
.
new
do
|
h
,
table_name
|
h
[
table_name
]
=
Hash
[
columns
[
table_name
].
map
{
|
col
|
[
col
.
name
,
col
.
default
]
}]
end
@primary_keys
=
Hash
.
new
do
|
h
,
table_name
|
h
[
table_name
]
=
table_exists?
(
table_name
)
?
conn
.
primary_key
(
table_name
)
:
'id'
end
end
# A cached lookup for table existence.
def
table_exists?
(
name
)
return
@tables
[
name
]
if
@tables
.
key?
name
connection
.
tables
.
each
{
|
table
|
@tables
[
table
]
=
true
}
@tables
[
name
]
=
connection
.
table_exists?
(
name
)
if
!
@tables
.
key?
(
name
)
@tables
[
name
]
end
# Clears out internal caches:
#
# * columns
# * columns_hash
# * tables
def
clear!
@columns
.
clear
@columns_hash
.
clear
@column_defaults
.
clear
@tables
.
clear
end
# Clear out internal caches for table with +table_name+.
def
clear_table_cache!
(
table_name
)
@columns
.
delete
table_name
@columns_hash
.
delete
table_name
@column_defaults
.
delete
table_name
@primary_keys
.
delete
table_name
end
end
end
end
activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb
浏览文件 @
bd2f5c06
...
...
@@ -89,10 +89,7 @@ def initialize(connection, logger, config)
@statements
=
StatementPool
.
new
(
@connection
,
config
.
fetch
(
:statement_limit
)
{
1000
})
@config
=
config
end
def
self
.
visitor_for
(
pool
)
# :nodoc:
Arel
::
Visitors
::
SQLite
.
new
(
pool
)
@visitor
=
Arel
::
Visitors
::
SQLite
.
new
self
end
def
adapter_name
#:nodoc:
...
...
activerecord/lib/active_record/relation/predicate_builder.rb
浏览文件 @
bd2f5c06
...
...
@@ -23,7 +23,7 @@ def self.build_from_hash(engine, attributes, default_table)
attribute
.
in
(
value
.
arel
.
ast
)
when
Array
,
ActiveRecord
::
Associations
::
CollectionProxy
values
=
value
.
to_a
.
map
{
|
x
|
x
.
is_a?
(
ActiveRecord
::
Base
)
?
x
.
id
:
x
}
ranges
,
values
=
values
.
partition
{
|
v
alue
|
value
.
is_a?
(
Range
)
||
value
.
is_a?
(
Arel
::
Relation
)}
ranges
,
values
=
values
.
partition
{
|
v
|
v
.
is_a?
(
Range
)
||
v
.
is_a?
(
Arel
::
Relation
)}
array_predicates
=
ranges
.
map
{
|
range
|
attribute
.
in
(
range
)}
...
...
activerecord/lib/active_record/session_store.rb
浏览文件 @
bd2f5c06
...
...
@@ -59,12 +59,12 @@ def unmarshal(data)
end
def
drop_table!
connection
_pool
.
clear_table_cache!
(
table_name
)
connection
.
schema_cache
.
clear_table_cache!
(
table_name
)
connection
.
drop_table
table_name
end
def
create_table!
connection
_pool
.
clear_table_cache!
(
table_name
)
connection
.
schema_cache
.
clear_table_cache!
(
table_name
)
connection
.
create_table
(
table_name
)
do
|
t
|
t
.
string
session_id_column
,
:limit
=>
255
t
.
text
data_column_name
...
...
activerecord/test/active_record/connection_adapters/fake_adapter.rb
浏览文件 @
bd2f5c06
...
...
@@ -9,11 +9,16 @@ module ConnectionAdapters
class
FakeAdapter
<
AbstractAdapter
attr_accessor
:tables
,
:primary_keys
@columns
=
Hash
.
new
{
|
h
,
k
|
h
[
k
]
=
[]
}
class
<<
self
attr_reader
:columns
end
def
initialize
(
connection
,
logger
)
super
@tables
=
[]
@primary_keys
=
{}
@columns
=
Hash
.
new
{
|
h
,
k
|
h
[
k
]
=
[]
}
@columns
=
self
.
class
.
columns
end
def
primary_key
(
table
)
...
...
activerecord/test/cases/adapter_test.rb
浏览文件 @
bd2f5c06
...
...
@@ -157,14 +157,4 @@ def test_disable_referential_integrity
end
end
end
def
test_deprecated_visitor_for
visitor_klass
=
Class
.
new
(
Arel
::
Visitors
::
ToSql
)
Arel
::
Visitors
::
VISITORS
[
'fuuu'
]
=
visitor_klass
pool
=
stub
(
:spec
=>
stub
(
:config
=>
{
:adapter
=>
'fuuu'
}))
visitor
=
assert_deprecated
{
ActiveRecord
::
ConnectionAdapters
::
AbstractAdapter
.
visitor_for
(
pool
)
}
assert
visitor
.
is_a?
(
visitor_klass
)
end
end
activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb
浏览文件 @
bd2f5c06
...
...
@@ -158,6 +158,7 @@ def test_quote_binary_column_escapes_it
binary
.
save!
assert_equal
str
,
binary
.
data
ensure
DualEncoding
.
connection
.
drop_table
(
'dual_encodings'
)
end
...
...
activerecord/test/cases/connection_adapters/schema_cache_test.rb
0 → 100644
浏览文件 @
bd2f5c06
require
"cases/helper"
module
ActiveRecord
module
ConnectionAdapters
class
SchemaCacheTest
<
ActiveRecord
::
TestCase
def
setup
connection
=
ActiveRecord
::
Base
.
connection
@cache
=
SchemaCache
.
new
connection
if
in_memory_db?
connection
.
create_table
:posts
do
|
t
|
t
.
integer
:cololumn
end
end
end
def
test_primary_key
assert_equal
'id'
,
@cache
.
primary_keys
[
'posts'
]
end
def
test_primary_key_for_non_existent_table
assert_equal
'id'
,
@cache
.
primary_keys
[
'omgponies'
]
end
def
test_primary_key_is_set_on_columns
posts_columns
=
@cache
.
columns_hash
[
'posts'
]
assert
posts_columns
[
'id'
].
primary
(
posts_columns
.
keys
-
[
'id'
]).
each
do
|
key
|
assert
!
posts_columns
[
key
].
primary
end
end
def
test_caches_columns
columns
=
@cache
.
columns
[
'posts'
]
assert_equal
columns
,
@cache
.
columns
[
'posts'
]
end
def
test_caches_columns_hash
columns_hash
=
@cache
.
columns_hash
[
'posts'
]
assert_equal
columns_hash
,
@cache
.
columns_hash
[
'posts'
]
end
def
test_clearing_column_cache
@cache
.
columns
[
'posts'
]
@cache
.
columns_hash
[
'posts'
]
@cache
.
clear!
assert_equal
0
,
@cache
.
columns
.
size
assert_equal
0
,
@cache
.
columns_hash
.
size
end
end
end
end
activerecord/test/cases/connection_pool_test.rb
浏览文件 @
bd2f5c06
...
...
@@ -26,43 +26,6 @@ def test_active_connection?
assert
!
@pool
.
active_connection?
end
def
test_pool_caches_columns
columns
=
@pool
.
columns
[
'posts'
]
assert_equal
columns
,
@pool
.
columns
[
'posts'
]
end
def
test_pool_caches_columns_hash
columns_hash
=
@pool
.
columns_hash
[
'posts'
]
assert_equal
columns_hash
,
@pool
.
columns_hash
[
'posts'
]
end
def
test_clearing_column_cache
@pool
.
columns
[
'posts'
]
@pool
.
columns_hash
[
'posts'
]
@pool
.
clear_cache!
assert_equal
0
,
@pool
.
columns
.
size
assert_equal
0
,
@pool
.
columns_hash
.
size
end
def
test_primary_key
assert_equal
'id'
,
@pool
.
primary_keys
[
'posts'
]
end
def
test_primary_key_for_non_existent_table
assert_equal
'id'
,
@pool
.
primary_keys
[
'omgponies'
]
end
def
test_primary_key_is_set_on_columns
posts_columns
=
@pool
.
columns_hash
[
'posts'
]
assert
posts_columns
[
'id'
].
primary
(
posts_columns
.
keys
-
[
'id'
]).
each
do
|
key
|
assert
!
posts_columns
[
key
].
primary
end
end
def
test_clear_stale_cached_connections!
pool
=
ConnectionPool
.
new
ActiveRecord
::
Base
.
connection_pool
.
spec
...
...
activerecord/test/cases/pooled_connections_test.rb
浏览文件 @
bd2f5c06
...
...
@@ -66,78 +66,6 @@ def test_pooled_connection_checkin_one
assert_equal
1
,
ActiveRecord
::
Base
.
connection_pool
.
connections
.
size
end
def
test_pooled_connection_checkin_two
checkout_checkin_connections
2
,
3
assert_equal
3
,
@connection_count
assert_equal
0
,
@timed_out
assert_equal
1
,
ActiveRecord
::
Base
.
connection_pool
.
connections
.
size
end
def
test_pooled_connection_checkout_existing_first
ActiveRecord
::
Base
.
establish_connection
(
@connection
.
merge
({
:pool
=>
1
}))
conn_pool
=
ActiveRecord
::
Base
.
connection_pool
conn
=
conn_pool
.
checkout
conn_pool
.
checkin
(
conn
)
conn
=
conn_pool
.
checkout
assert
ActiveRecord
::
ConnectionAdapters
::
AbstractAdapter
===
conn
conn_pool
.
checkin
(
conn
)
end
def
test_not_connected_defined_connection_returns_false
ActiveRecord
::
Base
.
establish_connection
(
@connection
)
assert
!
ActiveRecord
::
Base
.
connected?
end
def
test_undefined_connection_returns_false
old_handler
=
ActiveRecord
::
Base
.
connection_handler
ActiveRecord
::
Base
.
connection_handler
=
ActiveRecord
::
ConnectionAdapters
::
ConnectionHandler
.
new
assert
!
ActiveRecord
::
Base
.
connected?
ensure
ActiveRecord
::
Base
.
connection_handler
=
old_handler
end
def
test_connection_config
ActiveRecord
::
Base
.
establish_connection
(
@connection
)
assert_equal
@connection
,
ActiveRecord
::
Base
.
connection_config
end
def
test_with_connection_nesting_safety
ActiveRecord
::
Base
.
establish_connection
(
@connection
.
merge
({
:pool
=>
1
,
:wait_timeout
=>
0.1
}))
before_count
=
Project
.
count
add_record
(
'one'
)
ActiveRecord
::
Base
.
connection
.
transaction
do
add_record
(
'two'
)
# Have another thread try to screw up the transaction
Thread
.
new
do
ActiveRecord
::
Base
.
connection
.
rollback_db_transaction
ActiveRecord
::
Base
.
connection_pool
.
release_connection
end
add_record
(
'three'
)
end
after_count
=
Project
.
count
assert_equal
3
,
after_count
-
before_count
end
def
test_connection_pool_callbacks
checked_out
,
checked_in
=
false
,
false
ActiveRecord
::
ConnectionAdapters
::
AbstractAdapter
.
class_eval
do
set_callback
(
:checkout
,
:after
)
{
checked_out
=
true
}
set_callback
(
:checkin
,
:before
)
{
checked_in
=
true
}
end
@per_test_teardown
<<
proc
do
ActiveRecord
::
ConnectionAdapters
::
AbstractAdapter
.
class_eval
do
reset_callbacks
:checkout
reset_callbacks
:checkin
end
end
checkout_checkin_connections
1
,
1
assert
checked_out
assert
checked_in
end
private
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录