sequel_core 1.5.1 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. data/CHANGELOG +116 -0
  2. data/COPYING +19 -19
  3. data/README +83 -32
  4. data/Rakefile +9 -20
  5. data/bin/sequel +43 -112
  6. data/doc/cheat_sheet.rdoc +225 -0
  7. data/doc/dataset_filtering.rdoc +257 -0
  8. data/lib/sequel_core/adapters/adapter_skeleton.rb +4 -2
  9. data/lib/sequel_core/adapters/ado.rb +3 -1
  10. data/lib/sequel_core/adapters/db2.rb +4 -2
  11. data/lib/sequel_core/adapters/dbi.rb +127 -113
  12. data/lib/sequel_core/adapters/informix.rb +4 -2
  13. data/lib/sequel_core/adapters/jdbc.rb +5 -3
  14. data/lib/sequel_core/adapters/mysql.rb +112 -46
  15. data/lib/sequel_core/adapters/odbc.rb +5 -7
  16. data/lib/sequel_core/adapters/odbc_mssql.rb +12 -3
  17. data/lib/sequel_core/adapters/openbase.rb +3 -1
  18. data/lib/sequel_core/adapters/oracle.rb +11 -9
  19. data/lib/sequel_core/adapters/postgres.rb +261 -262
  20. data/lib/sequel_core/adapters/sqlite.rb +72 -22
  21. data/lib/sequel_core/connection_pool.rb +140 -73
  22. data/lib/sequel_core/core_ext.rb +201 -66
  23. data/lib/sequel_core/core_sql.rb +123 -153
  24. data/lib/sequel_core/database/schema.rb +156 -0
  25. data/lib/sequel_core/database.rb +321 -338
  26. data/lib/sequel_core/dataset/callback.rb +11 -12
  27. data/lib/sequel_core/dataset/convenience.rb +213 -240
  28. data/lib/sequel_core/dataset/pagination.rb +58 -43
  29. data/lib/sequel_core/dataset/parse_tree_sequelizer.rb +331 -0
  30. data/lib/sequel_core/dataset/query.rb +41 -0
  31. data/lib/sequel_core/dataset/schema.rb +15 -0
  32. data/lib/sequel_core/dataset/sequelizer.rb +41 -373
  33. data/lib/sequel_core/dataset/sql.rb +741 -632
  34. data/lib/sequel_core/dataset.rb +183 -168
  35. data/lib/sequel_core/deprecated.rb +1 -169
  36. data/lib/sequel_core/exceptions.rb +24 -19
  37. data/lib/sequel_core/migration.rb +44 -52
  38. data/lib/sequel_core/object_graph.rb +43 -42
  39. data/lib/sequel_core/pretty_table.rb +71 -76
  40. data/lib/sequel_core/schema/generator.rb +163 -105
  41. data/lib/sequel_core/schema/sql.rb +250 -93
  42. data/lib/sequel_core/schema.rb +2 -8
  43. data/lib/sequel_core/sql.rb +394 -0
  44. data/lib/sequel_core/worker.rb +37 -27
  45. data/lib/sequel_core.rb +99 -45
  46. data/spec/adapters/informix_spec.rb +0 -1
  47. data/spec/adapters/mysql_spec.rb +177 -124
  48. data/spec/adapters/oracle_spec.rb +0 -1
  49. data/spec/adapters/postgres_spec.rb +98 -58
  50. data/spec/adapters/sqlite_spec.rb +45 -4
  51. data/spec/blockless_filters_spec.rb +269 -0
  52. data/spec/connection_pool_spec.rb +21 -18
  53. data/spec/core_ext_spec.rb +169 -19
  54. data/spec/core_sql_spec.rb +56 -49
  55. data/spec/database_spec.rb +78 -17
  56. data/spec/dataset_spec.rb +300 -428
  57. data/spec/migration_spec.rb +1 -1
  58. data/spec/object_graph_spec.rb +5 -11
  59. data/spec/rcov.opts +1 -1
  60. data/spec/schema_generator_spec.rb +16 -4
  61. data/spec/schema_spec.rb +89 -10
  62. data/spec/sequelizer_spec.rb +56 -56
  63. data/spec/spec.opts +0 -5
  64. data/spec/spec_config.rb +7 -0
  65. data/spec/spec_config.rb.example +5 -5
  66. data/spec/spec_helper.rb +6 -0
  67. data/spec/worker_spec.rb +1 -1
  68. metadata +78 -63
