sequel_core 2.2.0 → 3.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. metadata +30 -101
  2. data/CHANGELOG +0 -1519
  3. data/COPYING +0 -19
  4. data/README +0 -313
  5. data/Rakefile +0 -158
  6. data/bin/sequel +0 -117
  7. data/doc/cheat_sheet.rdoc +0 -225
  8. data/doc/dataset_filtering.rdoc +0 -182
  9. data/lib/sequel_core.rb +0 -136
  10. data/lib/sequel_core/adapters/adapter_skeleton.rb +0 -68
  11. data/lib/sequel_core/adapters/ado.rb +0 -90
  12. data/lib/sequel_core/adapters/db2.rb +0 -160
  13. data/lib/sequel_core/adapters/dbi.rb +0 -127
  14. data/lib/sequel_core/adapters/informix.rb +0 -89
  15. data/lib/sequel_core/adapters/jdbc.rb +0 -110
  16. data/lib/sequel_core/adapters/mysql.rb +0 -486
  17. data/lib/sequel_core/adapters/odbc.rb +0 -167
  18. data/lib/sequel_core/adapters/odbc_mssql.rb +0 -106
  19. data/lib/sequel_core/adapters/openbase.rb +0 -76
  20. data/lib/sequel_core/adapters/oracle.rb +0 -182
  21. data/lib/sequel_core/adapters/postgres.rb +0 -560
  22. data/lib/sequel_core/adapters/sqlite.rb +0 -270
  23. data/lib/sequel_core/connection_pool.rb +0 -194
  24. data/lib/sequel_core/core_ext.rb +0 -197
  25. data/lib/sequel_core/core_sql.rb +0 -184
  26. data/lib/sequel_core/database.rb +0 -462
  27. data/lib/sequel_core/database/schema.rb +0 -156
  28. data/lib/sequel_core/dataset.rb +0 -457
  29. data/lib/sequel_core/dataset/callback.rb +0 -13
  30. data/lib/sequel_core/dataset/convenience.rb +0 -245
  31. data/lib/sequel_core/dataset/pagination.rb +0 -96
  32. data/lib/sequel_core/dataset/query.rb +0 -41
  33. data/lib/sequel_core/dataset/schema.rb +0 -15
  34. data/lib/sequel_core/dataset/sql.rb +0 -889
  35. data/lib/sequel_core/deprecated.rb +0 -26
  36. data/lib/sequel_core/exceptions.rb +0 -42
  37. data/lib/sequel_core/migration.rb +0 -187
  38. data/lib/sequel_core/object_graph.rb +0 -216
  39. data/lib/sequel_core/pretty_table.rb +0 -71
  40. data/lib/sequel_core/schema.rb +0 -2
  41. data/lib/sequel_core/schema/generator.rb +0 -239
  42. data/lib/sequel_core/schema/sql.rb +0 -326
  43. data/lib/sequel_core/sql.rb +0 -812
  44. data/lib/sequel_core/worker.rb +0 -68
  45. data/spec/adapters/informix_spec.rb +0 -96
  46. data/spec/adapters/mysql_spec.rb +0 -765
  47. data/spec/adapters/oracle_spec.rb +0 -222
  48. data/spec/adapters/postgres_spec.rb +0 -441
  49. data/spec/adapters/sqlite_spec.rb +0 -413
  50. data/spec/connection_pool_spec.rb +0 -363
  51. data/spec/core_ext_spec.rb +0 -156
  52. data/spec/core_sql_spec.rb +0 -427
  53. data/spec/database_spec.rb +0 -963
  54. data/spec/dataset_spec.rb +0 -2933
  55. data/spec/expression_filters_spec.rb +0 -316
  56. data/spec/migration_spec.rb +0 -261
  57. data/spec/object_graph_spec.rb +0 -230
  58. data/spec/pretty_table_spec.rb +0 -58
  59. data/spec/rcov.opts +0 -6
  60. data/spec/schema_generator_spec.rb +0 -122
  61. data/spec/schema_spec.rb +0 -422
  62. data/spec/spec.opts +0 -0
  63. data/spec/spec_config.rb +0 -7
  64. data/spec/spec_config.rb.example +0 -8
  65. data/spec/spec_helper.rb +0 -55
  66. data/spec/worker_spec.rb +0 -96
