seamless_database_pool 1.0.5 → 1.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Rakefile +52 -4
- data/lib/active_record/connection_adapters/seamless_database_pool_adapter.rb +116 -125
- data/lib/seamless_database_pool/arel_compiler.rb +27 -0
- data/lib/seamless_database_pool.rb +80 -77
- data/spec/connection_adapters_spec.rb +212 -0
- data/spec/database.yml +35 -0
- data/spec/seamless_database_pool_adapter_spec.rb +236 -258
- data/spec/spec_helper.rb +4 -3
- data/spec/test_adapter/active_record/connection_adapters/read_only_adapter.rb +51 -0
- data/spec/test_model.rb +46 -0
- metadata +53 -23
- data/MIT-LICENSE +0 -20
- data/VERSION +0 -1
- data/init.rb +0 -2
- data/seamless_database_pool.gemspec +0 -69
- data/spec/test_models.rb +0 -35
@@ -0,0 +1,212 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'spec_helper'))
|
2
|
+
|
3
|
+
describe "Test connection adapters" do
|
4
|
+
if SeamlessDatabasePool::TestModel.database_configs.empty?
|
5
|
+
puts "No adapters specified for testing. Specify the adapters with TEST_ADAPTERS variable"
|
6
|
+
else
|
7
|
+
SeamlessDatabasePool::TestModel.database_configs.keys.each do |adapter|
|
8
|
+
context adapter do
|
9
|
+
let(:model){ SeamlessDatabasePool::TestModel.db_model(adapter)}
|
10
|
+
let(:connection){ model.connection }
|
11
|
+
let(:read_connection){ connection.available_read_connections.first }
|
12
|
+
let(:master_connection){ connection.master_connection }
|
13
|
+
|
14
|
+
before(:all) do
|
15
|
+
model.use_database_connection(adapter)
|
16
|
+
model.create_tables
|
17
|
+
end
|
18
|
+
|
19
|
+
after(:all) do
|
20
|
+
model.drop_tables
|
21
|
+
model.cleanup_database!
|
22
|
+
end
|
23
|
+
|
24
|
+
before(:each) do
|
25
|
+
model.create!(:name => 'test', :value => 1)
|
26
|
+
SeamlessDatabasePool.use_persistent_read_connection
|
27
|
+
end
|
28
|
+
|
29
|
+
after(:each) do
|
30
|
+
model.delete_all
|
31
|
+
SeamlessDatabasePool.use_master_connection
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should force the master connection on reload" do
|
35
|
+
record = model.first
|
36
|
+
SeamlessDatabasePool.should_not_receive(:current_read_connection)
|
37
|
+
record.reload
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should quote table names properly" do
|
41
|
+
connection.quote_table_name("foo").should == master_connection.quote_table_name("foo")
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should quote column names properly" do
|
45
|
+
connection.quote_column_name("foo").should == master_connection.quote_column_name("foo")
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should quote string properly" do
|
49
|
+
connection.quote_string("foo").should == master_connection.quote_string("foo")
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should quote booleans properly" do
|
53
|
+
connection.quoted_true.should == master_connection.quoted_true
|
54
|
+
connection.quoted_false.should == master_connection.quoted_false
|
55
|
+
end
|
56
|
+
|
57
|
+
it "should quote dates properly" do
|
58
|
+
date = Date.today
|
59
|
+
time = Time.now
|
60
|
+
connection.quoted_date(date).should == master_connection.quoted_date(date)
|
61
|
+
connection.quoted_date(time).should == master_connection.quoted_date(time)
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should query for records" do
|
65
|
+
record = model.find_by_name("test")
|
66
|
+
record.name.should == "test"
|
67
|
+
end
|
68
|
+
|
69
|
+
it "should work with query caching" do
|
70
|
+
record_id = model.first.id
|
71
|
+
model.cache do
|
72
|
+
found = model.find(record_id)
|
73
|
+
found.name = "new value"
|
74
|
+
found.save!
|
75
|
+
model.find(record_id).name.should == "new value"
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
context "read connection" do
|
80
|
+
|
81
|
+
let(:sample_sql){"SELECT #{connection.quote_column_name('name')} FROM #{connection.quote_table_name(model.table_name)}"}
|
82
|
+
|
83
|
+
it "should not include the master connection in the read pool for these tests" do
|
84
|
+
connection.available_read_connections.should_not include(master_connection)
|
85
|
+
connection.current_read_connection.should_not == master_connection
|
86
|
+
end
|
87
|
+
|
88
|
+
it "should send select to the read connection" do
|
89
|
+
results = connection.send(:select, sample_sql)
|
90
|
+
results.should == [{"name" => "test"}]
|
91
|
+
results.should == master_connection.send(:select, sample_sql)
|
92
|
+
results.should be_read_only
|
93
|
+
end
|
94
|
+
|
95
|
+
it "should send select_all to the read connection" do
|
96
|
+
results = connection.select_all(sample_sql)
|
97
|
+
results.should == [{"name" => "test"}]
|
98
|
+
results.should == master_connection.select_all(sample_sql)
|
99
|
+
results.should be_read_only
|
100
|
+
end
|
101
|
+
|
102
|
+
it "should send select_one to the read connection" do
|
103
|
+
results = connection.select_one(sample_sql)
|
104
|
+
results.should == {"name" => "test"}
|
105
|
+
results.should == master_connection.select_one(sample_sql)
|
106
|
+
results.should be_read_only
|
107
|
+
end
|
108
|
+
|
109
|
+
it "should send select_values to the read connection" do
|
110
|
+
results = connection.select_values(sample_sql)
|
111
|
+
results.should == ["test"]
|
112
|
+
results.should == master_connection.select_values(sample_sql)
|
113
|
+
results.should be_read_only
|
114
|
+
end
|
115
|
+
|
116
|
+
it "should send select_value to the read connection" do
|
117
|
+
results = connection.select_value(sample_sql)
|
118
|
+
results.should == "test"
|
119
|
+
results.should == master_connection.select_value(sample_sql)
|
120
|
+
results.should be_read_only
|
121
|
+
end
|
122
|
+
|
123
|
+
it "should send select_rows to the read connection" do
|
124
|
+
results = connection.select_all(sample_sql)
|
125
|
+
results.should == [{"name" => "test"}]
|
126
|
+
results.should == master_connection.select_all(sample_sql)
|
127
|
+
results.should be_read_only
|
128
|
+
end
|
129
|
+
|
130
|
+
it "should send execute to the read connection" do
|
131
|
+
results = connection.execute(sample_sql)
|
132
|
+
results.should be_read_only
|
133
|
+
end
|
134
|
+
|
135
|
+
it "should send columns to the read connection" do
|
136
|
+
results = connection.columns(model.table_name)
|
137
|
+
columns = results.collect{|c| c.name}.sort.should
|
138
|
+
columns.should == ["id", "name", "value"]
|
139
|
+
columns.should == master_connection.columns(model.table_name).collect{|c| c.name}.sort
|
140
|
+
results.should be_read_only
|
141
|
+
end
|
142
|
+
|
143
|
+
it "should send tables to the read connection" do
|
144
|
+
results = connection.tables
|
145
|
+
results.should == ["test_models"]
|
146
|
+
results.should == master_connection.tables
|
147
|
+
results.should be_read_only
|
148
|
+
end
|
149
|
+
|
150
|
+
it "should reconnect dead connections in the read pool" do
|
151
|
+
read_connection.disconnect!
|
152
|
+
read_connection.should_not be_active
|
153
|
+
results = connection.select_all(sample_sql)
|
154
|
+
results.should be_read_only
|
155
|
+
read_connection.should be_active
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
context "master connection" do
|
160
|
+
|
161
|
+
let(:insert_sql){ "INSERT INTO #{connection.quote_table_name(model.table_name)} (#{connection.quote_column_name('name')}) VALUES ('new')" }
|
162
|
+
let(:update_sql){ "UPDATE #{connection.quote_table_name(model.table_name)} SET #{connection.quote_column_name('value')} = 2" }
|
163
|
+
let(:delete_sql){ "DELETE FROM #{connection.quote_table_name(model.table_name)}" }
|
164
|
+
|
165
|
+
it "should blow up if a master connection method is sent to the read only connection" do
|
166
|
+
lambda{read_connection.update(update_sql)}.should raise_error(NotImplementedError)
|
167
|
+
lambda{read_connection.update(insert_sql)}.should raise_error(NotImplementedError)
|
168
|
+
lambda{read_connection.update(delete_sql)}.should raise_error(NotImplementedError)
|
169
|
+
lambda{read_connection.transaction{}}.should raise_error(NotImplementedError)
|
170
|
+
lambda{read_connection.create_table(:test)}.should raise_error(NotImplementedError)
|
171
|
+
end
|
172
|
+
|
173
|
+
it "should send update to the master connection" do
|
174
|
+
connection.update(update_sql)
|
175
|
+
model.first.value.should == 2
|
176
|
+
end
|
177
|
+
|
178
|
+
it "should send insert to the master connection" do
|
179
|
+
connection.update(insert_sql)
|
180
|
+
model.find_by_name("new").should_not == nil
|
181
|
+
end
|
182
|
+
|
183
|
+
it "should send delete to the master connection" do
|
184
|
+
connection.update(delete_sql)
|
185
|
+
model.first.should == nil
|
186
|
+
end
|
187
|
+
|
188
|
+
it "should send transaction to the master connection" do
|
189
|
+
connection.transaction do
|
190
|
+
connection.update(update_sql)
|
191
|
+
end
|
192
|
+
model.first.value.should == 2
|
193
|
+
end
|
194
|
+
|
195
|
+
it "should send schema altering statements to the master connection" do
|
196
|
+
SeamlessDatabasePool.use_master_connection do
|
197
|
+
begin
|
198
|
+
connection.create_table(:foo) do |t|
|
199
|
+
t.string :name
|
200
|
+
end
|
201
|
+
connection.add_index(:foo, :name)
|
202
|
+
ensure
|
203
|
+
connection.remove_index(:foo, :name)
|
204
|
+
connection.drop_table(:foo)
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|
212
|
+
end
|
data/spec/database.yml
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
# This file contains the databases that the test suite will be run against if you run rake:test:adapters or set the
|
2
|
+
# environment variable ADAPTER (use commas to test multiple adapters). If you want, you can add your own adapter below
|
3
|
+
# and it will be added to the test suite.
|
4
|
+
|
5
|
+
sqlite3:
|
6
|
+
adapter: seamless_database_pool
|
7
|
+
database: test.sqlite3
|
8
|
+
master:
|
9
|
+
adapter: sqlite3
|
10
|
+
pool_weight: 0
|
11
|
+
read_pool:
|
12
|
+
- adapter: read_only
|
13
|
+
real_adapter: sqlite3
|
14
|
+
|
15
|
+
postgresql:
|
16
|
+
adapter: seamless_database_pool
|
17
|
+
database: seamless_database_pool_test
|
18
|
+
username: postgres
|
19
|
+
password: postgres
|
20
|
+
master:
|
21
|
+
adapter: postgresql
|
22
|
+
pool_weight: 0
|
23
|
+
read_pool:
|
24
|
+
- adapter: read_only
|
25
|
+
real_adapter: postgresql
|
26
|
+
|
27
|
+
mysql:
|
28
|
+
adapter: seamless_database_pool
|
29
|
+
database: seamless_database_pool_test
|
30
|
+
master:
|
31
|
+
adapter: mysql
|
32
|
+
pool_weight: 0
|
33
|
+
read_pool:
|
34
|
+
- adapter: read_only
|
35
|
+
real_adapter: mysql
|