@@ -0,0 +1,269 @@
1
+ require File.join(File.dirname(__FILE__), 'spec_helper')
2
+
3
+ context "Blockless Ruby Filters" do
4
+ before do
5
+ db = Sequel::Database.new
6
+ db.quote_identifiers = false
7
+ @d = db[:items]
8
+ def @d.l(*args)
9
+ literal(filter_expr(*args))
10
+ end
11
+ end
12
+
13
+ it "should support boolean columns directly" do
14
+ @d.l(:x).should == 'x'
15
+ end
16
+
17
+ it "should support NOT via Symbol#~" do
18
+ @d.l(~:x).should == 'NOT x'
19
+ end
20
+
21
+ it "should support qualified columns" do
22
+ @d.l(:x__y).should == 'x.y'
23
+ @d.l(~:x__y).should == 'NOT x.y'
24
+ end
25
+
26
+ it "should support NOT with SQL functions" do
27
+ @d.l(~:is_blah[]).should == 'NOT is_blah()'
28
+ @d.l(~:is_blah[:x]).should == 'NOT is_blah(x)'
29
+ @d.l(~:is_blah[:x__y]).should == 'NOT is_blah(x.y)'
30
+ @d.l(~:is_blah[:x, :x__y]).should == 'NOT is_blah(x, x.y)'
31
+ end
32
+
33
+ it "should handle multiple ~" do
34
+ @d.l(~~:x).should == 'x'
35
+ @d.l(~~~:x).should == 'NOT x'
36
+ @d.l(~~(:x > 100)).should == '(x > 100)'
37
+ @d.l(~~(:x & :y)).should == '(x AND y)'
38
+ @d.l(~~(:x | :y)).should == '(x OR y)'
39
+ end
40
+
41
+ it "should support >, <, >=, and <= via Symbol#>,<,>=,<=" do
42
+ @d.l(:x > 100).should == '(x > 100)'
43
+ @d.l(:x < 100.01).should == '(x < 100.01)'
44
+ @d.l(:x >= 100000000000000000000000000000000000).should == '(x >= 100000000000000000000000000000000000)'
45
+ @d.l(:x <= 100).should == '(x <= 100)'
46
+ end
47
+
48
+ it "should support negation of >, <, >=, and <= via Symbol#~" do
49
+ @d.l(~(:x > 100)).should == '(x <= 100)'
50
+ @d.l(~(:x < 100.01)).should == '(x >= 100.01)'
51
+ @d.l(~(:x >= 100000000000000000000000000000000000)).should == '(x < 100000000000000000000000000000000000)'
52
+ @d.l(~(:x <= 100)).should == '(x > 100)'
53
+ end
54
+
55
+ it "should support = via Hash" do
56
+ @d.l(:x => 100).should == '(x = 100)'
57
+ @d.l(:x => 'a').should == '(x = \'a\')'
58
+ @d.l(:x => true).should == '(x = \'t\')'
59
+ @d.l(:x => false).should == '(x = \'f\')'
60
+ @d.l(:x => nil).should == '(x IS NULL)'
61
+ @d.l(:x => [1,2,3]).should == '(x IN (1, 2, 3))'
62
+ end
63
+
64
+ it "should support != via Hash#~" do
65
+ @d.l(~{:x => 100}).should == '(x != 100)'
66
+ @d.l(~{:x => 'a'}).should == '(x != \'a\')'
67
+ @d.l(~{:x => true}).should == '(x != \'t\')'
68
+ @d.l(~{:x => false}).should == '(x != \'f\')'
69
+ @d.l(~{:x => nil}).should == '(x IS NOT NULL)'
70
+ end
71
+
72
+ it "should support ~ via Hash and Regexp (if supported by database)" do
73
+ @d.l(:x => /blah/).should == '(x ~ \'blah\')'
74
+ end
75
+
76
+ it "should support !~ via Hash#~ and Regexp" do
77
+ @d.l(~{:x => /blah/}).should == '(x !~ \'blah\')'
78
+ end
79
+
80
+ it "should support LIKE via Symbol#like" do
81
+ @d.l(:x.like('a')).should == '(x LIKE \'a\')'
82
+ @d.l(:x.like(/a/)).should == '(x ~ \'a\')'
83
+ @d.l(:x.like('a', 'b')).should == '((x LIKE \'a\') OR (x LIKE \'b\'))'
84
+ @d.l(:x.like(/a/, /b/)).should == '((x ~ \'a\') OR (x ~ \'b\'))'
85
+ @d.l(:x.like('a', /b/)).should == '((x LIKE \'a\') OR (x ~ \'b\'))'
86
+ end
87
+
88
+ it "should support NOT LIKE via Symbol#like and Symbol#~" do
89
+ @d.l(~:x.like('a')).should == '(x NOT LIKE \'a\')'
90
+ @d.l(~:x.like(/a/)).should == '(x !~ \'a\')'
91
+ @d.l(~:x.like('a', 'b')).should == '((x NOT LIKE \'a\') AND (x NOT LIKE \'b\'))'
92
+ @d.l(~:x.like(/a/, /b/)).should == '((x !~ \'a\') AND (x !~ \'b\'))'
93
+ @d.l(~:x.like('a', /b/)).should == '((x NOT LIKE \'a\') AND (x !~ \'b\'))'
94
+ end
95
+
96
+ it "should support negating ranges via Hash#~ and Range" do
97
+ @d.l(~{:x => 1..5}).should == '((x < 1) OR (x > 5))'
98
+ @d.l(~{:x => 1...5}).should == '((x < 1) OR (x >= 5))'
99
+ end
100
+
101
+ it "should support negating NOT IN via Hash#~ and Dataset or Array" do
102
+ @d.l(~{:x => @d.select(:i)}).should == '(x NOT IN (SELECT i FROM items))'
103
+ @d.l(~{:x => [1,2,3]}).should == '(x NOT IN (1, 2, 3))'
104
+ end
105
+
106
+ it "should support + - * / via Symbol#+,-,*,/" do
107
+ @d.l(:x + 1 > 100).should == '((x + 1) > 100)'
108
+ @d.l((:x * :y) < 100.01).should == '((x * y) < 100.01)'
109
+ @d.l((:x - :y/2) >= 100000000000000000000000000000000000).should == '((x - (y / 2)) >= 100000000000000000000000000000000000)'
110
+ @d.l((((:x - :y)/(:x + :y))*:z) <= 100).should == '((((x - y) / (x + y)) * z) <= 100)'
111
+ @d.l(~((((:x - :y)/(:x + :y))*:z) <= 100)).should == '((((x - y) / (x + y)) * z) > 100)'
112
+ end
113
+
114
+ it "should not allow negation of non-boolean expressions" do
115
+ proc{~(:x + 1 > 100)}.should_not raise_error
116
+ proc{~(:x + 1)}.should raise_error(Sequel::Error)
117
+ end
118
+
119
+ it "should not allow mathematical, inequality, or string operations on true, false, or nil" do
120
+ proc{:x + 1}.should_not raise_error
121
+ proc{:x - true}.should raise_error(Sequel::Error)
122
+ proc{:x / false}.should raise_error(Sequel::Error)
123
+ proc{:x * nil}.should raise_error(Sequel::Error)
124
+ proc{:x > 1}.should_not raise_error
125
+ proc{:x < true}.should raise_error(Sequel::Error)
126
+ proc{:x >= false}.should raise_error(Sequel::Error)
127
+ proc{:x <= nil}.should raise_error(Sequel::Error)
128
+ proc{[:x, nil].sql_string_join}.should raise_error(Sequel::Error)
129
+ end
130
+
131
+ it "should not allow mathematical, inequality, or string operations on boolean complex expressions" do
132
+ proc{:x + (:y + 1)}.should_not raise_error
133
+ proc{:x - (~:y)}.should raise_error(Sequel::Error)
134
+ proc{:x / (:y & :z)}.should raise_error(Sequel::Error)
135
+ proc{:x * (:y | :z)}.should raise_error(Sequel::Error)
136
+ proc{:x > (:y > 5)}.should raise_error(Sequel::Error)
137
+ proc{:x < (:y < 5)}.should raise_error(Sequel::Error)
138
+ proc{:x >= (:y >= 5)}.should raise_error(Sequel::Error)
139
+ proc{:x <= (:y <= 5)}.should raise_error(Sequel::Error)
140
+ proc{:x > {:y => nil}}.should raise_error(Sequel::Error)
141
+ proc{:x < ~{:y => nil}}.should raise_error(Sequel::Error)
142
+ proc{:x >= {:y => 5}}.should raise_error(Sequel::Error)
143
+ proc{:x <= ~{:y => 5}}.should raise_error(Sequel::Error)
144
+ proc{:x >= {:y => [1,2,3]}}.should raise_error(Sequel::Error)
145
+ proc{:x <= ~{:y => [1,2,3]}}.should raise_error(Sequel::Error)
146
+ proc{:x + :y.like('a')}.should raise_error(Sequel::Error)
147
+ proc{:x - :y.like(/a/)}.should raise_error(Sequel::Error)
148
+ proc{:x * :y.like(/a/i)}.should raise_error(Sequel::Error)
149
+ proc{:x + ~:y.like('a')}.should raise_error(Sequel::Error)
150
+ proc{:x - ~:y.like(/a/)}.should raise_error(Sequel::Error)
151
+ proc{:x * ~:y.like(/a/i)}.should raise_error(Sequel::Error)
152
+ proc{[:x, ~:y.like(/a/i)].sql_string_join}.should raise_error(Sequel::Error)
153
+ end
154
+
155
+ it "should support AND conditions via &" do
156
+ @d.l(:x & :y).should == '(x AND y)'
157
+ @d.l(:x & :y & :z).should == '((x AND y) AND z)'
158
+ @d.l(:x & {:y => :z}).should == '(x AND (y = z))'
159
+ @d.l({:y => :z} & :x).should == '((y = z) AND x)'
160
+ @d.l({:x => :a} & {:y => :z}).should == '((x = a) AND (y = z))'
161
+ @d.l((:x > 200) & (:y < 200)).should == '((x > 200) AND (y < 200))'
162
+ @d.l(:x & ~:y).should == '(x AND NOT y)'
163
+ @d.l(~:x & :y).should == '(NOT x AND y)'
164
+ @d.l(~:x & ~:y).should == '(NOT x AND NOT y)'
165
+ end
166
+
167
+ it "should support OR conditions via |" do
168
+ @d.l(:x | :y).should == '(x OR y)'
169
+ @d.l(:x | :y | :z).should == '((x OR y) OR z)'
170
+ @d.l(:x | {:y => :z}).should == '(x OR (y = z))'
171
+ @d.l({:y => :z} | :x).should == '((y = z) OR x)'
172
+ @d.l({:x => :a} | {:y => :z}).should == '((x = a) OR (y = z))'
173
+ @d.l((:x > 200) | (:y < 200)).should == '((x > 200) OR (y < 200))'
174
+ end
175
+
176
+ it "should support & | combinations" do
177
+ @d.l((:x | :y) & :z).should == '((x OR y) AND z)'
178
+ @d.l(:x | (:y & :z)).should == '(x OR (y AND z))'
179
+ @d.l((:x & :w) | (:y & :z)).should == '((x AND w) OR (y AND z))'
180
+ end
181
+
182
+ it "should support & | with ~" do
183
+ @d.l(~((:x | :y) & :z)).should == '((NOT x AND NOT y) OR NOT z)'
184
+ @d.l(~(:x | (:y & :z))).should == '(NOT x AND (NOT y OR NOT z))'
185
+ @d.l(~((:x & :w) | (:y & :z))).should == '((NOT x OR NOT w) AND (NOT y OR NOT z))'
186
+ @d.l(~((:x > 200) | (:y & :z))).should == '((x <= 200) AND (NOT y OR NOT z))'
187
+ end
188
+
189
+ it "should support LiteralString" do
190
+ @d.l('x'.lit).should == '(x)'
191
+ @d.l(~'x'.lit).should == 'NOT x'
192
+ @d.l(~~'x'.lit).should == '(x)'
193
+ @d.l(~(('x'.lit | :y) & :z)).should == '((NOT x AND NOT y) OR NOT z)'
194
+ @d.l(~(:x | 'y'.lit)).should == '(NOT x AND NOT y)'
195
+ @d.l(~('x'.lit & 'y'.lit)).should == '(NOT x OR NOT y)'
196
+ @d.l({'y'.lit => 'z'.lit} & 'x'.lit).should == '((y = z) AND x)'
197
+ @d.l(('x'.lit > 200) & ('y'.lit < 200)).should == '((x > 200) AND (y < 200))'
198
+ @d.l(~('x'.lit + 1 > 100)).should == '((x + 1) <= 100)'
199
+ @d.l('x'.lit.like(/a/)).should == '(x ~ \'a\')'
200
+ @d.l('x'.lit + 1 > 100).should == '((x + 1) > 100)'
201
+ @d.l(('x'.lit * :y) < 100.01).should == '((x * y) < 100.01)'
202
+ @d.l(('x'.lit - :y/2) >= 100000000000000000000000000000000000).should == '((x - (y / 2)) >= 100000000000000000000000000000000000)'
203
+ @d.l(('z'.lit * (('x'.lit / :y)/(:x + :y))) <= 100).should == '((z * ((x / y) / (x + y))) <= 100)'
204
+ @d.l(~(((('x'.lit - :y)/(:x + :y))*:z) <= 100)).should == '((((x - y) / (x + y)) * z) > 100)'
205
+ end
206
+
207
+ it "should support hashes by ANDing the conditions" do
208
+ @d.l(:x => 100, :y => 'a')[1...-1].split(' AND ').sort.should == ['(x = 100)', '(y = \'a\')']
209
+ @d.l(:x => true, :y => false)[1...-1].split(' AND ').sort.should == ['(x = \'t\')', '(y = \'f\')']
210
+ @d.l(:x => nil, :y => [1,2,3])[1...-1].split(' AND ').sort.should == ['(x IS NULL)', '(y IN (1, 2, 3))']
211
+ end
212
+
213
+ it "should support sql_negate on hashes" do
214
+ @d.l({:x => 100, :y => 'a'}.sql_negate)[1...-1].split(' AND ').sort.should == ['(x != 100)', '(y != \'a\')']
215
+ @d.l({:x => true, :y => false}.sql_negate)[1...-1].split(' AND ').sort.should == ['(x != \'t\')', '(y != \'f\')']
216
+ @d.l({:x => nil, :y => [1,2,3]}.sql_negate)[1...-1].split(' AND ').sort.should == ['(x IS NOT NULL)', '(y NOT IN (1, 2, 3))']
217
+ end
218
+
219
+ it "should support ~ on hashes" do
220
+ @d.l(~{:x => 100, :y => 'a'})[1...-1].split(' OR ').sort.should == ['(x != 100)', '(y != \'a\')']
221
+ @d.l(~{:x => true, :y => false})[1...-1].split(' OR ').sort.should == ['(x != \'t\')', '(y != \'f\')']
222
+ @d.l(~{:x => nil, :y => [1,2,3]})[1...-1].split(' OR ').sort.should == ['(x IS NOT NULL)', '(y NOT IN (1, 2, 3))']
223
+ end
224
+
225
+ it "should support sql_or on hashes" do
226
+ @d.l({:x => 100, :y => 'a'}.sql_or)[1...-1].split(' OR ').sort.should == ['(x = 100)', '(y = \'a\')']
227
+ @d.l({:x => true, :y => false}.sql_or)[1...-1].split(' OR ').sort.should == ['(x = \'t\')', '(y = \'f\')']
228
+ @d.l({:x => nil, :y => [1,2,3]}.sql_or)[1...-1].split(' OR ').sort.should == ['(x IS NULL)', '(y IN (1, 2, 3))']
229
+ end
230
+
231
+ it "should support arrays with all two pairs the same as hashes" do
232
+ @d.l([[:x, 100],[:y, 'a']]).should == '((x = 100) AND (y = \'a\'))'
233
+ @d.l([[:x, true], [:y, false]]).should == '((x = \'t\') AND (y = \'f\'))'
234
+ @d.l([[:x, nil], [:y, [1,2,3]]]).should == '((x IS NULL) AND (y IN (1, 2, 3)))'
235
+ end
236
+
237
+ it "should support sql_negate on arrays with all two pairs" do
238
+ @d.l([[:x, 100],[:y, 'a']].sql_negate).should == '((x != 100) AND (y != \'a\'))'
239
+ @d.l([[:x, true], [:y, false]].sql_negate).should == '((x != \'t\') AND (y != \'f\'))'
240
+ @d.l([[:x, nil], [:y, [1,2,3]]].sql_negate).should == '((x IS NOT NULL) AND (y NOT IN (1, 2, 3)))'
241
+ end
242
+
243
+ it "should support ~ on arrays with all two pairs" do
244
+ @d.l(~[[:x, 100],[:y, 'a']]).should == '((x != 100) OR (y != \'a\'))'
245
+ @d.l(~[[:x, true], [:y, false]]).should == '((x != \'t\') OR (y != \'f\'))'
246
+ @d.l(~[[:x, nil], [:y, [1,2,3]]]).should == '((x IS NOT NULL) OR (y NOT IN (1, 2, 3)))'
247
+ end
248
+
249
+ it "should support sql_or on arrays with all two pairs" do
250
+ @d.l([[:x, 100],[:y, 'a']].sql_or).should == '((x = 100) OR (y = \'a\'))'
251
+ @d.l([[:x, true], [:y, false]].sql_or).should == '((x = \'t\') OR (y = \'f\'))'
252
+ @d.l([[:x, nil], [:y, [1,2,3]]].sql_or).should == '((x IS NULL) OR (y IN (1, 2, 3)))'
253
+ end
254
+
255
+ it "should support Array#sql_string_join for concatenation of SQL strings" do
256
+ @d.l([:x].sql_string_join).should == '(x)'
257
+ @d.l([:x].sql_string_join(', ')).should == '(x)'
258
+ @d.l([:x, :y].sql_string_join).should == '(x || y)'
259
+ @d.l([:x, :y].sql_string_join(', ')).should == "(x || ', ' || y)"
260
+ @d.l([:x[1], :y|1].sql_string_join).should == '(x(1) || y[1])'
261
+ @d.l([:x[1], 'y.z'.lit].sql_string_join(', ')).should == "(x(1) || ', ' || y.z)"
262
+ @d.l([:x, 1, :y].sql_string_join).should == "(x || '1' || y)"
263
+ @d.l([:x, 1, :y].sql_string_join(', ')).should == "(x || ', ' || '1' || ', ' || y)"
264
+ @d.l([:x, 1, :y].sql_string_join(:y__z)).should == "(x || y.z || '1' || y.z || y)"
265
+ @d.l([:x, 1, :y].sql_string_join(1)).should == "(x || '1' || '1' || '1' || y)"
266
+ @d.l([:x, :y].sql_string_join('y.x || x.y'.lit)).should == "(x || y.x || x.y || y)"
267
+ @d.l([[:x, :y].sql_string_join, [:a, :b].sql_string_join].sql_string_join).should == "((x || y) || (a || b))"
268
+ end
269
+ end
@@ -1,8 +1,10 @@
1
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}
2
4
 
