connection_manager 1.0.4 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/CHANGE.md +12 -1
- data/README.md +99 -82
- data/connection_manager.gemspec +7 -11
- data/lib/connection_manager/builder.rb +56 -0
- data/lib/connection_manager/connection_adapters/abstract_adapter.rb +50 -0
- data/lib/connection_manager/connection_adapters/mysql_adapter.rb +39 -0
- data/lib/connection_manager/connection_handling.rb +91 -0
- data/lib/connection_manager/core.rb +24 -0
- data/lib/connection_manager/querying.rb +13 -0
- data/lib/connection_manager/railtie.rb +10 -0
- data/lib/connection_manager/relation.rb +21 -0
- data/lib/connection_manager/replication.rb +56 -85
- data/lib/connection_manager/shards.rb +2 -1
- data/lib/connection_manager/using.rb +30 -24
- data/lib/connection_manager/version.rb +1 -1
- data/lib/connection_manager.rb +26 -16
- data/spec/{mysql2_database.yml → database.yml} +30 -26
- data/spec/factories.rb +1 -1
- data/spec/helpers/database_spec_helper.rb +91 -62
- data/spec/helpers/models_spec_helper.rb +23 -12
- data/spec/lib/builder_spec.rb +31 -0
- data/spec/lib/connection_adapters/abstract_adapter_spec.rb +48 -0
- data/spec/lib/connection_adapters/mysql_adapter_spec.rb +13 -0
- data/spec/lib/connection_handling_spec.rb +65 -0
- data/spec/lib/core_spec.rb +10 -0
- data/spec/lib/integration/cross_schema_spec.rb +35 -0
- data/spec/lib/querying_spec.rb +19 -0
- data/spec/lib/relation_spec.rb +21 -0
- data/spec/lib/replication_spec.rb +19 -57
- data/spec/lib/shards_spec.rb +3 -3
- data/spec/lib/using_proxy_spec.rb +27 -0
- data/spec/lib/using_spec.rb +28 -15
- data/spec/spec_helper.rb +2 -10
- metadata +73 -35
- data/lib/connection_manager/connection_builder.rb +0 -82
- data/lib/connection_manager/connection_manager_railtie.rb +0 -8
- data/lib/connection_manager/helpers/abstract_adapter_helper.rb +0 -95
- data/lib/connection_manager/helpers/connection_helpers.rb +0 -119
- data/lib/connection_manager/patches/cross_schema_patch.rb +0 -67
- data/spec/jdbcmysql_database.yml +0 -50
- data/spec/lib/connection_builder_spec.rb +0 -28
- data/spec/lib/connection_helpers_spec.rb +0 -79
- data/spec/lib/patches/cross_schema_path_spec.rb +0 -74
- data/spec/sqlite_database.yml +0 -26
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: connection_manager
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Joshua Mckinney
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-06-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -31,19 +31,53 @@ dependencies:
|
|
31
31
|
- !ruby/object:Gem::Version
|
32
32
|
version: '4.1'
|
33
33
|
- !ruby/object:Gem::Dependency
|
34
|
-
name:
|
34
|
+
name: activesupport
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - ! '>='
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '3.0'
|
40
|
+
- - <=
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: '4.1'
|
43
|
+
type: :runtime
|
44
|
+
prerelease: false
|
45
|
+
version_requirements: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - ! '>='
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: '3.0'
|
50
|
+
- - <=
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: '4.1'
|
53
|
+
- !ruby/object:Gem::Dependency
|
54
|
+
name: thread_safe
|
35
55
|
requirement: !ruby/object:Gem::Requirement
|
36
56
|
requirements:
|
37
57
|
- - ! '>='
|
38
58
|
- !ruby/object:Gem::Version
|
39
59
|
version: '0'
|
40
|
-
type: :
|
60
|
+
type: :runtime
|
41
61
|
prerelease: false
|
42
62
|
version_requirements: !ruby/object:Gem::Requirement
|
43
63
|
requirements:
|
44
64
|
- - ! '>='
|
45
65
|
- !ruby/object:Gem::Version
|
46
66
|
version: '0'
|
67
|
+
- !ruby/object:Gem::Dependency
|
68
|
+
name: rspec
|
69
|
+
requirement: !ruby/object:Gem::Requirement
|
70
|
+
requirements:
|
71
|
+
- - ~>
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: '2.0'
|
74
|
+
type: :development
|
75
|
+
prerelease: false
|
76
|
+
version_requirements: !ruby/object:Gem::Requirement
|
77
|
+
requirements:
|
78
|
+
- - ~>
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
version: '2.0'
|
47
81
|
- !ruby/object:Gem::Dependency
|
48
82
|
name: autotest
|
49
83
|
requirement: !ruby/object:Gem::Requirement
|
@@ -87,27 +121,21 @@ dependencies:
|
|
87
121
|
- !ruby/object:Gem::Version
|
88
122
|
version: '0'
|
89
123
|
- !ruby/object:Gem::Dependency
|
90
|
-
name:
|
124
|
+
name: mysql2
|
91
125
|
requirement: !ruby/object:Gem::Requirement
|
92
126
|
requirements:
|
93
127
|
- - ! '>='
|
94
128
|
- !ruby/object:Gem::Version
|
95
|
-
version: '
|
96
|
-
- - <=
|
97
|
-
- !ruby/object:Gem::Version
|
98
|
-
version: '4.1'
|
129
|
+
version: '0'
|
99
130
|
type: :development
|
100
131
|
prerelease: false
|
101
132
|
version_requirements: !ruby/object:Gem::Requirement
|
102
133
|
requirements:
|
103
134
|
- - ! '>='
|
104
135
|
- !ruby/object:Gem::Version
|
105
|
-
version: '
|
106
|
-
- - <=
|
107
|
-
- !ruby/object:Gem::Version
|
108
|
-
version: '4.1'
|
136
|
+
version: '0'
|
109
137
|
- !ruby/object:Gem::Dependency
|
110
|
-
name:
|
138
|
+
name: pg
|
111
139
|
requirement: !ruby/object:Gem::Requirement
|
112
140
|
requirements:
|
113
141
|
- - ! '>='
|
@@ -120,8 +148,8 @@ dependencies:
|
|
120
148
|
- - ! '>='
|
121
149
|
- !ruby/object:Gem::Version
|
122
150
|
version: '0'
|
123
|
-
description:
|
124
|
-
|
151
|
+
description: Improves support for cross-schema, replication and mutli-DMS applications
|
152
|
+
using ActiveRecord.
|
125
153
|
email:
|
126
154
|
- joshmckin@gmail.com
|
127
155
|
executables: []
|
@@ -137,29 +165,36 @@ files:
|
|
137
165
|
- Rakefile
|
138
166
|
- connection_manager.gemspec
|
139
167
|
- lib/connection_manager.rb
|
140
|
-
- lib/connection_manager/
|
141
|
-
- lib/connection_manager/
|
142
|
-
- lib/connection_manager/
|
143
|
-
- lib/connection_manager/
|
144
|
-
- lib/connection_manager/
|
168
|
+
- lib/connection_manager/builder.rb
|
169
|
+
- lib/connection_manager/connection_adapters/abstract_adapter.rb
|
170
|
+
- lib/connection_manager/connection_adapters/mysql_adapter.rb
|
171
|
+
- lib/connection_manager/connection_handling.rb
|
172
|
+
- lib/connection_manager/core.rb
|
173
|
+
- lib/connection_manager/querying.rb
|
174
|
+
- lib/connection_manager/railtie.rb
|
175
|
+
- lib/connection_manager/relation.rb
|
145
176
|
- lib/connection_manager/replication.rb
|
146
177
|
- lib/connection_manager/shards.rb
|
147
178
|
- lib/connection_manager/using.rb
|
148
179
|
- lib/connection_manager/version.rb
|
180
|
+
- spec/database.yml
|
149
181
|
- spec/factories.rb
|
150
182
|
- spec/helpers/database_spec_helper.rb
|
151
183
|
- spec/helpers/models_spec_helper.rb
|
152
|
-
- spec/
|
153
|
-
- spec/lib/
|
154
|
-
- spec/lib/
|
155
|
-
- spec/lib/
|
184
|
+
- spec/lib/builder_spec.rb
|
185
|
+
- spec/lib/connection_adapters/abstract_adapter_spec.rb
|
186
|
+
- spec/lib/connection_adapters/mysql_adapter_spec.rb
|
187
|
+
- spec/lib/connection_handling_spec.rb
|
188
|
+
- spec/lib/core_spec.rb
|
189
|
+
- spec/lib/integration/cross_schema_spec.rb
|
190
|
+
- spec/lib/querying_spec.rb
|
191
|
+
- spec/lib/relation_spec.rb
|
156
192
|
- spec/lib/replication_spec.rb
|
157
193
|
- spec/lib/shards_spec.rb
|
194
|
+
- spec/lib/using_proxy_spec.rb
|
158
195
|
- spec/lib/using_spec.rb
|
159
|
-
- spec/mysql2_database.yml
|
160
196
|
- spec/spec.opts
|
161
197
|
- spec/spec_helper.rb
|
162
|
-
- spec/sqlite_database.yml
|
163
198
|
homepage: ''
|
164
199
|
licenses: []
|
165
200
|
metadata: {}
|
@@ -182,20 +217,23 @@ rubyforge_project: connection_manager
|
|
182
217
|
rubygems_version: 2.2.2
|
183
218
|
signing_key:
|
184
219
|
specification_version: 4
|
185
|
-
summary:
|
186
|
-
active_record
|
220
|
+
summary: Cross-schema, replication and mutli-DMS gem for ActiveRecord.
|
187
221
|
test_files:
|
222
|
+
- spec/database.yml
|
188
223
|
- spec/factories.rb
|
189
224
|
- spec/helpers/database_spec_helper.rb
|
190
225
|
- spec/helpers/models_spec_helper.rb
|
191
|
-
- spec/
|
192
|
-
- spec/lib/
|
193
|
-
- spec/lib/
|
194
|
-
- spec/lib/
|
226
|
+
- spec/lib/builder_spec.rb
|
227
|
+
- spec/lib/connection_adapters/abstract_adapter_spec.rb
|
228
|
+
- spec/lib/connection_adapters/mysql_adapter_spec.rb
|
229
|
+
- spec/lib/connection_handling_spec.rb
|
230
|
+
- spec/lib/core_spec.rb
|
231
|
+
- spec/lib/integration/cross_schema_spec.rb
|
232
|
+
- spec/lib/querying_spec.rb
|
233
|
+
- spec/lib/relation_spec.rb
|
195
234
|
- spec/lib/replication_spec.rb
|
196
235
|
- spec/lib/shards_spec.rb
|
236
|
+
- spec/lib/using_proxy_spec.rb
|
197
237
|
- spec/lib/using_spec.rb
|
198
|
-
- spec/mysql2_database.yml
|
199
238
|
- spec/spec.opts
|
200
239
|
- spec/spec_helper.rb
|
201
|
-
- spec/sqlite_database.yml
|
@@ -1,82 +0,0 @@
|
|
1
|
-
require 'active_support/core_ext/hash/indifferent_access'
|
2
|
-
module ConnectionManager
|
3
|
-
module ConnectionBuilder
|
4
|
-
|
5
|
-
# Get the current environment if defined
|
6
|
-
# Check for Rails, check for RACK_ENV, default to 'development'
|
7
|
-
def ar_env
|
8
|
-
return Rails.env if defined?(Rails)
|
9
|
-
return RACK_ENV if defined?(RACK_ENV)
|
10
|
-
return ENV["AR_ENV"] if ENV["AR_ENV"]
|
11
|
-
"development"
|
12
|
-
end
|
13
|
-
|
14
|
-
# Grab only those connections that correspond to the current env. If env
|
15
|
-
# is blank it grabs all the connection keys
|
16
|
-
#
|
17
|
-
# If you current environment valid database keys can be:
|
18
|
-
# * development
|
19
|
-
# * other_database_development
|
20
|
-
# * slave_database_development
|
21
|
-
def configuration_keys
|
22
|
-
ActiveRecord::Base.configurations.keys.select{|n| n.match(ar_env_regex)}
|
23
|
-
end
|
24
|
-
|
25
|
-
def database_yml_attributes(name_from_yml)
|
26
|
-
found = ActiveRecord::Base.configurations[name_from_yml]
|
27
|
-
ActiveRecord::Base.configurations[name_from_yml].symbolize_keys if found
|
28
|
-
end
|
29
|
-
|
30
|
-
# Returns currently loaded configurations where :build_connection is true
|
31
|
-
def database_keys_for_auto_build
|
32
|
-
ab_configs = []
|
33
|
-
configuration_keys.each do |key|
|
34
|
-
ab_configs << key if (database_yml_attributes(key)[:build_connection_class] == true)
|
35
|
-
end
|
36
|
-
ab_configs
|
37
|
-
end
|
38
|
-
|
39
|
-
# Builds connection classes using the database keys provided; expects an array.
|
40
|
-
def build_connection_classes(database_keys_to_use=database_keys_for_auto_build)
|
41
|
-
database_keys_to_use.each do |key|
|
42
|
-
build_connection_class(connection_class_name(key),key)
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
# Build connection classes base on the supplied class name and connection
|
47
|
-
# key from database.yml
|
48
|
-
def build_connection_class(class_name,connection_key)
|
49
|
-
begin
|
50
|
-
class_name.constantize
|
51
|
-
rescue NameError
|
52
|
-
klass = Class.new(ActiveRecord::Base)
|
53
|
-
new_connection_class = Object.const_set(class_name, klass)
|
54
|
-
new_connection_class.establish_managed_connection(connection_key)
|
55
|
-
new_connection_class.use_database(new_connection_class.current_database_name)
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
private
|
60
|
-
def ar_env_regex
|
61
|
-
return @ar_env_regex if @ar_env_regex
|
62
|
-
s = "#{ar_env}$"
|
63
|
-
@ar_env_regex = Regexp.new("(#{s})")
|
64
|
-
end
|
65
|
-
|
66
|
-
# Creates a string to be used for the class name. Removes the current env.
|
67
|
-
def clean_yml_key(name)
|
68
|
-
new_name = "#{name}".gsub(ar_env_regex,'')
|
69
|
-
new_name = "Base"if new_name.blank?
|
70
|
-
new_name.gsub(/\_$/,'')
|
71
|
-
end
|
72
|
-
|
73
|
-
# Given an connection key name from the database.yml, returns the string
|
74
|
-
# equivalent of the class name for that entry.
|
75
|
-
def connection_class_name(name_from_yml)
|
76
|
-
new_class_name = clean_yml_key(name_from_yml)
|
77
|
-
new_class_name = new_class_name.gsub(/\_/,' ').titleize.gsub(/ /,'')
|
78
|
-
new_class_name << "Connection"
|
79
|
-
new_class_name
|
80
|
-
end
|
81
|
-
end
|
82
|
-
end
|
@@ -1,95 +0,0 @@
|
|
1
|
-
module ConnectionManager
|
2
|
-
module AbstractAdapterHelper
|
3
|
-
def config
|
4
|
-
@config
|
5
|
-
end
|
6
|
-
|
7
|
-
# Determines if connection supports cross database queries
|
8
|
-
def cross_database_support?
|
9
|
-
@cross_database_support ||= (@config[:cross_database_support] || @config[:adapter].match(/(mysql)|(postgres)|(sqlserver)/i))
|
10
|
-
end
|
11
|
-
alias :cross_schema_support? :cross_database_support?
|
12
|
-
|
13
|
-
def using_em_adapter?
|
14
|
-
(@config[:adapter].match(/^em\_/) && defined?(EM) && EM::reactor_running?)
|
15
|
-
end
|
16
|
-
|
17
|
-
def readonly?
|
18
|
-
(@config[:readonly] == true)
|
19
|
-
end
|
20
|
-
|
21
|
-
def replicated?
|
22
|
-
(!slave_keys.blank? || !master_keys.blank?)
|
23
|
-
end
|
24
|
-
|
25
|
-
def database_name
|
26
|
-
@config[:database]
|
27
|
-
end
|
28
|
-
|
29
|
-
def replication_keys(type=:slaves)
|
30
|
-
return slave_keys if type == :slaves
|
31
|
-
master_keys
|
32
|
-
end
|
33
|
-
|
34
|
-
def slave_keys
|
35
|
-
@slave_keys ||= (@config[:slaves] ? @config[:slaves].collect{|r| r.to_sym} : [] )
|
36
|
-
end
|
37
|
-
|
38
|
-
def master_keys
|
39
|
-
@master_keys ||= (@config[:masters] ? @config[:masters].collect{|r| r.to_sym} : [])
|
40
|
-
end
|
41
|
-
|
42
|
-
if ActiveRecord::VERSION::MAJOR == 3 && ActiveRecord::VERSION::MINOR <= 1
|
43
|
-
|
44
|
-
# Returns the schema for a give table. Returns nil of multiple matches are found
|
45
|
-
def fetch_table_schema(table_name)
|
46
|
-
return nil unless cross_database_support?
|
47
|
-
sql = "SELECT table_schema FROM INFORMATION_SCHEMA.TABLES WHERE table_name = '#{table_name}'"
|
48
|
-
results = execute(sql, 'SCHEMA')
|
49
|
-
found = results.to_a
|
50
|
-
return found[0][0] if (found.length == 1)
|
51
|
-
nil
|
52
|
-
end
|
53
|
-
|
54
|
-
# Returns table_schema.table_name for the given table. Returns nil if multiple matches are found
|
55
|
-
def fetch_full_table_name(table_name)
|
56
|
-
return nil unless cross_database_support?
|
57
|
-
return table_name if (table_name.to_s.match(/(^$)|(\.)/))
|
58
|
-
sql = "SELECT CONCAT(table_schema,'.',table_name) FROM INFORMATION_SCHEMA.TABLES WHERE table_name = '#{table_name}'"
|
59
|
-
found = nil
|
60
|
-
results = execute(sql, 'SCHEMA')
|
61
|
-
found = results.to_a
|
62
|
-
if (found.length == 1)
|
63
|
-
found = found[0][0]
|
64
|
-
else
|
65
|
-
found = table_name
|
66
|
-
end
|
67
|
-
found
|
68
|
-
end
|
69
|
-
else
|
70
|
-
|
71
|
-
# Returns the schema for a give table. Returns nil of multiple matches are found
|
72
|
-
def fetch_table_schema(table_name)
|
73
|
-
return nil unless cross_database_support?
|
74
|
-
sql = "SELECT table_schema FROM INFORMATION_SCHEMA.TABLES WHERE table_name = '#{table_name}'"
|
75
|
-
execute_and_free(sql, 'SCHEMA') do |result|
|
76
|
-
found = result.to_a
|
77
|
-
return nil unless (found.length == 1)
|
78
|
-
found[0][0]
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
# Returns table_schema.table_name for the given table. Returns nil if multiple matches are found
|
83
|
-
def fetch_full_table_name(table_name)
|
84
|
-
return nil unless cross_database_support?
|
85
|
-
return table_name if (table_name.to_s.match(/(^$)|(\.)/))
|
86
|
-
sql = "SELECT CONCAT(table_schema,'.',table_name) FROM INFORMATION_SCHEMA.TABLES WHERE table_name = '#{table_name}'"
|
87
|
-
execute_and_free(sql, 'SCHEMA') do |result|
|
88
|
-
found = result.to_a
|
89
|
-
return table_name unless (found.length == 1)
|
90
|
-
found[0][0]
|
91
|
-
end
|
92
|
-
end
|
93
|
-
end
|
94
|
-
end
|
95
|
-
end
|
@@ -1,119 +0,0 @@
|
|
1
|
-
require 'active_support/core_ext/hash/indifferent_access'
|
2
|
-
module ConnectionManager
|
3
|
-
module ConnectionHelpers
|
4
|
-
@@managed_connections = HashWithIndifferentAccess.new
|
5
|
-
|
6
|
-
# Returns the database_name of the connection unless set otherwise
|
7
|
-
def current_database_name
|
8
|
-
return "#{connection.config[:database].to_s}" if @current_database_name.blank?
|
9
|
-
@current_database_name
|
10
|
-
end
|
11
|
-
alias :database_name :current_database_name
|
12
|
-
alias :current_schema_name :current_database_name
|
13
|
-
alias :schema_name :current_database_name
|
14
|
-
|
15
|
-
|
16
|
-
# Sometimes we need to manually set the database name, like when the connection
|
17
|
-
# has a database but our table is in a different database/schema but on the
|
18
|
-
# same DMS.
|
19
|
-
def current_database_name=current_database_name
|
20
|
-
@current_database_name= current_database_name
|
21
|
-
end
|
22
|
-
alias :database_name= :current_database_name=
|
23
|
-
alias :current_schema_name= :current_database_name=
|
24
|
-
alias :schema_name= :current_database_name=
|
25
|
-
|
26
|
-
# Returns true if this is a readonly only a readonly model
|
27
|
-
# If the connection.readonly? then the model that uses the connection
|
28
|
-
# must be readonly.
|
29
|
-
def readonly?
|
30
|
-
((@readonly == true)||connection.readonly?)
|
31
|
-
end
|
32
|
-
|
33
|
-
# Allow setting of readonly at the model level
|
34
|
-
def readonly=readonly
|
35
|
-
@readonly = readonly
|
36
|
-
end
|
37
|
-
|
38
|
-
# A place to store managed connections
|
39
|
-
def managed_connections
|
40
|
-
@@managed_connections
|
41
|
-
end
|
42
|
-
|
43
|
-
def add_managed_connections(yml_key,value)
|
44
|
-
@@managed_connections[yml_key] ||= []
|
45
|
-
@@managed_connections[yml_key] << value unless @@managed_connections[yml_key].include?(value)
|
46
|
-
@@managed_connections
|
47
|
-
end
|
48
|
-
|
49
|
-
def managed_connection_classes
|
50
|
-
managed_connections.values.flatten
|
51
|
-
end
|
52
|
-
|
53
|
-
def yml_key
|
54
|
-
@yml_key
|
55
|
-
end
|
56
|
-
|
57
|
-
# Tell Active Record to use a different database/schema on this model.
|
58
|
-
# You may call #use_database when your schemas reside on the same database server
|
59
|
-
# and you do not want to create extra connection class and database.yml entries.
|
60
|
-
#
|
61
|
-
# Options:
|
62
|
-
# * :table_name_prefix - the prefix required for making cross database/schema
|
63
|
-
# joins for you database management system. By default table_name_prefix is the
|
64
|
-
# database/schema name followed by a period EX: "my_database."
|
65
|
-
# * :table_name - the table name for the model if it does not match ActiveRecord
|
66
|
-
# naming conventions
|
67
|
-
#
|
68
|
-
# EX: class LegacyUser < ActiveRecord::Base
|
69
|
-
# use_database('DBUser', :table_name => 'UserData')
|
70
|
-
# end
|
71
|
-
#
|
72
|
-
# LegacyUser.limit(1).to_sql => "SELECT * FROM `BDUser`.`UserData` LIMIT 1
|
73
|
-
#
|
74
|
-
def use_database(database_name=nil,opts={})
|
75
|
-
self.current_database_name = database_name if database_name
|
76
|
-
opts[:table_name_prefix] = "#{self.current_database_name}." if opts[:table_name_prefix].blank? && self.connection.cross_database_support?
|
77
|
-
unless self.abstract_class? || self.name == "ActiveRecord::Base"
|
78
|
-
opts[:table_name] = self.table_name if opts[:table_name].blank?
|
79
|
-
opts[:table_name].gsub!(self.table_name_prefix,'') unless self.table_name_prefix.blank?
|
80
|
-
self.table_name = "#{opts[:table_name_prefix]}#{opts[:table_name]}"
|
81
|
-
end
|
82
|
-
self.table_name_prefix = opts[:table_name_prefix] unless opts[:table_name_prefix].blank?
|
83
|
-
end
|
84
|
-
alias :use_schema :use_database
|
85
|
-
|
86
|
-
# Establishes and checks in a connection, normally for abstract classes AKA connection classes.
|
87
|
-
#
|
88
|
-
# Options:
|
89
|
-
# * :abstract_class - used the set #abstract_class, default is true
|
90
|
-
# * :readonly - force all instances to readonly
|
91
|
-
# * :class_name - name of connection class name, default is current class name
|
92
|
-
# * :table_name_prefix - prefix to append to table name for cross database joins,
|
93
|
-
# default is the "#{self.database_name}."
|
94
|
-
# EX:
|
95
|
-
# class MyConnection < ActiveRecord::Base
|
96
|
-
# establish_managed_connection :key_from_db_yml,{:readonly => true}
|
97
|
-
# end
|
98
|
-
#
|
99
|
-
def establish_managed_connection(yml_key,opts={})
|
100
|
-
@yml_key = yml_key
|
101
|
-
opts = {:class_name => self.name,
|
102
|
-
:abstract_class => true}.merge(opts)
|
103
|
-
establish_connection(yml_key)
|
104
|
-
self.abstract_class = opts[:abstract_class]
|
105
|
-
set_to_readonly if (readonly? || opts[:readonly] || self.connection.readonly?)
|
106
|
-
add_managed_connections(yml_key,opts[:class_name])
|
107
|
-
use_database(self.current_database_name,opts)
|
108
|
-
end
|
109
|
-
|
110
|
-
# Override ActiveRecord::Base instance method readonly? to force
|
111
|
-
# readonly connections.
|
112
|
-
def set_to_readonly
|
113
|
-
self.readonly = true
|
114
|
-
define_method(:readonly?) do
|
115
|
-
true
|
116
|
-
end
|
117
|
-
end
|
118
|
-
end
|
119
|
-
end
|
@@ -1,67 +0,0 @@
|
|
1
|
-
module ActiveRecord
|
2
|
-
class Base
|
3
|
-
class << self
|
4
|
-
# We want to make sure we get the full table name with schema
|
5
|
-
def arel_table # :nodoc:
|
6
|
-
begin
|
7
|
-
@arel_table ||= Arel::Table.new(quoted_table_name.to_s.gsub('`',''), arel_engine)
|
8
|
-
rescue ActiveRecord::ConnectionNotEstablished
|
9
|
-
Arel::Table.new(table_name, arel_engine)
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
private
|
14
|
-
|
15
|
-
# In a schema schema environment we want to set table name prefix
|
16
|
-
# to the schema_name + . if its not set already
|
17
|
-
alias :base_compute_table_name :compute_table_name
|
18
|
-
def compute_table_name
|
19
|
-
result = base_compute_table_name
|
20
|
-
if result.match(/^[^.]*$/) && connection.cross_schema_support?
|
21
|
-
t_schema = connection.fetch_table_schema(undecorated_table_name(name))
|
22
|
-
self.table_name_prefix = "#{t_schema}." if t_schema
|
23
|
-
result = base_compute_table_name
|
24
|
-
end
|
25
|
-
result
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
if ActiveRecord::VERSION::MAJOR == 3 && ActiveRecord::VERSION::MINOR <= 1
|
32
|
-
require 'active_record/connection_adapters/mysql2_adapter'
|
33
|
-
module ActiveRecord
|
34
|
-
module ConnectionAdapters
|
35
|
-
class Mysql2Adapter < AbstractAdapter
|
36
|
-
|
37
|
-
# Force all tables to be cached for the life connection
|
38
|
-
def cached_tables
|
39
|
-
@cached_tables ||= {}
|
40
|
-
end
|
41
|
-
|
42
|
-
def tables(name = nil, database = nil, like =nil)
|
43
|
-
return cached_tables[database] if cached_tables[database] && like.nil?
|
44
|
-
cached_tables[database] ||= []
|
45
|
-
return [like] if like && cached_tables[database].include?(like)
|
46
|
-
sql = "SHOW TABLES "
|
47
|
-
sql << "IN #{database} " if database
|
48
|
-
sql << "LIKE #{quote(like)}" if like
|
49
|
-
result = execute(sql, 'SCHEMA')
|
50
|
-
cached_tables[database] = (cached_tables[database] | result.collect { |field| field[0] }).compact
|
51
|
-
end
|
52
|
-
|
53
|
-
# We have to clean the name of '`' and fetch table name with schema
|
54
|
-
def table_exists?(name)
|
55
|
-
return false unless name
|
56
|
-
name = name.to_s
|
57
|
-
schema, table = name.split('.', 2)
|
58
|
-
unless table # A table was provided without a schema
|
59
|
-
table = schema
|
60
|
-
schema = nil
|
61
|
-
end
|
62
|
-
tables(nil, schema, table).include?(table)
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|
data/spec/jdbcmysql_database.yml
DELETED
@@ -1,50 +0,0 @@
|
|
1
|
-
# Warning: The database defined as "test" will be erased and
|
2
|
-
# re-generated from your development database when you run "rake".
|
3
|
-
# Do not set this db to the same as development or production.
|
4
|
-
common: &common
|
5
|
-
adapter: jdbcmysql
|
6
|
-
username: root
|
7
|
-
password: omegared
|
8
|
-
pool: 100
|
9
|
-
timeout: 5000
|
10
|
-
build_connection_class: true
|
11
|
-
|
12
|
-
master: &master
|
13
|
-
username: root
|
14
|
-
password: omegared
|
15
|
-
|
16
|
-
readonly: &readonly
|
17
|
-
username: readonly
|
18
|
-
password: omegared
|
19
|
-
|
20
|
-
test:
|
21
|
-
<<: *common
|
22
|
-
<<: *master
|
23
|
-
database: cm_test
|
24
|
-
slaves: [slave_1_cm_test, slave_2_cm_test]
|
25
|
-
|
26
|
-
cm_user_test:
|
27
|
-
<<: *common
|
28
|
-
<<: *master
|
29
|
-
database: cm_user_test
|
30
|
-
slaves: [slave_1_cm_user_test]
|
31
|
-
|
32
|
-
slave_1_cm_test:
|
33
|
-
<<: *common
|
34
|
-
<<: *readonly
|
35
|
-
database: cm_test
|
36
|
-
|
37
|
-
slave_2_cm_test:
|
38
|
-
<<: *common
|
39
|
-
<<: *readonly
|
40
|
-
database: cm_test
|
41
|
-
|
42
|
-
shard_1_cm_test:
|
43
|
-
<<: *common
|
44
|
-
<<: *master
|
45
|
-
database: legacy_cm_test
|
46
|
-
|
47
|
-
slave_1_cm_user_test:
|
48
|
-
<<: *common
|
49
|
-
<<: *readonly
|
50
|
-
database: cm_user_test
|
@@ -1,28 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
describe ConnectionManager::ConnectionBuilder do
|
3
|
-
|
4
|
-
describe '#connection_class_name' do
|
5
|
-
it "should return a string for a class name appended with 'Connection' " do
|
6
|
-
ActiveRecord::Base.send(:connection_class_name,"my_database").should eql("MyDatabaseConnection")
|
7
|
-
end
|
8
|
-
it "should return remove the appended rails env" do
|
9
|
-
ActiveRecord::Base.send(:connection_class_name,"my_database_test").should eql("MyDatabaseConnection")
|
10
|
-
end
|
11
|
-
it "should use the database name from the database.yml if supplied string is only is only the Rails.env" do
|
12
|
-
ActiveRecord::Base.send(:connection_class_name,"test").should eql("BaseConnection")
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
describe '#build_connection_class' do
|
17
|
-
before(:all) do
|
18
|
-
ActiveRecord::Base.build_connection_class("MyConnectionClass", :test)
|
19
|
-
end
|
20
|
-
it "should add a class with supplied class name to ConnectionManager::ConnectionBuilder" do
|
21
|
-
defined?(MyConnectionClass).should be_true
|
22
|
-
MyConnectionClass.is_a?(Class).should be_true
|
23
|
-
end
|
24
|
-
it "should have a super class of ActiveRecord::Base" do
|
25
|
-
MyConnectionClass.superclass.should eql(ActiveRecord::Base)
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|