@@ -1,413 +0,0 @@
1
- require File.join(File.dirname(__FILE__), '../spec_helper.rb')
2
-
3
- unless defined?(SQLITE_DB)
4
- SQLITE_DB = Sequel.connect('sqlite:/')
5
- end
6
-
7
- SQLITE_DB.create_table :items do
8
- integer :id, :primary_key => true, :auto_increment => true
9
- text :name
10
- float :value
11
- end
12
- SQLITE_DB.create_table :test2 do
13
- text :name
14
- integer :value
15
- end
16
- SQLITE_DB.create_table(:time) {timestamp :t}
17
-
18
- context "An SQLite database" do
19
- before do
20
- @db = Sequel.connect('sqlite:/')
21
- end
22
- after do
23
- @db.disconnect
24
- end
25
-
26
- specify "should provide a list of existing tables" do
27
- @db.tables.should == []
28
-
29
- @db.create_table :testing do
30
- text :name
31
- end
32
- @db.tables.should include(:testing)
33
- end
34
-
35
- specify "should support getting pragma values" do
36
- @db.pragma_get(:auto_vacuum).should == '0'
37
- end
38
-
39
- specify "should support setting pragma values" do
40
- @db.pragma_set(:auto_vacuum, '1')
41
- @db.pragma_get(:auto_vacuum).should == '1'
42
- @db.pragma_set(:auto_vacuum, '2')
43
- @db.pragma_get(:auto_vacuum).should == '2'
44
- end
45
-
46
- specify "should support getting and setting the auto_vacuum pragma" do
47
- @db.auto_vacuum = :full
48
- @db.auto_vacuum.should == :full
49
- @db.auto_vacuum = :incremental
50
- @db.auto_vacuum.should == :incremental
51
-
52
- proc {@db.auto_vacuum = :invalid}.should raise_error(Sequel::Error)
53
- end
54
-
55
- specify "should support getting and setting the synchronous pragma" do
56
- @db.synchronous = :off
57
- @db.synchronous.should == :off
58
- @db.synchronous = :normal
59
- @db.synchronous.should == :normal
60
- @db.synchronous = :full
61
- @db.synchronous.should == :full
62
-
63
- proc {@db.synchronous = :invalid}.should raise_error(Sequel::Error)
64
- end
65
-
66
- specify "should support getting and setting the temp_store pragma" do
67
- @db.temp_store = :default
68
- @db.temp_store.should == :default
69
- @db.temp_store = :file
70
- @db.temp_store.should == :file
71
- @db.temp_store = :memory
72
- @db.temp_store.should == :memory
73
-
74
- proc {@db.temp_store = :invalid}.should raise_error(Sequel::Error)
75
- end
76
-
77
- specify "should be able to execute multiple statements at once" do
78
- @db.create_table :t do
79
- text :name
80
- end
81
-
82
- @db << "insert into t (name) values ('abc');insert into t (name) values ('def')"
83
-
84
- @db[:t].count.should == 2
85
-
86
- @db[:t].order(:name).map(:name).should == ['abc', 'def']
87
- end
88
-
89
- specify "should be able to execute transactions" do
90
- @db.transaction do
91
- @db.create_table(:t) {text :name}
92
- end
93
-
94
- @db.tables.should == [:t]
95
-
96
- proc {@db.transaction do
97
- @db.create_table(:u) {text :name}
98
- raise ArgumentError
99
- end}.should raise_error(ArgumentError)
100
- # no commit
101
- @db.tables.should == [:t]
102
-
103
- proc {@db.transaction do
104
- @db.create_table(:v) {text :name}
105
- raise Sequel::Error::Rollback
106
- end}.should_not raise_error
107
- # no commit
108
- @db.tables.should == [:t]
109
- end
110
-
111
- specify "should support nested transactions" do
112
- @db.transaction do
113
- @db.transaction do
114
- @db.create_table(:t) {text :name}
115
- end
116
- end
117
-
118
- @db.tables.should == [:t]
119
-
120
- proc {@db.transaction do
121
- @db.create_table(:v) {text :name}
122
- @db.transaction do
123
- raise Sequel::Error::Rollback # should roll back the top-level transaction
124
- end
125
- end}.should_not raise_error
126
- # no commit
127
- @db.tables.should == [:t]
128
- end
129
-
130
- specify "should handle returning inside of transaction by committing" do
131
- @db.create_table(:items){text :name}
132
- def @db.ret_commit
133
- transaction do
134
- self[:items] << {:name => 'abc'}
135
- return
136
- self[:items] << {:name => 'd'}
137
- end
138
- end
139
- @db[:items].count.should == 0
140
- @db.ret_commit
141
- @db[:items].count.should == 1
142
- @db.ret_commit
143
- @db[:items].count.should == 2
144
- proc do
145
- @db.transaction do
146
- raise Interrupt, 'asdf'
147
- end
148
- end.should raise_error(Interrupt)
149
-
150
- @db[:items].count.should == 2
151
- end
152
-
153
- specify "should provide disconnect functionality" do
154
- @db.tables
155
- @db.pool.size.should == 1
156
- @db.disconnect
157
- @db.pool.size.should == 0
158
- end
159
-
160
- specify "should support timestamps" do
161
- t1 = Time.at(Time.now.to_i) #normalize time
162
-
163
- SQLITE_DB[:time] << {:t => t1}
164
- SQLITE_DB[:time].first[:t].should == t1
165
- end
166
-
167
- specify "should support sequential primary keys" do
168
- @db.create_table!(:with_pk) {primary_key :id; text :name}
169
- @db[:with_pk] << {:name => 'abc'}
170
- @db[:with_pk] << {:name => 'def'}
171
- @db[:with_pk] << {:name => 'ghi'}
172
- @db[:with_pk].order(:name).all.should == [
173
- {:id => 1, :name => 'abc'},
174
- {:id => 2, :name => 'def'},
175
- {:id => 3, :name => 'ghi'}
176
- ]
177
- end
178
-
179
- specify "should catch invalid SQL errors and raise them as Error::InvalidStatement" do
180
- proc {@db.execute 'blah blah'}.should raise_error(
181
- Sequel::Error::InvalidStatement, "blah blah\r\nnear \"blah\": syntax error")
182
-
183
- proc {@db.execute_insert 'blah blah'}.should raise_error(
184
- Sequel::Error::InvalidStatement, "blah blah\r\nnear \"blah\": syntax error")
185
-
186
- proc {@db.execute_select 'blah blah'}.should raise_error(
187
- Sequel::Error::InvalidStatement, "blah blah\r\nnear \"blah\": syntax error")
188
-
189
- proc {@db.single_value 'blah blah'}.should raise_error(
190
- Sequel::Error::InvalidStatement, "blah blah\r\nnear \"blah\": syntax error")
191
- end
192
-
193
- specify "should not swallow non-SQLite based exceptions" do
194
- proc {@db.pool.hold{raise Interrupt, "test"}}.should raise_error(Interrupt)
195
- end
196
-
197
- specify "should correctly parse the schema" do
198
- @db.create_table(:time) {timestamp :t}
199
- @db.schema(:time, :reload=>true).should == [[:t, {:type=>:datetime, :allow_null=>true, :max_chars=>nil, :default=>nil, :db_type=>"timestamp", :numeric_precision=>nil, :primary_key=>false}]]
200
- end
201
-
202
- specify "should get the schema all database tables if no table name is used" do
203
- @db.create_table(:time) {timestamp :t}
204
- @db.schema(:time, :reload=>true).should == @db.schema(nil, :reload=>true)[:time]
205
- end
206
- end
207
-
208
- context "An SQLite dataset" do
209
- setup do
210
- @d = SQLITE_DB[:items]
211
- @d.delete # remove all records
212
- end
213
-
214
- specify "should return the correct records" do
215
- @d.to_a.should == []
216
- @d << {:name => 'abc', :value => 1.23}
217
- @d << {:name => 'abc', :value => 4.56}
218
- @d << {:name => 'def', :value => 7.89}
219
- @d.select(:name, :value).to_a.sort_by {|h| h[:value]}.should == [
220
- {:name => 'abc', :value => 1.23},
221
- {:name => 'abc', :value => 4.56},
222
- {:name => 'def', :value => 7.89}
223
- ]
224
- end
225
-
226
- specify "should return the correct record count" do
227
- @d.count.should == 0
228
- @d << {:name => 'abc', :value => 1.23}
229
- @d << {:name => 'abc', :value => 4.56}
230
- @d << {:name => 'def', :value => 7.89}
231
- @d.count.should == 3
232
- end
233
-
234
- specify "should return the last inserted id when inserting records" do
235
- id = @d << {:name => 'abc', :value => 1.23}
236
- id.should == @d.first[:id]
237
- end
238
-
239
- specify "should update records correctly" do
240
- @d << {:name => 'abc', :value => 1.23}
241
- @d << {:name => 'abc', :value => 4.56}
242
- @d << {:name => 'def', :value => 7.89}
243
- @d.filter(:name => 'abc').update(:value => 5.3)
244
-
245
- # the third record should stay the same
246
- @d[:name => 'def'][:value].should == 7.89
247
- @d.filter(:value => 5.3).count.should == 2
248
- end
249
-
250
- specify "should delete records correctly" do
251
- @d << {:name => 'abc', :value => 1.23}
252
- @d << {:name => 'abc', :value => 4.56}
253
- @d << {:name => 'def', :value => 7.89}
254
- @d.filter(:name => 'abc').delete
255
-
256
- @d.count.should == 1
257
- @d.first[:name].should == 'def'
258
- end
259
-
260
- specify "should handle string pattern matches correctly" do
261
- @d.literal(:x.like('a')).should == "(x LIKE 'a')"
262
- @d.literal(~:x.like('a')).should == "NOT (x LIKE 'a')"
263
- @d.literal(:x.ilike('a')).should == "(x LIKE 'a')"
264
- @d.literal(~:x.ilike('a')).should == "NOT (x LIKE 'a')"
265
- end
266
-
267
- specify "should raise errors if given a regexp pattern match" do
268
- proc{@d.literal(:x.like(/a/))}.should raise_error(Sequel::Error)
269
- proc{@d.literal(~:x.like(/a/))}.should raise_error(Sequel::Error)
270
- proc{@d.literal(:x.like(/a/i))}.should raise_error(Sequel::Error)
271
- proc{@d.literal(~:x.like(/a/i))}.should raise_error(Sequel::Error)
272
- end
273
- end
274
-
275
- context "An SQLite dataset" do
276
- setup do
277
- @d = SQLITE_DB[:items]
278
- @d.delete # remove all records
279
- @d << {:name => 'abc', :value => 1.23}
280
- @d << {:name => 'def', :value => 4.56}
281
- @d << {:name => 'ghi', :value => 7.89}
282
- end
283
-
284
- specify "should correctly return avg" do
285
- @d.avg(:value).should == ((1.23 + 4.56 + 7.89) / 3).to_s
286
- end
287
-
288
- specify "should correctly return sum" do
289
- @d.sum(:value).should == (1.23 + 4.56 + 7.89).to_s
290
- end
291
-
292
- specify "should correctly return max" do
293
- @d.max(:value).should == 7.89.to_s
294
- end
295
-
296
- specify "should correctly return min" do
297
- @d.min(:value).should == 1.23.to_s
298
- end
299
- end
300
-
301
- context "SQLite::Dataset#delete" do
302
- setup do
303
- @d = SQLITE_DB[:items]
304
- @d.delete # remove all records
305
- @d << {:name => 'abc', :value => 1.23}
306
- @d << {:name => 'def', :value => 4.56}
307
- @d << {:name => 'ghi', :value => 7.89}
308
- end
309
-
310
- specify "should return the number of records affected when filtered" do
311
- @d.count.should == 3
312
- @d.filter {:value < 3}.delete.should == 1
313
- @d.count.should == 2
314
-
315
- @d.filter {:value < 3}.delete.should == 0
316
- @d.count.should == 2
317
- end
318
-
319
- specify "should return the number of records affected when unfiltered" do
320
- @d.count.should == 3
321
- @d.delete.should == 3
322
- @d.count.should == 0
323
-
324
- @d.delete.should == 0
325
- end
326
- end
327
-
328
- context "SQLite::Dataset#update" do
329
- setup do
330
- @d = SQLITE_DB[:items]
331
- @d.delete # remove all records
332
- @d << {:name => 'abc', :value => 1.23}
333
- @d << {:name => 'def', :value => 4.56}
334
- @d << {:name => 'ghi', :value => 7.89}
335
- end
336
-
337
- specify "should return the number of records affected" do
338
- @d.filter(:name => 'abc').update(:value => 2).should == 1
339
-
340
- @d.update(:value => 10).should == 3
341
-
342
- @d.filter(:name => 'xxx').update(:value => 23).should == 0
343
- end
344
- end
345
-
346
- context "SQLite dataset" do
347
- setup do
348
- SQLITE_DB.create_table :test do
349
- integer :id, :primary_key => true, :auto_increment => true
350
- text :name
351
- float :value
352
- end
353
-
354
- @d = SQLITE_DB[:items]
355
- @d.delete # remove all records
356
- @d << {:name => 'abc', :value => 1.23}
357
- @d << {:name => 'def', :value => 4.56}
358
- @d << {:name => 'ghi', :value => 7.89}
359
- end
360
-
361
- teardown do
362
- SQLITE_DB.drop_table :test
363
- end
364
-
365
- specify "should be able to insert from a subquery" do
366
- SQLITE_DB[:test] << @d
367
- SQLITE_DB[:test].count.should == 3
368
- SQLITE_DB[:test].select(:name, :value).order(:value).to_a.should == \
369
- @d.select(:name, :value).order(:value).to_a
370
- end
371
- end
372
-
373
- context "A SQLite database" do
374
- setup do
375
- @db = SQLITE_DB
376
- @db.create_table! :test2 do
377
- text :name
378
- integer :value
379
- end
380
- end
381
-
382
- specify "should support add_column operations" do
383
- @db.add_column :test2, :xyz, :text
384
-
385
- @db[:test2].columns.should == [:name, :value, :xyz]
386
- @db[:test2] << {:name => 'mmm', :value => 111, :xyz=>'000'}
387
- @db[:test2].first.should == {:name => 'mmm', :value => 111, :xyz=>'000'}
388
- end
389
-
390
- specify "should support drop_column operations" do
391
- @db.drop_column :test2, :value
392
- @db[:test2].columns.should == [:name]
393
- @db[:test2] << {:name => 'mmm'}
394
- @db[:test2].first.should == {:name => 'mmm'}
395
- end
396
-
397
- specify "should not support rename_column operations" do
398
- proc {@db.rename_column :test2, :value, :zyx}.should raise_error(Sequel::Error)
399
- end
400
-
401
- specify "should not support set_column_type operations" do
402
- proc {@db.set_column_type :test2, :value, :integer}.should raise_error(Sequel::Error)
403
- end
404
-
405
- specify "should support add_index" do
406
- @db.add_index :test2, :value, :unique => true
407
- @db.add_index :test2, [:name, :value]
408
- end
409
-
410
- specify "should not support drop_index" do
411
- proc {@db.drop_index :test2, :value}.should raise_error(Sequel::Error)
412
- end
413
- end
@@ -1,363 +0,0 @@
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(: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).should == :got_connection
60
- @cpool.send(:make_new).should == :got_connection
61
- @cpool.send(:make_new).should == nil
62
- @cpool.created_count.should == 2
63
- end
64
- end
65
-
66
- class DummyConnection
67
- @@value = 0
68
- def initialize
69
- @@value += 1
70
- end
71
-
72
- def value
73
- @@value
74
- end
75
- end
76
-
77
- context "ConnectionPool#hold" do
78
- setup do
79
- @pool = Sequel::ConnectionPool.new(CONNECTION_POOL_DEFAULTS) {DummyConnection.new}
80
- end
81
-
82
- specify "should pass the result of the connection maker proc to the supplied block" do
83
- res = nil
84
- @pool.hold {|c| res = c}
85
- res.should be_a_kind_of(DummyConnection)
86
- res.value.should == 1
87
- @pool.hold {|c| res = c}
88
- res.should be_a_kind_of(DummyConnection)
89
- res.value.should == 1 # the connection maker is invoked only once
90
- end
91
-
92
- specify "should be re-entrant by the same thread" do
93
- cc = nil
94
- @pool.hold {|c| @pool.hold {|c| @pool.hold {|c| cc = c}}}
95
- cc.should be_a_kind_of(DummyConnection)
96
- end
97
-
98
- specify "should catch exceptions and reraise them" do
99
- proc {@pool.hold {|c| c.foobar}}.should raise_error(NoMethodError)
100
- end
101
-
102
- specify "should handle Exception errors (normally not caught by rescue)" do
103
- err = nil
104
- begin
105
- @pool.hold {raise Exception}
106
- rescue => e
107
- err = e
108
- end
109
- err.should be_a_kind_of(RuntimeError)
110
- end
111
- end
112
-
113
- context "ConnectionPool#connection_proc" do
114
- setup do
115
- @pool = Sequel::ConnectionPool.new(CONNECTION_POOL_DEFAULTS)
116
- end
117
-
118
- specify "should be nil if no block is supplied to the pool" do
119
- @pool.connection_proc.should be_nil
120
- proc {@pool.hold {}}.should raise_error
121
- end
122
-
123
- specify "should be mutable" do
124
- @pool.connection_proc = proc {'herro'}
125
- res = nil
126
- proc {@pool.hold {|c| res = c}}.should_not raise_error
127
- res.should == 'herro'
128
- end
129
- end
130
-
131
- context "A connection pool with a max size of 1" do
132
- setup do
133
- @invoked_count = 0
134
- @pool = Sequel::ConnectionPool.new(CONNECTION_POOL_DEFAULTS.merge(:max_connections=>1)) {@invoked_count += 1; 'herro'}
135
- end
136
-
137
- specify "should let only one thread access the connection at any time" do
138
- cc,c1, c2 = nil
139
-
140
- t1 = Thread.new {@pool.hold {|c| cc = c; c1 = c.dup; while c == 'herro';sleep 0.1;end}}
141
- sleep 0.2
142
- cc.should == 'herro'
143
- c1.should == 'herro'
144
-
145
- t2 = Thread.new {@pool.hold {|c| c2 = c.dup; while c == 'hello';sleep 0.1;end}}
146
- sleep 0.2
147
-
148
- # connection held by t1
149
- t1.should be_alive
150
- t2.should be_alive
151
-
152
- cc.should == 'herro'
153
- c1.should == 'herro'
154
- c2.should be_nil
155
-
156
- @pool.available_connections.should be_empty
157
- @pool.allocated.should == {t1=>cc}
158
-
159
- cc.gsub!('rr', 'll')
160
- sleep 0.5
161
-
162
- # connection held by t2
163
- t1.should_not be_alive
164
- t2.should be_alive
165
-
166
- c2.should == 'hello'
167
-
168
- @pool.available_connections.should be_empty
169
- @pool.allocated.should == {t2=>cc}
170
-
171
- cc.gsub!('ll', 'rr')
172
- sleep 0.5
173
-
174
- #connection released
175
- t2.should_not be_alive
176
-
177
- cc.should == 'herro'
178
-
179
- @invoked_count.should == 1
180
- @pool.size.should == 1
181
- @pool.available_connections.should == [cc]
182
- @pool.allocated.should be_empty
183
- end
184
-
185
- specify "should let the same thread reenter #hold" do
186
- c1, c2, c3 = nil
187
- @pool.hold do |c|
188
- c1 = c
189
- @pool.hold do |c|
190
- c2 = c
191
- @pool.hold do |c|
192
- c3 = c
193
- end
194
- end
195
- end
196
- c1.should == 'herro'
197
- c2.should == 'herro'
198
- c3.should == 'herro'
199
-
200
- @invoked_count.should == 1
201
- @pool.size.should == 1
202
- @pool.available_connections.size.should == 1
203
- @pool.allocated.should be_empty
204
- end
205
- end
206
-
207
- context "A connection pool with a max size of 5" do
208
- setup do
209
- @invoked_count = 0
210
- @pool = Sequel::ConnectionPool.new(CONNECTION_POOL_DEFAULTS.merge(:max_connections=>5)) {@invoked_count += 1}
211
- end
212
-
213
- specify "should let five threads simultaneously access separate connections" do
214
- cc = {}
215
- threads = []
216
- stop = nil
217
-
218
- 5.times {|i| threads << Thread.new {@pool.hold {|c| cc[i] = c; while !stop;sleep 0.1;end}}; sleep 0.1}
219
- sleep 0.2
220
- threads.each {|t| t.should be_alive}
221
- cc.size.should == 5
222
- @invoked_count.should == 5
223
- @pool.size.should == 5
224
- @pool.available_connections.should be_empty
225
- i = 0
226
- h = {}
227
- threads.each{|t| h[t] = (i+=1)}
228
- @pool.allocated.should == h
229
-
230
- threads[0].raise "your'e dead"
231
- sleep 0.1
232
- threads[3].raise "your'e dead too"
233
-
234
- sleep 0.1
235
-
236
- @pool.available_connections.should == [1, 4]
237
- @pool.allocated.should == {threads[1]=>2, threads[2]=>3, threads[4]=>5}
238
-
239
- stop = true
240
- sleep 0.2
241
-
242
- @pool.available_connections.size.should == 5
243
- @pool.allocated.should be_empty
244
- end
245
-
246
- specify "should block threads until a connection becomes available" do
247
- cc = {}
248
- threads = []
249
- stop = nil
250
-
251
- 5.times {|i| threads << Thread.new {@pool.hold {|c| cc[i] = c; while !stop;sleep 0.1;end}}; sleep 0.1}
252
- sleep 0.2
253
- threads.each {|t| t.should be_alive}
254
- @pool.available_connections.should be_empty
255
-
256
- 3.times {|i| threads << Thread.new {@pool.hold {|c| cc[i + 5] = c}}}
257
-
258
- sleep 0.2
259
- threads[5].should be_alive
260
- threads[6].should be_alive
261
- threads[7].should be_alive
262
- cc.size.should == 5
263
- cc[5].should be_nil
264
- cc[6].should be_nil
265
- cc[7].should be_nil
266
-
267
- stop = true
268
- sleep 0.3
269
-
270
- threads.each {|t| t.should_not be_alive}
271
-
272
- @pool.size.should == 5
273
- @invoked_count.should == 5
274
- @pool.available_connections.size.should == 5
275
- @pool.allocated.should be_empty
276
- end
277
- end
278
-
279
- context "ConnectionPool#disconnect" do
280
- setup do
281
- @count = 0
282
- @pool = Sequel::ConnectionPool.new(CONNECTION_POOL_DEFAULTS.merge(:max_connections=>5)) {{:id => @count += 1}}
283
- end
284
-
285
- specify "should invoke the given block for each available connection" do
286
- threads = []
287
- stop = nil
288
- 5.times {|i| threads << Thread.new {@pool.hold {|c| while !stop;sleep 0.1;end}}; sleep 0.1}
289
- while @pool.size < 5
290
- sleep 0.2
291
- end
292
- stop = true
293
- sleep 1
294
- threads.each {|t| t.join}
295
-
296
- @pool.size.should == 5
297
- @pool.available_connections.size.should == 5
298
- @pool.available_connections.each {|c| c[:id].should_not be_nil}
299
- conns = []
300
- @pool.disconnect {|c| conns << c}
301
- conns.size.should == 5
302
- end
303
-
304
- specify "should remove all available connections" do
305
- threads = []
306
- stop = nil
307
- 5.times {|i| threads << Thread.new {@pool.hold {|c| while !stop;sleep 0.1;end}}; sleep 0.1}
308
- while @pool.size < 5
309
- sleep 0.2
310
- end
311
- stop = true
312
- sleep 1
313
- threads.each {|t| t.join}
314
-
315
- @pool.size.should == 5
316
- @pool.disconnect
317
- @pool.size.should == 0
318
- end
319
-
320
- specify "should not touch connections in use" do
321
- threads = []
322
- stop = nil
323
- 5.times {|i| threads << Thread.new {@pool.hold {|c| while !stop;sleep 0.1;end}}; sleep 0.1}
324
- while @pool.size < 5
325
- sleep 0.2
326
- end
327
- stop = true
328
- sleep 1
329
- threads.each {|t| t.join}
330
-
331
- @pool.size.should == 5
332
-
333
- @pool.hold do |conn|
334
- @pool.available_connections.size.should == 4
335
- @pool.available_connections.each {|c| c.should_not be(conn)}
336
- conns = []
337
- @pool.disconnect {|c| conns << c}
338
- conns.size.should == 4
339
- end
340
- @pool.size.should == 1
341
- end
342
- end
343
-
344
- context "SingleThreadedPool" do
345
- setup do
346
- @pool = Sequel::SingleThreadedPool.new(CONNECTION_POOL_DEFAULTS){1234}
347
- end
348
-
349
- specify "should provide a #hold method" do
350
- conn = nil
351
- @pool.hold {|c| conn = c}
352
- conn.should == 1234
353
- end
354
-
355
- specify "should provide a #disconnect method" do
356
- @pool.hold {|c|}
357
- @pool.conn.should == 1234
358
- conn = nil
359
- @pool.disconnect {|c| conn = c}
360
- conn.should == 1234
361
- @pool.conn.should be_nil
362
- end
363
- end