3
5
  context "An empty ConnectionPool" do
4
6
  setup do
5
- @cpool = ConnectionPool.new
7
+ @cpool = ConnectionPool.new(CONNECTION_POOL_DEFAULTS)
6
8
  end
7
9
 
8
10
  specify "should have no available connections" do
@@ -10,7 +12,7 @@ context "An empty ConnectionPool" do
10
12
  end
11
13
 
12
14
  specify "should have no allocated connections" do
13
- @cpool.allocated.should == {}
15
+ @cpool.allocated.should == []
14
16
  end
15
17
 
16
18
  specify "should have a created_count of zero" do
@@ -21,21 +23,22 @@ end
21
23
  context "A connection pool handling connections" do
22
24
  setup do
23
25
  @max_size = 2
24
- @cpool = ConnectionPool.new(@max_size) {:got_connection}
26
+ @cpool = ConnectionPool.new(CONNECTION_POOL_DEFAULTS.merge(:max_connections=>@max_size)) {:got_connection}
25
27
  end
26
28
 
27
29
  specify "#hold should increment #created_count" do
28
30
  @cpool.hold do
29
31
  @cpool.created_count.should == 1
30
- @cpool.hold {@cpool.created_count.should == 1}
32
+ @cpool.hold {@cpool.created_count.should == 2}
33
+ @cpool.hold {@cpool.hold {@cpool.created_count.should == 2}}
31
34
  end
