epugh-sequel 0.0.0
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/README.rdoc +652 -0
- data/VERSION.yml +4 -0
- data/bin/sequel +104 -0
- data/lib/sequel.rb +1 -0
- data/lib/sequel/adapters/ado.rb +85 -0
- data/lib/sequel/adapters/db2.rb +132 -0
- data/lib/sequel/adapters/dbi.rb +101 -0
- data/lib/sequel/adapters/do.rb +197 -0
- data/lib/sequel/adapters/do/mysql.rb +38 -0
- data/lib/sequel/adapters/do/postgres.rb +92 -0
- data/lib/sequel/adapters/do/sqlite.rb +31 -0
- data/lib/sequel/adapters/firebird.rb +307 -0
- data/lib/sequel/adapters/informix.rb +75 -0
- data/lib/sequel/adapters/jdbc.rb +485 -0
- data/lib/sequel/adapters/jdbc/h2.rb +62 -0
- data/lib/sequel/adapters/jdbc/mysql.rb +56 -0
- data/lib/sequel/adapters/jdbc/oracle.rb +23 -0
- data/lib/sequel/adapters/jdbc/postgresql.rb +101 -0
- data/lib/sequel/adapters/jdbc/sqlite.rb +43 -0
- data/lib/sequel/adapters/mysql.rb +370 -0
- data/lib/sequel/adapters/odbc.rb +184 -0
- data/lib/sequel/adapters/openbase.rb +57 -0
- data/lib/sequel/adapters/oracle.rb +140 -0
- data/lib/sequel/adapters/postgres.rb +453 -0
- data/lib/sequel/adapters/shared/mssql.rb +93 -0
- data/lib/sequel/adapters/shared/mysql.rb +341 -0
- data/lib/sequel/adapters/shared/oracle.rb +62 -0
- data/lib/sequel/adapters/shared/postgres.rb +743 -0
- data/lib/sequel/adapters/shared/progress.rb +34 -0
- data/lib/sequel/adapters/shared/sqlite.rb +263 -0
- data/lib/sequel/adapters/sqlite.rb +243 -0
- data/lib/sequel/adapters/utils/date_format.rb +21 -0
- data/lib/sequel/adapters/utils/stored_procedures.rb +75 -0
- data/lib/sequel/adapters/utils/unsupported.rb +62 -0
- data/lib/sequel/connection_pool.rb +258 -0
- data/lib/sequel/core.rb +204 -0
- data/lib/sequel/core_sql.rb +185 -0
- data/lib/sequel/database.rb +687 -0
- data/lib/sequel/database/schema_generator.rb +324 -0
- data/lib/sequel/database/schema_methods.rb +164 -0
- data/lib/sequel/database/schema_sql.rb +324 -0
- data/lib/sequel/dataset.rb +422 -0
- data/lib/sequel/dataset/convenience.rb +237 -0
- data/lib/sequel/dataset/prepared_statements.rb +220 -0
- data/lib/sequel/dataset/sql.rb +1105 -0
- data/lib/sequel/deprecated.rb +529 -0
- data/lib/sequel/exceptions.rb +44 -0
- data/lib/sequel/extensions/blank.rb +42 -0
- data/lib/sequel/extensions/inflector.rb +288 -0
- data/lib/sequel/extensions/pagination.rb +96 -0
- data/lib/sequel/extensions/pretty_table.rb +78 -0
- data/lib/sequel/extensions/query.rb +48 -0
- data/lib/sequel/extensions/string_date_time.rb +47 -0
- data/lib/sequel/metaprogramming.rb +44 -0
- data/lib/sequel/migration.rb +212 -0
- data/lib/sequel/model.rb +142 -0
- data/lib/sequel/model/association_reflection.rb +263 -0
- data/lib/sequel/model/associations.rb +1024 -0
- data/lib/sequel/model/base.rb +911 -0
- data/lib/sequel/model/deprecated.rb +188 -0
- data/lib/sequel/model/deprecated_hooks.rb +103 -0
- data/lib/sequel/model/deprecated_inflector.rb +335 -0
- data/lib/sequel/model/deprecated_validations.rb +384 -0
- data/lib/sequel/model/errors.rb +37 -0
- data/lib/sequel/model/exceptions.rb +7 -0
- data/lib/sequel/model/inflections.rb +230 -0
- data/lib/sequel/model/plugins.rb +74 -0
- data/lib/sequel/object_graph.rb +230 -0
- data/lib/sequel/plugins/caching.rb +122 -0
- data/lib/sequel/plugins/hook_class_methods.rb +122 -0
- data/lib/sequel/plugins/schema.rb +53 -0
- data/lib/sequel/plugins/single_table_inheritance.rb +63 -0
- data/lib/sequel/plugins/validation_class_methods.rb +373 -0
- data/lib/sequel/sql.rb +854 -0
- data/lib/sequel/version.rb +11 -0
- data/lib/sequel_core.rb +1 -0
- data/lib/sequel_model.rb +1 -0
- data/spec/adapters/ado_spec.rb +46 -0
- data/spec/adapters/firebird_spec.rb +376 -0
- data/spec/adapters/informix_spec.rb +96 -0
- data/spec/adapters/mysql_spec.rb +875 -0
- data/spec/adapters/oracle_spec.rb +272 -0
- data/spec/adapters/postgres_spec.rb +692 -0
- data/spec/adapters/spec_helper.rb +10 -0
- data/spec/adapters/sqlite_spec.rb +550 -0
- data/spec/core/connection_pool_spec.rb +526 -0
- data/spec/core/core_ext_spec.rb +156 -0
- data/spec/core/core_sql_spec.rb +528 -0
- data/spec/core/database_spec.rb +1214 -0
- data/spec/core/dataset_spec.rb +3513 -0
- data/spec/core/expression_filters_spec.rb +363 -0
- data/spec/core/migration_spec.rb +261 -0
- data/spec/core/object_graph_spec.rb +280 -0
- data/spec/core/pretty_table_spec.rb +58 -0
- data/spec/core/schema_generator_spec.rb +167 -0
- data/spec/core/schema_spec.rb +778 -0
- data/spec/core/spec_helper.rb +82 -0
- data/spec/core/version_spec.rb +7 -0
- data/spec/extensions/blank_spec.rb +67 -0
- data/spec/extensions/caching_spec.rb +201 -0
- data/spec/extensions/hook_class_methods_spec.rb +470 -0
- data/spec/extensions/inflector_spec.rb +122 -0
- data/spec/extensions/pagination_spec.rb +99 -0
- data/spec/extensions/pretty_table_spec.rb +91 -0
- data/spec/extensions/query_spec.rb +85 -0
- data/spec/extensions/schema_spec.rb +111 -0
- data/spec/extensions/single_table_inheritance_spec.rb +53 -0
- data/spec/extensions/spec_helper.rb +90 -0
- data/spec/extensions/string_date_time_spec.rb +93 -0
- data/spec/extensions/validation_class_methods_spec.rb +1054 -0
- data/spec/integration/dataset_test.rb +160 -0
- data/spec/integration/eager_loader_test.rb +683 -0
- data/spec/integration/prepared_statement_test.rb +130 -0
- data/spec/integration/schema_test.rb +183 -0
- data/spec/integration/spec_helper.rb +75 -0
- data/spec/integration/type_test.rb +96 -0
- data/spec/model/association_reflection_spec.rb +93 -0
- data/spec/model/associations_spec.rb +1780 -0
- data/spec/model/base_spec.rb +494 -0
- data/spec/model/caching_spec.rb +217 -0
- data/spec/model/dataset_methods_spec.rb +78 -0
- data/spec/model/eager_loading_spec.rb +1165 -0
- data/spec/model/hooks_spec.rb +472 -0
- data/spec/model/inflector_spec.rb +126 -0
- data/spec/model/model_spec.rb +588 -0
- data/spec/model/plugins_spec.rb +142 -0
- data/spec/model/record_spec.rb +1243 -0
- data/spec/model/schema_spec.rb +92 -0
- data/spec/model/spec_helper.rb +124 -0
- data/spec/model/validations_spec.rb +1080 -0
- data/spec/rcov.opts +6 -0
- data/spec/spec.opts +0 -0
- data/spec/spec_config.rb.example +10 -0
- metadata +202 -0
|
@@ -0,0 +1,526 @@
|
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'spec_helper')
|
|
2
|
+
CONNECTION_POOL_DEFAULTS = {:pool_timeout=>5, :pool_sleep_time=>0.001,
|
|
3
|
+
:pool_reuse_connections=>:allow, :pool_convert_exceptions=>true, :max_connections=>4}
|
|
4
|
+
|
|
5
|
+
context "An empty ConnectionPool" do
|
|
6
|
+
setup do
|
|
7
|
+
@cpool = Sequel::ConnectionPool.new(CONNECTION_POOL_DEFAULTS)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
specify "should have no available connections" do
|
|
11
|
+
@cpool.available_connections.should == []
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
specify "should have no allocated connections" do
|
|
15
|
+
@cpool.allocated.should == {}
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
specify "should have a created_count of zero" do
|
|
19
|
+
@cpool.created_count.should == 0
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
context "A connection pool handling connections" do
|
|
24
|
+
setup do
|
|
25
|
+
@max_size = 2
|
|
26
|
+
@cpool = Sequel::ConnectionPool.new(CONNECTION_POOL_DEFAULTS.merge(:disconnection_proc=>proc{|c| @max_size=3}, :max_connections=>@max_size)) {:got_connection}
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
specify "#hold should increment #created_count" do
|
|
30
|
+
@cpool.hold do
|
|
31
|
+
@cpool.created_count.should == 1
|
|
32
|
+
@cpool.hold {@cpool.hold {@cpool.created_count.should == 1}}
|
|
33
|
+
Thread.new{@cpool.hold {@cpool.created_count.should == 2}}.join
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
specify "#hold should add the connection to the #allocated array" do
|
|
38
|
+
@cpool.hold do
|
|
39
|
+
@cpool.allocated.size.should == 1
|
|
40
|
+
|
|
41
|
+
@cpool.allocated.should == {Thread.current=>:got_connection}
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
specify "#hold should yield a new connection" do
|
|
46
|
+
@cpool.hold {|conn| conn.should == :got_connection}
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
specify "a connection should be de-allocated after it has been used in #hold" do
|
|
50
|
+
@cpool.hold {}
|
|
51
|
+
@cpool.allocated.size.should == 0
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
specify "#hold should return the value of its block" do
|
|
55
|
+
@cpool.hold {:block_return}.should == :block_return
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
specify "#make_new should not make more than max_size connections" do
|
|
59
|
+
@cpool.send(:make_new, :default).should == :got_connection
|
|
60
|
+
@cpool.send(:make_new, :default).should == :got_connection
|
|
61
|
+
@cpool.send(:make_new, :default).should == nil
|
|
62
|
+
@cpool.created_count.should == 2
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
specify ":disconnection_proc option should set the disconnection proc to use" do
|
|
66
|
+
@max_size.should == 2
|
|
67
|
+
proc{@cpool.hold{raise Sequel::DatabaseDisconnectError}}.should raise_error(Sequel::DatabaseDisconnectError)
|
|
68
|
+
@max_size.should == 3
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
specify "#disconnection_proc= should set the disconnection proc to use" do
|
|
72
|
+
a = 1
|
|
73
|
+
@cpool.disconnection_proc = proc{|c| a += 1}
|
|
74
|
+
proc{@cpool.hold{raise Sequel::DatabaseDisconnectError}}.should raise_error(Sequel::DatabaseDisconnectError)
|
|
75
|
+
a.should == 2
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
specify "#hold should remove the connection if a DatabaseDisconnectError is raised" do
|
|
79
|
+
@cpool.created_count.should == 0
|
|
80
|
+
@cpool.hold{Thread.new{@cpool.hold{}}; sleep 0.01}
|
|
81
|
+
@cpool.created_count.should == 2
|
|
82
|
+
proc{@cpool.hold{raise Sequel::DatabaseDisconnectError}}.should raise_error(Sequel::DatabaseDisconnectError)
|
|
83
|
+
@cpool.created_count.should == 1
|
|
84
|
+
proc{@cpool.hold{raise Sequel::DatabaseDisconnectError}}.should raise_error(Sequel::DatabaseDisconnectError)
|
|
85
|
+
@cpool.created_count.should == 0
|
|
86
|
+
proc{@cpool.hold{raise Sequel::DatabaseDisconnectError}}.should raise_error(Sequel::DatabaseDisconnectError)
|
|
87
|
+
@cpool.created_count.should == 0
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
context "A connection pool handling connection errors" do
|
|
92
|
+
specify "#hold should raise a Sequel::DatabaseConnectionError if an exception is raised by the connection_proc" do
|
|
93
|
+
cpool = Sequel::ConnectionPool.new(CONNECTION_POOL_DEFAULTS){raise Interrupt}
|
|
94
|
+
proc{cpool.hold{:block_return}}.should raise_error(Sequel::DatabaseConnectionError)
|
|
95
|
+
cpool.created_count.should == 0
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
specify "#hold should raise a Sequel::DatabaseConnectionError if nil is returned by the connection_proc" do
|
|
99
|
+
cpool = Sequel::ConnectionPool.new(CONNECTION_POOL_DEFAULTS){nil}
|
|
100
|
+
proc{cpool.hold{:block_return}}.should raise_error(Sequel::DatabaseConnectionError)
|
|
101
|
+
cpool.created_count.should == 0
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
class DummyConnection
|
|
106
|
+
@@value = 0
|
|
107
|
+
def initialize
|
|
108
|
+
@@value += 1
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def value
|
|
112
|
+
@@value
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
context "ConnectionPool#hold" do
|
|
117
|
+
setup do
|
|
118
|
+
@pool = Sequel::ConnectionPool.new(CONNECTION_POOL_DEFAULTS) {DummyConnection.new}
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
specify "should pass the result of the connection maker proc to the supplied block" do
|
|
122
|
+
res = nil
|
|
123
|
+
@pool.hold {|c| res = c}
|
|
124
|
+
res.should be_a_kind_of(DummyConnection)
|
|
125
|
+
res.value.should == 1
|
|
126
|
+
@pool.hold {|c| res = c}
|
|
127
|
+
res.should be_a_kind_of(DummyConnection)
|
|
128
|
+
res.value.should == 1 # the connection maker is invoked only once
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
specify "should be re-entrant by the same thread" do
|
|
132
|
+
cc = nil
|
|
133
|
+
@pool.hold {|c| @pool.hold {|c| @pool.hold {|c| cc = c}}}
|
|
134
|
+
cc.should be_a_kind_of(DummyConnection)
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
specify "should catch exceptions and reraise them" do
|
|
138
|
+
proc {@pool.hold {|c| c.foobar}}.should raise_error(NoMethodError)
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
specify "should handle Exception errors (normally not caught by rescue)" do
|
|
142
|
+
err = nil
|
|
143
|
+
begin
|
|
144
|
+
@pool.hold {raise Exception}
|
|
145
|
+
rescue => e
|
|
146
|
+
err = e
|
|
147
|
+
end
|
|
148
|
+
err.should be_a_kind_of(RuntimeError)
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
context "ConnectionPool#connection_proc" do
|
|
153
|
+
setup do
|
|
154
|
+
@pool = Sequel::ConnectionPool.new(CONNECTION_POOL_DEFAULTS)
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
specify "should be nil if no block is supplied to the pool" do
|
|
158
|
+
@pool.connection_proc.should be_nil
|
|
159
|
+
proc {@pool.hold {}}.should raise_error
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
specify "should be mutable" do
|
|
163
|
+
@pool.connection_proc = proc {'herro'}
|
|
164
|
+
res = nil
|
|
165
|
+
proc {@pool.hold {|c| res = c}}.should_not raise_error
|
|
166
|
+
res.should == 'herro'
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
context "A connection pool with a max size of 1" do
|
|
171
|
+
setup do
|
|
172
|
+
@invoked_count = 0
|
|
173
|
+
@pool = Sequel::ConnectionPool.new(CONNECTION_POOL_DEFAULTS.merge(:max_connections=>1)) {@invoked_count += 1; 'herro'}
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
specify "should let only one thread access the connection at any time" do
|
|
177
|
+
cc,c1, c2 = nil
|
|
178
|
+
|
|
179
|
+
t1 = Thread.new {@pool.hold {|c| cc = c; c1 = c.dup; while c == 'herro';sleep 0.01;end}}
|
|
180
|
+
sleep 0.02
|
|
181
|
+
cc.should == 'herro'
|
|
182
|
+
c1.should == 'herro'
|
|
183
|
+
|
|
184
|
+
t2 = Thread.new {@pool.hold {|c| c2 = c.dup; while c == 'hello';sleep 0.01;end}}
|
|
185
|
+
sleep 0.02
|
|
186
|
+
|
|
187
|
+
# connection held by t1
|
|
188
|
+
t1.should be_alive
|
|
189
|
+
t2.should be_alive
|
|
190
|
+
|
|
191
|
+
cc.should == 'herro'
|
|
192
|
+
c1.should == 'herro'
|
|
193
|
+
c2.should be_nil
|
|
194
|
+
|
|
195
|
+
@pool.available_connections.should be_empty
|
|
196
|
+
@pool.allocated.should == {t1=>cc}
|
|
197
|
+
|
|
198
|
+
cc.gsub!('rr', 'll')
|
|
199
|
+
sleep 0.05
|
|
200
|
+
|
|
201
|
+
# connection held by t2
|
|
202
|
+
t1.should_not be_alive
|
|
203
|
+
t2.should be_alive
|
|
204
|
+
|
|
205
|
+
c2.should == 'hello'
|
|
206
|
+
|
|
207
|
+
@pool.available_connections.should be_empty
|
|
208
|
+
@pool.allocated.should == {t2=>cc}
|
|
209
|
+
|
|
210
|
+
cc.gsub!('ll', 'rr')
|
|
211
|
+
sleep 0.05
|
|
212
|
+
|
|
213
|
+
#connection released
|
|
214
|
+
t2.should_not be_alive
|
|
215
|
+
|
|
216
|
+
cc.should == 'herro'
|
|
217
|
+
|
|
218
|
+
@invoked_count.should == 1
|
|
219
|
+
@pool.size.should == 1
|
|
220
|
+
@pool.available_connections.should == [cc]
|
|
221
|
+
@pool.allocated.should be_empty
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
specify "should let the same thread reenter #hold" do
|
|
225
|
+
c1, c2, c3 = nil
|
|
226
|
+
@pool.hold do |c|
|
|
227
|
+
c1 = c
|
|
228
|
+
@pool.hold do |c|
|
|
229
|
+
c2 = c
|
|
230
|
+
@pool.hold do |c|
|
|
231
|
+
c3 = c
|
|
232
|
+
end
|
|
233
|
+
end
|
|
234
|
+
end
|
|
235
|
+
c1.should == 'herro'
|
|
236
|
+
c2.should == 'herro'
|
|
237
|
+
c3.should == 'herro'
|
|
238
|
+
|
|
239
|
+
@invoked_count.should == 1
|
|
240
|
+
@pool.size.should == 1
|
|
241
|
+
@pool.available_connections.size.should == 1
|
|
242
|
+
@pool.allocated.should be_empty
|
|
243
|
+
end
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
context "A connection pool with a max size of 5" do
|
|
247
|
+
setup do
|
|
248
|
+
@invoked_count = 0
|
|
249
|
+
@pool = Sequel::ConnectionPool.new(CONNECTION_POOL_DEFAULTS.merge(:max_connections=>5)) {@invoked_count += 1}
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
specify "should let five threads simultaneously access separate connections" do
|
|
253
|
+
cc = {}
|
|
254
|
+
threads = []
|
|
255
|
+
stop = nil
|
|
256
|
+
|
|
257
|
+
5.times {|i| threads << Thread.new {@pool.hold {|c| cc[i] = c; while !stop;sleep 0.01;end}}; sleep 0.01}
|
|
258
|
+
sleep 0.02
|
|
259
|
+
threads.each {|t| t.should be_alive}
|
|
260
|
+
cc.size.should == 5
|
|
261
|
+
@invoked_count.should == 5
|
|
262
|
+
@pool.size.should == 5
|
|
263
|
+
@pool.available_connections.should be_empty
|
|
264
|
+
i = 0
|
|
265
|
+
h = {}
|
|
266
|
+
threads.each{|t| h[t] = (i+=1)}
|
|
267
|
+
@pool.allocated.should == h
|
|
268
|
+
|
|
269
|
+
threads[0].raise "your'e dead"
|
|
270
|
+
sleep 0.01
|
|
271
|
+
threads[3].raise "your'e dead too"
|
|
272
|
+
|
|
273
|
+
sleep 0.01
|
|
274
|
+
|
|
275
|
+
@pool.available_connections.should == [1, 4]
|
|
276
|
+
@pool.allocated.should == {threads[1]=>2, threads[2]=>3, threads[4]=>5}
|
|
277
|
+
|
|
278
|
+
stop = true
|
|
279
|
+
sleep 0.02
|
|
280
|
+
|
|
281
|
+
@pool.available_connections.size.should == 5
|
|
282
|
+
@pool.allocated.should be_empty
|
|
283
|
+
end
|
|
284
|
+
|
|
285
|
+
specify "should block threads until a connection becomes available" do
|
|
286
|
+
cc = {}
|
|
287
|
+
threads = []
|
|
288
|
+
stop = nil
|
|
289
|
+
|
|
290
|
+
5.times {|i| threads << Thread.new {@pool.hold {|c| cc[i] = c; while !stop;sleep 0.01;end}}; sleep 0.01}
|
|
291
|
+
sleep 0.02
|
|
292
|
+
threads.each {|t| t.should be_alive}
|
|
293
|
+
@pool.available_connections.should be_empty
|
|
294
|
+
|
|
295
|
+
3.times {|i| threads << Thread.new {@pool.hold {|c| cc[i + 5] = c}}}
|
|
296
|
+
|
|
297
|
+
sleep 0.02
|
|
298
|
+
threads[5].should be_alive
|
|
299
|
+
threads[6].should be_alive
|
|
300
|
+
threads[7].should be_alive
|
|
301
|
+
cc.size.should == 5
|
|
302
|
+
cc[5].should be_nil
|
|
303
|
+
cc[6].should be_nil
|
|
304
|
+
cc[7].should be_nil
|
|
305
|
+
|
|
306
|
+
stop = true
|
|
307
|
+
sleep 0.05
|
|
308
|
+
|
|
309
|
+
threads.each {|t| t.should_not be_alive}
|
|
310
|
+
|
|
311
|
+
@pool.size.should == 5
|
|
312
|
+
@invoked_count.should == 5
|
|
313
|
+
@pool.available_connections.size.should == 5
|
|
314
|
+
@pool.allocated.should be_empty
|
|
315
|
+
end
|
|
316
|
+
end
|
|
317
|
+
|
|
318
|
+
context "ConnectionPool#disconnect" do
|
|
319
|
+
setup do
|
|
320
|
+
@count = 0
|
|
321
|
+
@pool = Sequel::ConnectionPool.new(CONNECTION_POOL_DEFAULTS.merge(:max_connections=>5)) {{:id => @count += 1}}
|
|
322
|
+
end
|
|
323
|
+
|
|
324
|
+
specify "should invoke the given block for each available connection" do
|
|
325
|
+
threads = []
|
|
326
|
+
stop = nil
|
|
327
|
+
5.times {|i| threads << Thread.new {@pool.hold {|c| while !stop;sleep 0.01;end}}; sleep 0.01}
|
|
328
|
+
while @pool.size < 5
|
|
329
|
+
sleep 0.02
|
|
330
|
+
end
|
|
331
|
+
stop = true
|
|
332
|
+
sleep 0.1
|
|
333
|
+
threads.each {|t| t.join}
|
|
334
|
+
|
|
335
|
+
@pool.size.should == 5
|
|
336
|
+
@pool.available_connections.size.should == 5
|
|
337
|
+
@pool.available_connections.each {|c| c[:id].should_not be_nil}
|
|
338
|
+
conns = []
|
|
339
|
+
@pool.disconnect {|c| conns << c}
|
|
340
|
+
conns.size.should == 5
|
|
341
|
+
end
|
|
342
|
+
|
|
343
|
+
specify "should remove all available connections" do
|
|
344
|
+
threads = []
|
|
345
|
+
stop = nil
|
|
346
|
+
5.times {|i| threads << Thread.new {@pool.hold {|c| while !stop;sleep 0.01;end}}; sleep 0.01}
|
|
347
|
+
while @pool.size < 5
|
|
348
|
+
sleep 0.02
|
|
349
|
+
end
|
|
350
|
+
stop = true
|
|
351
|
+
sleep 0.1
|
|
352
|
+
threads.each {|t| t.join}
|
|
353
|
+
|
|
354
|
+
@pool.size.should == 5
|
|
355
|
+
@pool.disconnect
|
|
356
|
+
@pool.size.should == 0
|
|
357
|
+
end
|
|
358
|
+
|
|
359
|
+
specify "should not touch connections in use" do
|
|
360
|
+
threads = []
|
|
361
|
+
stop = nil
|
|
362
|
+
5.times {|i| threads << Thread.new {@pool.hold {|c| while !stop;sleep 0.01;end}}; sleep 0.01}
|
|
363
|
+
while @pool.size < 5
|
|
364
|
+
sleep 0.02
|
|
365
|
+
end
|
|
366
|
+
stop = true
|
|
367
|
+
sleep 0.1
|
|
368
|
+
threads.each {|t| t.join}
|
|
369
|
+
|
|
370
|
+
@pool.size.should == 5
|
|
371
|
+
|
|
372
|
+
@pool.hold do |conn|
|
|
373
|
+
@pool.available_connections.size.should == 4
|
|
374
|
+
@pool.available_connections.each {|c| c.should_not be(conn)}
|
|
375
|
+
conns = []
|
|
376
|
+
@pool.disconnect {|c| conns << c}
|
|
377
|
+
conns.size.should == 4
|
|
378
|
+
end
|
|
379
|
+
@pool.size.should == 1
|
|
380
|
+
end
|
|
381
|
+
end
|
|
382
|
+
|
|
383
|
+
context "A connection pool with multiple servers" do
|
|
384
|
+
setup do
|
|
385
|
+
@invoked_counts = Hash.new(0)
|
|
386
|
+
@pool = Sequel::ConnectionPool.new(CONNECTION_POOL_DEFAULTS.merge(:servers=>{:read_only=>{}})){|server| "#{server}#{@invoked_counts[server] += 1}"}
|
|
387
|
+
end
|
|
388
|
+
|
|
389
|
+
specify "should use the :default server by default" do
|
|
390
|
+
@pool.size.should == 0
|
|
391
|
+
@pool.hold do |c|
|
|
392
|
+
c.should == "default1"
|
|
393
|
+
@pool.allocated.should == {Thread.current=>"default1"}
|
|
394
|
+
end
|
|
395
|
+
@pool.available_connections.should == ["default1"]
|
|
396
|
+
@pool.size.should == 1
|
|
397
|
+
@invoked_counts.should == {:default=>1}
|
|
398
|
+
end
|
|
399
|
+
|
|
400
|
+
specify "should use the requested server if server is given" do
|
|
401
|
+
@pool.size(:read_only).should == 0
|
|
402
|
+
@pool.hold(:read_only) do |c|
|
|
403
|
+
c.should == "read_only1"
|
|
404
|
+
@pool.allocated(:read_only).should == {Thread.current=>"read_only1"}
|
|
405
|
+
end
|
|
406
|
+
@pool.available_connections(:read_only).should == ["read_only1"]
|
|
407
|
+
@pool.size(:read_only).should == 1
|
|
408
|
+
@invoked_counts.should == {:read_only=>1}
|
|
409
|
+
end
|
|
410
|
+
|
|
411
|
+
specify "#hold should only yield connections for the server requested" do
|
|
412
|
+
@pool.hold(:read_only) do |c|
|
|
413
|
+
c.should == "read_only1"
|
|
414
|
+
@pool.allocated(:read_only).should == {Thread.current=>"read_only1"}
|
|
415
|
+
@pool.hold do |d|
|
|
416
|
+
d.should == "default1"
|
|
417
|
+
@pool.hold do |e|
|
|
418
|
+
e.should == d
|
|
419
|
+
@pool.hold(:read_only){|b| b.should == c}
|
|
420
|
+
end
|
|
421
|
+
@pool.allocated.should == {Thread.current=>"default1"}
|
|
422
|
+
end
|
|
423
|
+
end
|
|
424
|
+
@invoked_counts.should == {:read_only=>1, :default=>1}
|
|
425
|
+
end
|
|
426
|
+
|
|
427
|
+
specify "#disconnect should disconnect from all servers" do
|
|
428
|
+
@pool.hold(:read_only){}
|
|
429
|
+
@pool.hold{}
|
|
430
|
+
conns = []
|
|
431
|
+
@pool.size.should == 1
|
|
432
|
+
@pool.size(:read_only).should == 1
|
|
433
|
+
@pool.disconnect{|c| conns << c}
|
|
434
|
+
conns.sort.should == %w'default1 read_only1'
|
|
435
|
+
@pool.size.should == 0
|
|
436
|
+
@pool.size(:read_only).should == 0
|
|
437
|
+
@pool.hold(:read_only){|c| c.should == 'read_only2'}
|
|
438
|
+
@pool.hold{|c| c.should == 'default2'}
|
|
439
|
+
end
|
|
440
|
+
end
|
|
441
|
+
|
|
442
|
+
context "SingleThreadedPool" do
|
|
443
|
+
setup do
|
|
444
|
+
@pool = Sequel::SingleThreadedPool.new(CONNECTION_POOL_DEFAULTS){1234}
|
|
445
|
+
end
|
|
446
|
+
|
|
447
|
+
specify "should provide a #hold method" do
|
|
448
|
+
conn = nil
|
|
449
|
+
@pool.hold {|c| conn = c}
|
|
450
|
+
conn.should == 1234
|
|
451
|
+
end
|
|
452
|
+
|
|
453
|
+
specify "should provide a #disconnect method" do
|
|
454
|
+
@pool.hold {|c|}
|
|
455
|
+
@pool.conn.should == 1234
|
|
456
|
+
conn = nil
|
|
457
|
+
@pool.disconnect {|c| conn = c}
|
|
458
|
+
conn.should == 1234
|
|
459
|
+
@pool.conn.should be_nil
|
|
460
|
+
end
|
|
461
|
+
end
|
|
462
|
+
|
|
463
|
+
context "A single threaded pool with multiple servers" do
|
|
464
|
+
setup do
|
|
465
|
+
@max_size=2
|
|
466
|
+
@pool = Sequel::SingleThreadedPool.new(CONNECTION_POOL_DEFAULTS.merge(:disconnection_proc=>proc{|c| @max_size=3}, :servers=>{:read_only=>{}})){|server| server}
|
|
467
|
+
end
|
|
468
|
+
|
|
469
|
+
specify "should use the :default server by default" do
|
|
470
|
+
@pool.hold{|c| c.should == :default}
|
|
471
|
+
@pool.conn.should == :default
|
|
472
|
+
end
|
|
473
|
+
|
|
474
|
+
specify "should use the requested server if server is given" do
|
|
475
|
+
@pool.hold(:read_only){|c| c.should == :read_only}
|
|
476
|
+
@pool.conn(:read_only).should == :read_only
|
|
477
|
+
end
|
|
478
|
+
|
|
479
|
+
specify "#hold should only yield connections for the server requested" do
|
|
480
|
+
@pool.hold(:read_only) do |c|
|
|
481
|
+
c.should == :read_only
|
|
482
|
+
@pool.hold do |d|
|
|
483
|
+
d.should == :default
|
|
484
|
+
@pool.hold do |e|
|
|
485
|
+
e.should == d
|
|
486
|
+
@pool.hold(:read_only){|b| b.should == c}
|
|
487
|
+
end
|
|
488
|
+
end
|
|
489
|
+
end
|
|
490
|
+
@pool.conn.should == :default
|
|
491
|
+
@pool.conn(:read_only).should == :read_only
|
|
492
|
+
end
|
|
493
|
+
|
|
494
|
+
specify "#disconnect should disconnect from all servers" do
|
|
495
|
+
@pool.hold(:read_only){}
|
|
496
|
+
@pool.hold{}
|
|
497
|
+
conns = []
|
|
498
|
+
@pool.conn.should == :default
|
|
499
|
+
@pool.conn(:read_only).should == :read_only
|
|
500
|
+
@pool.disconnect{|c| conns << c}
|
|
501
|
+
conns.sort_by{|x| x.to_s}.should == [:default, :read_only]
|
|
502
|
+
@pool.conn.should == nil
|
|
503
|
+
@pool.conn(:read_only).should == nil
|
|
504
|
+
end
|
|
505
|
+
|
|
506
|
+
specify ":disconnection_proc option should set the disconnection proc to use" do
|
|
507
|
+
@max_size.should == 2
|
|
508
|
+
proc{@pool.hold{raise Sequel::DatabaseDisconnectError}}.should raise_error(Sequel::DatabaseDisconnectError)
|
|
509
|
+
@max_size.should == 3
|
|
510
|
+
end
|
|
511
|
+
|
|
512
|
+
specify "#disconnection_proc= should set the disconnection proc to use" do
|
|
513
|
+
a = 1
|
|
514
|
+
@pool.disconnection_proc = proc{|c| a += 1}
|
|
515
|
+
proc{@pool.hold{raise Sequel::DatabaseDisconnectError}}.should raise_error(Sequel::DatabaseDisconnectError)
|
|
516
|
+
a.should == 2
|
|
517
|
+
end
|
|
518
|
+
|
|
519
|
+
specify "#hold should remove the connection if a DatabaseDisconnectError is raised" do
|
|
520
|
+
@pool.instance_variable_get(:@conns).length.should == 0
|
|
521
|
+
@pool.hold{}
|
|
522
|
+
@pool.instance_variable_get(:@conns).length.should == 1
|
|
523
|
+
proc{@pool.hold{raise Sequel::DatabaseDisconnectError}}.should raise_error(Sequel::DatabaseDisconnectError)
|
|
524
|
+
@pool.instance_variable_get(:@conns).length.should == 0
|
|
525
|
+
end
|
|
526
|
+
end
|