sequel_core 2.2.0 → 3.8.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.
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