32
35
  end
33
36
 
34
- specify "#hold should add the connection to the #allocated hash" do
37
+ specify "#hold should add the connection to the #allocated array" do
35
38
  @cpool.hold do
36
39
  @cpool.allocated.size.should == 1
37
40
 
38
- @cpool.allocated.values.should == [:got_connection]
41
+ @cpool.allocated.should == [[Thread.current, :got_connection]]
39
42
  end
40
43
  end
41
44
 
@@ -73,7 +76,7 @@ end
73
76
 
74
77
  context "ConnectionPool#hold" do
75
78
  setup do
76
- @pool = ConnectionPool.new {DummyConnection.new}
79
+ @pool = ConnectionPool.new(CONNECTION_POOL_DEFAULTS) {DummyConnection.new}
77
80
  end
78
81
 
79
82
  specify "should pass the result of the connection maker proc to the supplied block" do
@@ -109,7 +112,7 @@ end
109
112
 
110
113
  context "ConnectionPool#connection_proc" do
111
114
  setup do
112
- @pool = ConnectionPool.new
115
+ @pool = ConnectionPool.new(CONNECTION_POOL_DEFAULTS)
113
116
  end
114
117
 
115
118
  specify "should be nil if no block is supplied to the pool" do
@@ -128,7 +131,7 @@ end
128
131
  context "A connection pool with a max size of 1" do
129
132
  setup do
130
133
  @invoked_count = 0
131
- @pool = ConnectionPool.new(1) {@invoked_count += 1; 'herro'}
134
+ @pool = ConnectionPool.new(CONNECTION_POOL_DEFAULTS.merge(:max_connections=>1)) {@invoked_count += 1; 'herro'}
132
135
  end
133
136
 
134
137
  specify "should let only one thread access the connection at any time" do
@@ -151,7 +154,7 @@ context "A connection pool with a max size of 1" do
151
154
  c2.should be_nil
152
155
 
153
156
  @pool.available_connections.should be_empty
154
- @pool.allocated.should == {t1 => cc}
157
+ @pool.allocated.should == [[t1, cc]]
155
158
 
156
159
  cc.gsub!('rr', 'll')
157
160
  sleep 0.5
@@ -163,7 +166,7 @@ context "A connection pool with a max size of 1" do
163
166
  c2.should == 'hello'
164
167
 
165
168
  @pool.available_connections.should be_empty
166
- @pool.allocated.should == {t2 => cc}
169
+ @pool.allocated.should == [[t2, cc]]
167
170
 
168
171
  cc.gsub!('ll', 'rr')
169
172
  sleep 0.5
@@ -204,7 +207,7 @@ end
204
207
  context "A connection pool with a max size of 5" do
205
208
  setup do
206
209
  @invoked_count = 0
207
- @pool = ConnectionPool.new(5) {@invoked_count += 1}
210
+ @pool = ConnectionPool.new(CONNECTION_POOL_DEFAULTS.merge(:max_connections=>5)) {@invoked_count += 1}
208
211
  end
209
212
 
210
213
  specify "should let five threads simultaneously access separate connections" do
@@ -219,8 +222,8 @@ context "A connection pool with a max size of 5" do
219
222
  @invoked_count.should == 5
220
223
  @pool.size.should == 5
221
224
  @pool.available_connections.should be_empty
222
- @pool.allocated.should == {threads[0] => 1, threads[1] => 2, threads[2] => 3,
223
- threads[3] => 4, threads[4] => 5}
225
+ i = 0
226
+ @pool.allocated.should == threads.collect{|t| [t,i+=1]}
224
227
 
225
228
  threads[0].raise "your'e dead"
226
229
  sleep 0.1
@@ -229,7 +232,7 @@ context "A connection pool with a max size of 5" do
229
232
  sleep 0.1
230
233
 
231
234
  @pool.available_connections.should == [1, 4]
232
- @pool.allocated.should == {threads[1] => 2, threads[2] => 3, threads[4] => 5}
235
+ @pool.allocated.should == [[threads[1], 2], [threads[2], 3], [threads[4], 5]]
233
236
 
234
237
  stop = true
235
238
  sleep 0.2
@@ -274,7 +277,7 @@ end
274
277
  context "ConnectionPool#disconnect" do
275
278
  setup do
276
279
  @count = 0
277
- @pool = ConnectionPool.new(5) {{:id => @count += 1}}
280
+ @pool = ConnectionPool.new(CONNECTION_POOL_DEFAULTS.merge(:max_connections=>5)) {{:id => @count += 1}}
278
281
  end
279
282
 
280
283
  specify "should invoke the given block for each available connection" do
@@ -338,7 +341,7 @@ end
338
341
 
339
342
  context "SingleThreadedPool" do
340
343
  setup do
341
- @pool = SingleThreadedPool.new {1234}
344
+ @pool = SingleThreadedPool.new(CONNECTION_POOL_DEFAULTS){1234}
342
345
  end
343
346
 
344
347
  specify "should provide a #hold method" do
@@ -355,4 +358,4 @@ context "SingleThreadedPool" do
355
358
  conn.should == 1234
356
359
  @pool.conn.should be_nil
357
360
  end
358
- end
361
+ end
@@ -1,19 +1,169 @@
1
- require File.join(File.dirname(__FILE__), 'spec_helper')
2
-
3
- context "Enumerable#send_each" do
4
- specify "should send the supplied method to each item" do
5
- a = ['abbc', 'bbccdd', 'hebtre']
6
- a.send_each(:gsub!, 'b', '_')
7
- a.should == ['a__c', '__ccdd', 'he_tre']
8
- end
9
- end
10
-
11
- context "Range#interval" do
12
- specify "should return the interval between the beginning and end of the range" do
13
- (1..10).interval.should == 9
14
-
15
- r = rand(100000) + 10
16
- t1 = Time.now; t2 = t1 + r
17
- (t1..t2).interval.should == r
18
- end
19
- end
1
+ require File.join(File.dirname(__FILE__), 'spec_helper')
2
+
3
+ context "Array#extract_options!" do
4
+ specify "should pop the last item if it is a hash" do
5
+ a = [1,2,{1=>2}]
6
+ a.extract_options!.should == {1=>2}
7
+ a.should == [1,2]
8
+ end
9
+
10
+ specify "should return an empty hash if the last item is not a hash" do
11
+ a = [1,2]
12
+ a.extract_options!.should == {}
13
+ a.should == [1,2]
14
+ end
15
+ end
16
+
17
+ context "Enumerable#send_each" do
18
+ specify "should send the supplied method to each item" do
19
+ a = ['abbc', 'bbccdd', 'hebtre']
20
+ a.send_each(:gsub!, 'b', '_')
21
+ a.should == ['a__c', '__ccdd', 'he_tre']
22
+ end
23
+ end
24
+
25
+ context "Range#interval" do
26
+ specify "should return the interval between the beginning and end for an inclusive range" do
27
+ (1..10).interval.should == 9
28
+
29
+ r = rand(100000) + 10
30
+ t1 = Time.now; t2 = t1 + r
31
+ (t1..t2).interval.should == r
32
+ end
33
+
34
+ specify "should return the interval between the beginning and end for an exclusive range" do
35
+ (1...10).interval.should == 8
36
+
37
+ r = rand(100000) + 10
38
+ t1 = Time.now; t2 = t1 + r
39
+ (t1...t2).interval.should == r - 1
40
+ end
41
+ end
42
+
43
+ context "Module#class_attr_reader" do
44
+ specify "it should create instance methods that call class methods of the same name" do
45
+ @c = Class.new do
46
+ def self.x; 1; end
47
+ class_attr_reader :x
48
+ end
49
+ @c.new.x.should == 1
50
+ def @c.x; 2; end
51
+ @c.new.x.should == 2
52
+ end
53
+ end
54
+
55
+ context "Module#metaalias" do
56
+ specify "it should create aliases of singleton/class methods" do
57
+ @c = Class.new do
58
+ def self.x; 1; end
59
+ metaalias :y, :x
60
+ end
61
+ @c.y.should == 1
62
+ def @c.x; 2; end
63
+ @c.y.should == 1
64
+ end
65
+ end
66
+
67
+ context "Module#metaattr_reader" do
68
+ specify "it should create attr_readers of singleton/class methods" do
69
+ @c = Class.new do
70
+ @y = 1
71
+ @x = 2
72
+ metaattr_reader :y, :x
73
+ end
74
+ @c.y.should == 1
75
+ @c.x.should == 2
76
+ end
77
+ end
78
+
79
+ context "Module#metaprivate" do
80
+ specify "it should create aliases of singleton/class methods" do
81
+ @c = Class.new do
82
+ def self.x; 1; end
83
+ end
84
+ @c.x.should == 1
85
+ @c.class_eval do
86
+ metaprivate :x
87
+ end
88
+ proc{@c.x}.should raise_error(NoMethodError)
89
+ end
90
+ end
91
+
92
+ context "Object#is_one_of?" do
93
+ specify "it should be true if the object is one of the classes" do
94
+ 1.is_one_of?(Numeric, Array).should == true
95
+ [].is_one_of?(Numeric, Array).should == true
96
+ {}.is_one_of?(Numeric, Enumerable).should == true
97
+ end
98
+
99
+ specify "it should be false if the object is not one of the classes" do
100
+ 'a'.is_one_of?(Numeric, Array).should == false
101
+ Object.new.is_one_of?(Numeric, Array).should == false
102
+ end
103
+ end
104
+
105
+ context "Object#blank?" do
106
+ specify "it should be true if the object responds true to empty?" do
107
+ [].blank?.should == true
108
+ {}.blank?.should == true
109
+ o = Object.new
110
+ def o.empty?; true; end
111
+ o.blank?.should == true
112
+ end
113
+
114
+ specify "it should be false if the object doesn't respond true to empty?" do
115
+ [2].blank?.should == false
116
+ {1=>2}.blank?.should == false
117
+ Object.new.blank?.should == false
118
+ end
119
+ end
120
+
121
+ context "Numeric#blank?" do
122
+ specify "it should always be false" do
123
+ 1.blank?.should == false
124
+ 0.blank?.should == false
125
+ -1.blank?.should == false
126
+ 1.0.blank?.should == false
127
+ 0.0.blank?.should == false
128
+ -1.0.blank?.should == false
129
+ 10000000000000000.blank?.should == false
130
+ -10000000000000000.blank?.should == false
131
+ 10000000000000000.0.blank?.should == false
132
+ -10000000000000000.0.blank?.should == false
133
+ end
134
+ end
135
+
136
+ context "NilClass#blank?" do
137
+ specify "it should always be true" do
138
+ nil.blank?.should == true
139
+ end
140
+ end
141
+
142
+ context "TrueClass#blank?" do
143
+ specify "it should always be false" do
144
+ true.blank?.should == false
145
+ end
146
+ end
147
+
148
+ context "FalseClass#blank?" do
149
+ specify "it should always be true" do
150
+ false.blank?.should == true
151
+ end
152
+ end
153
+
154
+ context "FalseClass#blank?" do
155
+ specify "it should be true if the string is empty" do
156
+ ''.blank?.should == true
157
+ end
158
+ specify "it should be true if the string is composed of just whitespace" do
159
+ ' '.blank?.should == true
160
+ "\r\n\t".blank?.should == true
161
+ (' '*4000).blank?.should == true
162
+ ("\r\n\t"*4000).blank?.should == true
163
+ end
164
+ specify "it should be false if the string has any non whitespace characters" do
165
+ '1'.blank?.should == false
166
+ ("\r\n\t"*4000 + 'a').blank?.should == false
167
+ ("\r\na\t"*4000).blank?.should == false
168
+ end
169
+ end